From 76a5cc5049290770249b6661a2f4558b7fbb645e Mon Sep 17 00:00:00 2001 From: ennewalker Date: Thu, 12 Feb 2009 05:05:43 +0000 Subject: 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 --- crawl-ref/source/describe.h | 155 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 148 insertions(+), 7 deletions(-) (limited to 'crawl-ref/source/describe.h') 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 +#include #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 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 +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 -- cgit v1.2.3-54-g00ecf