Menus with wide header or separator lines were rendered wide enough
to avoid wrapping those lines, but ones with narrow header/separators
and wide selectable entries were limited to half the display even
though lots of lines that would fit with full width were being wrapped.
Change the latter behavior.
Menus are right justified with the edge of the map when narrower than
it, left justified otherwise, and if the display is wider than the map,
they'll extend beyond its right edge. (That hasn't actually changed;
it's just that left-justification is more likely now that menus will
be wide enough to show wide inventory lines without wrapping.)
Get rid of my ridiculous hack to force wider menu for the 'symset'
and 'roguesymset' sub-menus of 'O' since it's no longer useful.
There's still room for improvement. If any lines need to be wrapped
despite using the full width, or perhaps are just a lot wider than
most of the entries, menu width could be narrowed to just enough for
'normal' lines to fit so that one or two really long entries don't
distort the menu. That's a bit more complicated than I want to deal
with right now. [If implemented, it would be relevant for tty too.]
Have the 'menucolors' option control menu color pattern matching
(instead of curses-specific 'guicolor') for all menus, not just for
the persistent inventory window.
With 'popup_dialog' On, a prompt which exactly fills the available
width would start the next line with a space (to separate the prompt
from user's answer) and then have the cursor waiting after it. That's
unlike other behavior in the curses interface where the line split
would be instead of the separating space rather than in addition to it.
Old:
|long prompt?|
| X__________|
New:
|long prompt?|
|X___________|
where the X represents the cursor sitting over the start of blank space
waiting for user's answer.
With 'popup_dialog' On, a one line popup with question and likely
responses and default answer was shown, but without having the
cursor displayed at the end of emphasize that it was waiting for an
answer. Make the popup be one character wider so that there is room
to show the cursor. No effect when 'popup_dialog' is Off and prompts
are shown at the bottom of the message window; those already have the
cursor sitting at the end.
Make final inventory disclosure use a full width menu instead of
the default 38-column width with lots of wrapping. Also, increase
that default from 38 to 40 for the rest of the time. Commit
9f6588af49 made the 38 vs 40 portion
matter much less but I decided to keep it in anyway.
When a menu or 'things that are here' popup has only a couple of
lines and they happen to be narrow, a sized-to-fit window isn't
always easy to spot when it is shown over the ends of old messages
rather than over the map, even with a border box around it. Give
such windows a minimum size of 5x25 so that they always stand out
enough to be immediately seen. This will cause more message text to
be rewritten occasionally (after dismissing the menu or text window)
but the curses interface seems to discount that as something to be
concerned about.
Using ':' to have search string matching toggle items chosen for
selection would show selection highlighting on the current page for
items matched off-page.
Most of the entries for '?' looked awful because curses was using
((terminal_width / 2) - 2) for the window width ('- 2' was to make
for for a border around the popup window, regardless of what the
'windowborder' option was set to). Splitting text that has been
manually formatted for 80 columns "worked" but looked bad when not
required.
Some of the help files are using 79 characters on a few lines,
producing wrapped text when displayed. Those would look better if
limited them to 78 or if curses can be modified to suppress the
window border when the entire display is being covered by a popup.
Fixes#193
Under curses interface, make characters which are both entry selectors
and menu commands function as a selector. Needed to support using ':'
to look inside a container when applying/looting it via menu, instead
of performing a menu search operation. (There was another case like
this but I can't remember what the circumstances are. The fix is
general enough to cover it, whatever it is.)
For menus which don't have ':' as a choice, make sure search prompt
doesn't offer garbage default input when built with EDIT_GETLIN.
Bug? If player has 'popup_dialog' option On, EDIT_GETLIN is ignored.
Plain curses I/O doesn't seem to offer a way to implement it.
The curses interface would assign menu selector characters a-z, A-Z,
and then 0-9, but trying to type 0-9 would start a count rather than
select an entry, and if the display was tall enough for more than 62
entries, the ones after '9' were ASCII punctuation characters.
Limit the number of entries per page to 52 + number_of_'$'_entries
(which should be 0 or 1) so that it won't run out of normal letters.
The perm_invent window, if enabled, ought to allow more than that
because it isn't used to make selections and might have an arbtirary
number of '#' overflow entries. But I'll leave that for somebody
else to tackle.
Tested by temporarily setting the limit to 26 instead of 52 since
I'm not able to display anything tall enough to exercise the latter.
I've noticed many instances of the game pausing and not being sure why,
then pressing <space> and having it resume. The curses interface had
a tendency to put its equivalent of the --More-- prompt, >>, somewhere
where that wasn't visible, either off the right hand edge (possibly) or
underneath the window borders if those were enabled. Especially the
very last one it issues prior to exit. (An extra one compared to tty
behavior.)
This ended up being a pretty substantial overhaul of message window
handling. I wouldn't be surprised if it has off-by-one errors which
happen to be paired up and cancel each other out. ">>" is still drawn
in orange if guicolor is on, now in inverse video when that is off.
If it happens to be drawn at the same screen location in consecutive
instances, the first ">" will toggle between blink and not blink so
that there'll be no doubt as to whether the keypress registered when
dismissing it (moot if the text preceding it is different but there's
no attempt to be smart enough to check that, just screen placement).
Make the same fix to curses that was done for tty in 3.6.1: don't
let MSGTYPE entries be matched against prompt strings. Like tty,
curses was using ordinary pline() to issue prompts; something like
MSGTYPE=hide"yn"
could wreak havoc. Switch to custompline(OVERRIDE_MSGTYPE,...).
This changes the recently added msg_window:f for curses to start
viewing the old messages on the last page rather than the first. For
msg_window:Reversed (the default for curses) and for either direction
when all of the message history happens to fit on one page, there's
no change. But for multiple pages, the FIFO feedback now pads the top
of the first page with blank lines so that the last page is full, and
it starts out showing that last page first. So if you only want to go
back few or several messages, they will be in view immediately.
Old layout:
|first message (oldest) | |1st message of last page |
|2nd message of 1st page | | ... |
| ... | |final (most recent) mesg |
| ... | | (blank filler) |
|last message of 1st page | | (blank filler) |
| (1 of 2) => | | <= (2 of 2) |
and ^P started with first page visible and needed normal menu handling,
<space> or '>' or '|', to go forward to view the most recent messages.
New layout:
|1st message of last page | | (blank filler) |
|2nd message of last page | | (blank filler) |
| ... | |first message (oldest) |
| ... | | ... |
|final (most recent) | |last message of 1st page |
| <= (2 of 2) | | (1 of 2) => |
and ^P starts on last page (two of two in this example) but can go
back with '<' and '^'.
So if the total size takes one and third pages (which isn't uncommon
for the default number of kept messages), you'll see 3/4 of the most
recent messages on the initial screen, then you can page backward if
you want to see the other 1/4.
The page indicator is deliberately drawn a bit differently just to
draw attention to the fact you're starting on the last page. I'm not
sure whether that is actually worthwhile but it was trivial to do.
The curses interface was using 'moves' as if it meant "moves" rather
than "turns". Typing ESC at >> (curses' terser version of --More--)
prompt would suppress messages for the rest of the current turn rather
than just the rest of the current move. So if the hero got an extra
move due to being Fast, there would be no feedback during that move.
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.
Fix:
../sys/winnt/nhraykey.c: In function 'CheckInput':
../sys/winnt/nhraykey.c:459:37: warning: type of 'mode' defaults to 'int' [-Wimplicit-int]
int __declspec(dllexport) __stdcall CheckInput(hConIn, ir, count, numpad,
^~~~~~~~~~
Twice I've gone through the curses code to deal with CHAR_P, BOOLEAN_P,
and so forth. Both times I eventually changed my mind. This time I'm
just adding an explanatory comment instead.
Extend the earlier support for Delete/Rubout in getline() to the
text entry for extended commands. In other words, treat <delete>
and <backspace> as synonyms in both places.
Some reformatting too, but only in a couple of the files.
This takes care of a lot of the leaked memory in the curses interface.
It still needs to free memory allocated for status fields when the
status window is destroyed at game end; likewise for message history
when the message window is destroyed.
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().