git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@9030 c06c8d41-db1a-0410-9941-cceddc491573
XKSYV5QUG2PET6BNBZPNI4D7LDBJGWOH335OD3J24AKJWE63J3WQC Q57GOIHVFNJHTBYNUGJNME3UF2QFRJ6CN2UXVY47NHU7XAT7JJYAC HM6NOS7BN5665KWIFGBXOHZIDMRSVCESN72GMGI6NVBFZGCF3L6QC LJPUO3NNFABVOQOBA5LUDNT2R5H4LMP6TPJBNVJ7VJBERCBYZIXQC 2VHVHQYNKZF65BHNKJ3LCA3WM4DRAEMWDQJATNJCOOXVDBS56YRQC YKUVKAIE3IVK377PRJKAXPM45POXYW3ATAKNI3XWKXVFBDRU5LSQC 7OC5HCGLN26GDA5SQTWKBSUZYZDZJXWIVMJ4NKKXREOEEPUGQ4YQC HZEC4TVVUHE6YKEXPOUMNQJOCFGF2MSEU7AUD6VID6FSMYU4XX2QC RZTIYZABUF6FQZEBZOPVWTIMYI3ZI637PTR4MZTBPLOCDRAXPPOQC Q3B3UVMYEVC4YJUPYVSNTR4DJH4E6J4JJDHZNT5LNOCHCPPMEMXAC XKNRIFG2ULQLAAQ5GC4RBZPOERV73DLCNILEA5EP37JLIX5EP3OQC PBTLQZHBQK5TAIO7SNSCKSHOQQ65CFFI55OTTETV7FG2FCJOXKHQC NDE6CROMCVOJRMRMEID7QISFPZKUK2VCV6ISP5OEQRBH7EIXUIEQC K57Q5SRNXYQOX5FP3L3VSFBWNR57NLO33GV2YPS6PQI54KKIFFFQC ZGWMTQ4GG7W5HDVHPQCWJIUK4LK4PS3CDOOIQSFANTU33D45DCPAC MV5USMLTBKVRWBAD67UFJ2BS4Y5HEOMYASRSB44DS24BBMRP75RQC IP4A3VRYFYIVLRUAU4DF4KDNP6E4UISWJX3LI2F4EGSSMIJYRJXAC NSHZVI2TCGOCTEKV72C5K4CNZW3I6MCHG372NYXYZI7U2U5BQ66AC K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC IIN7AVA6JYRBXH6ZYRR7BY7TV6PW7ANAQ2A3PD55FKBKKQFEEF2AC TAHSTXR7ROOMDFUSBUU4ZAIEWQLAS5CIRCTARLD4Q2BGNLSL7E5QC MSRJ3N4NX255RVISUOPTTTY2GG4JVVNNM76HWUZ2EKCYESNI6MLQC SVY2PTCLXR3KNPQAWXVXTTGCC5DR334HOAKHYO3VDDRWM2BWMALAC CRX4RG35C3DH57NIXCW4CG4X7SBMSX7TAJR2BAFQ4LQKCLYUNANQC LZBHBSCXDX2JKU2BSO5QP3WDHFIGHPXK4CKUZV6FWYDRFWLQK26QC 4JHALUQLYAZQSH6MHLCS4EIIRHIT3Y4IYT2CE66NHSSWZFZY3SZQC HNPSSHGZFQ3E2I6X6VTKZ3WBBM2G25P2D7SIL2SZYKV2CCEA2ADAC IU2CR2KXWJ6QGCVGNCXUWKK2HDUYYVR5IU4D65WVPLV7KWS6PASAC ZIFFVCQ72K35WGIUMZYN3KOXIUXF2CNXWKG6ZWEZ6LT3NSF3XOQAC NGDLKK45NREMXETWADSYSC6NNAGN4X5BZDJXHLL432WTAJKCG36AC KVPP3CYPEFADQCL5Y56ELSUBA47SFNAJNCSVCSOK2GF67DHVMBCQC RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC PRQVFUGUGPKI2Q74ODEI3CYUJQB63CKC6ONQTE3BTOHKXG4JCNLQC 5YWWRDK5FK7BY5EPDN5YUHWM5MZUSHBARTQEQXGX3327OCM4O3AAC 5V47S4NNTHWTSAHV3YLO2VGH7JTUIYJ3GBPDN5ZM4UQALT2ZEXDQC 5B5DP5S6A6LQMKZYVLQAEMHQZWFWYDHPCKQGRNSCNNYIBQYZ6BIQC IHOKNI4O7EEW4UBMKHP6XOZNEIQSW4AYOT4O3JXUIXNNR553IQAQC CNBEMJYK6RATHVHUXN5RFKJCRHZJUCPOGHKWPVD4QLVNDNLDDCFQC GL7TJGUGV4JPLZCDWH6QVST4RYW7UJV6IP7UAEWEKNBWJO2H2ZHAC EJ64OVL7LJHMMGNKBJK5STXIL47GM2DFXVA4HEQWSCQWTNJL5D4AC IXLNOTBJGHKESBCTME6QAR6XVWFNCHYGMS62V62ZJEA7VLQHXO2QC RQR4PTMGQLTRWLYRU3KXIIDGND7FBORESJWMWFVD3WYU5SISZXAAC QCUMH3C7GXV7ZW444WT5SFAXQOJKJSE2YCQCEHMRYXCWF4QI7UMAC 4RFKVDJKTCRBZU6WPJ2E5OVI5IRPY3UTRPOBLC5QHY4CQJJTLZKQC YFIVTYI7PMVAXV23DUPXPAQNEY3YSFIXQGSN32I3WVHMMD5XS5DQC 25CH7HH4LKXFIZ75YNMXS3TSXO6O27DYSOPLOD45K4OCNFWLS4LQC DMG73XDQHY2X2PHKWIY56XKD3O4NPGZKKIO6GX3IV2LLRVXPGKYQC UOWPKKEVEMM6D67GLKB2PKCAWJU2GJJQTOLF6IQ6ZQB5WB3UH5JQC SDLKLUNFGVKDS55DDJZCBAVIB7NL3RRYPTACAY65SCUQKV6APFSAC BFCFMN2BXNLXJCYYCL2V2XTDQQNM3PJPSRB6CU76FM3332NC7GMAC SHFSQYLN7WPQC35V3XYYEIZ4CQMREASUNR474CIKFG3C2FYI4SHQC WXZQJUZXMYS7R6ORNB7DWE5KEUXT262GXWMRPOJYYB4I3BFGYLLAC TYCM7ZQG5JPPK4A5K6IBVRKJYQS2F2A3SESBC53MUNXHMZCKYF5QC VRFQK6S2TXOFFO5K5HRDXPR7QEKKAZAVCASSIJVPWQ4GE26UOGTQC QDWDUURSNLMT6AXNNJ3DEQCWAKCAIHV6MP5F7QGIBGXOG2BI2NPQC 3ZWALZFSTSIVYXY4BAY6ANGINTDACZC6RSSJTEMQSTSUIE66YOBQC MLZSEZWNNZMSIDQNAAIOJJR4K7VSVJICL5SAGHD3ROM7SYDVZABAC RYT42Z6CED4KV5CCJ45CHZ3DQGLFMDCVH6CSQZNXOILULDG4MXVQC ZCPJIAG7SEY2TUBAGOFWCEJYXSBT36CZU5VO7BWEGSLJ4K24B4TAC X2FMEN4E345XD26Z2X7JMJ7VGHOGCGIELMHQRE2ITLVNQACP3NOQC IPQ63XIUPHFMCQOZZAVSGCJOZFDRDWZTUUJSAUMARNDUFLBEMYIAC 6L4EP4ZRWWYLT55PD5KTTJON5J2JB5VV5MWNHF5VPZQZ5BKEYZ4QC HKQTMQVLLOBG2VO47TUGSTQALA3D2YLMEVADXXYNR4RGGKD3F2ZAC UW2ZVPHGKMKJVTB5LIV2DZCHXY6DSFRZ6DMKHLHFNHZUPRUAKHUAC Z6XF4AIERIW4U4AR3HU2ILYFZ54IK4K4ORQ6JKCEWRO5LZODWDDAC PAYI4UTJCR3XZSFOX5L35EURHRXQ6STO4Z7AQ3525QPNL3QYLNBAC 33MBISZXMRGZMQ37PVINHKNWAXHYPHURMRG6ST7O2SKIRGGBHI2AC RW3H34H6MQOI3CW4ILNH3VXRKQY73KIUGZKGDQDXPGGB5D6N4RFAC 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;}}
}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 descriptionif (alt == "Floor."){alt.clear();return false;
}
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];elseitem = &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);
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;
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();
}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 LOSif (!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 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);
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);
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;}}
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;}
void print_description(const std::string &body){describe_info inf;inf.body << body;print_description(inf);}
// 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;}
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); }};
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;}}std::string::size_type nextLine = std::string::npos;unsigned int currentPos = 0;
void print_description(const describe_info &inf){
// 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);