There was a transcription error in the comments in cstd.h for
the standard list of header files, where only the description
remained for <stdlib.h>, not the name of the file itself.
Remove several extraneous inclusions of the standard C99 headers.
Tested on the following afterwards:
Linux (using hints/linux.370) including tty, curses, qt6, and X11
macOS (using hints/macOS.370) including tty, curses, qt5, and X11
Windows MSYS2 using sys/windows/GNUmakefile
Windows Visual Studio using sys/windows/Makefile.nmake
msdos cross-compile on Ubuntu using djgpp cross-compiler
gcc has recognized various "magic comments" for white-listing
occurrences of implicit fallthrough in switch statements for
a long time:
The range and shape of "falls through" comments accepted are
contingent upon the level of the warning. (The default level is =3.)
-Wimplicit-fallthrough=0 disables the warning altogether.
-Wimplicit-fallthrough=1 treats any kind of comment as a "falls through" comment.
-Wimplicit-fallthrough=2 essentially accepts any comment that contains something
that matches (case insensitively) "falls?[ \t-]*thr(ough|u)" regular expression.
-Wimplicit-fallthrough=3 case sensitively matches a wide range of regular
expressions, listed in the GCC manual. E.g., all of these are accepted:
/* Falls through. */
/* fall-thru */
/* Else falls through. */
/* FALLTHRU */
/* ... falls through ... */
etc.
-Wimplicit-fallthrough=4 also, case sensitively matches a range of regular
expressions but is much more strict than level =3.
-Wimplicit-fallthrough=5 doesn't recognize any comments.
Plenty of other compilers did not recognize the gcc comment convention,
and up until now the compiler warning for detecting unintended
fallthrough had to be suppressed on other compilers. That's because the code
in NetHack has been relying on the gcc approach, and only the gcc approach.
The C23 standard introduces an attribute [[fallthrough]] for the
functionality, when implicit fallthrough warnings have been enabled.
Several popular compilers already support that, or a very similar attribute
style approach, today, even ahead of their C23 support:
C compiler whitelist approach
--------------------------- -------------------------------------
C23 conforming compilers [[fallthrough]]
clang versions supporting
standards prior to
C23 __attribute__((__fallthrough__))
Microsoft Visual Studio
since VS 2022 17.4.
The warning C5262 controls
whether the implict
fallthrough is detected and
warned about with
/std:clatest. [[fallthrough]]
This adds support to NetHack for the attribute approach by inserting a
macro FALLTHROUGH to the existing cases that require white-listing, so
other compilers can analyze things too.
The definition of the FALLTHROUGH macro is controlled in include/tradstdc.h.
The gcc comment approach has also been left in place at this time.
The map frame (background) colors were all over the place; the
code should be much cleaner now, and still work exactly the same
as before.
I tested this with terminals with 8, 16, and 256 COLORS.
My recent change to petattr caused a crash in curses when no
petattr was used in config file - because curses was setting
petattr to curses-specific value. Init the setting in core
instead.
Instead of just accepting an attribute, it's now possible to
use a color, or both color and attribute, for example:
OPTIONS=menu_headings:inverse
OPTIONS=menu_headings:red
OPTIONS=menu_headings:red&underline
Default is still just inverse.
This lets the player change the menu heading color without
needing to use menu colors for them.
Also makes it so the core uses NO_COLOR instead of 0, for all
the menu lines which don't have any prefedefined color.
Tested for tty, curses, x11, qt, and win32
Move the tty role/race/&c selection from wintty.c to role.c and remove
its references to BASE_WINDOW. Have curses call the same routine now
so that the player has the option to choose role, race, gender, and
alignment in any order and to confirm or override random settings
prior to starting play. Also if you went through "who are you?" then
final confirmation includes an extra menu choice to rename the hero.
It still has the quirk of sometimes remembering some of the previous
aspects when you re-pick a new value for some aspect which already
been selected.
The menus pop up on top of the copyright screen and that looks a bit
strange. I don't think core code has any way to erase that base
window without erasing the entire screen so to fix the strangeness
the window ports would need to do that before calling the selection
routine. I didn't do that because the very first prompt, "Shall I
pick ... for you? [ynaq]" shows up in that window rather than in a
popup over it, and having it be all by itself on an otherwise blank
screen seemed to be even stranger.
X11 and Qt both have more sophisticated selection routines so I
haven't tried to switch either of them to use this. They both use a
fancy role-selection-specific menu with all the aspects present at
once so this wouldn't fit without more work than I care to tackle.
The consolidation of global variables from scattered source
files into decl.c and declared in decl.h was begun in 3.7.0.
Their placement in common files was done for centralized
initialization and potential re-initialization during a
"play again" scenario.
It wasn't really necessary for all of them to be housed in a
single huge structure to meet the "play again" requirement,
and the single huge structure has been a little unwieldy when
it comes to maintenance.
Following this commit, instead of one single extremely large structure
named 'g' to house all of the relocated global variables, they
are distributed into several ga through gz.
To make things easy for the developer, each variable is placed
into the struct corresponding to the starting letter of the variable.
That way, no lookup is required in order to know which struct houses
a particular variable, it is a simple match to the starting letter
for all the centralized global variables.
A global variable named 'amulets', would be found in ga.
ga.amulets
^ ^
A global varable named 'move', would be found in gm.
gm.moves
^ ^
A global variable named 'val_for_n_or_more' would be found in gv.
gv.val_for_n_or_more
^ ^
A global variable named 'youmonst' would be found in gy.
gy.youmonst
^ ^
../win/curses/cursinit.c:102:9: warning: variable 'min_message_height' set but not used [-Wunused-but-set-variable]
int min_message_height = 1;
^
1 warning generated.
(user-side decisions really, but as it stands right now
user-side decisions/options are made and processed by the core)
add a parameter to add_menu so color can be passed
A new feature, enabled by default to maximize testing, but one which can
be disabled by commenting it out in config.h
With this, some additional information is added to the glyphmap entries
in a new optional substructure called u with these fields:
ucolor RGB color for use with truecolor terminals/platforms.
A ucolor value of zero means "not set." The actual
rgb value of 0 has the 0x1000000 bit set.
u256coloridx 256 color index value for use with 256 color
terminals, the closest color match to ucolor.
utf8str Custom representation via utf-8 string (can be null).
There is a new symset included in the symbols file, called enhanced1.
Some initial code has been added to parse individual
OPTIONS=glyph:glyphid/R-G-B entries in the config file.
The glyphid can, in theory, either be an individual glyph (G_* glyphid)
for a single glyph, or it can be an existing symbol S_ value
(monster, object, or cmap symbol) to store the custom representation for
all the glyphs that match that symbol.
Examples:
OPTIONS=glyph:G_fountain/U+03A8/0-150-255
(Your platform/terminal font needs to be able to include/display the
character, of course.)
The NetHack core code does parsing and storing the customized
entries, and adding them to the glyphmap data structure.
Any window port can utilize the additional information in the glyphinfo
that is passed to them, once code is added to do so.
Also, consolidate some symbol-related code into symbols.c, and remove it from
files.c and options.c
On terminals with at least 16 colors there should be no need for special
handling dark gray.
The curses code uses COLORS < 16, COLORS <= 16, COLORS > 16, or COLORS >= 16
at several places although I'm not sure if they are correct or which could
possibly be off-by-one errors.
But realistically in this case, we only need to distinguish between 8 color
terminals and terminals supporting more than 8 colors as this will mean the
terminal supports at least 256 colors.
Under curses interface, provide a way to get a little more space
for perm_invent without turning off windowborders entirely.
Possible 'windowborders' values:
0 = no borders, max screen space available for useful info
1 = full borders, two lines and two columns wasted for each window
2 = contingent borders, show if screen is big enough, else hide
New:
3 = as 1 except no borders for perm_invent window
4 = as 2 except never borders for perm_invent window
3 and 4 let the map, message, and status windows have borders while
providing two extra lines and two extra columns on each line for
persistent inventory. It's not much but better than nothing when
borders are enabled.
Gcc 9 has become more vocal with sprintf buffer overflow
checking. Remove these sprintf warnings by changing the
offending calls to a snprintf wrapper that will explicitly
check the result.
further adjustments to the window port interface to pass a pointer
to a glyph_info struct which describes not just the glyph number
itself, but also the ttychar, the color, the glyphflags, and the
symset index.
This affects two existing window port calls that get passed glyphs
and does the parameter consistently for both of them using the
glyph_info struct pointer:
print_glyph()
add_menu().
The recently added glyphmod parameter is now unnecessary and has been
removed.
combine boolean and compound options into a single allopt[] array for
processing in options.c.
move the definitions of the options into new include/optlist.h file which
uses a set of macros to define them appropriately.
during compile of options.c each option described in include/optlist.h:
1. automatically results in a function prototype for an optfn called
optfn_xxxx (xxxx is the option name).
2. automatically results in an opt_xxxx enum value for referencing
its index throughout options.c (xxxx is the option name).
3. is used to initialize an element of the allopt[] array at index
opt_xxxx (xxxx is the option name) based on the settings in the
NHOPTB, NHOPTC, NHOPTP macros. Those macros only live during the
compilation of include/optlist.h.
each optfn_xxxx() function can be called with a req id of: do_init, do_set,
get_val or do_handler.
req do_init is called from options_init, and if initialization or memory
allocation or other initialization for that particular option is needed,
it can be done in response to the init req.
req do_set is called from parseoptions() for each option it encounters
and the optfn_xxxx() function is expected to react and set the option
based on the string values that parseoptions() passes to it.
req get_val expects each optfn_xxxx() function to write the current
option value into the buffer it is passed.
req do_handler is called during doset() operations in response to player
selections most likely from the 'O' option-setting menu, but only if the
option is identified as having do_handler support in the allopts[]
'has_handler' boolean flag. Not every optfn_xxxx() does.
function special_handling() is eliminated. It's code has been redistributed
to individual handler functions for the option or purpose that they serve.
moved reglyph_darkroom() function from options.c to display.c
Provide a way to communicate additional behaviors and/or appearances
desired from NetHack window port menus.
This is foundation work for changes to follow at a future date.
groundwork only - window port interface change
This changes the last parameter for add_menu() from a boolean
to an unsigned int, to allow additional itemflags in future
beyond just the "preselected" that the original boolean offered.
There shouldn't be any functionality changes with this groundwork-only
change, and if there are it is unintentional and should be reported.
Fixes#235
For initial options under curses, specifying 'DECgraphics' as a
boolean rather than as 'symset:DECgraphics' wasn't overriding the
new default 'symset:curses'. Since previously DECgraphics was
rejected for curses, it's possible that no one noticed.
Primary and rogue symbols were being set to default if primary hadn't
been given a value, possibly clobbering rogue symbols if those had
been given a value. Initialize them independenly.
Return early from curses_convert_glyph() if the value doesn't have
the 8th bit set since it now deals exclusively with DECgraphics
handling. Force a sane value for returning early on rogue level.
This time I'm putting things in as-is before making a few tweaks.
The pull request was three or four separate changes. I used the
patch instead so they've been collected into one commit.
Highlighting for monsters shown due to extended monster detection and
for lava shown in black and white didn't work because that keys off
of 'iflags.use_inverse' (actually a macro for 'iflags.wc_inverse') and
curses wasn't enabling that window-capability option. To be fair, it
was probably unconditional at the time the curses interface was first
developed. It checked for whether a monster was supposed to be drawn
with inverse highlighting but wouldn't draw it that way because the
flag was always false. Inverse b&w lava is relatively new and curses
hadn't been taught about it.
Various other things such as pets (if hilite_pet is on) and object
piles (if hilite_pile is on) get highlighted with inverse video when
use_color is off, regardless of whether use_inverse is on or off.
That's probably a bug.
Fixes#230
Incorporate github pull request #230, support for DECgraphics-style
line drawing in the curses interface. I've rewritten the
curses_convert_glyph() part so that it doesn't require C99 and
doesn't reinitialize its pair of arrays for every character written
to the map. The DECgraphics conversion is now a straight char for
char one, DEC line drawing code to ACS, without regard to what map
symbol is intended or what 'cursesgraphics' uses for that symbol.
Right button is button3 rather than button2. Accept either and treat
both as "not left" to pass CLICK_2 back to the core.
Treat <Ctrl>+left-click as "not left" too, to simplify usage with Mac
one-button mouse (where <Ctrl>+left-click can be configured to send
"secondary click" but might not be set do so) or one-button laptop
trackpad (where having two fingers on the scrolling portion of the pad
while clicking the button is necessary to send "secondary click").
Autodescribe feedback and multi-digit count prompts are always shown
on the last line of the message window and are suppressed from message
history (both ^P and DUMPLOG). When the message window is using all
available lines, the last one was being overwritten (until the count
or the feedback was completed or dismissed, then last line returned).
Adopt the suggestion that it be scrolled up a line instead of being
overwritten. [I haven't been able to reproduce the reported problem
where shorter overlaid text left some of longer underlying text visible
but that should now become moot.]
Bonus fix: while testing, I noticed that if your screen only has room
for a one-line message window and you used ESC to cancel 'pick a spot
with cursor' prompting before moving the cursor, the prompt was left
intact on the message line. tty erases it in that situation, but the
clear_nhwindow(WIN_MESSAGE) was a no-op for curses because it usually
doesn't erase old messages. This changes the curses behavior when the
core asks it to erase the message window: now it forces one blank line
of fake autodesribe feedback (causing the prompt or other most recent
message to scroll off top), then removes that fake feedback (leaving
a blank message line). For multi-line message window, the old messages
scroll up by one line sooner than they would when waiting for the next
real message but are otherwise unaffected.
curses uses 'reversed' (LIFO) style when displaying previous messages.
Use the existing (previously tty-only) 'msg_window' option to also
support 'full' (FIFO). The actual code needed as just a couple of
lines; tweaking options parsing and the documentation was more work.
Using ^P right after resize or 'O' of align_message, align_status,
statuslines, or windowborders would result in
'curses_display_nhmenu: attempt to display empty menu'
because some memory cleanup I added several weeks back was being
executed when the curses interface tore down and recreated its
internal windows.
This fixes ^P handling by making sure that that menu (which is just
text but uses a menu to support '>'/'<'/'^'/'|' scrolling) will never
be empty and it also fixes the window deletion to not throw away
message history until it's final deletion at exit time.
^P uses a popup window to display previous messages and it was never
deleting that window, just creating a new one each time. Same with
the routine which displays an external help file. Using either or
combination of both close to 5000 times would probably make internal
window creation get stuck in an infinite loop. Delete those windows
after they're used so it'll never be put to the test.
The memory cleanup I added for map/status/messages/invent was only
being preformed at end of game, not when saving. Fix that too.
More groundwork for overhauling the status display for curses, plus
a few functional changes. It was doing a full status update for
every changed field (except conditions), instead of waiting for a
flush directive after gathering multiple changes at a time. Since
it already does gather every change, the fix to wait is trivial.
This decouples 'hitpointbar' from 'statushilites'. When highlighting
is off, it uses inverse video only. When on, it behaves as before:
using inverse video plus the most recent color used to highlight HP
(which can vary if that has rules to highlight changes or percentage
thresholds) but ignoring any HP attribute(s). This also enables the
latent 'statuslines' option and changes 'windowborders' option from
being settable at startup only to changeable during play.
'statuslines' can have a value of 2 (the default) or 3 and applies to
'align_status:bottom' or 'top'; it's ignored for 'left' and 'right'.
At the moment, setting it to 3 only allows status condition overflow
to wrap from the end of line to 2 to the beginning of line 3, and if
window borders are drawn they'll clobber the last character on line 2
and first one on line 3. There's no point in trying to fix that
because it will go away when the main status overhaul changes go in.
Condition wrapping for vertical orientation (left or right placement)
was already subject to the same phenomenon and will be superseded too.
This also changes the meaning of the 'windowborders' value so could
impact players using source from git (or possibly beta binaries for
Windows, but not for OSX where curses interface wasn't included).
Old:
0 = unspecified, 1 = On, 2 = Off, 3 = Auto (On if display is big
enough, Off otherwise; reevaluated after dynamic resizing);
Unspecified got changed to 3 during curses windowing initialization.
New:
0 = Off, 1 = On, 2 = Auto;
0 gets changed to 2 for default value at start of options processing.
So old value of 2 is changing meaning and explicit old value of 3 is
becoming invalid. Implicit 3 changes to default 2. Explicit 3 could
be the subject of a fixup but there isn't much point since 2 can't
have a similar fix. Users who are using old 2 or explicit 3 will need
to update their run-time config files.
This adds 'statuslines' to the Guidebook and moves some other recently
added documentation of curses options from among the general options
(section 9.4) to "Window Port Customization options" (section 9.5).
None of them have been added to dat/opthelp which seems to be missing
all the wincap options.
Originally I made a lot of changes (mostly moving C99 declarations to
start of their blocks) to the old '#if 0' code at end of cursstat.c,
but have tossed those, except for one subtle bug that assumed 'int'
and 'long' are the same size.
Miscellaenous stuff either groundwork for or noticed while updating
curses status. The status changes themselves need some more testing.
One or two of the comments refer to that revised status which hasn't
been checked in yet.
This started out as an attempt to document the curses options in the
Guidebook, but I didn't actually get that far. Instead, integrate
the curses options better via more consistent WC/WC2 usage. This
prevents 'guicolor' from showing up as a boolean option for non-curses
interface in curses+other binary.
For curses itself, let 'petattr' be set/reset via 'O'. Also, accept
'Dim' as a possible pet highlight attribute since it already handles
all the other ordinary attributes. I'm not sure what leftline and
rightline highlighting are supposed to do. They were missing for
ncurses (or maybe they're misspelled for PDcurses?) but adding them
didn't produce any visible effect (using TERM=xterm-256color on OSX
with default font/character set).
Not addressed:
1) general confusion about compile-time vs run-time option filtering;
2) curses pet highlighting only works if 'color' option is enabled.