Commit Graph

106 Commits

Author SHA1 Message Date
Pasi Kallinen
e240efa10b Restoring a game can return to the wishing prompt
In TTY or curses, if the terminal goes away while you're in the wishing
prompt, return to the prompt when the game is restored.

Breaks saves.
2025-07-12 18:21:12 +03:00
PatR
e21a5c6ac3 curses band-aid
heaputil reported an attempt to free a null pointer at line 1314 of
cursdial.c (in menu_display_page()).

curses_break_str() can return Null but its callers aren't prepared
for that.  Make it return an empty string that can be passed to
free() instead.
2025-04-20 14:19:40 -07:00
nhmall
45b2a6c49a more C standard progress
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
2024-12-20 10:32:38 -05:00
nhmall
0792e5fe9e expand implicit fallthrough detection to non-gcc compilers
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.
2024-11-30 14:16:27 -05:00
nhmall
0eb7f109e0 follow-up, program_state 2024-07-13 16:31:35 -04:00
nhmall
6c0ae092c6 distinguish global variables that get written to savefile
The g? structs had a mix of variables that were written to
the savefile, and those that were not.

For better clarity and to distinguish those that end up in
the savefile, relocate some g? variables that get written
directly to the savefile into different structs.

This updates EDITLEVEL, although technically it probably
didn't need to, since savefile contents are not changing.

Details:

    gb.bases            -> svb.bases
    gb.bbubbles         -> svb.bbubbles
    gb.branches         -> svb.branches
    gc.context          -> svc.context
    gd.disco            -> svd.disco
    gd.dndest           -> svd.dndest
    gd.doors            -> svd.doors
    gd.doors_alloc      -> svd.doors_alloc
    gd.dungeon_topology -> svd.dungeon_topology
    gd.dungeons         -> svd.dungeons
    ge.exclusion_zones  -> sve.exclusion_zones
    gh.hackpid          -> svh.hackpid
    gi.inv_pos          -> svi.inv_pos
    gk.killer           -> svk.killer
    gl.lastseentyp      -> svl.lastseentyp
    gl.level            -> svl.level
    gl.level_info       -> svl.level_info
    gm.mapseenchn       -> svm.mapseenchn
    gm.moves            -> svm.moves
    gm.mvitals          -> svm.mvitals
    gn.n_dgns           -> svn.n_dgns
    gn.n_regions        -> svn.n_regions
    gn.nroom            -> svn.nroom
    go.oracle_cnt       -> svo.oracle_cnt
    gp.pl_character     -> svp.pl_character
    gp.pl_fruit         -> svp.pl_fruit
    gp.plname           -> svp.plname
    gp.program_state    -> svp.program_state
    gq.quest_status     -> svq.quest_status
    gr.rooms            -> svr.rooms
    gs.sp_levchn        -> svs.sp_levchn
    gs.spl_book         -> svs.spl_book
    gt.timer_id         -> svt.timer_id
    gt.tune             -> svt.tune
    gu.updest           -> svu.updest
    gx.xmax             -> svx.xmax
    gx.xmin             -> svx.xmin
    gy.ymax             -> svy.ymax
    gy.ymin             -> svy.ymin

Related note:
There are some pointer variables that are heads of chains that were not
moved from 'g?' to 'sv?', because they are not actually written to the
savefile directly, but the objects/monst/trap/lightsource/timer in the
chains they point to are. That can be changed, if desired.
Examples: gi.invent, gm.migrating_objs, gb.billobjs, gm.migrating_mons,
          gf.ftrap, gl.light_base, gt.timer_base
2024-07-13 14:57:50 -04:00
Pasi Kallinen
243f6410d2 Curses: simplify color handling
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.
2024-03-15 20:36:56 +02:00
PatR
d682d8b3d3 curses: build fix for italics attribute support
I've been building tty-only for a while in order to speed up
builds, so a recent change to the curses interface that broke
compile on older OSX went unnoticed.  The <curses.h> on my
OSX 10.11.6 system does not define A_ITALIC.
2024-02-08 13:10:42 -08:00
Pasi Kallinen
fd8b2b58d1 petattr: Change accepted parameters, add support for tty 2024-01-28 10:05:42 +02:00
nhmall
9d32956616 curses static analyzer bits
This is mostly just adding some Null guards ahead of
code that was already dereferencing pointers, so there
should be no change in behavior.

Also adds one validation of an array index that was
drawing a complaint.
2023-12-29 10:38:37 -05:00
nhmall
04082a2033 Remove TEXTCOLOR build option 2023-11-22 16:01:58 -05:00
nhmall
bb10f9a5d0 more menu header tweaking re options
<color>
off: map, menu items, menu headings, menu prompt/title all, everything should have color suppressed.

<curses guicolor>
on: map, menu items, menu headings, menu prompt/title can all feature color, as can
menu borders, menu-selector letters.
off: map, menu headings, menu prompt and menu items (menucolors on) can still feature color,
but all other non-map features such as menu borders, menu-selector
letters will not have color.

<menucolors>
on: menu items can have colors if they match one of the regex in config
file; menu headings, menu prompt can also be in color (based on menu_headings option).
off: menu items won't have colors, but menu headings, menu prompt still
will feature colors (based on menu_headings option); those are not impacted by turning
off menucolors.
2023-11-16 13:41:07 -05:00
nhmall
97ddfd9355 curses menu_heading repairs 2023-11-15 11:11:55 -05:00
Pasi Kallinen
dd5ca5b058 Change menu_headings to accept color and attribute
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
2023-11-13 07:33:56 +02:00
PatR
853613cb68 curses numpad handling comments
Update a couple of comments for yesterday's 8-bit escapes M-O to M-^O
fix.
2023-08-14 13:08:11 -07:00
PatR
8b57393027 curses number pad revisited
The previous curses escape sequence conversion for 8-bit sequences was
looking for those to start with M-O when the correct value for that is
actually M-^O.

Add support for the number pad's non-digit keys.  Most useful for real
VTxxx keyboard since emulators are usually stuck mapping '+' and '.'
to ',', '.', and '-'.  There's no universal solution for that.
2023-08-13 13:07:54 -07:00
PatR
70834c12df curses number pad handling
This attempts to address the issue on hardfought (as described by K2
on reddit two weeks ago) which happened after updating their terminfo
database.  It's based on the reported workaround of having users force
their terminals to avoid "application keypad mode".  The fixes entry is
my guess at what is happening so could be wrong....

I don't have a numeric keypad so this is untested; it /ought to work/.
NetHack's curses interface is doing it's own keypad recognition when
the curses library returns a multi-char sequence rather than converting
that into corresponding KEY_xxx token.  Numpad keys that the interface
recognizes begin with 2 char 'ESC O' when transmitted as 7-bit sequences.
This adds support for SS3 (as sent by DEC Vtxxx terminals and emulators;
value is single char 'M-O') for 8-bit sequences.

It shouldn't break typing Alt+O but that's something else that I can't
test properly.  Setting nethack's 'altmeta' option and manually typing
2 char 'ESC O' still works as intended.

This is curses-specific; the tty interface is completely unaffected.
[However, the vms port has supported SS3 with tty for decades. :-]
2023-08-11 13:14:01 -07:00
nhmall
36ba2b9a0e fix curses build issue caused by "attr_t same as int" assumption
In file included from ../win/curses/cursmisc.c:6:
../win/curses/cursmisc.c: In function 'curses_convert_attr':
../lib/pdcursesmod/curses.h:562:32: warning: overflow in conversion from 'long long unsigned int' to 'int' changes value from '2147483648' to '-2147483648' [-Woverflow]
  562 | #define PDC_ATTRIBUTE_BIT( N)  ((chtype)1 << (N))
      |                                ^
../lib/pdcursesmod/curses.h:574:27: note: in expansion of macro 'PDC_ATTRIBUTE_BIT'
  574 |     # define A_DIM        PDC_ATTRIBUTE_BIT( PDC_CHARTEXT_BITS + 10)
      |                           ^~~~~~~~~~~~~~~~~
../win/curses/cursmisc.c:752:23: note: in expansion of macro 'A_DIM'
  752 |         curses_attr = A_DIM;
      |                       ^~~~~
2023-06-12 13:53:34 -04:00
nhmall
b21ef624eb fix dos cross-compile 2023-06-06 18:42:27 -04:00
PatR
4e32364313 fix #K3934 - curses menu bug when entering count
Entering a multi-digit count when selecting from a menu in the curses
interface causes the menu to disappear.  Report was about putting a
large subset of an object stack into a container but the bug affected
all menus that accepted counts.

curses_get_count() was changed to call core's get_count() quite a
while back.  get_count() calls mark_synch() when more that one digit
is typed or when backspace to remove the first digit occurs.
curses_mark_synch() had been a no-op but more recently it was changed
to try to make sure that the screen was up to date.  But it did that
by refreshing the persistent windows, making any temporary popup menu
or text window become hidden.  Also, the count-in-progress is being
sent to the message window with the no-history flag, so refreshing
the message window removed that too.

Switch curses_mark_synch() to use the basic screen refresh call that
doesn't do anything window-specific.  This also changes menu count
handling to have get_count() echo the number starting with the first
digit instead of waiting until the second.

If anything in the menu makes it be very wide it can cover up the
message window and any count being echoed there won't be visible.
I'm not going to try to figure out how to deal with that; it isn't
all that different from the old single-digit/unseen-count behavior.
2023-06-02 11:42:18 -07:00
PatR
0d31bb8c88 change program_state.getting_a_command
to program_state.input_state

Rename program_state.getting_a_command and give it an int value
instead of treating it as boolean.  Start using to it for Qt to
suppress commands initiated from the drop down menus in the title bar
if nethack isn't expecting to get a command from the user.  Those menu
choices inject extended command text into the input stream and should
be avoided when entering text or waiting for a menu to be dismissed.

These menus would be better if they grayed out unavailable choices
when pulled down instead of accepting any choice and then treating
that no good.  I'm not going to try to figure out to do that with Qt.
And this workaround for the menus doesn't have any affect on the
toolbar buttons below the title bar.  Those execute core commands
directly and when I tried to use jacket routines instead, the tool bar
stopped showing up so I've given up.

This won't fix the reported problem of getting stuck in a loop.
2023-04-06 01:56:08 -07:00
nhmall
a136dbac06 comment update in win/curses/cursmisc.c 2023-03-24 11:54:47 -04:00
PatR
3fcd56e6e3 curses: resize vs beep
Dynamically resizing the terminal window during play by dragging its
edges was beeping (a lot if you dragged slowly).  Recogize the key
code sent for that instead of complaining about unrecognized input.
2023-03-23 12:47:56 -07:00
PatR
f5d400be75 fix github issue #1002 - curses screen flash
Reported by jeremyhetzler:  with recently revised curses interface,
when dismissing a menu or prompt with ESC the screen flashed.

This was caused by calling beep() when the terminal is set for
'visible bell' (of flagged as incapable of 'audible bell'); the
curses library flashed the screen deliberately.  We don't want that.

Change the function key handling to not call beep() when an ESC
is typed by itself rather than being the leading part of a
multi-character escape sequence.  beep() will still be called if
you type an arrow key (or other function key) when nethack is
expecting text input.  That's what the recent change intended.

This also removes an early return from parse_escape_sequence()
when a number pad key generates an escape sequence.  I don't have
a number pad to verify that this bit works as intended.

Closes #1002
2023-03-23 11:12:34 -07:00
Pasi Kallinen
35273b8a8c Curses: prevent spurious cursor updates
While watching a ttyrec, I noticed strange behaviour in
the cursor updates; it was moved to approximately middle
of the map window every so often, usually when doing ranged
attacks. This wasn't really noticeable in normal gameplay,
as it was moving the cursor there, and then almost immediately
to where it was supposed to be.

I managed to trace it down to the refresh() in curses_delay_output().
That call updates the terminal to match the ncurses stdscr window,
but the stdscr window cursor position wasn't updated by NetHack.
2023-03-12 19:21:51 +02:00
PatR
30de551f02 more curses key handling
Some bits made when attempting and failing to figure out the curses
problem (which turned out to be an early return skipping reset of
input timeout and fixed by paxed).
2023-03-08 14:38:53 -08:00
Pasi Kallinen
96587d2acf Fix curses quitting when trying to move
parse_escape_sequence changed getch timeout, but when receiving
a certain escape sequence, it returned without changing the
timeout back. This caused all subsequent getch calls be
non-blocking, and getch returns ERR when there's no input
waiting in that mode.

NetHack interprets ERR as the terminal going away, so performs
an automatic save.
2023-03-08 12:19:57 +02:00
nhmall
6836eb07d8 follow-up bit for cursmisc.c 2023-03-01 20:05:43 -05:00
nhmall
5a4d983104 fix uppercase alt key combinations with PDCurses 2023-03-01 17:06:15 -05:00
PatR
6ba11256ba partial fix for #K3869 - curses: meta characters
Meta-key fix for curses interface running on top of ncurses library.
Previously only digits and lower case letters would produce a meta
character when combined with Alt (or Option on Apple keyboards), now
it should work for any basic character (not arrows or other function
keys).  It only works on terminals that send two characters ESC k
for Alt+k but that is not a change in behavior.

curses interface running on top of PDcurses library uses different
code which isn't fixed by this.  The alt key fixup it does have was
already present in curses_read_char() and recently got duplicated in
curses_convert_keys().  At least one other routine calls the latter
so it was necessary, but curses_read_char() calls that routine so
doesn't need to keep its own copy of the fixup.
2023-02-28 10:14:25 -08:00
nhmall
7c0d65718c paste error 2023-02-28 00:09:37 -05:00
nhmall
42e337c306 return correct ALT-key sequences with PDCurses
They weren't working at all because the values of ALT_A through ALT_Z
were out of the normal char range with PDCurses, and caught by the default
case in the switch, where reject got set.

/* use key as-is unless it's out of normal char range */
        reject = ((uchar) ret < 1 || ret > 255);
2023-02-28 00:05:04 -05:00
PatR
d75beae272 address github issue #987 - curses: arrow keys
Issue reported by jeremyhetzler:  left and right arrows produced
unexpected characters when trying to use them to edit text that is
being entered.

The curses interface converts arrow keys and function keys related
to the keypad into movement keys (hjkl or 4286 depending on the
number_pad setting).  But it was doing that all the time, not just
when nethack wanted movement keys.  This extends the existing
program_state.getting_a_command flag to getdir() so that it can be
used for controlling that in addition to 'altmeta' support.

Typing an arrow when interacting with the map (actual command or
getpos, now getdir too) will still work.  Typing one when making a
wish or naming a pet will issue a beep and be treated as if '\0' had
been typed, and that normally gets treated as if ESC had been typed.
[Possible room for improvement there.  Losing the whole text when
trying to back up a character feels a bit harsh.]

Treating left arrow as escape rather than as h or 4 will probably be
enough to train players not to try to edit text with it after they
get burned by that a time or two.

Bonus fix:  curses' keystroke conversion only supported traditional
number_pad behavior, not the inverted phone number pad layout.

Closes #987
2023-02-23 14:02:28 -08:00
nhmall
02a48aa8cf split g into multiple structures
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
     ^ ^
2022-11-29 21:53:21 -05:00
Pasi Kallinen
ef093d0b30 Fix curses cursor keys
My change to allow fuzzer run in curses caused the cursor keys
to not work (eg. paging through menus with left and right cursor),
so fix that.
2022-09-24 10:40:38 +03:00
Pasi Kallinen
fbb32ea7fa Curses: enable debug fuzzer 2022-09-22 13:10:19 +03:00
PatR
4aefe3dae0 curses A_ITALIC build fix
My /usr/include/curses.h has various A_attribute macros but A_ITALIC
isn't one of them.  Compiling cursmisc.c failed because one of the
uses of that wasn't guarded by #ifdef A_ITALIC.  Instead of adding the
ommitted #if, substitute A_UNDERLINE for A_ITALIC when that's missing.

The select attribute menu when adding a menu color or a status hilite
now shows an entry for italic that's underlined (as expected) but the
underline entry itself does not display any sort of attribute.  I
didn't pursue that.
2022-09-05 14:40:41 -07:00
Patric Mueller
8bf5654eed tty and curses: support italic as text attribute 2022-09-04 22:33:25 +02:00
nhmall
3004cf2d34 be more consistent with coordinates 2022-07-02 09:10:03 -04:00
nhmall
2770223d10 interface groundwork for core-side color decisions
(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
2022-06-25 13:21:51 -04:00
PatR
a9a9d19038 item-action 'I' - use #adjust to split a stack
More context-sensitive inventory support.  While examining inventory,
if you pick an item other than gold and it has a quantity of more
than 1, "I - Adjust inventory by splitting this stack" will be one
of the menu choices.

Breaking doorganize() into two parts was much easier than expected,
but the new internal command added to be an alternate for the first
part had more niggling details than anticipated.

Message history only shows the first digit with "Split off how many?"
if the player enters more than that.
2022-04-20 13:38:09 -07:00
PatR
41eecdf6b3 curses menu: support backspace/delete for counts
Have curses call the core get_count() routine instead rolling its
own so that backspace and delete are supported.  That part was
trivial to accomplish.  Unfortunately it brought the disappearing
menu phenomenon back so it became more complicated overall.
2021-06-06 05:54:53 -07:00
PatR
0280006d76 fix #K3357 - curses menu disappears
This fixes the disappearing menu, but not curses menu count entry
failing to honor backspace/delete.  Entering two or more digits
to get a "Count:12" message, followed by non-digit which removes
that, resulted in the menu for apply/loot in-out container operation
vanishing while it was still waiting for a choice.  (Typing a choice
blindly did work.)

The code intended to handle this.  I don't understand why refresh()
wasn't working.  Reordering stuff didn't help until I changed that
from refresh() to wrefresh(win).

The original Count:123 display was limited to 25 characters and
menus to half the main window, so they didn't overlap.  I made the
count display wider--because it is now also used for 'autodescribe'
feedback when moving the cursor around the map--so made something
that originally was impossible become possible.  One line of the
menu does get erased while "Count:" is displayed, but then gets put
back by the wrefresh().
2021-06-05 16:11:50 -07:00
Patric Mueller
5c15ca1002 curses: remove unnecessary special handling for dark gray
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.
2021-06-05 14:38:41 +02:00
PatR
015380fecf remove several obsolete C() and M() macros
The ones moved from cmd.c to global.h suffice.
2021-03-10 13:50:44 -08:00
nhmall
262f0d11b5 a couple of curses warnings on one compiler 2021-01-29 23:14:16 -05:00
nhmall
f963c5aca7 switch source tree from k&r to c99 2021-01-26 21:06:16 -05:00
nhmall
c9673b3d9e more window port interface adjustments
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.
2021-01-05 10:09:37 -05:00
Pasi Kallinen
7cfc5a7142 Fix buffer underrun in curses 2020-11-15 13:22:45 +02:00
nhmall
ac9ba38449 file header bump from "NetHack 3.6" to "NetHack 3.7" 2020-08-03 22:07:36 -04:00