Skip to content

Commit

Permalink
Fix the alignment of many unicode strings (#34886)
Browse files Browse the repository at this point in the history
* Fix alignment of unicode strings

* Update itemname_test.cpp
  • Loading branch information
Qrox authored and ZhilkinSerg committed Oct 21, 2019
1 parent 58d5940 commit 0490a5a
Show file tree
Hide file tree
Showing 38 changed files with 277 additions and 224 deletions.
8 changes: 2 additions & 6 deletions src/action.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -906,9 +906,7 @@ action_id handle_action_menu()

int width = 0;
for( auto &cur_entry : entries ) {
if( width < static_cast<int>( cur_entry.txt.length() ) ) {
width = cur_entry.txt.length();
}
width = std::max( width, utf8_width( cur_entry.txt ) );
}
//border=2, selectors=3, after=3 for balance.
width += 2 + 3 + 3;
Expand Down Expand Up @@ -964,9 +962,7 @@ action_id handle_main_menu()

int width = 0;
for( auto &entry : entries ) {
if( width < static_cast<int>( entry.txt.length() ) ) {
width = entry.txt.length();
}
width = std::max( width, utf8_width( entry.txt ) );
}
//border=2, selectors=3, after=3 for balance.
width += 2 + 3 + 3;
Expand Down
6 changes: 3 additions & 3 deletions src/advanced_inv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ void advanced_inventory::print_items( advanced_inventory_pane &pane, bool active
volume_carried,
volume_capacity,
volume_units_abbr() );
const int hrightcol = columns - 1 - formatted_head.length();
const int hrightcol = columns - 1 - utf8_width( formatted_head );
nc_color color = weight_carried > weight_capacity ? c_red : c_light_green;
mvwprintz( window, point( hrightcol, 4 ), color, "%.1f", weight_carried );
wprintz( window, c_light_gray, "/%.1f %s ", weight_capacity, weight_units() );
Expand Down Expand Up @@ -295,7 +295,7 @@ void advanced_inventory::print_items( advanced_inventory_pane &pane, bool active
format_volume( maxvolume ),
volume_units_abbr() );
}
mvwprintz( window, point( columns - 1 - formatted_head.length(), 4 ), norm, formatted_head );
mvwprintz( window, point( columns - 1 - utf8_width( formatted_head ), 4 ), norm, formatted_head );
}

//print header row and determine max item name length
Expand Down Expand Up @@ -769,7 +769,7 @@ void advanced_inv_area::init()
}

// remove leading space
if( flags.length() && flags[0] == ' ' ) {
if( !flags.empty() && flags[0] == ' ' ) {
flags.erase( 0, 1 );
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/avatar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -457,7 +457,7 @@ bool avatar::read( int inventory_position, const bool continuous )

// Some helpers to reduce repetition:
auto length = []( const std::pair<npc *, std::string> &elem ) {
return elem.first->disp_name().size() + elem.second.size();
return utf8_width( elem.first->disp_name() ) + utf8_width( elem.second );
};

auto max_length = [&length]( const std::map<npc *, std::string> &m ) {
Expand All @@ -474,7 +474,7 @@ bool avatar::read( int inventory_position, const bool continuous )
const int lvl = elem.first->get_skill_level( skill );
const std::string lvl_text = skill ? string_format( _( " | current level: %d" ), lvl ) : "";
const std::string name_text = elem.first->disp_name() + elem.second;
return string_format( "%-*s%s", static_cast<int>( max_length( m ) ), name_text, lvl_text );
return string_format( "%s%s", left_justify( name_text, max_length( m ) ), lvl_text );
};

auto add_header = [&menu]( const std::string & str ) {
Expand Down
2 changes: 1 addition & 1 deletion src/cata_tiles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3240,7 +3240,7 @@ void cata_tiles::draw_sct_frame( std::multimap<point, formatted_text> &overlay_s
for( auto iter = SCT.vSCT.begin(); iter != SCT.vSCT.end(); ++iter ) {
const int iDX = iter->getPosX();
const int iDY = iter->getPosY();
const int full_text_length = iter->getText().length();
const int full_text_length = utf8_width( iter->getText() );

int iOffsetX = 0;
int iOffsetY = 0;
Expand Down
33 changes: 31 additions & 2 deletions src/catacharset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,35 @@ int utf8_width( const utf8_wrapper &str, const bool ignore_tags )
return utf8_width( str.c_str(), ignore_tags );
}

std::string left_justify( const std::string &str, const int width, const bool ignore_tags )
{
int str_width = utf8_width( str, ignore_tags );
if( str_width >= width ) {
return str;
} else {
return str + std::string( width - str_width, ' ' );
}
}

std::string right_justify( const std::string &str, const int width, const bool ignore_tags )
{
int str_width = utf8_width( str, ignore_tags );
if( str_width >= width ) {
return str;
} else {
return std::string( width - str_width, ' ' ) + str;
}
}

std::string utf8_justify( const std::string &str, const int width, const bool ignore_tags )
{
if( width < 0 ) {
return left_justify( str, -width, ignore_tags );
} else {
return right_justify( str, width, ignore_tags );
}
}

//Convert cursor position to byte offset
//returns the first character position in bytes behind the cursor position.
//If the cursor is not on the first half of the character,
Expand Down Expand Up @@ -247,7 +276,7 @@ static void build_base64_decoding_table()
std::string base64_encode( const std::string &str )
{
//assume it is already encoded
if( str.length() > 0 && str[0] == '#' ) {
if( !str.empty() && str[0] == '#' ) {
return str;
}

Expand Down Expand Up @@ -281,7 +310,7 @@ std::string base64_encode( const std::string &str )
std::string base64_decode( const std::string &str )
{
// do not decode if it is not base64
if( str.length() == 0 || str[0] != '#' ) {
if( str.empty() || str[0] != '#' ) {
return str;
}

Expand Down
4 changes: 4 additions & 0 deletions src/catacharset.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ int utf8_width( const char *s, bool ignore_tags = false );
int utf8_width( const std::string &str, bool ignore_tags = false );
int utf8_width( const utf8_wrapper &str, bool ignore_tags = false );

std::string left_justify( const std::string &str, int width, bool ignore_tags = false );
std::string right_justify( const std::string &str, int width, bool ignore_tags = false );
std::string utf8_justify( const std::string &str, int width, bool ignore_tags = false );

/**
* Center text inside whole line.
* @param text to be centered.
Expand Down
14 changes: 6 additions & 8 deletions src/character.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3173,7 +3173,7 @@ hp_part Character::body_window( const std::string &menu_header,
std::string h_bar = get_hp_bar( hp, maximal_hp, false ).first;
nc_color h_bar_col = get_hp_bar( hp, maximal_hp, false ).second;

return colorize( h_bar, h_bar_col ) + colorize( std::string( 5 - h_bar.size(),
return colorize( h_bar, h_bar_col ) + colorize( std::string( 5 - utf8_width( h_bar ),
'.' ), c_white );
}
};
Expand Down Expand Up @@ -3779,9 +3779,9 @@ std::string Character::extended_description() const
const auto &bps = get_all_body_parts( true );
// Find length of bp names, to align
// accumulate looks weird here, any better function?
size_t longest = std::accumulate( bps.begin(), bps.end(), static_cast<size_t>( 0 ),
[]( size_t m, body_part bp ) {
return std::max( m, body_part_name_as_heading( bp, 1 ).size() );
int longest = std::accumulate( bps.begin(), bps.end(), 0,
[]( int m, body_part bp ) {
return std::max( m, utf8_width( body_part_name_as_heading( bp, 1 ) ) );
} );

// This is a stripped-down version of the body_window function
Expand All @@ -3796,13 +3796,11 @@ std::string Character::extended_description() const
nc_color name_color = state_col;
auto hp_bar = get_hp_bar( current_hp, maximal_hp, false );

ss << colorize( bp_heading, name_color );
// Align them. There is probably a less ugly way to do it
ss << std::string( longest - bp_heading.size() + 1, ' ' );
ss << colorize( left_justify( bp_heading, longest ), name_color );
ss << colorize( hp_bar.first, hp_bar.second );
// Trailing bars. UGLY!
// TODO: Integrate into get_hp_bar somehow
ss << colorize( std::string( 5 - hp_bar.first.size(), '.' ), c_white );
ss << colorize( std::string( 5 - utf8_width( hp_bar.first ), '.' ), c_white );
ss << std::endl;
}

Expand Down
8 changes: 6 additions & 2 deletions src/debug_menu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1625,15 +1625,19 @@ void debug()
std::vector<uilist_entry> uiles;
{
uilist_entry uile( _( "Spell" ) );
uile.ctxt = string_format( "%3s %3s", _( "LVL" ), _( "MAX" ) );
uile.ctxt = string_format( "%s %s",
//~ translation should not exceed 4 console cells
right_justify( _( "LVL" ), 4 ),
//~ translation should not exceed 4 console cells
right_justify( _( "MAX" ), 4 ) );
uile.enabled = false;
uile.force_color = c_light_blue;
uiles.emplace_back( uile );
}
int retval = 0;
for( spell *sp : spells ) {
uilist_entry uile( sp->name() );
uile.ctxt = string_format( "%3d %3d", sp->get_level(), sp->get_max_level() );
uile.ctxt = string_format( "%4d %4d", sp->get_level(), sp->get_max_level() );
uile.retval = retval++;
uile.enabled = !sp->is_max_level();
uiles.emplace_back( uile );
Expand Down
29 changes: 16 additions & 13 deletions src/faction_camp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ const skill_id skill_traps( "traps" );
const skill_id skill_archery( "archery" );
const skill_id skill_swimming( "swimming" );

static const trait_id trait_DEBUG_HS( "DEBUG_HS" );

const zone_type_id z_loot_unsorted( "LOOT_UNSORTED" );
const zone_type_id z_loot_ignore( "LOOT_IGNORE" );
const zone_type_id z_camp_food( "CAMP_FOOD" );
Expand Down Expand Up @@ -440,6 +442,7 @@ static bool update_time_left( std::string &entry, const comp_list &npc_list )
entry = entry + " [" +
to_string( comp->companion_mission_time_ret - calendar::turn ) +
_( " left]\n" );
avail = g->u.has_trait( trait_DEBUG_HS );
}
}
entry = entry + _( "\n\nDo you wish to bring your allies back into your party?" );
Expand Down Expand Up @@ -2576,7 +2579,7 @@ void basecamp::recruit_return( const std::string &task, int score )
int food_desire = rng( 0, 5 );
while( rec_m >= 0 ) {
std::string description = _( "NPC Overview:\n\n" );
description += string_format( _( "Name: %20s\n\n" ), recruit->name );
description += string_format( _( "Name: %s\n\n" ), right_justify( recruit->name, 20 ) );
description += string_format( _( "Strength: %10d\n" ), recruit->str_max );
description += string_format( _( "Dexterity: %10d\n" ), recruit->dex_max );
description += string_format( _( "Intelligence: %10d\n" ), recruit->int_max );
Expand All @@ -2590,11 +2593,11 @@ void basecamp::recruit_return( const std::string &task, int score )
return level_a > level_b || ( level_a == level_b && a.name() < b.name() );
} );

description += string_format( "%12s: %4d\n", skillslist[0]->name(),
description += string_format( "%s: %4d\n", right_justify( skillslist[0]->name(), 12 ),
recruit->get_skill_level( skillslist[0]->ident() ) );
description += string_format( "%12s: %4d\n", skillslist[1]->name(),
description += string_format( "%s: %4d\n", right_justify( skillslist[1]->name(), 12 ),
recruit->get_skill_level( skillslist[1]->ident() ) );
description += string_format( "%12s: %4d\n\n", skillslist[2]->name(),
description += string_format( "%s: %4d\n\n", right_justify( skillslist[2]->name(), 12 ),
recruit->get_skill_level( skillslist[2]->ident() ) );

description += _( "Asking for:\n" );
Expand Down Expand Up @@ -3430,10 +3433,10 @@ std::string camp_trip_description( const time_duration &total_time,
entry += string_format( _( ">One Way: %15d (trips)\n" ), trips );
entry += string_format( _( ">Covered: %15d (m)\n" ), dist_m * trips );
}
entry += string_format( _( ">Travel: %23s\n" ), to_string( travel_time ) );
entry += string_format( _( ">Working: %23s\n" ), to_string( working_time ) );
entry += string_format( _( ">Travel: %s\n" ), right_justify( to_string( travel_time ), 23 ) );
entry += string_format( _( ">Working: %s\n" ), right_justify( to_string( working_time ), 23 ) );
entry += "---- ----\n";
entry += string_format( _( "Total: %23s\n" ), to_string( total_time ) );
entry += string_format( _( "Total: %s\n" ), right_justify( to_string( total_time ), 23 ) );
entry += string_format( _( "Food: %15d (kcal)\n\n" ), need_food );
return entry;
}
Expand Down Expand Up @@ -3593,28 +3596,28 @@ std::string basecamp::farm_description( const tripoint &farm_pos, size_t &plots_

std::string camp_car_description( vehicle *car )
{
std::string entry = string_format( _( "Name: %25s\n" ), car->name );
std::string entry = string_format( _( "Name: %s\n" ), right_justify( car->name, 25 ) );
entry += _( "---- Engines ----\n" );
for( const vpart_reference &vpr : car->get_any_parts( "ENGINE" ) ) {
const vehicle_part &pt = vpr.part();
const vpart_info &vp = pt.info();
entry += string_format( _( "Engine: %25s\n" ), vp.name() );
entry += string_format( _( "Engine: %s\n" ), right_justify( vp.name(), 25 ) );
entry += string_format( _( ">Status: %24d%%\n" ),
static_cast<int>( 100 * pt.health_percent() ) );
entry += string_format( _( ">Fuel: %25s\n" ), vp.fuel_type );
entry += string_format( _( ">Fuel: %s\n" ), right_justify( item::nname( vp.fuel_type ), 25 ) );
}
std::map<itype_id, int> fuels = car->fuels_left();
entry += _( "---- Fuel Storage & Battery ----\n" );
for( auto &fuel : fuels ) {
std::string fuel_entry = string_format( "%d/%d", car->fuel_left( fuel.first ),
car->fuel_capacity( fuel.first ) );
entry += string_format( ">%s:%*s\n", item( fuel.first ).tname(),
33 - item( fuel.first ).tname().length(), fuel_entry );
entry += string_format( ">%s:%s\n", item( fuel.first ).tname(),
right_justify( fuel_entry, 33 - utf8_width( item( fuel.first ).tname() ) ) );
}
for( auto &pt : car->parts ) {
if( pt.is_battery() ) {
const vpart_info &vp = pt.info();
entry += string_format( ">%s:%*d%%\n", vp.name(), 32 - vp.name().length(),
entry += string_format( ">%s:%*d%%\n", vp.name(), 32 - utf8_width( vp.name() ),
static_cast<int>( 100.0 * pt.ammo_remaining() /
pt.ammo_capacity() ) );
}
Expand Down
25 changes: 14 additions & 11 deletions src/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1007,7 +1007,7 @@ bool game::cleanup_at_end()
iNameLine = vRip.size();
vRip.emplace_back( "| <" );
vRip.emplace_back( "| |" );
iMaxWidth = vRip[vRip.size() - 1].length();
iMaxWidth = utf8_width( vRip.back() );
vRip.emplace_back( "| |" );
vRip.emplace_back( "|_____.-._____ __/|_________|" );
vRip.emplace_back( " | |" );
Expand Down Expand Up @@ -1041,7 +1041,7 @@ bool game::cleanup_at_end()
iNameLine = vRip.size();
vRip.emplace_back( "| <" );
vRip.emplace_back( "| |" );
iMaxWidth = vRip[vRip.size() - 1].length();
iMaxWidth = utf8_width( vRip.back() );
vRip.emplace_back( "| |" );
vRip.emplace_back( "|_____.-._______ __/|__________|" );
vRip.emplace_back( " % / `_-. _ |%" );
Expand All @@ -1064,7 +1064,7 @@ bool game::cleanup_at_end()
vRip.emplace_back( R"(| |)" );
vRip.emplace_back( R"(| _ |)" );
vRip.emplace_back( R"(|__/ |)" );
iMaxWidth = vRip[vRip.size() - 1].length();
iMaxWidth = utf8_width( vRip.back() );
vRip.emplace_back( R"( / `--. |)" );
vRip.emplace_back( R"(| ( )" );
iInfoLine = vRip.size();
Expand All @@ -1091,27 +1091,30 @@ bool game::cleanup_at_end()
sfx::fade_audio_group( sfx::group::fatigue, 2000 );

for( size_t iY = 0; iY < vRip.size(); ++iY ) {
for( size_t iX = 0; iX < vRip[iY].length(); ++iX ) {
char cTemp = vRip[iY][iX];
if( cTemp != ' ' ) {
size_t iX = 0;
const char *str = vRip[iY].data();
for( int slen = vRip[iY].size(); slen > 0; ) {
const uint32_t cTemp = UTF8_getch( &str, &slen );
if( cTemp != U' ' ) {
nc_color ncColor = c_light_gray;

if( cTemp == '%' ) {
if( cTemp == U'%' ) {
ncColor = c_green;

} else if( cTemp == '_' || cTemp == '|' ) {
} else if( cTemp == U'_' || cTemp == U'|' ) {
ncColor = c_white;

} else if( cTemp == '@' ) {
} else if( cTemp == U'@' ) {
ncColor = c_brown;

} else if( cTemp == '*' ) {
} else if( cTemp == U'*' ) {
ncColor = c_red;
}

mvwputch( w_rip, point( iX + FULL_SCREEN_WIDTH / 2 - ( iMaxWidth / 2 ), iY + 1 ), ncColor,
vRip[iY][iX] );
cTemp );
}
iX += mk_wcwidth( cTemp );
}
}

Expand Down
7 changes: 4 additions & 3 deletions src/handle_action.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,8 @@ input_context game::get_player_input( std::string &action )
for( auto &elem : SCT.vSCT ) {
//Erase previous text from w_terrain
if( elem.getStep() > 0 ) {
for( size_t i = 0; i < elem.getText().length(); ++i ) {
const int width = utf8_width( elem.getText() );
for( int i = 0; i < width; ++i ) {
const tripoint location( elem.getPosX() + i, elem.getPosY(), get_levz() );
const lit_level lighting = visibility_cache[location.x][location.y];
wmove( w_terrain, location.xy() + point( -offset_x, -offset_y ) );
Expand All @@ -264,8 +265,8 @@ input_context game::get_player_input( std::string &action )
//Check for creatures on all drawing positions and offset if necessary
for( auto iter = SCT.vSCT.rbegin(); iter != SCT.vSCT.rend(); ++iter ) {
const direction oCurDir = iter->getDirecton();

for( int i = 0; i < static_cast<int>( iter->getText().length() ); ++i ) {
const int width = utf8_width( iter->getText() );
for( int i = 0; i < width; ++i ) {
tripoint tmp( iter->getPosX() + i, iter->getPosY(), get_levz() );
const Creature *critter = critter_at( tmp, true );

Expand Down
2 changes: 1 addition & 1 deletion src/input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ std::string get_input_string_from_file( const std::string &fname )
if( !ret.empty() && static_cast<unsigned char>( ret[0] ) == 0xef ) {
ret.erase( 0, 3 );
}
while( !ret.empty() && ( ret[ret.size() - 1] == '\r' || ret[ret.size() - 1] == '\n' ) ) {
while( !ret.empty() && ( ret.back() == '\r' || ret.back() == '\n' ) ) {
ret.erase( ret.size() - 1, 1 );
}
} );
Expand Down
Loading

0 comments on commit 0490a5a

Please sign in to comment.