Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/engine/ui/cmd/do_display.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,12 @@ void do_display(CharData *ch, char *argument, int/* cmd*/, int/* subcmd*/) {
} else {
set_display_bits(ch, false);

// Аргумент перебираем посимвольно, а не побайтно: под UTF-8 русская буква занимает два
// байта, и шаг в один байт приводил ко второму, хвостовому байту буквы. Он не совпадал
// ни с одной меткой и уводил в default, то есть свой набор букв поставить было нельзя
// вовсе -- работали только "статус все" и "статус нет".
const size_t len = strlen(argument);
for (size_t i = 0; i < len; i++) {
for (size_t i = 0; i < len; i += native_text::char_bytes(argument + i)) {
switch (native_text::first_char_code_lower(argument + i)) {
case 'h':
case rus::kZhe: ch->SetFlag(EPrf::kDispHp);
Expand Down
1 change: 1 addition & 0 deletions tests/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ test_sources = files(
'world_data_source_manager.cpp',
'bitset_flags.cpp',
'extra_description.cpp',
'status.command.cpp',
'filter.affect_name.cpp',
'trigger_indenter.cpp',
'trigger_script_parser.cpp',
Expand Down
69 changes: 69 additions & 0 deletions tests/status.command.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// Команда "статус" со своим набором букв (issue: статус все/нет работали, свой набор -- нет).
//
// Аргумент разбирался побайтно, а под UTF-8 русская буква занимает два байта: после каждой
// буквы шаг в один байт приводил к её хвостовому байту, тот не совпадал ни с одной меткой и
// уводил разбор в default -- команда печатала справку и не ставила ничего. Латиница из одного
// байта при этом работала, поэтому баг выглядел как "русские буквы не принимаются".

#include "engine/ui/cmd/do_display.h"

#include "simulator/character_builder.h"
#include "engine/entities/char_data.h"
#include "gameplay/core/constants.h"

#include <gtest/gtest.h>

#include <cstring>

namespace {

CharData::shared_ptr MakePlayer(simulator::CharacterBuilder &builder) {
builder.make_basic_player(static_cast<short>(ECharClass::kSorcerer), 30);
return builder.get();
}

void RunStatus(const CharData::shared_ptr &ch, const char *argument) {
char buffer[64];
strncpy(buffer, argument, sizeof(buffer) - 1);
buffer[sizeof(buffer) - 1] = '\0';
do_display(ch.get(), buffer, 0, 0);
}

} // namespace

TEST(StatusCommand, CyrillicLettersSetTheirOwnFlags) {
simulator::CharacterBuilder builder;
auto ch = MakePlayer(builder);

RunStatus(ch, "жзв");

EXPECT_TRUE(ch->IsFlagged(EPrf::kDispHp)) << "Ж -- жизнь";
EXPECT_TRUE(ch->IsFlagged(EPrf::kDispMana)) << "З -- запас сил";
EXPECT_TRUE(ch->IsFlagged(EPrf::kDispExits)) << "В -- выходы";
EXPECT_FALSE(ch->IsFlagged(EPrf::kDispMoney)) << "Д не набирали";
}

TEST(StatusCommand, LatinLettersStillWork) {
simulator::CharacterBuilder builder;
auto ch = MakePlayer(builder);

RunStatus(ch, "hw");

EXPECT_TRUE(ch->IsFlagged(EPrf::kDispHp));
EXPECT_TRUE(ch->IsFlagged(EPrf::kDispMana));
EXPECT_FALSE(ch->IsFlagged(EPrf::kDispExits));
}

TEST(StatusCommand, UnknownLetterStopsParsing) {
simulator::CharacterBuilder builder;
auto ch = MakePlayer(builder);

RunStatus(ch, "жяв");

// Поведение как было: неизвестная буква печатает справку и обрывает разбор, но то, что
// успело примениться до неё, остаётся.
EXPECT_TRUE(ch->IsFlagged(EPrf::kDispHp)) << "Ж до неизвестной буквы";
EXPECT_FALSE(ch->IsFlagged(EPrf::kDispExits)) << "В после неё уже не разбирается";
}

// vim: ts=4 sw=4 tw=0 noet syntax=cpp :
Loading