コード例 #1
0
ファイル: ui.cpp プロジェクト: terribleperson/Cataclysm-DDA
/**
 * Find the minimum width between max( min_width, 1 ) and
 * max( max_width, min_width, 1 ) to fold the string to no more than max_lines,
 * or no more than the minimum number of lines possible, assuming that
 * foldstring( width ).size() decreases monotonously with width.
 **/
static int find_minimum_fold_width( const std::string &str, int max_lines,
                                    int min_width, int max_width )
{
    if( str.empty() ) {
        return std::max( min_width, 1 );
    }
    min_width = std::max( min_width, 1 );
    // max_width could be further limited by the string width, but utf8_width is
    // not handling linebreaks properly.

    if( min_width < max_width ) {
        // If with max_width the string still folds to more than max_lines, find the
        // minimum width that folds the string to such number of lines instead.
        max_lines = std::max<int>( max_lines, foldstring( str, max_width ).size() );
        while( min_width < max_width ) {
            int width = ( min_width + max_width ) / 2;
            // width may equal min_width, but will always be less than max_width.
            int lines = foldstring( str, width ).size();
            // If the current width folds the string to no more than max_lines
            if( lines <= max_lines ) {
                // The minimum width is between min_width and width.
                max_width = width;
            } else {
                // The minimum width is between width + 1 and max_width.
                min_width = width + 1;
            }
            // The new interval will always be smaller than the previous one,
            // so the loop is guaranteed to end.
        }
    }
    return min_width;
};
コード例 #2
0
ファイル: ui.cpp プロジェクト: niglow/Cataclysm-DDA
// Find the best width to fold the string to no more than max_lines,
// Assuming that foldstring( width ).size() decreases monotonously w.r.t. width.
static int find_best_fold_width( const std::string &str, const int max_lines,
                                 const int max_width_avail )
{
    if( str.empty() ) {
        return 0;
    }
    // min_width inclusive, max_width exclusive.
    int min_width = 1;
    // +1 for exclusion.
    int max_width = std::min( utf8_width( str ), max_width_avail ) + 1;
    while( min_width + 1 < max_width ) {
        int width = ( min_width + max_width ) / 2;
        int lines = foldstring( str, width ).size();
        if( lines == max_lines ) {
            return width;
        } else if( lines < max_lines ) {
            // decrease width for more lines
            max_width = width;
        } else {
            // increase width for less lines
            min_width = width + 1;
        }
    }
    return min_width;
};
コード例 #3
0
ファイル: messages.cpp プロジェクト: Catacstone/Cataclysm-DDA
void Messages::display_messages(WINDOW *const ipk_target, int const left, int const top,
                                int const right, int const bottom)
{
    if (!size()) {
        return;
    }
    
    int const maxlength = right - left;
    int line = bottom;

    for (int i = size() - 1; i >= 0; --i) {
        if (line < top) {
            break;
        }

        const game_message &m = player_messages.impl_->messages[i];
        const nc_color col = m.get_color(player_messages.impl_->curmes);

        const auto folded_strings = foldstring(m.get_with_count(), maxlength);
        const auto folded_rend = folded_strings.rend();
        for( auto string_iter = folded_strings.rbegin();
             string_iter != folded_rend && line >= top; ++string_iter, line-- ) {
            mvwprintz(ipk_target, line, left, col, "%s", string_iter->c_str());
        }
    }

    player_messages.impl_->curmes = calendar::turn.get_turn();
}
コード例 #4
0
std::vector<std::string> requirement_data::get_folded_list( int width,
        const inventory &crafting_inv, const std::vector< std::vector<T> > &objs,
        int batch ) const
{
    // hack: ensure 'cached' availability is up to date
    can_make_with_inventory( crafting_inv );

    std::vector<std::string> out_buffer;
    for( const auto &comp_list : objs ) {
        const bool has_one = any_marked_available( comp_list );
        std::ostringstream buffer;
        for( auto a = comp_list.begin(); a != comp_list.end(); ++a ) {
            if( a != comp_list.begin() ) {
                buffer << "<color_white> " << _( "OR" ) << "</color> ";
            }
            const std::string col = a->get_color( has_one, crafting_inv, batch );
            buffer << "<color_" << col << ">" << a->to_string( batch ) << "</color>";
        }
        std::vector<std::string> folded = foldstring( buffer.str(), width - 2 );

        for( size_t i = 0; i < folded.size(); i++ ) {
            if( i == 0 ) {
                out_buffer.push_back( std::string( "> " ).append( folded[i] ) );
            } else {
                out_buffer.push_back( std::string( "  " ).append( folded[i] ) );
            }
        }
    }
    return out_buffer;
}
コード例 #5
0
ファイル: output.cpp プロジェクト: NickJ1984/Cataclysm-DDA
void popup_nowait(const char *mes, ...)
{
 va_list ap;
 va_start(ap, mes);
 char buff[4096];
 vsprintf(buff, mes, ap);
 va_end(ap);
 std::string tmp = buff;
 int width = 0;
 int height = 2;
 std::vector<std::string> folded = foldstring(tmp, 99999);
 height += folded.size();
 for(int i=0; i<folded.size(); i++) {
     int cw = utf8_width(folded[i].c_str());
     if(cw>width) {
         width = cw;
     }
 }
 width += 2;
 if (height > FULL_SCREEN_HEIGHT)
  height = FULL_SCREEN_HEIGHT;
 WINDOW *w = newwin(height, width, (TERMY-(height+1))/2, (TERMX > width) ? (TERMX-width)/2 : 0);
 wborder(w, LINE_XOXO, LINE_XOXO, LINE_OXOX, LINE_OXOX,
            LINE_OXXO, LINE_OOXX, LINE_XXOO, LINE_XOOX );
 for(int i=0; i<folded.size(); i++) {
     mvwprintz(w, i+1, 1, c_white, folded[i].c_str());
 }
 wrefresh(w);
 delwin(w);
 refresh();
}
コード例 #6
0
ファイル: output.cpp プロジェクト: ramza500/Cataclysm-DDA
int fold_and_print_from(WINDOW *w, int begin_y, int begin_x, int width, int begin_line,
                        nc_color base_color, const std::string &text)
{
    nc_color color = base_color;
    std::vector<std::string> textformatted;
    textformatted = foldstring(text, width);
    for (int line_num = 0; line_num < textformatted.size(); line_num++) {
        if (line_num >= begin_line) {
            wmove(w, line_num + begin_y - begin_line, begin_x);
        }
        // split into colourable sections
        std::vector<std::string> color_segments = split_by_color(textformatted[line_num]);
        // for each section, get the colour, and print it
        std::vector<std::string>::iterator it;
        for (it = color_segments.begin(); it != color_segments.end(); ++it) {
            if (!it->empty() && it->at(0) == '<') {
                color = get_color_from_tag(*it, base_color);
            }
            if (line_num >= begin_line) {
                std::string l = rm_prefix(*it);
                if(l != "--") { // -- is a newline!
                    wprintz(w, color, "%s", rm_prefix(*it).c_str());
                }
            }
        }
    }
    return textformatted.size();
};
コード例 #7
0
ファイル: output.cpp プロジェクト: 8Z/Cataclysm-DDA
// returns number of printed lines
int fold_and_print(WINDOW* w, int begin_y, int begin_x, int width, nc_color base_color, const char *mes, ...)
{
    va_list ap;
    va_start(ap,mes);
    char buff[6000];    //TODO replace Magic Number
    vsprintf(buff, mes, ap);
    va_end(ap);

    nc_color color = base_color;
    std::vector<std::string> textformatted;
    textformatted = foldstring(buff, width);
    for (int line_num=0; line_num<textformatted.size(); line_num++)
    {
        wmove(w, line_num+begin_y, begin_x);
        // split into colourable sections
        std::vector<std::string> color_segments = split_by_color(textformatted[line_num]);
        // for each section, get the colour, and print it
        std::vector<std::string>::iterator it;
        for (it = color_segments.begin(); it != color_segments.end(); ++it) {
            if (!it->empty() && it->at(0) == '<') {
                color = get_color_from_tag(*it, base_color);
            }
            wprintz(w, color, "%s", rm_prefix(*it).c_str());
        }
    }
    return textformatted.size();
};
コード例 #8
0
std::vector<std::string> Messages::dialog::filter_help_text( int width )
{
    const auto &help_fmt = _(
                               "Format is [[TYPE]:]TEXT. The values for TYPE are: %s\n"
                               "Examples:\n"
                               "  good:mutation\n"
                               "  :you pick up: 1\n"
                               "  crash!\n"
                           );
    std::stringstream type_text;
    const auto &type_list = msg_type_and_names();
    for( auto it = type_list.begin(); it != type_list.end(); ++it ) {
        // Skip m_debug outside debug mode (but allow searching for it)
        if( debug_mode || it->first != m_debug ) {
            const auto &col_name = get_all_colors().get_name( msgtype_to_color( it->first ) );
            auto next_it = std::next( it );
            // Skip m_debug outside debug mode
            if( !debug_mode && next_it != type_list.end() && next_it->first == m_debug ) {
                next_it = std::next( next_it );
            }
            if( next_it != type_list.end() ) {
                //~ the 2nd %s is a type name, this is used to format a list of type names
                type_text << string_format( pgettext( "message log", "<color_%s>%s</color>, " ),
                                            col_name, pgettext( "message type", it->second ) );
            } else {
                //~ the 2nd %s is a type name, this is used to format the last type name in a list of type names
                type_text << string_format( pgettext( "message log", "<color_%s>%s</color>." ),
                                            col_name, pgettext( "message type", it->second ) );
            }
        }
    }
    return foldstring( string_format( help_fmt, type_text.str() ), width );
}
コード例 #9
0
ファイル: wish.cpp プロジェクト: 8Z/Cataclysm-DDA
        virtual void select(int entnum, uimenu *menu) {
            const int starty = 3;
            const int startx = menu->w_width - menu->pad_right;
            itype *ity = item_controller->find_template(standard_itype_ids[entnum]);

            std::string padding = std::string(menu->pad_right - 1, ' ');

            for(int i = 0; i < lastlen + starty + 1; i++ ) {
                mvwprintw(menu->window, 1 + i, startx, "%s", padding.c_str() );
            }

            if ( ity != NULL ) {
                tmp.make(item_controller->find_template(standard_itype_ids[entnum]));
                tmp.bday = g->turn;
                if (tmp.is_tool()) {
                    tmp.charges = dynamic_cast<it_tool *>(tmp.type)->max_charges;
                } else if (tmp.is_ammo()) {
                    tmp.charges = 100;
                } else if (tmp.is_gun()) {
                    tmp.charges = 0;
                } else if (tmp.is_gunmod() && (tmp.has_flag("MODE_AUX") ||
                                               tmp.typeId() == "spare_mag")) {
                    tmp.charges = 0;
                } else {
                    tmp.charges = -1;
                }
                if( tmp.is_stationary() ) {
                    tmp.note = SNIPPET.assign( (dynamic_cast<it_stationary *>(tmp.type))->category );
                }

                std::vector<std::string> desc = foldstring(tmp.info(true), menu->pad_right - 1);
                int dsize = desc.size();
                if ( dsize > menu->w_height - 5 ) {
                    dsize = menu->w_height - 5;
                }
                lastlen = dsize;
                std::string header = string_format("#%d: %s%s",
                                                   entnum,
                                                   standard_itype_ids[entnum].c_str(),
                                                   ( incontainer ? " (contained)" : "" )
                                                  );

                mvwprintz(menu->window, 1, startx + ( menu->pad_right - 1 - header.size() ) / 2, c_cyan, "%s",
                          header.c_str()
                         );

                for(int i = 0; i < desc.size(); i++ ) {
                    mvwprintw(menu->window, starty + i, startx, "%s", desc[i].c_str() );
                }

                mvwprintz(menu->window, menu->w_height - 3, startx, c_green, "%s", msg.c_str());
                msg = padding;
                mvwprintw(menu->window, menu->w_height - 2, startx, "[/] find, [f] container, [q]uit");
            }
        }
コード例 #10
0
ファイル: output.cpp プロジェクト: GlyphGryph/Cataclysm-DDA
std::string string_input_popup(std::string title, int width, std::string input, std::string desc,
                               std::string identifier, int max_length )
{
    nc_color title_color = c_ltred;
    nc_color desc_color = c_green;

    std::vector<std::string> descformatted;

    int titlesize = utf8_width(title.c_str());
    int startx = titlesize + 2;
    if ( max_length == 0 ) {
        max_length = width;
    }
    int w_height = 3;
    int iPopupWidth = (width == 0) ? FULL_SCREEN_WIDTH : width + titlesize + 4;
    if (iPopupWidth > FULL_SCREEN_WIDTH) {
        iPopupWidth = FULL_SCREEN_WIDTH;
    }
    if ( desc.size() > 0 ) {
        int twidth = utf8_width(desc.c_str());
        if ( twidth > iPopupWidth - 4 ) {
            twidth = iPopupWidth - 4;
        }
        descformatted = foldstring(desc, twidth);
        w_height += descformatted.size();
    }
    int starty = 1 + descformatted.size();

    if ( max_length == 0 ) {
        max_length = 1024;
    }
    int w_y = (TERMY - w_height) / 2;
    int w_x = ((TERMX > iPopupWidth) ? (TERMX - iPopupWidth) / 2 : 0);
    WINDOW *w = newwin(w_height, iPopupWidth, w_y,
                       ((TERMX > iPopupWidth) ? (TERMX - iPopupWidth) / 2 : 0));

    wborder(w, LINE_XOXO, LINE_XOXO, LINE_OXOX, LINE_OXOX,
            LINE_OXXO, LINE_OOXX, LINE_XXOO, LINE_XOOX );

    int endx = iPopupWidth - 3;

    for(int i = 0; i < descformatted.size(); i++ ) {
        mvwprintz(w, 1 + i, 1, desc_color, "%s", descformatted[i].c_str() );
    }
    mvwprintz(w, starty, 1, title_color, "%s", title.c_str() );
    long key = 0;
    int pos = -1;
    std::string ret = string_input_win(w, input, max_length, startx, starty, endx, true, key, pos,
                                       identifier, w_x, w_y, true );
    werase(w);
    wrefresh(w);
    delwin(w);
    refresh();
    return ret;
}
コード例 #11
0
int monster::print_info(WINDOW* w, int vStart, int vLines, int column)
{
// First line of w is the border; the next two are terrain info, and after that
// is a blank line. w is 13 characters tall, and we can't use the last one
// because it's a border as well; so we have lines 4 through 11.
// w is also 48 characters wide - 2 characters for border = 46 characters for us
// vStart added because 'help' text in targeting win makes helpful info hard to find
// at a glance.

 const int vEnd = vStart + vLines;

 mvwprintz(w, vStart++, column, c_white, "%s ", name().c_str());
 nc_color color = c_white;
 std::string attitude = "";

 get_Attitude(color, attitude);
 wprintz(w, color, "%s", attitude.c_str());

 if (has_effect("downed"))
  wprintz(w, h_white, _("On ground"));
 else if (has_effect("stunned"))
  wprintz(w, h_white, _("Stunned"));
 else if (has_effect("beartrap"))
  wprintz(w, h_white, _("Trapped"));
 std::string damage_info;
 nc_color col;
 if (hp >= type->hp) {
  damage_info = _("It is uninjured");
  col = c_green;
 } else if (hp >= type->hp * .8) {
  damage_info = _("It is lightly injured");
  col = c_ltgreen;
 } else if (hp >= type->hp * .6) {
  damage_info = _("It is moderately injured");
  col = c_yellow;
 } else if (hp >= type->hp * .3) {
  damage_info = _("It is heavily injured");
  col = c_yellow;
 } else if (hp >= type->hp * .1) {
  damage_info = _("It is severely injured");
  col = c_ltred;
 } else {
  damage_info = _("it is nearly dead");
  col = c_red;
 }
 mvwprintz(w, vStart++, column, col, "%s", damage_info.c_str());

    std::vector<std::string> lines = foldstring(type->description, getmaxx(w) - 1 - column);
    int numlines = lines.size();
    for (int i = 0; i < numlines && vStart <= vEnd; i++)
        mvwprintz(w, vStart++, column, c_white, "%s", lines[i].c_str());

    return vStart;
}
コード例 #12
0
ファイル: output.cpp プロジェクト: ramza500/Cataclysm-DDA
long popup(const std::string &text, PopupFlags flags)
{
    int width = 0;
    int height = 2;
    std::vector<std::string> folded = foldstring(text, FULL_SCREEN_WIDTH - 2);
    height += folded.size();
    for( size_t i = 0; i < folded.size(); ++i ) {
        int cw = utf8_width(folded[i].c_str());
        if(cw > width) {
            width = cw;
        }
    }
    width += 2;
    WINDOW *w;
    if ((flags & PF_FULLSCREEN) != 0) {
        w = newwin(FULL_SCREEN_HEIGHT, FULL_SCREEN_WIDTH,
                        (TERMY > FULL_SCREEN_HEIGHT) ? (TERMY - FULL_SCREEN_HEIGHT) / 2 : 0,
                        (TERMX > FULL_SCREEN_WIDTH) ? (TERMX - FULL_SCREEN_WIDTH) / 2 : 0);
    } else if ((flags & PF_ON_TOP) == 0) {
        if (height > FULL_SCREEN_HEIGHT) {
            height = FULL_SCREEN_HEIGHT;
        }
        w = newwin(height, width, (TERMY - (height + 1)) / 2,
                       (TERMX > width) ? (TERMX - width) / 2 : 0);
    } else {
        w = newwin(height, width, 0, (TERMX > width) ? (TERMX - width) / 2 : 0);
    }
    draw_border(w);

    for( size_t i = 0; i < folded.size(); ++i ) {
        mvwprintz(w, i + 1, 1, c_white, "%s", folded[i].c_str());
    }

    long ch = 0;
    // Don't wait if not required.
    while((flags & PF_NO_WAIT) == 0) {
        wrefresh(w);
        ch = getch();
        if ((flags & PF_GET_KEY) != 0) {
            // return the first key that got pressed.
            werase(w);
            break;
        }
        if (ch == ' ' || ch == '\n' || ch == KEY_ESCAPE) {
            // The usuall "escape menu/window" keys.
            werase(w);
            break;
        }
    }
    wrefresh(w);
    delwin(w);
    refresh();
    return ch;
}
コード例 #13
0
void lua_console::read_stream( std::stringstream &stream, nc_color text_color )
{
    std::string line;
    while( std::getline( stream, line ) ) {
        for( auto str : foldstring( line, width ) ) {
            text_stack.push_back( {str, text_color} );
        }
    }
    stream.str( std::string() ); // empty the buffer
    stream.clear();
}
コード例 #14
0
ファイル: monster.cpp プロジェクト: donhayes/Cataclysm-DDA
int monster::print_info(WINDOW* w, int vStart, int vLines, int column) const
{
    const int vEnd = vStart + vLines;

    mvwprintz(w, vStart++, column, c_white, "%s ", name().c_str());
    nc_color color = c_white;
    std::string attitude = "";

    get_Attitude(color, attitude);
    wprintz(w, color, "%s", attitude.c_str());

    if (has_effect("downed")) {
        wprintz(w, h_white, _("On ground"));
    } else if (has_effect("stunned")) {
        wprintz(w, h_white, _("Stunned"));
    } else if (has_effect("beartrap")) {
        wprintz(w, h_white, _("Trapped"));
    } else if (has_effect("tied")) {
        wprintz(w, h_white, _("Tied"));
    }
    std::string damage_info;
    nc_color col;
    if (hp >= type->hp) {
        damage_info = _("It is uninjured");
        col = c_green;
    } else if (hp >= type->hp * .8) {
        damage_info = _("It is lightly injured");
        col = c_ltgreen;
    } else if (hp >= type->hp * .6) {
        damage_info = _("It is moderately injured");
        col = c_yellow;
    } else if (hp >= type->hp * .3) {
        damage_info = _("It is heavily injured");
        col = c_yellow;
    } else if (hp >= type->hp * .1) {
        damage_info = _("It is severely injured");
        col = c_ltred;
    } else {
        damage_info = _("it is nearly dead");
        col = c_red;
    }
    mvwprintz(w, vStart++, column, col, "%s", damage_info.c_str());

    std::vector<std::string> lines = foldstring(type->description, getmaxx(w) - 1 - column);
    int numlines = lines.size();
    for (int i = 0; i < numlines && vStart <= vEnd; i++) {
        mvwprintz(w, vStart++, column, c_white, "%s", lines[i].c_str());
    }

    return vStart;
}
コード例 #15
0
std::vector<std::string> requirement_data::get_folded_list( int width,
        const inventory &crafting_inv, const std::vector< std::vector<T> > &objs,
        int batch, std::string hilite ) const
{
    // hack: ensure 'cached' availability is up to date
    can_make_with_inventory( crafting_inv );

    std::vector<std::string> out_buffer;
    for( const auto &comp_list : objs ) {
        const bool has_one = any_marked_available( comp_list );
        std::ostringstream buffer;
        std::vector<std::string> buffer_has;
        bool already_has;
        for( auto a = comp_list.begin(); a != comp_list.end(); ++a ) {
            already_has = false;
            for( auto cont : buffer_has ) {
                if( cont == a->to_string( batch ) + a->get_color( has_one, crafting_inv, batch ) ) {
                    already_has = true;
                    break;
                }
            }
            if( already_has ) {
                continue;
            }

            if( a != comp_list.begin() ) {
                buffer << "<color_white> " << _( "OR" ) << "</color> ";
            }
            const std::string col = a->get_color( has_one, crafting_inv, batch );

            if( !hilite.empty() && lcmatch( a->to_string( batch ), hilite ) ) {
                buffer << get_tag_from_color( yellow_background( color_from_string( col ) ) );
            } else {
                buffer << "<color_" << col << ">";
            }
            buffer << a->to_string( batch ) << "</color>" << "</color>";
            buffer_has.push_back( a->to_string( batch ) + a->get_color( has_one, crafting_inv, batch ) );
        }
        std::vector<std::string> folded = foldstring( buffer.str(), width - 2 );

        for( size_t i = 0; i < folded.size(); i++ ) {
            if( i == 0 ) {
                out_buffer.push_back( std::string( "> " ).append( folded[i] ) );
            } else {
                out_buffer.push_back( std::string( "  " ).append( folded[i] ) );
            }
        }
    }
    return out_buffer;
}
コード例 #16
0
ファイル: output.cpp プロジェクト: NickJ1984/Cataclysm-DDA
// returns number of printed lines
int fold_and_print(WINDOW* w, int begin_y, int begin_x, int width, nc_color color, const char *mes, ...)
{
    va_list ap;
    va_start(ap,mes);
    char buff[6000];    //TODO replace Magic Number
    vsprintf(buff, mes, ap);
    va_end(ap);

    std::vector<std::string> textformatted;
    textformatted = foldstring(buff, width);
    for (int line_num=0; line_num<textformatted.size(); line_num++)
    {
        mvwprintz(w, line_num+begin_y, begin_x, color, "%s", textformatted[line_num].c_str());
    }
    return textformatted.size();
};
コード例 #17
0
ファイル: messages.cpp プロジェクト: Devanon/Cataclysm-DDA
void Messages::display_messages(WINDOW *ipk_target, int left, int top, int right, int bottom)
{
    if (!size()) {
        return;
    }
    const int maxlength = right - left;
    int line = bottom;
    for (int i = size() - 1; i >= 0 && line >= top; i--) {
        const game_message &m = player_messages.messages[i];
        const std::string mstr = m.get_with_count();
        const nc_color col = m.get_color();
        std::vector<std::string> folded = foldstring(mstr, maxlength);
        for (int j = folded.size() - 1; j >= 0 && line >= top; j--, line--) {
            mvwprintz(ipk_target, line, left, col, "%s", folded[j].c_str());
        }
    }
    player_messages.curmes = int(calendar::turn);
}
コード例 #18
0
ファイル: output.cpp プロジェクト: NeverGoWest/Cataclysm-DDA
bool query_yn(const char *mes, ...)
{
    va_list ap;
    va_start(ap, mes);
    char buff[1024];
    vsprintf(buff, mes, ap);
    va_end(ap);

    bool force_uc = OPTIONS["FORCE_CAPITAL_YN"];
    std::string query;
    if (force_uc) {
        query = string_format(_("%s (Y/N - Case Sensitive)"), buff);
    } else {
        query = string_format(_("%s (y/n)"), buff);
    }

    int win_width = utf8_width(query.c_str()) + 2;
    win_width = (win_width < FULL_SCREEN_WIDTH - 2 ? win_width : FULL_SCREEN_WIDTH - 2);

    std::vector<std::string> textformatted;
    textformatted = foldstring(query, win_width);
    WINDOW *w = newwin(textformatted.size() + 2, win_width, (TERMY - 3) / 2,
                       (TERMX > win_width) ? (TERMX - win_width) / 2 : 0);

    fold_and_print(w, 1, 1, win_width, c_ltred, query.c_str());

    draw_border(w);

    wrefresh(w);
    char ch;
    do {
        ch = getch();
    } while (ch != '\n' && ch != ' ' && ch != KEY_ESCAPE && ch != 'Y'
             && ch != 'N' && (force_uc || (ch != 'y' && ch != 'n')));
    werase(w);
    wrefresh(w);
    delwin(w);
    refresh();
    if (ch == 'Y' || ch == 'y') {
        return true;
    }
    return false;
}
コード例 #19
0
ファイル: output.cpp プロジェクト: NeverGoWest/Cataclysm-DDA
void popup(const char *mes, ...)
{
    va_list ap;
    va_start(ap, mes);
    char buff[4096];
    vsprintf(buff, mes, ap);
    va_end(ap);
    std::string tmp = buff;
    int width = 0;
    int height = 2;
    std::vector<std::string> folded = foldstring(tmp, FULL_SCREEN_WIDTH - 2);
    height += folded.size();
    for(int i = 0; i < folded.size(); i++) {
        int cw = utf8_width(folded[i].c_str());
        if(cw > width) {
            width = cw;
        }
    }
    width += 2;
    if (height > FULL_SCREEN_HEIGHT) {
        height = FULL_SCREEN_HEIGHT;
    }
    WINDOW *w = newwin(height, width, (TERMY - (height + 1)) / 2,
                       (TERMX > width) ? (TERMX - width) / 2 : 0);
    draw_border(w);

    for(int i = 0; i < folded.size(); i++) {
        mvwprintz(w, i + 1, 1, c_white, folded[i].c_str());
    }

    wrefresh(w);
    char ch;
    do {
        ch = getch();
    } while(ch != ' ' && ch != '\n' && ch != KEY_ESCAPE);
    werase(w);
    wrefresh(w);
    delwin(w);
    refresh();
}
コード例 #20
0
ファイル: output.cpp プロジェクト: NickJ1984/Cataclysm-DDA
void full_screen_popup(const char* mes, ...)
{
 va_list ap;
 va_start(ap, mes);
 char buff[8192];
 vsprintf(buff, mes, ap);
 va_end(ap);
 std::string tmp = buff;
 int width = 0;
 int height = 2;
 std::vector<std::string> folded = foldstring(tmp, FULL_SCREEN_WIDTH-3);
 height += folded.size();
 for(int i=0; i<folded.size(); i++) {
     int cw = utf8_width(folded[i].c_str());
     if(cw>width) {
         width = cw;
     }
 }
 width += 2;

 WINDOW *w = newwin(FULL_SCREEN_HEIGHT, FULL_SCREEN_WIDTH,
                    (TERMY > FULL_SCREEN_HEIGHT) ? (TERMY-FULL_SCREEN_HEIGHT)/2 : 0,
                    (TERMX > FULL_SCREEN_WIDTH) ? (TERMX-FULL_SCREEN_WIDTH)/2 : 0);
 wborder(w, LINE_XOXO, LINE_XOXO, LINE_OXOX, LINE_OXOX,
            LINE_OXXO, LINE_OOXX, LINE_XXOO, LINE_XOOX );

 for(int i=0; i<folded.size(); i++) {
     mvwprintz(w, i+1, 2, c_white, folded[i].c_str());
 }

 wrefresh(w);
 char ch;
 do
  ch = getch();
 while(ch != ' ' && ch != '\n' && ch != KEY_ESCAPE);
 werase(w);
 wrefresh(w);
 delwin(w);
 refresh();
}
コード例 #21
0
ファイル: output.cpp プロジェクト: NickJ1984/Cataclysm-DDA
void popup_top(const char *mes, ...)
{
 va_list ap;
 va_start(ap, mes);
 char buff[4096];
 vsprintf(buff, mes, ap);
 va_end(ap);
 std::string tmp = buff;
 int width = 0;
 int height = 2;
 std::vector<std::string> folded = foldstring(tmp, 99999);
 height += folded.size();
 for(int i=0; i<folded.size(); i++) {
     int cw = utf8_width(folded[i].c_str());
     if(cw>width) {
         width = cw;
     }
 }
 width += 2;
 WINDOW *w = newwin(height, width, 0, (TERMX > width) ? (TERMX-width)/2 : 0);
 wborder(w, LINE_XOXO, LINE_XOXO, LINE_OXOX, LINE_OXOX,
            LINE_OXXO, LINE_OOXX, LINE_XXOO, LINE_XOOX );

 for(int i=0; i<folded.size(); i++) {
     mvwprintz(w, i+1, 1, c_white, folded[i].c_str());
 }

 wrefresh(w);
 char ch;
 do
  ch = getch();
 while(ch != ' ' && ch != '\n' && ch != KEY_ESCAPE);
 werase(w);
 wrefresh(w);
 delwin(w);
 refresh();
}
コード例 #22
0
ファイル: output.cpp プロジェクト: ramza500/Cataclysm-DDA
void multipage(WINDOW *w, std::vector<std::string> text, std::string caption, int begin_y)
{
    int height = getmaxy(w);
    int width = getmaxx(w);

    //Do not erase the current screen if it's not first line of the text
    if (begin_y == 0) {
        werase(w);
    }

    /* TODO:
        issue:     # of lines in the paragraph > height -> inf. loop;
        solution:  split this paragraph in two pieces;
    */
    for (size_t i = 0; i < text.size(); i++) {
        if (begin_y == 0 && caption != "") {
            begin_y = fold_and_print(w, 0, 1, width - 2, c_white, caption) + 1;
        }
        std::vector<std::string> next_paragraph = foldstring(text[i].c_str(), width - 2);
        if (begin_y + next_paragraph.size() > height - ((i + 1) < text.size() ? 1 : 0)) {
            // Next page
            i--;
            mvwprintw(w, height - 1, 1, _("Press any key for more..."));
            wrefresh(w);
            refresh();
            getch();
            werase(w);
            begin_y = 0;
        } else {
            begin_y += fold_and_print(w, begin_y, 1, width - 2, c_white, text[i]) + 1;
        }
    }
    wrefresh(w);
    refresh();
    getch();
}
コード例 #23
0
const recipe *select_crafting_recipe( int &batch_size )
{
    if( normalized_names.empty() ) {
        translate_all();
    }

    const int headHeight = 3;
    const int subHeadHeight = 2;
    const int freeWidth = TERMX - FULL_SCREEN_WIDTH;
    bool isWide = ( TERMX > FULL_SCREEN_WIDTH && freeWidth > 15 );

    const int width = isWide ? ( freeWidth > FULL_SCREEN_WIDTH ? FULL_SCREEN_WIDTH * 2 : TERMX ) :
                      FULL_SCREEN_WIDTH;
    const int wStart = ( TERMX - width ) / 2;
    const int tailHeight = isWide ? 3 : 4;
    const int dataLines = TERMY - ( headHeight + subHeadHeight ) - tailHeight;
    const int dataHalfLines = dataLines / 2;
    const int dataHeight = TERMY - ( headHeight + subHeadHeight );
    const int infoWidth = width - FULL_SCREEN_WIDTH - 1;

    const recipe *last_recipe = nullptr;

    catacurses::window w_head = catacurses::newwin( headHeight, width, 0, wStart );
    catacurses::window w_subhead = catacurses::newwin( subHeadHeight, width, 3, wStart );
    catacurses::window w_data = catacurses::newwin( dataHeight, width, headHeight + subHeadHeight,
                                wStart );

    int item_info_x = infoWidth;
    int item_info_y = dataHeight - 3;
    int item_info_width = wStart + width - infoWidth;
    int item_info_height = headHeight + subHeadHeight;

    if( !isWide ) {
        item_info_x = 1;
        item_info_y = 1;
        item_info_width = 1;
        item_info_height = 1;
    }

    catacurses::window w_iteminfo = catacurses::newwin( item_info_y, item_info_x, item_info_height,
                                    item_info_width );

    list_circularizer<std::string> tab( craft_cat_list );
    list_circularizer<std::string> subtab( craft_subcat_list[tab.cur()] );
    std::vector<const recipe *> current;
    std::vector<bool> available;
    const int componentPrintHeight = dataHeight - tailHeight - 1;
    //preserves component color printout between mode rotations
    nc_color rotated_color = c_white;
    int previous_item_line = -1;
    std::string previous_tab;
    std::string previous_subtab;
    item tmp;
    int line = 0;
    int ypos = 0;
    int scroll_pos = 0;
    bool redraw = true;
    bool keepline = false;
    bool done = false;
    bool batch = false;
    bool show_hidden = false;
    int batch_line = 0;
    int display_mode = 0;
    const recipe *chosen = nullptr;
    std::vector<iteminfo> thisItem;
    std::vector<iteminfo> dummy;

    input_context ctxt( "CRAFTING" );
    ctxt.register_cardinal();
    ctxt.register_action( "QUIT" );
    ctxt.register_action( "CONFIRM" );
    ctxt.register_action( "CYCLE_MODE" );
    ctxt.register_action( "SCROLL_UP" );
    ctxt.register_action( "SCROLL_DOWN" );
    ctxt.register_action( "PREV_TAB" );
    ctxt.register_action( "NEXT_TAB" );
    ctxt.register_action( "FILTER" );
    ctxt.register_action( "RESET_FILTER" );
    ctxt.register_action( "TOGGLE_FAVORITE" );
    ctxt.register_action( "HELP_RECIPE" );
    ctxt.register_action( "HELP_KEYBINDINGS" );
    ctxt.register_action( "CYCLE_BATCH" );
    ctxt.register_action( "RELATED_RECIPES" );
    ctxt.register_action( "HIDE_SHOW_RECIPE" );

    const inventory &crafting_inv = g->u.crafting_inventory();
    const std::vector<npc *> helpers = g->u.get_crafting_helpers();
    std::string filterstring;

    const auto &available_recipes = g->u.get_available_recipes( crafting_inv, &helpers );
    std::map<const recipe *, bool> availability_cache;

    do {
        if( redraw ) {
            // When we switch tabs, redraw the header
            redraw = false;
            if( ! keepline ) {
                line = 0;
            } else {
                keepline = false;
            }

            if( display_mode > 2 ) {
                display_mode = 2;
            }

            TAB_MODE m = ( batch ) ? BATCH : ( filterstring.empty() ) ? NORMAL : FILTERED;
            draw_recipe_tabs( w_head, tab.cur(), m );
            draw_recipe_subtabs( w_subhead, tab.cur(), subtab.cur(), available_recipes, m );

            show_hidden = false;
            available.clear();

            if( batch ) {
                current.clear();
                for( int i = 1; i <= 20; i++ ) {
                    current.push_back( chosen );
                    available.push_back( chosen->requirements().can_make_with_inventory( crafting_inv, i ) );
                }
            } else {
                std::vector<const recipe *> picking;
                if( !filterstring.empty() ) {
                    auto qry = trim( filterstring );
                    if( qry.size() > 2 && qry[1] == ':' ) {
                        switch( qry[0] ) {
                            case 't':
                                picking = available_recipes.search( qry.substr( 2 ), recipe_subset::search_type::tool );
                                break;

                            case 'c':
                                picking = available_recipes.search( qry.substr( 2 ), recipe_subset::search_type::component );
                                break;

                            case 's':
                                picking = available_recipes.search( qry.substr( 2 ), recipe_subset::search_type::skill );
                                break;

                            case 'p':
                                picking = available_recipes.search( qry.substr( 2 ), recipe_subset::search_type::primary_skill );
                                break;

                            case 'Q':
                                picking = available_recipes.search( qry.substr( 2 ), recipe_subset::search_type::quality );
                                break;

                            case 'q':
                                picking = available_recipes.search( qry.substr( 2 ), recipe_subset::search_type::quality_result );
                                break;

                            case 'd':
                                picking = available_recipes.search( qry.substr( 2 ),
                                                                    recipe_subset::search_type::description_result );
                                break;

                            case 'm': {
                                auto &learned = g->u.get_learned_recipes();
                                if( query_is_yes( qry ) ) {
                                    std::set_intersection( available_recipes.begin(), available_recipes.end(), learned.begin(),
                                                           learned.end(), std::back_inserter( picking ) );
                                } else {
                                    std::set_difference( available_recipes.begin(), available_recipes.end(), learned.begin(),
                                                         learned.end(),
                                                         std::back_inserter( picking ) );
                                }
                                break;
                            }

                            case 'h': {
                                std::copy( available_recipes.begin(), available_recipes.end(), std::back_inserter( picking ) );
                                if( query_is_yes( qry ) ) {
                                    show_hidden = true;
                                }
                                break;
                            }

                            default:
                                current.clear();
                        }
                    } else {
                        picking = available_recipes.search( qry );
                    }
                } else if( subtab.cur() == "CSC_*_FAVORITE" ) {
                    picking = available_recipes.favorite();
                } else if( subtab.cur() == "CSC_*_RECENT" ) {
                    picking = available_recipes.recent();
                } else {
                    picking = available_recipes.in_category( tab.cur(), subtab.cur() != "CSC_ALL" ? subtab.cur() : "" );
                }

                current.clear();
                for( auto i : picking ) {
                    if( ( uistate.hidden_recipes.find( i->ident() ) != uistate.hidden_recipes.end() ) == show_hidden ) {
                        current.push_back( i );
                    }
                }
                if( !show_hidden ) {
                    draw_hidden_amount( w_head, 0, picking.size() - current.size() );
                }

                available.reserve( current.size() );
                // cache recipe availability on first display
                for( const auto e : current ) {
                    if( !availability_cache.count( e ) ) {
                        availability_cache.emplace( e, e->requirements().can_make_with_inventory( crafting_inv ) );
                    }
                }

                if( subtab.cur() != "CSC_*_RECENT" ) {
                    std::stable_sort( current.begin(), current.end(), []( const recipe * a, const recipe * b ) {
                        return b->difficulty < a->difficulty;
                    } );

                    std::stable_sort( current.begin(), current.end(), [&]( const recipe * a, const recipe * b ) {
                        return availability_cache[a] && !availability_cache[b];
                    } );
                }

                std::transform( current.begin(), current.end(),
                std::back_inserter( available ), [&]( const recipe * e ) {
                    return availability_cache[e];
                } );
            }

            // current/available have been rebuilt, make sure our cursor is still in range
            if( current.empty() ) {
                line = 0;
            } else {
                line = std::min( line, static_cast<int>( current.size() ) - 1 );
            }
        }

        // Clear the screen of recipe data, and draw it anew
        werase( w_data );

        if( isWide ) {
            werase( w_iteminfo );
        }

        if( isWide ) {
            mvwprintz( w_data, dataLines + 1, 5, c_white,
                       _( "Press <ENTER> to attempt to craft object." ) );
            wprintz( w_data, c_white, "  " );
            if( !filterstring.empty() ) {
                wprintz( w_data, c_white,
                         _( "[E]: Describe, [F]ind, [R]eset, [m]ode, [s]how/hide, Re[L]ated, [*]Favorite, %s [?] keybindings" ),
                         ( batch ) ? _( "cancel [b]atch" ) : _( "[b]atch" ) );
            } else {
                wprintz( w_data, c_white,
                         _( "[E]: Describe, [F]ind, [m]ode, [s]how/hide, Re[L]ated, [*]Favorite, %s [?] keybindings" ),
                         ( batch ) ? _( "cancel [b]atch" ) : _( "[b]atch" ) );
            }
        } else {
            if( !filterstring.empty() ) {
                mvwprintz( w_data, dataLines + 1, 5, c_white,
                           _( "[E]: Describe, [F]ind, [R]eset, [m]ode, [s]how/hide, Re[L]ated, [*]Favorite, [b]atch [?] keybindings" ) );
            } else {
                mvwprintz( w_data, dataLines + 1, 5, c_white,
                           _( "[E]: Describe, [F]ind, [m]ode, [s]how/hide, Re[L]ated, [*]Favorite, [b]atch [?] keybindings" ) );
            }
            mvwprintz( w_data, dataLines + 2, 5, c_white,
                       _( "Press <ENTER> to attempt to craft object." ) );
        }
        // Draw borders
        for( int i = 1; i < width - 1; ++i ) { // _
            mvwputch( w_data, dataHeight - 1, i, BORDER_COLOR, LINE_OXOX );
        }
        for( int i = 0; i < dataHeight - 1; ++i ) { // |
            mvwputch( w_data, i, 0, BORDER_COLOR, LINE_XOXO );
            mvwputch( w_data, i, width - 1, BORDER_COLOR, LINE_XOXO );
        }
        mvwputch( w_data, dataHeight - 1,  0, BORDER_COLOR, LINE_XXOO ); // _|
        mvwputch( w_data, dataHeight - 1, width - 1, BORDER_COLOR, LINE_XOOX ); // |_

        int recmin = 0, recmax = current.size();
        if( recmax > dataLines ) {
            if( line <= recmin + dataHalfLines ) {
                for( int i = recmin; i < recmin + dataLines; ++i ) {
                    std::string tmp_name = current[i]->result_name();
                    if( batch ) {
                        tmp_name = string_format( _( "%2dx %s" ), i + 1, tmp_name.c_str() );
                    }
                    mvwprintz( w_data, i - recmin, 2, c_dark_gray, "" ); // Clear the line
                    if( i == line ) {
                        mvwprintz( w_data, i - recmin, 2, ( available[i] ? h_white : h_dark_gray ),
                                   utf8_truncate( tmp_name, 28 ).c_str() );
                    } else {
                        mvwprintz( w_data, i - recmin, 2, ( available[i] ? c_white : c_dark_gray ),
                                   utf8_truncate( tmp_name, 28 ).c_str() );
                    }
                }
            } else if( line >= recmax - dataHalfLines ) {
                for( int i = recmax - dataLines; i < recmax; ++i ) {
                    std::string tmp_name = current[i]->result_name();
                    if( batch ) {
                        tmp_name = string_format( _( "%2dx %s" ), i + 1, tmp_name.c_str() );
                    }
                    mvwprintz( w_data, dataLines + i - recmax, 2, c_light_gray, "" ); // Clear the line
                    if( i == line ) {
                        mvwprintz( w_data, dataLines + i - recmax, 2,
                                   ( available[i] ? h_white : h_dark_gray ),
                                   utf8_truncate( tmp_name, 28 ).c_str() );
                    } else {
                        mvwprintz( w_data, dataLines + i - recmax, 2,
                                   ( available[i] ? c_white : c_dark_gray ),
                                   utf8_truncate( tmp_name, 28 ).c_str() );
                    }
                }
            } else {
                for( int i = line - dataHalfLines; i < line - dataHalfLines + dataLines; ++i ) {
                    std::string tmp_name = current[i]->result_name();
                    if( batch ) {
                        tmp_name = string_format( _( "%2dx %s" ), i + 1, tmp_name.c_str() );
                    }
                    mvwprintz( w_data, dataHalfLines + i - line, 2, c_light_gray, "" ); // Clear the line
                    if( i == line ) {
                        mvwprintz( w_data, dataHalfLines + i - line, 2,
                                   ( available[i] ? h_white : h_dark_gray ),
                                   utf8_truncate( tmp_name, 28 ).c_str() );
                    } else {
                        mvwprintz( w_data, dataHalfLines + i - line, 2,
                                   ( available[i] ? c_white : c_dark_gray ),
                                   utf8_truncate( tmp_name, 28 ).c_str() );
                    }
                }
            }
        } else {
            for( size_t i = 0; i < current.size() && i < static_cast<size_t>( dataHeight ) + 1; ++i ) {
                std::string tmp_name = current[i]->result_name();
                if( batch ) {
                    tmp_name = string_format( _( "%2dx %s" ), static_cast<int>( i ) + 1, tmp_name.c_str() );
                }
                if( static_cast<int>( i ) == line ) {
                    mvwprintz( w_data, i, 2, ( available[i] ? h_white : h_dark_gray ),
                               utf8_truncate( tmp_name, 28 ).c_str() );
                } else {
                    mvwprintz( w_data, i, 2, ( available[i] ? c_white : c_dark_gray ),
                               utf8_truncate( tmp_name, 28 ).c_str() );
                }
            }
        }

        if( !current.empty() ) {
            int pane = FULL_SCREEN_WIDTH - 30 - 1;
            int count = batch ? line + 1 : 1; // batch size
            nc_color col = available[ line ] ? c_white : c_light_gray;

            const auto &req = current[ line ]->requirements();

            draw_can_craft_indicator( w_head, 0, *current[line] );
            wrefresh( w_head );

            ypos = 0;

            auto qry = trim( filterstring );
            std::string qry_comps;
            if( qry.compare( 0, 2, "c:" ) == 0 ) {
                qry_comps = qry.substr( 2 );
            }

            std::vector<std::string> component_print_buffer;
            auto tools = req.get_folded_tools_list( pane, col, crafting_inv, count );
            auto comps = req.get_folded_components_list( pane, col, crafting_inv, count, qry_comps );
            component_print_buffer.insert( component_print_buffer.end(), tools.begin(), tools.end() );
            component_print_buffer.insert( component_print_buffer.end(), comps.begin(), comps.end() );

            if( !g->u.knows_recipe( current[line] ) ) {
                component_print_buffer.push_back( _( "Recipe not memorized yet" ) );
                auto books_with_recipe = g->u.get_books_for_recipe( crafting_inv, current[line] );
                std::string enumerated_books =
                    enumerate_as_string( books_with_recipe.begin(), books_with_recipe.end(),
                []( itype_id type_id ) {
                    return item::find_type( type_id )->nname( 1 );
                } );
                const std::string text = string_format( _( "Written in: %s" ), enumerated_books.c_str() );
                std::vector<std::string> folded_lines = foldstring( text, pane );
                component_print_buffer.insert(
                    component_print_buffer.end(), folded_lines.begin(), folded_lines.end() );
            }

            //handle positioning of component list if it needed to be scrolled
            int componentPrintOffset = 0;
            if( display_mode > 2 ) {
                componentPrintOffset = ( display_mode - 2 ) * componentPrintHeight;
            }
            if( component_print_buffer.size() < static_cast<size_t>( componentPrintOffset ) ) {
                componentPrintOffset = 0;
                if( previous_tab != tab.cur() || previous_subtab != subtab.cur() || previous_item_line != line ) {
                    display_mode = 2;
                } else {
                    display_mode = 0;
                }
            }

            //only used to preserve mode position on components when
            //moving to another item and the view is already scrolled
            previous_tab = tab.cur();
            previous_subtab = subtab.cur();
            previous_item_line = line;
            const int xpos = 30;

            if( display_mode == 0 ) {
                const int width = getmaxx( w_data ) - xpos - item_info_x;
                print_colored_text(
                    w_data, ypos++, xpos, col, col,
                    string_format( _( "Primary skill used: <color_cyan>%s</color>" ),
                                   ( !current[line]->skill_used ? _( "N/A" ) :
                                     current[line]->skill_used.obj().name() ) ) );
                auto player_skill = g->u.get_skill_level( current[line]->skill_used );
                std::string difficulty_color =
                    current[ line ]->difficulty > player_skill ? "yellow" : "green";
                print_colored_text(
                    w_data, ypos++, xpos, col, col,
                    string_format( _( "Difficulty: <color_%s>%d</color>" ),
                                   difficulty_color, current[ line ]->difficulty ) );
                std::string skill_level_string =
                    current[line]->skill_used ?
                    string_format( _( "Your skill level: <color_%s>%d</color>" ),
                                   difficulty_color, player_skill ) :
                    _( "Your skill level: <color_yellow>N/A</color>" );
                print_colored_text( w_data, ypos++, xpos, col, col, skill_level_string );
                ypos += fold_and_print( w_data, ypos, xpos, width, col,
                                        _( "Other skills used: %s" ),
                                        current[line]->required_skills_string( &g->u ) );

                const int expected_turns = g->u.expected_time_to_craft( *current[line],
                                           count ) / to_moves<int>( 1_turns );
                ypos += fold_and_print( w_data, ypos, xpos, pane, col,
                                        _( "Time to complete: <color_cyan>%s</color>" ),
                                        to_string( time_duration::from_turns( expected_turns ) ) );

                print_colored_text(
                    w_data, ypos++, xpos, col, col,
                    string_format( _( "Dark craftable? <color_cyan>%s</color>" ),
                                   current[line]->has_flag( "BLIND_EASY" ) ? _( "Easy" ) :
                                   current[line]->has_flag( "BLIND_HARD" ) ? _( "Hard" ) :
                                   _( "Impossible" ) ) );
                ypos += print_items( *current[line], w_data, ypos, xpos, col, batch ? line + 1 : 1 );
            }

            //color needs to be preserved in case part of the previous page was cut off
            nc_color stored_color = col;
            if( display_mode > 2 ) {
                stored_color = rotated_color;
            } else {
                rotated_color = col;
            }
            int components_printed = 0;
            for( size_t i = static_cast<size_t>( componentPrintOffset );
                 i < component_print_buffer.size(); i++ ) {
                if( ypos >= componentPrintHeight ) {
                    break;
                }

                components_printed++;
                print_colored_text( w_data, ypos++, xpos, stored_color, col, component_print_buffer[i] );
            }

            if( ypos >= componentPrintHeight &&
                component_print_buffer.size() > static_cast<size_t>( components_printed ) ) {
                mvwprintz( w_data, ypos++, xpos, col, _( "v (more)" ) );
                rotated_color = stored_color;
            }

            if( isWide ) {
                if( last_recipe != current[line] ) {
                    last_recipe = current[line];
                    tmp = current[line]->create_result();
                }
                tmp.info( true, thisItem, count );
                draw_item_info( w_iteminfo, tmp.tname(), tmp.type_name(), thisItem, dummy,
                                scroll_pos, true, true, true, false, true );
            }
        }

        draw_scrollbar( w_data, line, dataLines, recmax, 0 );
        wrefresh( w_data );

        if( isWide ) {
            wrefresh( w_iteminfo );
        }

        const std::string action = ctxt.handle_input();
        if( action == "CYCLE_MODE" ) {
            display_mode = display_mode + 1;
            if( display_mode <= 0 ) {
                display_mode = 0;
            }
        } else if( action == "LEFT" ) {
            std::string start = subtab.cur();
            do {
                subtab.prev();
            } while( subtab.cur() != start && available_recipes.empty_category( tab.cur(),
                     subtab.cur() != "CSC_ALL" ? subtab.cur() : "" ) );
            redraw = true;
        } else if( action == "SCROLL_UP" ) {
            scroll_pos--;
        } else if( action == "SCROLL_DOWN" ) {
            scroll_pos++;
        } else if( action == "PREV_TAB" ) {
            tab.prev();
            subtab = list_circularizer<std::string>( craft_subcat_list[tab.cur()] );//default ALL
            redraw = true;
        } else if( action == "RIGHT" ) {
            std::string start = subtab.cur();
            do {
                subtab.next();
            } while( subtab.cur() != start && available_recipes.empty_category( tab.cur(),
                     subtab.cur() != "CSC_ALL" ? subtab.cur() : "" ) );
            redraw = true;
        } else if( action == "NEXT_TAB" ) {
            tab.next();
            subtab = list_circularizer<std::string>( craft_subcat_list[tab.cur()] );//default ALL
            redraw = true;
        } else if( action == "DOWN" ) {
            line++;
        } else if( action == "UP" ) {
            line--;
        } else if( action == "CONFIRM" ) {
            if( available.empty() || !available[line] ) {
                popup( _( "You can't do that!" ) );
            } else if( !g->u.check_eligible_containers_for_crafting( *current[line],
                       ( batch ) ? line + 1 : 1 ) ) {
                // popup is already inside check
            } else {
                chosen = current[line];
                batch_size = ( batch ) ? line + 1 : 1;
                done = true;
            }
        } else if( action == "HELP_RECIPE" ) {
            if( current.empty() ) {
                popup( _( "Nothing selected!" ) );
                redraw = true;
                continue;
            }
            tmp = current[line]->create_result();

            full_screen_popup( "%s\n%s", tmp.type_name( 1 ).c_str(),  tmp.info( true ).c_str() );
            redraw = true;
            keepline = true;
        } else if( action == "FILTER" ) {
            struct SearchPrefix {
                char key;
                std::string example;
                std::string description;
            };
            std::vector<SearchPrefix> prefixes = {
                { 'q', _( "metal sawing" ), _( "<color_cyan>quality</color> of resulting item" ) },
                //~ Example result description search term
                { 'd', _( "reach attack" ), _( "<color_cyan>full description</color> of resulting item (slow)" ) },
                { 'c', _( "two by four" ), _( "<color_cyan>component</color> required to craft" ) },
                { 'p', _( "tailoring" ), _( "<color_cyan>primary skill</color> used to craft" ) },
                { 's', _( "cooking" ), _( "<color_cyan>any skill</color> used to craft" ) },
                { 'Q', _( "fine bolt turning" ), _( "<color_cyan>quality</color> required to craft" ) },
                { 't', _( "soldering iron" ), _( "<color_cyan>tool</color> required to craft" ) },
                { 'h', _( "yes" ), _( "recipes which are <color_cyan>hidden</color> or not" ) },
                { 'm', _( "no" ), _( "recipes which are <color_cyan>memorized</color> or not" ) },
            };
            int max_example_length = 0;
            for( const auto &prefix : prefixes ) {
                max_example_length = std::max( max_example_length, utf8_width( prefix.example ) );
            }
            std::string spaces( max_example_length, ' ' );

            std::string description =
                _( "The default is to search result names.  Some single-character prefixes "
                   "can be used with a colon (:) to search in other ways.\n"
                   "\n"
                   "<color_white>Examples:</color>\n" );

            {
                std::string example_name = _( "shirt" );
                auto padding = max_example_length - utf8_width( example_name );
                description += string_format(
                                   _( "  <color_white>%s</color>%.*s    %s\n" ),
                                   example_name, padding, spaces,
                                   _( "<color_cyan>name</color> of resulting item" ) );
            }

            for( const auto &prefix : prefixes ) {
                auto padding = max_example_length - utf8_width( prefix.example );
                description += string_format(
                                   _( "  <color_yellow>%c</color><color_white>:%s</color>%.*s  %s\n" ),
                                   prefix.key, prefix.example, padding, spaces, prefix.description );
            }

            string_input_popup()
            .title( _( "Search:" ) )
            .width( 85 )
            .description( description )
            .desc_color( c_light_gray )
            .edit( filterstring );
            redraw = true;
        } else if( action == "QUIT" ) {
            chosen = nullptr;
            done = true;
        } else if( action == "RESET_FILTER" ) {
            filterstring.clear();
            redraw = true;
        } else if( action == "CYCLE_BATCH" ) {
            if( current.empty() ) {
                popup( _( "Nothing selected!" ) );
                redraw = true;
                continue;
            }
            batch = !batch;
            if( batch ) {
                batch_line = line;
                chosen = current[batch_line];
            } else {
                line = batch_line;
                keepline = true;
            }
            redraw = true;
        } else if( action == "TOGGLE_FAVORITE" ) {
            keepline = true;
            redraw = true;
            if( current.empty() ) {
                popup( _( "Nothing selected!" ) );
                continue;
            }
            if( uistate.favorite_recipes.find( current[line]->ident() ) != uistate.favorite_recipes.end() ) {
                uistate.favorite_recipes.erase( current[line]->ident() );
            } else {
                uistate.favorite_recipes.insert( current[line]->ident() );
            }
        } else if( action == "HIDE_SHOW_RECIPE" ) {
            if( current.empty() ) {
                popup( _( "Nothing selected!" ) );
                redraw = true;
                continue;
            }
            if( show_hidden ) {
                uistate.hidden_recipes.erase( current[line]->ident() );
            } else {
                uistate.hidden_recipes.insert( current[line]->ident() );
            }

            redraw = true;
        } else if( action == "RELATED_RECIPES" ) {
            if( current.empty() ) {
                popup( _( "Nothing selected!" ) );
                redraw = true;
                continue;
            }
            std::string recipe_name = peek_related_recipe( current[ line ], available_recipes );
            if( recipe_name.empty() ) {
                keepline = true;
            } else {
                filterstring = recipe_name;
            }

            redraw = true;
        }
        if( line < 0 ) {
            line = current.size() - 1;
        } else if( line >= static_cast<int>( current.size() ) ) {
            line = 0;
        }
    } while( !done );

    return chosen;
}
コード例 #24
0
ファイル: ui.cpp プロジェクト: Euphe/Cataclysm-DDA
/*
 * Calculate sizes, populate arrays, initialize window
 */
void uimenu::setup() {
    bool w_auto = (w_width == -1 || w_width == -2 );
    bool w_autofold = ( w_width == -2);

    if ( w_auto ) {
        w_width = 4;
        if ( !title.empty() ) w_width = title.size() + 5;
    }

    bool h_auto = (w_height == -1);
    if ( h_auto ) {
        w_height = 4;
    }
    max_entry_len = 0;
    std::vector<int> autoassign;
    autoassign.clear();
    int pad = pad_left + pad_right + 2;
    for ( int i = 0; i < entries.size(); i++ ) {
        int txtwidth = utf8_width(entries[ i ].txt.c_str());
        if ( txtwidth > max_entry_len ) {
            max_entry_len = txtwidth;
        }
        if(entries[ i ].enabled) {
            if( entries[ i ].hotkey > 0 ) {
                keymap[ entries[ i ].hotkey ] = i;
            } else if ( entries[ i ].hotkey == -1 && i < 100 ) {
                autoassign.push_back(i);
            }
            if ( entries[ i ].retval == -1 ) {
                entries[ i ].retval = i;
            }
            if ( w_auto && w_width < txtwidth + pad + 4 ) {
                w_width = txtwidth + pad + 4;
            }
        } else {
            if ( w_auto && w_width < txtwidth + pad + 4 ) {
                w_width = txtwidth + pad + 4;    // todo: or +5 if header
            }
        }
        if ( entries[ i ].text_color == C_UNSET_MASK ) {
            entries[ i ].text_color = text_color;
        }
        fentries.push_back( i );
    }
    if ( !autoassign.empty() ) {
        int modifier = 0; //Increase this by one if assignment fails (the key is already used then).
        for ( int a = 0; a < autoassign.size(); ) {
            int setkey=-1;
            if ( (a + modifier) < 9 ) {
                setkey = (a + modifier) + 49; // 1-9;
            } else if ( (a + modifier) == 9 ) {
                setkey = (a + modifier) + 39; // 0;
            } else if ( (a + modifier) < 36 ) {
                setkey = (a + modifier) + 87; // a-z
            } else if ( (a + modifier) < 61 ) {
                setkey = (a + modifier) + 29; // A-Z
            }
            if ( setkey != -1 && keymap.count(setkey) <= 0 ) {
                int palloc = autoassign[ a ];
                entries[ palloc ].hotkey = setkey;
                keymap[ setkey ] = palloc;
                a++;
            } else {
                modifier++; //Keymap.count was not <= 0
            }
        }
    }

    if (w_auto && w_width > TERMX) {
        w_width = TERMX;
    }

    if(!text.empty() ) {
        int twidth = utf8_width(text.c_str());
        bool formattxt=true;
        int realtextwidth = 0;
        if ( textwidth == -1 ) {
            if ( w_autofold || !w_auto ) {
               realtextwidth = w_width - 4;
            } else {
               realtextwidth = twidth;
               if ( twidth + 4 > w_width ) {
                   if ( realtextwidth + 4 > TERMX ) {
                       realtextwidth = TERMX - 4;
                   }
                   textformatted = foldstring(text, realtextwidth);
                   formattxt=false;
                   realtextwidth = 10;
                   for ( int l=0; l < textformatted.size(); l++ ) {
                       if ( utf8_width(textformatted[l].c_str()) > realtextwidth ) {
                           realtextwidth = utf8_width(textformatted[l].c_str());
                       }
                   }
                   if ( realtextwidth + 4 > w_width ) {
                       w_width = realtextwidth + 4;
                   }
               }
            }
        } else if ( textwidth != -1 ) {
            realtextwidth = textwidth;
        }
        if ( formattxt == true ) {
            textformatted = foldstring(text, realtextwidth);
        }
    }

    if (h_auto) {
        w_height = 3 + textformatted.size() + entries.size();
    }

    if ( w_height > TERMY ) {
        w_height = TERMY;
    }

    vmax = entries.size();
    if ( vmax + 3 + textformatted.size() > w_height ) {
        vmax = w_height - 3 - textformatted.size();
        if ( vmax < 1 ) {
            if (textformatted.empty()) {
                popup("Can't display menu options, 0 %d available screen rows are occupied\nThis is probably a bug.\n",TERMY);
            } else {
                popup("Can't display menu options, %d %d available screen rows are occupied by\n'%s\n(snip)\n%s'\nThis is probably a bug.\n",
                    textformatted.size(), TERMY, textformatted[0].c_str(),
                      textformatted[ textformatted.size() - 1 ].c_str()
                );
            }
        }
    }

    if (w_x == -1) {
        w_x = int((TERMX - w_width) / 2);
    }
    if (w_y == -1) {
        w_y = int((TERMY - w_height) / 2);
    }

    if ( scrollbar_side == -1 ) {
        scrollbar_side = ( pad_left > 0 ? 1 : 0 );
    }
    if ( entries.size() <= vmax ) {
        scrollbar_auto = false;
    }
    window = newwin(w_height, w_width, w_y, w_x);

    werase(window);
    draw_border(window, border_color);
    if( !title.empty() ) {
        mvwprintz(window, 0, 1, border_color, "< ");
        wprintz(window, title_color, "%s", title.c_str() );
        wprintz(window, border_color, " >");
    }
    fselected = selected;
    started = true;
}
コード例 #25
0
static void check_equal( IterResult beg_res, IterResult end_res,
                         IterExpect beg_exp, IterExpect end_exp )
{
    CHECK( std::distance( beg_res, end_res ) == std::distance( beg_exp, end_exp ) );
    IterResult result = beg_res;
    IterExpect expect = beg_exp;
    for( ; result != end_res && expect != end_exp; ++result, ++expect ) {
        CHECK( *result == *expect );
    }
}

TEST_CASE( "fold-string" )
{
    SECTION( "Case 1 - test wrapping of lorem ipsum" ) {
        const auto folded = foldstring(
                                "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque a.",
                                17
                            );
        const auto expected = {
            /*
             0123456789abcdefg
            */
            "Lorem ipsum dolor",
            "sit amet, ",
            "consectetur ",
            "adipiscing elit. ",
            "Pellentesque a.",
        };
        check_equal( folded.begin(), folded.end(), expected.begin(), expected.end() );
    }

    SECTION( "Case 2 - test wrapping of Chinese" ) {
コード例 #26
0
ファイル: monster.cpp プロジェクト: Doffeh/Cataclysm-DDA
int monster::print_info(game *g, WINDOW* w, int vStart, int vLines, int column)
{
// First line of w is the border; the next two are terrain info, and after that
// is a blank line. w is 13 characters tall, and we can't use the last one
// because it's a border as well; so we have lines 4 through 11.
// w is also 48 characters wide - 2 characters for border = 46 characters for us
// vStart added because 'help' text in targeting win makes helpful info hard to find
// at a glance.

 const int vEnd = vStart + vLines;

 mvwprintz(w, vStart++, column, c_white, "%s ", type->name.c_str());
 switch (attitude(&(g->u))) {
  case MATT_FRIEND:
   wprintz(w, h_white, _("Friendly! "));
   break;
  case MATT_FLEE:
   wprintz(w, c_green, _("Fleeing! "));
   break;
  case MATT_IGNORE:
   wprintz(w, c_ltgray, _("Ignoring "));
   break;
  case MATT_FOLLOW:
   wprintz(w, c_yellow, _("Tracking "));
   break;
  case MATT_ATTACK:
   wprintz(w, c_red, _("Hostile! "));
   break;
  default:
   wprintz(w, h_red, "BUG: Behavior unnamed. (monster.cpp:print_info)");
   break;
 }
 if (has_effect(ME_DOWNED))
  wprintz(w, h_white, _("On ground"));
 else if (has_effect(ME_STUNNED))
  wprintz(w, h_white, _("Stunned"));
 else if (has_effect(ME_BEARTRAP))
  wprintz(w, h_white, _("Trapped"));
 std::string damage_info;
 nc_color col;
 if (hp >= type->hp) {
  damage_info = _("It is uninjured");
  col = c_green;
 } else if (hp >= type->hp * .8) {
  damage_info = _("It is lightly injured");
  col = c_ltgreen;
 } else if (hp >= type->hp * .6) {
  damage_info = _("It is moderately injured");
  col = c_yellow;
 } else if (hp >= type->hp * .3) {
  damage_info = _("It is heavily injured");
  col = c_yellow;
 } else if (hp >= type->hp * .1) {
  damage_info = _("It is severly injured");
  col = c_ltred;
 } else {
  damage_info = _("it is nearly dead");
  col = c_red;
 }
 mvwprintz(w, vStart++, column, col, damage_info.c_str());

    std::vector<std::string> lines = foldstring(type->description, getmaxx(w) - 1 - column);
    int numlines = lines.size();
    for (int i = 0; i < numlines && vStart <= vEnd; i++)
        mvwprintz(w, vStart++, column, c_white, lines[i].c_str());

    return vStart;
}
コード例 #27
0
void robot_finds_kitten::process_input(int input, WINDOW *w)
{
    timespec ts;
    ts.tv_sec = 1;
    ts.tv_nsec = 0;

    int check_x = robot.x;
    int check_y = robot.y;

    switch (input) {
    case KEY_UP: /* up */
        check_y--;
        break;
    case KEY_DOWN: /* down */
        check_y++;
        break;
    case KEY_LEFT: /* left */
        check_x--;
        break;
    case KEY_RIGHT: /* right */
        check_x++;
        break;
    case 0:
        break;
    default: { /* invalid command */
        for (int c = 0; c < rfkCOLS; c++) {
            mvwputch (w, 0, c, c_white, ' ');
            mvwputch (w, 1, c, c_white, ' ');
        }
        mvwprintz (w, 0, 0, c_white, _("Invalid command: Use direction keys or press 'q'."));
        return;
    }
    }

    if (check_y < 3 || check_y > rfkLINES - 1 || check_x < 0 || check_x > rfkCOLS - 1) {
        return;
    }

    if (rfkscreen[check_x][check_y] != EMPTY) {
        switch (rfkscreen[check_x][check_y]) {
        case ROBOT:
            /* We didn't move. */
            break;
        case KITTEN: {/* Found it! */
            for (int c = 0; c < rfkCOLS; c++) {
                mvwputch (w, 0, c, c_white, ' ');
            }

            /* The grand cinema scene. */
            for (int c = 0; c <= 3; c++) {

                wmove(w, 1, (rfkCOLS / 2) - 5 + c);
                wputch(w, c_white, ' ');
                wmove(w, 1, (rfkCOLS / 2) + 4 - c);
                wputch(w, c_white, ' ');
                wmove(w, 1, (rfkCOLS / 2) - 4 + c);
                if (input == KEY_LEFT || input == KEY_UP) {
                    draw_kitten(w);
                } else {
                    draw_robot(w);
                }
                wmove(w, 1, (rfkCOLS / 2) + 3 - c);
                if (input == KEY_LEFT || input == KEY_UP) {
                    draw_robot(w);
                } else {
                    draw_kitten(w);
                }
                wrefresh (w);
                nanosleep(&ts, NULL);
            }

            /* They're in love! */
            mvwprintz(w, 0, ((rfkCOLS - 6) / 2) - 1, c_ltred, "<3<3<3");
            wrefresh(w);
            nanosleep(&ts, NULL);
            for (int c = 0; c < rfkCOLS; c++) {
                mvwputch (w, 0, c, c_white, ' ');
                mvwputch (w, 1, c, c_white, ' ');
            }
            mvwprintz (w, 0, 0, c_white, _("You found kitten! Way to go, robot!"));
            wrefresh(w);
            ret = true;
            int ech = input;
            do {
                ech = getch ();
            } while ( ech == input );
        }
        break;

        default: {
            for (int c = 0; c < rfkCOLS; c++) {
                mvwputch (w, 0, c, c_white, ' ');
                mvwputch (w, 1, c, c_white, ' ');
            }
            std::vector<std::string> bogusvstr = foldstring( getmessage(
                    bogus_messages[rfkscreen[check_x][check_y] - 2]), rfkCOLS);
            for (size_t c = 0; c < bogusvstr.size(); c++) {
                mvwprintw (w, c, 0, "%s", bogusvstr[c].c_str());
            }
            wrefresh(w);
        }
        break;
        }
        wmove(w, 2, 0);
        return;
    }
    /* Otherwise, move the robot. */
    robot.x = check_x;
    robot.y = check_y;
}
コード例 #28
0
ファイル: veh_type.cpp プロジェクト: cellxiecao/Cataclysm-DDA
int vpart_info::format_description( std::ostringstream &msg, const std::string &format_color,
                                    int width ) const
{
    int lines = 1;
    msg << _( "<color_white>Description</color>\n" );
    msg << "> " << format_color;

    class::item base( item );
    std::ostringstream long_descrip;
    if( ! description.empty() ) {
        long_descrip << _( description.c_str() );
    }
    for( const auto &flagid : flags ) {
        if( flagid == "ALARMCLOCK" || flagid == "WATCH" ) {
            continue;
        }
        json_flag flag = json_flag::get( flagid );
        if( ! flag.info().empty() ) {
            if( ! long_descrip.str().empty() ) {
                long_descrip << "  ";
            }
            long_descrip << _( flag.info().c_str() );
        }
    }
    if( ( has_flag( "SEAT" ) || has_flag( "BED" ) ) && ! has_flag( "BELTABLE" ) ) {
        json_flag nobelt = json_flag::get( "NONBELTABLE" );
        long_descrip << "  " << _( nobelt.info().c_str() );
    }
    if( has_flag( "BOARDABLE" ) && has_flag( "OPENABLE" ) ) {
        json_flag nobelt = json_flag::get( "DOOR" );
        long_descrip << "  " << _( nobelt.info().c_str() );
    }
    if( has_flag( "TURRET" ) ) {
        long_descrip << string_format( _( "\nRange: %1$5d     Damage: %2$5.0f" ),
                                       base.gun_range( true ),
                                       base.gun_damage().total_damage() );
    }

    if( ! long_descrip.str().empty() ) {
        const auto wrap_descrip = foldstring( long_descrip.str(), width );
        msg << wrap_descrip[0];
        for( size_t i = 1; i < wrap_descrip.size(); i++ ) {
            msg << "\n  " << wrap_descrip[i];
        }
        msg << "</color>\n";
        lines += wrap_descrip.size();
    }

    // borrowed from item.cpp and adjusted
    const quality_id quality_jack( "JACK" );
    const quality_id quality_lift( "LIFT" );
    for( const auto &qual : qualities ) {
        msg << "> " << format_color << string_format( _( "Has level %1$d %2$s quality" ),
                qual.second, qual.first.obj().name.c_str() );
        if( qual.first == quality_jack || qual.first == quality_lift ) {
            msg << string_format( _( " and is rated at %1$d %2$s" ),
                                  static_cast<int>( convert_weight( qual.second * TOOL_LIFT_FACTOR ) ),
                                  weight_units() );
        }
        msg << ".</color>\n";
        lines += 1;
    }
    return lines;
}
コード例 #29
0
ファイル: wish.cpp プロジェクト: Madnus/Cataclysm-DDA
        virtual void select(int entnum, uimenu *menu) override
        {
            if ( ! started ) {
                started = true;
                padding = std::string(menu->pad_right - 1, ' ');
                for( auto &traits_iter : mutation_branch::get_all() ) {
                    vTraits.push_back( traits_iter.first );
                    pTraits[traits_iter.first] = ( p->has_trait( traits_iter.first ) );
                }
            }
            auto &mdata = mutation_branch::get( vTraits[entnum] );

            int startx = menu->w_width - menu->pad_right;
            for ( int i = 2; i < lastlen; i++ ) {
                mvwprintw(menu->window, i, startx, "%s", padding.c_str() );
            }

            mvwprintw(menu->window, 3, startx,
                      mdata.valid ? _("Valid") : _("Nonvalid"));
            int line2 = 4;

            if ( !mdata.prereqs.empty() ) {
                line2++;
                mvwprintz(menu->window, line2, startx, c_ltgray, _("Prereqs:"));
                for (auto &j : mdata.prereqs) {
                    mvwprintz(menu->window, line2, startx + 11, mcolor(j), "%s", mutation_branch::get_name( j ).c_str());
                    line2++;
                }
            }

            if ( !mdata.prereqs2.empty() ) {
                line2++;
                mvwprintz(menu->window, line2, startx, c_ltgray, _("Prereqs, 2d:"));
                for (auto &j : mdata.prereqs2) {
                    mvwprintz(menu->window, line2, startx + 15, mcolor(j), "%s", mutation_branch::get_name( j ).c_str());
                    line2++;
                }
            }

            if ( !mdata.threshreq.empty() ) {
                line2++;
                mvwprintz(menu->window, line2, startx, c_ltgray, _("Thresholds required:"));
                for (auto &j : mdata.threshreq) {
                    mvwprintz(menu->window, line2, startx + 21, mcolor(j), "%s", mutation_branch::get_name( j ).c_str());
                    line2++;
                }
            }

            if ( !mdata.cancels.empty() ) {
                line2++;
                mvwprintz(menu->window, line2, startx, c_ltgray, _("Cancels:"));
                for (auto &j : mdata.cancels) {
                    mvwprintz(menu->window, line2, startx + 11, mcolor(j), "%s", mutation_branch::get_name( j ).c_str());
                    line2++;
                }
            }

            if ( !mdata.replacements.empty() ) {
                line2++;
                mvwprintz(menu->window, line2, startx, c_ltgray, _("Becomes:"));
                for (auto &j : mdata.replacements) {
                    mvwprintz(menu->window, line2, startx + 11, mcolor(j), "%s", mutation_branch::get_name( j ).c_str());
                    line2++;
                }
            }

            if ( !mdata.additions.empty() ) {
                line2++;
                mvwprintz(menu->window, line2, startx, c_ltgray, _("Add-ons:"));
                for (auto &j : mdata.additions) {
                    mvwprintz(menu->window, line2, startx + 11, mcolor(j), "%s", mutation_branch::get_name( j ).c_str());
                    line2++;
                }
            }

            if ( !mdata.category.empty() ) {
                line2++;
                mvwprintz(menu->window, line2, startx, c_ltgray,  _("Category:"));
                for (auto &j : mdata.category) {
                    mvwprintw(menu->window, line2, startx + 11, "%s", j.c_str());
                    line2++;
                }
            }
            line2 += 2;

            mvwprintz(menu->window, line2, startx, c_ltgray, "pts: %d vis: %d ugly: %d",
                      mdata.points,
                      mdata.visibility,
                      mdata.ugliness
                     );
            line2 += 2;

            std::vector<std::string> desc = foldstring( mdata.description,
                                            menu->pad_right - 1 );
            for( auto &elem : desc ) {
                mvwprintz( menu->window, line2, startx, c_ltgray, "%s", elem.c_str() );
                line2++;
            }
            lastlen = line2 + 1;

            mvwprintz(menu->window, menu->w_height - 3, startx, c_green, "%s", msg.c_str());
            msg = padding;
            mvwprintw(menu->window, menu->w_height - 2, startx, _("[/] find, [q]uit"));

        };
コード例 #30
0
ファイル: ui.cpp プロジェクト: Anderviel/Cataclysm-DDA
void uimenu::setup() {
    bool w_auto = (w_width == -1 || w_width == -2 );
    bool w_autofold = ( w_width == -2);
    int realtextwidth = 0;

    if ( w_auto ) {
        w_width = 4;
        if ( title.size() > 0 ) w_width = title.size() + 5;
    }

    bool h_auto = (w_height == -1);
    if ( h_auto ) {
        w_height = 4;
    }

    std::vector<int> autoassign;
    autoassign.clear();
    int pad = pad_left + pad_right + 2;
    for ( int i = 0; i < entries.size(); i++ ) {
        int txtwidth = utf8_width(entries[ i ].txt.c_str());
        if(entries[ i ].enabled) {
            if( entries[ i ].hotkey > 0 ) {
                keymap[ entries[ i ].hotkey ] = i;
            } else if ( entries[ i ].hotkey == -1 && i < 100 ) {
                autoassign.push_back(i);
            }
            if ( entries[ i ].retval == -1 ) {
                entries[ i ].retval = i;
            }
            if ( w_auto && w_width < txtwidth + pad + 4 ) {
                w_width = txtwidth + pad + 4;
            }
        } else {
            if ( w_auto && w_width < txtwidth + pad + 4 ) {
                w_width = txtwidth + pad + 4;    // todo: or +5 if header
            }
        }
        if ( entries[ i ].text_color == C_UNSET_MASK ) {
            entries[ i ].text_color = text_color;
        }
    }
    if ( autoassign.size() > 0 ) {
        for ( int a = 0; a < autoassign.size(); a++ ) {
            int palloc = autoassign[ a ];
            int setkey=-1;
            if ( palloc < 9 ) {
                setkey = palloc + 49; // 1-9;
            } else if ( palloc == 9 ) {
                setkey = palloc + 39; // 0;
            } else if ( palloc < 36 ) {
                setkey = palloc + 87; // a-z
            } else if ( palloc < 61 ) {
                setkey = palloc + 29; // A-Z
            }
            if ( setkey != -1 && keymap.find(setkey) == keymap.end() ) {
                entries[ palloc ].hotkey = setkey;
                keymap[ setkey ] = palloc;
            }
        }
    }

    if (w_auto && w_width > TERMX) {
        w_width = TERMX;
    }

    if(text.size() > 0 ) {
        int twidth = utf8_width(text.c_str());
        bool formattxt=true;
        if ( textwidth == -1 ) {
            if ( w_autofold || !w_auto ) {
               realtextwidth = w_width - 4;
            } else {
               realtextwidth = twidth;
               if ( twidth + 4 > w_width ) {
                   if ( realtextwidth + 4 > TERMX ) {
                       realtextwidth = TERMX - 4;
                   }
                   textformatted = foldstring(text, realtextwidth);
                   formattxt=false;
                   realtextwidth = 10;
                   for ( int l=0; l < textformatted.size(); l++ ) {
                       if ( utf8_width(textformatted[l].c_str()) > realtextwidth ) {
                           realtextwidth = utf8_width(textformatted[l].c_str());
                       }
                   }
                   if ( realtextwidth + 4 > w_width ) {
                       w_width = realtextwidth + 4;
                   }
               }
            }
        } else if ( textwidth != -1 ) {
            realtextwidth = textwidth;
        }
        if ( formattxt == true ) {
            textformatted = foldstring(text, realtextwidth);
        }
    }

    if (h_auto) {
        w_height = 2 + textformatted.size() + entries.size();
    }

    vmax = entries.size();
    if ( w_height > TERMY ) {
        w_height = TERMY;
    }
    if ( vmax + 2 + textformatted.size() > w_height ) {
        vmax = w_height - 2 - textformatted.size();
        if ( vmax < 1 ) {
            popup("Can't display menu options, %d %d available screen rows are occupied by\n'%s\n(snip)\n%s'\nThis is probably a bug.\n",
               textformatted.size(),TERMY,textformatted[0].c_str(),textformatted[textformatted.size()-1].c_str()
            );
        }
    }

    if (w_x == -1) {
        w_x = int((TERMX - w_width) / 2);
    }
    if (w_y == -1) {
        w_y = int((TERMY - w_height) / 2);
    }

    window = newwin(w_height, w_width, w_y, w_x);
    werase(window);
    wattron(window, border_color);
    wborder(window, LINE_XOXO, LINE_XOXO, LINE_OXOX, LINE_OXOX,
            LINE_OXXO, LINE_OOXX, LINE_XXOO, LINE_XOOX );
    wattroff(window, border_color);
    if( title.size() > 0 ) {
        mvwprintz(window, 0, 1, border_color, "< ");
        wprintz(window, title_color, "%s", title.c_str() );
        wprintz(window, border_color, " >");
    }
    started = true;
}