Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix artifacts in viewer in tty #2107

Merged
merged 3 commits into from
Apr 7, 2024
Merged

fix artifacts in viewer in tty #2107

merged 3 commits into from
Apr 7, 2024

Conversation

unxed
Copy link
Contributor

@unxed unxed commented Mar 25, 2024

Fixes #2084

@unxed
Copy link
Contributor Author

unxed commented Mar 30, 2024

Здесь классы символов сгенерированы на Убунту 23.10, там ICU должна быть посвежее. И дополнительная проверка через wcwidth() убирает часть проблем в моем случае.

@elfmz
Copy link
Owner

elfmz commented Mar 31, 2024

вот эта проверка и смущает, по двум причинам:

  • wcwidth() вызывается из CharClasses.cpp но это очень узкое место для перфоманса, почему не вызывать ее из CharClasses_mk.cpp сразу чтоб сгенерился нужный свич в CharClasses.cpp?
  • поведение wcwidth() по-видимому зависит от текущей локали, и если локаль русская то возможно с японскими символами оно будет вести себя некорректно. Но это не точно. Просто смущает.

Вообще а почему wcwidth не совпадает с результатами ICUUC? Может там просто чтото не учитывается в исходном коде на проверках ее результатов?

@unxed
Copy link
Contributor Author

unxed commented Apr 1, 2024

Попробуем для примера разобрать символ, с которого началось обсуждение проблемы:
https://www.compart.com/en/unicode/U+0692

Вот этот код

	int c = 0x692;
	const auto jt = u_getIntPropertyValue(c, UCHAR_JOINING_TYPE);
	const auto cat = u_getIntPropertyValue(c, UCHAR_GENERAL_CATEGORY);
	printf("%i %i %i %i %i\n", cat, jt, cat == U_SURROGATE, jt == U_JT_RIGHT_JOINING, wcwidth(c));

Даёт

~/far2l/!local/far2l/utils/src$ ./a.out
5 4 0 1 -1

и на Mint 21.3, и на Ubuntu 23.10.

Почему это RIGHT JOINING, когда это обычная арабская буква? Почему wcwidth() для неё -1 возвращает? Одни вопросы без ответов.

@unxed
Copy link
Contributor Author

unxed commented Apr 1, 2024

Свойства символа 0x692, которые нам отдаёт ICU, такие:
Категория: U_UPPERCASE_LETTER (1) & U_MODIFIER_LETTER (4)
Тип соединения: U_JT_RIGHT_JOINING (4)

@unxed
Copy link
Contributor Author

unxed commented Apr 1, 2024

Получается, символ является префиксом, однако длина у него не нулевая. В far2l такое, по-моему, не поддерживается.

@unxed
Copy link
Contributor Author

unxed commented Apr 1, 2024

Окей, проблему с арабской буквой и другими ошибочными префиксами можно решить, например, так:

	WriteFunc("IsCharPrefix", [](wchar_t c)->bool {
		const auto jt = u_getIntPropertyValue(c, UCHAR_JOINING_TYPE);
		const auto cat = u_getIntPropertyValue(c, UCHAR_GENERAL_CATEGORY);
		return (cat == U_SURROGATE || ((jt == U_JT_RIGHT_JOINING) && (cat != U_OTHER_LETTER) && (cat != U_OTHER_NUMBER)));
	});

Но там другие артефакты остаются, ловятся на бинарнике far2l справа при включенном word wrap:
изображение

Явно что-то ещё не так определяется там, изучаю.

@unxed
Copy link
Contributor Author

unxed commented Apr 1, 2024

Как минимум часть оставшихся багов происходит из-за того, что в качестве постфиксов тоже определяются печатные символы. Это чинится например так:

		return (
				(jt != U_JT_NON_JOINING && jt != U_JT_TRANSPARENT && jt != U_JT_RIGHT_JOINING && jt != U_JT_DUAL_JOINING) &&

// sample: https://www.compart.com/en/unicode/U+0640, printable
				(cat != U_MODIFIER_LETTER) &&
				(cat != U_OTHER_LETTER) &&
				(cat != U_OTHER_NUMBER) &&
				(cat != U_OTHER_PUNCTUATION)

Но баги на просмотре бинарника far2l всё равно остаются.

@unxed
Copy link
Contributor Author

unxed commented Apr 1, 2024

Артефакты вида || справа побеждаются добавлением

			|| cat == U_ENCLOSING_MARK || cat == U_FORMAT_CHAR

после

			|| cat == U_NON_SPACING_MARK || cat == U_COMBINING_SPACING_MARK

, но там остаётся ещё противный баг с » справа, которых быть не должно. Он исчезает, сделать так:

		return ea_width == U_EA_FULLWIDTH; // || ea_width == U_EA_WIDE;

Разбираюсь.

@unxed
Copy link
Contributor Author

unxed commented Apr 1, 2024

Обновил PR. Текущий код решает проблему с артефактами, о которой был изначальный тикет. По крайней мере, теми из них, что были заметны при просмотре бинарника far2l.

А проблема с лишними », похоже, отдельная, и связана не с префиксами/постфиксами, а с какими-то проблемками с обработками символов двойной длины, и будто бы надо копать viewer, а не классы символов тут.

@unxed
Copy link
Contributor Author

unxed commented Apr 2, 2024

Ещё любопытное наблюдение: wcwidth() вообще не работает, если не сделать предварительно

    setlocale(LC_CTYPE, "en_US.UTF-8");

@unxed
Copy link
Contributor Author

unxed commented Apr 2, 2024

В данный момент я упёрся в символ мягкого переноса, 0xAD. Он может иметь ширину 0 или 1 клетки, в зависимости от положения в строке (с правого краю или нет).

Вот, например, тестовый файл. Если открыть его в редакторе и подвигать курсор, ничего не выйдет. Если прописать в IsCharSuffix() дополнительное условие (c != 0xAD) &&, редактирование начинает работать, но с правого краю всё равно остаётся артефакт II. И сам символ не отрисовывается (хотя учитывая, что мы запретили ему считаться суффиксом, не очень понятно, почему).

Что с этим делать пока не пониманю.
bugN01.tar.gz

@elfmz elfmz merged commit e6ad61a into elfmz:master Apr 7, 2024
2 checks passed
@unxed unxed deleted the tty-viewer-fix branch April 7, 2024 21:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

viewing binary files breaks output to kitty terminal
2 participants