Add Qt4 windowport

Originally by Ray Chason for 3.4.3, based on the Qt windowport by
Warwick Allison. The look and feel is mostly the same.

Some improvements over the Qt 3 interface are:

* Panes are resizable
* Full support for IBMgraphics, and walls and corridors are drawn with
  graphical primitives for a continuous appearance no matter what the font
  says
* Lots of irritating glitches fixed
* Menus support proportional fonts correctly

Adding this because the old Qt windowport cannot be compiled on Qt4,
even with Qt3 compatibility stuff.

TODO:
 - background map glyphs
 - status hilites
 - menucolors
This commit is contained in:
Pasi Kallinen
2017-10-08 01:15:02 +03:00
parent a4706b0928
commit ed335dd0a7
52 changed files with 8024 additions and 9 deletions
+1
View File
@@ -718,6 +718,7 @@ Ray Chason's proper background tiles for lava and water
Ray Chason's MS-DOS port restored to functionality with credit to Reddit user Ray Chason's MS-DOS port restored to functionality with credit to Reddit user
b_helyer for the fix to sys/share/pcmain.c b_helyer for the fix to sys/share/pcmain.c
Ray Chason's MSDOS port support for some VESA modes Ray Chason's MSDOS port support for some VESA modes
Ray Chason's Qt4 windowport
Darshan Shaligram's pet ranged attack Darshan Shaligram's pet ranged attack
Jason Dorje Short's key rebinding Jason Dorje Short's key rebinding
Maxime Bacoux's new DUMPLOG: compile-time option to enable logging of Maxime Bacoux's new DUMPLOG: compile-time option to enable logging of
+3
View File
@@ -168,6 +168,9 @@ E boolean NDECL(status_hilite_menu);
/* ### cmd.c ### */ /* ### cmd.c ### */
E int NDECL(doconduct);
E int NDECL(domonability);
E char FDECL(cmd_from_func, (int NDECL((*))));
E boolean FDECL(redraw_cmd, (CHAR_P)); E boolean FDECL(redraw_cmd, (CHAR_P));
#ifdef USE_TRAMPOLI #ifdef USE_TRAMPOLI
E int NDECL(doextcmd); E int NDECL(doextcmd);
+3 -6
View File
@@ -117,7 +117,6 @@ static int NDECL((*timed_occ_fn));
STATIC_PTR int NDECL(doprev_message); STATIC_PTR int NDECL(doprev_message);
STATIC_PTR int NDECL(timed_occupation); STATIC_PTR int NDECL(timed_occupation);
STATIC_PTR int NDECL(doextcmd); STATIC_PTR int NDECL(doextcmd);
STATIC_PTR int NDECL(domonability);
STATIC_PTR int NDECL(dotravel); STATIC_PTR int NDECL(dotravel);
STATIC_PTR int NDECL(doterrain); STATIC_PTR int NDECL(doterrain);
STATIC_PTR int NDECL(wiz_wish); STATIC_PTR int NDECL(wiz_wish);
@@ -164,9 +163,7 @@ STATIC_DCL boolean FDECL(accept_menu_prefix, (int NDECL((*))));
STATIC_DCL int NDECL(wiz_port_debug); STATIC_DCL int NDECL(wiz_port_debug);
#endif #endif
STATIC_PTR int NDECL(wiz_rumor_check); STATIC_PTR int NDECL(wiz_rumor_check);
STATIC_DCL char FDECL(cmd_from_func, (int NDECL((*))));
STATIC_PTR int NDECL(doattributes); STATIC_PTR int NDECL(doattributes);
STATIC_PTR int NDECL(doconduct); /**/
STATIC_DCL void FDECL(enlght_line, (const char *, const char *, const char *, STATIC_DCL void FDECL(enlght_line, (const char *, const char *, const char *,
const char *)); const char *));
@@ -523,7 +520,7 @@ extcmd_via_menu()
#endif /* TTY_GRAPHICS */ #endif /* TTY_GRAPHICS */
/* #monster command - use special monster ability while polymorphed */ /* #monster command - use special monster ability while polymorphed */
STATIC_PTR int int
domonability(VOID_ARGS) domonability(VOID_ARGS)
{ {
if (can_breathe(youmonst.data)) if (can_breathe(youmonst.data))
@@ -2734,7 +2731,7 @@ int msgflag; /* for variant message phrasing */
/* KMH, #conduct /* KMH, #conduct
* (shares enlightenment's tense handling) * (shares enlightenment's tense handling)
*/ */
STATIC_PTR int int
doconduct(VOID_ARGS) doconduct(VOID_ARGS)
{ {
show_conduct(0); show_conduct(0);
@@ -3283,7 +3280,7 @@ dokeylist(VOID_ARGS)
destroy_nhwindow(datawin); destroy_nhwindow(datawin);
} }
STATIC_OVL char char
cmd_from_func(fn) cmd_from_func(fn)
int NDECL((*fn)); int NDECL((*fn));
{ {
+90 -3
View File
@@ -201,6 +201,22 @@ WINX11OBJ = Window.o dialogs.o winX.o winmap.o winmenu.o winmesg.o \
WINQTSRC = ../win/Qt/qt_win.cpp ../win/Qt/qt_clust.cpp ../win/Qt/qttableview.cpp WINQTSRC = ../win/Qt/qt_win.cpp ../win/Qt/qt_clust.cpp ../win/Qt/qttableview.cpp
WINQTOBJ = qt_win.o qt_clust.o qttableview.o tile.o WINQTOBJ = qt_win.o qt_clust.o qttableview.o tile.o
# #
# Files for a Qt 4 or 5 port
#
WINQT4SRC = ../win/Qt4/qt4bind.cpp ../win/Qt4/qt4click.cpp \
../win/Qt4/qt4clust.cpp ../win/Qt4/qt4delay.cpp \
../win/Qt4/qt4glyph.cpp ../win/Qt4/qt4icon.cpp ../win/Qt4/qt4inv.cpp \
../win/Qt4/qt4key.cpp ../win/Qt4/qt4line.cpp ../win/Qt4/qt4main.cpp \
../win/Qt4/qt4map.cpp ../win/Qt4/qt4menu.cpp ../win/Qt4/qt4msg.cpp \
../win/Qt4/qt4plsel.cpp ../win/Qt4/qt4rip.cpp ../win/Qt4/qt4set.cpp \
../win/Qt4/qt4stat.cpp ../win/Qt4/qt4str.cpp ../win/Qt4/qt4streq.cpp \
../win/Qt4/qt4svsel.cpp ../win/Qt4/qt4win.cpp ../win/Qt4/qt4xcmd.cpp \
../win/Qt4/qt4yndlg.cpp
WINQT4OBJ = qt4bind.o qt4click.o qt4clust.o qt4delay.o qt4glyph.o qt4icon.o \
qt4inv.o qt4key.o qt4line.o qt4main.o qt4map.o qt4menu.o qt4msg.o \
qt4plsel.o qt4rip.o qt4set.o qt4stat.o qt4str.o qt4streq.o qt4svsel.o \
qt4win.o qt4xcmd.o qt4yndlg.o tile.o
#
# Files for a Gnome port # Files for a Gnome port
# #
WINGNOMESRC = ../win/gnome/gnaskstr.c ../win/gnome/gnbind.c \ WINGNOMESRC = ../win/gnome/gnaskstr.c ../win/gnome/gnbind.c \
@@ -253,9 +269,12 @@ WINX11LIB = -lXaw -lXmu -lXext -lXt -lX11
# WINX11LIB = -lXaw -lXmu -lXext -lXt -lXpm -lX11 -lm # WINX11LIB = -lXaw -lXmu -lXext -lXt -lXpm -lX11 -lm
# WINX11LIB = -lXaw -lXmu -lXpm -lXext -lXt -lX11 -lSM -lICE -lm # BSD/OS 2.0 # WINX11LIB = -lXaw -lXmu -lXpm -lXext -lXt -lX11 -lSM -lICE -lm # BSD/OS 2.0
# #
# libraries for Qt # libraries for Qt 3
WINQTLIB = -L$(QTDIR)/lib -lqt WINQTLIB = -L$(QTDIR)/lib -lqt
# #
# libraries for Qt 4
WINQT4LIB = `pkg-config QtGui --libs`
#
# libraries for KDE (with Qt) # libraries for KDE (with Qt)
WINKDELIB = -lkdecore -lkdeui -lXext WINKDELIB = -lkdecore -lkdeui -lXext
# #
@@ -360,7 +379,7 @@ GENCSRC = monstr.c vis_tab.c #tile.c
# all windowing-system-dependent .c (for dependencies and such) # all windowing-system-dependent .c (for dependencies and such)
WINCSRC = $(WINTTYSRC) $(WINX11SRC) $(WINGNOMESRC) $(WINGEMSRC) WINCSRC = $(WINTTYSRC) $(WINX11SRC) $(WINGNOMESRC) $(WINGEMSRC)
# all windowing-system-dependent .cpp (for dependencies and such) # all windowing-system-dependent .cpp (for dependencies and such)
WINCXXSRC = $(WINQTSRC) $(WINBESRC) WINCXXSRC = $(WINQTSRC) $(WINQT4SRC) $(WINBESRC)
# Files for window system chaining. Requires SYSCF; include via HINTSRC/HINTOBJ # Files for window system chaining. Requires SYSCF; include via HINTSRC/HINTOBJ
CHAINSRC = ../win/chain/wc_chainin.c ../win/chain/wc_chainout.c \ CHAINSRC = ../win/chain/wc_chainin.c ../win/chain/wc_chainout.c \
@@ -486,7 +505,7 @@ objects.o:
$(CC) $(CFLAGS) -c objects.c $(CC) $(CFLAGS) -c objects.c
@rm -f $(MAKEDEFS) @rm -f $(MAKEDEFS)
# Qt windowport meta-object-compiler output # Qt 3 windowport meta-object-compiler output
qt_kde0.moc: ../include/qt_kde0.h qt_kde0.moc: ../include/qt_kde0.h
$(QTDIR)/bin/moc -o qt_kde0.moc ../include/qt_kde0.h $(QTDIR)/bin/moc -o qt_kde0.moc ../include/qt_kde0.h
@@ -496,6 +515,28 @@ qt_win.moc: ../include/qt_win.h
qttableview.moc: ../include/qttableview.h qttableview.moc: ../include/qttableview.h
$(QTDIR)/bin/moc -o qttableview.moc ../include/qttableview.h $(QTDIR)/bin/moc -o qttableview.moc ../include/qttableview.h
# Qt 4 windowport meta-object-compiler output
qt4kde0.moc : ../win/Qt4/qt4kde0.h
$(QTDIR)/bin/moc -o qt4kde0.moc ../win/Qt4/qt4kde0.h
qt4main.moc : ../win/Qt4/qt4main.h
$(QTDIR)/bin/moc -o qt4main.moc ../win/Qt4/qt4main.h
qt4map.moc : ../win/Qt4/qt4map.h
$(QTDIR)/bin/moc -o qt4map.moc ../win/Qt4/qt4map.h
qt4menu.moc : ../win/Qt4/qt4menu.h
$(QTDIR)/bin/moc -o qt4menu.moc ../win/Qt4/qt4menu.h
qt4msg.moc : ../win/Qt4/qt4msg.h
$(QTDIR)/bin/moc -o qt4msg.moc ../win/Qt4/qt4msg.h
qt4plsel.moc : ../win/Qt4/qt4plsel.h
$(QTDIR)/bin/moc -o qt4plsel.moc ../win/Qt4/qt4plsel.h
qt4set.moc : ../win/Qt4/qt4set.h
$(QTDIR)/bin/moc -o qt4set.moc ../win/Qt4/qt4set.h
qt4stat.moc : ../win/Qt4/qt4stat.h
$(QTDIR)/bin/moc -o qt4stat.moc ../win/Qt4/qt4stat.h
qt4xcmd.moc : ../win/Qt4/qt4xcmd.h
$(QTDIR)/bin/moc -o qt4xcmd.moc ../win/Qt4/qt4xcmd.h
qt4yndlg.moc : ../win/Qt4/qt4yndlg.h
$(QTDIR)/bin/moc -o qt4yndlg.moc ../win/Qt4/qt4yndlg.h
# build monst.o and objects.o before executing '$(MAKE) makedefs' # build monst.o and objects.o before executing '$(MAKE) makedefs'
$(MAKEDEFS): $(FIRSTOBJ) \ $(MAKEDEFS): $(FIRSTOBJ) \
../util/makedefs.c $(CONFIG_H) ../include/permonst.h \ ../util/makedefs.c $(CONFIG_H) ../include/permonst.h \
@@ -737,6 +778,52 @@ qt_clust.o: ../win/Qt/qt_clust.cpp ../include/qt_clust.h
$(CXX) $(CXXFLAGS) -c ../win/Qt/qt_clust.cpp $(CXX) $(CXXFLAGS) -c ../win/Qt/qt_clust.cpp
qttableview.o: ../win/Qt/qttableview.cpp ../include/qttableview.h qttableview.o: ../win/Qt/qttableview.cpp ../include/qttableview.h
$(CXX) $(CXXFLAGS) -c ../win/Qt/qttableview.cpp $(CXX) $(CXXFLAGS) -c ../win/Qt/qttableview.cpp
qt4bind.o : ../win/Qt4/qt4bind.cpp $(HACK_H) ../win/Qt4/qt4bind.h
$(CXX) $(CXXFLAGS) -c ../win/Qt4/qt4bind.cpp
qt4click.o : ../win/Qt4/qt4click.cpp $(HACK_H) ../win/Qt4/qt4click.h
$(CXX) $(CXXFLAGS) -c ../win/Qt4/qt4click.cpp
qt4clust.o : ../win/Qt4/qt4clust.cpp $(HACK_H) ../win/Qt4/qt4clust.h
$(CXX) $(CXXFLAGS) -c ../win/Qt4/qt4clust.cpp
qt4delay.o : ../win/Qt4/qt4delay.cpp $(HACK_H) ../win/Qt4/qt4delay.h
$(CXX) $(CXXFLAGS) -c ../win/Qt4/qt4delay.cpp
qt4glyph.o : ../win/Qt4/qt4glyph.cpp $(HACK_H) ../win/Qt4/qt4glyph.h
$(CXX) $(CXXFLAGS) -c ../win/Qt4/qt4glyph.cpp
qt4icon.o : ../win/Qt4/qt4icon.cpp $(HACK_H) ../win/Qt4/qt4icon.h
$(CXX) $(CXXFLAGS) -c ../win/Qt4/qt4icon.cpp
qt4inv.o : ../win/Qt4/qt4inv.cpp $(HACK_H) ../win/Qt4/qt4inv.h
$(CXX) $(CXXFLAGS) -c ../win/Qt4/qt4inv.cpp
qt4key.o : ../win/Qt4/qt4key.cpp $(HACK_H) ../win/Qt4/qt4key.h
$(CXX) $(CXXFLAGS) -c ../win/Qt4/qt4key.cpp
qt4line.o : ../win/Qt4/qt4line.cpp $(HACK_H) ../win/Qt4/qt4line.h
$(CXX) $(CXXFLAGS) -c ../win/Qt4/qt4line.cpp
qt4main.o : ../win/Qt4/qt4main.cpp $(HACK_H) qt4main.moc ../win/Qt4/qt4main.h qt4kde0.moc
$(CXX) $(CXXFLAGS) -c ../win/Qt4/qt4main.cpp
qt4map.o : ../win/Qt4/qt4map.cpp $(HACK_H) qt4map.moc ../win/Qt4/qt4map.h
$(CXX) $(CXXFLAGS) -c ../win/Qt4/qt4map.cpp
qt4menu.o : ../win/Qt4/qt4menu.cpp $(HACK_H) qt4menu.moc ../win/Qt4/qt4menu.h
$(CXX) $(CXXFLAGS) -c ../win/Qt4/qt4menu.cpp
qt4msg.o : ../win/Qt4/qt4msg.cpp $(HACK_H) qt4msg.moc ../win/Qt4/qt4msg.h
$(CXX) $(CXXFLAGS) -c ../win/Qt4/qt4msg.cpp
qt4plsel.o : ../win/Qt4/qt4plsel.cpp $(HACK_H) qt4plsel.moc ../win/Qt4/qt4plsel.h
$(CXX) $(CXXFLAGS) -c ../win/Qt4/qt4plsel.cpp
qt4rip.o : ../win/Qt4/qt4rip.cpp $(HACK_H) ../win/Qt4/qt4rip.h
$(CXX) $(CXXFLAGS) -c ../win/Qt4/qt4rip.cpp
qt4set.o : ../win/Qt4/qt4set.cpp $(HACK_H) qt4set.moc ../win/Qt4/qt4set.h
$(CXX) $(CXXFLAGS) -c ../win/Qt4/qt4set.cpp
qt4stat.o : ../win/Qt4/qt4stat.cpp $(HACK_H) qt4stat.moc ../win/Qt4/qt4stat.h
$(CXX) $(CXXFLAGS) -c ../win/Qt4/qt4stat.cpp
qt4str.o : ../win/Qt4/qt4str.cpp ../win/Qt4/qt4str.h
$(CXX) $(CXXFLAGS) -c ../win/Qt4/qt4str.cpp
qt4streq.o : ../win/Qt4/qt4streq.cpp $(HACK_H) ../win/Qt4/qt4streq.h
$(CXX) $(CXXFLAGS) -c ../win/Qt4/qt4streq.cpp
qt4svsel.o : ../win/Qt4/qt4svsel.cpp $(HACK_H) ../win/Qt4/qt4svsel.h
$(CXX) $(CXXFLAGS) -c ../win/Qt4/qt4svsel.cpp
qt4win.o : ../win/Qt4/qt4win.cpp $(HACK_H) ../win/Qt4/qt4win.h
$(CXX) $(CXXFLAGS) -c ../win/Qt4/qt4win.cpp
qt4xcmd.o : ../win/Qt4/qt4xcmd.cpp $(HACK_H) qt4xcmd.moc ../win/Qt4/qt4xcmd.h
$(CXX) $(CXXFLAGS) -c ../win/Qt4/qt4xcmd.cpp
qt4yndlg.o : ../win/Qt4/qt4yndlg.cpp $(HACK_H) qt4yndlg.moc ../win/Qt4/qt4yndlg.h
$(CXX) $(CXXFLAGS) -c ../win/Qt4/qt4yndlg.cpp
wc_chainin.o: ../win/chain/wc_chainin.c $(HACK_H) wc_chainin.o: ../win/chain/wc_chainin.c $(HACK_H)
$(CC) $(CFLAGS) -c ../win/chain/wc_chainin.c $(CC) $(CFLAGS) -c ../win/chain/wc_chainin.c
wc_chainout.o: ../win/chain/wc_chainout.c $(HACK_H) wc_chainout.o: ../win/chain/wc_chainout.c $(HACK_H)
+47
View File
@@ -0,0 +1,47 @@
#
# NetHack 3.6 linux-x11 $NHDT-Date: 1432512814 2015/05/25 00:13:34 $ $NHDT-Branch: master $:$NHDT-Revision: 1.12 $
# Copyright (c) Kenneth Lorber, Kensington, Maryland, 2007.
# NetHack may be freely redistributed. See license for details.
#
#-PRE
# Linux hints file
# This hints file provides a single-user Qt4 build for Linux, specifically
# for Ubuntu dapper.
#PREFIX=/usr
PREFIX=$(wildcard ~)/nh/install
HACKDIR=$(PREFIX)/games/lib/$(GAME)dir
SHELLDIR = $(PREFIX)/games
INSTDIR=$(HACKDIR)
VARDIR = $(HACKDIR)
POSTINSTALL= cp -n sys/unix/sysconf $(INSTDIR)/sysconf; $(CHOWN) $(GAMEUID) $(INSTDIR)/sysconf; $(CHGRP) $(GAMEGRP) $(INSTDIR)/sysconf; chmod $(VARFILEPERM) $(INSTDIR)/sysconf;
POSTINSTALL+= bdftopcf win/X11/nh10.bdf > $(INSTDIR)/nh10.pcf; (cd $(INSTDIR); mkfontdir);
CFLAGS=-O -I../include -DNOTPARMDECL
CFLAGS+=-DHACKDIR=\"$(HACKDIR)\"
CFLAGS+=-DSYSCF -DSYSCF_FILE=\"$(HACKDIR)/sysconf\"
CFLAGS+=-DCOMPRESS=\"/bin/gzip\" -DCOMPRESS_EXTENSION=\".gz\"
CFLAGS+=-DQT_GRAPHICS -DDEFAULT_WINDOW_SYS=\"Qt\" -DNOTTYGRAPHICS
CFLAGS+=`pkg-config QtGui --cflags`
LINK=g++
CXX=g++
WINSRC = $(WINQT4SRC)
WINOBJ = $(WINQT4OBJ)
WINLIB = $(WINQT4LIB)
VARDATND = nhtiles.bmp rip.xpm nhsplash.xpm pet_mark.xbm pilemark.xbm
QTDIR=/usr
CHOWN=true
CHGRP=true
VARDIRPERM = 0755
VARFILEPERM = 0600
GAMEPERM = 0755
# note: needs libxt-dev libxaw7-dev libx11-dev bdftopcf
+745
View File
@@ -0,0 +1,745 @@
// Copyright (c) Warwick Allison, 1999.
// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
// NetHack may be freely redistributed. See license for details.
// qt4bind.cpp -- bindings between the Qt 4 interface and the main code
extern "C" {
#include "hack.h"
}
#undef Invisible
#undef Warning
#undef index
#undef msleep
#undef rindex
#undef wizard
#undef yn
#undef min
#undef max
#include <QtGui/QtGui>
#if QT_VERSION >= 0x050000
#include <QtWidgets/QtWidgets>
#include <QtMultimedia/QSound>
#else
#include <QtGui/QSound>
#endif
#include "qt4bind.h"
#include "qt4click.h"
#include "qt4delay.h"
#include "qt4xcmd.h"
#include "qt4key.h"
#include "qt4map.h"
#include "qt4menu.h"
#include "qt4msg.h"
#include "qt4plsel.h"
#include "qt4svsel.h"
#include "qt4set.h"
#include "qt4stat.h"
#include "qt4streq.h"
#include "qt4yndlg.h"
#include "qt4str.h"
extern "C" {
#include "dlb.h"
}
// temporary
extern int qt_compact_mode;
// end temporary
namespace nethack_qt4 {
// XXX Should be from Options
//
// XXX Hmm. Tricky part is that perhaps some macros should only be active
// XXX when a key is about to be gotten. For example, the user could
// XXX define "-" to do "E-yyyyyyyy\r", but would still need "-" for
// XXX other purposes. Maybe just too bad.
//
static struct key_macro_rec {
int key;
int state;
const char* macro;
} key_macro[]={
{ Qt::Key_F1, 0, "n100." }, // Rest (x100)
{ Qt::Key_F2, 0, "n20s" }, // Search (x20)
{ Qt::Key_Tab, 0, "\001" },
{ 0, 0, 0 }
};
NetHackQtBind::NetHackQtBind(int& argc, char** argv) :
#ifdef KDE
KApplication(argc,argv)
#elif defined(QWS) // not quite the right condition
QPEApplication(argc,argv)
#else
QApplication(argc,argv)
#endif
{
QPixmap pm("nhsplash.xpm");
if ( iflags.wc_splash_screen && !pm.isNull() ) {
splash = new QFrame(NULL,
Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint | Qt::WindowStaysOnTopHint );
QVBoxLayout *vb = new QVBoxLayout(splash);
QLabel *lsplash = new QLabel(splash);
vb->addWidget(lsplash);
lsplash->setAlignment(Qt::AlignCenter);
lsplash->setPixmap(pm);
QLabel* capt = new QLabel("Loading...",splash);
vb->addWidget(capt);
capt->setAlignment(Qt::AlignCenter);
if ( !pm.isNull() ) {
lsplash->setFixedSize(pm.size());
lsplash->setMask(pm);
}
splash->move((QApplication::desktop()->width()-pm.width())/2,
(QApplication::desktop()->height()-pm.height())/2);
//splash->setGeometry(0,0,100,100);
if ( qt_compact_mode ) {
splash->showMaximized();
} else {
splash->setFrameStyle(QFrame::WinPanel|QFrame::Raised);
splash->setLineWidth(10);
splash->adjustSize();
splash->show();
}
// force content refresh outside event loop
splash->repaint();
lsplash->repaint();
capt->repaint();
qApp->flush();
} else {
splash = 0;
}
main = new NetHackQtMainWindow(keybuffer);
connect(qApp, SIGNAL(lastWindowClosed()), qApp, SLOT(quit()));
qt_settings=new NetHackQtSettings(main->width(),main->height());
}
void NetHackQtBind::qt_init_nhwindows(int* argc, char** argv)
{
iflags.menu_tab_sep = true;
#ifdef UNIX
// Userid control
//
// Michael Hohmuth <hohmuth@inf.tu-dresden.de>...
//
// As the game runs setuid games, it must seteuid(getuid()) before
// calling XOpenDisplay(), and reset the euid afterwards.
// Otherwise, it can't read the $HOME/.Xauthority file and whines about
// not being able to open the X display (if a magic-cookie
// authorization mechanism is being used).
uid_t gamesuid=geteuid();
seteuid(getuid());
#endif
QApplication::setColorSpec(ManyColor);
instance=new NetHackQtBind(*argc,argv);
#ifdef UNIX
seteuid(gamesuid);
#endif
#ifdef _WS_WIN_
// This nethack engine feature should be moved into windowport API
nt_kbhit = NetHackQtBind::qt_kbhit;
#endif
}
int NetHackQtBind::qt_kbhit()
{
return !keybuffer.Empty();
}
static bool have_asked = false;
void NetHackQtBind::qt_player_selection()
{
if ( !have_asked )
qt_askname();
}
void NetHackQtBind::qt_askname()
{
have_asked = true;
// We do it all here, and nothing in askname
char** saved = get_saved_games();
int ch = -1;
if ( saved && *saved ) {
if ( splash ) splash->hide();
NetHackQtSavedGameSelector sgsel((const char**)saved);
ch = sgsel.choose();
if ( ch >= 0 )
str_copy(plname, saved[ch], SIZE(plname));
}
free_saved_games(saved);
switch (ch) {
case -1:
if ( splash ) splash->hide();
if (NetHackQtPlayerSelector(keybuffer).Choose())
return;
case -2:
break;
default:
return;
}
// Quit
clearlocks();
qt_exit_nhwindows(0);
nh_terminate(0);
}
void NetHackQtBind::qt_get_nh_event()
{
}
#if defined(QWS)
// Kludge to access lastWindowClosed() signal.
class TApp : public QApplication {
public:
TApp(int& c, char**v) : QApplication(c,v) {}
void lwc() { emit lastWindowClosed(); }
};
#endif
void NetHackQtBind::qt_exit_nhwindows(const char *)
{
#if defined(QWS)
// Avoids bug in SHARP SL5500
((TApp*)qApp)->lwc();
qApp->quit();
#endif
delete instance; // ie. qApp
}
void NetHackQtBind::qt_suspend_nhwindows(const char *)
{
}
void NetHackQtBind::qt_resume_nhwindows()
{
}
static QVector<NetHackQtWindow*> id_to_window;
winid NetHackQtBind::qt_create_nhwindow(int type)
{
winid id;
for (id = 0; id < (winid) id_to_window.size(); id++) {
if ( !id_to_window[(int)id] )
break;
}
if ( id == (winid) id_to_window.size() )
id_to_window.resize(id+1);
NetHackQtWindow* window=0;
switch (type) {
case NHW_MAP: {
NetHackQtMapWindow2* w=new NetHackQtMapWindow2(clickbuffer);
main->AddMapWindow(w);
window=w;
} break; case NHW_MESSAGE: {
NetHackQtMessageWindow* w=new NetHackQtMessageWindow;
main->AddMessageWindow(w);
window=w;
} break; case NHW_STATUS: {
NetHackQtStatusWindow* w=new NetHackQtStatusWindow;
main->AddStatusWindow(w);
window=w;
} break; case NHW_MENU:
window=new NetHackQtMenuOrTextWindow(mainWidget());
break; case NHW_TEXT:
window=new NetHackQtTextWindow(mainWidget());
}
window->nhid = id;
// Note: use of isHidden does not work with Qt 2.1
if ( splash
#if QT_VERSION >= 300
&& !main->isHidden()
#else
&& main->isVisible()
#endif
)
{
delete splash;
splash = 0;
}
id_to_window[(int)id] = window;
return id;
}
void NetHackQtBind::qt_clear_nhwindow(winid wid)
{
NetHackQtWindow* window=id_to_window[(int)wid];
window->Clear();
}
void NetHackQtBind::qt_display_nhwindow(winid wid, BOOLEAN_P block)
{
NetHackQtWindow* window=id_to_window[(int)wid];
window->Display(block);
}
void NetHackQtBind::qt_destroy_nhwindow(winid wid)
{
NetHackQtWindow* window=id_to_window[(int)wid];
main->RemoveWindow(window);
if (window->Destroy())
delete window;
id_to_window[(int)wid] = 0;
}
void NetHackQtBind::qt_curs(winid wid, int x, int y)
{
NetHackQtWindow* window=id_to_window[(int)wid];
window->CursorTo(x,y);
}
void NetHackQtBind::qt_putstr(winid wid, int attr, const char *text)
{
NetHackQtWindow* window=id_to_window[(int)wid];
window->PutStr(attr,QString::fromLatin1(text));
}
void NetHackQtBind::qt_putstr(winid wid, int attr, const std::string& text)
{
NetHackQtWindow* window=id_to_window[(int)wid];
window->PutStr(attr,QString::fromLatin1(text.c_str(), text.size()));
}
void NetHackQtBind::qt_putstr(winid wid, int attr, const QString& text)
{
NetHackQtWindow* window=id_to_window[(int)wid];
window->PutStr(attr,text);
}
void NetHackQtBind::qt_display_file(const char *filename, BOOLEAN_P must_exist)
{
NetHackQtTextWindow* window=new NetHackQtTextWindow(mainWidget());
bool complain = false;
{
dlb *f;
char buf[BUFSZ];
char *cr;
window->Clear();
f = dlb_fopen(filename, "r");
if (!f) {
complain = must_exist;
} else {
while (dlb_fgets(buf, BUFSZ, f)) {
if ((cr = index(buf, '\n')) != 0) *cr = 0;
#ifdef MSDOS
if ((cr = index(buf, '\r')) != 0) *cr = 0;
#endif
window->PutStr(ATR_NONE, tabexpand(buf));
}
window->Display(false);
(void) dlb_fclose(f);
}
}
if (complain) {
QString message;
message.sprintf("File not found: %s\n",filename);
QMessageBox::warning(NULL, "File Error", message, QMessageBox::Ignore);
}
}
void NetHackQtBind::qt_start_menu(winid wid)
{
NetHackQtWindow* window=id_to_window[(int)wid];
window->StartMenu();
}
void NetHackQtBind::qt_add_menu(winid wid, int glyph,
const ANY_P * identifier, CHAR_P ch, CHAR_P gch, int attr,
const char *str, BOOLEAN_P presel)
{
NetHackQtWindow* window=id_to_window[(int)wid];
window->AddMenu(glyph, identifier, ch, gch, attr,
QString::fromLatin1(str),
presel);
}
void NetHackQtBind::qt_end_menu(winid wid, const char *prompt)
{
NetHackQtWindow* window=id_to_window[(int)wid];
window->EndMenu(prompt);
}
int NetHackQtBind::qt_select_menu(winid wid, int how, MENU_ITEM_P **menu_list)
{
NetHackQtWindow* window=id_to_window[(int)wid];
return window->SelectMenu(how,menu_list);
}
void NetHackQtBind::qt_update_inventory()
{
if (main)
main->updateInventory();
/* doesn't work yet
if (program_state.something_worth_saving && flags.perm_invent)
display_inventory(NULL, false);
*/
}
void NetHackQtBind::qt_mark_synch()
{
}
void NetHackQtBind::qt_wait_synch()
{
}
void NetHackQtBind::qt_cliparound(int x, int y)
{
// XXXNH - winid should be a parameter!
qt_cliparound_window(WIN_MAP,x,y);
}
void NetHackQtBind::qt_cliparound_window(winid wid, int x, int y)
{
NetHackQtWindow* window=id_to_window[(int)wid];
window->ClipAround(x,y);
}
void NetHackQtBind::qt_print_glyph(winid wid,XCHAR_P x,XCHAR_P y,int glyph,int bkglyph)
{
/* TODO: bkglyph */
NetHackQtWindow* window=id_to_window[(int)wid];
window->PrintGlyph(x,y,glyph);
}
//void NetHackQtBind::qt_print_glyph_compose(winid wid,xchar x,xchar y,int glyph1, int glyph2)
//{
//NetHackQtWindow* window=id_to_window[(int)wid];
//window->PrintGlyphCompose(x,y,glyph1,glyph2);
//}
void NetHackQtBind::qt_raw_print(const char *str)
{
puts(str);
}
void NetHackQtBind::qt_raw_print_bold(const char *str)
{
puts(str);
}
int NetHackQtBind::qt_nhgetch()
{
if (main)
main->fadeHighlighting();
// Process events until a key arrives.
//
while (keybuffer.Empty()) {
qApp->exec();
}
return keybuffer.GetAscii();
}
int NetHackQtBind::qt_nh_poskey(int *x, int *y, int *mod)
{
if (main)
main->fadeHighlighting();
// Process events until a key or map-click arrives.
//
while (keybuffer.Empty() && clickbuffer.Empty()) {
qApp->exec();
}
if (!keybuffer.Empty()) {
return keybuffer.GetAscii();
} else {
*x=clickbuffer.NextX();
*y=clickbuffer.NextY();
*mod=clickbuffer.NextMod();
clickbuffer.Get();
return 0;
}
}
void NetHackQtBind::qt_nhbell()
{
QApplication::beep();
}
int NetHackQtBind::qt_doprev_message()
{
// Don't need it - uses scrollbar
// XXX but could make this a shortcut
return 0;
}
char NetHackQtBind::qt_yn_function(const char *question_, const char *choices, CHAR_P def)
{
QString question(QString::fromLatin1(question_));
if (qt_settings->ynInMessages() && WIN_MESSAGE!=WIN_ERR) {
// Similar to X11 windowport `slow' feature.
QString message;
char yn_esc_map='\033';
if (choices) {
// anything beyond <esc> is hidden>
QString choicebuf = choices;
size_t cb = choicebuf.indexOf('\033');
choicebuf = choicebuf.mid(0U, cb);
message = QString("%1 [%2] ").arg(question, choicebuf);
if (def) message += QString("(%1) ").arg(QChar(def));
// escape maps to 'q' or 'n' or default, in that order
yn_esc_map = (index(choices, 'q') ? 'q' :
(index(choices, 'n') ? 'n' : def));
} else {
message = question;
}
#ifdef USE_POPUPS
// Improve some special-cases (DIRKS 08/02/23)
if (strcmp (choices,"ynq") == 0) {
switch (QMessageBox::information (NetHackQtBind::mainWidget(),"NetHack",question,"&Yes","&No","&Quit",0,2))
{
case 0: return 'y';
case 1: return 'n';
case 2: return 'q';
}
}
if (strcmp (choices,"yn") == 0) {
switch (QMessageBox::information(NetHackQtBind::mainWidget(),"NetHack",question,"&Yes", "&No",0,1))
{
case 0: return 'y';
case 1: return 'n';
}
}
#endif
NetHackQtBind::qt_putstr(WIN_MESSAGE, ATR_BOLD, message);
int result=-1;
while (result<0) {
char ch=NetHackQtBind::qt_nhgetch();
if (ch=='\033') {
result=yn_esc_map;
} else if (choices && !index(choices,ch)) {
if (def && (ch==' ' || ch=='\r' || ch=='\n')) {
result=def;
} else {
NetHackQtBind::qt_nhbell();
// and try again...
}
} else {
result=ch;
}
}
NetHackQtBind::qt_clear_nhwindow(WIN_MESSAGE);
return result;
} else {
NetHackQtYnDialog dialog(mainWidget(),question,choices,def);
return dialog.Exec();
}
}
void NetHackQtBind::qt_getlin(const char *prompt, char *line)
{
NetHackQtStringRequestor requestor(mainWidget(),prompt);
if (!requestor.Get(line)) {
line[0]=0;
}
}
int NetHackQtBind::qt_get_ext_cmd()
{
NetHackQtExtCmdRequestor requestor(mainWidget());
return requestor.get();
}
void NetHackQtBind::qt_number_pad(int)
{
// Ignore.
}
void NetHackQtBind::qt_delay_output()
{
NetHackQtDelay delay(15);
delay.wait();
}
void NetHackQtBind::qt_start_screen()
{
// Ignore.
}
void NetHackQtBind::qt_end_screen()
{
// Ignore.
}
void NetHackQtBind::qt_outrip(winid wid, int how, time_t when)
{
NetHackQtWindow* window=id_to_window[(int)wid];
window->UseRIP(how, when);
}
bool NetHackQtBind::notify(QObject *receiver, QEvent *event)
{
// Ignore Alt-key navigation to menubar, it's annoying when you
// use Alt-Direction to move around.
if ( main && event->type()==QEvent::KeyRelease && main==receiver
&& ((QKeyEvent*)event)->key() == Qt::Key_Alt )
return true;
bool result=QApplication::notify(receiver,event);
if (event->type()==QEvent::KeyPress) {
QKeyEvent* key_event=(QKeyEvent*)event;
if (!key_event->isAccepted()) {
const int k=key_event->key();
bool macro=false;
for (int i=0; !macro && key_macro[i].key; i++) {
if (key_macro[i].key==k
&& ((key_macro[i].state&key_event->modifiers())==key_macro[i].state))
{
keybuffer.Put(key_macro[i].macro);
macro=true;
}
}
QString key=key_event->text();
QChar ch = !key.isEmpty() ? key.at(0) : 0;
if (ch > 128) ch = 0;
if ( ch == 0 && (key_event->modifiers() & Qt::ControlModifier) ) {
// On Mac, ascii control codes are not sent, force them.
if ( k>=Qt::Key_A && k<=Qt::Key_Z )
ch = k - Qt::Key_A + 1;
}
if (!macro && ch != 0) {
bool alt = (key_event->modifiers()&Qt::AltModifier) ||
(k >= Qt::Key_0 && k <= Qt::Key_9 && (key_event->modifiers()&Qt::ControlModifier));
keybuffer.Put(key_event->key(),ch.cell() + (alt ? 128 : 0),
key_event->modifiers());
key_event->accept();
result=true;
}
if (ch != 0 || macro) {
qApp->exit();
}
}
}
return result;
}
NetHackQtBind* NetHackQtBind::instance=0;
NetHackQtKeyBuffer NetHackQtBind::keybuffer;
NetHackQtClickBuffer NetHackQtBind::clickbuffer;
NetHackQtMainWindow* NetHackQtBind::main=0;
QFrame* NetHackQtBind::splash=0;
static void Qt_positionbar(char *) {}
} // namespace nethack_qt4
struct window_procs Qt_procs = {
"Qt",
WC_COLOR | WC_HILITE_PET
| WC_ASCII_MAP | WC_TILED_MAP
| WC_FONT_MAP | WC_TILE_FILE | WC_TILE_WIDTH | WC_TILE_HEIGHT
| WC_PLAYER_SELECTION | WC_SPLASH_SCREEN,
0L,
nethack_qt4::NetHackQtBind::qt_init_nhwindows,
nethack_qt4::NetHackQtBind::qt_player_selection,
nethack_qt4::NetHackQtBind::qt_askname,
nethack_qt4::NetHackQtBind::qt_get_nh_event,
nethack_qt4::NetHackQtBind::qt_exit_nhwindows,
nethack_qt4::NetHackQtBind::qt_suspend_nhwindows,
nethack_qt4::NetHackQtBind::qt_resume_nhwindows,
nethack_qt4::NetHackQtBind::qt_create_nhwindow,
nethack_qt4::NetHackQtBind::qt_clear_nhwindow,
nethack_qt4::NetHackQtBind::qt_display_nhwindow,
nethack_qt4::NetHackQtBind::qt_destroy_nhwindow,
nethack_qt4::NetHackQtBind::qt_curs,
nethack_qt4::NetHackQtBind::qt_putstr,
nethack_qt4::NetHackQtBind::qt_putstr, /* FIXME: should be qt_putmixed() */
nethack_qt4::NetHackQtBind::qt_display_file,
nethack_qt4::NetHackQtBind::qt_start_menu,
nethack_qt4::NetHackQtBind::qt_add_menu,
nethack_qt4::NetHackQtBind::qt_end_menu,
nethack_qt4::NetHackQtBind::qt_select_menu,
genl_message_menu, /* no need for X-specific handling */
nethack_qt4::NetHackQtBind::qt_update_inventory,
nethack_qt4::NetHackQtBind::qt_mark_synch,
nethack_qt4::NetHackQtBind::qt_wait_synch,
#ifdef CLIPPING
nethack_qt4::NetHackQtBind::qt_cliparound,
#endif
#ifdef POSITIONBAR
nethack_qt4::Qt_positionbar,
#endif
nethack_qt4::NetHackQtBind::qt_print_glyph,
//NetHackQtBind::qt_print_glyph_compose,
nethack_qt4::NetHackQtBind::qt_raw_print,
nethack_qt4::NetHackQtBind::qt_raw_print_bold,
nethack_qt4::NetHackQtBind::qt_nhgetch,
nethack_qt4::NetHackQtBind::qt_nh_poskey,
nethack_qt4::NetHackQtBind::qt_nhbell,
nethack_qt4::NetHackQtBind::qt_doprev_message,
nethack_qt4::NetHackQtBind::qt_yn_function,
nethack_qt4::NetHackQtBind::qt_getlin,
nethack_qt4::NetHackQtBind::qt_get_ext_cmd,
nethack_qt4::NetHackQtBind::qt_number_pad,
nethack_qt4::NetHackQtBind::qt_delay_output,
#ifdef CHANGE_COLOR /* only a Mac option currently */
donull,
donull,
donull,
donull,
#endif
/* other defs that really should go away (they're tty specific) */
nethack_qt4::NetHackQtBind::qt_start_screen,
nethack_qt4::NetHackQtBind::qt_end_screen,
#ifdef GRAPHIC_TOMBSTONE
nethack_qt4::NetHackQtBind::qt_outrip,
#else
genl_outrip,
#endif
genl_preference_update,
genl_getmsghistory, genl_putmsghistory,
genl_status_init,
genl_status_finish, genl_status_enablefield,
#ifdef STATUS_HILITES
genl_status_update,
#else
genl_status_update,
#endif
genl_can_suspend_yes,
};
extern "C" void play_usersound(const char* filename, int volume)
{
#ifdef USER_SOUNDS
#ifndef QT_NO_SOUND
QSound::play(filename);
#endif
#endif
}
+92
View File
@@ -0,0 +1,92 @@
// Copyright (c) Warwick Allison, 1999.
// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
// NetHack may be freely redistributed. See license for details.
// qt4bind.h -- bindings between the Qt 4 interface and the main code
#ifndef QT4BIND_H
#define QT4BIND_H
#include "qt4main.h"
namespace nethack_qt4 {
class NetHackQtClickBuffer;
#ifdef KDE
#define NetHackQtBindBase KApplication
#elif defined(QWS)
#define NetHackQtBindBase QPEApplication
#else
#define NetHackQtBindBase QApplication
#endif
class NetHackQtBind : NetHackQtBindBase {
private:
// Single-instance preservation...
NetHackQtBind(int& argc, char** argv);
static NetHackQtBind* instance;
static NetHackQtKeyBuffer keybuffer;
static NetHackQtClickBuffer clickbuffer;
static QFrame* splash;
static NetHackQtMainWindow* main;
public:
static void qt_init_nhwindows(int* argc, char** argv);
static void qt_player_selection();
static void qt_askname();
static void qt_get_nh_event();
static void qt_exit_nhwindows(const char *);
static void qt_suspend_nhwindows(const char *);
static void qt_resume_nhwindows();
static winid qt_create_nhwindow(int type);
static void qt_clear_nhwindow(winid wid);
static void qt_display_nhwindow(winid wid, BOOLEAN_P block);
static void qt_destroy_nhwindow(winid wid);
static void qt_curs(winid wid, int x, int y);
static void qt_putstr(winid wid, int attr, const char *text);
static void qt_putstr(winid wid, int attr, const std::string& text);
static void qt_putstr(winid wid, int attr, const QString& text);
static void qt_display_file(const char *filename, BOOLEAN_P must_exist);
static void qt_start_menu(winid wid);
static void qt_add_menu(winid wid, int glyph,
const ANY_P * identifier, CHAR_P ch, CHAR_P gch, int attr,
const char *str, BOOLEAN_P presel);
static void qt_end_menu(winid wid, const char *prompt);
static int qt_select_menu(winid wid, int how, MENU_ITEM_P **menu_list);
static void qt_update_inventory();
static void qt_mark_synch();
static void qt_wait_synch();
static void qt_cliparound(int x, int y);
static void qt_cliparound_window(winid wid, int x, int y);
static void qt_print_glyph(winid wid,XCHAR_P x,XCHAR_P y,int glyph,int bkglyph);
static void qt_raw_print(const char *str);
static void qt_raw_print_bold(const char *str);
static int qt_nhgetch();
static int qt_nh_poskey(int *x, int *y, int *mod);
static void qt_nhbell();
static int qt_doprev_message();
static char qt_yn_function(const char *question, const char *choices, CHAR_P def);
static void qt_getlin(const char *prompt, char *line);
static int qt_get_ext_cmd();
static void qt_number_pad(int);
static void qt_delay_output();
static void qt_start_screen();
static void qt_end_screen();
static void qt_outrip(winid wid, int how, time_t when);
static int qt_kbhit();
static QWidget *mainWidget() { return main; }
private:
virtual bool notify(QObject *receiver, QEvent *event);
};
} // namespace nethack_qt4
#endif
+48
View File
@@ -0,0 +1,48 @@
// Copyright (c) Warwick Allison, 1999.
// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
// NetHack may be freely redistributed. See license for details.
// qt4click.cpp -- a mouse click buffer
#include "hack.h"
#undef Invisible
#undef Warning
#undef index
#undef msleep
#undef rindex
#undef wizard
#undef yn
#undef min
#undef max
#include <QtGui/QtGui>
#include "qt4click.h"
namespace nethack_qt4 {
NetHackQtClickBuffer::NetHackQtClickBuffer() :
in(0), out(0)
{
}
bool NetHackQtClickBuffer::Empty() const { return in==out; }
bool NetHackQtClickBuffer::Full() const { return (in+1)%maxclick==out; }
void NetHackQtClickBuffer::Put(int x, int y, int mod)
{
click[in].x=x;
click[in].y=y;
click[in].mod=mod;
in=(in+1)%maxclick;
}
int NetHackQtClickBuffer::NextX() const { return click[out].x; }
int NetHackQtClickBuffer::NextY() const { return click[out].y; }
int NetHackQtClickBuffer::NextMod() const { return click[out].mod; }
void NetHackQtClickBuffer::Get()
{
out=(out+1)%maxclick;
}
} // namespace nethack_qt4
+37
View File
@@ -0,0 +1,37 @@
// Copyright (c) Warwick Allison, 1999.
// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
// NetHack may be freely redistributed. See license for details.
// qt4click.h -- a mouse click buffer
#ifndef QT4CLICK_H
#define QT4CLICK_H
namespace nethack_qt4 {
class NetHackQtClickBuffer {
public:
NetHackQtClickBuffer();
bool Empty() const;
bool Full() const;
void Put(int x, int y, int mod);
int NextX() const;
int NextY() const;
int NextMod() const;
void Get();
private:
enum { maxclick=64 };
struct ClickRec {
int x,y,mod;
} click[maxclick];
int in,out;
};
} // namespace nethack_qt4
#endif
+167
View File
@@ -0,0 +1,167 @@
/* SCCS Id: @(#)qt_clust.cpp 3.4 1999/11/19 */
/* Copyright (c) Warwick Allison, 1999. */
/* NetHack may be freely redistributed. See license for details. */
#include "qt4clust.h"
static void include(QRect& r, const QRect& rect)
{
if (rect.left()<r.left()) {
r.setLeft(rect.left());
}
if (rect.right()>r.right()) {
r.setRight(rect.right());
}
if (rect.top()<r.top()) {
r.setTop(rect.top());
}
if (rect.bottom()>r.bottom()) {
r.setBottom(rect.bottom());
}
}
/*
A Clusterizer groups rectangles (QRects) into non-overlapping rectangles
by a merging heuristic.
*/
Clusterizer::Clusterizer(int maxclusters) :
cluster(new QRect[maxclusters]),
count(0),
max(maxclusters)
{ }
Clusterizer::~Clusterizer()
{
delete [] cluster;
}
void Clusterizer::clear()
{
count=0;
}
void Clusterizer::add(int x, int y)
{
add(QRect(x,y,1,1));
}
void Clusterizer::add(int x, int y, int w, int h)
{
add(QRect(x,y,w,h));
}
void Clusterizer::add(const QRect& rect)
{
QRect biggerrect(rect.x()-1,rect.y()-1,rect.width()+2,rect.height()+2);
//assert(rect.width()>0 && rect.height()>0);
int cursor;
for (cursor=0; cursor<count; cursor++) {
if (cluster[cursor].contains(rect)) {
// Wholly contained already.
return;
}
}
int lowestcost=9999999;
int cheapest=-1;
for (cursor=0; cursor<count; cursor++) {
if (cluster[cursor].intersects(biggerrect)) {
QRect larger=cluster[cursor];
include(larger,rect);
int cost=larger.width()*larger.height()
- cluster[cursor].width()*cluster[cursor].height();
if (cost < lowestcost) {
bool bad=false;
for (int c=0; c<count && !bad; c++) {
bad=cluster[c].intersects(larger) && c!=cursor;
}
if (!bad) {
cheapest=cursor;
lowestcost=cost;
}
}
}
}
if (cheapest>=0) {
include(cluster[cheapest],rect);
return;
}
if (count < max) {
cluster[count++]=rect;
return;
}
// Do cheapest of:
// add to closest cluster
// do cheapest cluster merge, add to new cluster
lowestcost=9999999;
cheapest=-1;
for (cursor=0; cursor<count; cursor++) {
QRect larger=cluster[cursor];
include(larger,rect);
int cost=larger.width()*larger.height()
- cluster[cursor].width()*cluster[cursor].height();
if (cost < lowestcost) {
bool bad=false;
for (int c=0; c<count && !bad; c++) {
bad=cluster[c].intersects(larger) && c!=cursor;
}
if (!bad) {
cheapest=cursor;
lowestcost=cost;
}
}
}
// XXX could make an heuristic guess as to whether we
// XXX need to bother looking for a cheap merge.
int cheapestmerge1=-1;
int cheapestmerge2=-1;
for (int merge1=0; merge1<count; merge1++) {
for (int merge2=0; merge2<count; merge2++) {
if (merge1!=merge2) {
QRect larger=cluster[merge1];
include(larger,cluster[merge2]);
int cost=larger.width()*larger.height()
- cluster[merge1].width()*cluster[merge1].height()
- cluster[merge2].width()*cluster[merge2].height();
if (cost < lowestcost) {
bool bad=false;
for (int c=0; c<count && !bad; c++) {
bad=cluster[c].intersects(larger) && c!=cursor;
}
if (!bad) {
cheapestmerge1=merge1;
cheapestmerge2=merge2;
lowestcost=cost;
}
}
}
}
}
if (cheapestmerge1>=0) {
include(cluster[cheapestmerge1],cluster[cheapestmerge2]);
cluster[cheapestmerge2]=cluster[count--];
} else {
// if (!cheapest) debugRectangles(rect);
include(cluster[cheapest],rect);
}
// NB: clusters do not intersect (or intersection will
// overwrite). This is a result of the above algorithm,
// given the assumption that (x,y) are ordered topleft
// to bottomright.
}
const QRect& Clusterizer::operator[](int i)
{
return cluster[i];
}
+29
View File
@@ -0,0 +1,29 @@
/* SCCS Id: @(#)qt_clust.h 3.4 1999/11/19 */
/* Copyright (c) Warwick Allison, 1999. */
/* NetHack may be freely redistributed. See license for details. */
#ifndef clusterizer_H
#define clusterizer_H
#include <QtCore/QRect>
class Clusterizer {
public:
Clusterizer(int maxclusters);
~Clusterizer();
void add(int x, int y); // 1x1 rectangle (point)
void add(int x, int y, int w, int h);
void add(const QRect& rect);
void clear();
int clusters() { return count; }
const QRect& operator[](int i);
private:
QRect* cluster;
int count;
const int max;
};
#endif
+42
View File
@@ -0,0 +1,42 @@
// Copyright (c) Warwick Allison, 1999.
// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
// NetHack may be freely redistributed. See license for details.
// qt4delay.cpp -- implement a delay
#include "hack.h"
#undef Invisible
#undef Warning
#undef index
#undef msleep
#undef rindex
#undef wizard
#undef yn
#undef min
#undef max
#include <QtGui/QtGui>
#include "qt4delay.h"
namespace nethack_qt4 {
// RLC Can we use QTimer::single_shot for this?
NetHackQtDelay::NetHackQtDelay(int ms) :
msec(ms), m_timer(0), m_loop(this)
{
}
void NetHackQtDelay::wait()
{
m_timer = startTimer(msec);
m_loop.exec();
}
void NetHackQtDelay::timerEvent(QTimerEvent* timer)
{
m_loop.exit();
killTimer(m_timer);
m_timer = 0;
}
} // namespace nethack_qt4
+26
View File
@@ -0,0 +1,26 @@
// Copyright (c) Warwick Allison, 1999.
// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
// NetHack may be freely redistributed. See license for details.
// qt4delay.h -- implement a delay
#ifndef QT4DELAY_H
#define QT4DELAY_H
namespace nethack_qt4 {
class NetHackQtDelay : QObject {
private:
int msec;
int m_timer;
QEventLoop m_loop;
public:
NetHackQtDelay(int ms);
void wait();
virtual void timerEvent(QTimerEvent* timer);
};
} // namespace nethack_qt4
#endif
+141
View File
@@ -0,0 +1,141 @@
// Copyright (c) Warwick Allison, 1999.
// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
// NetHack may be freely redistributed. See license for details.
// qt4glyph.cpp -- class to manage the glyphs in a tile set
extern "C" {
#include "hack.h"
}
#include "tile2x11.h"
#undef Invisible
#undef Warning
#undef index
#undef msleep
#undef rindex
#undef wizard
#undef yn
#undef min
#undef max
#include <QtGui/QtGui>
#if QT_VERSION >= 0x050000
#include <QtWidgets/QtWidgets>
#endif
#include "qt4glyph.h"
#include "qt4set.h"
#include "qt4str.h"
extern short glyph2tile[]; // from tile.c
namespace nethack_qt4 {
static int tilefile_tile_W=16;
static int tilefile_tile_H=16;
// Debian uses a separate PIXMAPDIR
#ifndef PIXMAPDIR
# ifdef HACKDIR
# define PIXMAPDIR HACKDIR
# else
# define PIXMAPDIR "."
# endif
#endif
NetHackQtGlyphs::NetHackQtGlyphs()
{
const char* tile_file = PIXMAPDIR "/nhtiles.bmp";
if ( iflags.wc_tile_file )
tile_file = iflags.wc_tile_file;
if (!img.load(tile_file)) {
tile_file = PIXMAPDIR "/x11tiles";
if (!img.load(tile_file)) {
QString msg;
msg.sprintf("Cannot load x11tiles or nhtiles.bmp");
QMessageBox::warning(0, "IO Error", msg);
} else {
tiles_per_row = TILES_PER_ROW;
if (img.width()%tiles_per_row) {
impossible("Tile file \"%s\" has %d columns, not multiple of row count (%d)",
tile_file, img.width(), tiles_per_row);
}
}
} else {
tiles_per_row = 40;
}
if ( iflags.wc_tile_width )
tilefile_tile_W = iflags.wc_tile_width;
else
tilefile_tile_W = img.width() / tiles_per_row;
if ( iflags.wc_tile_height )
tilefile_tile_H = iflags.wc_tile_height;
else
tilefile_tile_H = tilefile_tile_W;
setSize(tilefile_tile_W, tilefile_tile_H);
}
void NetHackQtGlyphs::drawGlyph(QPainter& painter, int glyph, int x, int y)
{
int tile = glyph2tile[glyph];
int px = (tile%tiles_per_row)*width();
int py = tile/tiles_per_row*height();
painter.drawPixmap(
x,
y,
pm,
px,py,
width(),height()
);
}
void NetHackQtGlyphs::drawCell(QPainter& painter, int glyph, int cellx, int celly)
{
drawGlyph(painter,glyph,cellx*width(),celly*height());
}
QPixmap NetHackQtGlyphs::glyph(int glyph)
{
int tile = glyph2tile[glyph];
int px = (tile%tiles_per_row)*tilefile_tile_W;
int py = tile/tiles_per_row*tilefile_tile_H;
return QPixmap::fromImage(img.copy(px, py, tilefile_tile_W, tilefile_tile_H));
}
void NetHackQtGlyphs::setSize(int w, int h)
{
if ( size == QSize(w,h) )
return;
bool was1 = size == pm1.size();
size = QSize(w,h);
if (!w || !h)
return; // Still not decided
if ( size == pm1.size() ) {
pm = pm1;
return;
}
if ( size == pm2.size() ) {
pm = pm2;
return;
}
if (w==tilefile_tile_W && h==tilefile_tile_H) {
pm.convertFromImage(img);
} else {
QApplication::setOverrideCursor( Qt::WaitCursor );
QImage scaled = img.scaled(
w*img.width()/tilefile_tile_W,
h*img.height()/tilefile_tile_H,
Qt::IgnoreAspectRatio,
Qt::SmoothTransformation
);
pm.convertFromImage(scaled,Qt::ThresholdDither|Qt::PreferDither);
QApplication::restoreOverrideCursor();
}
(was1 ? pm2 : pm1) = pm;
}
} // namespace nethack_qt4
+34
View File
@@ -0,0 +1,34 @@
// Copyright (c) Warwick Allison, 1999.
// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
// NetHack may be freely redistributed. See license for details.
// qt4glyph.h -- class to manage the glyphs in a tile set
#ifndef QT4GLYPH_H
#define QT4GLYPH_H
namespace nethack_qt4 {
class NetHackQtGlyphs {
public:
NetHackQtGlyphs();
int width() const { return size.width(); }
int height() const { return size.height(); }
void toggleSize();
void setSize(int w, int h);
void drawGlyph(QPainter&, int glyph, int pixelx, int pixely);
void drawCell(QPainter&, int glyph, int cellx, int celly);
QPixmap glyph(int glyph);
private:
QImage img;
QPixmap pm,pm1, pm2;
QSize size;
int tiles_per_row;
};
} // namespace nethack_qt4
#endif
+203
View File
@@ -0,0 +1,203 @@
// Copyright (c) Warwick Allison, 1999.
// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
// NetHack may be freely redistributed. See license for details.
// qt4icon.cpp -- a labelled icon
#include "hack.h"
#undef Invisible
#undef Warning
#undef index
#undef msleep
#undef rindex
#undef wizard
#undef yn
#undef min
#undef max
#include <QtGui/QtGui>
#if QT_VERSION >= 0x050000
#include <QtWidgets/QtWidgets>
#endif
#include "qt4icon.h"
namespace nethack_qt4 {
NetHackQtLabelledIcon::NetHackQtLabelledIcon(QWidget* parent, const char* l) :
QWidget(parent),
low_is_good(false),
prev_value(-123),
turn_count(-1),
label(new QLabel(l,this)),
icon(0)
{
initHighlight();
}
NetHackQtLabelledIcon::NetHackQtLabelledIcon(QWidget* parent, const char* l, const QPixmap& i) :
QWidget(parent),
low_is_good(false),
prev_value(-123),
turn_count(-1),
label(new QLabel(l,this)),
icon(new QLabel(this))
{
setIcon(i);
initHighlight();
}
void NetHackQtLabelledIcon::initHighlight()
{
hl_good = "QLabel { background-color : green; color : white }";
hl_bad = "QLabel { background-color : red ; color : white }";
}
void NetHackQtLabelledIcon::setLabel(const QString& t, bool lower)
{
if (!label) {
label=new QLabel(this);
label->setFont(font());
resizeEvent(0);
}
if (label->text() != t) {
label->setText(t);
highlight(lower==low_is_good ? hl_good : hl_bad);
}
}
void NetHackQtLabelledIcon::setLabel(const QString& t, long v, long cv, const QString& tail)
{
QString buf;
if (v==NoNum) {
buf = "";
} else {
buf.sprintf("%ld", v);
}
setLabel(t + buf + tail, cv < prev_value);
prev_value=cv;
}
void NetHackQtLabelledIcon::setLabel(const QString& t, long v, const QString& tail)
{
setLabel(t,v,v,tail);
}
void NetHackQtLabelledIcon::setIcon(const QPixmap& i)
{
if (icon) icon->setPixmap(i);
else { icon=new QLabel(this); icon->setPixmap(i); resizeEvent(0); }
icon->resize(i.width(),i.height());
}
void NetHackQtLabelledIcon::setFont(const QFont& f)
{
QWidget::setFont(f);
if (label) label->setFont(f);
}
void NetHackQtLabelledIcon::show()
{
#if QT_VERSION >= 300
if (isHidden())
#else
if (!isVisible())
#endif
highlight(hl_bad);
QWidget::show();
}
QSize NetHackQtLabelledIcon::sizeHint() const
{
QSize iconsize, textsize;
if (label && !icon) return label->sizeHint();
if (icon && !label) return icon->sizeHint();
if (!label && !icon) return QWidget::sizeHint();
iconsize = icon->sizeHint();
textsize = label->sizeHint();
return QSize(
std::max(iconsize.width(), textsize.width()),
iconsize.height() + textsize.height());
}
QSize NetHackQtLabelledIcon::minimumSizeHint() const
{
QSize iconsize, textsize;
if (label && !icon) return label->minimumSizeHint();
if (icon && !label) return icon->minimumSizeHint();
if (!label && !icon) return QWidget::minimumSizeHint();
iconsize = icon->minimumSizeHint();
textsize = label->minimumSizeHint();
return QSize(
std::max(iconsize.width(), textsize.width()),
iconsize.height() + textsize.height());
}
void NetHackQtLabelledIcon::highlightWhenChanging()
{
turn_count=0;
}
void NetHackQtLabelledIcon::lowIsGood()
{
low_is_good=true;
}
void NetHackQtLabelledIcon::dissipateHighlight()
{
if (turn_count>0) {
turn_count--;
if (!turn_count)
unhighlight();
}
}
void NetHackQtLabelledIcon::highlight(const QString& hl)
{
if (label) { // Surely it is?!
if (turn_count>=0) {
label->setStyleSheet(hl);
turn_count=4;
// `4' includes this turn, so dissipates after
// 3 more keypresses.
} else {
label->setStyleSheet("");
}
}
}
void NetHackQtLabelledIcon::unhighlight()
{
if (label) { // Surely it is?!
label->setStyleSheet("");
}
}
void NetHackQtLabelledIcon::resizeEvent(QResizeEvent*)
{
setAlignments();
//int labw=label ? label->fontMetrics().width(label->text()) : 0;
int labh=label ? label->fontMetrics().height() : 0;
int icoh=icon ? icon->height() : 0;
int h=icoh+labh;
int icoy=(h>height() ? height()-labh-icoh : height()/2-h/2);
int laby=icoy+icoh;
if (icon) {
icon->setGeometry(0,icoy,width(),icoh);
}
if (label) {
label->setGeometry(0,laby,width(),labh);
}
}
void NetHackQtLabelledIcon::setAlignments()
{
if (label) label->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
if (icon) icon->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
}
} // namespace nethack_qt4
+53
View File
@@ -0,0 +1,53 @@
// Copyright (c) Warwick Allison, 1999.
// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
// NetHack may be freely redistributed. See license for details.
// qt4icon.cpp -- a labelled icon
#ifndef QT4ICON_H
#define QT4ICON_H
namespace nethack_qt4 {
class NetHackQtLabelledIcon : public QWidget {
public:
NetHackQtLabelledIcon(QWidget* parent, const char* label);
NetHackQtLabelledIcon(QWidget* parent, const char* label, const QPixmap& icon);
enum { NoNum=-99999 };
void setLabel(const QString&, bool lower=true); // a string
void setLabel(const QString&, long, const QString& tail=""); // a number
void setLabel(const QString&, long show_value, long comparative_value, const QString& tail="");
void setIcon(const QPixmap&);
virtual void setFont(const QFont&);
void highlightWhenChanging();
void lowIsGood();
void dissipateHighlight();
virtual void show();
virtual QSize sizeHint() const;
virtual QSize minimumSizeHint() const;
protected:
void resizeEvent(QResizeEvent*);
private:
void initHighlight();
void setAlignments();
void highlight(const QString& highlight);
void unhighlight();
bool low_is_good;
int prev_value;
int turn_count; /* last time the value changed */
QString hl_good;
QString hl_bad;
QLabel* label;
QLabel* icon;
};
} // namespace nethack_qt4
#endif
+104
View File
@@ -0,0 +1,104 @@
// Copyright (c) Warwick Allison, 1999.
// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
// NetHack may be freely redistributed. See license for details.
// qt4inv.cpp -- inventory usage window
// This is at the top center of the main window
extern "C" {
#include "hack.h"
}
#undef Invisible
#undef Warning
#undef index
#undef msleep
#undef rindex
#undef wizard
#undef yn
#undef min
#undef max
#include <QtGui/QtGui>
#if QT_VERSION >= 0x050000
#include <QtWidgets/QtWidgets>
#endif
#include "qt4inv.h"
#include "qt4glyph.h"
#include "qt4set.h"
namespace nethack_qt4 {
NetHackQtInvUsageWindow::NetHackQtInvUsageWindow(QWidget* parent) :
QWidget(parent)
{
setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
}
void NetHackQtInvUsageWindow::drawWorn(QPainter& painter, obj* nhobj, int x, int y, bool canbe)
{
short int glyph;
if (nhobj)
glyph=obj_to_glyph(nhobj);
else if (canbe)
glyph=cmap_to_glyph(S_room);
else
glyph=cmap_to_glyph(S_stone);
qt_settings->glyphs().drawCell(painter,glyph,x,y);
}
void NetHackQtInvUsageWindow::paintEvent(QPaintEvent*)
{
// 012
//
//0 WhB
//1 s"w
//2 gCg
//3 =A=
//4 T
//5 S
QPainter painter;
painter.begin(this);
// Blanks
drawWorn(painter,0,0,4,false);
drawWorn(painter,0,0,5,false);
drawWorn(painter,0,2,4,false);
drawWorn(painter,0,2,5,false);
drawWorn(painter,uarm,1,3); // Armour
drawWorn(painter,uarmc,1,2); // Cloak
drawWorn(painter,uarmh,1,0); // Helmet
drawWorn(painter,uarms,0,1); // Shield
drawWorn(painter,uarmg,0,2); // Gloves - repeated
drawWorn(painter,uarmg,2,2); // Gloves - repeated
#ifdef TOURIST
drawWorn(painter,uarmf,1,5); // Shoes (feet)
drawWorn(painter,uarmu,1,4); // Undershirt
#else
drawWorn(painter,0 ,1,5,false);
drawWorn(painter,uarmf,1,4); // Shoes (feet)
#endif
drawWorn(painter,uleft,0,3); // RingL
drawWorn(painter,uright,2,3); // RingR
drawWorn(painter,uwep,2,1); // Weapon
drawWorn(painter,uswapwep,0,0); // Secondary weapon
drawWorn(painter,uamul,1,1); // Amulet
drawWorn(painter,ublindf,2,0); // Blindfold
painter.end();
}
QSize NetHackQtInvUsageWindow::sizeHint(void) const
{
if (qt_settings) {
return QSize(qt_settings->glyphs().width()*3,
qt_settings->glyphs().height()*6);
} else {
return QWidget::sizeHint();
}
}
} // namespace nethack_qt4
+25
View File
@@ -0,0 +1,25 @@
// Copyright (c) Warwick Allison, 1999.
// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
// NetHack may be freely redistributed. See license for details.
// qt4inv.h -- inventory usage window
// This is at the top center of the main window
#ifndef QT4INV_H
#define QT4INV_H
namespace nethack_qt4 {
class NetHackQtInvUsageWindow : public QWidget {
public:
NetHackQtInvUsageWindow(QWidget* parent);
virtual void paintEvent(QPaintEvent*);
virtual QSize sizeHint(void) const;
private:
void drawWorn(QPainter& painter, obj*, int x, int y, bool canbe=true);
};
} // namespace nethack_qt4
#endif
+14
View File
@@ -0,0 +1,14 @@
/* SCCS Id: @(#)qt_kde0.h 3.4 1999/11/19 */
/* Copyright (c) Warwick Allison, 1999. */
/* NetHack may be freely redistributed. See license for details. */
#ifndef QT_DUMMYKDE
#define QT_DUMMYKDE
namespace nethack_qt4 {
class KTopLevelWidget : public QMainWindow {
Q_OBJECT
};
}
#endif
+91
View File
@@ -0,0 +1,91 @@
// Copyright (c) Warwick Allison, 1999.
// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
// NetHack may be freely redistributed. See license for details.
// qt4key.cpp -- a key buffer
#include "hack.h"
#undef Invisible
#undef Warning
#undef index
#undef msleep
#undef rindex
#undef wizard
#undef yn
#undef min
#undef max
#include <QtGui/QtGui>
#include "qt4key.h"
namespace nethack_qt4 {
NetHackQtKeyBuffer::NetHackQtKeyBuffer() :
in(0), out(0)
{
}
bool NetHackQtKeyBuffer::Empty() const { return in==out; }
bool NetHackQtKeyBuffer::Full() const { return (in+1)%maxkey==out; }
void NetHackQtKeyBuffer::Put(int k, int a, int state)
{
if ( Full() ) return; // Safety
key[in]=k;
ascii[in]=a;
in=(in+1)%maxkey;
}
void NetHackQtKeyBuffer::Put(char a)
{
Put(0,a,0);
}
void NetHackQtKeyBuffer::Put(const char* str)
{
while (*str) Put(*str++);
}
int NetHackQtKeyBuffer::GetKey()
{
if ( Empty() ) return 0;
int r=TopKey();
out=(out+1)%maxkey;
return r;
}
int NetHackQtKeyBuffer::GetAscii()
{
if ( Empty() ) return 0; // Safety
int r=TopAscii();
out=(out+1)%maxkey;
return r;
}
Qt::KeyboardModifiers NetHackQtKeyBuffer::GetState()
{
if ( Empty() ) return 0;
Qt::KeyboardModifiers r=TopState();
out=(out+1)%maxkey;
return r;
}
int NetHackQtKeyBuffer::TopKey() const
{
if ( Empty() ) return 0;
return key[out];
}
int NetHackQtKeyBuffer::TopAscii() const
{
if ( Empty() ) return 0;
return ascii[out];
}
Qt::KeyboardModifiers NetHackQtKeyBuffer::TopState() const
{
if ( Empty() ) return 0;
return state[out];
}
} // namespace nethack_qt4
+40
View File
@@ -0,0 +1,40 @@
// Copyright (c) Warwick Allison, 1999.
// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
// NetHack may be freely redistributed. See license for details.
// qt4key.h -- a key buffer
#ifndef QT4KEY_H
#define QT4KEY_H
namespace nethack_qt4 {
class NetHackQtKeyBuffer {
public:
NetHackQtKeyBuffer();
bool Empty() const;
bool Full() const;
void Put(int k, int ascii, int state);
void Put(char a);
void Put(const char* str);
int GetKey();
int GetAscii();
Qt::KeyboardModifiers GetState();
int TopKey() const;
int TopAscii() const;
Qt::KeyboardModifiers TopState() const;
private:
enum { maxkey=64 };
int key[maxkey];
int ascii[maxkey];
Qt::KeyboardModifiers state[maxkey];
int in,out;
};
} // namespace nethack_qt4
#endif
+42
View File
@@ -0,0 +1,42 @@
// Copyright (c) Warwick Allison, 1999.
// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
// NetHack may be freely redistributed. See license for details.
// qt4line.cpp -- a one line input window
#include "hack.h"
#undef Invisible
#undef Warning
#undef index
#undef msleep
#undef rindex
#undef wizard
#undef yn
#undef min
#undef max
#include <QtGui/QtGui>
#if QT_VERSION >= 0x050000
#include <QtWidgets/QtWidgets>
#endif
#include "qt4line.h"
namespace nethack_qt4 {
NetHackQtLineEdit::NetHackQtLineEdit() :
QLineEdit(0)
{
}
NetHackQtLineEdit::NetHackQtLineEdit(QWidget* parent, const char* name) :
QLineEdit(parent)
{
}
void NetHackQtLineEdit::fakeEvent(int key, int ascii, Qt::KeyboardModifiers state)
{
QKeyEvent fake(QEvent::KeyPress,key,state,QChar(ascii));
keyPressEvent(&fake);
}
} // namespace nethack_qt4
+22
View File
@@ -0,0 +1,22 @@
// Copyright (c) Warwick Allison, 1999.
// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
// NetHack may be freely redistributed. See license for details.
// qt4line.h -- a one line input window
#ifndef QT4LINE_H
#define QT4LINE_H
namespace nethack_qt4 {
class NetHackQtLineEdit : public QLineEdit {
public:
NetHackQtLineEdit();
NetHackQtLineEdit(QWidget* parent, const char* name);
void fakeEvent(int key, int ascii, Qt::KeyboardModifiers state);
};
} // namespace nethack_qt4
#endif
+1063
View File
File diff suppressed because it is too large Load Diff
+94
View File
@@ -0,0 +1,94 @@
// Copyright (c) Warwick Allison, 1999.
// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
// NetHack may be freely redistributed. See license for details.
// qt4main.h -- the main window
#ifndef QT4MAIN_H
#define QT4MAIN_H
#ifdef KDE
#include <kapp.h>
#include <ktopwidget.h>
#else
#include "qt4kde0.h"
#endif
namespace nethack_qt4 {
class NetHackQtInvUsageWindow;
class NetHackQtKeyBuffer;
class NetHackQtMapWindow2;
class NetHackQtMessageWindow;
class NetHackQtStatusWindow;
class NetHackQtWindow;
// This class is the main widget for NetHack
//
// It is a collection of Message, Map, and Status windows. In the current
// version of nethack there is only one of each, and this class makes this
// assumption, not showing itself until all are inserted.
//
// This class simply knows how to layout such children sensibly.
//
// Since it is only responsible for layout, the class does not
// note the actual class of the windows.
//
class NetHackQtMainWindow : public KTopLevelWidget {
Q_OBJECT
public:
NetHackQtMainWindow(NetHackQtKeyBuffer&);
void AddMessageWindow(NetHackQtMessageWindow* window);
void AddMapWindow(NetHackQtMapWindow2* window);
void AddStatusWindow(NetHackQtStatusWindow* window);
void RemoveWindow(NetHackQtWindow* window);
void updateInventory();
void fadeHighlighting();
public slots:
void doMenuItem(QAction *);
void doQtSettings(bool);
void doAbout(bool);
//RLC void doGuidebook(bool);
void doKeys(const QString&);
protected:
virtual void resizeEvent(QResizeEvent*);
virtual void keyPressEvent(QKeyEvent*);
virtual void keyReleaseEvent(QKeyEvent* event);
virtual void closeEvent(QCloseEvent*);
private slots:
void layout();
void raiseMap();
void zoomMap();
void raiseMessages();
void raiseStatus();
private:
void ShowIfReady();
#ifdef KDE
KMenuBar* menubar;
#else
QMenuBar* menubar;
#endif
NetHackQtMessageWindow* message;
NetHackQtMapWindow2* map;
NetHackQtStatusWindow* status;
NetHackQtInvUsageWindow* invusage;
QSplitter *hsplitter;
QSplitter *vsplitter;
NetHackQtKeyBuffer& keysink;
QStackedWidget* stack;
int dirkey;
};
} // namespace nethack_qt4
#endif
+964
View File
@@ -0,0 +1,964 @@
// Copyright (c) Warwick Allison, 1999.
// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
// NetHack may be freely redistributed. See license for details.
// qt4map.cpp -- the map window
extern "C" {
#include "hack.h"
}
#undef Invisible
#undef Warning
#undef index
#undef msleep
#undef rindex
#undef wizard
#undef yn
#undef min
#undef max
#include <QtGui/QtGui>
#if QT_VERSION >= 0x050000
#include <QtWidgets/QtWidgets>
#endif
#include "qt4map.h"
#include "qt4map.moc"
#include "qt4click.h"
#include "qt4glyph.h"
#include "qt_xpms.h"
#include "qt4set.h"
#include "qt4str.h"
// temporary
extern int qt_compact_mode;
// end temporary
namespace nethack_qt4 {
#ifdef TEXTCOLOR
static const QPen& nhcolor_to_pen(int c)
{
static QPen* pen=0;
if ( !pen ) {
pen = new QPen[17];
pen[0] = QColor(64,64,64);
pen[1] = QColor(Qt::red);
pen[2] = QColor(0,191,0);
pen[3] = QColor(127,127,0);
pen[4] = QColor(Qt::blue);
pen[5] = QColor(Qt::magenta);
pen[6] = QColor(Qt::cyan);
pen[7] = QColor(Qt::gray);
pen[8] = QColor(Qt::white); // no color
pen[9] = QColor(255,127,0);
pen[10] = QColor(127,255,127);
pen[11] = QColor(Qt::yellow);
pen[12] = QColor(127,127,255);
pen[13] = QColor(255,127,255);
pen[14] = QColor(127,255,255);
pen[15] = QColor(Qt::white);
pen[16] = QColor(Qt::black);
}
return pen[c];
}
#endif
NetHackQtMapViewport::NetHackQtMapViewport(NetHackQtClickBuffer& click_sink) :
QWidget(NULL),
rogue_font(NULL),
clicksink(click_sink),
change(10)
{
pet_annotation = QPixmap(qt_compact_mode ? pet_mark_small_xpm : pet_mark_xpm);
Clear();
cursor.setX(0);
cursor.setY(0);
}
NetHackQtMapViewport::~NetHackQtMapViewport(void)
{
delete rogue_font;
}
void NetHackQtMapViewport::paintEvent(QPaintEvent* event)
{
QRect area=event->rect();
QRect garea;
garea.setCoords(
std::max(0,area.left()/qt_settings->glyphs().width()),
std::max(0,area.top()/qt_settings->glyphs().height()),
std::min(COLNO-1,area.right()/qt_settings->glyphs().width()),
std::min(ROWNO-1,area.bottom()/qt_settings->glyphs().height())
);
QPainter painter;
painter.begin(this);
if (Is_rogue_level(&u.uz) || iflags.wc_ascii_map) {
// You enter a VERY primitive world!
painter.setClipRect( event->rect() ); // (normally we don't clip)
painter.fillRect( event->rect(), Qt::black );
if ( !rogue_font ) {
// Find font...
int pts = 5;
QString fontfamily = iflags.wc_font_map
? iflags.wc_font_map : "Monospace";
bool bold = false;
if ( fontfamily.right(5).toLower() == "-bold" ) {
fontfamily.truncate(fontfamily.length()-5);
bold = true;
}
while ( pts < 32 ) {
QFont f(fontfamily, pts, bold ? QFont::Bold : QFont::Normal);
painter.setFont(QFont(fontfamily, pts));
QFontMetrics fm = painter.fontMetrics();
if ( fm.width("M") > qt_settings->glyphs().width() )
break;
if ( fm.height() > qt_settings->glyphs().height() )
break;
pts++;
}
rogue_font = new QFont(fontfamily,pts-1);
}
painter.setFont(*rogue_font);
for (int j=garea.top(); j<=garea.bottom(); j++) {
for (int i=garea.left(); i<=garea.right(); i++) {
unsigned short g=Glyph(i,j);
int color;
int ch;
unsigned special;
painter.setPen( Qt::green );
/* map glyph to character and color */
mapglyph(g, &ch, &color, &special, i, j);
ch = cp437(ch);
#ifdef TEXTCOLOR
painter.setPen( nhcolor_to_pen(color) );
#endif
if (!DrawWalls(
painter,
i*qt_settings->glyphs().width(),
j*qt_settings->glyphs().height(),
qt_settings->glyphs().width(),
qt_settings->glyphs().height(),
ch)) {
painter.drawText(
i*qt_settings->glyphs().width(),
j*qt_settings->glyphs().height(),
qt_settings->glyphs().width(),
qt_settings->glyphs().height(),
Qt::AlignCenter,
QString(QChar(ch)).left(1)
);
}
if (glyph_is_pet(g)
#ifdef TEXTCOLOR
&& ::iflags.hilite_pet
#endif
) {
painter.drawPixmap(QPoint(i*qt_settings->glyphs().width(), j*qt_settings->glyphs().height()), pet_annotation);
}
}
}
painter.setFont(font());
} else {
for (int j=garea.top(); j<=garea.bottom(); j++) {
for (int i=garea.left(); i<=garea.right(); i++) {
unsigned short g=Glyph(i,j);
qt_settings->glyphs().drawCell(painter, g, i, j);
if (glyph_is_pet(g)
#ifdef TEXTCOLOR
&& ::iflags.hilite_pet
#endif
) {
painter.drawPixmap(QPoint(i*qt_settings->glyphs().width(), j*qt_settings->glyphs().height()), pet_annotation);
}
}
}
}
if (garea.contains(cursor)) {
if (Is_rogue_level(&u.uz)) {
#ifdef TEXTCOLOR
painter.setPen( Qt::white );
#else
painter.setPen( Qt::green ); // REALLY primitive
#endif
} else
{
int hp100;
if (u.mtimedone) {
hp100=u.mhmax ? u.mh*100/u.mhmax : 100;
} else {
hp100=u.uhpmax ? u.uhp*100/u.uhpmax : 100;
}
if (hp100 > 75) painter.setPen(Qt::white);
else if (hp100 > 50) painter.setPen(Qt::yellow);
else if (hp100 > 25) painter.setPen(QColor(0xff,0xbf,0x00)); // orange
else if (hp100 > 10) painter.setPen(Qt::red);
else painter.setPen(Qt::magenta);
}
painter.drawRect(
cursor.x()*qt_settings->glyphs().width(),cursor.y()*qt_settings->glyphs().height(),
qt_settings->glyphs().width()-1,qt_settings->glyphs().height()-1);
}
#if 0
if (area.intersects(messages_rect)) {
painter.setPen(Qt::black);
painter.drawText(viewport.contentsX()+1,viewport.contentsY()+1,
viewport.width(),0, Qt::TextWordWrap|Qt::AlignTop|Qt::AlignLeft|Qt::TextDontClip, messages);
painter.setPen(Qt::white);
painter.drawText(viewport.contentsX(),viewport.contentsY(),
viewport.width(),0, Qt::TextWordWrap|Qt::AlignTop|Qt::AlignLeft|Qt::TextDontClip, messages);
}
#endif
painter.end();
}
bool NetHackQtMapViewport::DrawWalls(
QPainter& painter,
int x, int y, int w, int h,
unsigned ch)
{
enum
{
w_left = 0x01,
w_right = 0x02,
w_up = 0x04,
w_down = 0x08,
w_sq_top = 0x10,
w_sq_bottom = 0x20,
w_sq_left = 0x40,
w_sq_right = 0x80
};
unsigned linewidth;
unsigned walls;
int x1, y1, x2, y2, x3, y3;
linewidth = ((w < h) ? w : h)/8;
if (linewidth == 0) linewidth = 1;
// Single walls
walls = 0;
switch (ch)
{
case 0x2500: // BOX DRAWINGS LIGHT HORIZONTAL
walls = w_left | w_right;
break;
case 0x2502: // BOX DRAWINGS LIGHT VERTICAL
walls = w_up | w_down;
break;
case 0x250C: // BOX DRAWINGS LIGHT DOWN AND RIGHT
walls = w_down | w_right;
break;
case 0x2510: // BOX DRAWINGS LIGHT DOWN AND LEFT
walls = w_down | w_left;
break;
case 0x2514: // BOX DRAWINGS LIGHT UP AND RIGHT
walls = w_up | w_right;
break;
case 0x2518: // BOX DRAWINGS LIGHT UP AND LEFT
walls = w_up | w_left;
break;
case 0x251C: // BOX DRAWINGS LIGHT VERTICAL AND RIGHT
walls = w_up | w_down | w_right;
break;
case 0x2524: // BOX DRAWINGS LIGHT VERTICAL AND LEFT
walls = w_up | w_down | w_left;
break;
case 0x252C: // BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
walls = w_down | w_left | w_right;
break;
case 0x2534: // BOX DRAWINGS LIGHT UP AND HORIZONTAL
walls = w_up | w_left | w_right;
break;
case 0x253C: // BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
walls = w_up | w_down | w_left | w_right;
break;
}
if (walls != 0)
{
x1 = x + w/2;
switch (walls & (w_up | w_down))
{
case w_up:
painter.drawLine(x1, y, x1, y+h/2);
break;
case w_down:
painter.drawLine(x1, y+h/2, x1, y+h-1);
break;
case w_up | w_down:
painter.drawLine(x1, y, x1, y+h-1);
break;
}
y1 = y + h/2;
switch (walls & (w_left | w_right))
{
case w_left:
painter.drawLine(x, y1, x+w/2, y1);
break;
case w_right:
painter.drawLine(x+w/2, y1, x+w-1, y1);
break;
case w_left | w_right:
painter.drawLine(x, y1, x+w-1, y1);
break;
}
return true;
}
// Double walls
walls = 0;
switch (ch)
{
case 0x2550: // BOX DRAWINGS DOUBLE HORIZONTAL
walls = w_left | w_right | w_sq_top | w_sq_bottom;
break;
case 0x2551: // BOX DRAWINGS DOUBLE VERTICAL
walls = w_up | w_down | w_sq_left | w_sq_right;
break;
case 0x2554: // BOX DRAWINGS DOUBLE DOWN AND RIGHT
walls = w_down | w_right | w_sq_top | w_sq_left;
break;
case 0x2557: // BOX DRAWINGS DOUBLE DOWN AND LEFT
walls = w_down | w_left | w_sq_top | w_sq_right;
break;
case 0x255A: // BOX DRAWINGS DOUBLE UP AND RIGHT
walls = w_up | w_right | w_sq_bottom | w_sq_left;
break;
case 0x255D: // BOX DRAWINGS DOUBLE UP AND LEFT
walls = w_up | w_left | w_sq_bottom | w_sq_right;
break;
case 0x2560: // BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
walls = w_up | w_down | w_right | w_sq_left;
break;
case 0x2563: // BOX DRAWINGS DOUBLE VERTICAL AND LEFT
walls = w_up | w_down | w_left | w_sq_right;
break;
case 0x2566: // BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
walls = w_down | w_left | w_right | w_sq_top;
break;
case 0x2569: // BOX DRAWINGS DOUBLE UP AND HORIZONTAL
walls = w_up | w_left | w_right | w_sq_bottom;
break;
case 0x256C: // BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
walls = w_up | w_down | w_left | w_right;
break;
}
if (walls != 0)
{
x1 = x + w/2 - linewidth;
x2 = x + w/2 + linewidth;
x3 = x + w - 1;
y1 = y + h/2 - linewidth;
y2 = y + h/2 + linewidth;
y3 = y + h - 1;
if (walls & w_up)
{
painter.drawLine(x1, y, x1, y1);
painter.drawLine(x2, y, x2, y1);
}
if (walls & w_down)
{
painter.drawLine(x1, y2, x1, y3);
painter.drawLine(x2, y2, x2, y3);
}
if (walls & w_left)
{
painter.drawLine(x, y1, x1, y1);
painter.drawLine(x, y2, x1, y2);
}
if (walls & w_right)
{
painter.drawLine(x2, y1, x3, y1);
painter.drawLine(x2, y2, x3, y2);
}
if (walls & w_sq_top)
{
painter.drawLine(x1, y1, x2, y1);
}
if (walls & w_sq_bottom)
{
painter.drawLine(x1, y2, x2, y2);
}
if (walls & w_sq_left)
{
painter.drawLine(x1, y1, x1, y2);
}
if (walls & w_sq_right)
{
painter.drawLine(x2, y1, x2, y2);
}
return true;
}
// Solid blocks
if (0x2591 <= ch && ch <= 0x2593)
{
unsigned shade = ch - 0x2590;
QColor rgb(painter.pen().color());
QColor rgb2(
rgb.red()*shade/4,
rgb.green()*shade/4,
rgb.blue()*shade/4);
painter.fillRect(x, y, w, h, rgb2);
return true;
}
return false;
}
void NetHackQtMapViewport::mousePressEvent(QMouseEvent* event)
{
clicksink.Put(
event->pos().x()/qt_settings->glyphs().width(),
event->pos().y()/qt_settings->glyphs().height(),
event->button()==Qt::LeftButton ? CLICK_1 : CLICK_2
);
qApp->exit();
}
void NetHackQtMapViewport::updateTiles()
{
change.clear();
change.add(0,0,COLNO,ROWNO);
delete rogue_font; rogue_font = NULL;
}
QSize NetHackQtMapViewport::sizeHint() const
{
return QSize(
qt_settings->glyphs().width() * COLNO,
qt_settings->glyphs().height() * ROWNO);
}
QSize NetHackQtMapViewport::minimumSizeHint() const
{
return sizeHint();
}
void NetHackQtMapViewport::clickCursor()
{
clicksink.Put(cursor.x(),cursor.y(),CLICK_1);
qApp->exit();
}
void NetHackQtMapViewport::Clear()
{
unsigned short stone=cmap_to_glyph(S_stone);
for (int j=0; j<ROWNO; j++) {
for (int i=0; i<COLNO; i++) {
Glyph(i,j)=stone;
}
}
change.clear();
change.add(0,0,COLNO,ROWNO);
}
void NetHackQtMapViewport::Display(bool block)
{
for (int i=0; i<change.clusters(); i++) {
const QRect& ch=change[i];
repaint(
ch.x()*qt_settings->glyphs().width(),
ch.y()*qt_settings->glyphs().height(),
ch.width()*qt_settings->glyphs().width(),
ch.height()*qt_settings->glyphs().height()
);
}
change.clear();
if (block) {
yn_function("Press a key when done viewing",0,'\0');
}
}
void NetHackQtMapViewport::CursorTo(int x,int y)
{
Changed(cursor.x(),cursor.y());
cursor.setX(x);
cursor.setY(y);
Changed(cursor.x(),cursor.y());
}
void NetHackQtMapViewport::PrintGlyph(int x,int y,int glyph)
{
Glyph(x,y)=glyph;
Changed(x,y);
}
void NetHackQtMapViewport::Changed(int x, int y)
{
change.add(x,y);
}
NetHackQtMapWindow2::NetHackQtMapWindow2(NetHackQtClickBuffer& click_sink) :
QScrollArea(NULL),
m_viewport(new NetHackQtMapViewport(click_sink))
{
QPalette palette;
palette.setColor(backgroundRole(), Qt::black);
setPalette(palette);
setWidget(m_viewport);
connect(qt_settings,SIGNAL(tilesChanged()),this,SLOT(updateTiles()));
updateTiles();
}
void NetHackQtMapWindow2::updateTiles()
{
NetHackQtGlyphs& glyphs = qt_settings->glyphs();
int gw = glyphs.width();
int gh = glyphs.height();
// Be exactly the size we want to be - full map...
m_viewport->resize(COLNO*gw,ROWNO*gh);
verticalScrollBar()->setSingleStep(gh);
verticalScrollBar()->setPageStep(gh);
horizontalScrollBar()->setSingleStep(gw);
horizontalScrollBar()->setPageStep(gw);
m_viewport->updateTiles();
Display(false);
emit resized();
}
void NetHackQtMapWindow2::clearMessages()
{
messages = "";
update(messages_rect);
messages_rect = QRect();
}
void NetHackQtMapWindow2::putMessage(int attr, const QString& text)
{
if ( !messages.isEmpty() )
messages += "\n";
messages += QString(text).replace(QChar(0x200B), "");
QFontMetrics fm = fontMetrics();
#if 0
messages_rect = fm.boundingRect(viewport.contentsX(),viewport.contentsY(),viewport.width(),0, Qt::TextWordWrap|Qt::AlignTop|Qt::AlignLeft|Qt::TextDontClip, messages);
update(messages_rect);
#endif
}
void NetHackQtMapWindow2::clickCursor()
{
m_viewport->clickCursor();
}
QWidget *NetHackQtMapWindow2::Widget()
{
return this;
}
void NetHackQtMapWindow2::Clear()
{
m_viewport->Clear();
}
void NetHackQtMapWindow2::Display(bool block)
{
m_viewport->Display(block);
}
void NetHackQtMapWindow2::CursorTo(int x,int y)
{
m_viewport->CursorTo(x, y);
}
void NetHackQtMapWindow2::PutStr(int attr, const QString& text)
{
puts("unexpected PutStr in MapWindow");
}
void NetHackQtMapWindow2::ClipAround(int x,int y)
{
// Convert to pixel of center of tile
x=x*qt_settings->glyphs().width()+qt_settings->glyphs().width()/2;
y=y*qt_settings->glyphs().height()+qt_settings->glyphs().height()/2;
// Then ensure that pixel is visible
ensureVisible(x,y,width()*0.45,height()*0.45);
}
void NetHackQtMapWindow2::PrintGlyph(int x,int y,int glyph)
{
m_viewport->PrintGlyph(x, y, glyph);
}
#if 0 //RLC
// XXX Hmmm... crash after saving bones file if Map window is
// XXX deleted. Strange bug somewhere.
bool NetHackQtMapWindow::Destroy() { return false; }
NetHackQtMapWindow::NetHackQtMapWindow(NetHackQtClickBuffer& click_sink) :
clicksink(click_sink),
change(10),
rogue_font(0)
{
viewport.addChild(this);
QPalette palette;
palette.setColor(backgroundRole(), Qt::black);
setPalette(palette);
palette.setColor(viewport.backgroundRole(), Qt::black);
viewport.setPalette(palette);
pet_annotation = QPixmap(qt_compact_mode ? pet_mark_small_xpm : pet_mark_xpm);
cursor.setX(0);
cursor.setY(0);
Clear();
connect(qt_settings,SIGNAL(tilesChanged()),this,SLOT(updateTiles()));
connect(&viewport, SIGNAL(contentsMoving(int,int)), this,
SLOT(moveMessages(int,int)));
updateTiles();
//setFocusPolicy(Qt::StrongFocus);
}
void NetHackQtMapWindow::moveMessages(int x, int y)
{
QRect u = messages_rect;
messages_rect.moveTopLeft(QPoint(x,y));
u |= messages_rect;
update(u);
}
void NetHackQtMapWindow::clearMessages()
{
messages = "";
update(messages_rect);
messages_rect = QRect();
}
void NetHackQtMapWindow::putMessage(int attr, const QString& text)
{
if ( !messages.isEmpty() )
messages += "\n";
messages += QString(text).replace(QChar(0x200B), "");
QFontMetrics fm = fontMetrics();
messages_rect = fm.boundingRect(viewport.contentsX(),viewport.contentsY(),viewport.width(),0, Qt::TextWordWrap|Qt::AlignTop|Qt::AlignLeft|Qt::TextDontClip, messages);
update(messages_rect);
}
void NetHackQtMapWindow::updateTiles()
{
NetHackQtGlyphs& glyphs = qt_settings->glyphs();
int gw = glyphs.width();
int gh = glyphs.height();
// Be exactly the size we want to be - full map...
resize(COLNO*gw,ROWNO*gh);
viewport.verticalScrollBar()->setSingleStep(gh);
viewport.verticalScrollBar()->setPageStep(gh);
viewport.horizontalScrollBar()->setSingleStep(gw);
viewport.horizontalScrollBar()->setPageStep(gw);
/*
viewport.setMaximumSize(
gw*COLNO + viewport.verticalScrollBar()->width(),
gh*ROWNO + viewport.horizontalScrollBar()->height()
);
*/
viewport.updateScrollBars();
change.clear();
change.add(0,0,COLNO,ROWNO);
delete rogue_font; rogue_font = 0;
Display(false);
emit resized();
}
NetHackQtMapWindow::~NetHackQtMapWindow()
{
// Remove from viewport porthole, since that is a destructible member.
viewport.removeChild(this);
setParent(0,0);
}
QWidget* NetHackQtMapWindow::Widget()
{
return &viewport;
}
void NetHackQtMapWindow::Scroll(int dx, int dy)
{
if (viewport.horizontalScrollBar()->isVisible()) {
while (dx<0) { viewport.horizontalScrollBar()->triggerAction(QAbstractSlider::SliderPageStepSub); dx++; }
while (dx>0) { viewport.horizontalScrollBar()->triggerAction(QAbstractSlider::SliderPageStepAdd); dx--; }
}
if (viewport.verticalScrollBar()->isVisible()) {
while (dy<0) { viewport.verticalScrollBar()->triggerAction(QAbstractSlider::SliderPageStepSub); dy++; }
while (dy>0) { viewport.verticalScrollBar()->triggerAction(QAbstractSlider::SliderPageStepAdd); dy--; }
}
}
void NetHackQtMapWindow::Clear()
{
unsigned short stone=cmap_to_glyph(S_stone);
for (int j=0; j<ROWNO; j++) {
for (int i=0; i<COLNO; i++) {
Glyph(i,j)=stone;
}
}
change.clear();
change.add(0,0,COLNO,ROWNO);
}
void NetHackQtMapWindow::clickCursor()
{
clicksink.Put(cursor.x(),cursor.y(),CLICK_1);
qApp->exit();
}
void NetHackQtMapWindow::mousePressEvent(QMouseEvent* event)
{
clicksink.Put(
event->pos().x()/qt_settings->glyphs().width(),
event->pos().y()/qt_settings->glyphs().height(),
event->button()==Qt::LeftButton ? CLICK_1 : CLICK_2
);
qApp->exit();
}
void NetHackQtMapWindow::paintEvent(QPaintEvent* event)
{
QRect area=event->rect();
QRect garea;
garea.setCoords(
std::max(0,area.left()/qt_settings->glyphs().width()),
std::max(0,area.top()/qt_settings->glyphs().height()),
std::min(COLNO-1,area.right()/qt_settings->glyphs().width()),
std::min(ROWNO-1,area.bottom()/qt_settings->glyphs().height())
);
QPainter painter;
painter.begin(this);
if (is_rogue_level(&u.uz) || iflags.wc_ascii_map) {
// You enter a VERY primitive world!
painter.setClipRect( event->rect() ); // (normally we don't clip)
painter.fillRect( event->rect(), Qt::black );
if ( !rogue_font ) {
// Find font...
int pts = 5;
QString fontfamily = iflags.wc_font_map
? iflags.wc_font_map : "Courier";
bool bold = false;
if ( fontfamily.right(5).toLower() == "-bold" ) {
fontfamily.truncate(fontfamily.length()-5);
bold = true;
}
while ( pts < 32 ) {
QFont f(fontfamily, pts, bold ? QFont::Bold : QFont::Normal);
painter.setFont(QFont(fontfamily, pts));
QFontMetrics fm = painter.fontMetrics();
if ( fm.width("M") > qt_settings->glyphs().width() )
break;
if ( fm.height() > qt_settings->glyphs().height() )
break;
pts++;
}
rogue_font = new QFont(fontfamily,pts-1);
}
painter.setFont(*rogue_font);
for (int j=garea.top(); j<=garea.bottom(); j++) {
for (int i=garea.left(); i<=garea.right(); i++) {
unsigned short g=Glyph(i,j);
int color;
char32_t ch;
unsigned special;
painter.setPen( Qt::green );
/* map glyph to character and color */
mapglyph(g, &ch, &color, &special, i, j);
#ifdef TEXTCOLOR
painter.setPen( nhcolor_to_pen(color) );
#endif
painter.drawText(
i*qt_settings->glyphs().width(),
j*qt_settings->glyphs().height(),
qt_settings->glyphs().width(),
qt_settings->glyphs().height(),
Qt::AlignCenter,
QString(QChar(ch)).left(1)
);
if (glyph_is_pet(g)
#ifdef TEXTCOLOR
&& ::iflags.hilite_pet
#endif
) {
painter.drawPixmap(QPoint(i*qt_settings->glyphs().width(), j*qt_settings->glyphs().height()), pet_annotation);
}
}
}
painter.setFont(font());
} else {
for (int j=garea.top(); j<=garea.bottom(); j++) {
for (int i=garea.left(); i<=garea.right(); i++) {
unsigned short g=Glyph(i,j);
qt_settings->glyphs().drawCell(painter, g, i, j);
if (glyph_is_pet(g)
#ifdef TEXTCOLOR
&& ::iflags.hilite_pet
#endif
) {
painter.drawPixmap(QPoint(i*qt_settings->glyphs().width(), j*qt_settings->glyphs().height()), pet_annotation);
}
}
}
}
if (garea.contains(cursor)) {
if (Is_rogue_level(&u.uz)) {
#ifdef TEXTCOLOR
painter.setPen( Qt::white );
#else
painter.setPen( Qt::green ); // REALLY primitive
#endif
} else
{
int hp100;
if (u.mtimedone) {
hp100=u.mhmax ? u.mh*100/u.mhmax : 100;
} else {
hp100=u.uhpmax ? u.uhp*100/u.uhpmax : 100;
}
if (hp100 > 75) painter.setPen(Qt::white);
else if (hp100 > 50) painter.setPen(Qt::yellow);
else if (hp100 > 25) painter.setPen(QColor(0xff,0xbf,0x00)); // orange
else if (hp100 > 10) painter.setPen(Qt::red);
else painter.setPen(Qt::magenta);
}
painter.drawRect(
cursor.x()*qt_settings->glyphs().width(),cursor.y()*qt_settings->glyphs().height(),
qt_settings->glyphs().width()-1,qt_settings->glyphs().height()-1);
}
if (area.intersects(messages_rect)) {
painter.setPen(Qt::black);
painter.drawText(viewport.contentsX()+1,viewport.contentsY()+1,
viewport.width(),0, Qt::TextWordWrap|Qt::AlignTop|Qt::AlignLeft|Qt::TextDontClip, messages);
painter.setPen(Qt::white);
painter.drawText(viewport.contentsX(),viewport.contentsY(),
viewport.width(),0, Qt::TextWordWrap|Qt::AlignTop|Qt::AlignLeft|Qt::TextDontClip, messages);
}
painter.end();
}
void NetHackQtMapWindow::Display(bool block)
{
for (int i=0; i<change.clusters(); i++) {
const QRect& ch=change[i];
repaint(
ch.x()*qt_settings->glyphs().width(),
ch.y()*qt_settings->glyphs().height(),
ch.width()*qt_settings->glyphs().width(),
ch.height()*qt_settings->glyphs().height()
);
}
change.clear();
if (block) {
yn_function("Press a key when done viewing",0,'\0');
}
}
void NetHackQtMapWindow::CursorTo(int x,int y)
{
Changed(cursor.x(),cursor.y());
cursor.setX(x);
cursor.setY(y);
Changed(cursor.x(),cursor.y());
}
void NetHackQtMapWindow::PutStr(int attr, const QString& text)
{
puts("unexpected PutStr in MapWindow");
}
void NetHackQtMapWindow::ClipAround(int x,int y)
{
// Convert to pixel of center of tile
x=x*qt_settings->glyphs().width()+qt_settings->glyphs().width()/2;
y=y*qt_settings->glyphs().height()+qt_settings->glyphs().height()/2;
// Then ensure that pixel is visible
viewport.center(x,y,0.45,0.45);
}
void NetHackQtMapWindow::PrintGlyph(int x,int y,int glyph)
{
Glyph(x,y)=glyph;
Changed(x,y);
}
//void NetHackQtMapWindow::PrintGlyphCompose(int x,int y,int glyph1, int glyph2)
//{
// TODO: composed graphics
//}
void NetHackQtMapWindow::Changed(int x, int y)
{
change.add(x,y);
}
#endif
} // namespace nethack_qt4
+81
View File
@@ -0,0 +1,81 @@
// Copyright (c) Warwick Allison, 1999.
// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
// NetHack may be freely redistributed. See license for details.
// qt4map.h -- the map window
#ifndef QT4MAP_H
#define QT4MAP_H
#include "qt4win.h"
#include "qt4clust.h"
namespace nethack_qt4 {
class NetHackQtClickBuffer;
class NetHackQtMapViewport : public QWidget {
Q_OBJECT
public:
NetHackQtMapViewport(NetHackQtClickBuffer& click_sink);
~NetHackQtMapViewport(void);
protected:
virtual void paintEvent(QPaintEvent* event);
bool DrawWalls(QPainter& painter, int x, int y, int w, int h, unsigned ch);
virtual QSize sizeHint() const;
virtual QSize minimumSizeHint() const;
virtual void mousePressEvent(QMouseEvent* event);
private:
QFont *rogue_font;
unsigned short glyph[ROWNO][COLNO];
unsigned short& Glyph(int x, int y) { return glyph[y][x]; }
QPoint cursor;
QPixmap pet_annotation;
NetHackQtClickBuffer& clicksink;
Clusterizer change;
void clickCursor();
void Clear();
void Display(bool block);
void CursorTo(int x,int y);
void PrintGlyph(int x,int y,int glyph);
void Changed(int x, int y);
void updateTiles();
// NetHackQtMapWindow2 passes through many calls to the viewport
friend class NetHackQtMapWindow2;
};
class NetHackQtMapWindow2 : public QScrollArea, public NetHackQtWindow {
Q_OBJECT
public:
NetHackQtMapWindow2(NetHackQtClickBuffer& click_sink);
void clearMessages();
void putMessage(int attr, const QString& text);
void clickCursor();
virtual QWidget *Widget();
virtual void Clear();
virtual void Display(bool block);
virtual void CursorTo(int x,int y);
virtual void PutStr(int attr, const QString& text);
virtual void ClipAround(int x,int y);
virtual void PrintGlyph(int x,int y,int glyph);
signals:
void resized();
private slots:
void updateTiles();
private:
NetHackQtMapViewport *m_viewport;
QRect messages_rect;
QString messages;
};
} // namespace nethack_qt4
#endif
+840
View File
@@ -0,0 +1,840 @@
// Copyright (c) Warwick Allison, 1999.
// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
// NetHack may be freely redistributed. See license for details.
// qt4menu.cpp -- a menu or text-list widget
extern "C" {
#include "hack.h"
}
#undef Invisible
#undef Warning
#undef index
#undef msleep
#undef rindex
#undef wizard
#undef yn
#undef min
#undef max
#include <QtGui/QtGui>
#if QT_VERSION >= 0x050000
#include <QtWidgets/QtWidgets>
#endif
#include "qt4menu.h"
#include "qt4menu.moc"
#include "qt4glyph.h"
#include "qt4set.h"
#include "qt4streq.h"
#include "qt4str.h"
// temporary
extern "C" int qt_compact_mode;
// end temporary
#ifdef MENU_COLOR
extern "C" struct menucoloring *menu_colorings;
#endif
namespace nethack_qt4 {
// temporary
void centerOnMain( QWidget* w );
// end temporary
static boolean get_menu_coloring(char const *str, int *color, int *attr);
QSize NetHackQtTextListBox::sizeHint() const
{
QScrollBar *hscroll = horizontalScrollBar();
int hsize = hscroll ? hscroll->height() : 0;
return QSize(TotalWidth()+hsize, TotalHeight()+hsize);
}
int NetHackQtMenuListBox::TotalWidth() const
{
int width = 0;
for (int col = 0; col < columnCount(); ++col) {
width += columnWidth(col);
}
return width;
}
int NetHackQtMenuListBox::TotalHeight() const
{
int height = 0;
for (int row = 0; row < rowCount(); ++row) {
height += rowHeight(row);
}
return height;
}
QSize NetHackQtMenuListBox::sizeHint() const
{
QScrollBar *hscroll = horizontalScrollBar();
int hsize = hscroll ? hscroll->height() : 0;
return QSize(TotalWidth()+hsize, TotalHeight()+hsize);
}
// Table view columns:
//
// [pick-count] [accel] [glyph] [string]
//
// Maybe accel should be near string. We'll see.
// pick-count normally blank.
// double-clicking or click-on-count gives pop-up entry
// string is green when selected
//
NetHackQtMenuWindow::NetHackQtMenuWindow(QWidget *parent) :
QDialog(parent),
table(new NetHackQtMenuListBox()),
prompt(0),
counting(false)
{
QGridLayout *grid = new QGridLayout();
table->setColumnCount(5);
table->setFrameStyle(QFrame::Panel|QFrame::Sunken);
table->setLineWidth(2);
table->setShowGrid(false);
table->horizontalHeader()->hide();
table->verticalHeader()->hide();
ok=new QPushButton("Ok");
connect(ok,SIGNAL(clicked()),this,SLOT(accept()));
cancel=new QPushButton("Cancel");
connect(cancel,SIGNAL(clicked()),this,SLOT(reject()));
all=new QPushButton("All");
connect(all,SIGNAL(clicked()),this,SLOT(All()));
none=new QPushButton("None");
connect(none,SIGNAL(clicked()),this,SLOT(ChooseNone()));
invert=new QPushButton("Invert");
connect(invert,SIGNAL(clicked()),this,SLOT(Invert()));
search=new QPushButton("Search");
connect(search,SIGNAL(clicked()),this,SLOT(Search()));
QPoint pos(0,ok->height());
move(pos);
prompt.setParent(this,0);
prompt.move(pos);
grid->addWidget(ok, 0, 0);
grid->addWidget(cancel, 0, 1);
grid->addWidget(all, 0, 2);
grid->addWidget(none, 0, 3);
grid->addWidget(invert, 0, 4);
grid->addWidget(search, 0, 5);
grid->addWidget(&prompt, 1, 0, 1, 7);
grid->addWidget(table, 2, 0, 1, 7);
grid->setColumnStretch(6, 1);
grid->setRowStretch(2, 1);
setFocusPolicy(Qt::StrongFocus);
table->setFocusPolicy(Qt::NoFocus);
setLayout(grid);
}
NetHackQtMenuWindow::~NetHackQtMenuWindow()
{
}
QWidget* NetHackQtMenuWindow::Widget() { return this; }
void NetHackQtMenuWindow::StartMenu()
{
table->setRowCount((itemcount=0));
next_accel=0;
has_glyphs=false;
}
NetHackQtMenuWindow::MenuItem::MenuItem() :
str("")
{
}
NetHackQtMenuWindow::MenuItem::~MenuItem()
{
}
void NetHackQtMenuWindow::AddMenu(int glyph, const ANY_P* identifier,
char ch, char gch, int attr, const QString& str, bool presel)
{
if (!ch && identifier->a_void!=0) {
// Supply a keyboard accelerator. Limited supply.
static char accel[]="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
if (accel[next_accel]) {
ch=accel[next_accel++];
}
}
if ((int)itemlist.size() < itemcount+1) {
itemlist.resize(itemcount*4+10);
}
itemlist[itemcount].glyph=glyph;
itemlist[itemcount].identifier=*identifier;
itemlist[itemcount].ch=ch;
itemlist[itemcount].gch=gch;
itemlist[itemcount].attr=attr;
itemlist[itemcount].str=str;
itemlist[itemcount].selected=presel;
itemlist[itemcount].count=-1;
itemlist[itemcount].color = -1;
// Display the boulder symbol correctly
if (str.left(8) == "boulder\t") {
int bracket = str.indexOf('[');
if (bracket != -1) {
itemlist[itemcount].str = str.left(bracket+1)
+ QChar(cp437(str.at(bracket+1).unicode()))
+ str.mid(bracket+2);
}
}
#ifdef MENU_COLOR
int mcolor, mattr;
if (attr == 0
&& get_menu_coloring(str.toLatin1().constData(), &mcolor, &mattr)) {
itemlist[itemcount].attr = mattr;
itemlist[itemcount].color = mcolor;
}
#endif
++itemcount;
if (glyph!=NO_GLYPH) has_glyphs=true;
}
#ifdef MENU_COLOR
static boolean
get_menu_coloring(char const *str, int *color, int *attr)
{
struct menucoloring *tmpmc;
if (iflags.use_menu_color)
for (tmpmc = menu_colorings; tmpmc; tmpmc = tmpmc->next)
# ifdef MENU_COLOR_REGEX
if (re_search(&tmpmc->match, str, strlen(str), 0, 9999, 0) >= 0) {
# else
if (pmatch(tmpmc->match, str)) {
# endif
*color = tmpmc->color;
*attr = tmpmc->attr;
return TRUE;
}
return FALSE;
}
#endif /* MENU_COLOR */
void NetHackQtMenuWindow::EndMenu(const QString& p)
{
prompt.setText(p);
promptstr = p;
}
int NetHackQtMenuWindow::SelectMenu(int h, MENU_ITEM_P **menu_list)
{
QFont tablefont(qt_settings->normalFont());
table->setFont(tablefont);
table->setRowCount(itemcount);
how=h;
ok->setEnabled(how!=PICK_ONE);ok->setDefault(how!=PICK_ONE);
cancel->setEnabled(how!=PICK_NONE);
all->setEnabled(how==PICK_ANY);
none->setEnabled(how==PICK_ANY);
invert->setEnabled(how==PICK_ANY);
search->setEnabled(how!=PICK_NONE);
setResult(-1);
// Set contents of table
QFontMetrics fm(table->font());
for (int i = 0; i < 5; i++) {
table->setColumnWidth(i, 0);
}
for (int i = 0; i < itemcount; i++) {
AddRow(i, itemlist[i]);
}
// Determine column widths
std::vector<int> col_widths;
for (std::size_t i = 0; i < itemlist.size(); ++i) {
QStringList columns = itemlist[i].str.split("\t");
if (!itemlist[i].Selectable() && columns.size() == 1)
{
// Nonselectable line with no column dividers
// Assume this is a section header
continue;
}
for (std::size_t j = 0U; j < columns.size(); ++j) {
int w = fm.width(columns[j] + " \t");
if (j >= col_widths.size()) {
col_widths.push_back(w);
} else if (col_widths[j] < w) {
col_widths[j] = w;
}
}
}
// Pad each column to its column width
for (std::size_t i = 0U; i < itemlist.size(); ++i) {
QTableWidgetItem *twi = table->item(i, 4);
if (twi == NULL) { continue; }
QString text = twi->text();
QStringList columns = text.split("\t");
for (std::size_t j = 0U; j+1U < columns.size(); ++j) {
columns[j] += "\t";
int width = col_widths[j];
while (fm.width(columns[j]) < width) {
columns[j] += "\t";
}
}
text = columns.join("");
twi->setText(text);
WidenColumn(4, fm.width(text));
}
// FIXME: size for compact mode
//resize(this->width(), parent()->height()*7/8);
move(0, 0);
adjustSize();
centerOnMain(this);
exec();
int result=this->result();
*menu_list=0;
if (result>0 && how!=PICK_NONE) {
if (how==PICK_ONE) {
int i;
for (i=0; i<itemcount && !isSelected(i); i++)
;
if (i<itemcount) {
*menu_list=(MENU_ITEM_P *)alloc(sizeof(MENU_ITEM_P)*1);
(*menu_list)[0].item=itemlist[i].identifier;
(*menu_list)[0].count=count(i);
return 1;
} else {
return 0;
}
} else {
int selcount=0;
for (int i=0; i<itemcount; i++)
if (isSelected(i)) selcount++;
if (selcount) {
*menu_list=(MENU_ITEM_P *)alloc(sizeof(MENU_ITEM_P)*selcount);
int j=0;
for (int i=0; i<itemcount; i++) {
if (isSelected(i)) {
(*menu_list)[j].item=itemlist[i].identifier;
(*menu_list)[j].count=count(i);
j++;
}
}
return selcount;
} else {
return 0;
}
}
} else {
return -1;
}
}
void NetHackQtMenuWindow::AddRow(int row, const MenuItem& mi)
{
static const QColor colors[] = {
QColor(64, 64, 64),
QColor(Qt::red),
QColor(0, 191, 0),
QColor(127, 127, 0),
QColor(Qt::blue),
QColor(Qt::magenta),
QColor(Qt::cyan),
QColor(Qt::gray),
QColor(Qt::white),
QColor(255, 127, 0),
QColor(127, 255, 127),
QColor(Qt::yellow),
QColor(127, 127, 255),
QColor(255, 127, 255),
QColor(127, 255, 255),
QColor(Qt::white)
};
QFontMetrics fm(table->font());
QTableWidgetItem *twi;
if (mi.Selectable() && how != PICK_NONE) {
// Count
twi = new QTableWidgetItem("");
table->setItem(row, 0, twi);
twi->setFlags(Qt::ItemIsEnabled);
WidenColumn(0, fm.width("999999"));
// Check box, set if selected
QCheckBox *cb = new QCheckBox();
cb->setChecked(mi.selected);
cb->setFocusPolicy(Qt::NoFocus);
if (how == PICK_ONE)
connect(cb, SIGNAL(clicked(bool)), this, SLOT(DoSelection(bool)));
table->setCellWidget(row, 1, cb);
WidenColumn(1, cb->width());
}
if (mi.glyph != NO_GLYPH) {
// Icon
QPixmap pm(qt_settings->glyphs().glyph(mi.glyph));
twi = new QTableWidgetItem(QIcon(pm), "");
table->setItem(row, 2, twi);
twi->setFlags(Qt::ItemIsEnabled);
WidenColumn(2, pm.width());
}
QString letter, text(mi.str);
if (mi.ch != 0) {
// Letter specified
letter = QString(mi.ch) + " - ";
}
else {
// Letter is left blank, except for skills display when # and * are
// presented
if (text.startsWith(" ")) {
// If mi.str starts with " ", it's meant to line up with lines
// that have a letter; we don't want that here
text = text.mid(4);
} else if (text.startsWith(" #") || text.startsWith(" *")) {
// Put the * or # in the letter column
letter = text.left(4);
text = text.mid(4);
}
}
twi = new QTableWidgetItem(letter);
table->setItem(row, 3, twi);
table->item(row, 3)->setFlags(Qt::ItemIsEnabled);
WidenColumn(3, fm.width(letter));
twi = new QTableWidgetItem(text);
table->setItem(row, 4, twi);
table->item(row, 4)->setFlags(Qt::ItemIsEnabled);
WidenColumn(4, fm.width(text));
#ifdef MENU_COLOR
if (mi.color != -1) {
twi->setForeground(colors[mi.color]);
}
#endif
QFont itemfont(table->font());
switch (mi.attr) {
case ATR_BOLD:
itemfont.setWeight(QFont::Bold);
twi->setFont(itemfont);
break;
case ATR_DIM:
twi->setFlags(Qt::NoItemFlags);
break;
case ATR_ULINE:
itemfont.setUnderline(true);
twi->setFont(itemfont);
break;
case ATR_INVERSE:
{
QBrush fg = twi->foreground();
QBrush bg = twi->background();
if (fg == bg) {
// default foreground and background come up the same for
// some unknown reason
twi->setForeground(Qt::white);
twi->setBackground(Qt::black);
} else {
twi->setForeground(bg);
twi->setBackground(fg);
}
}
break;
}
}
void NetHackQtMenuWindow::WidenColumn(int column, int width)
{
// need to add a bit so the whole column displays
width += 7;
if (table->columnWidth(column) < width) {
table->setColumnWidth(column, width);
}
}
void NetHackQtMenuWindow::InputCount(char key)
{
if (key == '\b')
{
if (counting)
{
if (countstr.isEmpty())
ClearCount();
else
countstr = countstr.mid(0, countstr.size() - 1);
}
}
else
{
counting = true;
countstr += QChar(key);
}
if (counting)
prompt.setText("Count: " + countstr);
}
void NetHackQtMenuWindow::ClearCount(void)
{
counting = false;
prompt.setText(promptstr);
countstr = "";
}
void NetHackQtMenuWindow::keyPressEvent(QKeyEvent* event)
{
QString text = event->text();
const QChar *uni = text.unicode();
for (unsigned k = 0; uni[k] != 0; k++) {
unsigned key = uni[k].unicode();
if (key=='\033') {
if (counting)
ClearCount();
else
reject();
} else if (key=='\r' || key=='\n' || key==' ')
accept();
else if (key==MENU_SEARCH)
Search();
else if (key==MENU_SELECT_ALL)
All();
else if (key==MENU_INVERT_ALL)
Invert();
else if (key==MENU_UNSELECT_ALL)
ChooseNone();
else if (('0' <= key && key <= '9') || key == '\b')
InputCount(key);
else {
for (int i=0; i<itemcount; i++) {
if (itemlist[i].ch == key || itemlist[i].gch == key)
ToggleSelect(i);
}
}
}
}
void NetHackQtMenuWindow::All()
{
for (int i=0; i<itemcount; i++) {
QTableWidgetItem *count = table->item(i, 0);
if (count != NULL) count->setText("");
QCheckBox *cb = dynamic_cast<QCheckBox *>(table->cellWidget(i, 1));
if (cb != NULL) cb->setChecked(true);
}
}
void NetHackQtMenuWindow::ChooseNone()
{
for (int i=0; i<itemcount; i++) {
QTableWidgetItem *count = table->item(i, 0);
if (count != NULL) count->setText("");
QCheckBox *cb = dynamic_cast<QCheckBox *>(table->cellWidget(i, 1));
if (cb != NULL) cb->setChecked(false);
}
}
void NetHackQtMenuWindow::Invert()
{
for (int i=0; i<itemcount; i++) {
QTableWidgetItem *count = table->item(i, 0);
if (count != NULL) count->setText("");
QCheckBox *cb = dynamic_cast<QCheckBox *>(table->cellWidget(i, 1));
if (cb != NULL) cb->setChecked(cb->checkState() == Qt::Unchecked);
}
}
void NetHackQtMenuWindow::Search()
{
NetHackQtStringRequestor requestor(this, "Search for:");
char line[256];
if (requestor.Get(line)) {
for (int i=0; i<itemcount; i++) {
if (itemlist[i].str.contains(line))
ToggleSelect(i);
}
}
}
void NetHackQtMenuWindow::ToggleSelect(int i)
{
if (itemlist[i].Selectable()) {
QCheckBox *cb = dynamic_cast<QCheckBox *>(table->cellWidget(i, 1));
if (cb == NULL) return;
cb->setChecked((counting && !countstr.isEmpty())
|| cb->checkState() == Qt::Unchecked);
QTableWidgetItem *count = table->item(i, 0);
if (count != NULL) count->setText(countstr);
ClearCount();
if (how==PICK_ONE) {
accept();
}
}
}
void NetHackQtMenuWindow::DoSelection(bool)
{
if (how == PICK_ONE) {
accept();
}
}
bool NetHackQtMenuWindow::isSelected(int row)
{
QCheckBox *cb = dynamic_cast<QCheckBox *>(table->cellWidget(row, 1));
return cb != NULL && cb->checkState() != Qt::Unchecked;
}
int NetHackQtMenuWindow::count(int row)
{
QTableWidgetItem *count = table->item(row, 0);
if (count == NULL) return -1;
QString cstr = count->text();
return cstr.isEmpty() ? -1 : cstr.toInt();
}
NetHackQtTextWindow::NetHackQtTextWindow(QWidget *parent) :
QDialog(parent),
use_rip(false),
str_fixed(false),
ok("Dismiss",this),
search("Search",this),
lines(new NetHackQtTextListBox(this)),
rip(this)
{
ok.setDefault(true);
connect(&ok,SIGNAL(clicked()),this,SLOT(accept()));
connect(&search,SIGNAL(clicked()),this,SLOT(Search()));
connect(qt_settings,SIGNAL(fontChanged()),this,SLOT(doUpdate()));
QVBoxLayout* vb = new QVBoxLayout(this);
vb->addWidget(&rip);
QHBoxLayout* hb = new QHBoxLayout();
vb->addLayout(hb);
hb->addWidget(&ok);
hb->addWidget(&search);
vb->addWidget(lines);
}
void NetHackQtTextWindow::doUpdate()
{
update();
}
NetHackQtTextWindow::~NetHackQtTextWindow()
{
}
QWidget* NetHackQtTextWindow::Widget()
{
return this;
}
bool NetHackQtTextWindow::Destroy()
{
return !isVisible();
}
void NetHackQtTextWindow::UseRIP(int how, time_t when)
{
// Code from X11 windowport
#define STONE_LINE_LEN 16 /* # chars that fit on one line */
#define NAME_LINE 0 /* line # for player name */
#define GOLD_LINE 1 /* line # for amount of gold */
#define DEATH_LINE 2 /* line # for death description */
#define YEAR_LINE 6 /* line # for year */
static char** rip_line=0;
if (!rip_line) {
rip_line=new char*[YEAR_LINE+1];
for (int i=0; i<YEAR_LINE+1; i++) {
rip_line[i]=new char[STONE_LINE_LEN+1];
}
}
/* Follows same algorithm as genl_outrip() */
char buf[BUFSZ];
char *dpx;
int line;
/* Put name on stone */
snprintf(rip_line[NAME_LINE], STONE_LINE_LEN+1, "%s", plname);
/* Put $ on stone */
snprintf(rip_line[GOLD_LINE], STONE_LINE_LEN+1, "%ld Au", money_cnt(invent));
/* Put together death description */
formatkiller(buf, sizeof buf, how, FALSE);
//str_copy(buf, killer, SIZE(buf));
/* Put death type on stone */
for (line=DEATH_LINE, dpx = buf; line<YEAR_LINE; line++) {
int i,i0;
char tmpchar;
if ( (i0=strlen(dpx)) > STONE_LINE_LEN) {
for(i = STONE_LINE_LEN;
((i0 > STONE_LINE_LEN) && i); i--)
if(dpx[i] == ' ') i0 = i;
if(!i) i0 = STONE_LINE_LEN;
}
tmpchar = dpx[i0];
dpx[i0] = 0;
str_copy(rip_line[line], dpx, STONE_LINE_LEN+1);
if (tmpchar != ' ') {
dpx[i0] = tmpchar;
dpx= &dpx[i0];
} else dpx= &dpx[i0+1];
}
/* Put year on stone */
snprintf(rip_line[YEAR_LINE], STONE_LINE_LEN+1, "%4d", getyear());
rip.setLines(rip_line,YEAR_LINE+1);
use_rip=true;
}
void NetHackQtTextWindow::Clear()
{
lines->clear();
use_rip=false;
str_fixed=false;
}
void NetHackQtTextWindow::Display(bool block)
{
if (str_fixed) {
lines->setFont(qt_settings->normalFixedFont());
} else {
lines->setFont(qt_settings->normalFont());
}
int h=0;
if (use_rip) {
h+=rip.height();
ok.hide();
search.hide();
rip.show();
} else {
h+=ok.height()*2 + 7;
ok.show();
search.show();
rip.hide();
}
int mh = QApplication::desktop()->height()*3/5;
if ( (qt_compact_mode && lines->TotalHeight() > mh) || use_rip ) {
// big, so make it fill
showMaximized();
} else {
move(0, 0);
adjustSize();
centerOnMain(this);
show();
}
exec();
}
void NetHackQtTextWindow::PutStr(int attr, const QString& text)
{
str_fixed=str_fixed || text.contains(" ");
lines->addItem(text);
}
void NetHackQtTextWindow::Search()
{
NetHackQtStringRequestor requestor(this, "Search for:");
static char line[256]="";
requestor.SetDefault(line);
if (requestor.Get(line)) {
int current=lines->currentRow();
for (int i=1; i<lines->count(); i++) {
int lnum=(i+current)%lines->count();
QString str=lines->item(lnum)->text();
if (str.contains(line)) {
lines->setCurrentRow(lnum);
return;
}
}
lines->setCurrentItem(NULL);
}
}
NetHackQtMenuOrTextWindow::NetHackQtMenuOrTextWindow(QWidget *parent_) :
actual(0),
parent(parent_)
{
}
QWidget* NetHackQtMenuOrTextWindow::Widget()
{
if (!actual) impossible("Widget called before we know if Menu or Text");
return actual->Widget();
}
// Text
void NetHackQtMenuOrTextWindow::Clear()
{
if (!actual) impossible("Clear called before we know if Menu or Text");
actual->Clear();
}
void NetHackQtMenuOrTextWindow::Display(bool block)
{
if (!actual) impossible("Display called before we know if Menu or Text");
actual->Display(block);
}
bool NetHackQtMenuOrTextWindow::Destroy()
{
if (!actual) impossible("Destroy called before we know if Menu or Text");
return actual->Destroy();
}
void NetHackQtMenuOrTextWindow::PutStr(int attr, const QString& text)
{
if (!actual) actual=new NetHackQtTextWindow(parent);
actual->PutStr(attr,text);
}
// Menu
void NetHackQtMenuOrTextWindow::StartMenu()
{
if (!actual) actual=new NetHackQtMenuWindow(parent);
actual->StartMenu();
}
void NetHackQtMenuOrTextWindow::AddMenu(int glyph, const ANY_P* identifier, char ch, char gch, int attr,
const QString& str, bool presel)
{
if (!actual) impossible("AddMenu called before we know if Menu or Text");
actual->AddMenu(glyph,identifier,ch,gch,attr,str,presel);
}
void NetHackQtMenuOrTextWindow::EndMenu(const QString& prompt)
{
if (!actual) impossible("EndMenu called before we know if Menu or Text");
actual->EndMenu(prompt);
}
int NetHackQtMenuOrTextWindow::SelectMenu(int how, MENU_ITEM_P **menu_list)
{
if (!actual) impossible("SelectMenu called before we know if Menu or Text");
return actual->SelectMenu(how,menu_list);
}
} // namespace nethack_qt4
+182
View File
@@ -0,0 +1,182 @@
// Copyright (c) Warwick Allison, 1999.
// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
// NetHack may be freely redistributed. See license for details.
// qt4menu.cpp -- a menu or text-list widget
#ifndef QT4MENU_H
#define QT4MENU_H
#include "qt4win.h"
#include "qt4rip.h"
namespace nethack_qt4 {
class NetHackQtTextListBox : public QListWidget {
public:
NetHackQtTextListBox(QWidget* parent = NULL) : QListWidget(parent) { }
int TotalWidth() const
{
int width = 0;
QFontMetrics fm(font());
for (int i = 0; i < count(); i++) {
int lwidth = fm.width(item(i)->text());
width = std::max(width, lwidth);
}
return width;
}
int TotalHeight() const
{
QFontMetrics fm(font());
return fm.height() * count();
}
virtual QSize sizeHint() const;
};
class NetHackQtMenuListBox : public QTableWidget {
public:
NetHackQtMenuListBox(QWidget* parent = NULL) : QTableWidget(parent) { }
int TotalWidth() const;
int TotalHeight() const;
virtual QSize sizeHint() const;
};
class NetHackQtMenuWindow : public QDialog, public NetHackQtWindow {
Q_OBJECT
public:
NetHackQtMenuWindow(QWidget *parent = NULL);
~NetHackQtMenuWindow();
virtual QWidget* Widget();
virtual void StartMenu();
virtual void AddMenu(int glyph, const ANY_P* identifier, char ch, char gch, int attr,
const QString& str, bool presel);
virtual void EndMenu(const QString& prompt);
virtual int SelectMenu(int how, MENU_ITEM_P **menu_list);
public slots:
void All();
void ChooseNone();
void Invert();
void Search();
void ToggleSelect(int);
void DoSelection(bool);
protected:
virtual void keyPressEvent(QKeyEvent*);
private:
struct MenuItem {
MenuItem();
~MenuItem();
int glyph;
ANY_P identifier;
int attr;
QString str;
int count;
char ch;
char gch;
bool selected;
unsigned color;
bool Selectable() const { return identifier.a_void!=0; }
};
QVector<MenuItem> itemlist;
int itemcount;
int next_accel;
QTableWidget* table;
QPushButton* ok;
QPushButton* cancel;
QPushButton* all;
QPushButton* none;
QPushButton* invert;
QPushButton* search;
QLabel prompt;
// Count replaces prompt while it is being input
QString promptstr;
QString countstr;
bool counting;
void InputCount(char key);
void ClearCount(void);
int how;
bool has_glyphs;
bool isSelected(int row);
int count(int row);
void AddRow(int row, const MenuItem& mi);
void WidenColumn(int column, int width);
};
class NetHackQtTextWindow : public QDialog, public NetHackQtWindow {
Q_OBJECT
public:
NetHackQtTextWindow(QWidget *parent = NULL);
~NetHackQtTextWindow();
virtual QWidget* Widget();
virtual void Clear();
virtual bool Destroy();
virtual void Display(bool block);
virtual void PutStr(int attr, const QString& text);
virtual void UseRIP(int how, time_t when);
public slots:
void Search();
private slots:
void doUpdate();
private:
bool use_rip;
bool str_fixed;
QPushButton ok;
QPushButton search;
NetHackQtTextListBox* lines;
NetHackQtRIP rip;
};
class NetHackQtMenuOrTextWindow : public NetHackQtWindow {
private:
NetHackQtWindow* actual;
QWidget *parent;
public:
NetHackQtMenuOrTextWindow(QWidget *parent = NULL);
virtual QWidget* Widget();
// Text
virtual void Clear();
virtual bool Destroy();
virtual void Display(bool block);
virtual void PutStr(int attr, const QString& text);
// Menu
virtual void StartMenu();
virtual void AddMenu(int glyph, const ANY_P* identifier, char ch, char gch, int attr,
const QString& str, bool presel);
virtual void EndMenu(const QString& prompt);
virtual int SelectMenu(int how, MENU_ITEM_P **menu_list);
};
} // namespace nethack_qt4
#endif
+134
View File
@@ -0,0 +1,134 @@
// Copyright (c) Warwick Allison, 1999.
// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
// NetHack may be freely redistributed. See license for details.
// qt4msg.cpp -- a message window
extern "C" {
#include "hack.h"
}
#undef Invisible
#undef Warning
#undef index
#undef msleep
#undef rindex
#undef wizard
#undef yn
#undef min
#undef max
#include <QtGui/QtGui>
#if QT_VERSION >= 0x050000
#include <QtWidgets/QtWidgets>
#endif
#include "qt4msg.h"
#include "qt4msg.moc"
#include "qt4map.h"
#include "qt4set.h"
#include "qt4str.h"
namespace nethack_qt4 {
NetHackQtMessageWindow::NetHackQtMessageWindow() :
list(new QListWidget())
{
list->setFocusPolicy(Qt::NoFocus);
::iflags.window_inited = 1;
map = 0;
connect(qt_settings,SIGNAL(fontChanged()),this,SLOT(updateFont()));
updateFont();
}
NetHackQtMessageWindow::~NetHackQtMessageWindow()
{
::iflags.window_inited = 0;
delete list;
}
QWidget* NetHackQtMessageWindow::Widget() { return list; }
void NetHackQtMessageWindow::setMap(NetHackQtMapWindow2* m)
{
map = m;
updateFont();
}
void NetHackQtMessageWindow::updateFont()
{
list->setFont(qt_settings->normalFont());
if ( map )
map->setFont(qt_settings->normalFont());
}
void NetHackQtMessageWindow::Scroll(int dx, int dy)
{
//RLC Is this necessary?
//RLC list->Scroll(dx,dy);
}
void NetHackQtMessageWindow::Clear()
{
if ( map )
map->clearMessages();
}
void NetHackQtMessageWindow::Display(bool block)
{
if (changed) {
list->repaint();
changed=false;
}
}
void NetHackQtMessageWindow::PutStr(int attr, const QString& text)
{
#ifdef USER_SOUNDS
play_sound_for_message(text.toLatin1().constData());
#endif
changed=true;
// If the line is output from the "/" command, map the first character
// as a symbol
QString text2;
if (text.mid(1, 3) == " ") {
text2 = QChar(cp437(text.at(0).unicode())) + text.mid(1);
} else {
text2 = text;
}
#if 0
QListWidgetItem *item = new QListWidgetItem(text2);
QFont font = item->font();
font.setUnderline(attr == ATR_ULINE);
font.setWeight((attr == ATR_BOLD) ? QFont::Bold : QFont::Normal);
item->setFont(font);
QColor fg = item->foreground().color();
QColor bg = item->background().color();
if (attr == ATR_DIM)
{
fg.setAlpha(fg.alpha() / 2);
}
if (attr == ATR_INVERSE)
{
QColor swap;
swap = fg; fg = bg; bg = swap;
}
item->setForeground(fg);
item->setBackground(bg);
#endif
// ATR_BLINK not supported
if (list->count() >= ::iflags.msg_history)
delete list->item(0);
list->addItem(text2);
// Force scrollbar to bottom
list->setCurrentRow(list->count()-1);
if ( map )
map->putMessage(attr, text2);
}
} // namespace nethack_qt4
+42
View File
@@ -0,0 +1,42 @@
// Copyright (c) Warwick Allison, 1999.
// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
// NetHack may be freely redistributed. See license for details.
// qt4msg.h -- a message window
#ifndef QT4MSG_H
#define QT4MSG_H
#include "qt4win.h"
namespace nethack_qt4 {
class NetHackQtMapWindow2;
class NetHackQtMessageWindow : QObject, public NetHackQtWindow {
Q_OBJECT
public:
NetHackQtMessageWindow();
~NetHackQtMessageWindow();
virtual QWidget* Widget();
virtual void Clear();
virtual void Display(bool block);
virtual void PutStr(int attr, const QString& text);
void Scroll(int dx, int dy);
void setMap(NetHackQtMapWindow2*);
private:
QListWidget* list;
bool changed;
NetHackQtMapWindow2* map;
private slots:
void updateFont();
};
} // namespace nethack_qt4
#endif
+502
View File
@@ -0,0 +1,502 @@
// Copyright (c) Warwick Allison, 1999.
// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
// NetHack may be freely redistributed. See license for details.
// qt4plsel.cpp -- player selector dialog
extern "C" {
#include "hack.h"
}
#undef Invisible
#undef Warning
#undef index
#undef msleep
#undef rindex
#undef wizard
#undef yn
#undef min
#undef max
#include <QtGui/QtGui>
#if QT_VERSION >= 0x050000
#include <QtWidgets/QtWidgets>
#endif
#include "qt4plsel.h"
#include "qt4plsel.moc"
#include "qt4bind.h"
#include "qt4glyph.h"
#include "qt4set.h"
#include "qt4str.h"
// Warwick prefers it this way...
#define QT_CHOOSE_RACE_FIRST
namespace nethack_qt4 {
// temporary
void centerOnMain( QWidget* w );
// end temporary
static const char nh_attribution[] = "<center><big>NetHack</big>"
"<br><small>by the NetHack DevTeam</small></center>";
class NhPSListViewItem : public QTableWidgetItem {
public:
NhPSListViewItem( QTableWidget* parent, const QString& name ) :
QTableWidgetItem(name)
{
}
void setGlyph(int g)
{
NetHackQtGlyphs& glyphs = qt_settings->glyphs();
int gw = glyphs.width();
int gh = glyphs.height();
QPixmap pm(gw,gh);
QPainter p(&pm);
glyphs.drawGlyph(p, g, 0, 0);
p.end();
setIcon(QIcon(pm));
//RLC setHeight(std::max(pm.height()+1,height()));
}
#if 0 //RLC
void paintCell( QPainter *p, const QColorGroup &cg,
int column, int width, int alignment )
{
if ( isSelectable() ) {
QTableWidgetItem::paintCell( p, cg, column, width, alignment );
} else {
QColorGroup disabled(
cg.foreground().light(),
cg.button().light(),
cg.light(), cg.dark(), cg.mid(),
Qt::gray, cg.base() );
QTableWidgetItem::paintCell( p, disabled, column, width, alignment );
}
}
#endif
};
class NhPSListViewRole : public NhPSListViewItem {
public:
NhPSListViewRole( QTableWidget* parent, int id ) :
NhPSListViewItem(parent,
#ifdef QT_CHOOSE_RACE_FIRST // Lowerize - looks better
QString(roles[id].name.m).toLower()
#else
roles[id].name.m
#endif
)
{
setGlyph(monnum_to_glyph(roles[id].malenum));
}
};
class NhPSListViewRace : public NhPSListViewItem {
public:
NhPSListViewRace( QTableWidget* parent, int id ) :
NhPSListViewItem(parent,
#ifdef QT_CHOOSE_RACE_FIRST // Capitalize - looks better
str_titlecase(races[id].noun)
#else
races[id].noun
#endif
)
{
setGlyph(monnum_to_glyph(races[id].malenum));
}
};
class NhPSListView : public QTableWidget {
public:
NhPSListView( QWidget* parent ) :
QTableWidget(parent)
{
setColumnCount(1);
verticalHeader()->hide();
#if QT_VERSION >= 0x050000
horizontalHeader()->setSectionsClickable(false);
#else
horizontalHeader()->setClickable(false);
#endif
}
QSizePolicy sizePolicy() const
{
return QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
}
QSize minimumSizeHint() const
{
return sizeHint();
}
QSize sizeHint() const
{
return QSize(columnWidth(0), QTableWidget::sizeHint().height());
}
};
NetHackQtPlayerSelector::NetHackQtPlayerSelector(NetHackQtKeyBuffer& ks) :
QDialog(NetHackQtBind::mainWidget()),
fully_specified_role(true)
{
/*
0 1 2
+ Name ------------------------------------+
0 | |
+ ---- ------------------------------------+
+ Role ---+ + Race ---+ + Gender ------+
| | | | | * Male |
1 | | | | | * Female |
| | | | +--------------+
| | | |
| | | | + Alignment ---+
2 | | | | | * Male |
| | | | | * Female |
| | | | +--------------+
3 | | | | ...stretch...
| | | |
4 | | | | [ Play ]
5 | | | | [ Quit ]
+---------+ +---------+
*/
QGridLayout *l = new QGridLayout(this);
l->setColumnStretch(2, 1);
sizePolicy().setHorizontalPolicy(QSizePolicy::Minimum);
QGroupBox* namebox = new QGroupBox("Name", this);
QVBoxLayout *namelayout = new QVBoxLayout(namebox);
QLineEdit* name = new QLineEdit(namebox);
namelayout->addWidget(name);
name->setMaxLength(sizeof(plname)-1);
if ( strncmp(plname,"player",6) && strncmp(plname,"games",5) )
name->setText(plname);
connect(name, SIGNAL(textChanged(const QString&)),
this, SLOT(selectName(const QString&)) );
name->setFocus();
QGroupBox* genderbox = new QGroupBox("Sex",this);
QButtonGroup *gendergroup = new QButtonGroup(this);
QGroupBox* alignbox = new QGroupBox("Alignment",this);
QButtonGroup *aligngroup = new QButtonGroup(this);
QVBoxLayout* vbgb = new QVBoxLayout(genderbox);
vbgb->addSpacing(fontMetrics().height()*3/4);
QVBoxLayout* vbab = new QVBoxLayout(alignbox);
vbab->addSpacing(fontMetrics().height());
QLabel* logo = new QLabel(nh_attribution, this);
l->addWidget( namebox, 0,0,1,3 );
#ifdef QT_CHOOSE_RACE_FIRST
race = new NhPSListView(this);
role = new NhPSListView(this);
l->addWidget( race, 1,0,5,1 );
l->addWidget( role, 1,1,5,1 );
#else
role = new NhPSListView(this);
race = new NhPSListView(this);
l->addWidget( role, 1,0,5,1 );
l->addWidget( race, 1,1,5,1 );
#endif
l->addWidget( genderbox, 1, 2 );
l->addWidget( alignbox, 2, 2 );
l->addWidget( logo, 3, 2, Qt::AlignCenter );
l->setRowStretch( 3, 5 );
int i;
int nrole;
// XXX QListView unsorted goes in rev.
for (nrole=0; roles[nrole].name.m; nrole++)
;
role->setRowCount(nrole);
for (i=0; roles[i].name.m; i++) {
QTableWidgetItem *item = new QTableWidgetItem(
QIcon(qt_settings->glyphs().glyph(roles[i].malenum)),
roles[i].name.m);
item->setFlags(Qt::ItemIsEnabled|Qt::ItemIsSelectable);
role->setItem(i, 0, item);
}
connect( role, SIGNAL(currentCellChanged(int, int, int, int)), this, SLOT(selectRole(int, int, int, int)) );
role->setHorizontalHeaderLabels(QStringList("Role"));
role->resizeColumnToContents(0);
int nrace;
for (nrace=0; races[nrace].noun; nrace++)
;
race->setRowCount(nrace);
for (i=0; races[i].noun; i++) {
QTableWidgetItem *item = new QTableWidgetItem(
QIcon(qt_settings->glyphs().glyph(races[i].malenum)),
races[i].noun);
item->setFlags(Qt::ItemIsEnabled|Qt::ItemIsSelectable);
race->setItem(i, 0, item);
}
connect( race, SIGNAL(currentCellChanged(int, int, int, int)), this, SLOT(selectRace(int, int, int, int)) );
race->setHorizontalHeaderLabels(QStringList("Race"));
race->resizeColumnToContents(0);
gender = new QRadioButton*[ROLE_GENDERS];
for (i=0; i<ROLE_GENDERS; i++) {
gender[i] = new QRadioButton( genders[i].adj, genderbox );
genderbox->layout()->addWidget(gender[i]);
gendergroup->addButton(gender[i], i);
}
connect( gendergroup, SIGNAL(buttonPressed(int)), this, SLOT(selectGender(int)) );
alignment = new QRadioButton*[ROLE_ALIGNS];
for (i=0; i<ROLE_ALIGNS; i++) {
alignment[i] = new QRadioButton( aligns[i].adj, alignbox );
alignbox->layout()->addWidget(alignment[i]);
aligngroup->addButton(alignment[i], i);
}
connect( aligngroup, SIGNAL(buttonPressed(int)), this, SLOT(selectAlignment(int)) );
QPushButton* ok = new QPushButton("Play",this);
l->addWidget( ok, 4, 2 );
ok->setDefault(true);
connect( ok, SIGNAL(clicked()), this, SLOT(accept()) );
QPushButton* cancel = new QPushButton("Quit",this);
l->addWidget( cancel, 5, 2 );
connect( cancel, SIGNAL(clicked()), this, SLOT(reject()) );
// Randomize race and role, unless specified in config
int ro = flags.initrole;
if (ro == ROLE_NONE || ro == ROLE_RANDOM) {
ro = rn2(nrole);
if (flags.initrole != ROLE_RANDOM) {
fully_specified_role = false;
}
}
int ra = flags.initrace;
if (ra == ROLE_NONE || ra == ROLE_RANDOM) {
ra = rn2(nrace);
if (flags.initrace != ROLE_RANDOM) {
fully_specified_role = false;
}
}
// make sure we have a valid combination, honoring
// the users request if possible.
bool choose_race_first;
#ifdef QT_CHOOSE_RACE_FIRST
choose_race_first = true;
if (flags.initrole >= 0 && flags.initrace < 0) {
choose_race_first = false;
}
#else
choose_race_first = false;
if (flags.initrace >= 0 && flags.initrole < 0) {
choose_race_first = true;
}
#endif
while (!validrace(ro,ra)) {
if (choose_race_first) {
ro = rn2(nrole);
if (flags.initrole != ROLE_RANDOM) {
fully_specified_role = false;
}
} else {
ra = rn2(nrace);
if (flags.initrace != ROLE_RANDOM) {
fully_specified_role = false;
}
}
}
int g = flags.initgend;
if (g == -1) {
g = rn2(ROLE_GENDERS);
fully_specified_role = false;
}
while (!validgend(ro,ra,g)) {
g = rn2(ROLE_GENDERS);
}
gender[g]->setChecked(true);
selectGender(g);
int a = flags.initalign;
if (a == -1) {
a = rn2(ROLE_ALIGNS);
fully_specified_role = false;
}
while (!validalign(ro,ra,a)) {
a = rn2(ROLE_ALIGNS);
}
alignment[a]->setChecked(true);
selectAlignment(a);
role->setCurrentCell(ro, 0);
race->setCurrentCell(ra, 0);
flags.initrace = race->currentRow();
flags.initrole = role->currentRow();
}
void NetHackQtPlayerSelector::selectName(const QString& n)
{
str_copy(plname,n.toLatin1().constData(),SIZE(plname));
}
void NetHackQtPlayerSelector::selectRole(int crow, int ccol, int prow, int pcol)
{
int ra = race->currentRow();
int ro = role->currentRow();
if (ra == -1 || ro == -1) return;
QTableWidgetItem* item;
item = role->item(prow, 0);
if (item != NULL)
item->setSelected(false);
#ifdef QT_CHOOSE_RACE_FIRST
selectRace(crow, ccol, prow, pcol);
#else
QTableWidgetItem* i=role->currentItem();
QTableWidgetItem* valid=0;
int j;
for (j=0; roles[j].name.m; j++) {
bool v = validrace(j,ra);
item = role->item(j, 0);
item->setFlags(Qt::ItemIsEnabled|Qt::ItemIsSelectable);
if ( !valid && v ) valid = item;
}
if ( !validrace(role->currentRow(),ra) )
i = valid;
role->setCurrentItem(i, 0);
for (j=0; roles[j].name.m; j++) {
item = role->item(j, 0);
item->setSelected(item == i);
bool v = validrace(j,ra);
item->setFlags(
v ? Qt::ItemIsEnabled|Qt::ItemIsSelectable
: Qt::NoItemFlags);
}
#endif
flags.initrole = role->currentRow();
setupOthers();
}
void NetHackQtPlayerSelector::selectRace(int crow, int ccol, int prow, int pcol)
{
int ra = race->currentRow();
int ro = role->currentRow();
if (ra == -1 || ro == -1) return;
QTableWidgetItem* item;
item = race->item(prow, 0);
if (item != NULL)
item->setSelected(false);
#ifndef QT_CHOOSE_RACE_FIRST
selectRole(crow, ccol, prow, pcol);
#else
QTableWidgetItem* i=race->currentItem();
QTableWidgetItem* valid=0;
int j;
for (j=0; races[j].noun; j++) {
bool v = validrace(ro,j);
item = race->item(j, 0);
item->setFlags(Qt::ItemIsEnabled|Qt::ItemIsSelectable);
if ( !valid && v ) valid = item;
}
if ( !validrace(ro,race->currentRow()) )
i = valid;
for (j=0; races[j].noun; j++) {
item = race->item(j, 0);
item->setSelected(item == i);
bool v = validrace(ro,j);
item->setFlags(
v ? Qt::ItemIsEnabled|Qt::ItemIsSelectable
: Qt::NoItemFlags);
}
#endif
flags.initrace = race->currentRow();
setupOthers();
}
void NetHackQtPlayerSelector::setupOthers()
{
int ro = role->currentRow();
int ra = race->currentRow();
int valid=-1;
int c=0;
int j;
for (j=0; j<ROLE_GENDERS; j++) {
bool v = validgend(ro,ra,j);
if ( gender[j]->isChecked() )
c = j;
gender[j]->setEnabled(v);
if ( valid<0 && v ) valid = j;
}
if ( !validgend(ro,ra,c) )
c = valid;
int k;
for (k=0; k<ROLE_GENDERS; k++) {
gender[k]->setChecked(c==k);
}
selectGender(c);
valid=-1;
for (j=0; j<ROLE_ALIGNS; j++) {
bool v = validalign(ro,ra,j);
if ( alignment[j]->isChecked() )
c = j;
alignment[j]->setEnabled(v);
if ( valid<0 && v ) valid = j;
}
if ( !validalign(ro,ra,c) )
c = valid;
for (k=0; k<ROLE_ALIGNS; k++) {
alignment[k]->setChecked(c==k);
}
selectAlignment(c);
}
void NetHackQtPlayerSelector::selectGender(int i)
{
flags.initgend = i;
}
void NetHackQtPlayerSelector::selectAlignment(int i)
{
flags.initalign = i;
}
void NetHackQtPlayerSelector::Quit()
{
done(R_Quit);
}
void NetHackQtPlayerSelector::Random()
{
done(R_Rand);
}
bool NetHackQtPlayerSelector::Choose()
{
if (fully_specified_role) return true;
#if defined(QWS) // probably safe with Qt 3, too (where show!=exec in QDialog).
if ( qt_compact_mode ) {
showMaximized();
} else
#endif
{
adjustSize();
centerOnMain(this);
}
if ( exec() ) {
return true;
} else {
return false;
}
}
} // namespace nethack_qt4
+45
View File
@@ -0,0 +1,45 @@
// Copyright (c) Warwick Allison, 1999.
// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
// NetHack may be freely redistributed. See license for details.
// qt4plsel.h -- player selector dialog
#ifndef QT4PLSEL_H
#define QT4PLSEL_H
namespace nethack_qt4 {
class NetHackQtKeyBuffer;
class NetHackQtPlayerSelector : private QDialog {
Q_OBJECT
public:
enum { R_None=-1, R_Quit=-2, R_Rand=-3 };
NetHackQtPlayerSelector(NetHackQtKeyBuffer&);
public slots:
void Quit();
void Random();
void selectName(const QString& n);
void selectRole(int current, int, int previous, int);
void selectRace(int current, int, int previous, int);
void setupOthers();
void selectGender(int);
void selectAlignment(int);
public:
bool Choose();
private:
QTableWidget* role;
QTableWidget* race;
QRadioButton **gender;
QRadioButton **alignment;
bool fully_specified_role;
};
} // namespace nethack_qt4
#endif
+94
View File
@@ -0,0 +1,94 @@
// Copyright (c) Warwick Allison, 1999.
// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
// NetHack may be freely redistributed. See license for details.
// qt4rip.cpp -- tombstone window
#include "hack.h"
#undef Invisible
#undef Warning
#undef index
#undef msleep
#undef rindex
#undef wizard
#undef yn
#undef min
#undef max
#include <QtGui/QtGui>
#if QT_VERSION >= 0x050000
#include <QtWidgets/QtWidgets>
#endif
#include "qt4rip.h"
#include "qt4bind.h"
#include "qt4str.h"
namespace nethack_qt4 {
QPixmap* NetHackQtRIP::pixmap=0;
// Debian uses a separate PIXMAPDIR
#ifndef PIXMAPDIR
# ifdef HACKDIR
# define PIXMAPDIR HACKDIR
# else
# define PIXMAPDIR "."
# endif
#endif
static void
tryload(QPixmap& pm, const char* fn)
{
if (!pm.load(fn)) {
QString msg;
msg.sprintf("Cannot load \"%s\"", fn);
QMessageBox::warning(NetHackQtBind::mainWidget(), "IO Error", msg);
}
}
NetHackQtRIP::NetHackQtRIP(QWidget* parent) :
QWidget(parent)
{
if (!pixmap) {
pixmap=new QPixmap;
tryload(*pixmap, PIXMAPDIR "/rip.xpm");
}
riplines=0;
resize(pixmap->width(),pixmap->height());
setFont(QFont("times",12)); // XXX may need to be configurable
}
void NetHackQtRIP::setLines(char** l, int n)
{
line=l;
riplines=n;
}
QSize NetHackQtRIP::sizeHint() const
{
return pixmap->size();
}
void NetHackQtRIP::paintEvent(QPaintEvent* event)
{
if ( riplines ) {
int pix_x=(width()-pixmap->width())/2;
int pix_y=(height()-pixmap->height())/2;
// XXX positions based on RIP image
int rip_text_x=pix_x+156;
int rip_text_y=pix_y+67;
int rip_text_h=94/riplines;
QPainter painter;
painter.begin(this);
painter.drawPixmap(pix_x,pix_y,*pixmap);
for (int i=0; i<riplines; i++) {
painter.drawText(rip_text_x-i/2,rip_text_y+i*rip_text_h,
1,1,Qt::TextDontClip|Qt::AlignHCenter,line[i]);
}
painter.end();
}
}
} // namespace nethack_qt4
+30
View File
@@ -0,0 +1,30 @@
// Copyright (c) Warwick Allison, 1999.
// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
// NetHack may be freely redistributed. See license for details.
// qt4rip.h -- tombstone window
#ifndef QT4RIP_H
#define QT4RIP_H
namespace nethack_qt4 {
class NetHackQtRIP : public QWidget {
private:
static QPixmap* pixmap;
char** line;
int riplines;
public:
NetHackQtRIP(QWidget* parent);
void setLines(char** l, int n);
protected:
virtual void paintEvent(QPaintEvent* event);
QSize sizeHint() const;
};
} // namespace nethack_qt4
#endif
+186
View File
@@ -0,0 +1,186 @@
// Copyright (c) Warwick Allison, 1999.
// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
// NetHack may be freely redistributed. See license for details.
// qt4set.cpp -- the Qt settings
#include "hack.h"
#undef Invisible
#undef Warning
#undef index
#undef msleep
#undef rindex
#undef wizard
#undef yn
#undef min
#undef max
#include <QtGui/QtGui>
#if QT_VERSION >= 0x050000
#include <QtWidgets/QtWidgets>
#endif
#include "qt4set.h"
#include "qt4set.moc"
#include "qt4glyph.h"
#include "qt4str.h"
/* Used by tile/font-size patch below and in ../../src/files.c */
char *qt_tilewidth=NULL;
char *qt_tileheight=NULL;
char *qt_fontsize=NULL;
#if defined(QWS)
int qt_compact_mode = 1;
#else
int qt_compact_mode = 0;
#endif
namespace nethack_qt4 {
#define TILEWMIN 1
#define TILEHMIN 1
NetHackQtSettings::NetHackQtSettings(int w, int h) :
tilewidth(this),
tileheight(this),
widthlbl("&Width:",this),
heightlbl("&Height:",this),
whichsize("&Zoomed",this),
fontsize(this),
normal("times"),
#ifdef WS_WIN
normalfixed("courier new"),
#else
normalfixed("courier"),
#endif
large("times"),
theglyphs(0)
{
int default_fontsize;
widthlbl.setBuddy(&tilewidth);
tilewidth.setRange(TILEWMIN, 128);
heightlbl.setBuddy(&tileheight);
tileheight.setRange(TILEHMIN, 128);
default_fontsize=2;
tilewidth.setValue(16);
tileheight.setValue(16);
// Tile/font sizes read from .nethackrc
if (qt_tilewidth != NULL) {
tilewidth.setValue(atoi(qt_tilewidth));
delete[] qt_tilewidth;
}
if (qt_tileheight != NULL) {
tileheight.setValue(atoi(qt_tileheight));
delete[] qt_tileheight;
}
if (qt_fontsize != NULL) {
switch (tolower(qt_fontsize[0])) {
case 'h': default_fontsize = 0; break;
case 'l': default_fontsize = 1; break;
case 'm': default_fontsize = 2; break;
case 's': default_fontsize = 3; break;
case 't': default_fontsize = 4; break;
}
delete[] qt_fontsize;
}
theglyphs=new NetHackQtGlyphs();
resizeTiles();
connect(&tilewidth,SIGNAL(valueChanged(int)),this,SLOT(resizeTiles()));
connect(&tileheight,SIGNAL(valueChanged(int)),this,SLOT(resizeTiles()));
connect(&whichsize,SIGNAL(toggled(bool)),this,SLOT(setGlyphSize(bool)));
fontsize.addItem("Huge");
fontsize.addItem("Large");
fontsize.addItem("Medium");
fontsize.addItem("Small");
fontsize.addItem("Tiny");
fontsize.setCurrentIndex(default_fontsize);
connect(&fontsize,SIGNAL(activated(int)),this,SIGNAL(fontChanged()));
QGridLayout* grid = new QGridLayout(this);
grid->addWidget(&whichsize, 0, 0, 1, 2);
grid->addWidget(&tilewidth, 1, 1); grid->addWidget(&widthlbl, 1, 0);
grid->addWidget(&tileheight, 2, 1); grid->addWidget(&heightlbl, 2, 0);
QLabel* flabel=new QLabel("&Font:",this);
flabel->setBuddy(&fontsize);
grid->addWidget(flabel, 3, 0); grid->addWidget(&fontsize, 3, 1);
QPushButton* dismiss=new QPushButton("Dismiss",this);
dismiss->setDefault(true);
grid->addWidget(dismiss, 4, 0, 1, 2);
grid->setRowStretch(4,0);
grid->setColumnStretch(1,1);
grid->setColumnStretch(2,2);
grid->activate();
connect(dismiss,SIGNAL(clicked()),this,SLOT(accept()));
resize(150,140);
}
NetHackQtGlyphs& NetHackQtSettings::glyphs()
{
return *theglyphs;
}
void NetHackQtSettings::resizeTiles()
{
int w = tilewidth.value();
int h = tileheight.value();
theglyphs->setSize(w,h);
emit tilesChanged();
}
void NetHackQtSettings::toggleGlyphSize()
{
whichsize.toggle();
}
void NetHackQtSettings::setGlyphSize(bool which)
{
QSize n = QSize(tilewidth.value(),tileheight.value());
if ( othersize.isValid() ) {
tilewidth.blockSignals(true);
tileheight.blockSignals(true);
tilewidth.setValue(othersize.width());
tileheight.setValue(othersize.height());
tileheight.blockSignals(false);
tilewidth.blockSignals(false);
resizeTiles();
}
othersize = n;
}
const QFont& NetHackQtSettings::normalFont()
{
static int size[]={ 18, 14, 12, 10, 8 };
normal.setPointSize(size[fontsize.currentIndex()]);
return normal;
}
const QFont& NetHackQtSettings::normalFixedFont()
{
static int size[]={ 18, 14, 13, 10, 8 };
normalfixed.setPointSize(size[fontsize.currentIndex()]);
return normalfixed;
}
const QFont& NetHackQtSettings::largeFont()
{
static int size[]={ 24, 18, 14, 12, 10 };
large.setPointSize(size[fontsize.currentIndex()]);
return large;
}
bool NetHackQtSettings::ynInMessages()
{
return !qt_compact_mode && !iflags.wc_popup_dialog;
}
NetHackQtSettings* qt_settings;
} // namespace nethack_qt4
+57
View File
@@ -0,0 +1,57 @@
// Copyright (c) Warwick Allison, 1999.
// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
// NetHack may be freely redistributed. See license for details.
// qt4set.h -- the Qt settings
#ifndef QT4SET_H
#define QT4SET_H
namespace nethack_qt4 {
class NetHackQtGlyphs;
class NetHackQtSettings : public QDialog {
Q_OBJECT
public:
// Size of window - used to decide default sizes
NetHackQtSettings(int width, int height);
NetHackQtGlyphs& glyphs();
const QFont& normalFont();
const QFont& normalFixedFont();
const QFont& largeFont();
bool ynInMessages();
signals:
void fontChanged();
void tilesChanged();
public slots:
void toggleGlyphSize();
void setGlyphSize(bool);
private:
QSpinBox tilewidth;
QSpinBox tileheight;
QLabel widthlbl;
QLabel heightlbl;
QCheckBox whichsize;
QSize othersize;
QComboBox fontsize;
QFont normal, normalfixed, large;
NetHackQtGlyphs* theglyphs;
private slots:
void resizeTiles();
};
extern NetHackQtSettings* qt_settings;
} // namespace nethack_qt4
#endif
+540
View File
@@ -0,0 +1,540 @@
// Copyright (c) Warwick Allison, 1999.
// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
// NetHack may be freely redistributed. See license for details.
// qt4stat.cpp -- bindings between the Qt 4 interface and the main code
extern "C" {
#include "hack.h"
}
#undef Invisible
#undef Warning
#undef index
#undef msleep
#undef rindex
#undef wizard
#undef yn
#undef min
#undef max
#include <QtGui/QtGui>
#if QT_VERSION >= 0x050000
#include <QtWidgets/QtWidgets>
#endif
#include "qt4stat.h"
#include "qt4stat.moc"
#include "qt4set.h"
#include "qt4str.h"
#include "qt_xpms.h"
extern const char *enc_stat[]; /* from botl.c */
extern const char *hu_stat[]; /* from eat.c */
namespace nethack_qt4 {
NetHackQtStatusWindow::NetHackQtStatusWindow() :
// Notes:
// Alignment needs -2 init value, because -1 is an alignment.
// Armor Class is an schar, so 256 is out of range.
// Blank value is 0 and should never change.
name(this,"(name)"),
dlevel(this,"(dlevel)"),
str(this,"STR"),
dex(this,"DEX"),
con(this,"CON"),
intel(this,"INT"),
wis(this,"WIS"),
cha(this,"CHA"),
gold(this,"Gold"),
hp(this,"Hit Points"),
power(this,"Power"),
ac(this,"Armour Class"),
level(this,"Level"),
exp(this,"Experience"),
align(this,"Alignment"),
time(this,"Time"),
score(this,"Score"),
hunger(this,""),
confused(this,"Confused"),
sick_fp(this,"Sick"),
sick_il(this,"Ill"),
blind(this,""),
stunned(this,"Stunned"),
hallu(this,"Hallu"),
encumber(this,""),
hline1(this),
hline2(this),
hline3(this),
first_set(true)
{
p_str = QPixmap(str_xpm);
p_str = QPixmap(str_xpm);
p_dex = QPixmap(dex_xpm);
p_con = QPixmap(cns_xpm);
p_int = QPixmap(int_xpm);
p_wis = QPixmap(wis_xpm);
p_cha = QPixmap(cha_xpm);
p_chaotic = QPixmap(chaotic_xpm);
p_neutral = QPixmap(neutral_xpm);
p_lawful = QPixmap(lawful_xpm);
p_satiated = QPixmap(satiated_xpm);
p_hungry = QPixmap(hungry_xpm);
p_confused = QPixmap(confused_xpm);
p_sick_fp = QPixmap(sick_fp_xpm);
p_sick_il = QPixmap(sick_il_xpm);
p_blind = QPixmap(blind_xpm);
p_stunned = QPixmap(stunned_xpm);
p_hallu = QPixmap(hallu_xpm);
p_encumber[0] = QPixmap(slt_enc_xpm);
p_encumber[1] = QPixmap(mod_enc_xpm);
p_encumber[2] = QPixmap(hvy_enc_xpm);
p_encumber[3] = QPixmap(ext_enc_xpm);
p_encumber[4] = QPixmap(ovr_enc_xpm);
str.setIcon(p_str);
dex.setIcon(p_dex);
con.setIcon(p_con);
intel.setIcon(p_int);
wis.setIcon(p_wis);
cha.setIcon(p_cha);
align.setIcon(p_neutral);
hunger.setIcon(p_hungry);
confused.setIcon(p_confused);
sick_fp.setIcon(p_sick_fp);
sick_il.setIcon(p_sick_il);
blind.setIcon(p_blind);
stunned.setIcon(p_stunned);
hallu.setIcon(p_hallu);
encumber.setIcon(p_encumber[0]);
hline1.setFrameStyle(QFrame::HLine|QFrame::Sunken);
hline2.setFrameStyle(QFrame::HLine|QFrame::Sunken);
hline3.setFrameStyle(QFrame::HLine|QFrame::Sunken);
hline1.setLineWidth(1);
hline2.setLineWidth(1);
hline3.setLineWidth(1);
#if 1 //RLC
name.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
dlevel.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
QVBoxLayout *vbox = new QVBoxLayout();
vbox->setSpacing(0);
vbox->addWidget(&name);
vbox->addWidget(&dlevel);
vbox->addWidget(&hline1);
QHBoxLayout *atr1box = new QHBoxLayout();
atr1box->addWidget(&str);
atr1box->addWidget(&dex);
atr1box->addWidget(&con);
atr1box->addWidget(&intel);
atr1box->addWidget(&wis);
atr1box->addWidget(&cha);
vbox->addLayout(atr1box);
vbox->addWidget(&hline2);
QHBoxLayout *atr2box = new QHBoxLayout();
atr2box->addWidget(&gold);
atr2box->addWidget(&hp);
atr2box->addWidget(&power);
atr2box->addWidget(&ac);
atr2box->addWidget(&level);
atr2box->addWidget(&exp);
vbox->addLayout(atr2box);
vbox->addWidget(&hline3);
QHBoxLayout *timebox = new QHBoxLayout();
timebox->addWidget(&time);
timebox->addWidget(&score);
vbox->addLayout(timebox);
QHBoxLayout *statbox = new QHBoxLayout();
statbox->addWidget(&align);
statbox->addWidget(&hunger);
statbox->addWidget(&confused);
statbox->addWidget(&sick_fp);
statbox->addWidget(&sick_il);
statbox->addWidget(&blind);
statbox->addWidget(&stunned);
statbox->addWidget(&hallu);
statbox->addWidget(&encumber);
statbox->setAlignment(Qt::AlignLeft|Qt::AlignVCenter);
vbox->addLayout(statbox);
setLayout(vbox);
#endif
connect(qt_settings,SIGNAL(fontChanged()),this,SLOT(doUpdate()));
doUpdate();
}
void NetHackQtStatusWindow::doUpdate()
{
const QFont& large=qt_settings->largeFont();
name.setFont(large);
dlevel.setFont(large);
const QFont& normal=qt_settings->normalFont();
str.setFont(normal);
dex.setFont(normal);
con.setFont(normal);
intel.setFont(normal);
wis.setFont(normal);
cha.setFont(normal);
gold.setFont(normal);
hp.setFont(normal);
power.setFont(normal);
ac.setFont(normal);
level.setFont(normal);
exp.setFont(normal);
align.setFont(normal);
time.setFont(normal);
score.setFont(normal);
hunger.setFont(normal);
confused.setFont(normal);
sick_fp.setFont(normal);
sick_il.setFont(normal);
blind.setFont(normal);
stunned.setFont(normal);
hallu.setFont(normal);
encumber.setFont(normal);
updateStats();
}
QWidget* NetHackQtStatusWindow::Widget() { return this; }
void NetHackQtStatusWindow::Clear()
{
}
void NetHackQtStatusWindow::Display(bool block)
{
}
void NetHackQtStatusWindow::CursorTo(int,int y)
{
cursy=y;
}
void NetHackQtStatusWindow::PutStr(int attr, const QString& text)
{
// do a complete update when line 0 is done (as per X11 fancy status)
if (cursy==0) updateStats();
}
#if 0 // RLC
void NetHackQtStatusWindow::resizeEvent(QResizeEvent*)
{
#if 0
const float SP_name=0.13; // <Name> the <Class> (large)
const float SP_dlev=0.13; // Level 3 in The Dungeons of Doom (large)
const float SP_atr1=0.25; // STR DEX CON INT WIS CHA
const float SP_hln1=0.02; // ---
const float SP_atr2=0.09; // Au HP PW AC LVL EXP
const float SP_hln2=0.02; // ---
const float SP_time=0.09; // time score
const float SP_hln3=0.02; // ---
const float SP_stat=0.25; // Alignment, Poisoned, Hungry, Sick, etc.
int h=height();
int x=0,y=0;
int iw; // Width of an item across line
int lh; // Height of a line of values
lh=int(h*SP_name);
name.setGeometry(0,0,width(),lh); y+=lh;
lh=int(h*SP_dlev);
dlevel.setGeometry(0,y,width(),lh); y+=lh;
lh=int(h*SP_hln1);
hline1.setGeometry(0,y,width(),lh); y+=lh;
lh=int(h*SP_atr1);
iw=width()/6;
str.setGeometry(x,y,iw,lh); x+=iw;
dex.setGeometry(x,y,iw,lh); x+=iw;
con.setGeometry(x,y,iw,lh); x+=iw;
intel.setGeometry(x,y,iw,lh); x+=iw;
wis.setGeometry(x,y,iw,lh); x+=iw;
cha.setGeometry(x,y,iw,lh); x+=iw;
x=0; y+=lh;
lh=int(h*SP_hln2);
hline2.setGeometry(0,y,width(),lh); y+=lh;
lh=int(h*SP_atr2);
iw=width()/6;
gold.setGeometry(x,y,iw,lh); x+=iw;
hp.setGeometry(x,y,iw,lh); x+=iw;
power.setGeometry(x,y,iw,lh); x+=iw;
ac.setGeometry(x,y,iw,lh); x+=iw;
level.setGeometry(x,y,iw,lh); x+=iw;
exp.setGeometry(x,y,iw,lh); x+=iw;
x=0; y+=lh;
lh=int(h*SP_hln3);
hline3.setGeometry(0,y,width(),lh); y+=lh;
lh=int(h*SP_time);
iw=width()/3; x+=iw/2;
time.setGeometry(x,y,iw,lh); x+=iw;
score.setGeometry(x,y,iw,lh); x+=iw;
x=0; y+=lh;
lh=int(h*SP_stat);
iw=width()/9;
align.setGeometry(x,y,iw,lh); x+=iw;
hunger.setGeometry(x,y,iw,lh); x+=iw;
confused.setGeometry(x,y,iw,lh); x+=iw;
sick_fp.setGeometry(x,y,iw,lh); x+=iw;
sick_il.setGeometry(x,y,iw,lh); x+=iw;
blind.setGeometry(x,y,iw,lh); x+=iw;
stunned.setGeometry(x,y,iw,lh); x+=iw;
hallu.setGeometry(x,y,iw,lh); x+=iw;
encumber.setGeometry(x,y,iw,lh); x+=iw;
x=0; y+=lh;
#else
// This is clumsy. But QLayout objects are proving balky.
int row[10];
row[0] = name.sizeHint().height();
row[1] = dlevel.sizeHint().height();
row[2] = h.sizeHint().height();
#endif
}
#endif
/*
* Set all widget values to a null string. This is used after all spacings
* have been calculated so that when the window is popped up we don't get all
* kinds of funny values being displayed.
*/
void NetHackQtStatusWindow::nullOut()
{
}
void NetHackQtStatusWindow::fadeHighlighting()
{
name.dissipateHighlight();
dlevel.dissipateHighlight();
str.dissipateHighlight();
dex.dissipateHighlight();
con.dissipateHighlight();
intel.dissipateHighlight();
wis.dissipateHighlight();
cha.dissipateHighlight();
gold.dissipateHighlight();
hp.dissipateHighlight();
power.dissipateHighlight();
ac.dissipateHighlight();
level.dissipateHighlight();
exp.dissipateHighlight();
align.dissipateHighlight();
time.dissipateHighlight();
score.dissipateHighlight();
hunger.dissipateHighlight();
confused.dissipateHighlight();
sick_fp.dissipateHighlight();
sick_il.dissipateHighlight();
blind.dissipateHighlight();
stunned.dissipateHighlight();
hallu.dissipateHighlight();
encumber.dissipateHighlight();
}
/*
* Update the displayed status. The current code in botl.c updates
* two lines of information. Both lines are always updated one after
* the other. So only do our update when we update the second line.
*
* Information on the first line:
* name, attributes, alignment, score
*
* Information on the second line:
* dlvl, gold, hp, power, ac, {level & exp or HD **}
* status (hunger, conf, halu, stun, sick, blind), time, encumbrance
*
* [**] HD is shown instead of level and exp if mtimedone is non-zero.
*/
void NetHackQtStatusWindow::updateStats()
{
if (!parentWidget()) return;
QString buf;
const char *text;
if (cursy != 0) return; /* do a complete update when line 0 is done */
if (ACURR(A_STR) > 118) {
buf.sprintf("STR:%d",ACURR(A_STR)-100);
} else if (ACURR(A_STR)==118) {
buf.sprintf("STR:18/**");
} else if(ACURR(A_STR) > 18) {
buf.sprintf("STR:18/%02d",ACURR(A_STR)-18);
} else {
buf.sprintf("STR:%d",ACURR(A_STR));
}
str.setLabel(buf,NetHackQtLabelledIcon::NoNum,ACURR(A_STR));
dex.setLabel("DEX:",(long)ACURR(A_DEX));
con.setLabel("CON:",(long)ACURR(A_CON));
intel.setLabel("INT:",(long)ACURR(A_INT));
wis.setLabel("WIS:",(long)ACURR(A_WIS));
cha.setLabel("CHA:",(long)ACURR(A_CHA));
const char* hung=hu_stat[u.uhs];
if (hung[0]==' ') {
hunger.hide();
} else {
hunger.setIcon(u.uhs ? p_hungry : p_satiated);
hunger.setLabel(hung);
hunger.show();
}
if (Confusion) confused.show(); else confused.hide();
if (Sick) {
if (u.usick_type & SICK_VOMITABLE) {
sick_fp.show();
} else {
sick_fp.hide();
}
if (u.usick_type & SICK_NONVOMITABLE) {
sick_il.show();
} else {
sick_il.hide();
}
} else {
sick_fp.hide();
sick_il.hide();
}
if (Blind) {
blind.setLabel("Blind");
blind.show();
} else {
blind.hide();
}
if (Stunned) stunned.show(); else stunned.hide();
if (Hallucination) hallu.show(); else hallu.hide();
const char* enc=enc_stat[near_capacity()];
if (enc[0]==' ' || !enc[0]) {
encumber.hide();
} else {
encumber.setIcon(p_encumber[near_capacity()-1]);
encumber.setLabel(enc);
encumber.show();
}
if (u.mtimedone) {
buf = nh_capitalize_words(mons[u.umonnum].mname);
} else {
buf = rank_of(u.ulevel, pl_character[0], ::flags.female);
}
QString buf2;
buf2.sprintf("%s the %s", plname, buf.toLatin1().constData());
name.setLabel(buf2, NetHackQtLabelledIcon::NoNum, u.ulevel);
char buf3[BUFSZ];
if (describe_level(buf3)) {
dlevel.setLabel(buf3,true);
} else {
buf.sprintf("%s, level ", dungeons[u.uz.dnum].dname);
dlevel.setLabel(buf,(long)::depth(&u.uz));
}
gold.setLabel("Au:", money_cnt(invent));
if (u.mtimedone) {
// You're a monster!
buf.sprintf("/%d", u.mhmax);
hp.setLabel("HP:", u.mh > 0 ? u.mh : 0, buf);
level.setLabel("HD:",(long)mons[u.umonnum].mlevel);
} else {
// You're normal.
buf.sprintf("/%d", u.uhpmax);
hp.setLabel("HP:", u.uhp > 0 ? u.uhp : 0, buf);
level.setLabel("Level:",(long)u.ulevel);
}
buf.sprintf("/%d", u.uenmax);
power.setLabel("Pow:", u.uen, buf);
ac.setLabel("AC:",(long)u.uac);
#ifdef EXP_ON_BOTL
if (::flags.showexp) {
exp.setLabel("Exp:",(long)u.uexp);
} else
#endif
{
exp.setLabel("");
}
if (u.ualign.type==A_CHAOTIC) {
align.setIcon(p_chaotic);
text = "Chaotic";
} else if (u.ualign.type==A_NEUTRAL) {
align.setIcon(p_neutral);
text = "Neutral";
} else {
align.setIcon(p_lawful);
text = "Lawful";
}
align.setLabel(text);
if (::flags.time) time.setLabel("Time:",(long)moves);
else time.setLabel("");
#ifdef SCORE_ON_BOTL
if (::flags.showscore) {
score.setLabel("Score:",(long)botl_score());
} else
#endif
{
score.setLabel("");
}
if (first_set)
{
first_set=false;
name.highlightWhenChanging();
dlevel.highlightWhenChanging();
str.highlightWhenChanging();
dex.highlightWhenChanging();
con.highlightWhenChanging();
intel.highlightWhenChanging();
wis.highlightWhenChanging();
cha.highlightWhenChanging();
gold.highlightWhenChanging();
hp.highlightWhenChanging();
power.highlightWhenChanging();
ac.highlightWhenChanging(); ac.lowIsGood();
level.highlightWhenChanging();
exp.highlightWhenChanging();
align.highlightWhenChanging();
//time.highlightWhenChanging();
score.highlightWhenChanging();
hunger.highlightWhenChanging();
confused.highlightWhenChanging();
sick_fp.highlightWhenChanging();
sick_il.highlightWhenChanging();
blind.highlightWhenChanging();
stunned.highlightWhenChanging();
hallu.highlightWhenChanging();
encumber.highlightWhenChanging();
}
}
/*
* Turn off hilighted status values after a certain amount of turns.
*/
void NetHackQtStatusWindow::checkTurnEvents()
{
}
} // namespace nethack_qt4
+106
View File
@@ -0,0 +1,106 @@
// Copyright (c) Warwick Allison, 1999.
// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
// NetHack may be freely redistributed. See license for details.
// qt4stat.h -- bindings between the Qt 4 interface and the main code
#ifndef QT4STAT_H
#define QT4STAT_H
#include "qt4win.h"
#include "qt4icon.h"
namespace nethack_qt4 {
class NetHackQtStatusWindow : QWidget, public NetHackQtWindow {
Q_OBJECT
public:
NetHackQtStatusWindow();
virtual QWidget* Widget();
virtual void Clear();
virtual void Display(bool block);
virtual void CursorTo(int x,int y);
virtual void PutStr(int attr, const QString& text);
void fadeHighlighting();
protected:
//RLC void resizeEvent(QResizeEvent*);
private slots:
void doUpdate();
private:
enum { hilight_time=1 };
QPixmap p_str;
QPixmap p_dex;
QPixmap p_con;
QPixmap p_int;
QPixmap p_wis;
QPixmap p_cha;
QPixmap p_chaotic;
QPixmap p_neutral;
QPixmap p_lawful;
QPixmap p_satiated;
QPixmap p_hungry;
QPixmap p_confused;
QPixmap p_sick_fp;
QPixmap p_sick_il;
QPixmap p_blind;
QPixmap p_stunned;
QPixmap p_hallu;
QPixmap p_encumber[5];
NetHackQtLabelledIcon name;
NetHackQtLabelledIcon dlevel;
NetHackQtLabelledIcon str;
NetHackQtLabelledIcon dex;
NetHackQtLabelledIcon con;
NetHackQtLabelledIcon intel;
NetHackQtLabelledIcon wis;
NetHackQtLabelledIcon cha;
NetHackQtLabelledIcon gold;
NetHackQtLabelledIcon hp;
NetHackQtLabelledIcon power;
NetHackQtLabelledIcon ac;
NetHackQtLabelledIcon level;
NetHackQtLabelledIcon exp;
NetHackQtLabelledIcon align;
NetHackQtLabelledIcon time;
NetHackQtLabelledIcon score;
NetHackQtLabelledIcon hunger;
NetHackQtLabelledIcon confused;
NetHackQtLabelledIcon sick_fp;
NetHackQtLabelledIcon sick_il;
NetHackQtLabelledIcon blind;
NetHackQtLabelledIcon stunned;
NetHackQtLabelledIcon hallu;
NetHackQtLabelledIcon encumber;
QFrame hline1;
QFrame hline2;
QFrame hline3;
int cursy;
bool first_set;
void nullOut();
void updateStats();
void checkTurnEvents();
};
} // namespace nethack_qt4
#endif
+83
View File
@@ -0,0 +1,83 @@
// Copyright (c) Warwick Allison, 1999.
// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
// NetHack may be freely redistributed. See license for details.
// qt4str.cpp -- some string functions
#include <QtCore/QString>
#include <QtCore/QStringList>
#include "qt4str.h"
namespace nethack_qt4 {
// Bounded string copy
size_t str_copy(char *dest, const char *src, size_t max)
{
size_t len = strlen(src);
if (max != 0) {
size_t csize = len;
if (len > max - 1) {
len = max - 1;
}
memcpy(dest, src, csize);
dest[csize] = '\0';
}
return len;
}
QString str_titlecase(const QString& str)
{
if (str == "") { return str; }
return str.left(1).toUpper() + str.mid(1).toLower();
}
QString nh_capitalize_words(const QString& str)
{
QStringList words = str.split(" ");
for (size_t i = 0; i < words.size(); ++i) {
words[i] = str_titlecase(words[i]);
}
return words.join(" ");
}
int cp437(int ch)
{
static const unsigned short cp437table[] = {
0x0000, 0x263A, 0x263B, 0x2665, 0x2666, 0x2663, 0x2660, 0x2022,
0x25D8, 0x25CB, 0x25D9, 0x2642, 0x2640, 0x266A, 0x266B, 0x263C,
0x25BA, 0x25C4, 0x2195, 0x203C, 0x00B6, 0x00A7, 0x25AC, 0x21A8,
0x2191, 0x2193, 0x2192, 0x2190, 0x221F, 0x2194, 0x25B2, 0x25BC,
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x2302,
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7,
0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9,
0x00FF, 0x00D6, 0x00DC, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA,
0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F,
0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B,
0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4,
0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229,
0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248,
0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0,
};
return cp437table[(unsigned char)ch];
}
} // namespace nethack_qt4
+24
View File
@@ -0,0 +1,24 @@
// Copyright (c) Warwick Allison, 1999.
// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
// NetHack may be freely redistributed. See license for details.
// qt4str.h -- various string functions
#ifndef QT4STR_H
#define QT4STR_H
namespace nethack_qt4 {
// Bounded string copy
extern size_t str_copy(char *dest, const char *src, size_t max);
// Case mappings
extern QString str_titlecase(const QString& str);
extern QString nh_capitalize_words(const QString& str);
// Map symbol conversion
extern int cp437(int ch);
} // namespace nethack_qt4
#endif
+99
View File
@@ -0,0 +1,99 @@
// Copyright (c) Warwick Allison, 1999.
// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
// NetHack may be freely redistributed. See license for details.
// qt4streq.cpp -- string requestor
#include "hack.h"
#undef Invisible
#undef Warning
#undef index
#undef msleep
#undef rindex
#undef wizard
#undef yn
#undef min
#undef max
#include <QtGui/QtGui>
#if QT_VERSION >= 0x050000
#include <QtWidgets/QtWidgets>
#endif
#include "qt4streq.h"
#include "qt4str.h"
namespace nethack_qt4 {
// temporary
void centerOnMain(QWidget *);
// end temporary
NetHackQtStringRequestor::NetHackQtStringRequestor(QWidget *parent, const char* p, const char* cancelstr) :
QDialog(parent),
prompt(QString::fromLatin1(p),this),
input(this,"input")
{
cancel=new QPushButton(cancelstr,this);
connect(cancel,SIGNAL(clicked()),this,SLOT(reject()));
okay=new QPushButton("Okay",this);
connect(okay,SIGNAL(clicked()),this,SLOT(accept()));
connect(&input,SIGNAL(returnPressed()),this,SLOT(accept()));
okay->setDefault(true);
setFocusPolicy(Qt::StrongFocus);
}
void NetHackQtStringRequestor::resizeEvent(QResizeEvent*)
{
const int margin=5;
const int gutter=5;
int h=(height()-margin*2-gutter);
if (prompt.text().size() > 16) {
h/=3;
prompt.setGeometry(margin,margin,width()-margin*2,h);
input.setGeometry(width()*1/5,margin+h+gutter,
(width()-margin-2-gutter)*4/5,h);
} else {
h/=2;
prompt.setGeometry(margin,margin,(width()-margin*2-gutter)*2/5,h);
input.setGeometry(prompt.geometry().right()+gutter,margin,
(width()-margin-2-gutter)*3/5,h);
}
cancel->setGeometry(margin,input.geometry().bottom()+gutter,
(width()-margin*2-gutter)/2,h);
okay->setGeometry(cancel->geometry().right()+gutter,cancel->geometry().y(),
cancel->width(),h);
}
void NetHackQtStringRequestor::SetDefault(const char* d)
{
input.setText(d);
}
bool NetHackQtStringRequestor::Get(char* buffer, int maxchar)
{
input.setMaxLength(maxchar);
if (prompt.text().size() > 16) {
resize(fontMetrics().width(prompt.text())+50,fontMetrics().height()*6);
} else {
resize(fontMetrics().width(prompt.text())*2+50,fontMetrics().height()*4);
}
centerOnMain(this);
show();
input.setFocus();
exec();
if (result()) {
str_copy(buffer,input.text().toLatin1().constData(),maxchar);
return true;
} else {
return false;
}
}
} // namespace nethack_qt4
+30
View File
@@ -0,0 +1,30 @@
// Copyright (c) Warwick Allison, 1999.
// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
// NetHack may be freely redistributed. See license for details.
// qt4streq.h -- string requestor
#ifndef QT4STREQ_H
#define QT4STREQ_H
#include "qt4line.h"
namespace nethack_qt4 {
class NetHackQtStringRequestor : QDialog {
private:
QLabel prompt;
NetHackQtLineEdit input;
QPushButton* okay;
QPushButton* cancel;
public:
NetHackQtStringRequestor(QWidget *parent, const char* p,const char* cancelstr="Cancel");
void SetDefault(const char*);
bool Get(char* buffer, int maxchar=80);
virtual void resizeEvent(QResizeEvent*);
};
} // namespace nethack_qt4
#endif
+80
View File
@@ -0,0 +1,80 @@
// Copyright (c) Warwick Allison, 1999.
// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
// NetHack may be freely redistributed. See license for details.
// qt4svsel.cpp -- saved game selector
#include "hack.h"
#undef Invisible
#undef Warning
#undef index
#undef msleep
#undef rindex
#undef wizard
#undef yn
#undef min
#undef max
#include <QtGui/QtGui>
#if QT_VERSION >= 0x050000
#include <QtWidgets/QtWidgets>
#endif
#include "qt4svsel.h"
#include "qt4bind.h"
#include "qt4str.h"
namespace nethack_qt4 {
NetHackQtSavedGameSelector::NetHackQtSavedGameSelector(const char** saved) :
QDialog(NetHackQtBind::mainWidget())
{
QVBoxLayout *vbl = new QVBoxLayout(this);
QHBoxLayout* hb;
QLabel* logo = new QLabel(this); vbl->addWidget(logo);
logo->setAlignment(Qt::AlignCenter);
logo->setPixmap(QPixmap("nhsplash.xpm"));
QLabel* attr = new QLabel("by the NetHack DevTeam",this);
attr->setAlignment(Qt::AlignCenter);
vbl->addWidget(attr);
vbl->addStretch(2);
/*
QLabel* logo = new QLabel(hb);
hb = new QHBox(this);
vbl->addWidget(hb, Qt::AlignCenter);
logo->setPixmap(QPixmap(nh_icon));
logo->setAlignment(AlignRight|Qt::AlignVCenter);
new QLabel(nh_attribution,hb);
*/
hb = new QHBoxLayout(this);
vbl->addLayout(hb, Qt::AlignCenter);
QPushButton* q = new QPushButton("Quit",this);
hb->addWidget(q);
connect(q, SIGNAL(clicked()), this, SLOT(reject()));
QPushButton* c = new QPushButton("New Game",this);
hb->addWidget(c);
connect(c, SIGNAL(clicked()), this, SLOT(accept()));
c->setDefault(true);
QGroupBox* box = new QGroupBox("Saved Characters",this);
QButtonGroup *bg = new QButtonGroup(this);
vbl->addWidget(box);
QVBoxLayout *bgl = new QVBoxLayout(box);
connect(bg, SIGNAL(buttonPressed(int)), this, SLOT(done(int)));
for (int i=0; saved[i]; i++) {
QPushButton* b = new QPushButton(saved[i],box);
bg->addButton(b, i+2);
}
}
int NetHackQtSavedGameSelector::choose()
{
#if defined(QWS) // probably safe with Qt 3, too (where show!=exec in QDialog).
if ( qt_compact_mode )
showMaximized();
#endif
return exec()-2;
}
} // namespace nethack_qt4
+21
View File
@@ -0,0 +1,21 @@
// Copyright (c) Warwick Allison, 1999.
// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
// NetHack may be freely redistributed. See license for details.
// qt4svsel.h -- saved game selector
#ifndef QT4SVSEL_H
#define QT4SVSEL_H
namespace nethack_qt4 {
class NetHackQtSavedGameSelector : public QDialog {
public:
NetHackQtSavedGameSelector(const char** saved);
int choose();
};
} // namespace nethack_qt4
#endif
+136
View File
@@ -0,0 +1,136 @@
// Copyright (c) Warwick Allison, 1999.
// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
// NetHack may be freely redistributed. See license for details.
// Qt Binding for NetHack 3.4
//
// Copyright (C) 1996-2001 by Warwick W. Allison (warwick@troll.no)
//
// Contributors:
// Michael Hohmuth <hohmuth@inf.tu-dresden.de>
// - Userid control
// Svante Gerhard <svante@algonet.se>
// - .nethackrc tile and font size settings
// Dirk Schoenberger <schoenberger@signsoft.com>
// - KDE support
// - SlashEm support
// and many others for bug reports.
//
// Unfortunately, this doesn't use Qt as well as I would like,
// primarily because NetHack is fundamentally a getkey-type program
// rather than being event driven (hence the ugly key and click buffer)
// and also because this is my first major application of Qt.
//
// The problem of NetHack's getkey requirement is solved by intercepting
// key events by overiding QApplicion::notify(...), and putting them in
// a buffer. Mouse clicks on the map window are treated with a similar
// buffer. When the NetHack engine calls for a key, one is taken from
// the buffer, or if that is empty, QApplication::exec() is called.
// Whenever keys or clicks go into the buffer, QApplication::exit()
// is called.
//
// Another problem is that some NetHack players are decade-long players who
// demand complete keyboard control (while Qt and X11 conspire to make this
// difficult by having widget-based focus rather than application based -
// a good thing in general). This problem is solved by again using the key
// event buffer.
//
// Out of all this hackery comes a silver lining however, as macros for
// the super-expert and menus for the ultra-newbie are also made possible
// by the key event buffer.
//
// This includes all the definitions we need from the NetHack main
// engine. We pretend MSC is a STDC compiler, because C++ is close
// enough, and we undefine NetHack macros which conflict with Qt
// identifiers.
#define QT_DEPRECATED_WARNINGS
#include "hack.h"
#undef Invisible
#undef Warning
#undef index
#undef msleep
#undef rindex
#undef wizard
#undef yn
#undef min
#undef max
#include <QtGui/QtGui>
#if QT_VERSION >= 0x050000
#include <QtWidgets/QtWidgets>
#endif
#include "qt4win.h"
#include "qt4bind.h"
#include "qt4click.h"
#include "qt4glyph.h"
#include "qt4inv.h"
#include "qt4key.h"
#include "qt4icon.h"
#include "qt4map.h"
#include "qt4menu.h"
#include "qt4msg.h"
#include "qt4set.h"
#include <ctype.h>
#include "qt4clust.h"
#include <dirent.h>
#ifdef _WS_X11_
// For userid control
#include <unistd.h>
#endif
#ifdef USER_SOUNDS
#if QT_VERSION >= 0x050000
# include <QtMultimedia/QSound>
# else
# include <QtGui/QSound>
# endif
#endif
#ifdef USER_SOUNDS
extern void play_sound_for_message(const std::string& str);
#endif
namespace nethack_qt4 {
void
centerOnMain( QWidget* w )
{
QWidget* m = NetHackQtBind::mainWidget();
if (!m) m = qApp->desktop();
QPoint p = m->mapToGlobal(QPoint(0,0));
w->move( p.x() + m->width()/2 - w->width()/2,
p.y() + m->height()/2 - w->height()/2 );
}
NetHackQtWindow::NetHackQtWindow()
{
}
NetHackQtWindow::~NetHackQtWindow()
{
}
// XXX Use "expected ..." for now, abort or default later.
//
void NetHackQtWindow::Clear() { puts("unexpected Clear"); }
void NetHackQtWindow::Display(bool block) { puts("unexpected Display"); }
bool NetHackQtWindow::Destroy() { return true; }
void NetHackQtWindow::CursorTo(int x,int y) { puts("unexpected CursorTo"); }
void NetHackQtWindow::PutStr(int attr, const QString& text) { puts("unexpected PutStr"); }
void NetHackQtWindow::StartMenu() { puts("unexpected StartMenu"); }
void NetHackQtWindow::AddMenu(int glyph, const ANY_P* identifier, char ch, char gch, int attr,
const QString& str, bool presel) { puts("unexpected AddMenu"); }
void NetHackQtWindow::EndMenu(const QString& prompt) { puts("unexpected EndMenu"); }
int NetHackQtWindow::SelectMenu(int how, MENU_ITEM_P **menu_list) { puts("unexpected SelectMenu"); return 0; }
void NetHackQtWindow::ClipAround(int x,int y) { puts("unexpected ClipAround"); }
void NetHackQtWindow::PrintGlyph(int x,int y,int glyph) { puts("unexpected PrintGlyph"); }
//void NetHackQtWindow::PrintGlyphCompose(int x,int y,int,int) { puts("unexpected PrintGlyphCompose"); }
void NetHackQtWindow::UseRIP(int how, time_t when) { puts("unexpected UseRIP"); }
} // namespace nethack_qt4
+49
View File
@@ -0,0 +1,49 @@
// Copyright (c) Warwick Allison, 1999.
// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
// NetHack may be freely redistributed. See license for details.
// Qt Binding for NetHack 3.4
//
// Unfortunately, this doesn't use Qt as well as I would like,
// primarily because NetHack is fundamentally a getkey-type
// program rather than being event driven (hence the ugly key
// and click buffer rather), but also because this is my first
// major application of Qt.
//
#ifndef qt4win_h
#define qt4win_h
namespace nethack_qt4 {
class NetHackQtWindow {
public:
NetHackQtWindow();
virtual ~NetHackQtWindow();
virtual QWidget* Widget() =0;
virtual void Clear();
virtual void Display(bool block);
virtual bool Destroy();
virtual void CursorTo(int x,int y);
virtual void PutStr(int attr, const QString& text);
void PutStr(int attr, const char *text)
{
PutStr(attr, QString::fromUtf8(text).replace(QChar(0x200B), ""));
}
virtual void StartMenu();
virtual void AddMenu(int glyph, const ANY_P* identifier, char ch, char gch, int attr,
const QString& str, bool presel);
virtual void EndMenu(const QString& prompt);
virtual int SelectMenu(int how, MENU_ITEM_P **menu_list);
virtual void ClipAround(int x,int y);
virtual void PrintGlyph(int x,int y,int glyph);
virtual void UseRIP(int how, time_t when);
int nhid;
};
} // namespace nethack_qt4
#endif
+134
View File
@@ -0,0 +1,134 @@
// Copyright (c) Warwick Allison, 1999.
// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
// NetHack may be freely redistributed. See license for details.
// qt4xcmd.cpp -- extended command widget
#include "hack.h"
#include "func_tab.h"
#undef Invisible
#undef Warning
#undef index
#undef msleep
#undef rindex
#undef wizard
#undef yn
#undef min
#undef max
#include <QtGui/QtGui>
#if QT_VERSION >= 0x050000
#include <QtWidgets/QtWidgets>
#endif
#include "qt4xcmd.h"
#include "qt4xcmd.moc"
#include "qt4bind.h"
#include "qt4set.h"
#include "qt4str.h"
namespace nethack_qt4 {
// temporary
void centerOnMain(QWidget *);
// end temporary
NetHackQtExtCmdRequestor::NetHackQtExtCmdRequestor(QWidget *parent) :
QDialog(parent)
{
QVBoxLayout *l = new QVBoxLayout(this);
QPushButton* can = new QPushButton("Cancel", this);
can->setDefault(true);
can->setMinimumSize(can->sizeHint());
l->addWidget(can);
prompt = new QLabel("#", this);
l->addWidget(prompt);
QButtonGroup *group=new QButtonGroup(this);
QGroupBox *grid=new QGroupBox("Extended commands",this);
l->addWidget(grid);
int i;
int butw=50;
QFontMetrics fm = fontMetrics();
for (i=0; extcmdlist[i].ef_txt; i++) {
butw = std::max(butw,30+fm.width(extcmdlist[i].ef_txt));
}
int ncols=4;
QVBoxLayout* bl = new QVBoxLayout(grid);
bl->addSpacing(fm.height());
QGridLayout* gl = new QGridLayout();
bl->addLayout(gl);
for (i=0; extcmdlist[i].ef_txt; i++) {
QPushButton* pb=new QPushButton(extcmdlist[i].ef_txt, grid);
pb->setMinimumSize(butw,pb->sizeHint().height());
group->addButton(pb, i+1);
gl->addWidget(pb,i/ncols,i%ncols);
}
group->addButton(can, 0);
connect(group,SIGNAL(buttonPressed(int)),this,SLOT(done(int)));
bl->activate();
l->activate();
resize(1,1);
}
void NetHackQtExtCmdRequestor::cancel()
{
reject();
}
void NetHackQtExtCmdRequestor::keyPressEvent(QKeyEvent *event)
{
QString text = event->text();
if (text == "\r" || text == "\n" || text == " " || text == "\033")
{
reject();
}
else if (text == "\b")
{
QString promptstr = prompt->text();
if (promptstr != "#")
prompt->setText(promptstr.left(promptstr.size()-1));
}
else
{
QString promptstr = prompt->text() + text;
QString typedstr = promptstr.mid(1); // skip the '#'
unsigned matches = 0;
unsigned match = 0;
for (unsigned i=0; extcmdlist[i].ef_txt; i++) {
if (QString(extcmdlist[i].ef_txt).startsWith(typedstr)) {
++matches;
if (matches >= 2)
break;
match = i;
}
}
if (matches == 1)
done(match+1);
else if (matches >= 2)
prompt->setText(promptstr);
}
}
int NetHackQtExtCmdRequestor::get()
{
const int none = -10;
resize(1,1); // pack
centerOnMain(this);
// Add any keys presently buffered to the prompt
setResult(none);
while (NetHackQtBind::qt_kbhit() && result() == none) {
int ch = NetHackQtBind::qt_nhgetch();
QKeyEvent event(QEvent::KeyPress, 0, Qt::NoModifier, QChar(ch));
keyPressEvent(&event);
}
if (result() == none)
exec();
return result()-1;
}
} // namespace nethack_qt4
+31
View File
@@ -0,0 +1,31 @@
// Copyright (c) Warwick Allison, 1999.
// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
// NetHack may be freely redistributed. See license for details.
// qt4xcmd.h -- extended command widget
#ifndef QT4XCMD_H
#define QT4XCMD_H
namespace nethack_qt4 {
class NetHackQtExtCmdRequestor : public QDialog {
Q_OBJECT
protected:
virtual void keyPressEvent(QKeyEvent *event);
public:
NetHackQtExtCmdRequestor(QWidget *parent);
int get();
private:
QLabel *prompt;
private slots:
void cancel();
};
} // namespace nethack_qt4
#endif
+244
View File
@@ -0,0 +1,244 @@
// Copyright (c) Warwick Allison, 1999.
// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
// NetHack may be freely redistributed. See license for details.
// qt4yndlg.cpp -- yes/no dialog
#include "hack.h"
#undef Invisible
#undef Warning
#undef index
#undef msleep
#undef rindex
#undef wizard
#undef yn
#undef min
#undef max
#include <QtGui/QtGui>
#if QT_VERSION >= 0x050000
#include <QtWidgets/QtWidgets>
#endif
#include "qt4yndlg.h"
#include "qt4yndlg.moc"
#include "qt4str.h"
// temporary
extern int qt_compact_mode;
// end temporary
namespace nethack_qt4 {
// temporary
void centerOnMain(QWidget *);
// end temporary
NetHackQtYnDialog::NetHackQtYnDialog(QWidget *parent,const QString& q,const char* ch,char df) :
QDialog(parent),
question(q), choices(ch), def(df),
keypress('\033')
{
setWindowTitle("NetHack: Question");
}
char NetHackQtYnDialog::Exec()
{
QString ch(QString::fromLatin1(choices));
int ch_per_line=6;
QString qlabel;
QString enable;
if ( qt_compact_mode && !choices ) {
ch = "";
// expand choices from prompt
// ##### why isn't choices set properly???
int c = question.indexOf(QChar('['));
qlabel = QString(question).left(c);
if ( c >= 0 ) {
c++;
if ( question[c] == '-' )
ch.append(question[c++]);
unsigned from=0;
while ( c < question.size() && question[c] != ']' && question[c] != ' ' ) {
if ( question[c] == '-' ) {
from = question[c-1].unicode();
} else if ( from != 0 ) {
for (unsigned f=from+1; f<=question[c]; f++)
ch.append(QChar(f));
from = 0;
} else {
ch.append(question[c]);
from = 0;
}
c++;
}
if ( question[c] == ' ' ) {
while ( c < question.size() && question[c] != ']' ) {
if ( question[c] == '*' || question[c] == '?' )
ch.append(question[c]);
c++;
}
}
}
if ( question.indexOf("what direction") >= 0 ) {
// We replace this regardless, since sometimes you get choices.
const char* d = Cmd.dirchars;
enable=ch;
ch="";
ch.append(d[1]);
ch.append(d[2]);
ch.append(d[3]);
ch.append(d[0]);
ch.append('.');
ch.append(d[4]);
ch.append(d[7]);
ch.append(d[6]);
ch.append(d[5]);
ch.append(d[8]);
ch.append(d[9]);
ch_per_line = 3;
def = ' ';
} else {
// Hmm... they'll have to use a virtual keyboard
}
} else {
ch = QString::fromLatin1(choices);
qlabel = question.replace(QChar(0x200B), QString(""));
}
if (!ch.isNull()) {
QVBoxLayout *vb = new QVBoxLayout;
bool bigq = qlabel.length()>40;
if ( bigq ) {
QLabel* q = new QLabel(qlabel,this);
q->setAlignment(Qt::AlignLeft);
q->setWordWrap(true);
q->setMargin(4);
vb->addWidget(q);
}
QGroupBox *group = new QGroupBox(bigq ? QString::null : qlabel, this);
vb->addWidget(group);
QHBoxLayout *groupbox = new QHBoxLayout();
group->setLayout(groupbox);
QButtonGroup *bgroup = new QButtonGroup(group);
int nchoices=ch.length();
bool allow_count=ch.contains('#');
QString yn = "yn", ynq = "ynq";
bool is_ynq = ch == yn || ch == ynq;
const int margin=8;
const int gutter=8;
const int extra=fontMetrics().height(); // Extra for group
int x=margin, y=extra+margin;
int butsize=fontMetrics().height()*2+5;
QPushButton* button;
for (int i=0; i<nchoices && ch[i]!='\033'; i++) {
QString button_name = QString(ch[i]);
if (is_ynq) {
if (button_name == ynq.mid(0, 1)) {
button_name = "Yes";
} else if (button_name == ynq.mid(1, 1)) {
button_name = "No";
} else if (button_name == ynq.mid(2, 1)) {
button_name = "Cancel";
}
}
button=new QPushButton(button_name);
if ( !enable.isNull() ) {
if ( !enable.contains(ch[i]) )
button->setEnabled(false);
}
button->setFixedSize(butsize,butsize); // Square
if (ch[i]==def) button->setDefault(true);
if (i%10==9) {
// last in row
x=margin;
y+=butsize+gutter;
} else {
x+=butsize+gutter;
}
groupbox->addWidget(button);
bgroup->addButton(button, i);
}
connect(bgroup,SIGNAL(buttonClicked(int)),this,SLOT(doneItem(int)));
QLabel* lb=0;
QLineEdit* le=0;
if (allow_count) {
QHBoxLayout *hb = new QHBoxLayout(this);
lb=new QLabel("Count: ");
hb->addWidget(lb);
le=new QLineEdit();
hb->addWidget(le);
vb->addLayout(hb);
}
setLayout(vb);
adjustSize();
centerOnMain(this);
show();
char choice=0;
char ch_esc=0;
for (uint i=0; i<ch.length(); i++) {
if (ch[i].unicode()=='q') ch_esc='q';
else if (!ch_esc && ch[i].unicode()=='n') ch_esc='n';
}
exec();
if ( result() == 0) {
choice = ch_esc ? ch_esc : def ? def : ' ';
} else if ( result() == 1 ) {
choice = def ? def : ch_esc ? ch_esc : ' ';
} else if ( result() >= 1000 ) {
choice = ch[result() - 1000].unicode();
}
if (allow_count && !le->text().isEmpty()) {
yn_number=le->text().toInt();
choice='#';
}
return choice;
} else {
QLabel label(qlabel,this);
QPushButton cancel("Dismiss",this);
label.setFrameStyle(QFrame::Box|QFrame::Sunken);
label.setAlignment(Qt::AlignCenter);
label.resize(fontMetrics().width(qlabel)+60,30+fontMetrics().height());
cancel.move(width()/2-cancel.width()/2,label.geometry().bottom()+8);
connect(&cancel,SIGNAL(clicked()),this,SLOT(reject()));
centerOnMain(this);
setResult(-1);
show();
keypress = '\033';
exec();
return keypress;
}
}
void NetHackQtYnDialog::keyPressEvent(QKeyEvent* event)
{
// Don't want QDialog's Return/Esc behaviour
//RLC ...or do we?
QString text(event->text());
if (choices == NULL || choices[0] == 0) {
if (text != "") {
keypress = text.toUcs4()[0];
done(1);
}
} else {
int where = QString::fromLatin1(choices).indexOf(text);
if (where != -1 && text != "#") {
done(where+1000);
} else {
QDialog::keyPressEvent(event);
}
}
}
void NetHackQtYnDialog::doneItem(int i)
{
done(i+1000);
}
} // namespace nethack_qt4
+34
View File
@@ -0,0 +1,34 @@
// Copyright (c) Warwick Allison, 1999.
// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
// NetHack may be freely redistributed. See license for details.
// qt4yndlg.h -- yes/no dialog
#ifndef QT4YNDLG_H
#define QT4YNDLG_H
namespace nethack_qt4 {
class NetHackQtYnDialog : QDialog {
Q_OBJECT
private:
QString question;
const char* choices;
char def;
char keypress;
protected:
virtual void keyPressEvent(QKeyEvent*);
private slots:
void doneItem(int);
public:
NetHackQtYnDialog(QWidget *,const QString&,const char*,char);
char Exec();
};
} // namespace nethack_qt4
#endif