mirror of
https://codeberg.org/noisytoot/notnotdnethack.git
synced 2024-11-21 16:55:06 +00:00
5901b7c7ca
Thanks, kerio!
812 lines
39 KiB
Text
812 lines
39 KiB
Text
Introduction
|
|
|
|
This file documents the support for various windowing systems in
|
|
NetHack. The support is through a standard interface, separating the
|
|
main NetHack code from window-system specific code. The implementation
|
|
supports multiple window systems in the same binary. Even if you only
|
|
wish to support one window-port on your port, you will need to follow
|
|
the instructions in Section IX to get a compilable binary.
|
|
|
|
Contents:
|
|
I. Window Types and Terminology
|
|
II. Interface Specification
|
|
III. Global variables
|
|
IV. WINCAP preferences support
|
|
V. New or respecified common, high level routines
|
|
VI. Helper routines
|
|
VII. Game startup
|
|
VIII. Conventions
|
|
IX. Implementation and Multi-window support
|
|
|
|
I. Window Types and Terminology
|
|
|
|
There are 5 basic window types, used to call create_nhwindow():
|
|
|
|
NHW_MESSAGE (top line)
|
|
NHW_STATUS (bottom lines)
|
|
NHW_MAP (main dungeon)
|
|
NHW_MENU (inventory or other "corner" windows)
|
|
NHW_TEXT (help/text, full screen paged window)
|
|
|
|
The tty window-port also uses NHW_BASE (the base display) internally.
|
|
|
|
NHW_MENU windows can be used for either menu or text display. Their
|
|
basic feature is that for the tty-port, if the window is small enough,
|
|
it appears in the corner of the tty display instead of overwriting
|
|
the whole screen. The first call to add information to the window
|
|
will decide if it is going to be used to display a menu or text.
|
|
If start_menu() is called, then it will be used as a menu. If
|
|
putstr() is called, it will be used as text. Once decided, there
|
|
is no turning back. For the tty-port, if the data is too large for
|
|
a single screen then the data is paged (with --more--) between pages.
|
|
Only NHW_MENU type windows can be used for menus.
|
|
|
|
NHW_TEXT windows are used to display a large amount of textual data.
|
|
This is the type of window one would use for displaying a help file,
|
|
for example. In the tty window-port, windows of type NHW_TEXT can
|
|
page using the DEF_PAGER, if DEF_PAGER is defined. There exists an
|
|
assumption that the font for text windows is monospaced. The help
|
|
files are all formatted accordingly.
|
|
|
|
"window" is always of type winid. This is currently implemented as an
|
|
integer, but doesn't necessarily have to be done that way. There are
|
|
a few fixed window names that are known throughout the code:
|
|
|
|
WIN_MESSAGE (top line)
|
|
WIN_STATUS (bottom lines)
|
|
WIN_MAP (main dungeon)
|
|
WIN_INVEN (inventory)
|
|
|
|
Other windows are created and destroyed as needed.
|
|
|
|
"Port" in this document refers to a CPU/OS/hardware platform (UNIX, MSDOS
|
|
TOS, etc.) "window-port" refers to the windowing platform. This is
|
|
orthogonal (e.g. UNIX might use either a tty window-port or an X11
|
|
window-port).
|
|
|
|
|
|
II. Interface Specification
|
|
|
|
All functions below are void unless otherwise noted.
|
|
|
|
A. Low-level routines:
|
|
|
|
raw_print(str) -- Print directly to a screen, or otherwise guarantee that
|
|
the user sees str. raw_print() appends a newline to str.
|
|
It need not recognize ASCII control characters. This is
|
|
used during startup (before windowing system initialization
|
|
-- maybe this means only error startup messages are raw),
|
|
for error messages, and maybe other "msg" uses. E.g.
|
|
updating status for micros (i.e, "saving").
|
|
raw_print_bold(str)
|
|
-- Like raw_print(), but prints in bold/standout (if possible).
|
|
curs(window, x, y)
|
|
-- Next output to window will start at (x,y), also moves
|
|
displayable cursor to (x,y). For backward compatibility,
|
|
1 <= x < cols, 0 <= y < rows, where cols and rows are
|
|
the size of window.
|
|
-- For variable sized windows, like the status window, the
|
|
behavior when curs() is called outside the window's limits
|
|
is unspecified. The mac port wraps to 0, with the status
|
|
window being 2 lines high and 80 columns wide.
|
|
-- Still used by curs_on_u(), status updates, screen locating
|
|
(identify, teleport).
|
|
-- NHW_MESSAGE, NHW_MENU and NHW_TEXT windows do not
|
|
currently support curs in the tty window-port.
|
|
putstr(window, attr, str)
|
|
-- Print str on the window with the given attribute. Only
|
|
printable ASCII characters (040-0126) must be supported.
|
|
Multiple putstr()s are output on separate lines. Attributes
|
|
can be one of
|
|
ATR_NONE (or 0)
|
|
ATR_ULINE
|
|
ATR_BOLD
|
|
ATR_BLINK
|
|
ATR_INVERSE
|
|
If a window-port does not support all of these, it may map
|
|
unsupported attributes to a supported one (e.g. map them
|
|
all to ATR_INVERSE). putstr() may compress spaces out of
|
|
str, break str, or truncate str, if necessary for the
|
|
display. Where putstr() breaks a line, it has to clear
|
|
to end-of-line.
|
|
-- putstr should be implemented such that if two putstr()s
|
|
are done consecutively the user will see the first and
|
|
then the second. In the tty port, pline() achieves this
|
|
by calling more() or displaying both on the same line.
|
|
get_nh_event() -- Does window event processing (e.g. exposure events).
|
|
A noop for the tty and X window-ports.
|
|
int nhgetch() -- Returns a single character input from the user.
|
|
-- In the tty window-port, nhgetch() assumes that tgetch()
|
|
will be the routine the OS provides to read a character.
|
|
Returned character _must_ be non-zero and it must be
|
|
non meta-zero too (zero with the meta-bit set).
|
|
int nh_poskey(int *x, int *y, int *mod)
|
|
-- Returns a single character input from the user or a
|
|
a positioning event (perhaps from a mouse). If the
|
|
return value is non-zero, a character was typed, else,
|
|
a position in the MAP window is returned in x, y and mod.
|
|
mod may be one of
|
|
|
|
CLICK_1 /* mouse click type 1 */
|
|
CLICK_2 /* mouse click type 2 */
|
|
|
|
The different click types can map to whatever the
|
|
hardware supports. If no mouse is supported, this
|
|
routine always returns a non-zero character.
|
|
|
|
B. High-level routines:
|
|
|
|
print_glyph(window, x, y, glyph)
|
|
-- Print the glyph at (x,y) on the given window. Glyphs are
|
|
integers at the interface, mapped to whatever the window-
|
|
port wants (symbol, font, color, attributes, ...there's
|
|
a 1-1 map between glyphs and distinct things on the map).
|
|
char yn_function(const char *ques, const char *choices, char default)
|
|
-- Print a prompt made up of ques, choices and default.
|
|
Read a single character response that is contained in
|
|
choices or default. If choices is NULL, all possible
|
|
inputs are accepted and returned. This overrides
|
|
everything else. The choices are expected to be in
|
|
lower case. Entering ESC always maps to 'q', or 'n',
|
|
in that order, if present in choices, otherwise it maps
|
|
to default. Entering any other quit character (SPACE,
|
|
RETURN, NEWLINE) maps to default.
|
|
-- If the choices string contains ESC, then anything after
|
|
it is an acceptable response, but the ESC and whatever
|
|
follows is not included in the prompt.
|
|
-- If the choices string contains a '#' then accept a count.
|
|
Place this value in the global "yn_number" and return '#'.
|
|
-- This uses the top line in the tty window-port, other
|
|
ports might use a popup.
|
|
-- If choices is NULL, all possible inputs are accepted and
|
|
returned, preserving case (upper or lower.) This means that
|
|
if the calling function needs an exact match, it must handle
|
|
user input correctness itself.
|
|
getlin(const char *ques, char *input)
|
|
-- Prints ques as a prompt and reads a single line of text,
|
|
up to a newline. The string entered is returned without the
|
|
newline. ESC is used to cancel, in which case the string
|
|
"\033\000" is returned.
|
|
-- getlin() must call flush_screen(1) before doing anything.
|
|
-- This uses the top line in the tty window-port, other
|
|
ports might use a popup.
|
|
-- getlin() can assume the input buffer is at least BUFSZ
|
|
bytes in size and must truncate inputs to fit, including
|
|
the nul character.
|
|
int get_ext_cmd(void)
|
|
-- Get an extended command in a window-port specific way.
|
|
An index into extcmdlist[] is returned on a successful
|
|
selection, -1 otherwise.
|
|
player_selection()
|
|
-- Do a window-port specific player type selection. If
|
|
player_selection() offers a Quit option, it is its
|
|
responsibility to clean up and terminate the process.
|
|
You need to fill in pl_character[0].
|
|
display_file(str, boolean complain)
|
|
-- Display the file named str. Complain about missing files
|
|
iff complain is TRUE.
|
|
update_inventory()
|
|
-- Indicate to the window port that the inventory has been
|
|
changed.
|
|
-- Merely calls display_inventory() for window-ports that
|
|
leave the window up, otherwise empty.
|
|
doprev_message()
|
|
-- Display previous messages. Used by the ^P command.
|
|
-- On the tty-port this scrolls WIN_MESSAGE back one line.
|
|
|
|
update_positionbar(char *features)
|
|
-- Optional, POSITIONBAR must be defined. Provide some
|
|
additional information for use in a horizontal
|
|
position bar (most useful on clipped displays).
|
|
Features is a series of char pairs. The first char
|
|
in the pair is a symbol and the second char is the
|
|
column where it is currently located.
|
|
A '<' is used to mark an upstairs, a '>'
|
|
for a downstairs, and an '@' for the current player
|
|
location. A zero char marks the end of the list.
|
|
|
|
|
|
C. Window Utility Routines
|
|
|
|
init_nhwindows(int* argcp, char** argv)
|
|
-- Initialize the windows used by NetHack. This can also
|
|
create the standard windows listed at the top, but does
|
|
not display them.
|
|
-- Any commandline arguments relevant to the windowport
|
|
should be interpreted, and *argcp and *argv should
|
|
be changed to remove those arguments.
|
|
-- When the message window is created, the variable
|
|
iflags.window_inited needs to be set to TRUE. Otherwise
|
|
all plines() will be done via raw_print().
|
|
** Why not have init_nhwindows() create all of the "standard"
|
|
** windows? Or at least all but WIN_INFO? -dean
|
|
exit_nhwindows(str)
|
|
-- Exits the window system. This should dismiss all windows,
|
|
except the "window" used for raw_print(). str is printed
|
|
if possible.
|
|
window = create_nhwindow(type)
|
|
-- Create a window of type "type."
|
|
clear_nhwindow(window)
|
|
-- Clear the given window, when appropriate.
|
|
display_nhwindow(window, boolean blocking)
|
|
-- Display the window on the screen. If there is data
|
|
pending for output in that window, it should be sent.
|
|
If blocking is TRUE, display_nhwindow() will not
|
|
return until the data has been displayed on the screen,
|
|
and acknowledged by the user where appropriate.
|
|
-- All calls are blocking in the tty window-port.
|
|
-- Calling display_nhwindow(WIN_MESSAGE,???) will do a
|
|
--more--, if necessary, in the tty window-port.
|
|
destroy_nhwindow(window)
|
|
-- Destroy will dismiss the window if the window has not
|
|
already been dismissed.
|
|
start_menu(window)
|
|
-- Start using window as a menu. You must call start_menu()
|
|
before add_menu(). After calling start_menu() you may not
|
|
putstr() to the window. Only windows of type NHW_MENU may
|
|
be used for menus.
|
|
add_menu(windid window, int glyph, const anything identifier,
|
|
char accelerator, char groupacc,
|
|
int attr, char *str, boolean preselected)
|
|
-- Add a text line str to the given menu window. If identifier
|
|
is 0, then the line cannot be selected (e.g. a title).
|
|
Otherwise, identifier is the value returned if the line is
|
|
selected. Accelerator is a keyboard key that can be used
|
|
to select the line. If the accelerator of a selectable
|
|
item is 0, the window system is free to select its own
|
|
accelerator. It is up to the window-port to make the
|
|
accelerator visible to the user (e.g. put "a - " in front
|
|
of str). The value attr is the same as in putstr().
|
|
Glyph is an optional glyph to accompany the line. If
|
|
window port cannot or does not want to display it, this
|
|
is OK. If there is no glyph applicable, then this
|
|
value will be NO_GLYPH.
|
|
-- All accelerators should be in the range [A-Za-z],
|
|
but there are a few exceptions such as the tty player
|
|
selection code which uses '*'.
|
|
-- It is expected that callers do not mix accelerator
|
|
choices. Either all selectable items have an accelerator
|
|
or let the window system pick them. Don't do both.
|
|
-- Groupacc is a group accelerator. It may be any character
|
|
outside of the standard accelerator (see above) or a
|
|
number. If 0, the item is unaffected by any group
|
|
accelerator. If this accelerator conflicts with
|
|
the menu command (or their user defined alises), it loses.
|
|
The menu commands and aliases take care not to interfere
|
|
with the default object class symbols.
|
|
-- If you want this choice to be preselected when the
|
|
menu is displayed, set preselected to TRUE.
|
|
|
|
end_menu(window, prompt)
|
|
-- Stop adding entries to the menu and flushes the window
|
|
to the screen (brings to front?). Prompt is a prompt
|
|
to give the user. If prompt is NULL, no prompt will
|
|
be printed.
|
|
** This probably shouldn't flush the window any more (if
|
|
** it ever did). That should be select_menu's job. -dean
|
|
int select_menu(windid window, int how, menu_item **selected)
|
|
-- Return the number of items selected; 0 if none were chosen,
|
|
-1 when explicitly cancelled. If items were selected, then
|
|
selected is filled in with an allocated array of menu_item
|
|
structures, one for each selected line. The caller must
|
|
free this array when done with it. The "count" field
|
|
of selected is a user supplied count. If the user did
|
|
not supply a count, then the count field is filled with
|
|
-1 (meaning all). A count of zero is equivalent to not
|
|
being selected and should not be in the list. If no items
|
|
were selected, then selected is NULL'ed out. How is the
|
|
mode of the menu. Three valid values are PICK_NONE,
|
|
PICK_ONE, and PICK_ANY, meaning: nothing is selectable,
|
|
only one thing is selectable, and any number valid items
|
|
may selected. If how is PICK_NONE, this function should
|
|
never return anything but 0 or -1.
|
|
-- You may call select_menu() on a window multiple times --
|
|
the menu is saved until start_menu() or destroy_nhwindow()
|
|
is called on the window.
|
|
-- Note that NHW_MENU windows need not have select_menu()
|
|
called for them. There is no way of knowing whether
|
|
select_menu() will be called for the window at
|
|
create_nhwindow() time.
|
|
char message_menu(char let, int how, const char *mesg)
|
|
-- tty-specific hack to allow single line context-sensitive
|
|
help to behave compatibly with multi-line help menus.
|
|
-- This should only be called when a prompt is active; it
|
|
sends `mesg' to the message window. For tty, it forces
|
|
a --More-- prompt and enables `let' as a viable keystroke
|
|
for dismissing that prompt, so that the original prompt
|
|
can be answered from the message line "help menu".
|
|
-- Return value is either `let', '\0' (no selection was made),
|
|
or '\033' (explicit cancellation was requested).
|
|
-- Interfaces which issue prompts and messages to separate
|
|
windows typically won't need this functionality, so can
|
|
substitute genl_message_menu (windows.c) instead.
|
|
|
|
D. Misc. Routines
|
|
|
|
make_sound(???) -- To be determined later. THIS IS CURRENTLY UN-IMPLEMENTED.
|
|
nhbell() -- Beep at user. [This will exist at least until sounds are
|
|
redone, since sounds aren't attributable to windows anyway.]
|
|
mark_synch() -- Don't go beyond this point in I/O on any channel until
|
|
all channels are caught up to here. Can be an empty call
|
|
for the moment
|
|
wait_synch() -- Wait until all pending output is complete (*flush*() for
|
|
streams goes here).
|
|
-- May also deal with exposure events etc. so that the
|
|
display is OK when return from wait_synch().
|
|
delay_output() -- Causes a visible delay of 50ms in the output.
|
|
Conceptually, this is similar to wait_synch() followed
|
|
by a nap(50ms), but allows asynchronous operation.
|
|
askname() -- Ask the user for a player name.
|
|
cliparound(x, y)-- Make sure that the user is more-or-less centered on the
|
|
screen if the playing area is larger than the screen.
|
|
-- This function is only defined if CLIPPING is defined.
|
|
number_pad(state)
|
|
-- Initialize the number pad to the given state.
|
|
suspend_nhwindows(str)
|
|
-- Prepare the window to be suspended.
|
|
resume_nhwindows()
|
|
-- Restore the windows after being suspended.
|
|
|
|
start_screen() -- Only used on Unix tty ports, but must be declared for
|
|
completeness. Sets up the tty to work in full-screen
|
|
graphics mode. Look at win/tty/termcap.c for an
|
|
example. If your window-port does not need this function
|
|
just declare an empty function.
|
|
end_screen() -- Only used on Unix tty ports, but must be declared for
|
|
completeness. The complement of start_screen().
|
|
|
|
outrip(winid, int)
|
|
-- The tombstone code. If you want the traditional code use
|
|
genl_outrip for the value and check the #if in rip.c.
|
|
|
|
preference_update(preference)
|
|
-- The player has just changed one of the wincap preference
|
|
settings, and the NetHack core is notifying your window
|
|
port of that change. If your window-port is capable of
|
|
dynamically adjusting to the change then it should do so.
|
|
Your window-port will only be notified of a particular
|
|
change if it indicated that it wants to be by setting the
|
|
corresponding bit in the wincap mask.
|
|
|
|
III. Global variables
|
|
|
|
The following global variables are defined in decl.c and must be used by
|
|
the window interface to the rest of NetHack.
|
|
|
|
char toplines[BUFSZ] Contains the last message printed to the WIN_MESSAGE
|
|
window, used by Norep().
|
|
winid WIN_MESSAGE, WIN_MAP, WIN_STATUS, WIN_INVEN
|
|
The four standard windows.
|
|
char *AE, *AS; Checked in options.c to see if we should switch
|
|
to DEC_GRAPHICS. It is #ifdefed VMS and UNIX.
|
|
int LI, CO; Set in sys/unix/ioctl.c.
|
|
|
|
The following appears to be Unix specific. Other ports using the tty
|
|
window-port should also declare this variable in one of your sys/*.c files.
|
|
|
|
short ospeed; Set and declared in sys/unix/unixtty.c (don't
|
|
know about other sys files).
|
|
|
|
The following global variable is defined in options.c. It equates a
|
|
list of wincap option names with their associated bit-mask [see
|
|
section IV WINCAP preferences support]. The array is zero-terminated.
|
|
|
|
struct wc_Opt wc_options[];
|
|
One entry for each available WINCAP option.
|
|
Each entry has a wc_name field and a wc_bit
|
|
field.
|
|
|
|
IV. WINCAP preferences support
|
|
|
|
Starting with NetHack 3.4.0, the window interface was enhanced to provide
|
|
a common way of setting window port user preferences from the config file,
|
|
and from the command line for some settings.
|
|
|
|
The wincap preference settings all have their underlying values stored
|
|
in iflags fields. The names of the wincap related fields are all pre-
|
|
fixed with wc_ or wc2_ to make it easy to identify them. Your window
|
|
port can access the fields directly.
|
|
|
|
Your window port identifies what options it will react to and support
|
|
by setting bits in the window_procs wincap mask and/or wincap2 mask.
|
|
See section IX for details of where the wincap masks reside.
|
|
|
|
Two things control whether any preference setting appears in the
|
|
'O' command options menu during the game:
|
|
1. The option must be marked as being supported by having its
|
|
bit set in the window_procs wincap or wincap2 mask.
|
|
2. The option must have its optflag field set to SET_IN_GAME in order
|
|
to be able to set the option, or marked DISP_IN_GAME if you just
|
|
want to reveal what the option is set to.
|
|
Both conditions must be true to be able to see or set the option from
|
|
within NetHack.
|
|
|
|
The default values for the optflag field for all the options are
|
|
hard-coded into the option in options.c. The default value for
|
|
the wc_ options can be altered by calling
|
|
set_wc_option_mod_status(optmask, status)
|
|
The default value for the wc2_ options can be altered by calling
|
|
set_wc2_option_mod_status(optmask, status)
|
|
In each case, set the option modification status to one of SET_IN_FILE,
|
|
DISP_IN_GAME, or SET_IN_GAME.
|
|
|
|
The setting of any wincap or wincap2 option is handled by the NetHack
|
|
core option processing code. You do not have to provide a parser in
|
|
your window port, nor should you set the values for the
|
|
iflags.wc_* and iflags.wc2_* fields directly within the port code.
|
|
The port code should honor whatever values were put there by the core
|
|
when processing options, either in the config file, or by the 'O' command.
|
|
|
|
You may be wondering what values your window port will find in the
|
|
iflags.wc_* and iflags.wc2_* fields for options that the user has not
|
|
specified in his/her config file. Put another way, how does you port code
|
|
tell if an option has not been set? The next paragraph explains that.
|
|
|
|
If the core does not set an option, it will still be initialized
|
|
to its default value. Those default values for the
|
|
iflags.wc_* and iflags.wc_* fields are:
|
|
|
|
o All boolean fields are initialized to the starting
|
|
value specified for that option in the boolopt array in
|
|
options.c. The window-port should respect that setting
|
|
unless it has a very good reason for not doing so.
|
|
o All int fields are initialized to zero. Zero is not a valid
|
|
setting for any of the int options, so if your port code
|
|
encounters a zero there, it can assume that the preference
|
|
option was not specified. In that case, the window-port code
|
|
should use a default setting that the port is comfortable with.
|
|
It should write the default setting back into the iflags.wc_*
|
|
field. That is the only time that your window-port could should
|
|
update those fields.
|
|
o All "char *" fields will be null pointers. Be sure to check for
|
|
that in your window-port code before using such a pointer, or
|
|
you'll end up triggering a nasty fault.
|
|
|
|
Here are the wincap and wincap2 preference settings that your port can choose
|
|
to support:
|
|
|
|
wincap
|
|
+--------------------+--------------------+--------------------+--------+
|
|
| | | iflags field | data |
|
|
| player option | bit in wincap mask | for value | type |
|
|
|--------------------+--------------------+--------------------+--------+
|
|
| align_message | WC_ALIGN_MESSAGE | wc_align_message |int |
|
|
| align_status | WC_ALIGN_STATUS | wc_align_status |int |
|
|
| ascii_map | WC_ASCII_MAP | wc_ascii_map |boolean |
|
|
| color | WC_COLOR | wc_color |boolean |
|
|
| eight_bit_tty | WC_EIGHT_BIT_IN | wc_eight_bit_input |boolean |
|
|
| font_map | WC_FONT_MAP | wc_font_map |char * |
|
|
| font_menu | WC_FONT_MENU | wc_font_menu |char * |
|
|
| font_message | WC_FONT_MESSAGE | wc_font_message |char * |
|
|
| font_status | WC_FONT_STATUS | wc_font_status |char * |
|
|
| font_text | WC_FONT_TEXT | wc_font_text |char * |
|
|
| font_size_map | WC_FONTSIZ_MAP | wc_fontsiz_map |int |
|
|
| font_size_menu | WC_FONTSIZ_MENU | wc_fontsiz_menu |int |
|
|
| font_size_message | WC_FONTSIZ_MESSAGE | wc_fontsiz_message |int |
|
|
| font_size_status | WC_FONTSIZ_STATUS | wc_fontsiz_status |int |
|
|
| font_size_text | WC_FONTSIZ_TEXT | wc_fontsiz_text |int |
|
|
| hilite_pet | WC_HILITE_PET | wc_hilite_pet |boolean |
|
|
| map_mode | WC_MAP_MODE | wc_map_mode |int |
|
|
| player_selection | WC_PLAYER_SELECTION| wc_player_selection|int |
|
|
| popup_dialog | WC_POPUP_DIALOG | wc_popup_dialog |boolean |
|
|
| preload_tiles | WC_PRELOAD_TILES | wc_preload_tiles |boolean |
|
|
| scroll_amount | WC_SCROLL_AMOUNT | wc_scroll_amount |int |
|
|
| scroll_margin | WC_SCROLL_MARGIN | wc_scroll_margin |int |
|
|
| splash_screen | WC_SPLASH_SCREEN | wc_splash_screen |boolean |
|
|
| tiled_map | WC_TILED_MAP | wc_tiled_map |boolean |
|
|
| tile_width | WC_TILE_WIDTH | wc_tile_width |int |
|
|
| tile_height | WC_TILE_HEIGHT | wc_tile_height |int |
|
|
| tile_file | WC_TILE_FILE | wc_tile_file |char * |
|
|
| use_inverse | WC_INVERSE | wc_inverse |boolean |
|
|
| vary_msgcount | WC_VARY_MSGCOUNT | wc_vary_msgcount |int |
|
|
| windowcolors | WC_WINDOWCOLORS | wc_foregrnd_menu |char * |
|
|
| | | wc_backgrnd_menu |char * |
|
|
| | | wc_foregrnd_message|char * |
|
|
| | | wc_backgrnd_message|char * |
|
|
| | | wc_foregrnd_status |char * |
|
|
| | | wc_backgrnd_status |char * |
|
|
| | | wc_foregrnd_text |char * |
|
|
| | | wc_backgrnd_text |char * |
|
|
| mouse | WC_MOUSE_SUPPORT | wc_mouse_support |boolean |
|
|
+--------------------+--------------------+--------------------+--------+
|
|
|
|
wincap2
|
|
+--------------------+--------------------+--------------------+--------+
|
|
| | | iflags field | data |
|
|
| player option | bit in wincap mask | for value | type |
|
|
|--------------------+--------------------+--------------------+--------+
|
|
| fullscreen | WC2_FULLSCREEN | wc2_fullscreen |boolean |
|
|
| softkeyboard | WC2_SOFTKEYBOARD | wc2_softkeyboard |boolean |
|
|
| wraptext | WC2_WRAPTEXT | wc2_wraptext |boolean |
|
|
| term_cols | WC2_TERM_COLS | wc2_term_cols |int |
|
|
| term_rows | WC2_TERM_ROWS | wc2_term_rows |int |
|
|
| windowborders | WC2_WINDOWBORDERS | wc2_windowborders |int |
|
|
+--------------------+--------------------+--------------------+--------+
|
|
|
|
align_message -- where to place message window (top, bottom, left, right)
|
|
align_status -- where to place status window (top, bottom, left, right).
|
|
ascii_map -- port should display an ascii map if it can.
|
|
color -- port should display color if it can.
|
|
eight_bit_tty -- port should allow eight bit input.
|
|
font_map -- port should use a font by this name for map window.
|
|
font_menu -- port should use a font by this name for menu windows.
|
|
font_message -- port should use a font by this name for message window.
|
|
font_size_map -- port should use this size font for the map window.
|
|
font_size_menu -- port should use this size font for menu windows.
|
|
font_size_message
|
|
-- port should use this size font for the message window.
|
|
font_size_status-- port should use this size font for the status window.
|
|
font_size_text -- port should use this size font for text windows.
|
|
font_status -- port should use a font by this name for status window.
|
|
font_text -- port should use a font by this name for text windows.
|
|
fullscreen -- port should try to use the whole screen.
|
|
hilite_pet -- port should mark pets in some special way on the map.
|
|
map_mode -- port should display the map in the manner specified.
|
|
player_selection
|
|
-- dialog or prompts for choosing character.
|
|
popup_dialog -- port should pop up dialog boxes for input.
|
|
preload_tiles -- port should preload tiles into memory.
|
|
scroll_amount -- scroll this amount when scroll_margin is reached.
|
|
scroll_margin -- port should scroll the display when the hero or cursor
|
|
is this number of cells away from the edge of the window.
|
|
softkeyboard -- handhelds should display an on-screen keyboard if possible.
|
|
splash_screen -- port should/should not display an opening splashscreen.
|
|
term_cols -- Terminal should size itself to specified width, if possible.
|
|
term_rows -- Terminal should size itself to specified height, if possible.
|
|
tiled_map -- port should display a tiled map if it can.
|
|
tile_width -- port should display tiles with this width or round to closest
|
|
if it can.
|
|
tile_height -- port should display tiles with this height or round to closest
|
|
if it can.
|
|
tile_file -- open this alternative tile file. The file name is likely to be
|
|
window-port or platform specific.
|
|
use_inverse -- port should display inverse when NetHack asks for it.
|
|
vary_msgcount -- port should display this number of messages at a time in
|
|
the message window.
|
|
windowborders -- port should display borders around main NetHack windows.
|
|
Can be set to (1) on, (2) off, or (3) auto.
|
|
windowcolors
|
|
-- port should use these colors for window foreground/background
|
|
colors. Syntax:
|
|
menu fore/back message fore/back status fore/back text fore/back
|
|
wraptext -- port should wrap long lines of text if they don't fit in
|
|
the visible area of the window
|
|
mouse_support -- port should enable mouse support if possible
|
|
|
|
Whenever one of these settings is adjusted, the port is notified of a change
|
|
to the setting by calling the port's preference_update() routine. The port
|
|
is only notified if it has indicated that it supports that option by setting
|
|
the option's bit in the port's wincap mask. The port can choose to adjust
|
|
for the change to an option that it receives notification about, or ignore it.
|
|
The former approach is recommended. If you don't want to deal with a
|
|
user-initiated setting change, then the port should call
|
|
set_wc_option_mod_status(mask, SET_IN_FILE) to make the option invisible to
|
|
the user.
|
|
|
|
Functions available for the window port to call:
|
|
|
|
set_wc_option_mod_status(optmask, status)
|
|
-- Adjust the optflag field for a set of wincap options to
|
|
specify whether the port wants the option to appear
|
|
in the 'O' command options menu, The second parameter,
|
|
"status" can be set to SET_IN_FILE, DISP_IN_GAME,
|
|
or SET_IN_GAME (SET_IN_FILE implies that the option
|
|
is completely hidden during the game).
|
|
|
|
set_wc2_option_mod_status(optmask, status)
|
|
-- Adjust the optflag field for a set of wincap2 options to
|
|
specify whether the port wants the option to appear
|
|
in the 'O' command options menu, The second parameter,
|
|
"status" can be set to SET_IN_FILE, DISP_IN_GAME,
|
|
or SET_IN_GAME (SET_IN_FILE implies that the option
|
|
is completely hidden during the game).
|
|
|
|
set_option_mod_status(optnam, status)
|
|
-- Adjust the optflag field for one of the core options
|
|
that is not part of the wincap suite. A port might use
|
|
this to override the default initialization setting for
|
|
status specified in options.c. Note that you have to
|
|
specify the option by name and that you can only set
|
|
one option per call unlike set_wc_option_mod_status().
|
|
|
|
|
|
Adding a new wincap option:
|
|
|
|
To add a new wincap option, please follow all these steps:
|
|
1. Add the option to the wincap preference settings table above. Since
|
|
wincap is full, your option will likely target wincap2 field.
|
|
2. Add the description to the paragraph below the chart.
|
|
3. Add the WC_ or WC2_ to the bit list in include/winprocs.h
|
|
(in wincap2 if there is no room in wincap).
|
|
4. Add the wc_ or wc2_ field(s) to the iflags structure in flag.h.
|
|
5. Add the name and value to wc_options[] or wc2_options[] in options.c
|
|
6. Add an appropriate parser to parseoptions() in options.c.
|
|
7. Add code to display current value to get_compopt_value() in options.c.
|
|
8. Document the option in Guidebook.mn and Guidebook.tex.
|
|
9. Add the bit name to the OR'd values in your window port's winprocs struct
|
|
wincap mask if your port supports the option.
|
|
|
|
V. New or respecified common, high level routines
|
|
|
|
These are not part of the interface, but mentioned here for your information.
|
|
|
|
char display_inventory(lets, want_reply)
|
|
-- Calls a start_menu()/add_menu()/select_menu() sequence.
|
|
It returns the item selected, or '\0' if none is selected.
|
|
Returns '\033' if the menu was canceled.
|
|
raw_printf(str, ...)
|
|
-- Like raw_print(), but accepts arguments like printf(). This
|
|
routine processes the arguments and then calls raw_print().
|
|
-- The mac version #defines error raw_printf. I think this
|
|
is a reasonable thing to do for most ports.
|
|
pline(str, ...)
|
|
-- Prints a string to WIN_MESSAGE using a printf() interface.
|
|
It has the variants You(), Your(), Norep(), and others
|
|
in pline.c which all use the same mechanism. pline()
|
|
requires the variable "char toplines[]" be defined; Every
|
|
putstr() on WIN_MESSAGE must copy str to toplines[] for use
|
|
by Norep() and pline(). If the window system is not active
|
|
(!iflags.window_inited) pline() uses raw_print().
|
|
|
|
VI. Helper Routines
|
|
|
|
These are not part of the interface. They may be called by your
|
|
window port routines to perform the desired task, instead of duplicating
|
|
the necessary code in each window port.
|
|
|
|
mapglyph(int glyph, int *ochar, int *ocolor, unsigned *special, int x, int y)
|
|
-- Maps glyph at x,y to NetHack ascii character and color.
|
|
If it represents something special such as a pet, that
|
|
information is returned as set bits in "special."
|
|
Usually called from the window port's print_glyph()
|
|
routine.
|
|
|
|
VII. Game startup
|
|
|
|
The following is the general order in which calls from main() should be made,
|
|
as they relate to the window system. The actual code may differ, but the
|
|
order of the calls should be the same.
|
|
|
|
|
|
choose_windows(DEFAULT_WINDOW_SYS) /* choose a default window system */
|
|
initoptions() /* read the resource file */
|
|
init_nhwindows() /* initialize the window system */
|
|
process_options(argc, argv) /* process command line options or equiv */
|
|
if(save file is present) {
|
|
display_gamewindows() /* create & display the game windows */
|
|
dorestore() /* restore old game; pline()s are OK */
|
|
} else {
|
|
player_selection() /* select a player type using a window */
|
|
display_gamewindows() /* create & display the game windows */
|
|
}
|
|
pline("Hello, welcome...");
|
|
|
|
Choose_windows() is a common routine, and calling it in main() is necessary
|
|
to initialize the function pointer table to _something_ so that calls to
|
|
raw_print() will not fail. Choose_windows() should be called almost
|
|
immediately upon entering main(). Look at unixmain.c for an example.
|
|
|
|
Display_gamewindows() is a common routine that displays the three standard
|
|
game windows (WIN_MESSAGE, WIN_MAP, and WIN_STATUS). It is normally called
|
|
just before the "Hello, welcome" message.
|
|
|
|
Process_options() is currently still unique to each port. There may be need
|
|
in the future to make it possible to replace this on a per window-port basis.
|
|
|
|
|
|
VIII. Conventions
|
|
|
|
init_nhwindows() is expected to display a gee-whiz banner window, including
|
|
the Copyright message. It is recommended that the COPYRIGHT_BANNER_A,
|
|
COPYRIGHT_BANNER_B, and COPYRIGHT_BANNER_C macros from patchlevel.h be used
|
|
for constructing the Copyright message. COPYRIGHT_BANNER_A is a
|
|
quoted string that has the NetHack copyright declaration,
|
|
COPYRIGHT_BANNER_B is a quoted string that states who the copyright
|
|
belongs to, and COPYRIGHT_BANNER_C simply says "See License for
|
|
details." Be sure to #include "patchlevel.h" to define these macros.
|
|
Using the macros will prevent having to update the Copyright information
|
|
in each window-port prior to each release.
|
|
|
|
Ports (MSDOS, TOS, MAC, etc) _may_ use window-port specific routines in
|
|
their port specific files, _AT_THEIR_OWN_RISK_. Since "port" and
|
|
"window-port" are orthogonal, you make your "port" code less portable by
|
|
using "window-port" specific routines. Every effort should be made to
|
|
use window-port interface routines, unless there is something port
|
|
specific that is better suited (e.g. msmsg() for MSDOS).
|
|
|
|
The tty window-port is contained in win/tty, the X window port is contained
|
|
in win/X11. The files in these directories contain _only_ window port code,
|
|
and may be replaced completely by other window ports.
|
|
|
|
|
|
IX. Implementation and Multi-window support
|
|
|
|
NetHack 3.2 and higher support multiple window systems in the same binary.
|
|
When writing a new window-port, you need to follow the following guidelines:
|
|
|
|
1) Pick a unique prefix to identify your window-port. For example, the tty
|
|
window port uses "tty"; the X11 window-port uses "X11".
|
|
2) When declaring your interface function, precede the function names with
|
|
your unique prefix. E.g:
|
|
|
|
void tty_init_nhwindows()
|
|
{
|
|
/* code for initializing windows in the tty port */
|
|
}
|
|
|
|
When calling window functions from within your port code, we suggest
|
|
calling the prefixed version to avoid unnecessary overhead. However,
|
|
you may safely call the non-prefixed version (e.g. putstr() rather than
|
|
tty_putstr()) as long as you #include "hack.h". If you do not
|
|
include hack.h and use the non-prefixed names, you will get compile
|
|
or link-time errors.
|
|
|
|
We also suggest declaring all functions and port-specific data with
|
|
this prefix to avoid unexpected overlaps with other window-ports.
|
|
The tty and X11 ports do not currently follow this suggestion, but do
|
|
use separate non-overlapping convention for naming data and internal
|
|
functions.
|
|
|
|
3) Declare a structure, "struct window_procs prefix_procs", (with your
|
|
prefix instead of "prefix") and fill in names of all of your
|
|
interface functions. The first entry in this structure is the name
|
|
of your window-port, which should be the prefix. The second entry
|
|
is the wincap mask that identifies what window port preference
|
|
settings your port will react to and support. The other entries
|
|
are the function addresses.
|
|
|
|
Assuming that you followed the convention in (2), you can safely copy
|
|
the structure definition from an existing window-port and just change
|
|
the prefixes. That will guarantee that you get the order of your
|
|
initializations correct (not all compilers will catch out-of-order
|
|
function pointer declarations).
|
|
|
|
4) Add a #define to config.h identifying your window-port in the
|
|
"Windowing systems" section. Follow the "prefix_GRAPHICS" convention
|
|
for your window-port.
|
|
|
|
5) Add your prefix to the list of valid prefixes listed in the "Known
|
|
systems are" comment.
|
|
|
|
6) Edit makedefs.c and add a string for your windowing system to window_opts
|
|
inside an #ifdef prefix_GRAPHICS.
|
|
|
|
7) Edit windows.c and add an external reference to your prefix_procs inside
|
|
an #ifdef prefix_GRAPHICS. Also add an entry to the win_choices
|
|
structure for your window-port of the form:
|
|
|
|
#ifdef prefix_GRAPHICS
|
|
{ &prefix_procs, prefix_init_function },
|
|
#endif
|
|
|
|
The init_function is necessary for some compilers and systems to force
|
|
correct linking. If your system does not need such massaging, you
|
|
may put a null pointer here.
|
|
|
|
You should declare prefix_procs and prefix_init_function as extern's
|
|
in your win*.h file, and #include that file at the beginning of
|
|
windows.c, also inside an #ifdef prefix_GRAPHICS. Some win*.h files
|
|
are rather sensitive, and you might have to duplicate your
|
|
prefix_procs and prefix_init_function's instead of including win*.h.
|
|
The tty port includes wintty.h, the X11 port duplicates the declarations.
|
|
|
|
8) If your port uses Makefile.src, add the .c and .o files and an
|
|
appropriate comment in the section on "WINSRC" and "WINOBJ". See
|
|
Makefile.src for the style to use. If you don't use Makefile.src,
|
|
we suggest using a similar convention for the make-equivalent used
|
|
on your system. Also add your new source and binaries to WINSRC and
|
|
WINOBJ (if you want the NetHack binary to include them, that is).
|
|
|
|
9) Look at your port's portmain.c (the file containing main()) and make
|
|
sure that all of the calls match the the requirements laid out in
|
|
Section VII.
|
|
|
|
Now, proceed with compilation and installation as usual. Don't forget
|
|
to edit Makefile.src (or its equivalent) and config.h to set the
|
|
window-ports you want in your binary, the default window-port to use,
|
|
and the .o's needed to build a valid game.
|
|
|
|
One caveat. Unfortunately, if you incorrectly specify the
|
|
DEFAULT_WINDOW_SYS, NetHack will dump core (or whatever) without
|
|
printing any message, because raw_print() cannot function without first
|
|
setting the window-port.
|