Menus in the curses interface would honor a digit as a selector
character ("letter" :-) for PICK_ANY menus but forced it to start a
count in PICK_ONE menus. This fixes that, although the menu where I
was using digits as selectors (not included) has been changed to use
letters so this fix isn't being exercised anymore.
Also, add a couple of comments about persistent inventory.
The default engraving-in-corridor character is the same as the default
corridor symbol (and also default lit corridor one), distinguished by
color. Show it differently (in inverse vidoe, like lava vs water and
sink vs fountain) if color is Off.
It might be better to change the engraving-in-room symbol to be the
same as the room one so that they'll be more consistent with corridors;
color is probably sufficient without resorting to back-tick. But this
update hasn't done that.
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.
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. :-]
We received a report from someone whose build was failing because
of the use of cchar_t and setcchar(). They were getting errors
even though they were using an up-to-date curses library.
Apparently, ncurses requires that _XOPEN_SOURCE_EXTENDED must be
defined before the curses header files in order for those features
to be available.
We had already updated our .370 series of hints and hints/include
files with
-D_XOPEN_SOURCE_EXTENDED=1
but this person must have been building in some other way.
Instead of failing to build in that situation, allow the
fallback to the older, less-functional genl_putmixed() function,
but also try not to do so silently and display a message that
functionality is reduced.
The difference between the use of genl_putmixed() and
curses_putmixed() or tty_putmixed(), is that when doing
'/' farlook operations, curses_putmixed() and tty_putmixed() try to
display a character in the message window that looks exactly the same
as the one on the map, even if a symbol from a symset is being used
on the map, or when using ENHANCED_SYMBOLS.
Related note: curses_putmixed() matches the symbol and the color,
whereas tty_putmixed() (at present) does not attempt to match the
color.
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;
| ^~~~~
The curses interface was using genl_putmixed() which doesn't
preserve the symbol actually used for a glyph on the display.
This is a first-attempt at implementing curses_putmixed().
On Linux you'll need to distribute the Makefiles again
sh sys/unix/setup.sh sys/unix/hints/linux.370
On macOS, you'll need to distribute the Makefiles again
sh sys/unix/setup.sh sys/unix/hints/macOS.370
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.
author Ray Chason <ray.chason@protonmail.com> 1684372172 -0400
committer nhmall <nhmall@nethack.org> 1685414340 -0400
Add configuration to support Curses on WinGUI
and enable support for Unicode on Curses.
Allow NetHackW to select the Curses interface
Reorder drawing of extended command prompt
Curses on WinGUI needs this change. This may be a bug in PDCursesMod,
but it seems to be harmless to the other ports.
Avoid calling Curses after the windows are closed
Provide erase_char and kill_char for WinGUI Curses
Set Lua version to 5.4.6
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.
In curses, selecting a partial stack, then unselecting the entry,
and then selecting it normally, the entry still kept the quantity
from the partial selection. Make it behave like all the other
windowports by resetting the quantity when the entry is unselected.
This is a better workaround for the missing message window border when
when restoring with align_status:left. Unlike the previous hack, this
may even be the correct way to handle it in the first place.
I haven't tracked down when the problem started.
This fixes the missing message window border when restoring with
align_status:left (which narrows and forces that window to the right).
It can't possibly be the correct way to fix things but does work.
This was not a problem with 3.6.4 (the most recent pre-3.7 playground
I have on hand) but I don't have the energy to use 'git bisect' to
track done when it started to whether the cause is discernable. The
message history is put into place without going through putstr() so
differs from normal message handling.
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.
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
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.
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).
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.
In some scenarios where a message prompted a 'more' (in curses shown as
'>>'), the '>>' could overwrite the last one or two characters of the
message.
This could happen if a single message on its own was the length of the
message space minus 2 (e.g. for an 80 character terminal, "h - a concave
amulet named this is an amulet name, it is very long, and so on."), or
if an addition to an existing line brought it to the length of the
message space minus 1 or 2 (e.g. "You materialize on a different level!
You remember this level as testlevlname."). The two scenarios had
slightly different causes.
I think this fixes both of those scenarios. I believe this is the
cause of the problem described in GitHub issue #990 but there isn't
enough detail to know that for a fact.
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.
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);
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
From the newsgroup: identifying by menu pops up multiple menus in
succession if the player picks fewer invent entries than are being
granted, but the second and subsequent ones could cover up the
message window and hide the feedback from prior ones.
If multiple popup menus are needed when identifying, issue --More--
before each menu after the first. The code seemed to be trying to
do this already, but it should have used wait_synch() rather than
mark_synch(), or perhaps used display_nhwindow(WIN_MESSAGE, TRUE)
instead of either one of those. For curses, both mark_synch() and
wait_synch() were no-ops. Now they do something. X11's behavior
wasn't right either; it seemed to be lagging one message behind
(something I had noticed recently and then forgotten about; I still
don't remember the context then so don't know whether this fixes
that earlier situation).
This ended up combining several unrelated changes.
Add missing 'fixes' entry for curses-specific item in New Features.
When answering "Shall I pick ... for you? [ynaq]", accept \m as well
as \n and space for choosing the default of 'y', same as normal
ynaq() would. Also add '*' to '@' as not-shown potential answers;
they force 'random'.
When tty tore down any of the menus, things were reasonable if they
were short enough for corner windows, but tall ones that switch to
full screen weren't fully erased. The parts of those outside of the
map window stayed behind when the tall menu was closed and cleared.
Mainly affects picking the "~ - reset filtering" choice but also
affected the role menu on 24 line tty screens. (Didn't affect curses
because it tracks and refreshes its base window when some overlaying
window goes away.)
The role menu used 25 lines so required a second page for the case
of a 24 line screen on tty. Dealing with that is a bit ugly but it
wasn't an issue when this form of role selection was tty-only (because
the info about choices made so far was displayed on the base window
rather than in an extra menu line back then) so I added a hack for it.
If the role menu will take one more line than the screen height, the
separator between 'random' (below 'Wizard') and 'pick race first' gets
squeezed out. If the menu needs two more lines (doesn't happen now,
except by changing screen size to 23 lines for testing), a second line
gets squeezed out. (Not attempted for curses because it wouldn't
help. 'windowborders' and one or two extra separators it adds make
menus taller. I doubt if many players use curses on 24-line screens
but if they do, they'll be using something new rather than going from
something that used to fit on one page with 3.6.x.)
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.