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
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
^ ^
I forced a test compile to -std=c++20 mostly to see what we would
be up against. There was only a small number of things and they
are corrected in this commit.
c++20 has some issues with comparisons and bit twiddling between
different enums.
The vendor-supplied Qt5 header files triggered some of those issues as
well, so the qt_pre.h and qt_post.h NetHack header files were adjusted
to make those new warnings go away. I have not tested Qt6 under the
new compiler and c++ version yet.
Because there are multiple pragmas in qt_pre.h now, the conditional
ifdef structure in there was modified a little to make maintenance
simpler and have a single pragma push at the top. The pragma pop
comes after the Qt vendor-supplied header files, and is done
in qt_post.h.
The display.h macro cmap_to_glyph() was used in
a Qt c++ file and triggered a series of warnings because of that.
Rather than write c++20-friendly versions of those macros, the
simple fix is to provide a function on the C side of things
to front the cmap_to_glyph() macro, so fn_cmap_to_glyph()
was added.
Also thrown into this commit, PatR picked up on the fact that for
yesterday's new warning in qt_menu.cpp, the compiler had correctly
picked up on the fact that the format range of the variable 'cash'
had been correctly upper-capped at 999999999L in the warning message
because of an assignment prior. He suggested that perhaps by also adding
if (cash < 0)
cash = 0;
the warning might be eliminated altogether.
After a test, that was proven to be correct, so yesterday's
more-kludgy change is reverted and replaced with that variable
variable restriction ahead of the snprintf().
---------------------
win/curses/cursstat.c:
../win/curses/cursstat.c:301:9: warning: variable 'height' set but not used [-Wunused-but-set-variable]
height, width, w, xtra, clen, x, y, t, ex, ey,
^
1 warning generated.
---------------------
win/Qt/qt_menu.cpp:
../win/Qt/qt_menu.cpp:1123:9: warning: variable 'h' set but not used [-Wunused-but-set-variable]
int h=0;
^
1 warning generated.
---------------------
/win/Qt/qt_yndlg.cpp:
../win/Qt/qt_yndlg.cpp:170:6: warning: variable 'x' set but not used [-Wunused-but-set-variable]
int x=margin, y=extra+margin;
^
../win/Qt/qt_yndlg.cpp:170:16: warning: variable 'y' set but not used [-Wunused-but-set-variable]
int x=margin, y=extra+margin;
^
2 warnings generated.
Commenting out the x and y references, then leads to the following additional warnings,
so comment those out too:
../win/Qt/qt_yndlg.cpp:167:12: warning: unused variable 'margin' [-Wunused-variable]
const int margin=8;
^
../win/Qt/qt_yndlg.cpp:168:12: warning: unused variable 'gutter' [-Wunused-variable]
const int gutter=8;
^
../win/Qt/qt_yndlg.cpp:169:12: warning: unused variable 'extra' [-Wunused-variable]
const int extra=fontMetrics().height(); // Extra for group
^
3 warnings generated.
---------------------
Our C() macro conflicts with Qt6 usage, so #undef C has added. Move
that from nearly every qt_*.cpp into qt_pre.h where other similar
fixups are handled.
Mostly the warnings were about QString::sprintf and QFontMetrics::width.
sprintf replacement is asprintf, which annoyingly behaves differently
from sprintf - it seems to append to the string.
Not thoroughly tested, but seems to work.
../win/Qt/qt_yndlg.cpp: In member function ‘char nethack_qt_::NetHackQtYnDialog::Exec()’:
../win/Qt/qt_yndlg.cpp:80:9: warning: variable ‘ch_per_line’ set but not used [-Wunused-but-set-variable]
80 | int ch_per_line=6;
| ^~~~~~~~~~~
Fix the popup versions of qt_yn_function() to handle control
characters by using the same key press event decoding routine
and menus and extended commands. Moves 'keyValue()' to
qt_key.cpp and its declaration to qt_key.h, requring several
files to start using #include "qt_key.h".
'make depend' update to follow.
Take care of a Qt TODO: when using 'popup_dialog' and entering
a count during a yn#aq question, change the default answer button
from 'n' to 'y' since ending the count with <return> accepts it.
I'm not sure whether any yn_function() calls include ampersand
in the list of acceptable choices but if any did, the button
for that character would have shown up blank. (Clicking on it
would have successfully produced '&' as player's input though.)
When 'popup_dialog' is set, the Qt interface uses a popup window
for yn_function() calls and the dialog has a list of buttons, one
per potential choice. It has been handling "yn?" and "ynq?"
questions differently from general request-one-char prompts, using
buttons "Yes", "No, and "Cancel" instead of showing individual
letters. This extends that to "ynaq" and "yn#aq" questions and
labels 'q' reply as "Stop" instead of "Cancel" for those. Also,
when player uses keyboard instead of mouse to answer, allow 'c'
as well as 'q' for cancel ones, 's' as well as 'q' for stop ones.
Prompt Buttons
yn [Yes ][ No ]
ynq [ Yes ][ No ][Cancel]
ynaq [Yes ][ No ][All ][Stop]
yn#aq [Yes ]Count:______[ No ][All ][Stop]
rl [ Left ][Right ] //unchanged; included for completeness
(For contrast, when something specifies "ny" as the acceptable
choices, the buttons will just be [n][y]. Prompts for choosing
from a list of inventory letters can't accidentally match these
special cases as long as they're specified in alphabetical order.)
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).
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.
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.
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.
In file included from ../win/Qt/qt_bind.cpp:20:
In file included from /usr/local/Cellar/qt/5.15.0/lib/QtGui.framework/Headers/QtGui:3:
In file included from /usr/local/Cellar/qt/5.15.0/lib/QtGui.framework/Headers/QtGuiDepends:3:
In file included from /usr/local/Cellar/qt/5.15.0/lib/QtCore.framework/Headers/QtCore:4:
In file included from /usr/local/Cellar/qt/5.15.0/lib/QtCore.framework/Headers/qglobal.h:1302:
/usr/local/Cellar/qt/5.15.0/lib/QtCore.framework/Headers/qflags.h:121:41: warning: declaration shadows a
variable in the global namespace [-Wshadow]
Q_DECL_CONSTEXPR inline QFlags(Enum flags) noexcept : i(Int(flags)) {}
^
[…]
../include/flag.h:390:29: note: previous declaration is here
extern NEARDATA struct flag flags;
^
In file included from ../win/Qt/qt_click.cpp:18:
In file included from /usr/local/Cellar/qt/5.15.0/lib/QtGui.framework/Headers/QtGui:3:
In file included from /usr/local/Cellar/qt/5.15.0/lib/QtGui.framework/Headers/QtGuiDepends:3:
In file included from /usr/local/Cellar/qt/5.15.0/lib/QtCore.framework/Headers/QtCore:36:
/usr/local/Cellar/qt/5.15.0/lib/QtCore.framework/Headers/qcache.h:191:15: warning: declaration shadows a
variable in the global namespace [-Wshadow]
Node *u = n;
^
../include/decl.h:219:23: note: previous declaration is here
E NEARDATA struct you u;
^
[…]
In file included from ../win/Qt/qt_click.cpp:18:
In file included from /usr/local/Cellar/qt/5.15.0/lib/QtGui.framework/Headers/QtGui:5:
In file included from /usr/local/Cellar/qt/5.15.0/lib/QtGui.framework/Headers/qabstracttextdocumentlayout.h:45:
In file included from /usr/local/Cellar/qt/5.15.0/lib/QtGui.framework/Headers/qtextlayout.h:47:
In file included from /usr/local/Cellar/qt/5.15.0/lib/QtGui.framework/Headers/qcolor.h:44:
/usr/local/Cellar/qt/5.15.0/lib/QtGui.framework/Headers/qrgb.h:66:46: warning: declaration shadows a
variable in the global namespace [-Wshadow]
inline Q_DECL_CONSTEXPR QRgb qRgb(int r, int g, int b)// set RGB value
^
../include/decl.h:1208:27: note: previous declaration is here
E struct instance_globals g;
^
[…]
In file included from ../win/Qt/qt_glyph.cpp:21:
In file included from /usr/local/Cellar/qt/5.15.0/lib/QtGui.framework/Headers/QtGui:5:
In file included from /usr/local/Cellar/qt/5.15.0/lib/QtGui.framework/Headers/qabstracttextdocumentlayout.h:48:
/usr/local/Cellar/qt/5.15.0/lib/QtGui.framework/Headers/qpalette.h:107:49: warning: declaration shadows a
variable in the global namespace [-Wshadow]
inline void setCurrentColorGroup(ColorGroup cg) { data.current_group = cg; }
^
../include/decl.h:1216:30: note: previous declaration is here
E const struct const_globals cg;
^