From 137d900672cf15df2d5f3cf5988aff20d33620f7 Mon Sep 17 00:00:00 2001 From: dshaligram Date: Fri, 25 Jan 2008 11:13:18 +0000 Subject: [1801838] Use a menu to show mutation list so long lists don't scroll off the end of the terminal. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@3331 c06c8d41-db1a-0410-9941-cceddc491573 --- crawl-ref/source/cio.h | 2 - crawl-ref/source/command.cc | 44 ++++++++++++++- crawl-ref/source/format.cc | 11 ++++ crawl-ref/source/format.h | 5 +- crawl-ref/source/libutil.cc | 6 ++ crawl-ref/source/libutil.h | 3 +- crawl-ref/source/menu.cc | 131 +++++++++++++++++++++++++------------------ crawl-ref/source/menu.h | 17 ++++++ crawl-ref/source/mon-util.cc | 10 +++- crawl-ref/source/mutation.cc | 9 +-- 10 files changed, 170 insertions(+), 68 deletions(-) diff --git a/crawl-ref/source/cio.h b/crawl-ref/source/cio.h index 93e6471df4..75e9ca048d 100644 --- a/crawl-ref/source/cio.h +++ b/crawl-ref/source/cio.h @@ -184,7 +184,6 @@ enum KEYS // Mouse codes. CK_MOUSE_MOVE = 10001, -#ifdef USE_TILE CK_MOUSE_DONE, CK_MOUSE_B1, CK_MOUSE_B2, @@ -193,7 +192,6 @@ enum KEYS CK_MOUSE_B5, CK_MOUSE_B1ITEM, CK_MOUSE_B2ITEM, -#endif CK_MOUSE_CLICK }; diff --git a/crawl-ref/source/command.cc b/crawl-ref/source/command.cc index c8ef7a641b..d94af8de8d 100644 --- a/crawl-ref/source/command.cc +++ b/crawl-ref/source/command.cc @@ -1318,19 +1318,58 @@ static int keyhelp_keyfilter(int ch) return ch; } +/////////////////////////////////////////////////////////////////////////// +// Manual menu highlighter. + +class help_highlighter : public MenuHighlighter +{ +public: + help_highlighter(); + int entry_colour(const MenuEntry *entry) const; +private: + text_pattern pattern; + std::string get_species_key() const; +}; + +help_highlighter::help_highlighter() + : pattern(get_species_key()) +{ +} + +int help_highlighter::entry_colour(const MenuEntry *entry) const +{ + return !pattern.empty() && pattern.matches(entry->text)? WHITE : -1; +} + +// to highlight species in aptitudes list ('?%') +std::string help_highlighter::get_species_key() const +{ + if (player_genus(GENPC_DRACONIAN) && you.experience_level < 7) + return ""; + + std::string result = species_name(you.species, you.experience_level); + if (player_genus(GENPC_DRACONIAN)) + strip_tag(result, + species_name(you.species, you.experience_level, true)); + + result += " "; + return (result); +} +//////////////////////////////////////////////////////////////////////////// + static void show_keyhelp_menu(const std::vector &lines, bool with_manual, bool easy_exit = false, int hotkey = 0) { formatted_scroller cmd_help; - + // Set flags, and use easy exit if necessary. int flags = MF_NOSELECT | MF_ALWAYS_SHOW_MORE | MF_NOWRAP; if (easy_exit) flags |= MF_EASY_EXIT; cmd_help.set_flags(flags, false); cmd_help.set_tag("help"); - + // FIXME: Allow for hiding Page down when at the end of the listing, ditto // for page up at start of listing. cmd_help.set_more( formatted_string::parse_string( @@ -1339,6 +1378,7 @@ static void show_keyhelp_menu(const std::vector &lines, if ( with_manual ) { + cmd_help.set_highlighter(new help_highlighter); cmd_help.f_keyfilter = keyhelp_keyfilter; column_composer cols(2, 40); diff --git a/crawl-ref/source/format.cc b/crawl-ref/source/format.cc index 33bb2a47d1..7d529315a3 100644 --- a/crawl-ref/source/format.cc +++ b/crawl-ref/source/format.cc @@ -31,6 +31,12 @@ int formatted_string::get_colour(const std::string &tag) return (colour != -1? colour : LIGHTGREY); } +// Parses a formatted string in much the same way as parse_string, but +// handles EOL by moving the cursor down to the next line instead of +// using a literal EOL. This is important if the text is not supposed +// to clobber existing text to the right of the lines being displayed +// (some of the tutorial messages need this). +// formatted_string formatted_string::parse_block( const std::string &s, bool eol_ends_format, @@ -208,6 +214,11 @@ std::string formatted_string::html_dump() const return s; } +bool formatted_string::operator < (const formatted_string &other) const +{ + return std::string(*this) < std::string(other); +} + const formatted_string & formatted_string::operator += (const formatted_string &other) { diff --git a/crawl-ref/source/format.h b/crawl-ref/source/format.h index 6376849b27..700f958af6 100644 --- a/crawl-ref/source/format.h +++ b/crawl-ref/source/format.h @@ -40,6 +40,7 @@ public: std::string::size_type length() const; std::string html_dump() const; + bool operator < ( const formatted_string &other ) const; const formatted_string &operator += (const formatted_string &other); public: @@ -59,7 +60,6 @@ private: int find_last_colour() const; public: - struct fs_op { fs_op_type type; @@ -89,7 +89,8 @@ public: void display() const; }; - std::vector ops; + typedef std::vector oplist; + oplist ops; }; int count_linebreaks(const formatted_string& fs); diff --git a/crawl-ref/source/libutil.cc b/crawl-ref/source/libutil.cc index ac78351bc2..62d7d9374e 100644 --- a/crawl-ref/source/libutil.cc +++ b/crawl-ref/source/libutil.cc @@ -466,6 +466,12 @@ std::string &trim_string( std::string &str ) return (str); } +std::string &trim_string_right( std::string &str ) +{ + str.erase( str.find_last_not_of( " \t\n\r" ) + 1 ); + return (str); +} + static void add_segment(std::vector &segs, std::string s, bool trim, diff --git a/crawl-ref/source/libutil.h b/crawl-ref/source/libutil.h index 4c64be32e6..11087ffd11 100644 --- a/crawl-ref/source/libutil.h +++ b/crawl-ref/source/libutil.h @@ -91,7 +91,8 @@ typedef void *(*p_compile)(const char *pattern, bool ignore_case); typedef void (*p_free)(void *cp); typedef bool (*p_match)(void *compiled_pattern, const char *text, int length); -std::string & trim_string( std::string &str ); +std::string &trim_string( std::string &str ); +std::string &trim_string_right( std::string &str ); std::string trimmed_string( std::string s ); inline bool starts_with(const std::string &s, const std::string &prefix) diff --git a/crawl-ref/source/menu.cc b/crawl-ref/source/menu.cc index c69380419c..81a16be254 100644 --- a/crawl-ref/source/menu.cc +++ b/crawl-ref/source/menu.cc @@ -18,29 +18,87 @@ #include "initfile.h" Menu::Menu( int _flags, const std::string& tagname ) - : f_selitem(NULL), - f_drawitem(NULL), - f_keyfilter(NULL), - title(NULL), - flags(_flags), - tag(tagname), - first_entry(0), - y_offset(0), - pagesize(0), - max_pagesize(0), - more("-more-", true), - items(), - sel(), - select_filter(), - highlighter(new MenuHighlighter), - num(-1), - lastch(0), - alive(false), - last_selected(-1) + : f_selitem(NULL), f_drawitem(NULL), f_keyfilter(NULL), title(NULL), + flags(_flags), tag(tagname), first_entry(0), y_offset(0), + pagesize(0), max_pagesize(0), more("-more-", true), items(), + sel(), select_filter(), highlighter(new MenuHighlighter), num(-1), + lastch(0), alive(false), last_selected(-1) { set_flags(flags); } +Menu::Menu( const formatted_string &fs ) + : f_selitem(NULL), f_drawitem(NULL), f_keyfilter(NULL), title(NULL), + + // This is a text-viewer menu, init flags to be easy on the user. + flags(MF_NOSELECT | MF_EASY_EXIT), + + tag(), first_entry(0), y_offset(0), pagesize(0), + max_pagesize(0), more("-more-", true), items(), sel(), + select_filter(), highlighter(new MenuHighlighter), num(-1), + lastch(0), alive(false), last_selected(-1) +{ + int colour = LIGHTGREY; + int last_text_colour = LIGHTGREY; + std::string line; + for (formatted_string::oplist::const_iterator i = fs.ops.begin(); + i != fs.ops.end(); ++i) + { + const formatted_string::fs_op &op(*i); + switch (op.type) + { + case FSOP_COLOUR: + colour = op.x; + break; + case FSOP_TEXT: + line += op.text; + if (op.text.find_first_not_of(" \t\r\n") != std::string::npos) + last_text_colour = colour; + check_add_formatted_line(last_text_colour, line, true); + break; + default: + break; + } + } + check_add_formatted_line(colour, line, false); +} + +void Menu::check_add_formatted_line(int col, std::string &line, bool check_eol) +{ + if (line.empty()) + return; + + if (check_eol && line.find(EOL) == std::string::npos) + return; + + std::vector lines = split_string(EOL, line, false, true); + int size = lines.size(); + + // If we have stuff after EOL, leave that in the line variable and + // don't add an entry for it, unless the caller told us not to + // check EOL sanity. + if (check_eol && !ends_with(line, EOL)) + line = lines[--size]; + else + line.clear(); + + for (int i = 0; i < size; ++i) + { + std::string &s(lines[i]); + + trim_string_right(s); + + MenuEntry *me = new MenuEntry(s); + me->colour = col; + if (!title) + set_title(me); + else + add_entry(me); + } + + line.clear(); +} + Menu::~Menu() { for (int i = 0, count = items.size(); i < count; ++i) @@ -176,16 +234,12 @@ bool Menu::process_key( int keyin ) case CK_ENTER: return false; case CK_ESCAPE: -#ifdef USE_TILE case CK_MOUSE_B2: -#endif sel.clear(); lastch = keyin; return false; case ' ': case CK_PGDN: case '>': case '\'': -#ifdef USE_TILE case CK_MOUSE_B1: -#endif nav = true; repaint = page_down(); if (!repaint && !is_set(MF_EASY_EXIT) && !is_set(MF_NOWRAP)) @@ -579,42 +633,11 @@ void Menu::update_title() gotoxy(x, y); } -// to highlight species in aptitudes list ('?%') -static std::string get_species_key() -{ - if (player_genus(GENPC_DRACONIAN) && you.experience_level < 7) - return ""; - - std::string result = ""; - switch (you.species) - { - case SP_RED_DRACONIAN: result = "Red"; break; - case SP_WHITE_DRACONIAN: result = "White"; break; - case SP_GREEN_DRACONIAN: result = "Green"; break; - case SP_GOLDEN_DRACONIAN: result = "Yellow"; break; - case SP_GREY_DRACONIAN: result = "Grey"; break; - case SP_BLACK_DRACONIAN: result = "Black"; break; - case SP_PURPLE_DRACONIAN: result = "Purple"; break; - case SP_MOTTLED_DRACONIAN: result = "Mottled"; break; - case SP_PALE_DRACONIAN: result = "Pale"; break; - default: - result = species_name(you.species, 1); - } - result += " "; - return (result); -} - int Menu::item_colour(int, const MenuEntry *entry) const { int icol = -1; if (highlighter) icol = highlighter->entry_colour(entry); - else - { - text_pattern tp(get_species_key()); - if (!tp.empty() && tp.matches(entry->text)) - icol = WHITE; - } return (icol == -1? entry->colour : icol); } diff --git a/crawl-ref/source/menu.h b/crawl-ref/source/menu.h index 86bdc4f246..88c1d00d0d 100644 --- a/crawl-ref/source/menu.h +++ b/crawl-ref/source/menu.h @@ -177,10 +177,26 @@ enum MenuFlag // you pass in MUST be allocated with new, or Crawl will crash. #define NUMBUFSIZ 10 + +// FIXME: MenuEntry is a large object, and shouldn't be used for +// showing text files. + class Menu { public: Menu( int flags = MF_MULTISELECT, const std::string& tagname = "" ); + + // Initializes a Menu from a formatted_string as follows: + // + // 1) Splits the formatted_string on EOL (this is not necessarily \n). + // 2) Picks the most recently used non-whitespace colour as the colour + // for the next line (so it can't do multiple colours on one line). + // 3) Ignores all cursor movement ops in the formatted_string. + // + // These are limitations that should be fixed eventually. + // + Menu( const formatted_string &fs ); + virtual ~Menu(); // Remove all items from the Menu, leave title intact. @@ -257,6 +273,7 @@ protected: int last_selected; protected: + void check_add_formatted_line(int col, std::string &line, bool check_eol); void do_menu(); virtual void draw_select_count(int count, bool force = false); virtual void draw_item( int index ) const; diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc index 9bf5b9cb22..c34626ca91 100644 --- a/crawl-ref/source/mon-util.cc +++ b/crawl-ref/source/mon-util.cc @@ -3945,9 +3945,13 @@ void monsters::load_spells(mon_spellbook_type book) } } #if DEBUG_DIAGNOSTICS - for (int i = 0; i < NUM_MONSTER_SPELL_SLOTS; i++) - mprf( MSGCH_DIAGNOSTICS, "Spell #%d: %d (%s)", - i, spells[i], spell_title(spells[i]) ); + // Only for ghosts, too spammy to use for all monsters. + if (book == MST_GHOST) + { + for (int i = 0; i < NUM_MONSTER_SPELL_SLOTS; i++) + mprf( MSGCH_DIAGNOSTICS, "Spell #%d: %d (%s)", + i, spells[i], spell_title(spells[i]) ); + } #endif } diff --git a/crawl-ref/source/mutation.cc b/crawl-ref/source/mutation.cc index c2cc554230..57b8549a9e 100644 --- a/crawl-ref/source/mutation.cc +++ b/crawl-ref/source/mutation.cc @@ -38,6 +38,7 @@ #include "format.h" #include "itemprop.h" #include "macro.h" +#include "menu.h" #include "notes.h" #include "ouch.h" #include "player.h" @@ -1333,10 +1334,10 @@ void display_mutations() { clrscr(); gotoxy(1,1); - describe_mutations().display(); - - if (getch() == 0) - getch(); + + const formatted_string mutation_fs = describe_mutations(); + Menu mutation_menu(mutation_fs); + mutation_menu.show(); } static int calc_mutation_amusement_value(mutation_type which_mutation) -- cgit v1.2.3-54-g00ecf