bool list_items_match( const item *item, std::string sPattern )
{
    size_t iPos;
    bool hasExclude = false;

    if( sPattern.find( "-" ) != std::string::npos ) {
        hasExclude = true;
    }

    do {
        iPos = sPattern.find( "," );
        std::string pat = ( iPos == std::string::npos ) ? sPattern : sPattern.substr( 0, iPos );
        bool exclude = false;
        if( pat.substr( 0, 1 ) == "-" ) {
            exclude = true;
            pat = pat.substr( 1, pat.size() - 1 );
        } else if( hasExclude ) {
            hasExclude = false; //If there are non exclusive items to filter, we flip this back to false.
        }

        std::string namepat = pat;
        std::transform( namepat.begin(), namepat.end(), namepat.begin(), tolower );
        if( lcmatch( remove_color_tags( item->tname() ), namepat ) ) {
            return !exclude;
        }

        if( pat.find( "{", 0 ) != std::string::npos ) {
            std::string adv_pat_type = pat.substr( 1, pat.find( ":" ) - 1 );
            std::string adv_pat_search = pat.substr( pat.find( ":" ) + 1,
                                         ( pat.find( "}" ) - pat.find( ":" ) ) - 1 );
            std::transform( adv_pat_search.begin(), adv_pat_search.end(), adv_pat_search.begin(), tolower );
            if( adv_pat_type == "c" && lcmatch( item->get_category().name, adv_pat_search ) ) {
                return !exclude;
            } else if( adv_pat_type == "m" ) {
                for( auto material : item->made_of_types() ) {
                    if( lcmatch( material->name(), adv_pat_search ) ) {
                        return !exclude;
                    }
                }
            } else if( adv_pat_type == "dgt" && item->damage() > atoi( adv_pat_search.c_str() ) ) {
                return !exclude;
            } else if( adv_pat_type == "dlt" && item->damage() < atoi( adv_pat_search.c_str() ) ) {
                return !exclude;
            }
        }

        if( iPos != std::string::npos ) {
            sPattern = sPattern.substr( iPos + 1, sPattern.size() );
        }

    } while( iPos != std::string::npos );

    return hasExclude;
}
예제 #2
0
std::vector<std::string> input_context::filter_strings_by_phrase(
    const std::vector<std::string> &strings, const std::string &phrase ) const
{
    std::vector<std::string> filtered_strings;

    for( auto &str : strings ) {
        if( lcmatch( remove_color_tags( get_action_name( str ) ), phrase ) ) {
            filtered_strings.push_back( str );
        }
    }

    return filtered_strings;
}
예제 #3
0
std::vector<const recipe *> recipe_subset::search( const std::string &txt,
        const search_type key ) const
{
    std::vector<const recipe *> res;

    std::copy_if( recipes.begin(), recipes.end(), std::back_inserter( res ), [&]( const recipe * r ) {
        if( !*r ) {
            return false;
        }
        switch( key ) {
            case search_type::name:
                return lcmatch( r->result_name(), txt );

            case search_type::skill:
                return lcmatch( r->required_skills_string( nullptr ), txt ) ||
                       lcmatch( r->skill_used->name(), txt );

            case search_type::primary_skill:
                return lcmatch( r->skill_used->name(), txt );

            case search_type::component:
                return search_reqs( r->requirements().get_components(), txt );

            case search_type::tool:
                return search_reqs( r->requirements().get_tools(), txt );

            case search_type::quality:
                return search_reqs( r->requirements().get_qualities(), txt );

            case search_type::quality_result: {
                const auto &quals = item::find_type( r->result() )->qualities;
                return std::any_of( quals.begin(), quals.end(), [&]( const std::pair<quality_id, int> &e ) {
                    return lcmatch( e.first->name, txt );
                } );
            }

            case search_type::description_result: {
                const item result = r->create_result();
                return lcmatch( remove_color_tags( result.info( true ) ), txt );
            }

            default:
                return false;
        }
    } );

    return res;
}
예제 #4
0
    void add_msg_string(std::string &&msg, game_message_type const type) {
        if (msg.length() == 0) {
            return;
        }
        // hide messages if dead
        if (g->u.is_dead_state()) {
            return;
        }

        if (type == m_debug && !debug_mode) {
            return;
        }
        
        if (coalesce_messages(msg, type)) {
            return;
        }

        while (messages.size() > 255) {
            messages.pop_front();
        }

        messages.emplace_back(remove_color_tags(std::move(msg)), type);
    }
예제 #5
0
void Messages::dialog::do_filter( const std::string &filter_str )
{
    // Split the search string into type and text
    bool has_type_filter = false;
    game_message_type filter_type = m_neutral;
    std::string filter_text;
    const auto colon = filter_str.find( ':' );
    if( colon != std::string::npos ) {
        has_type_filter = msg_type_from_name( filter_type, filter_str.substr( 0, colon ) );
        filter_text = filter_str.substr( colon + 1 );
    } else {
        filter_text = filter_str;
    }

    // Start filtering the log
    folded_filtered.clear();
    for( size_t folded_ind = 0; folded_ind < folded_all.size(); ) {
        const size_t msg_ind = folded_all[folded_ind].first;
        const game_message &msg = player_messages.history( msg_ind );
        const bool match = ( !has_type_filter || filter_type == msg.type ) &&
                           ci_find_substr( remove_color_tags( msg.get_with_count() ), filter_text ) >= 0;

        // Always advance the index, but only add to filtered list if the original message matches
        for( ; folded_ind < folded_all.size() && folded_all[folded_ind].first == msg_ind; ++folded_ind ) {
            if( match ) {
                folded_filtered.emplace_back( folded_ind );
            }
        }
    }

    // Reset view
    if( log_from_top || max_lines > folded_filtered.size() ) {
        offset = 0;
    } else {
        offset = folded_filtered.size() - max_lines;
    }
}
예제 #6
0
bool Player::create_new_character()
{
  Window w_newch(0, 0, 80, 24);
  cuss::interface i_newch;
  if (!i_newch.load_from_file(CUSS_DIR + "/i_newchar_stats.cuss")) {
    return false;
  }

  New_char_screen cur_screen = NCS_STATS;

  Stat_selected cur_stat = STATSEL_STR;
  int* stat_value = &(stats.strength);

/* We need to set up a list of traits which does NOT include the placeholder / 
 * marker "traits" like TRAIT_MAX_GOOD and TRAIT_MAX_NEUTRAL etc.
 */
  std::vector<Trait_id> selectable_traits;
  for (int i = 1; i < TRAIT_MAX_BAD; i++) {
    if (i != TRAIT_MAX_GOOD && i != TRAIT_MAX_NEUTRAL) {
      selectable_traits.push_back( Trait_id(i) );
    }
  }

  std::vector<std::string> traits_list     = get_trait_list     (this);
  std::vector<std::string> profession_list = get_profession_list(this);

  name = "";

  int points = 4;
  int num_traits = 0;

  i_newch.ref_data("num_points", &points);

  i_newch.ref_data("num_strength",     &stats.strength);
  i_newch.ref_data("num_dexterity",    &stats.dexterity);
  i_newch.ref_data("num_perception",   &stats.perception);
  i_newch.ref_data("num_intelligence", &stats.intelligence);
  i_newch.set_data("text_description", get_stat_description(cur_stat));

  i_newch.set_data("text_strength",     "<c=ltblue>Strength<c=/>");
  i_newch.set_data("text_dexterity",    "<c=ltgray>Dexterity<c=/>");
  i_newch.set_data("text_perception",   "<c=ltgray>Perception<c=/>");
  i_newch.set_data("text_intelligence", "<c=ltgray>Intelligence<c=/>");

  bool done = false;

  while (!done) {  // We'll exit this function via keypresses, always
// Always set num_points!

    i_newch.draw(&w_newch);
    w_newch.refresh();

    long ch = getch();
    bool changed_screen = false;

    if (ch == '<') {
      cur_screen = New_char_screen( cur_screen - 1 );
      if (cur_screen == NCS_CANCEL) {
        if (query_yn("Cancel character creation?")) {
          return false;
        }
        cur_screen = NCS_STATS;
      } else {
        changed_screen = true;
      }
    } else if (ch == '>') {
      cur_screen = New_char_screen( cur_screen + 1 );
      if (cur_screen == NCS_DONE) {
        std::string reason_for_fail;
        if (points > 0) {
          reason_for_fail += "\nYou have unspent points!";
        }
        if (profession == NULL) {
          reason_for_fail += "\nYou didn't choose a profession!";
        }
        if (name.empty()) {
          reason_for_fail += "\nYour name is blank!";
        }
        if (!reason_for_fail.empty()) {
          popup("Wait, you can't start the game yet!%s",
                reason_for_fail.c_str());
        } else if (query_yn("Complete character and start the game?")) {
          done = true;
        }
        cur_screen = NCS_DESCRIPTION;
      } else {
        changed_screen = true;
      }
    } else {
// We should be doing this with cuss keybindings, but... that gets complex.
// Maybe one day I'll update cuss to be more friendly.
      switch (cur_screen) {

        case NCS_STATS: {
          bool changed_stat = false;
          switch (ch) {
            case '2':
            case 'j':
            case KEY_DOWN:
              if (cur_stat == STATSEL_INT) {
                cur_stat = STATSEL_STR;
              } else {
                cur_stat = Stat_selected( cur_stat + 1 );
              }
              changed_stat = true;
              break;

            case '8':
            case 'k':
            case KEY_UP:
              if (cur_stat == STATSEL_STR) {
                cur_stat = STATSEL_INT;
              } else {
                cur_stat = Stat_selected( cur_stat - 1 );
              }
              changed_stat = true;
              break;

            case '4':
            case 'h':
            case KEY_LEFT:
              if (*stat_value > 4) {
                if (*stat_value > 16) {
                  points++; // Stats above 16 cost 2 points, so get extra back
                }
                points++;
                (*stat_value)--;
              }
              break;

            case '6':
            case 'l':
            case KEY_RIGHT: {
              int point_req = (*stat_value >= 16 ? 2 : 1);
              if (*stat_value < 20 && points >= point_req) {
                points -= point_req;
                (*stat_value)++;
              }
            } break;
          } // switch (ch)

          if (changed_stat) { // Update stat_value
            i_newch.set_data("text_strength",    "<c=ltgray>Strength<c=/>");
            i_newch.set_data("text_dexterity",   "<c=ltgray>Dexterity<c=/>");
            i_newch.set_data("text_perception",  "<c=ltgray>Perception<c=/>");
            i_newch.set_data("text_intelligence","<c=ltgray>Intelligence<c=/>");

            i_newch.set_data("text_description",
                             get_stat_description(cur_stat));
            switch (cur_stat) {
              case STATSEL_STR:
                stat_value = &(stats.strength);
                i_newch.set_data("text_strength",
                                 "<c=ltblue>Strength<c=/>");
                break;
              case STATSEL_DEX:
                stat_value = &(stats.dexterity);
                i_newch.set_data("text_dexterity",
                                 "<c=ltblue>Dexterity<c=/>");
                break;
              case STATSEL_PER:
                stat_value = &(stats.perception);
                i_newch.set_data("text_perception",
                                 "<c=ltblue>Perception<c=/>");
                break;
              case STATSEL_INT:
                stat_value = &(stats.intelligence);
                i_newch.set_data("text_intelligence",
                                 "<c=ltblue>Intelligence<c=/>");
                break;
            }
          }
        } break;

        case NCS_TRAITS: {
          switch (ch) {
            case '2':
            case 'j':
            case KEY_DOWN:
            {
              i_newch.add_data("list_traits", 1);
              int sel = i_newch.get_int("list_traits");
              Trait_id cur_trait = selectable_traits[sel];
              i_newch.set_data("num_cost", abs(trait_cost(cur_trait)));
              if (trait_cost(cur_trait) >= 0) {
                i_newch.set_data("text_cost", "<c=yellow>Cost:<c=/>");
              } else {
                i_newch.set_data("text_cost", "<c=yellow>Earns:<c=/>");
              }
              if (trait_cost(cur_trait) > points) {
                i_newch.set_data("num_cost", c_red);
              } else {
                i_newch.set_data("num_cost", c_white);
              }
              i_newch.set_data("text_description",
                               trait_description(cur_trait));
            } break;

            case '8':
            case 'k':
            case KEY_UP:
            {
              i_newch.add_data("list_traits", -1);
              int sel = i_newch.get_int("list_traits");
              Trait_id cur_trait = selectable_traits[sel];
              i_newch.set_data("num_cost", abs(trait_cost(cur_trait)));
              if (trait_cost(cur_trait) >= 0) {
                i_newch.set_data("text_cost", "<c=yellow>Cost:<c=/>");
              } else {
                i_newch.set_data("text_cost", "<c=yellow>Earns:<c=/>");
              }
              if (trait_cost(cur_trait) > points) {
                i_newch.set_data("num_cost", c_red);
              } else {
                i_newch.set_data("num_cost", c_white);
              }
              i_newch.set_data("text_description",
                               trait_description(cur_trait));
            } break;

            case '\n':
            case ' ':
            {
              int sel = i_newch.get_int("list_traits");
              Trait_id cur_trait = selectable_traits[sel];
              if (has_trait(cur_trait)) {
                traits[cur_trait] = false;
                points += trait_cost(cur_trait);
                num_traits--;
                traits_list = get_trait_list(this);
              } else if (points >= trait_cost(cur_trait) && num_traits < 5){
                traits[cur_trait] = true;
                points -= trait_cost(cur_trait);
                num_traits++;
                traits_list = get_trait_list(this);
              }
              i_newch.set_data("num_traits_left", 5 - num_traits);
              if (num_traits >= 5) {
                i_newch.set_data("num_traits_left", c_red);
              }
            } break;

          } // switch (ch)
        } break;

        case NCS_PROFESSION: {
          switch (ch) {
            case '2':
            case 'j':
            case KEY_DOWN:
            {
              i_newch.add_data("list_professions", 1);
              std::string prof_name = i_newch.get_str("list_professions");
              prof_name = remove_color_tags(prof_name);
              Profession* cur_prof = PROFESSIONS.lookup_name(prof_name);
              if (!cur_prof) {
                debugmsg("No such profession as '%s'!", prof_name.c_str());
                return false;
              }
              i_newch.set_data("text_description", cur_prof->description);
            } break;

            case '8':
            case 'k':
            case KEY_UP:
            {
              i_newch.add_data("list_professions", -1);
              std::string prof_name = i_newch.get_str("list_professions");
              prof_name = remove_color_tags(prof_name);
              Profession* cur_prof = PROFESSIONS.lookup_name(prof_name);
              if (!cur_prof) {
                debugmsg("No such profession as '%s'!", prof_name.c_str());
                return false;
              }
              i_newch.set_data("text_description", cur_prof->description);
            } break;

            case '\n':
            case ' ':
            {
              std::string prof_name = i_newch.get_str("list_professions");
              prof_name = remove_color_tags(prof_name);
              Profession* cur_prof = PROFESSIONS.lookup_name(prof_name);
              if (!cur_prof) {
                debugmsg("No such profession as '%s'!", prof_name.c_str());
                return false;
              }
              set_profession(cur_prof);
              profession_list = get_profession_list(this);
            } break;

          } // switch (ch)
        } break;

        case NCS_DESCRIPTION: {
          if (ch == '/') {
            male = !male;
            if (male) {
              i_newch.set_data("text_male",   "<c=yellow>Male<c=/>");
              i_newch.set_data("text_female", "<c=dkgray>Female<c=/>");
            } else {
              i_newch.set_data("text_male",   "<c=dkgray>Male<c=/>");
              i_newch.set_data("text_female", "<c=yellow>Female<c=/>");
            }
          } else {
/* Let the interface handle name entry; this includes cursor movement,
 * backspace, etc.  The only downside is that this allows entry of "invalid"
 * name characters like "'&^%$#@ etc.  Bad?
 */
            cuss::element* entry = i_newch.find_by_name("entry_name");
            entry->handle_keypress(ch);
          }
            
        } break;

      } // switch (cur_screen)
    } // key pressed isn't '<' or '>'

    if (changed_screen) {
      std::string filename = CUSS_DIR + "/i_newchar_";
      switch (cur_screen) {
        case NCS_STATS:       filename += "stats.cuss";       break;
        case NCS_TRAITS:      filename += "traits.cuss";      break;
        case NCS_PROFESSION:  filename += "profession.cuss";  break;
        case NCS_DESCRIPTION: filename += "description.cuss"; break;
      }
      if (!i_newch.load_from_file(filename)) {
        return false;
      }

      i_newch.ref_data("num_points", &points);

      switch (cur_screen) {

        case NCS_STATS:
          cur_stat = STATSEL_STR;
          i_newch.set_data("text_strength",     "<c=ltblue>Strength<c=/>");
          i_newch.set_data("text_dexterity",    "<c=ltgray>Dexterity<c=/>");
          i_newch.set_data("text_perception",   "<c=ltgray>Perception<c=/>");
          i_newch.set_data("text_intelligence", "<c=ltgray>Intelligence<c=/>");
          i_newch.ref_data("num_strength",     &stats.strength);
          i_newch.ref_data("num_dexterity",    &stats.dexterity);
          i_newch.ref_data("num_perception",   &stats.perception);
          i_newch.ref_data("num_intelligence", &stats.intelligence);
          i_newch.set_data("text_description", get_stat_description(cur_stat));
          break;

        case NCS_TRAITS: {
          i_newch.select("list_traits");
          i_newch.ref_data("list_traits", &traits_list);
          int sel = i_newch.get_int("list_traits");
          Trait_id cur_trait = selectable_traits[sel];
          i_newch.set_data("text_description", trait_description(cur_trait));
          i_newch.set_data("num_cost", abs(trait_cost(cur_trait)));
          if (trait_cost(cur_trait) >= 0) {
            i_newch.set_data("text_cost", "<c=yellow>Cost:<c=/>");
          } else {
            i_newch.set_data("text_cost", "<c=yellow>Earns:<c=/>");
          }
          if (trait_cost(cur_trait) > points) {
            i_newch.set_data("num_cost", c_red);
          } else {
            i_newch.set_data("num_cost", c_white);
          }
          i_newch.set_data("num_traits_left", 5 - num_traits);
          if (num_traits >= 5) {
            i_newch.set_data("num_traits_left", c_red);
          }
        } break;

        case NCS_PROFESSION: {
          i_newch.select("list_professions");
          i_newch.ref_data("list_professions", &profession_list);
          std::string prof_name = i_newch.get_str("list_professions");
          prof_name = remove_color_tags(prof_name);
          Profession* cur_prof = PROFESSIONS.lookup_name(prof_name);
          if (!cur_prof) {
            debugmsg("No such profession as '%s'!", prof_name.c_str());
            return false;
          }
          i_newch.set_data("text_description", cur_prof->description);
        } break;

        case NCS_DESCRIPTION:
          i_newch.ref_data("entry_name", &name);
          if (male) {
            i_newch.set_data("text_male",   "<c=yellow>Male<c=/>");
            i_newch.set_data("text_female", "<c=dkgray>Female<c=/>");
          } else {
            i_newch.set_data("text_male",   "<c=dkgray>Male<c=/>");
            i_newch.set_data("text_female", "<c=yellow>Female<c=/>");
          }
          break;
      } // switch (cur_screen)
    } // if (changed_screen)
  }

// Now set up our skills and equipment based on our profession
  if (!profession) {
    debugmsg("Character creation finished without a profession!");
    return false;
  }
  std::vector<Item_type_chance> prof_items = profession->items.item_types;
  for (int i = 0; i < prof_items.size(); i++) {
    int count = prof_items[i].number;
    Item tmp_it(prof_items[i].item);
    for (int i = 0; i < count; i++) {
      if (tmp_it.get_item_class() == ITEM_CLASS_CLOTHING) {
        items_worn.push_back(tmp_it);
      } else {
        inventory.push_back(tmp_it);
      }
    }
  }

  skills = profession->skills;

// The "Durable" trait needs to be set up here.
  if (has_trait(TRAIT_DURABLE)) {
    for (int i = 0; i < HP_PART_MAX; i++) {
      current_hp[i] = 115;
      max_hp[i] = 115;
    }
  }

// Myopic characters get free glasses
  if (has_trait(TRAIT_MYOPIC)) {
    Item_type* glasses = ITEM_TYPES.lookup_name("glasses");
    if (!glasses) {
      debugmsg("No item 'glasses' exists - required for the Myopic trait!");
      return false;
    }
    Item tmp_it(glasses);
    items_worn.push_back(tmp_it);
  }

  return true;
}
예제 #7
0
/**
 * Generate and refresh output
 */
void uimenu::show()
{
    if (!started) {
        setup();
    }

    werase(window);
    draw_border(window, border_color);
    if( !title.empty() ) {
        mvwprintz(window, 0, 1, border_color, "< ");
        wprintz( window, title_color, title );
        wprintz(window, border_color, " >");
    }

    std::string padspaces = std::string(w_width - 2 - pad_left - pad_right, ' ');
    const int text_lines = textformatted.size();
    int estart = 1;
    if( !textformatted.empty() ) {
        for ( int i = 0; i < text_lines; i++ ) {
            trim_and_print( window, 1 + i, 2, getmaxx( window ) - 4, text_color, textformatted[i] );
        }

        mvwputch(window, text_lines + 1, 0, border_color, LINE_XXXO);
        for ( int i = 1; i < w_width - 1; ++i) {
            mvwputch(window, text_lines + 1, i, border_color, LINE_OXOX);
        }
        mvwputch(window, text_lines + 1, w_width - 1, border_color, LINE_XOXX);
        estart += text_lines + 1; // +1 for the horizontal line.
    }

    calcStartPos( vshift, fselected, vmax, fentries.size() );

    for ( int fei = vshift, si = 0; si < vmax; fei++, si++ ) {
        if ( fei < (int)fentries.size() ) {
            int ei = fentries [ fei ];
            nc_color co = ( ei == selected ?
                            hilight_color :
                            ( entries[ ei ].enabled || entries[ei].force_color ?
                              entries[ ei ].text_color :
                              disabled_color )
                          );

            if ( hilight_full ) {
                mvwprintz( window, estart + si, pad_left + 1, co, padspaces );
            }
            if( entries[ ei ].hotkey >= 33 && entries[ ei ].hotkey < 126 ) {
                const nc_color hotkey_co = ei == selected ? hilight_color : hotkey_color;
                mvwprintz( window, estart + si, pad_left + 2, entries[ ei ].enabled ? hotkey_co : co,
                           "%c", entries[ ei ].hotkey );
            }
            if( padspaces.size() > 3 ) {
                // padspaces's length indicates the maximal width of the entry, it is used above to
                // activate the highlighting, it is used to override previous text there, but in both
                // cases printing starts at pad_left+1, here it starts at pad_left+4, so 3 cells less
                // to be used.
                const auto entry = utf8_wrapper( ei == selected ? remove_color_tags( entries[ ei ].txt ) : entries[ ei ].txt );
                trim_and_print( window, estart + si, pad_left + 4,
                                max_entry_len, co, "%s", entry.c_str() );

                if( max_column_len && !entries[ ei ].ctxt.empty() ) {
                    const auto centry = utf8_wrapper( ei == selected ? remove_color_tags( entries[ ei ].ctxt ) : entries[ ei ].ctxt );
                    trim_and_print( window, estart + si, getmaxx( window ) - max_column_len - 2,
                                    max_column_len, co, "%s", centry.c_str() );
                }
            }
            mvwzstr menu_entry_extra_text = entries[ei].extratxt;
            if ( !menu_entry_extra_text.txt.empty() ) {
                mvwprintz( window, estart + si, pad_left + 1 + menu_entry_extra_text.left,
                           menu_entry_extra_text.color, menu_entry_extra_text.txt );
            }
            if ( menu_entry_extra_text.sym != 0 ) {
                mvwputch ( window, estart + si, pad_left + 1 + menu_entry_extra_text.left,
                           menu_entry_extra_text.color, menu_entry_extra_text.sym );
            }
            if ( callback != NULL && ei == selected ) {
                callback->select(ei, this);
            }
        } else {
            mvwprintz( window, estart + si, pad_left + 1, c_light_gray, padspaces );
        }
    }

    if ( desc_enabled ) {
        // draw border
        mvwputch(window, w_height - desc_lines - 2, 0, border_color, LINE_XXXO);
        for ( int i = 1; i < w_width - 1; ++i) {
            mvwputch(window, w_height - desc_lines - 2, i, border_color, LINE_OXOX);
        }
        mvwputch(window, w_height - desc_lines - 2, w_width - 1, border_color, LINE_XOXX);

        // clear previous desc the ugly way
        for ( int y = desc_lines + 1; y > 1; --y ) {
            for ( int x = 2; x < w_width - 2; ++x) {
                mvwputch(window, w_height - y, x, text_color, " ");
            }
        }

        if( static_cast<size_t>( selected ) < entries.size() ){
            fold_and_print( window, w_height - desc_lines - 1, 2, w_width - 4, text_color,
                            entries[selected].desc );
        }
    }

    if ( !filter.empty() ) {
        mvwprintz( window, w_height - 1, 2, border_color, "< %s >", filter.c_str() );
        mvwprintz( window, w_height - 1, 4, text_color, filter );
    }
    apply_scrollbar();

    this->refresh(true);
}
예제 #8
0
/**
 * Calculate sizes, populate arrays, initialize window
 */
void uimenu::setup()
{
    bool w_auto = (w_width == -1 || w_width == -2 );
    bool w_autofold = ( w_width == -2);

    // Space for a line between text and entries. Only needed if there is actually text.
    const int text_separator_line = text.empty() ? 0 : 1;
    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;
    }

    if ( desc_enabled && !(w_auto && h_auto) ) {
        desc_enabled = false; // give up
        debugmsg( "desc_enabled without w_auto and h_auto (h: %d, w: %d)", static_cast<int>( h_auto ), static_cast<int>( w_auto ) );
    }

    max_entry_len = 0;
    max_column_len = 0;
    std::vector<int> autoassign;
    int pad = pad_left + pad_right + 2;
    int descwidth_final = 0; // for description width guard
    for ( size_t i = 0; i < entries.size(); i++ ) {
        int txtwidth = utf8_width( remove_color_tags(entries[i].txt) );
        int ctxtwidth = utf8_width( remove_color_tags(entries[i].ctxt) );
        if ( txtwidth > max_entry_len ) {
            max_entry_len = txtwidth;
        }
        if ( ctxtwidth > max_column_len ) {
            max_column_len = ctxtwidth;
        }
        int clen = (ctxtwidth > 0) ? ctxtwidth + 2: 0;
        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 + clen ) {
                w_width = txtwidth + pad + 4 + clen;
            }
        } else {
            if ( w_auto && w_width < txtwidth + pad + 4 + clen ) {
                w_width = txtwidth + pad + 4 + clen;    // @todo: or +5 if header
            }
        }
        if ( desc_enabled ) {
            const int min_width = std::min( TERMX, std::max( w_width, descwidth_final ) ) - 4;
            const int max_width = TERMX - 4;
            int descwidth = find_minimum_fold_width( entries[i].desc, desc_lines,
                                                     min_width, max_width );
            descwidth += 4; // 2x border + 2x ' ' pad
            if ( descwidth_final < descwidth ) {
                descwidth_final = descwidth;
            }
        }
        if ( entries[ i ].text_color == c_red_red ) {
            entries[ i ].text_color = text_color;
        }
        fentries.push_back( i );
    }
    size_t next_free_hotkey = 0;
    for( auto it = autoassign.begin(); it != autoassign.end() &&
         next_free_hotkey < hotkeys.size(); ++it ) {
        while( next_free_hotkey < hotkeys.size() ) {
            const int setkey = hotkeys[next_free_hotkey];
            next_free_hotkey++;
            if( keymap.count( setkey ) == 0 ) {
                entries[*it].hotkey = setkey;
                keymap[setkey] = *it;
                break;
            }
        }
    }

    if (desc_enabled) {
        if (descwidth_final > TERMX) {
            desc_enabled = false; // give up
            debugmsg("description would exceed terminal width (%d vs %d available)", descwidth_final, TERMX);
        } else if (descwidth_final > w_width) {
            w_width = descwidth_final;
        }

    }

    if(!text.empty() ) {
        int twidth = utf8_width( remove_color_tags(text) );
        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 (auto &l : textformatted) {
                        const int w = utf8_width( remove_color_tags( l ) );
                        if ( w > realtextwidth ) {
                            realtextwidth = w;
                        }
                    }
                    if ( realtextwidth + 4 > w_width ) {
                        w_width = realtextwidth + 4;
                    }
                }
            }
        } else if ( textwidth != -1 ) {
            realtextwidth = textwidth;
            if( realtextwidth + 4 > w_width ) {
                w_width = realtextwidth + 4;
            }
        }
        if ( formattxt ) {
            textformatted = foldstring(text, realtextwidth);
        }
    }

    // shrink-to-fit
    if( desc_enabled ) {
        desc_lines = 0;
        for( const uimenu_entry &ent : entries ) {
            // -2 for borders, -2 for padding
            desc_lines = std::max<int>( desc_lines, foldstring( ent.desc, w_width - 4 ).size() );
        }
        if( desc_lines <= 0 ) {
            desc_enabled = false;
        }
    }

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

    vmax = entries.size();
    int additional_lines = 2 + text_separator_line + // add two for top & bottom borders
                           static_cast<int>( textformatted.size() );
    if( desc_enabled ) {
        additional_lines += desc_lines + 1; // add one for description separator line
    }

    if (h_auto) {
        w_height = vmax + additional_lines;
    }

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

    if( vmax + additional_lines > w_height ) {
        vmax = w_height - additional_lines;
        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, %lu %d available screen rows are occupied by\n'%s\n(snip)\n%s'\nThis is probably a bug.\n",
                       static_cast<unsigned long>( 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 ( (int)entries.size() <= vmax ) {
        scrollbar_auto = false;
    }
    window = catacurses::newwin( w_height, w_width, w_y, w_x );

    fselected = selected;
    if(fselected < 0) {
        fselected = selected = 0;
    } else if(fselected >= static_cast<int>(entries.size())) {
        fselected = selected = static_cast<int>(entries.size()) - 1;
    }
    if(!entries.empty() && !entries[fselected].enabled) {
        for(size_t i = 0; i < entries.size(); ++i) {
            if(entries[i].enabled) {
                fselected = selected = i;
                break;
            }
        }
    }
    started = true;
}
예제 #9
0
int tagless_length(const std::string &orig)
{
  std::string tagless = remove_color_tags(orig);
  return tagless.length();
}
예제 #10
0
void string_input_popup::create_window()
{
    nc_color title_color = c_light_red;
    nc_color desc_color = c_green;

    int titlesize = utf8_width( _title ); // Occupied horizontal space
    if( _max_length <= 0 ) {
        _max_length = _width;
    }
    // 2 for border (top and bottom) and 1 for the input text line.
    int w_height = 2 + 1;

    // |"w_width = width + titlesize (this text) + 5": _____  |
    int w_width = FULL_SCREEN_WIDTH;
    if( _width <= 0 ) {
        _width = std::max( 5, FULL_SCREEN_WIDTH - titlesize - 5 ); // Default if unspecified
    } else {
        _width = std::min( FULL_SCREEN_WIDTH - 20, _width );
        w_width = _width + titlesize + 5;
    }

    std::vector<std::string> title_split = { _title };
    if( w_width > FULL_SCREEN_WIDTH ) {
        // Out of horizontal space- wrap the title
        titlesize = FULL_SCREEN_WIDTH - _width - 5;
        w_width = FULL_SCREEN_WIDTH;

        for( int wraplen = w_width - 2; wraplen >= titlesize; wraplen-- ) {
            title_split = foldstring( _title, wraplen );
            if( int( title_split.back().size() ) <= titlesize ) {
                break;
            }
        }
        w_height += int( title_split.size() ) - 1;
    }

    std::vector<std::string> descformatted;
    if( !_description.empty() ) {
        const int twidth = std::min( utf8_width( remove_color_tags( _description ) ), w_width - 4 );
        descformatted = foldstring( _description, twidth );
        w_height += descformatted.size();
    }
    // length of title + border (left) + space
    _startx = titlesize + 2;
    // Below the description and below the top border
    _starty = 1 + descformatted.size();

    if( _max_length <= 0 ) {
        _max_length = 1024;
    }
    _endx = w_width - 3;
    _position = -1;

    const int w_y = ( TERMY - w_height ) / 2;
    const int w_x = std::max( ( TERMX - w_width ) / 2, 0 );
    w = catacurses::newwin( w_height, w_width, w_y, w_x );

    draw_border( w );

    for( size_t i = 0; i < descformatted.size(); ++i ) {
        trim_and_print( w, 1 + i, 1, w_width - 2, desc_color, descformatted[i] );
    }
    for( int i = 0; i < int( title_split.size() ) - 1; i++ ) {
        mvwprintz( w, _starty++, i + 1, title_color, title_split[i] );
    }
    right_print( w, _starty, w_width - titlesize - 1, title_color, title_split.back() );
    _starty = w_height - 2; // The ____ looks better at the bottom right when the title folds
}
예제 #11
0
void Messages::display_messages( const catacurses::window &ipk_target, const int left,
                                 const int top, const int right, const int bottom )
{
    if( !size() ) {
        return;
    }

    const int maxlength = right - left;
    int line = log_from_top ? top : bottom;

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

            const game_message &m = player_messages.messages[i];
            if( message_exceeds_ttl( m ) ) {
                break;
            }

            const nc_color col = m.get_color( player_messages.curmes );
            std::string message_text = m.get_with_count();
            if( !m.is_recent( player_messages.curmes ) ) {
                message_text = remove_color_tags( message_text );
            }

            for( const std::string &folded : foldstring( message_text, maxlength ) ) {
                if( line > bottom ) {
                    break;
                }
                // Redrawing line to ensure new messages similar to previous
                // messages will not be missed by screen readers
                wredrawln( ipk_target, line, 1 );
                nc_color col_out = col;
                print_colored_text( ipk_target, line++, left, col_out, col, folded );
            }
        }
    } else {
        for( int i = size() - 1; i >= 0; --i ) {
            if( line < top ) {
                break;
            }

            const game_message &m = player_messages.messages[i];
            if( message_exceeds_ttl( m ) ) {
                break;
            }

            const nc_color col = m.get_color( player_messages.curmes );
            std::string message_text = m.get_with_count();
            if( !m.is_recent( player_messages.curmes ) ) {
                message_text = remove_color_tags( message_text );
            }

            const auto folded_strings = foldstring( message_text, maxlength );
            const auto folded_rend = folded_strings.rend();
            for( auto string_iter = folded_strings.rbegin();
                 string_iter != folded_rend && line >= top; ++string_iter, line-- ) {
                // Redrawing line to ensure new messages similar to previous
                // messages will not be missed by screen readers
                wredrawln( ipk_target, line, 1 );
                nc_color col_out = col;
                print_colored_text( ipk_target, line, left, col_out, col, *string_iter );
            }
        }
    }

    player_messages.curmes = calendar::turn;
}
예제 #12
0
/*
 * 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;
    }

    if ( desc_enabled && !(w_auto && h_auto) ) {
        desc_enabled = false; // give up
        debugmsg("desc_enabled without w_auto and h_auto (h: %d, w: %d)", h_auto, w_auto);
    }

    max_entry_len = 0;
    max_desc_len = 0;
    std::vector<int> autoassign;
    int pad = pad_left + pad_right + 2;
    int descwidth_final = 0; // for description width guard
    for ( size_t i = 0; i < entries.size(); i++ ) {
        int txtwidth = utf8_width(remove_color_tags( 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 ( desc_enabled ) {
            // subtract one from desc_lines for the reminder of the text
            int descwidth = utf8_width(entries[i].desc.c_str()) / (desc_lines - 1);
            descwidth += 4; // 2x border + 2x ' ' pad
            if ( descwidth_final < descwidth ) {
                descwidth_final = descwidth;
            }
        }
        if ( entries[ i ].text_color == c_red_red ) {
            entries[ i ].text_color = text_color;
        }
        fentries.push_back( i );
    }
    size_t next_free_hotkey = 0;
    for( auto it = autoassign.begin(); it != autoassign.end() &&
            next_free_hotkey < hotkeys.size(); ++it ) {
        while( next_free_hotkey < hotkeys.size() ) {
            const int setkey = hotkeys[next_free_hotkey];
            next_free_hotkey++;
            if( keymap.count( setkey ) == 0 ) {
                entries[*it].hotkey = setkey;
                keymap[setkey] = *it;
                break;
            }
        }
    }

    if (desc_enabled) {
        if (descwidth_final > TERMX) {
            desc_enabled = false; // give up
            debugmsg("description would exceed terminal width (%d vs %d available)", descwidth_final, TERMX);
        } else if (descwidth_final > w_width) {
            w_width = descwidth_final;
        }
    }

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

    if(!text.empty() ) {
        int twidth = utf8_width(remove_color_tags( 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 (auto &l : textformatted) {
                        if ( utf8_width(l.c_str()) > realtextwidth ) {
                            realtextwidth = utf8_width(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 (desc_enabled) {
            int w_height_final = w_height + desc_lines + 1; // add one for border
            if (w_height_final > TERMY) {
                desc_enabled = false; // give up
                debugmsg("with description height would exceed terminal height (%d vs %d available)",
                         w_height_final, TERMY);
            } else {
                w_height = w_height_final;
            }
        }
    }

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

    vmax = entries.size();
    if ( vmax + 3 + (int)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 ( (int)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;
    if(fselected < 0) {
        fselected = selected = 0;
    } else if(fselected >= static_cast<int>(entries.size())) {
        fselected = selected = static_cast<int>(entries.size()) - 1;
    }
    if(!entries.empty() && !entries[fselected].enabled) {
        for(size_t i = 0; i < entries.size(); ++i) {
            if(entries[i].enabled) {
                fselected = selected = i;
                break;
            }
        }
    }
    started = true;
}