1 // Copyright (c) Warwick Allison, 1999.
2 // Qt4 conversion copyright (c) Ray Chason, 2012-2014.
3 // NetHack may be freely redistributed.  See license for details.
4 
5 // qt4menu.cpp -- a menu or text-list widget
6 
7 extern "C" {
8 #include "hack.h"
9 }
10 #undef Invisible
11 #undef Warning
12 #undef index
13 #undef msleep
14 #undef rindex
15 #undef wizard
16 #undef yn
17 #undef min
18 #undef max
19 
20 #include <QtGui/QtGui>
21 #if QT_VERSION >= 0x050000
22 #include <QtWidgets/QtWidgets>
23 #endif
24 #include "qt4menu.h"
25 #include "qt4menu.moc"
26 #include "qt4glyph.h"
27 #include "qt4set.h"
28 #include "qt4streq.h"
29 #include "qt4str.h"
30 
31 // temporary
32 extern "C" int qt_compact_mode;
33 // end temporary
34 
35 extern "C" struct menucoloring *menu_colorings;
36 
37 namespace nethack_qt4 {
38 
39 // temporary
40 void centerOnMain( QWidget* w );
41 // end temporary
42 
sizeHint() const43 QSize NetHackQtTextListBox::sizeHint() const
44 {
45     QScrollBar *hscroll = horizontalScrollBar();
46     int hsize = hscroll ? hscroll->height() : 0;
47     return QSize(TotalWidth()+hsize, TotalHeight()+hsize);
48 }
49 
TotalWidth() const50 int NetHackQtMenuListBox::TotalWidth() const
51 {
52     int width = 0;
53 
54     for (int col = 0; col < columnCount(); ++col) {
55 	width += columnWidth(col);
56     }
57     return width;
58 }
59 
TotalHeight() const60 int NetHackQtMenuListBox::TotalHeight() const
61 {
62     int height = 0;
63 
64     for (int row = 0; row < rowCount(); ++row) {
65 	height += rowHeight(row);
66     }
67     return height;
68 }
69 
sizeHint() const70 QSize NetHackQtMenuListBox::sizeHint() const
71 {
72     QScrollBar *hscroll = horizontalScrollBar();
73     int hsize = hscroll ? hscroll->height() : 0;
74     return QSize(TotalWidth()+hsize, TotalHeight()+hsize);
75 }
76 
77 // Table view columns:
78 //
79 // [pick-count] [accel] [glyph] [string]
80 //
81 // Maybe accel should be near string.  We'll see.
82 // pick-count normally blank.
83 //   double-clicking or click-on-count gives pop-up entry
84 // string is green when selected
85 //
NetHackQtMenuWindow(QWidget * parent)86 NetHackQtMenuWindow::NetHackQtMenuWindow(QWidget *parent) :
87     QDialog(parent),
88     table(new NetHackQtMenuListBox()),
89     prompt(0),
90     counting(false)
91 {
92     QGridLayout *grid = new QGridLayout();
93     table->setColumnCount(5);
94     table->setFrameStyle(QFrame::Panel|QFrame::Sunken);
95     table->setLineWidth(2);
96     table->setShowGrid(false);
97     table->horizontalHeader()->hide();
98     table->verticalHeader()->hide();
99 
100     ok=new QPushButton("Ok");
101     connect(ok,SIGNAL(clicked()),this,SLOT(accept()));
102 
103     cancel=new QPushButton("Cancel");
104     connect(cancel,SIGNAL(clicked()),this,SLOT(reject()));
105 
106     all=new QPushButton("All");
107     connect(all,SIGNAL(clicked()),this,SLOT(All()));
108 
109     none=new QPushButton("None");
110     connect(none,SIGNAL(clicked()),this,SLOT(ChooseNone()));
111 
112     invert=new QPushButton("Invert");
113     connect(invert,SIGNAL(clicked()),this,SLOT(Invert()));
114 
115     search=new QPushButton("Search");
116     connect(search,SIGNAL(clicked()),this,SLOT(Search()));
117 
118     QPoint pos(0,ok->height());
119     move(pos);
120     prompt.setParent(this,0);
121     prompt.move(pos);
122 
123     grid->addWidget(ok, 0, 0);
124     grid->addWidget(cancel, 0, 1);
125     grid->addWidget(all, 0, 2);
126     grid->addWidget(none, 0, 3);
127     grid->addWidget(invert, 0, 4);
128     grid->addWidget(search, 0, 5);
129     grid->addWidget(&prompt, 1, 0, 1, 7);
130     grid->addWidget(table, 2, 0, 1, 7);
131     grid->setColumnStretch(6, 1);
132     grid->setRowStretch(2, 1);
133     setFocusPolicy(Qt::StrongFocus);
134     table->setFocusPolicy(Qt::NoFocus);
135     connect(table, SIGNAL(cellClicked(int,int)), this, SLOT(cellToggleSelect(int,int)));
136 
137     setLayout(grid);
138 }
139 
~NetHackQtMenuWindow()140 NetHackQtMenuWindow::~NetHackQtMenuWindow()
141 {
142 }
143 
Widget()144 QWidget* NetHackQtMenuWindow::Widget() { return this; }
145 
StartMenu()146 void NetHackQtMenuWindow::StartMenu()
147 {
148     table->setRowCount((itemcount=0));
149     next_accel=0;
150     has_glyphs=false;
151 }
152 
MenuItem()153 NetHackQtMenuWindow::MenuItem::MenuItem() :
154     str("")
155 {
156 }
157 
~MenuItem()158 NetHackQtMenuWindow::MenuItem::~MenuItem()
159 {
160 }
161 
AddMenu(int glyph,const ANY_P * identifier,char ch,char gch,int attr,const QString & str,bool presel)162 void NetHackQtMenuWindow::AddMenu(int glyph, const ANY_P* identifier,
163 	char ch, char gch, int attr, const QString& str, bool presel)
164 {
165     if (!ch && identifier->a_void!=0) {
166 	// Supply a keyboard accelerator.  Limited supply.
167 	static char accel[]="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
168 	if (accel[next_accel]) {
169 	    ch=accel[next_accel++];
170 	}
171     }
172 
173     if ((int)itemlist.size() < itemcount+1) {
174 	itemlist.resize(itemcount*4+10);
175     }
176     itemlist[itemcount].glyph=glyph;
177     itemlist[itemcount].identifier=*identifier;
178     itemlist[itemcount].ch=ch;
179     itemlist[itemcount].gch=gch;
180     itemlist[itemcount].attr=attr;
181     itemlist[itemcount].str=str;
182     itemlist[itemcount].selected=presel;
183     itemlist[itemcount].count=-1;
184     itemlist[itemcount].color = -1;
185     // Display the boulder symbol correctly
186     if (str.left(8) == "boulder\t") {
187 	int bracket = str.indexOf('[');
188 	if (bracket != -1) {
189 	    itemlist[itemcount].str = str.left(bracket+1)
190 		+ QChar(cp437(str.at(bracket+1).unicode()))
191 		+ str.mid(bracket+2);
192 	}
193     }
194     int mcolor, mattr;
195     if (attr == 0
196         && get_menu_coloring(str.toLatin1().constData(), &mcolor, &mattr)) {
197 	itemlist[itemcount].attr = mattr;
198 	itemlist[itemcount].color = mcolor;
199     }
200     ++itemcount;
201 
202     if (glyph!=NO_GLYPH) has_glyphs=true;
203 }
204 
EndMenu(const QString & p)205 void NetHackQtMenuWindow::EndMenu(const QString& p)
206 {
207     prompt.setText(p);
208     promptstr = p;
209 }
210 
SelectMenu(int h,MENU_ITEM_P ** menu_list)211 int NetHackQtMenuWindow::SelectMenu(int h, MENU_ITEM_P **menu_list)
212 {
213     QFont tablefont(qt_settings->normalFont());
214     table->setFont(tablefont);
215 
216     table->setRowCount(itemcount);
217 
218     how=h;
219 
220     ok->setEnabled(how!=PICK_ONE);ok->setDefault(how!=PICK_ONE);
221     cancel->setEnabled(how!=PICK_NONE);
222     all->setEnabled(how==PICK_ANY);
223     none->setEnabled(how==PICK_ANY);
224     invert->setEnabled(how==PICK_ANY);
225     search->setEnabled(how!=PICK_NONE);
226 
227     setResult(-1);
228 
229     // Set contents of table
230     QFontMetrics fm(table->font());
231     for (int i = 0; i < 5; i++) {
232 	table->setColumnWidth(i, 0);
233     }
234     for (int i = 0; i < itemcount; i++) {
235 	AddRow(i, itemlist[i]);
236     }
237 
238     // Determine column widths
239     std::vector<int> col_widths;
240     for (std::size_t i = 0; i < itemlist.size(); ++i) {
241 	QStringList columns = itemlist[i].str.split("\t");
242         if (!itemlist[i].Selectable() && columns.size() == 1)
243         {
244             // Nonselectable line with no column dividers
245             // Assume this is a section header
246             continue;
247         }
248 	for (std::size_t j = 0U; j < columns.size(); ++j) {
249 	    int w = fm.width(columns[j] + "  \t");
250 	    if (j >= col_widths.size()) {
251 		col_widths.push_back(w);
252 	    } else if (col_widths[j] < w) {
253 		col_widths[j] = w;
254 	    }
255 	}
256     }
257 
258     // Pad each column to its column width
259     for (std::size_t i = 0U; i < itemlist.size(); ++i) {
260 	QTableWidgetItem *twi = table->item(i, 4);
261 	if (twi == NULL) { continue; }
262 	QString text = twi->text();
263 	QStringList columns = text.split("\t");
264 	for (std::size_t j = 0U; j+1U < columns.size(); ++j) {
265 	    columns[j] += "\t";
266 	    int width = col_widths[j];
267 	    while (fm.width(columns[j]) < width) {
268 		columns[j] += "\t";
269 	    }
270 	}
271 	text = columns.join("");
272 	twi->setText(text);
273 	WidenColumn(4, fm.width(text));
274     }
275 
276     // FIXME:  size for compact mode
277     //resize(this->width(), parent()->height()*7/8);
278     move(0, 0);
279     adjustSize();
280     centerOnMain(this);
281     exec();
282     int result=this->result();
283 
284     *menu_list=0;
285     if (result>0 && how!=PICK_NONE) {
286 	if (how==PICK_ONE) {
287 	    int i;
288 	    for (i=0; i<itemcount && !isSelected(i); i++)
289 		;
290 	    if (i<itemcount) {
291 		*menu_list=(MENU_ITEM_P *)alloc(sizeof(MENU_ITEM_P)*1);
292 		(*menu_list)[0].item=itemlist[i].identifier;
293 		(*menu_list)[0].count=count(i);
294 		return 1;
295 	    } else {
296 		return 0;
297 	    }
298 	} else {
299 	    int selcount=0;
300 	    for (int i=0; i<itemcount; i++)
301 		if (isSelected(i)) selcount++;
302 	    if (selcount) {
303 		*menu_list=(MENU_ITEM_P *)alloc(sizeof(MENU_ITEM_P)*selcount);
304 		int j=0;
305 		for (int i=0; i<itemcount; i++) {
306 		    if (isSelected(i)) {
307 			(*menu_list)[j].item=itemlist[i].identifier;
308 			(*menu_list)[j].count=count(i);
309 			j++;
310 		    }
311 		}
312 		return selcount;
313 	    } else {
314 		return 0;
315 	    }
316 	}
317     } else {
318 	return -1;
319     }
320 }
321 
AddRow(int row,const MenuItem & mi)322 void NetHackQtMenuWindow::AddRow(int row, const MenuItem& mi)
323 {
324     static const QColor colors[] = {
325 	QColor(64, 64, 64),
326 	QColor(Qt::red),
327 	QColor(0, 191, 0),
328 	QColor(127, 127, 0),
329 	QColor(Qt::blue),
330 	QColor(Qt::magenta),
331 	QColor(Qt::cyan),
332 	QColor(Qt::gray),
333 	QColor(Qt::white),
334 	QColor(255, 127, 0),
335 	QColor(127, 255, 127),
336 	QColor(Qt::yellow),
337 	QColor(127, 127, 255),
338 	QColor(255, 127, 255),
339 	QColor(127, 255, 255),
340 	QColor(Qt::white)
341     };
342     QFontMetrics fm(table->font());
343     QTableWidgetItem *twi;
344 
345     if (mi.Selectable() && how != PICK_NONE) {
346 	// Count
347 	twi = new QTableWidgetItem("");
348 	table->setItem(row, 0, twi);
349 	twi->setFlags(Qt::ItemIsEnabled);
350 	WidenColumn(0, fm.width("999999"));
351 	// Check box, set if selected
352 	QCheckBox *cb = new QCheckBox();
353 	cb->setChecked(mi.selected);
354 	cb->setFocusPolicy(Qt::NoFocus);
355 	if (how == PICK_ONE)
356 	    connect(cb, SIGNAL(clicked(bool)), this, SLOT(DoSelection(bool)));
357 	table->setCellWidget(row, 1, cb);
358 	WidenColumn(1, cb->width());
359     }
360     if (mi.glyph != NO_GLYPH) {
361 	// Icon
362 	QPixmap pm(qt_settings->glyphs().glyph(mi.glyph));
363 	twi = new QTableWidgetItem(QIcon(pm), "");
364 	table->setItem(row, 2, twi);
365 	twi->setFlags(Qt::ItemIsEnabled);
366 	WidenColumn(2, pm.width());
367     }
368     QString letter, text(mi.str);
369     if (mi.ch != 0) {
370 	// Letter specified
371 	letter = QString(mi.ch) + " - ";
372     }
373     else {
374 	// Letter is left blank, except for skills display when # and * are
375 	// presented
376 	if (text.startsWith("    ")) {
377 	    // If mi.str starts with "    ", it's meant to line up with lines
378 	    // that have a letter; we don't want that here
379 	    text = text.mid(4);
380 	} else if (text.startsWith("   #") || text.startsWith("   *")) {
381 	    // Put the * or # in the letter column
382 	    letter = text.left(4);
383 	    text = text.mid(4);
384 	}
385     }
386     twi = new QTableWidgetItem(letter);
387     table->setItem(row, 3, twi);
388     table->item(row, 3)->setFlags(Qt::ItemIsEnabled);
389     WidenColumn(3, fm.width(letter));
390     twi = new QTableWidgetItem(text);
391     table->setItem(row, 4, twi);
392     table->item(row, 4)->setFlags(Qt::ItemIsEnabled);
393     WidenColumn(4, fm.width(text));
394 
395     if (mi.color != -1) {
396 	twi->setForeground(colors[mi.color]);
397     }
398 
399     QFont itemfont(table->font());
400     switch (mi.attr) {
401     case ATR_BOLD:
402 	itemfont.setWeight(QFont::Bold);
403 	twi->setFont(itemfont);
404 	break;
405 
406     case ATR_DIM:
407 	twi->setFlags(Qt::NoItemFlags);
408 	break;
409 
410     case ATR_ULINE:
411 	itemfont.setUnderline(true);
412 	twi->setFont(itemfont);
413 	break;
414 
415     case ATR_INVERSE:
416 	{
417 	    QBrush fg = twi->foreground();
418 	    QBrush bg = twi->background();
419 	    if (fg == bg) {
420 		// default foreground and background come up the same for
421 		// some unknown reason
422 		twi->setForeground(Qt::white);
423 		twi->setBackground(Qt::black);
424 	    } else {
425 		twi->setForeground(bg);
426 		twi->setBackground(fg);
427 	    }
428 	}
429 	break;
430     }
431 }
432 
WidenColumn(int column,int width)433 void NetHackQtMenuWindow::WidenColumn(int column, int width)
434 {
435     // need to add a bit so the whole column displays
436     width += 7;
437     if (table->columnWidth(column) < width) {
438 	table->setColumnWidth(column, width);
439     }
440 }
441 
InputCount(char key)442 void NetHackQtMenuWindow::InputCount(char key)
443 {
444     if (key == '\b')
445     {
446 	if (counting)
447 	{
448 	    if (countstr.isEmpty())
449 		ClearCount();
450 	    else
451 		countstr = countstr.mid(0, countstr.size() - 1);
452 	}
453     }
454     else
455     {
456 	counting = true;
457 	countstr += QChar(key);
458     }
459     if (counting)
460 	prompt.setText("Count: " + countstr);
461 }
462 
ClearCount(void)463 void NetHackQtMenuWindow::ClearCount(void)
464 {
465     counting = false;
466     prompt.setText(promptstr);
467     countstr = "";
468 }
469 
keyPressEvent(QKeyEvent * event)470 void NetHackQtMenuWindow::keyPressEvent(QKeyEvent* event)
471 {
472     QString text = event->text();
473 
474     const QChar *uni = text.unicode();
475     for (unsigned k = 0; uni[k] != 0; k++) {
476 	unsigned key = uni[k].unicode();
477 	if (key=='\033') {
478 	    if (counting)
479 		ClearCount();
480 	    else
481 		reject();
482 	} else if (key=='\r' || key=='\n' || key==' ')
483 	    accept();
484 	else if (key==MENU_SEARCH)
485 	    Search();
486 	else if (key==MENU_SELECT_ALL || key==MENU_SELECT_PAGE)
487 	    All();
488 	else if (key==MENU_INVERT_ALL || key==MENU_INVERT_PAGE)
489 	    Invert();
490 	else if (key==MENU_UNSELECT_ALL || key==MENU_UNSELECT_PAGE)
491 	    ChooseNone();
492 	else if (('0' <= key && key <= '9') || key == '\b')
493 	    InputCount(key);
494 	else {
495 	    for (int i=0; i<itemcount; i++) {
496 		if (itemlist[i].ch == key || itemlist[i].gch == key)
497 		    ToggleSelect(i);
498 	    }
499 	}
500     }
501 }
502 
All()503 void NetHackQtMenuWindow::All()
504 {
505     if (how != PICK_ANY)
506         return;
507 
508     for (int i=0; i<itemcount; i++) {
509 	QTableWidgetItem *count = table->item(i, 0);
510 	if (count != NULL) count->setText("");
511 
512 	QCheckBox *cb = dynamic_cast<QCheckBox *>(table->cellWidget(i, 1));
513 	if (cb != NULL) cb->setChecked(true);
514     }
515 }
ChooseNone()516 void NetHackQtMenuWindow::ChooseNone()
517 {
518     if (how != PICK_ANY)
519         return;
520 
521     for (int i=0; i<itemcount; i++) {
522 	QTableWidgetItem *count = table->item(i, 0);
523 	if (count != NULL) count->setText("");
524 
525 	QCheckBox *cb = dynamic_cast<QCheckBox *>(table->cellWidget(i, 1));
526 	if (cb != NULL) cb->setChecked(false);
527     }
528 }
Invert()529 void NetHackQtMenuWindow::Invert()
530 {
531     if (how != PICK_ANY)
532         return;
533 
534     for (int i=0; i<itemcount; i++) {
535 	QTableWidgetItem *count = table->item(i, 0);
536 	if (count != NULL) count->setText("");
537 
538 	QCheckBox *cb = dynamic_cast<QCheckBox *>(table->cellWidget(i, 1));
539 	if (cb != NULL) cb->setChecked(cb->checkState() == Qt::Unchecked);
540     }
541 }
Search()542 void NetHackQtMenuWindow::Search()
543 {
544     if (how == PICK_NONE)
545         return;
546 
547     NetHackQtStringRequestor requestor(this, "Search for:");
548     char line[256];
549     if (requestor.Get(line)) {
550 	for (int i=0; i<itemcount; i++) {
551 	    if (itemlist[i].str.contains(line))
552 		ToggleSelect(i);
553 	}
554     }
555 }
ToggleSelect(int i)556 void NetHackQtMenuWindow::ToggleSelect(int i)
557 {
558     if (itemlist[i].Selectable()) {
559 	QCheckBox *cb = dynamic_cast<QCheckBox *>(table->cellWidget(i, 1));
560 	if (cb == NULL) return;
561 
562 	cb->setChecked((counting && !countstr.isEmpty())
563 		    || cb->checkState() == Qt::Unchecked);
564 
565 	QTableWidgetItem *count = table->item(i, 0);
566 	if (count != NULL) count->setText(countstr);
567 
568 	ClearCount();
569 
570 	if (how==PICK_ONE) {
571 	    accept();
572 	}
573     }
574 }
575 
cellToggleSelect(int i,int j)576 void NetHackQtMenuWindow::cellToggleSelect(int i, int j)
577 {
578     ToggleSelect(i);
579 }
580 
DoSelection(bool)581 void NetHackQtMenuWindow::DoSelection(bool)
582 {
583     if (how == PICK_ONE) {
584 	accept();
585     }
586 }
587 
isSelected(int row)588 bool NetHackQtMenuWindow::isSelected(int row)
589 {
590     QCheckBox *cb = dynamic_cast<QCheckBox *>(table->cellWidget(row, 1));
591     return cb != NULL && cb->checkState() != Qt::Unchecked;
592 }
593 
count(int row)594 int NetHackQtMenuWindow::count(int row)
595 {
596     QTableWidgetItem *count = table->item(row, 0);
597     if (count == NULL) return -1;
598     QString cstr = count->text();
599     return cstr.isEmpty() ? -1 : cstr.toInt();
600 }
601 
NetHackQtTextWindow(QWidget * parent)602 NetHackQtTextWindow::NetHackQtTextWindow(QWidget *parent) :
603     QDialog(parent),
604     use_rip(false),
605     str_fixed(false),
606     ok("Dismiss",this),
607     search("Search",this),
608     lines(new NetHackQtTextListBox(this)),
609     rip(this)
610 {
611     ok.setDefault(true);
612     connect(&ok,SIGNAL(clicked()),this,SLOT(accept()));
613     connect(&search,SIGNAL(clicked()),this,SLOT(Search()));
614     connect(qt_settings,SIGNAL(fontChanged()),this,SLOT(doUpdate()));
615 
616     QVBoxLayout* vb = new QVBoxLayout(this);
617     vb->addWidget(&rip);
618     QHBoxLayout* hb = new QHBoxLayout();
619     vb->addLayout(hb);
620     hb->addWidget(&ok);
621     hb->addWidget(&search);
622     vb->addWidget(lines);
623 }
624 
doUpdate()625 void NetHackQtTextWindow::doUpdate()
626 {
627     update();
628 }
629 
630 
~NetHackQtTextWindow()631 NetHackQtTextWindow::~NetHackQtTextWindow()
632 {
633 
634 }
635 
Widget()636 QWidget* NetHackQtTextWindow::Widget()
637 {
638     return this;
639 }
640 
Destroy()641 bool NetHackQtTextWindow::Destroy()
642 {
643     return !isVisible();
644 }
645 
UseRIP(int how,time_t when)646 void NetHackQtTextWindow::UseRIP(int how, time_t when)
647 {
648 // Code from X11 windowport
649 #define STONE_LINE_LEN 16    /* # chars that fit on one line */
650 #define NAME_LINE 0	/* line # for player name */
651 #define GOLD_LINE 1	/* line # for amount of gold */
652 #define DEATH_LINE 2	/* line # for death description */
653 #define YEAR_LINE 6	/* line # for year */
654 
655 static char** rip_line=0;
656     if (!rip_line) {
657 	rip_line=new char*[YEAR_LINE+1];
658 	for (int i=0; i<YEAR_LINE+1; i++) {
659 	    rip_line[i]=new char[STONE_LINE_LEN+1];
660 	}
661     }
662 
663     /* Follows same algorithm as genl_outrip() */
664 
665     char buf[BUFSZ];
666     char *dpx;
667     int line;
668 
669     /* Put name on stone */
670     snprintf(rip_line[NAME_LINE], STONE_LINE_LEN+1, "%s", plname);
671 
672     /* Put $ on stone */
673     snprintf(rip_line[GOLD_LINE], STONE_LINE_LEN+1, "%ld Au", money_cnt(invent));
674 
675     /* Put together death description */
676     formatkiller(buf, sizeof buf, how, FALSE);
677     //str_copy(buf, killer, SIZE(buf));
678 
679     /* Put death type on stone */
680     for (line=DEATH_LINE, dpx = buf; line<YEAR_LINE; line++) {
681 	int i,i0;
682 	char tmpchar;
683 
684 	if ( (i0=strlen(dpx)) > STONE_LINE_LEN) {
685 	    for(i = STONE_LINE_LEN;
686 		((i0 > STONE_LINE_LEN) && i); i--)
687 		if(dpx[i] == ' ') i0 = i;
688 	    if(!i) i0 = STONE_LINE_LEN;
689 	}
690 	tmpchar = dpx[i0];
691 	dpx[i0] = 0;
692 	str_copy(rip_line[line], dpx, STONE_LINE_LEN+1);
693 	if (tmpchar != ' ') {
694 	    dpx[i0] = tmpchar;
695 	    dpx= &dpx[i0];
696 	} else  dpx= &dpx[i0+1];
697     }
698 
699     /* Put year on stone */
700     snprintf(rip_line[YEAR_LINE], STONE_LINE_LEN+1, "%4d", getyear());
701 
702     rip.setLines(rip_line,YEAR_LINE+1);
703 
704     use_rip=true;
705 }
706 
Clear()707 void NetHackQtTextWindow::Clear()
708 {
709     lines->clear();
710     use_rip=false;
711     str_fixed=false;
712 }
713 
Display(bool block)714 void NetHackQtTextWindow::Display(bool block)
715 {
716     if (str_fixed) {
717 	lines->setFont(qt_settings->normalFixedFont());
718     } else {
719 	lines->setFont(qt_settings->normalFont());
720     }
721 
722     int h=0;
723     if (use_rip) {
724 	h+=rip.height();
725 	ok.hide();
726 	search.hide();
727 	rip.show();
728     } else {
729 	h+=ok.height()*2 + 7;
730 	ok.show();
731 	search.show();
732 	rip.hide();
733     }
734     int mh = QApplication::desktop()->height()*3/5;
735     if ( (qt_compact_mode && lines->TotalHeight() > mh) || use_rip ) {
736 	// big, so make it fill
737 	showMaximized();
738     } else {
739 	move(0, 0);
740 	adjustSize();
741 	centerOnMain(this);
742 	show();
743     }
744     exec();
745 }
746 
PutStr(int attr,const QString & text)747 void NetHackQtTextWindow::PutStr(int attr, const QString& text)
748 {
749     str_fixed=str_fixed || text.contains("    ");
750     lines->addItem(text);
751 }
752 
Search()753 void NetHackQtTextWindow::Search()
754 {
755     NetHackQtStringRequestor requestor(this, "Search for:");
756     static char line[256]="";
757     requestor.SetDefault(line);
758     if (requestor.Get(line)) {
759 	int current=lines->currentRow();
760 	for (int i=1; i<lines->count(); i++) {
761 	    int lnum=(i+current)%lines->count();
762 	    QString str=lines->item(lnum)->text();
763 	    if (str.contains(line)) {
764 		lines->setCurrentRow(lnum);
765 		return;
766 	    }
767 	}
768 	lines->setCurrentItem(NULL);
769     }
770 }
771 
NetHackQtMenuOrTextWindow(QWidget * parent_)772 NetHackQtMenuOrTextWindow::NetHackQtMenuOrTextWindow(QWidget *parent_) :
773     actual(0),
774     parent(parent_)
775 {
776 }
777 
Widget()778 QWidget* NetHackQtMenuOrTextWindow::Widget()
779 {
780     if (!actual) impossible("Widget called before we know if Menu or Text");
781     return actual->Widget();
782 }
783 
784 // Text
Clear()785 void NetHackQtMenuOrTextWindow::Clear()
786 {
787     if (!actual) impossible("Clear called before we know if Menu or Text");
788     actual->Clear();
789 }
Display(bool block)790 void NetHackQtMenuOrTextWindow::Display(bool block)
791 {
792     if (!actual) impossible("Display called before we know if Menu or Text");
793     actual->Display(block);
794 }
Destroy()795 bool NetHackQtMenuOrTextWindow::Destroy()
796 {
797     if (!actual) impossible("Destroy called before we know if Menu or Text");
798     return actual->Destroy();
799 }
800 
PutStr(int attr,const QString & text)801 void NetHackQtMenuOrTextWindow::PutStr(int attr, const QString& text)
802 {
803     if (!actual) actual=new NetHackQtTextWindow(parent);
804     actual->PutStr(attr,text);
805 }
806 
807 // Menu
StartMenu()808 void NetHackQtMenuOrTextWindow::StartMenu()
809 {
810     if (!actual) actual=new NetHackQtMenuWindow(parent);
811     actual->StartMenu();
812 }
AddMenu(int glyph,const ANY_P * identifier,char ch,char gch,int attr,const QString & str,bool presel)813 void NetHackQtMenuOrTextWindow::AddMenu(int glyph, const ANY_P* identifier, char ch, char gch, int attr,
814 	const QString& str, bool presel)
815 {
816     if (!actual) impossible("AddMenu called before we know if Menu or Text");
817     actual->AddMenu(glyph,identifier,ch,gch,attr,str,presel);
818 }
EndMenu(const QString & prompt)819 void NetHackQtMenuOrTextWindow::EndMenu(const QString& prompt)
820 {
821     if (!actual) impossible("EndMenu called before we know if Menu or Text");
822     actual->EndMenu(prompt);
823 }
SelectMenu(int how,MENU_ITEM_P ** menu_list)824 int NetHackQtMenuOrTextWindow::SelectMenu(int how, MENU_ITEM_P **menu_list)
825 {
826     if (!actual) impossible("SelectMenu called before we know if Menu or Text");
827     return actual->SelectMenu(how,menu_list);
828 }
829 
830 } // namespace nethack_qt4
831