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-07 20:26:02 +03:00
parent a4706b0928
commit ed335dd0a7
52 changed files with 8024 additions and 9 deletions

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
b_helyer for the fix to sys/share/pcmain.c
Ray Chason's MSDOS port support for some VESA modes
Ray Chason's Qt4 windowport
Darshan Shaligram's pet ranged attack
Jason Dorje Short's key rebinding
Maxime Bacoux's new DUMPLOG: compile-time option to enable logging of

View File

@@ -168,6 +168,9 @@ E boolean NDECL(status_hilite_menu);
/* ### 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));
#ifdef USE_TRAMPOLI
E int NDECL(doextcmd);

View File

@@ -117,7 +117,6 @@ static int NDECL((*timed_occ_fn));
STATIC_PTR int NDECL(doprev_message);
STATIC_PTR int NDECL(timed_occupation);
STATIC_PTR int NDECL(doextcmd);
STATIC_PTR int NDECL(domonability);
STATIC_PTR int NDECL(dotravel);
STATIC_PTR int NDECL(doterrain);
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);
#endif
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(doconduct); /**/
STATIC_DCL void FDECL(enlght_line, (const char *, const char *, const char *,
const char *));
@@ -523,7 +520,7 @@ extcmd_via_menu()
#endif /* TTY_GRAPHICS */
/* #monster command - use special monster ability while polymorphed */
STATIC_PTR int
int
domonability(VOID_ARGS)
{
if (can_breathe(youmonst.data))
@@ -2734,7 +2731,7 @@ int msgflag; /* for variant message phrasing */
/* KMH, #conduct
* (shares enlightenment's tense handling)
*/
STATIC_PTR int
int
doconduct(VOID_ARGS)
{
show_conduct(0);
@@ -3283,7 +3280,7 @@ dokeylist(VOID_ARGS)
destroy_nhwindow(datawin);
}
STATIC_OVL char
char
cmd_from_func(fn)
int NDECL((*fn));
{

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
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
#
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 -lXpm -lXext -lXt -lX11 -lSM -lICE -lm # BSD/OS 2.0
#
# libraries for Qt
# libraries for Qt 3
WINQTLIB = -L$(QTDIR)/lib -lqt
#
# libraries for Qt 4
WINQT4LIB = `pkg-config QtGui --libs`
#
# libraries for KDE (with Qt)
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)
WINCSRC = $(WINTTYSRC) $(WINX11SRC) $(WINGNOMESRC) $(WINGEMSRC)
# 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
CHAINSRC = ../win/chain/wc_chainin.c ../win/chain/wc_chainout.c \
@@ -486,7 +505,7 @@ objects.o:
$(CC) $(CFLAGS) -c objects.c
@rm -f $(MAKEDEFS)
# Qt windowport meta-object-compiler output
# Qt 3 windowport meta-object-compiler output
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
$(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'
$(MAKEDEFS): $(FIRSTOBJ) \
../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
qttableview.o: ../win/Qt/qttableview.cpp ../include/qttableview.h
$(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)
$(CC) $(CFLAGS) -c ../win/chain/wc_chainin.c
wc_chainout.o: ../win/chain/wc_chainout.c $(HACK_H)

47
sys/unix/hints/linux-qt4 Normal file
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
win/Qt4/qt4bind.cpp Normal file
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
win/Qt4/qt4bind.h Normal file
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
win/Qt4/qt4click.cpp Normal file
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
win/Qt4/qt4click.h Normal file
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
win/Qt4/qt4clust.cpp Normal file
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
win/Qt4/qt4clust.h Normal file
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
win/Qt4/qt4delay.cpp Normal file
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
win/Qt4/qt4delay.h Normal file
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
win/Qt4/qt4glyph.cpp Normal file
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
win/Qt4/qt4glyph.h Normal file
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
win/Qt4/qt4icon.cpp Normal file
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
win/Qt4/qt4icon.h Normal file
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
win/Qt4/qt4inv.cpp Normal file
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
win/Qt4/qt4inv.h Normal file
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
win/Qt4/qt4kde0.h Normal file
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
win/Qt4/qt4key.cpp Normal file
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
win/Qt4/qt4key.h Normal file
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
win/Qt4/qt4line.cpp Normal file
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
win/Qt4/qt4line.h Normal file
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
win/Qt4/qt4main.cpp Normal file

File diff suppressed because it is too large Load Diff

94
win/Qt4/qt4main.h Normal file
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
win/Qt4/qt4map.cpp Normal file
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
win/Qt4/qt4map.h Normal file
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
win/Qt4/qt4menu.cpp Normal file
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
win/Qt4/qt4menu.h Normal file
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
win/Qt4/qt4msg.cpp Normal file
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
win/Qt4/qt4msg.h Normal file
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
win/Qt4/qt4plsel.cpp Normal file
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
win/Qt4/qt4plsel.h Normal file
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
win/Qt4/qt4rip.cpp Normal file
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
win/Qt4/qt4rip.h Normal file
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
win/Qt4/qt4set.cpp Normal file
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
win/Qt4/qt4set.h Normal file
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
win/Qt4/qt4stat.cpp Normal file
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
win/Qt4/qt4stat.h Normal file
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
win/Qt4/qt4str.cpp Normal file
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
win/Qt4/qt4str.h Normal file
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
win/Qt4/qt4streq.cpp Normal file
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
win/Qt4/qt4streq.h Normal file
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
win/Qt4/qt4svsel.cpp Normal file
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
win/Qt4/qt4svsel.h Normal file
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
win/Qt4/qt4win.cpp Normal file
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
win/Qt4/qt4win.h Normal file
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
win/Qt4/qt4xcmd.cpp Normal file
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
win/Qt4/qt4xcmd.h Normal file
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
win/Qt4/qt4yndlg.cpp Normal file
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
win/Qt4/qt4yndlg.h Normal file
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