summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source
diff options
context:
space:
mode:
authorennewalker <ennewalker@c06c8d41-db1a-0410-9941-cceddc491573>2009-02-12 05:05:43 +0000
committerennewalker <ennewalker@c06c8d41-db1a-0410-9941-cceddc491573>2009-02-12 05:05:43 +0000
commit76a5cc5049290770249b6661a2f4558b7fbb645e (patch)
treefa2131d2cef62d963d3c6c821c3ca230b541260f /crawl-ref/source
parentaa6dd78dceb8d09547021cd319aaaef053df1f4f (diff)
downloadcrawl-ref-76a5cc5049290770249b6661a2f4558b7fbb645e.tar.gz
crawl-ref-76a5cc5049290770249b6661a2f4558b7fbb645e.zip
Mousing over monsters, items, and features will now show their description in the message window. This inadvertantly fixes [2469950], where some lines would appear off screen.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@9030 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref/source')
-rw-r--r--crawl-ref/source/command.cc15
-rw-r--r--crawl-ref/source/describe.cc269
-rw-r--r--crawl-ref/source/describe.h155
-rw-r--r--crawl-ref/source/directn.cc30
-rw-r--r--crawl-ref/source/directn.h3
-rw-r--r--crawl-ref/source/tilereg.cc178
-rw-r--r--crawl-ref/source/tilereg.h6
-rw-r--r--crawl-ref/source/tilesdl.cc36
8 files changed, 468 insertions, 224 deletions
diff --git a/crawl-ref/source/command.cc b/crawl-ref/source/command.cc
index ae0c88f9a1..1dcd900e9f 100644
--- a/crawl-ref/source/command.cc
+++ b/crawl-ref/source/command.cc
@@ -1255,10 +1255,9 @@ static bool _append_books(std::string &desc, item_def &item, std::string key)
static bool _do_description(std::string key, std::string type,
std::string footer = "")
{
+ describe_info inf;
std::string desc = getLongDescription(key);
- std::string quote = getQuoteString(key);
-
- std::string prefix, suffix;
+ inf.quote = getQuoteString(key);
int width = std::min(80, get_number_of_cols());
@@ -1267,8 +1266,8 @@ static bool _do_description(std::string key, std::string type,
{
if (is_good_god(which_god))
{
- suffix = "$$" + god_name(which_god) + " won't accept worship from "
- "undead or evil beings.";
+ inf.suffix = "$$" + god_name(which_god) +
+ " won't accept worship from undead or evil beings.";
}
std::string help = get_god_powers(which_god);
if (!help.empty())
@@ -1361,7 +1360,11 @@ static bool _do_description(std::string key, std::string type,
key = uppercase_first(key);
linebreak_string2(footer, width - 1);
- print_description(desc, key, suffix, prefix, footer, quote);
+
+ inf.footer = footer;
+ inf.title = key;
+
+ print_description(inf);
return (true);
}
diff --git a/crawl-ref/source/describe.cc b/crawl-ref/source/describe.cc
index ba24dcbc12..44cac75279 100644
--- a/crawl-ref/source/describe.cc
+++ b/crawl-ref/source/describe.cc
@@ -79,7 +79,7 @@ static void _append_value( std::string & description, int valu, bool plussed )
description += value_str;
}
-static int _count_desc_lines(const std::string _desc, const int width)
+int count_desc_lines(const std::string _desc, const int width)
{
std::string desc = get_linebreak_string(_desc, width);
@@ -104,129 +104,30 @@ static int _count_desc_lines(const std::string _desc, const int width)
// word and such. The character $ is interpreted as a CR.
//
//---------------------------------------------------------------
-void print_description(const std::string &d, const std::string title,
- const std::string suffix, const std::string prefix,
- const std::string footer, const std::string quote)
-{
- const unsigned int lineWidth = get_number_of_cols() - 1;
- const int height = get_number_of_lines();
-
- std::string desc;
-
- if (title.empty())
- desc = d;
- else
- {
- desc = title + "$$";
- desc += d;
- }
-
- int num_lines = _count_desc_lines(desc, lineWidth) + 1;
- const int suffix_lines = _count_desc_lines(suffix, lineWidth);
- const int prefix_lines = _count_desc_lines(prefix, lineWidth);
- const int footer_lines = _count_desc_lines(footer, lineWidth)
- + (footer.empty() ? 0 : 1);
- const int quote_lines = _count_desc_lines(quote, lineWidth);
-
- // Prefer the footer over the suffix.
- if (num_lines + suffix_lines + footer_lines <= height)
- {
- desc = desc + suffix;
- num_lines += suffix_lines;
- }
-
- // Prefer the footer over the prefix.
- if (num_lines + prefix_lines + footer_lines <= height)
- {
- desc = prefix + desc;
- num_lines += prefix_lines;
- }
-
- // Prefer the footer over the quote.
- if (num_lines + footer_lines + quote_lines + 1 <= height)
- {
- if (!desc.empty())
- {
- desc += "$";
- num_lines++;
- }
- desc = desc + quote;
- num_lines += quote_lines;
- }
-
- if (!footer.empty() && num_lines + footer_lines <= height)
- {
- const int bottom_line = std::min(std::max(24, num_lines + 2),
- height - footer_lines + 1);
- const int newlines = bottom_line - num_lines;
-
- if (newlines >= 0)
- {
- desc.append(newlines, '\n');
- desc = desc + footer;
- }
- }
+void print_description(const std::string &body)
+{
+ describe_info inf;
+ inf.body << body;
+ print_description(inf);
+}
- std::string::size_type nextLine = std::string::npos;
- unsigned int currentPos = 0;
+class default_desc_proc
+{
+public:
+ int width() { return get_number_of_cols() - 1; }
+ int height() { return get_number_of_lines(); }
+ void print(const std::string &str) { cprintf("%s", str.c_str()); }
+ void nextline() { cgotoxy(1, wherey() + 1); }
+};
+void print_description(const describe_info &inf)
+{
clrscr();
textcolor(LIGHTGREY);
- while (currentPos < desc.length())
- {
- if (currentPos != 0)
- cgotoxy(1, wherey() + 1);
-
- // See if $ sign is within one lineWidth.
- nextLine = desc.find('$', currentPos);
-
- if (nextLine >= currentPos && nextLine < currentPos + lineWidth)
- {
- cprintf("%s",
- (desc.substr(currentPos, nextLine-currentPos)).c_str());
- currentPos = nextLine + 1;
- continue;
- }
-
- // Handle real line breaks. No substitutions necessary, just update
- // the counts.
- nextLine = desc.find('\n', currentPos);
- if (nextLine >= currentPos && nextLine < currentPos + lineWidth)
- {
- cprintf("%s",
- (desc.substr(currentPos, nextLine-currentPos)).c_str());
- currentPos = nextLine + 1;
- continue;
- }
-
- // No newline -- see if rest of string will fit.
- if (currentPos + lineWidth >= desc.length())
- {
- cprintf((desc.substr(currentPos)).c_str());
- return;
- }
-
-
- // Ok, try to truncate at space.
- nextLine = desc.rfind(' ', currentPos + lineWidth);
-
- if (nextLine > 0)
- {
- cprintf((desc.substr(currentPos, nextLine - currentPos)).c_str());
- currentPos = nextLine + 1;
- continue;
- }
-
- // Oops. Just truncate.
- nextLine = currentPos + lineWidth;
-
- nextLine = std::min(d.length(), nextLine);
-
- cprintf((desc.substr(currentPos, nextLine - currentPos)).c_str());
- currentPos = nextLine;
- }
+ default_desc_proc proc;
+ process_description<default_desc_proc>(proc, inf);
}
const char* jewellery_base_ability_string(int subtype)
@@ -1885,8 +1786,8 @@ std::string get_item_description( const item_def &item, bool verbose,
std::string quote = getQuoteString(db_name);
- if (_count_desc_lines(db_desc, lineWidth)
- + _count_desc_lines(quote, lineWidth) <= height)
+ if (count_desc_lines(db_desc, lineWidth)
+ + count_desc_lines(quote, lineWidth) <= height)
{
if (!db_desc.empty())
db_desc += "$";
@@ -2107,7 +2008,7 @@ std::string get_item_description( const item_def &item, bool verbose,
case OBJ_POTIONS:
#ifdef DEBUG_BLOOD_POTIONS
// List content of timer vector for blood potions.
- if (is_blood_potion(item))
+ if (!dump && is_blood_potion(item))
{
item_def stack = static_cast<item_def>(item);
CrawlHashTable &props = stack.props;
@@ -2199,17 +2100,14 @@ static std::string _get_feature_description_wide(int feat)
return std::string();
}
-void describe_feature_wide(int x, int y)
+void get_feature_desc(const coord_def &pos, describe_info &inf)
{
- const coord_def pos(x, y);
const dungeon_feature_type feat = grd(pos);
-
std::string desc = feature_description(pos, false, DESC_CAP_A, false);
- std::string db_name =
- grd[x][y] == DNGN_ENTER_SHOP ? "A shop" : desc;
+ std::string db_name = grd(pos) == DNGN_ENTER_SHOP ? "A shop" : desc;
std::string long_desc = getLongDescription(db_name);
- desc += ".$$";
+ inf.body << desc << ".$$";
// If we couldn't find a description in the database then see if
// the feature's base name is different.
@@ -2252,15 +2150,22 @@ void describe_feature_wide(int x, int y)
db_name = key;
}
- desc += long_desc;
+ inf.body << long_desc;
// For things which require logic
if (!custom_desc)
- desc += _get_feature_description_wide(grd[x][y]);
+ inf.body << _get_feature_description_wide(grd(pos));
- std::string quote = getQuoteString(db_name);
+ inf.quote = getQuoteString(db_name);
+}
+
+void describe_feature_wide(int x, int y)
+{
+ const coord_def pos(x, y);
- print_description(desc, "", "", "", "", quote);
+ describe_info inf;
+ get_feature_desc(pos, inf);
+ print_description(inf);
mouse_control mc(MOUSE_MODE_MORE);
@@ -2289,25 +2194,31 @@ void set_feature_desc_long(const std::string &raw_name,
desc_table[raw_name] = desc;
}
+void get_item_desc(const item_def &item, describe_info &inf)
+{
+ inf.body << get_item_description(item, true, false, Options.tutorial_left);
+}
+
// Returns true if spells can be shown to player.
static bool _show_item_description(const item_def &item)
{
const unsigned int lineWidth = get_number_of_cols() - 1;
const int height = get_number_of_lines();
- std::string description = get_item_description( item, 1, false,
- Options.tutorial_left);
+ describe_info inf;
+ std::string desc =
+ get_item_description(item, true, false, Options.tutorial_left);
- int num_lines = _count_desc_lines(description, lineWidth) + 1;
+ int num_lines = count_desc_lines(desc, lineWidth) + 1;
// XXX: hack: Leave room for "Inscribe item?" and the blank line above
// it by removing item quote. This should really be taken care of
// by putting the quotes into a separate DB and treating them as
// a suffix that can be ignored by print_description().
if (height - num_lines <= 2)
- description = get_item_description( item, 1, false, true);
+ desc = get_item_description(item, 1, false, true);
- print_description(description);
+ print_description(desc);
if (Options.tutorial_left)
tutorial_describe_item(item);
@@ -2798,21 +2709,18 @@ static std::string _monster_stat_description(const monsters& mon)
return result.str();
}
-void describe_monsters(const monsters& mons)
+void get_monster_desc(const monsters& mons, describe_info &inf)
{
// For undetected mimics describe mimicked item instead.
if (mons_is_mimic(mons.type) && !(mons.flags & MF_KNOWN_MIMIC))
{
item_def item;
get_mimic_item(&mons, item);
- describe_item(item);
+ get_item_desc(item, inf);
return;
}
- std::ostringstream body;
- std::string title, prefix, suffix, quote;
-
- title = mons.full_name(DESC_CAP_A, true);
+ inf.title = mons.full_name(DESC_CAP_A, true);
std::string db_name = mons.base_name(DESC_DBNAME);
if (mons_is_mimic(mons.type) && mons.type != MONS_GOLD_MIMIC)
@@ -2820,8 +2728,8 @@ void describe_monsters(const monsters& mons)
// Don't get description for player ghosts.
if (mons.type != MONS_PLAYER_GHOST)
- body << getLongDescription(db_name);
- quote = getQuoteString(db_name);
+ inf.body << getLongDescription(db_name);
+ inf.quote = getQuoteString(db_name);
std::string symbol;
symbol += get_monster_data(mons.type)->showchar;
@@ -2831,12 +2739,12 @@ void describe_monsters(const monsters& mons)
std::string symbol_prefix = "__";
symbol_prefix += symbol;
symbol_prefix += "_prefix";
- prefix = getLongDescription(symbol_prefix);
+ inf.prefix = getLongDescription(symbol_prefix);
std::string quote2 = getQuoteString(symbol_prefix);
- if (!quote.empty() && !quote2.empty())
- quote += "$";
- quote += quote2;
+ if (!inf.quote.empty() && !quote2.empty())
+ inf.quote += "$";
+ inf.quote += quote2;
// Except for draconians and player ghosts, I have to admit I find the
// following special descriptions rather pointless. I certainly can't
@@ -2848,15 +2756,15 @@ void describe_monsters(const monsters& mons)
if (player_can_smell())
{
if (player_mutation_level(MUT_SAPROVOROUS) == 3)
- body << "$It smells great!$";
+ inf.body << "$It smells great!$";
else
- body << "$It stinks.$";
+ inf.body << "$It stinks.$";
}
break;
case MONS_SWAMP_DRAKE:
if (player_can_smell())
- body << "$It smells horrible.$";
+ inf.body << "$It smells horrible.$";
break;
case MONS_NAGA:
@@ -2865,26 +2773,26 @@ void describe_monsters(const monsters& mons)
case MONS_GUARDIAN_NAGA:
case MONS_GREATER_NAGA:
if (you.species == SP_NAGA)
- body << "$It is particularly attractive.$";
+ inf.body << "$It is particularly attractive.$";
else
- body << "$It is strange and repulsive.$";
+ inf.body << "$It is strange and repulsive.$";
break;
case MONS_VAMPIRE:
case MONS_VAMPIRE_KNIGHT:
case MONS_VAMPIRE_MAGE:
if (you.is_undead == US_ALIVE)
- body << "$It wants to drink your blood!$";
+ inf.body << "$It wants to drink your blood!$";
break;
case MONS_REAPER:
if (you.is_undead == US_ALIVE)
- body << "$It has come for your soul!$";
+ inf.body << "$It has come for your soul!$";
break;
case MONS_ELF:
// These are only possible from polymorphing or shapeshifting.
- body << "$This one is remarkably plain looking.$";
+ inf.body << "$This one is remarkably plain looking.$";
break;
case MONS_DRACONIAN:
@@ -2904,24 +2812,24 @@ void describe_monsters(const monsters& mons)
case MONS_DRACONIAN_MONK:
case MONS_DRACONIAN_KNIGHT:
{
- body << "$" << _describe_draconian( &mons );
+ inf.body << "$" << _describe_draconian( &mons );
break;
}
case MONS_PLAYER_GHOST:
- body << "The apparition of " << get_ghost_description(mons) << ".$";
+ inf.body << "The apparition of " << get_ghost_description(mons) << ".$";
break;
case MONS_PANDEMONIUM_DEMON:
- body << _describe_demon(mons);
+ inf.body << _describe_demon(mons);
break;
case MONS_URUG:
if (player_can_smell())
- body << "$He smells terrible.$";
+ inf.body << "$He smells terrible.$";
break;
case MONS_PROGRAM_BUG:
- body << "If this monster is a \"program bug\", then it's "
+ inf.body << "If this monster is a \"program bug\", then it's "
"recommended that you save your game and reload. Please report "
"monsters who masquerade as program bugs or run around the "
"dungeon without a proper description to the authorities.$";
@@ -2935,19 +2843,19 @@ void describe_monsters(const monsters& mons)
{
std::string result = _monster_stat_description(mons);
if (!result.empty())
- body << "$" << result;
+ inf.body << "$" << result;
}
if (!mons_can_use_stairs(&mons))
{
- body << "$" << mons_pronoun(static_cast<monster_type>(mons.type),
+ inf.body << "$" << mons_pronoun(static_cast<monster_type>(mons.type),
PRONOUN_CAP, true)
<< " is incapable of using stairs.$";
}
if (mons_is_summoned(&mons))
{
- body << "$" << "This monster has been summoned, and is thus only "
+ inf.body << "$" << "This monster has been summoned, and is thus only "
"temporary. Killing it yields no experience, nutrition "
"or items.$";
}
@@ -2955,13 +2863,13 @@ void describe_monsters(const monsters& mons)
std::string symbol_suffix = "__";
symbol_suffix += symbol;
symbol_suffix += "_suffix";
- suffix += getLongDescription(symbol_suffix);
- suffix += getLongDescription(symbol_suffix + "_examine");
+ inf.suffix += getLongDescription(symbol_suffix);
+ inf.suffix += getLongDescription(symbol_suffix + "_examine");
quote2 = getQuoteString(symbol_suffix);
- if (!quote.empty() && !quote2.empty())
- quote += "$";
- quote += quote2;
+ if (!inf.quote.empty() && !quote2.empty())
+ inf.quote += "$";
+ inf.quote += quote2;
#if DEBUG_DIAGNOSTICS
if (mons_class_flag( mons.type, M_SPELLCASTER ))
@@ -2975,14 +2883,14 @@ void describe_monsters(const monsters& mons)
{
if (!found_spell)
{
- body << "$$Monster Spells:$";
+ inf.body << "$$Monster Spells:$";
found_spell = true;
}
- body << " " << i << ": "
- << spell_title(hspell_pass[i])
- << " (" << static_cast<int>(hspell_pass[i])
- << ")$";
+ inf.body << " " << i << ": "
+ << spell_title(hspell_pass[i])
+ << " (" << static_cast<int>(hspell_pass[i])
+ << ")$";
}
}
}
@@ -2994,19 +2902,26 @@ void describe_monsters(const monsters& mons)
{
if (!has_item)
{
- body << "$Monster Inventory:$";
+ inf.body << "$Monster Inventory:$";
has_item = true;
}
- body << " " << i << ") "
+ inf.body << " " << i << ") "
<< mitm[mons.inv[i]].name(DESC_NOCAP_A, false, true);
}
}
#endif
+}
- print_description(body.str(), title, suffix, prefix, "", quote);
+void describe_monsters(const monsters& mons)
+{
+ describe_info inf;
+ get_monster_desc(mons, inf);
+ print_description(inf);
mouse_control mc(MOUSE_MODE_MORE);
+ // TODO enne - this should really move into get_monster_desc
+ // and an additional tutorial string added to describe_info.
if (Options.tutorial_left)
tutorial_describe_monster(&mons);
diff --git a/crawl-ref/source/describe.h b/crawl-ref/source/describe.h
index ab661c919c..647816ab57 100644
--- a/crawl-ref/source/describe.h
+++ b/crawl-ref/source/describe.h
@@ -11,6 +11,7 @@
#define DESCRIBE_H
#include <string>
+#include <sstream>
#include "externs.h"
#include "enum.h"
@@ -27,6 +28,16 @@ enum item_description_type
NUM_IDESC
};
+struct describe_info
+{
+ std::ostringstream body;
+ std::string title;
+ std::string prefix;
+ std::string suffix;
+ std::string footer;
+ std::string quote;
+};
+
void append_spells(std::string &desc, const item_def &item);
// last updated 12may2000 {dlb}
@@ -53,6 +64,7 @@ void describe_god( god_type which_god, bool give_title );
* called from: directn
* *********************************************************************** */
void describe_feature_wide(int x, int y);
+void get_feature_desc(const coord_def &gc, describe_info &inf);
// last updated 24 Dec 2008 {mpc}
/* ***********************************************************************
@@ -64,8 +76,9 @@ void set_feature_desc_long(const std::string &raw_name,
/* ***********************************************************************
* called from: item_use - shopping
* *********************************************************************** */
-void describe_item( item_def &item, bool allow_inscribe = false );
-void inscribe_item( item_def &item, bool proper_prompt );
+void describe_item(item_def &item, bool allow_inscribe = false);
+void get_item_desc(const item_def &item, describe_info &inf);
+void inscribe_item(item_def &item, bool proper_prompt);
/* ***********************************************************************
* called from: command
@@ -79,6 +92,7 @@ void append_missile_info(std::string &description);
* called from: command - direct
* *********************************************************************** */
void describe_monsters(const monsters &mons);
+void get_monster_desc(const monsters &item, describe_info &inf);
// last updated 12 Jun 2008 {jpeg}
/* ***********************************************************************
@@ -96,11 +110,10 @@ std::string get_skill_description(int skill, bool need_title = false);
void describe_skill(int skill);
-void print_description(const std::string &d, const std::string title = "",
- const std::string suffix = "",
- const std::string prefix = "",
- const std::string footer = "",
- const std::string quote = "");
+void print_description(const std::string &desc);
+void print_description(const describe_info &inf);
+
+template<class T> void process_description(T &proc, const describe_info &inf);
std::string randart_auto_inscription( const item_def& item );
void add_autoinscription( item_def &item, std::string ainscrip);
@@ -110,4 +123,132 @@ int str_to_trap(const std::string &s);
extern const char* god_gain_power_messages[NUM_GODS][MAX_GOD_ABILITIES];
+int count_desc_lines(const std::string _desc, const int width);
+
+/* ***********************************************************************
+ * template implementations
+ * *********************************************************************** */
+// My kingdom for a closure.
+template<class T>
+inline void process_description(T &proc, const describe_info &inf)
+{
+ const unsigned int line_width = proc.width();
+ const int height = proc.height();
+
+ std::string desc;
+
+ if (inf.title.empty())
+ desc = inf.body.str();
+ else
+ {
+ desc = inf.title + "$$";
+ desc += inf.body.str();
+ }
+
+ int num_lines = count_desc_lines(desc, line_width) + 1;
+
+ const int suffix_lines = count_desc_lines(inf.suffix, line_width);
+ const int prefix_lines = count_desc_lines(inf.prefix, line_width);
+ const int footer_lines = count_desc_lines(inf.footer, line_width)
+ + (inf.footer.empty() ? 0 : 1);
+ const int quote_lines = count_desc_lines(inf.quote, line_width);
+
+ // Prefer the footer over the suffix.
+ if (num_lines + suffix_lines + footer_lines <= height)
+ {
+ desc = desc + inf.suffix;
+ num_lines += suffix_lines;
+ }
+
+ // Prefer the footer over the prefix.
+ if (num_lines + prefix_lines + footer_lines <= height)
+ {
+ desc = inf.prefix + desc;
+ num_lines += prefix_lines;
+ }
+
+ // Prefer the footer over the quote.
+ if (num_lines + footer_lines + quote_lines + 1 <= height)
+ {
+ if (!desc.empty())
+ {
+ desc += "$";
+ num_lines++;
+ }
+ desc = desc + inf.quote;
+ num_lines += quote_lines;
+ }
+
+ if (!inf.footer.empty() && num_lines + footer_lines <= height)
+ {
+ const int bottom_line = std::min(std::max(24, num_lines + 2),
+ height - footer_lines + 1);
+ const int newlines = bottom_line - num_lines;
+
+ if (newlines >= 0)
+ {
+ desc.append(newlines, '\n');
+ desc = desc + inf.footer;
+ }
+ }
+
+ std::string::size_type nextLine = std::string::npos;
+ unsigned int currentPos = 0;
+
+ while (currentPos < desc.length())
+ {
+ if (currentPos != 0)
+ proc.nextline();
+
+ // See if $ sign is within one line_width.
+ nextLine = desc.find('$', currentPos);
+
+ if (nextLine >= currentPos && nextLine < currentPos + line_width)
+ {
+ proc.print(desc.substr(currentPos, nextLine-currentPos));
+ currentPos = nextLine + 1;
+ continue;
+ }
+
+ // Handle real line breaks. No substitutions necessary, just update
+ // the counts.
+ nextLine = desc.find('\n', currentPos);
+ if (nextLine >= currentPos && nextLine < currentPos + line_width)
+ {
+ proc.print(desc.substr(currentPos, nextLine-currentPos));
+ currentPos = nextLine + 1;
+ continue;
+ }
+
+ // No newline -- see if rest of string will fit.
+ if (currentPos + line_width >= desc.length())
+ {
+ proc.print(desc.substr(currentPos));
+ return;
+ }
+
+
+ // Ok, try to truncate at space.
+ nextLine = desc.rfind(' ', currentPos + line_width);
+
+ if (nextLine > 0)
+ {
+ proc.print(desc.substr(currentPos, nextLine - currentPos));
+ currentPos = nextLine + 1;
+ continue;
+ }
+
+ // Oops. Just truncate.
+ nextLine = currentPos + line_width;
+
+ nextLine = std::min(inf.body.str().length(), nextLine);
+
+ proc.print(desc.substr(currentPos, nextLine - currentPos));
+ currentPos = nextLine;
+ }
+}
+
+
+
+
#endif
diff --git a/crawl-ref/source/directn.cc b/crawl-ref/source/directn.cc
index 3bfc704e25..4ba3d94528 100644
--- a/crawl-ref/source/directn.cc
+++ b/crawl-ref/source/directn.cc
@@ -1658,8 +1658,38 @@ void terse_describe_square(const coord_def &c, bool in_range)
_describe_cell(c, in_range);
}
+void get_square_desc(const coord_def &c, describe_info &inf)
+{
+ // NOTE: Keep this function in sync with full_describe_square.
+
+ // Don't give out information for things outside LOS
+ if (!see_grid(c.x, c.y))
+ return;
+
+ const int mid = mgrd(c);
+ const int oid = igrd(c);
+
+ if (mid != NON_MONSTER && player_monster_visible(&menv[mid]))
+ {
+ // First priority: monsters.
+ get_monster_desc(menv[mid], inf);
+ }
+ else if (oid != NON_ITEM)
+ {
+ // Second priority: objects.
+ get_item_desc(mitm[oid], inf);
+ }
+ else
+ {
+ // Third priority: features.
+ get_feature_desc(c, inf);
+ }
+}
+
void full_describe_square(const coord_def &c)
{
+ // NOTE: Keep this function in sync with get_square_desc.
+
// Don't give out information for things outside LOS
if (!see_grid(c.x, c.y))
return;
diff --git a/crawl-ref/source/directn.h b/crawl-ref/source/directn.h
index 381e130ac0..da0d972f1b 100644
--- a/crawl-ref/source/directn.h
+++ b/crawl-ref/source/directn.h
@@ -10,6 +10,7 @@
#ifndef DIRECT_H
#define DIRECT_H
+#include "describe.h"
#include "externs.h"
#include "enum.h"
#include "libgui.h"
@@ -176,6 +177,8 @@ std::string thing_do_grammar(description_level_type dtype,
std::string get_terse_square_desc(const coord_def &gc);
void terse_describe_square(const coord_def &c, bool in_range = true);
void full_describe_square(const coord_def &c);
+void get_square_desc(const coord_def &c, describe_info &inf);
+
void describe_floor();
std::string get_monster_desc(const monsters *mon,
bool full_desc = true,
diff --git a/crawl-ref/source/tilereg.cc b/crawl-ref/source/tilereg.cc
index 65d2bf0972..b155533961 100644
--- a/crawl-ref/source/tilereg.cc
+++ b/crawl-ref/source/tilereg.cc
@@ -1052,6 +1052,114 @@ bool DungeonRegion::update_tip_text(std::string& tip)
return true;
}
+class alt_desc_proc
+{
+public:
+ alt_desc_proc(int _w, int _h) { w = _w; h = _h; }
+
+ int width() { return w; }
+ int height() { return h; }
+ void nextline()
+ {
+ ostr << "\n";
+ }
+ void print(const std::string &str)
+ {
+ ostr << str;
+ }
+
+ static int count_newlines(const std::string &str)
+ {
+ int count = 0;
+ for (size_t i = 0; i < str.size(); i++)
+ {
+ if (str[i] == '\n')
+ count++;
+ }
+ return count;
+ }
+
+ // Remove trailing newlines.
+ static void trim(std::string &str)
+ {
+ int idx = str.size();
+ while (--idx >= 0)
+ {
+ if (str[idx] != '\n')
+ break;
+ }
+ str.resize(idx + 1);
+ }
+
+ // rfind consecutive newlines and truncate.
+ static bool chop(std::string &str)
+ {
+ int loc = -1;
+ for (size_t i = 1; i < str.size(); i++)
+ {
+ if (str[i] == '\n' && str[i-1] == '\n')
+ loc = i;
+ }
+
+ if (loc == -1)
+ return false;
+
+ str.resize(loc);
+ return true;
+ }
+
+ void get_string(std::string &str)
+ {
+ str = replace_all(ostr.str(), "\n\n\n\n", "\n\n");
+ str = replace_all(str, "\n\n\n", "\n\n");
+
+ trim(str);
+ while (count_newlines(str) > h)
+ {
+ if (!chop(str))
+ break;
+ }
+ }
+
+protected:
+ int w;
+ int h;
+ std::ostringstream ostr;
+};
+
+bool DungeonRegion::update_alt_text(std::string &alt)
+{
+ if (mouse_control::current_mode() != MOUSE_MODE_COMMAND)
+ return false;
+
+ const coord_def &gc = m_cursor[CURSOR_MOUSE];
+
+ if (gc == NO_CURSOR)
+ return false;
+ if (!map_bounds(gc))
+ return false;
+
+ if (!see_grid(gc))
+ return false;
+
+ describe_info inf;
+ get_square_desc(gc, inf);
+
+ alt_desc_proc proc(crawl_view.msgsz.x, crawl_view.msgsz.y);
+ process_description<alt_desc_proc>(proc, inf);
+
+ proc.get_string(alt);
+
+ // Suppress floor description
+ if (alt == "Floor.")
+ {
+ alt.clear();
+ return false;
+ }
+
+ return true;
+}
+
void DungeonRegion::clear_text_tags(text_tag_type type)
{
m_tags[type].clear();
@@ -1192,8 +1300,7 @@ void InventoryRegion::render()
else
desc = you.inv[idx].name(DESC_INVENTORY_EQUIP);
- m_tag_font->render_string(x, y,
- desc.c_str(),
+ m_tag_font->render_string(x, y, desc.c_str(),
min_pos, max_pos, WHITE, false, 200);
}
}
@@ -1689,12 +1796,39 @@ bool InventoryRegion::update_tip_text(std::string& tip)
{
tip += "\n[Shift-L-Click] Drop (d)";
}
-
}
return true;
}
+bool InventoryRegion::update_alt_text(std::string &alt)
+{
+ if (m_cursor == NO_CURSOR)
+ return false;
+
+ unsigned int item_idx = cursor_index();
+ if (item_idx >= m_items.size() || m_items[item_idx].empty())
+ return false;
+
+ int idx = m_items[item_idx].idx;
+
+ const item_def *item;
+ if (m_items[item_idx].flag & TILEI_FLAG_FLOOR)
+ item = &mitm[idx];
+ else
+ item = &you.inv[idx];
+
+ describe_info inf;
+ get_item_desc(*item, inf);
+
+ alt_desc_proc proc(crawl_view.msgsz.x, crawl_view.msgsz.y);
+ process_description<alt_desc_proc>(proc, inf);
+
+ proc.get_string(alt);
+
+ return true;
+}
+
MapRegion::MapRegion(int pixsz) :
m_buf(NULL),
m_dirty(true),
@@ -2256,6 +2390,15 @@ void MessageRegion::render()
unsigned char char_back = 0;
unsigned char col_back = 0;
+ if (!m_overlay && !m_alt_text.empty())
+ {
+ coord_def min_pos(sx, sy);
+ coord_def max_pos(ex, ey);
+ m_font->render_string(sx + ox, sy + oy, m_alt_text.c_str(),
+ min_pos, max_pos, WHITE, false);
+ return;
+ }
+
if (this == TextRegion::cursor_region && cursor_x > 0 && cursor_y > 0)
{
idx = cursor_x + mx * cursor_y;
@@ -2289,34 +2432,13 @@ void MessageRegion::render()
if (height > 0)
{
height *= m_font->char_height();
- box_vert verts[4];
- for (int i = 0; i < 4; i++)
- {
- verts[i].r = 100;
- verts[i].g = 100;
- verts[i].b = 100;
- verts[i].a = 100;
- }
- verts[0].x = sx;
- verts[0].y = sy;
- verts[1].x = sx;
- verts[1].y = sy + height;
- verts[2].x = ex;
- verts[2].y = sy + height;
- verts[3].x = ex;
- verts[3].y = sy;
glLoadIdentity();
- GLState state;
- state.array_vertex = true;
- state.array_colour = true;
- state.blend = true;
- GLStateManager::set(state);
-
- glVertexPointer(2, GL_FLOAT, sizeof(box_vert), &verts[0].x);
- glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(box_vert), &verts[0].r);
- glDrawArrays(GL_QUADS, 0, sizeof(verts) / sizeof(box_vert));
+ ShapeBuffer buff;
+ VColour col(100, 100, 100, 100);
+ buff.add(sx, sy, ex, sy + height, col);
+ buff.draw();
}
}
diff --git a/crawl-ref/source/tilereg.h b/crawl-ref/source/tilereg.h
index 7bee88c983..b6f75de610 100644
--- a/crawl-ref/source/tilereg.h
+++ b/crawl-ref/source/tilereg.h
@@ -50,6 +50,7 @@ public:
bool inside(int px, int py);
virtual bool update_tip_text(std::string &tip) { return false; }
+ virtual bool update_alt_text(std::string &alt) { return false; }
virtual int handle_mouse(MouseEvent &event) = 0;
virtual void render() = 0;
@@ -167,7 +168,10 @@ public:
virtual int handle_mouse(MouseEvent &event);
virtual void render();
virtual bool update_tip_text(std::string &tip);
+
+ std::string &alt_text() { return m_alt_text; }
protected:
+ std::string m_alt_text;
bool m_overlay;
};
@@ -256,6 +260,7 @@ public:
virtual void clear();
virtual int handle_mouse(MouseEvent &event);
virtual bool update_tip_text(std::string &tip);
+ virtual bool update_alt_text(std::string &alt);
virtual void on_resize();
void load_dungeon(unsigned int* tileb, int cx_to_gx, int cy_to_gy);
@@ -338,6 +343,7 @@ public:
void update(int num, InventoryTile *items);
void update_slot(int slot, InventoryTile &item);
virtual bool update_tip_text(std::string &tip);
+ virtual bool update_alt_text(std::string &alt);
protected:
void pack_tile(int x, int y, int idx);
diff --git a/crawl-ref/source/tilesdl.cc b/crawl-ref/source/tilesdl.cc
index bf9f281ca3..06a8de6ee7 100644
--- a/crawl-ref/source/tilesdl.cc
+++ b/crawl-ref/source/tilesdl.cc
@@ -724,13 +724,33 @@ int TilesFramework::getch_ck()
ticks = SDL_GetTicks();
if (event.type != SDL_USEREVENT)
+ {
tiles.clear_text_tags(TAG_CELL_DESC);
+ m_region_msg->alt_text().clear();
+ }
+
+ // TODO enne - need to find a better time to decide when
+ // to generate a tip or some way to say "yes, but unchanged".
+ if (ticks > m_last_tick_moved)
+ {
+ m_region_msg->alt_text().clear();
+ for (unsigned int i = 0;
+ i < m_layers[m_active_layer].m_regions.size(); i++)
+ {
+ Region *reg = m_layers[m_active_layer].m_regions[i];
+ if (!reg->inside(m_mouse.x, m_mouse.y))
+ continue;
+ if (reg->update_alt_text(m_region_msg->alt_text()))
+ break;
+ }
+ }
switch (event.type)
{
case SDL_KEYDOWN:
m_key_mod |= _get_modifiers(event.key.keysym);
key = _translate_keysym(event.key.keysym);
+ m_region_tile->place_cursor(CURSOR_MOUSE, Region::NO_CURSOR);
// If you hit a key, disable tooltips until the mouse
// is moved again.
@@ -919,17 +939,21 @@ void TilesFramework::do_layout()
if (message_overlay)
{
m_region_msg->resize_to_fit(m_region_tile->ex, m_region_msg->ey);
- crawl_view.msgsz.x = m_region_msg->mx;
- crawl_view.msgsz.y = m_region_msg->my;
+ m_region_msg->ex = m_region_tile->ex;
}
else
{
- m_region_msg->resize_to_fit(m_region_msg->wx,
- m_windowsz.y - m_region_msg->sx);
+ m_region_msg->resize_to_fit(m_region_tile->wx,
+ m_windowsz.y - m_region_msg->sy);
int msg_y = std::min(Options.msg_max_height, (int)m_region_msg->my);
m_region_msg->resize(m_region_msg->mx, msg_y);
+
+ m_region_msg->ex = m_region_tile->ex;
+ m_region_msg->ey = m_windowsz.y;
}
m_region_msg->set_overlay(message_overlay);
+ crawl_view.msgsz.x = m_region_msg->mx;
+ crawl_view.msgsz.y = m_region_msg->my;
// Shrink view width if stat window can't fit...
int stat_col;
@@ -1121,9 +1145,9 @@ void TilesFramework::redraw()
{
const coord_def min_pos(0, 0);
FTFont *font = m_fonts[m_tip_font].font;
+
font->render_string(m_mouse.x, m_mouse.y - 2, m_tooltip.c_str(),
- min_pos, m_windowsz, WHITE, false, 150,
- BLUE, 5);
+ min_pos, m_windowsz, WHITE, false, 220, BLUE, 5);
}
SDL_GL_SwapBuffers();