modifying 'O' command behavour

I was asked how a window-port controls which options are
set to SET_IN_FILE, DISP_IN_GAME, or SET_IN_GAME.

This provides a run-time way to change an option's SET_IN_FILE,
DISP_IN_GAME, or SET_IN_GAME status through code, rather
than clog up options.c with a lot of compile-time #ifdefs
for different ports to offer different default option settings.
Update the documentation to reflect this.
This commit is contained in:
nethack.allison
2002-02-07 03:23:55 +00:00
parent 843bdde1b3
commit 4b364d6927
4 changed files with 138 additions and 21 deletions

View File

@@ -402,14 +402,56 @@ 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. See section IX for
details of where the wincap mask resides. Any preference settings
marked as being supported by having its bit set in the wincap mask
will be available for the user of your window port to set via the 'O'
command, while those not marked as supported will not appear in the
menus of the 'O' command.
details of where the wincap mask resides.
Setting of any wincap option is handled by the NetHack core option
code, you do not have to provide a parser in your window port.
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 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 options can be altered by calling
set_wc_option_mod_status(optmask, status)
specifying the option modification status to one of SET_IN_FILE,
DISP_IN_GAME, or SET_IN_GAME.
The setting of any wincap 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_* 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_* 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_* 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 preference settings that your port can choose
to support:
@@ -481,10 +523,26 @@ 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.
Whenever one of these settings is adjusted (and if supported by the port
by marking it so in the wincap mask), the port is notified of a change
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
can choose to adjust for the change or ignore it.
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 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).
V. New or respecified common, high level routines

View File

@@ -1341,6 +1341,8 @@ E char FDECL(map_menu_cmd, (CHAR_P));
E void FDECL(assign_warnings, (uchar *));
E char *FDECL(nh_getenv, (const char *));
E void FDECL(set_duplicate_opt_detection, (int));
E void FDECL(set_wc_option_mod_status, (unsigned long, int));
E void FDECL(set_option_mod_status, (char *, int));
/* ### pager.c ### */

View File

@@ -238,6 +238,16 @@ NEARDATA extern coord bhitpos; /* place where throw or zap hits or stops */
#define MENU_SELECTED TRUE
#define MENU_UNSELECTED FALSE
/*
* Option flags
* Each higher number includes the characteristics of the numbers
* below it.
*/
#define SET_IN_FILE 0 /* config file option only */
#define SET_VIA_PROG 1 /* may be set via extern program, not seen in game */
#define DISP_IN_GAME 2 /* may be set via extern program, displayed in game */
#define SET_IN_GAME 3 /* may be set via extern program or set in the game */
#define FEATURE_NOTICE_VER(major,minor,patch) (((unsigned long)major << 24) | \
((unsigned long)minor << 16) | \
((unsigned long)patch << 8) | \

View File

@@ -24,17 +24,6 @@ NEARDATA struct instance_flags iflags; /* provide linkage */
* and also the Guidebooks.
*/
/*
* Option flags
* Each higher number includes the characteristics of the numbers
* below it.
*/
#define SET_IN_FILE 0 /* config file option only, not visible in game
* or via program */
#define SET_VIA_PROG 1 /* may be set via extern program, not seen in game */
#define DISP_IN_GAME 2 /* may be set via extern program, displayed in game */
#define SET_IN_GAME 3 /* may be set via extern program or set in the game */
static struct Bool_Opt
{
const char *name;
@@ -3058,6 +3047,64 @@ struct wc_Opt wc_options[] = {
{(char *)0, 0L}
};
/*
* If a port wants to change or ensure that the
* SET_IN_FILE, DISP_IN_GAME, or SET_IN_GAME status of an option is
* correct (for controlling its display in the option menu) call
* set_option_mod_status()
* with the second argument of 0,2, or 3 respectively.
*/
void
set_option_mod_status(optnam, status)
char *optnam;
int status;
{
int k;
if (status < SET_IN_FILE || status > SET_IN_GAME) {
impossible("set_option_mod_status: status out of range %d.", status);
return;
}
for (k = 0; boolopt[k].name; k++) {
if (!strncmpi(boolopt[k].name, optnam, strlen(optnam))) {
boolopt[k].optflags = status;
return;
}
}
for (k = 0; compopt[k].name; k++) {
if (!strncmpi(compopt[k].name, optnam, strlen(optnam))) {
compopt[k].optflags = status;
return;
}
}
}
/*
* You can set several wc_options in one call to
* set_wc_option_mod_status() by setting
* the appropriate bits for each option that you
* are setting in the optmask argument
* prior to calling.
* example: set_wc_option_mod_status(WC_COLOR|WC_SCROLL_MARGIN, SET_IN_GAME);
*/
void
set_wc_option_mod_status(optmask, status)
unsigned long optmask;
int status;
{
int k = 0;
if (status < SET_IN_FILE || status > SET_IN_GAME) {
impossible("set_option_mod_status: status out of range %d.", status);
return;
}
while (wc_options[k].wc_name) {
if (optmask & wc_options[k].wc_bit) {
set_option_mod_status(wc_options[k].wc_name, status);
}
k++;
}
}
STATIC_OVL boolean
is_wc_option(optnam)
const char *optnam;