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.
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
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
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
^ ^
A change to the curses interface from three years ago to make sure
that round-off didn't make the horizontal and vertical clipped map
indicators appear to not be clipped was using ROWNO for both instead
of COLNO for the horizontal one. For modest clipping the mistake
was unnoticeable; I don't know whether that remained true for more
extreme clipping.
[Not fixed: the curses scrollbar stuff ignores the fact that map
column 0 is unused.]
* When saving: curses_exit_nhwindows calls curses_uncurse_terminal,
which calls endwin. curses_exit_nhwindows then calls raw_print,
which calls more Curses functions after endwin has been called.
Fix this by having curses_raw_print use puts if window_inited
is false.
* When dying, quitting, etc.: really_done opens the "Goodbye" window,
which refreshes the other windows when it closes. But the status
window (and possibly the map and message windows) are gone by that
point. The window pointers are properly NULLed, but the NULL is then
passed to touchwin. Fix this by checking window pointers for NULL.
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
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.
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.
Submitted for 3.7.0; all but one also apply to 3.6.3.
I rewrote the curses terminal-too-small message instead of just
fixing the spelling of "minumum".
From hardfought; latest gcc complains that /* fall through other stuff */
doesn't match its pattern for /* fall through */ comment indicating
that omitted 'break' statement is intentional and one switch case is
deliberately continuing into the code for another.
The position bars shown by curses when the map is clipped weren't
being drawn as intended (integer arithmetic). Changing parentheses
was enough to get it working, but it didn't handle the edge case
where non-zero got rounded to 0 (so when map was panned down, the
uppermost character of the vertical position bar still showed '*',
falsely indicating that top of map was currently within view.
tty ignores map column #0 (0-based index), like the core, and draws
the map in screen columns 1 (1-based index) through 79, leaving screen
column 80 blank. curses was drawing all 80 map columns and since #0
was always unused, screen column 1 was blank and the map was shown in
2 through 80. Change curses to work like tty.
This was too easy; there may be problems lurking. One known issue: it
should be made smarter about when clipping/panning is necessary since
it thinks that a full 80 columns are needed but 79 suffice.
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.
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.
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.
Three or four instances of one simple memory leak. Allocating a union
'anything' to pass to add_menu(), then not doing anything with it. The
value gets copied so there's no reason for the original to stick around.
[There are still lots of other memory leaks.]
There was no provision for malloc() potentially returning Null and it
wasn't integrated with nethack's MONITOR_HEAP. 'heaputil' shows that
the curses interface is leaking like a sieve. If some things are
actually being allocated separately and then freed from within curses,
those need to be thoroughly documented and maybe switched back to
malloc().