Требуется помощь С/С++ программиста

Нужна помощь С/С++ программиста для локализации зарубежного MUD-движка.

Так и не оставил идеи создания первого русскоязычного lpmud'а, для чего перепробовал различные драйвера и библиотеки этого мада (напомню, lpmud состоит из двух частей: драйвера, написанного на С/С++ и являющегося интерпретатором языка lpc, и библиотеки на lpc, которая содержит всю информацию о игровом мире и игровых механиках). Выбор остановился на драйвере DGD и библиотеке gurbalib, так как они до сих пор более или менее обновляются и хорошо задокументированы.

И драйвер и библиотека переписаны в юникодовской кодировке UTF-8 и все сообщения и описания нормально переводятся на русский. Но есть одна неприятная особенность, все сообщения и описания на русском получаются по длине в два раза короче оригинальных английских, из-за чего смотрятся не очень красиво (этим страдают все lpmud'ы).
gurbalib-rus
Видимо, в драйвере есть модуль отвечающий за форматирование текста и подсчитывающий длину строк по количеству байт, а так как русские символы занимают в два раза больше памяти, чем английские, то строки получаются в два раза короче. Нужно исправить этот баг движка.

Рабочая директория драйвера: https://github.com/Muderru/dgd.
Рабочая директория библиотеки: https://github.com/Muderru/gurbalib-rus.

25 комментариев

avatar
  • prool
  • 0
Стоп. А это не проблема клиента?

Я ходил по этим же граблям (не помню, в каком движке, но это и неважно, там была сделанная мной русификация в кодовой таблице UTF-8 и была та же проблема: тексты на русском занимали пол ширины экрана). Я пользовался клиентом prooltin (tintin++). И ВНЕЗАПНО я нашел, где в тинтине включить кодровку UTF-8 и всё исправилось. Включить кодировку там так

#config charset UTF-8

То есть может байтики считает не сервер, а клиент?
avatar
  • prool
  • 0
Если в используемом тобой клиенте есть кодировка UTF, это ничего не значит. Может, включение UTF там вызывает нерезание 8-го бита, а подсчет длины строк делается по-старому (функцией strlen, если это C/C++)
avatar
  • prool
  • 0
На кортинке видна Тортилла. Пинай авторов Тортиллы, они есть в дискорд-чатике
avatar
В мадлете то же самое
gurbalib-rus
avatar
  • prool
  • 0
int utf8_strlen(const string& str)
{
int c,i,ix,q;
for (q=0, i=0, ix=str.length(); i < ix; i++, q++)
{
c = (unsigned char) str[i];
if (c>=0 && c<=127) i+=0;
else if ((c & 0xE0) == 0xC0) i+=1;
else if ((c & 0xF0) == 0xE0) i+=2;
else if ((c & 0xF8) == 0xF0) i+=3;
//else if (($c & 0xFC) == 0xF8) i+=4; // 111110bb //byte 5, unnecessary in 4 byte UTF-8
//else if (($c & 0xFE) == 0xFC) i+=5; // 1111110b //byte 6, unnecessary in 4 byte UTF-8
else return 0;//invalid utf8
}
return q;
}
avatar
Что это?
avatar
  • prool
  • 0
Это реализация функции strlen, которая правильно считает длину строки с символами UTF-8. Как говорит молодежь «я просто оставлю это здесь». А то потеряю это
avatar
  • bodrich
  • 0
Только у комнат такой баг? Или, например, если в сказать что-нибудь длинное в чат на русском — тоже так будет съезжать?
avatar
  • bodrich
  • +1
Файл user.c, функция void wrap_message(string str, varargs int chat_flag)
Тебе нужно здесь изменить strlen и немного сам алгоритм работы
avatar
commit можешь сделать? Я не программист и ничего сам изменить не могу.
avatar
  • bodrich
  • 0
Не могу. Добавь прулевскую функцию int utf8_strlen(const string& str)
и в функции wrap_message измени все strlen на utf8_strlen
avatar
В какой файл добавлять int utf8_strlen(const string& str)?
avatar
  • bodrich
  • 0
lib/sys/obj/user.c
avatar
Ты уверен? Функция Пруля на С, а lib/sys/obj/user.c написана на lpc.
avatar
  • bodrich
  • 0
А ты попробуй! Есть вариант, что такое прокатит.
avatar
  • bodrich
  • 0
Если не прокатит, то попробуй вместо strlen, использовать функцию strwidth().
Либо ты можешь вообще убрать этот автоматический перенос слов
UPD. Возможно, у string есть функция length() или len() можно ее попробовать
avatar
Все сообщения на русском в два раза короче, например если сказать что-нибудь и т.д.
avatar
Создал соответствующий issue https://github.com/dworkin/dgd/issues/12, даже начали что-то мне отвечать. Только я не понимаю что. :(
avatar
  • prool
  • 0
Вот тебе исправление проблемы методом «очень грязного хака». Два места, в которых я что-то менял, помечены коментом /* prool fool */

Это новый вариант функции для файла ib/sys/obj/user.c

Но у меня описание комнаты на всю ширину экрана вывелось только после того, как я в prooltin дал команду #config charset utf-8
То есть и клиент должен понимать UTF-8

void wrap_message(string str, varargs int chat_flag) {
string msg, *words, *lines;
int width, i, j, sz;

if (!str || str == "") {
return;
}

width = -1;
/* Get the width from the player */
if (player) {
catch(width = player->query_width());
}

rlimits(MAX_DEPTH; MAX_TICKS) {
/* Split the string into lines */
lines = explode(str, "\n");

/* Parse each line */
for (j = 0; j < sizeof(lines); j++) {
str = lines[j];
msg = str;
if (0/*strlen(ansid->strip_colors(str)) > width*/) { /* prool fool */
int adding;
string word_todo;

sz = 0;
words = explode(str, " ");
msg = "";

for (i = 0; i < sizeof(words); i++) {
word_todo = nil;
if (strlen(words[i]) > 4 && (strstr(words[i], "%^") != -1)) {
word_todo = ansid->strip_colors(words[i]);
}
/* word_todo is the word stripped from ansi codes */
if (!word_todo) {
word_todo = words[i];
}

if (0/*sz + strlen(word_todo) + adding > width*/) {/* prool fool */
msg += "\n";

if (chat_flag) {
msg += " ";
}

/* add length of word without ansi codes */
sz = strlen(word_todo) + 2;

/* add word with ansi codes */
msg += words[i];
} else {
if (adding) {
msg += " " + words[i];
} else {
msg += words[i];
}
sz += strlen(word_todo) + adding;
}
/* determine how many spaces will be added next run */
if (sz == 0) {
adding = 0;
} else {
adding = 1;
}
}
}
if (query_player()->query_ansi()) {
msg = ansid->parse_colors(msg);
} else {
msg = ansid->strip_colors(msg);
}

send_message(msg + "\n");
}
}
}
avatar
Спасибо! Ты крут!
avatar
  • bodrich
  • 0
Я твой код запихнул в issue, мб потом кому-то пригодится.
avatar
  • prool
  • 0
Ты кого обезьяной назвал? :)
avatar
  • bodrich
  • 0
Я не силен в анлийском, но мне кажется dirt hack там было бы неуместно.
avatar
  • prool
  • 0
Черт его знает.
avatar
А найдется ли добрый человек, который сможет заставить регулярные выражения с русским текстом работать? Подозреваю, что копать нужно здесь https://github.com/Muderru/dgd/blob/master/src/ed/regexp.cpp.
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.