The failing Travis build issued about 500 lines of diagnostics
when complaining about one line of the source. It compiled ok
for me but I use older versions of Qt library and C++ compiler.
For Qt with 'popup_dialog' On, fix number entry when user types
a digit (or '#') directly onto the dialog instead of clicking
inside the Count box and then typing. Before, that first typed
digit was starting out as selected, so typing the next digit
replaced the selection instead of getting appended to the string
of digits being constructed. Fixed by moving the relevant code
to the KeyPress handler instead of re-executing the dialog.
Also, if a keypress is just a modifier, ignore it. The next
event should be the actual character. Prevents treating <shift>
(and <caps lock>!) as useless dialog responses. Before this,
attempting to type '#' to initiate a count wouldn't work because
the <shift> part of shift+3 ended the dialog. Now '#' works
(and is still optional; starting with a digit suffices).
Support MSGTYPE=stop by having qt_display_nhwindow(WIN_MESSAGE,TRUE)
issue a tty-style --More-- prompt. For popup_dialog Off, the prompt
gets appended to the most recent message; for popup_dialog On, it is
issued via a popup and not displayed in the message window.
It accepts <space>, ^J, ^M, and ^[ (ESC) to dismiss. There's no way
to dismiss it with the mouse (for !popup_dialog) which might need
some fix....
Several adventures along the way. The '^C-in-parent-terminal triggers
infinite loop repeatedly complaining about "event loop already running"'
is now a one-shot complaint. It isn't fixed but the severity of
having it happen is greatly reduced.
Some changes to the YnDialog widget used when popup_dialog is On.
If a button is labelled with a space, it just looks like an
unlabelled button. Switch to "Spc" for space, "Ent" for \n and
"Ret" for \r. (The last two aren't completely logical but I
haven't seen any dialogs that need them and they'll be better
than "^J" and "^M" if there are such.)
For yn#aq dialogs, preload a grayed-out "#" in the count widget.
Just for show; has no tangible effect.
The count widget should return long rather than plain int.
Replace the blank placeholder icon with individual placeholders
for Stone, Slime, Strngl, Deaf, Lev, Fly, and Ride. They're just
40x40 tiles showing solid color (different for each) holding white
block letters spelling the condition. For the first four of those,
the text runs from upper-left to lower-right, for Lev and Fly the
text runs from lower-left towards upper-right, and for Ride it's
horizontal. Not particularly exciting but better than blank. We
still need real artwork to make them be similar to the older
conditions.
Also moves the two petmarks and the pilemark from qt_xpms.h to
qt_map.cpp. The marks and the assorted status icons are all
static arrays, and including that header in two source files
meant that they were all duplicated unless the compiler or linker
was smart enough to discard the unused ones.
For Qt, experience points weren't shown when enabling 'showexp'
option because they were conditional upon '#if EXP_ON_BOTL'. That
got eliminated prior to 3.6.0 so wasn't defined for qt_stat.cpp.
When displayed, show Exp as Level:Xp/Exp instead of as a separate
status field. This has the intentional side-effect of omitting it
when hero is polymorphed and status shows HD instead of Xp.
Label the six characteristics in mixed case instead of all upper
case: Str, Dex, and so forth.
Any key bindings in player's run-time config file will already be
in place by the time the Qt menus are constructed. Those menus
will use the new key assignments rather than the defaults, so not
a bug.
The #enhance menu revealed a couple of menu problems for Qt.
Items flagged with "*" or "#" were showing tiny "..." instead of
the flag character. An existing problem rather than something
caused by yesterday's overhaul patch.
The "(Skills flagged by "*" may be enhanced when you're more
experienced.)" legend line was causing the regular entries to be
formatted strangely (their skill name column was much too wide).
That was caused by me dropping something (special case for header
lines during tab-separation handling) in yesterday's patch that
I mistakenly thought wasn't needed.
The save file selection widget was issuing a complaint to stderr:
|QLayout: Attempting to add QLayout "" to QDialog "", which already
| has a layout
This shuts that up, but doesn't fix the broken save file selection
so I haven't added a fixes37.0 entry.
handle preselected item in pick-one menu; picking it returns that
item rather than toggling it off and returning nothing, picking
something else only returns the other thing (was returning first
of the chosen item or the preselected item, foiling core's attempt
to deal with both and giving wrong result whenever the preselected
one came first--like pick-an-attribute for menu colors);
when handling typed input, check selector letters before menu
command keys so that special "letters" '-' (fingers, hands, self)
and ':' (look inside container) that are specified by a few menus
can be chosen by keyboard;
menus were using default line heights which are excessively tall,
effectively making them be double spaced and using more screen
space than should have been needed; reduce height to 60% of what
it was, still a bit taller than regular spacing; look at ^X--which
is rendered via menu--before and after to see the difference;
start with count column empty instead of 6 spaces; grow it as counts
get entered; reset to empty if [all], [none], or [invert] is used;
treat intermediate counts as long rather than int; right justify
formatted count values;
simplify creating menu return data (pick-one doesn't need separate
handling);
for pick-one menus,
enable [ok] button if there is one preselected item,
enable [all] button if there is only one item (may never happen),
enable [none] if there is a preselected item (menu remains active
if [none] is used to clear the preselection);
enable [invert] if there is one item (may never happen; should
allow two items if one of them is preselected--definitely does
happen--but that wouldn't work as intended without code changes);
honor pending count if an item is selected by clicking its checkbox
(already done for typing its letter or for clicking another part
of item's menu line);
accept <delete>/<rubout> in addition to <backspace> when backing out
a digit as a count is being typed;
accept ^[ as well as ESC key for cancelling count or entire menu;
honor 'menucolors'=false to ignore any defined menu color patterns.
Record a bunch of Qt stuff before I forget it all. It's probably
too late: I'll bet I've left some things out.
Doesn't include several menu problems that I've already fixed but
not checked in yet. (I don't have any other Qt changes pending.)
Qt's map hadn't been updated to draw unexplored locations with
the unexplored glyph so was still using solid stone instead.
Column 0 should be removed but I'll leave that for someone more
adventurous; I did it for curses and for X11 but am going to
pass here. It's very noticable after magic mapping but is only
"bad" (by wasting space) if clipping is being performed.
Enable existing wc_popup_dialog option. Use it in yn_function()
instead using a mystery value which apparently used to live in Qt
Settings but isn't there anymore so couldn't be turned on or off.
Also replaces conditional USE_POPUPS which isn't defined anywhere
either so presumably came from CFLAGS and only supported "yn?",
"ynq?", and "rl?" with hardcoded Qt popups rather than using
NetHackQtYnDialog.
Doing that revealed that the popup dialog for ynaq was in pretty
bad shape. It's functional but still needs a lot of work, beyond
the limited Qt/C++ capability I possess. The KeyPress issue which
accepts <shift> as input, thereby preventing <shift>+<character>
from being typed during ynaq prompting, is particularly nasty.
Append the ynaq dialog's response to the message line containing
the corresponding prompt similar to what's now done for regular
yn_function().
Add getlin() prompt+response to the message window.
The Qt interface highlights the last message issued (using a
mechanism for selection, as if for copy+paste or similar operation)
but it was staying highlighted until another message was eventually
given. Having an old message seem to stick around is annoying and
is particularly bad when the message is a prompt. If the player's
answer doesn't cause a message to be shown then it seems as if the
prompt is still pending.
This removes the highlighting (by bulk unselecting) once the player
gives another input keystroke or mouse click.
It would be much better if the selecting/highlighting was for all
messages issued since last time highlighting was cleared. Figuring
out how to do that correctly is more effort than I want to expend.
Make ASCII control characters ^[, ^\, ^], ^^, and ^_ work on Qt,
at least partly. Mainly for ^[ to be treated as ESC, which works
if you're aborting a count on the map but doesn't cancel out of
menus [yet?]. I didn't attempt to make ^@ send NUL.
Also, fix the hardcoded macros (activated by F1: rest 100 turns,
F2: search 20 times, and Tab: ^A to do-again). The first two sent
'n' before the count so wouldn't work as intended with number_pad
off, and the third was executing twice as if Tab sent two ^A's
instead of just one. Resting and searching might have been getting
duplicated too; I don't know how to simulate the relevant keys.
(I temporarily swapped definitions for F2 and Tab to test the
number_pad fix but hadn't done that earlier when I discovered the
Tab bug.)
Menus have [ok], [cancel], [all], [none], [invert], and [search]
buttons across their top but the [all], [none], and [invert] choices
didn't redraw the menu after making changes to the pending selections
so it seemed as if they weren't doing anything. Subsequently picking
[ok] revealed otherwise.
[search] is broken (instead of accepting a search string, the letters
I type are being used to toggle individual entries as I type). This
doesn't attempt to address that.
I was actually using fprintf(stderr,...) when testing and didn't
retry this bit after changing it to raw_printf(...). It's commented
out but needs fixing.
I've been trying to figure out how to make ^[ be treated as ESC but
so far have failed. That key combination just acts like a dead key.
But one bit of cp_key.cpp can be implemented instead of ignored.
No change in behavior because the keyboard-state value isn't being
used anywhere.
Infrastructure bits: Qt tombstone uses a short buffer; make sure that
the plname value fits instead of relying on snprintf() to truncate it.
A warning about gold, if any, was iffy but this should guarantee no
reason for future complaint. Year was safe but a compiler sensitive
to buffer overflows wouldn't know that.
Actual bugs: Qt used money in inventory for gold amount on tombstone;
that overlooks gold in containers and will be 0 by tombstone stage if
bones get saved. Year was recalculated from current date+time instead
of using the value that gets passed in--blindly flagging that variable
as UNUSED was a mistake.
Qt is capable of using an ascii map, and does so on the rogue level.
So failing to load tiles doesn't need to quit; it can continue in
text mode.
Not extensively tested. This disables the paper doll when the ascii
map is forced (either via options settings or due to tiles loading
failure, but not when simply on the rogue level) rather than trying
to display it with object class characters.
When items in the paper doll inventory subset (primary worn and
wielded items) have known BUC state, indicate what that is. It
now draws a one pixel wide white border around each doll tile,
and if BUC is known, that border gets its color changed (red for
known cursed, yellow for known uncursed, cyan for known blessed).
That isn't very visual so the first pixel inside the tile is
overwritten with the same color, and alternating pixels are also
overwritten for the second rectangle within. The 2..3 pixel wide
border is visible without cluttering the tile for 'normal' sized
paper doll. The tiles are allowed to be scrunched down to as
small as 6x6 so there won't be much left after 1 or 2 around the
edge are replaced.
Initially I was going to try to highlight welded items but the
more general BUC highlighting is simpler and usually more useful
to the player.
The qt_map.* bits are just reformatting. I was looking at pet
and pile annotations as a way to do BUC annotations but decided
not to attempt that.
During hallucination, actions which triggered update of persistent
inventory made Qt's display of map tiles for equipped objects have
those tiles switch randomly, but ordinary move-by-move fluctations
applied to floor objects left them alone.
Initially I took out hallucination of inventory items altogether,
but ended up putting that back and changing the floor hallucination
to affect Qt's paper doll too. The display.h change isn't needed
but I've left it in.
Enhance the "Qt Settings" dialog box to provide control over the
paper doll subset of inventory displayed between the message and
status windows (above the map). A ton of flailing about for a
fairly small but useful change in functionality.
Old dialog (no title):
| [ ] Zoomed -- check box
| "Width:" [ ] -- number entry spinner
| "Height:" [ ] -- ditto
| "Font:" [ ] -- Huge:18pt, Large:14, Medium:12, Small:10, Tiny:8
| [ Dismiss ] -- button
New dialog:
| "Qt NetHack Settings"
|
| "Map:" [ ] "Zoomed" -- check box
| "Tile Width" [ ] -- number entry spinner
| "Tile Height" [ ] -- ditto
| "Invent:" [ ] "Shown" -- check box
| "Doll Width" [ ] -- number entry spinner
| "Doll Height" [ ] -- ditto
| "Font:" [ ] -- Huge:18pt, Large:14, Medium:12, Small:10, Tiny:8
| [ Dismiss ] -- button
The inventory subset can now be suppressed. When shown (the default),
its size can be set independently of the map tiles' size. I've set
the default to be 32x32 tiles instead of 16x16 used for the map.
The settings are saved and restored automatically by Qt, and persist
not just across save/restore cycles but into new games. (That's not
a change, just a reminder.)
Move the nine #undef's common to all qt_*.cpp sources into qt_pre.h.
Make "hack.h" usage consistent; always enclose withing 'extern "C {'
and '}' even though only some of the sources care.
The core is mapping #annotate to ^N, which has no effect when
number_pad is Off. The Qt menu setup saw it as the way to run
that command, which will only work when number_pad is On. This
fixes the menu and didn't break the large subset of other menu
commands I've tried, but I haven't gotten through half of them yet.
An earlier tweak worked to prevent unnecessary line wrapping
for ^X output in a menu, but #enhance and '+' both had problems
with their last column. This seems to work better but is still
based on thrashing about rather than knowledge of how things are
supposed to operate.
In case you haven't seen it, the Qt screen layout is (a bigger
instance of):
+--------------------+------+--------------------------------+
| messages |invent| status |
| |subset| |
| | | |
| | | |
+------------------------------------------------------------+
| map |
| |
...
| |
+------------------------------------------------------------+
where some status fields include an icon and the inventory subset is
a miniature map showing a paper doll-style display of object tiles
for worn and wielded items. The two separating lines in the top half
can be dragged to resize the three windows there. The default message
window width to too small to see full text of some messages but can
be scrolled left and right. The window for the equipped subset of
inventory is unconditionally present; 'perm_invent' is a no-op.
Paper doll inventory layout (view with fixed-width font...):
Old New two-hand dual-wield
x H b x H b x H b . H b
S " w S " w W " W X " w
G C G G C q G C q G C q
= A = = A = = A = = A =
. U . l U L l U L l U L
. F . . F . . F . . F .
Legend:
'.' = blank, b = blindfold, '"' = amulet, '=' = left and right rings,
w/W = primary weapon, x/X = alternate/secondary weapon, q = quiver,
H = helmet, S = shield, G = gloves, C = cloak, A = suit, U = shirt,
F = boots, l = leash, L = active light source (lamp/candle/Sunsword).
Slots which don't have something equipped are shown blank.
'q' was missing; 'G' used to be shown on both sides. 'l' and 'L' are
new; for either, it picks the first one in inventory that's in active
use. The 'S' and 'x' slots vary depending upon weapon situation
since wearing a shield, wielding a two-handed weapon, and engaging in
two-weapon combat are all mutually exclusive.
The Qt menu entries which were executing nethack's help command
(the '?' menu) were doing so because their command keystroke was
a meta-character and such characters are being converted to '?'
to indicate an error in conversion to Latin1 character set. The
old Qt3 code didn't perform any such conversion.
This fix feels fragile because there are two different places
deciding how to disambiguate partial extended commands (the code
for Qt's '#' handling and a new routine in the core). Qt menus
now send '#' and enough letters to satisfy '#' handling for any
command which uses M-c or has no regular keystroke nor M-c one.
(If it were to send the full extended command name, the letters
after the unambiguous prefix would be left in the input queue to
be processed as subsequent commands.)
There is a fundamental problem that this doesn't address: if
the player uses BIND directives in the run-time config file, the
Qt menu bindings will break unless the BINDs are all done before
selecting windowtype. Qt's menu bindings translate a click on
a menu entry into the keystroke used to invoke the corresponding
command, so using BIND to change that after the menus are set up
will result in the wrong commands being executed.
Changes affecting everybody (using Qt): rename game->Save to
game->Save-and-exit and game->Quit to game->Quit-without-saving.
OSX-specific changes: add separate nethack->Quit and change
game->Quit-without-saving to game->_Quit-without-saving to prevent
that from being hijacked for the nethack menu. nethack->Quit menu
entry works. Command+Q is a keyboard shortcut for it. They bring
up a menu with choices of "Quit without saving" and "Cancel and
return to game". It's not the same as the handler for the window
Close button, which used to offer "Save" or "Cancel" (with the
latter triggering an infinite loop) but now offers "Save and exit"
or "Quit without saving". They don't share any code. The
game->_Quit-without-saving entry doesn't work; it runs nethack's '?'
command like a bunch of other broken menu entries. If it did work,
it would give nethack's "Really quit?" prompt and proceed from there.
The "Quit without saving" response for nethack->Quit confirmation
bypasses that and just quits.
Also OSX, add a second 'about' entry. The first one is hijacked and
added to the nethack menu, the second is help->_About_Qt_NetHack_
and avoids hijacking. Both nethack->About and help->_About_ bring
up the same dialog box showing version and assorted other info.
A lot of flailing about with for relatively small amount of progress.
In the Qt status panel the six characteristics and the older
status conditions all have icons (similar to map tiles) drawn
above their values. (The 3.6 era conditions that I added all
have blank icons and are in need of artwork. 3.7 conditions
aren't implemented.)
Int, Stun, and Conf all feature a brain oriented towards the
player's right shoulder. The intelligence one is just a bare
brain, the stunned one features a black cloud over it, and the
confusion one has something over it that is cloud-like but
shaped differently from Stun as well has being white rather
than black; I'm not sure what that depicts. This transposes
the Confusion icon so that it faces the player's left shoulder
instead of right. Not a very emphatic suggestion of confusion
but seems a useful difference without requiring any artistic
competence.
Menu hackery: change a couple of menu entry names on OSX to
control where they end up.
Move nethack's 'O' command from its hijacked position (due to name
"Options") of "nethack->Preferences..." to "Game->Run-time options".
Move persistent Qt settings on OSX from "Game->Qt settings" to
"nethack->Preferences...".
The Qt settings dialog (now accessed as Preferences...) desperately
needs a title and/or other explanatory text but I haven't figured
out how do to that. The values set with it are persistent, with
apparently quite a few choices for where to save them for future
runs. I used it to increase the size of text in the status window,
and found my settings stored in binary file
~/Library/Preferences/org.nethack.NetHack.plist
The subdirectories ~/Library and ~/Library/Preferences are
standard OSX per-user things. The file name is derived from values
set up in main routine: qt_main.cpp is setting OrganizationDomain
to "nethack.org" and ApplicationName to "NetHack". I've added a
value for ApplicationVersion but don't know whether anything cares
about it.
Add ^X (as "Attributes (extended status)") to the "Info" drop down
menu, also Overview, and Annotate.
Attributes and Overview work, Annotate results in running southeast.
Existing entries Conduct, Adjust, and Skills execute nethack's '?'
command so I didn't bother holding back on adding Annotate. Other
existing entries (Inventory, Discoveries, Spells, and Name) work.
If there's any sort of pattern involved, I'm not seeing it.
The Game menu has "Save", which shows up and works, but that's
supposed to be followed by "Quit" which doesn't show up when the
menu is used. This doesn't attempt to deal with that.
Command+q keystroke, which should close the application, behaves
the same as previously mentioned "quit nethack" in nethack menu:
runs nethack's '?' command and then resumes play.
Prevent an infinite loop that occurred if player clicked on the
close window button and then tried to cancel out of that in the
dialog it brings up.
I don't know whether Qt interface on platforms other than OSX
need this but they're getting it. The choices are changed from
"Save" or "Cancel" to "Save and exit" or "Quit without saving".
Since save allows subsequent restore, not being able to cancel
out of the application shutdown should only be an inconvenience.
Unresolved issues:
I don't know whether there's any other way to bring up that dialog,
where Cancel might be a viable choice. If so, handling that might
be tricky. Quit should definitely be available as an alterative
to Save, but that type of dialog doesn't seem to allow more than
two choices.
Picking "nethack" from application menu and then "quit nethack"
from the resulting pull down menu results in executing nethack's
help command (the '?' menu) and then just resumes play.
Add Michael's fix for control+x.
The enum name of the argument suggests that option+x should have
been sending control characters but that wasn't the case for me.
Before this fix, both control+x and option+x behaved like dead
keys, not transmitting anything for nethack to use. After this
fix, control+x sends ^X as desired but option+x is still dead.
The presence of longer lines has made the 'about' box become wider
so combine the first two short lines into one longer one.
Switching to the longer nethack version string resulted in "This
is NetHack MacOSX Nethack ..." so remove the initial "NetHack"
from the 'about' box's format string. That version string also
includes a final period; strip that off since "with Qt 5.x.y."
follows it to end the sentence.
Still some issues:
The application menu has first entry "nethack" which ought to be
capitalized but I haven't been able to figure out how to accomplish
that.
Some code in qt_main.cpp tries to add an extra instance of "about
NetHack" to the game window's "Help" menu but it doesn't show up.
Assuming you have the prerequisite packages, You can specify the
window ports to include on the make command line:
make WANT_WIN_QT=1 WANT_WIN_X11=1 WANT_WIN_CURSES=1 WANT_WIN_TTY=1 all
Prequisites for window ports beyond tty:
(some sample homebrew commands to obtain them shown but that is not the
only way):
xquartz for x11 support
brew install xquartz
Qt for Qt support
brew install Qt