far2l icon indicating copy to clipboard operation
far2l copied to clipboard

Searching in UTF8 documents is case-sensitive despite Case Sensitive checkbox unchecked for non-latin characters

Open LanThrusteR opened this issue 1 year ago • 42 comments

Open a document with Shift + F4 and write something like Привет (the first letter is in uppercase) and then try searching in the same document for привет (the first letter is lowercase) with Case sensitive checkbox unchecked the result : not found

With Latin letters it works OK.

LanThrusteR avatar Mar 06 '24 08:03 LanThrusteR

У меня не воспроизводится - всё ищется правильно.

akruphi avatar Mar 06 '24 09:03 akruphi

У меня не воспроизводится - всё ищется правильно.

Во вложении видео. У вас в окружении какая локаль стоит и как вы far2l запускаете?

мое окружение

LC_MONETARY=ru_RU.UTF-8
LC_MEASUREMENT=ru_RU.UTF-8
LC_TIME=en_GB.UTF-8
LC_ALL=en_US.UTF-8
LC_COLLATE=ru_RU.UTF-8

и нет других локалей в строке запуска far2l

https://github.com/elfmz/far2l/assets/8512951/68981fdd-6a1e-4c1d-b3d3-fc755b8dcdbc

LanThrusteR avatar Mar 07 '24 08:03 LanThrusteR

Моё окружение:

LANGUAGE=en_US:
LANG=en_US.UTF-8
LC_ADDRESS=ru_RU.UTF-8
LC_NAME=ru_RU.UTF-8
LC_MONETARY=ru_RU.UTF-8
LC_PAPER=ru_RU.UTF-8
LC_IDENTIFICATION=ru_RU.UTF-8
LC_TELEPHONE=ru_RU.UTF-8
LC_MEASUREMENT=ru_RU.UTF-8
LC_TIME=ru_RU.UTF-8
LC_NUMERIC=ru_RU.UTF-8

также прописано в ~/.config/far2l/cp

866
1251

Заменил в окружении export LC_ALL, LC_COLLATE и LC_TIME на значения как у @LanThrusteR и запустил far2l. Поиск это не сломало.

Интересный баг.

akruphi avatar Mar 07 '24 09:03 akruphi

866 1251 то же самое прописано

        linux-vdso.so.1 (0x00007ffe4f7ad000)
        libdl.so.2 => /lib64/libdl.so.2 (0x00007f458926d000)
        libuchardet.so.0 => /usr/lib64/libuchardet.so.0 (0x00007f458923b000)
        libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f458921b000)
        libstdc++.so.6 => /usr/lib/gcc/x86_64-pc-linux-gnu/12.2.1/libstdc++.so.6 (0x00007f4588ffb000)
        libm.so.6 => /lib64/libm.so.6 (0x00007f4588eb7000)
        libgcc_s.so.1 => /usr/lib/gcc/x86_64-pc-linux-gnu/12.2.1/libgcc_s.so.1 (0x00007f4588e98000)
        libc.so.6 => /lib64/libc.so.6 (0x00007f4588cda000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f4589615000)

интересно в чем дело, в окружении или в чем то ещё, может libuchardet влиять на поиск? Какая версия у вас libuchardet? У меня 0.0.7

LanThrusteR avatar Mar 07 '24 10:03 LanThrusteR

Какая версия у вас libuchardet? У меня 0.0.7

У меня в Ubuntu 22.04.4 LTS всё симлинчится на libuchardet.so.0.0.7

akruphi avatar Mar 07 '24 10:03 akruphi

Какая версия у вас libuchardet? У меня 0.0.7

У меня в Ubuntu 22.04.4 LTS всё симлинчится на libuchardet.so.0.0.7

что интересно: если запускать far2l из KDE лаунчера : поиск не работает если запустить konsole и из неё запустить far2l : поиск работает если запустить из лаунчера konsole -e far2l : поиск не работает т.е. пока всё свелось к тому как пускать far2l, если его пускать через лаунчер - то поиск не работает, если его пускать из любого терминала - то поиск работает....

хотя локали и переменные те же самые с виду если в far2l выдать env то видишь те же локали, попробую разобраться от чего именно это зависит от какой то переменной окружения или от чего, пока не ясно

LanThrusteR avatar Mar 07 '24 10:03 LanThrusteR

Всё выяснилось, в KDE у меня стоит регион en_GB

если запустить far2l как

env LC_ALL=en_GB.UTF-8 far2l

то поиск не работает

если

запустить как

env LC_ALL=en_US.UTF-8 far2l

то поиск работает

вообще это странный эффект, пока не понятно почему это происходит чем именно локаль en_US отличается от en_GB так чтобы влиять на поиск в русской кодировке

как быстрый фикс этой проблемы, - выглядит так что far2l должен иметь более сложную логику работы в локалями в случае если определена LC_COLLATE=ru_RU.UTF-8 а LC_ALL=en_GB.UTF-8

то нужно менять LC_ALL на LC_ALL=en_US.UTF-8

то что я вижу сейчас это как будто LC_COLLATE вообще не влияет на FAR2l

поиск не работает: env LC_ALL=en_GB.UTF-8 env LC_COLLATE=en_US.UTF-8 far2l env LC_ALL=en_GB.UTF-8 env LC_COLLATE=ru_RU.UTF-8 far2l

поиск работает: env LC_ALL=en_US.UTF-8 env LC_COLLATE=en_US.UTF-8 far2l env LC_ALL=en_US.UTF-8 env LC_COLLATE=ru_RU.UTF-8 far2l

LanThrusteR avatar Mar 07 '24 11:03 LanThrusteR

И я тут видел баг по локациям и быстрым клавишам если правильно помню, та же история т.е. если нет env LC_ALL=en_US.UTF-8 far2l или env LC_ALL=ru_RU.UTF-8 far2l

то если например текущая раскладка RU и нажать Alt + F1 и если локациям заданы латинские буквы (например L), то если нажать L (т.е. русскую д на текущий момент) то не сработает переключение, т.е. нужно переключить раскладку в латинскую и затем доступ к локацям по букве L заработает

т.е. LC_COLLATE=ru_RU.UTF-8

игнорируется far2l

PS и вот теперь и быстрый поиск по файлам (Alt + буквы) заработал по файлам с латинскими имненами но в при этом текущая раскладка RU, т.е. это всё одна проблема

LanThrusteR avatar Mar 07 '24 11:03 LanThrusteR

Внутри far2l явно кодовые страницы определяются из ~/.config/far2l/cp или при его отсутствии по LC_CTYPE (см. DeduceCodepages() в WinPort/src/APIStringCodepages.cpp). Очень странно как проползает влияние LC_ALL даже при наличии ~/.config/far2l/cp :exploding_head:

Наверное тему стоит переименовать в "Nonlatin letters search problem with LC_ALL non en_US.UTF8 or non ru_RU.UTF-8" или вот что-то подобное?

akruphi avatar Mar 07 '24 12:03 akruphi

если запустить far2l как env LC_ALL=en_GB.UTF-8 far2l то поиск не работает

Странно, но у меня работает (и far2l, и far2m).

shmuz avatar Mar 07 '24 13:03 shmuz

если запустить far2l как env LC_ALL=en_GB.UTF-8 far2l то поиск не работает

Странно, но у меня работает (и far2l, и far2m).

А чему у вас равно LC_CTYPE?

LanThrusteR avatar Mar 07 '24 14:03 LanThrusteR

А чему у вас равно LC_CTYPE?

Оно не выставлено, просто нет такой переменной. Если запускаю env LC_ALL=en_GB.UTF-8 LC_CTYPE=en_GB.UTF-8 ~/far2l/_build/install/far2l то ваш пример поиска всё равно работает правильно.

shmuz avatar Mar 07 '24 15:03 shmuz

Есть ещё интересное наблюдение, если в ./far2l-v_2.6.0/far2l/src/main.cpp закоментировать // setlocale(LC_ALL, ""); // otherwise non-latin keys missing with XIM input method

то становится все равно как запускать

env LC_ALL=en_GB.UTF-8 far2l или env LC_ALL=en_US.UTF-8 far2l

всегда НЕ РАБОТАЕТ, т.е. видимо в этом где то и есть проблема, нужно ещё где то установить

setlocale(LC_ALL, ""); // otherwise non-latin keys missing with XIM input method

пока не понятно почему так происходит, т.е. если я убираю setlocale(LC_ALL, ""); // otherwise non-latin keys missing with XIM input method

*я нахожус в KDE

то проблема вообще всегда существует и её нельзя исправить

env LC_ALL=en_US.UTF-8 far2l

между тем я не наблюдаю проблемы в комментарии // otherwise non-latin keys missing with XIM input method т.е. во всяком случае русские UTF-8 символы - работают как работали, из под X но если эту строку убрать - то проблема на видео происходит всегда и её не возможно (или пока не найдено как) обойти но если это строка есть - то решается с помощью

env LC_ALL=en_US.UTF-8 far2l

но в .bashrc прописано export LC_ALL="en_US.UTF-8"

(возможно главное чтобы не совпадало с локалью, выставленной в KDE)

Screenshot_20240307_190426

LanThrusteR avatar Mar 07 '24 15:03 LanThrusteR

А чему у вас равно LC_CTYPE?

Оно не выставлено, просто нет такой переменной. Если запускаю env LC_ALL=en_GB.UTF-8 LC_CTYPE=en_GB.UTF-8 ~/far2l/_build/install/far2l то ваш пример поиска всё равно работает правильно.

осмелюсь предположить что что вы FAR2L не под X Windows пробуете а через терминал т.е. не из под Xов

LanThrusteR avatar Mar 07 '24 15:03 LanThrusteR

осмелюсь предположить что что вы FAR2L не под X Windows пробуете а через терминал т.е. не из под Xов

Запускаю из терминала (GNOME Terminal) WX-вариант far2l, т.е. появляется отдельное от терминала окно.

shmuz avatar Mar 07 '24 16:03 shmuz

осмелюсь предположить что что вы FAR2L не под X Windows пробуете а через терминал т.е. не из под Xов

Запускаю из терминала (GNOME Terminal) WX-вариант far2l, т.е. появляется отдельное от терминала окно.

да, это странно, может быть в гноме этого нет, а у вас KDE нет попробовать то же самое?

LanThrusteR avatar Mar 07 '24 16:03 LanThrusteR

а у вас KDE нет попробовать то же самое?

Сейчас попробовал (Manjaro-KDE-Plasma) - проблема воспроизвелась. Попробовал также плагином LF Search под far2m - при использовании движков поиска PCRE или Oniguruma проблемы нет, при использовании движка Far проблема есть.

shmuz avatar Mar 07 '24 16:03 shmuz

если запустить как env LC_ALL=en_US.UTF-8 far2l то поиск работает

очень весёлая история. потому что у меня так -- НЕ работает как раз. :)

spnethw avatar Mar 08 '24 19:03 spnethw

если запустить как env LC_ALL=en_US.UTF-8 far2l то поиск работает

очень весёлая история. потому что у меня так -- НЕ работает как раз. :)

Возможно что локаль должна не совпадать с той что указана в настройках KDE (LC_ALL), у меня работает и вариант

env LC_ALL=ru_RU.UTF-8 far2l

попробуйте

LanThrusteR avatar Mar 09 '24 09:03 LanThrusteR

Итак

setlocale(LC_ALL, "");

в исходниках main.cpp говорить что мы должны использовать локаль системы, которая в моем случае en_GB

Если мы её переопределяем через

env LC_ALL=ru_RU.UTF-8 far2l

far2l рабоатет

env LC_ALL=en_US.UTF-8 far2l

far2l рабоатет! (хотя не должен)

LanThrusteR avatar Mar 09 '24 10:03 LanThrusteR

мой locale

LANG=en_GB.UTF-8 LC_CTYPE="en_US.UTF-8" LC_NUMERIC="en_US.UTF-8" LC_TIME="en_US.UTF-8" LC_COLLATE="en_US.UTF-8" LC_MONETARY="en_US.UTF-8" LC_MESSAGES="en_US.UTF-8" LC_PAPER="en_US.UTF-8" LC_NAME="en_US.UTF-8" LC_ADDRESS="en_US.UTF-8" LC_TELEPHONE="en_US.UTF-8" LC_MEASUREMENT="en_US.UTF-8" LC_IDENTIFICATION="en_US.UTF-8" LC_ALL=en_US.UTF-8

~/.bashrc export LC_ALL="en_US.UTF-8"

LanThrusteR avatar Mar 09 '24 12:03 LanThrusteR

Просто оставлю здесь: обнуление LC_ALL появилось в main() вот с этого коммита: https://github.com/elfmz/far2l/commit/fd01af64c52bf1ea7c2ea96e5fc6cef5eebbdcd4 ещё от Sep 2, 2016

akruphi avatar Mar 09 '24 13:03 akruphi

Немного копнул как оно внутри устроено :exploding_head:. Поиск делается через SearchString() из strmix.cpp внутри которой при !Case делается приведение Upper(Ch) != Upper(Str[J]). Где Upper() inline-ка из locale.hpp, которая для не ASCII символов дергает CharUpperBuff из APIStringMap.cpp и уже внутри которой зарыта

return WINPORT(LCMapString)( LOCALE_USER_DEFAULT, LCMAP_UPPERCASE, str, len, str, len );

и вот уже в LCMapStringEx() при flags & LCMAP_UPPERCASE дергается из стандартной библиотеки towupper(), которая и даёт сюрпризы этого issue.

UPD: Гугление показало, что из такого towupper() костылятся явным указанием локали при или перед приведением регистра:

  • std::toupper(c,loc) - link
  • toupper(c, std::locale("")) - link
  • либо двустрочником std::setlocale(LC_ALL, "ru_RU.utf8"); std::towupper(с); - link

Причём во всех случаях локаль должна корректно стоять в системе.

Как тут корректно решать проблему топикстартера не соображу.

akruphi avatar Mar 09 '24 14:03 akruphi

Причём во всех случаях локаль должна корректно стоять в системе. Как тут корректно решать проблему топикстартера не соображу.

Тут есть ещё одна загадка, логика строки в main.cpp

setlocale(LC_ALL, "");//otherwise non-latin keys missing with XIM input method

говорить stdlib использовать локаль из окружения, т.е. кажется что это сделано правильно какие бы причины ни были в начале, тогда почему в моем случае работает env LC_ALL=en_US.UTF-8 far2l env LC_ALL=ru_RU.UTF-8 far2l

и не работает env LC_ALL=en_GB.UTF-8 far2l

казалось бы в случае

LANG=en_GB.UTF-8 LC_CTYPE="en_US.UTF-8" LC_NUMERIC="en_US.UTF-8" LC_TIME="en_US.UTF-8" LC_COLLATE="en_US.UTF-8" LC_MONETARY="en_US.UTF-8" LC_MESSAGES="en_US.UTF-8" LC_PAPER="en_US.UTF-8" LC_NAME="en_US.UTF-8" LC_ADDRESS="en_US.UTF-8" LC_TELEPHONE="en_US.UTF-8" LC_MEASUREMENT="en_US.UTF-8" LC_IDENTIFICATION="en_US.UTF-8" LC_ALL=en_US.UTF-8

~/.bashrc export LC_ALL="en_US.UTF-8"

не должно работать оба варианта, и тем ни менее

LanThrusteR avatar Mar 09 '24 15:03 LanThrusteR

Если закомментировать setlocale(LC_ALL, "");//otherwise non-latin keys missing with XIM input method то начинает логично работать, не работает:

env LC_ALL=en_US.UTF-8 far2l env LC_ALL=en_GB.UTF-8 far2l

работает: env LC_ALL=ru_RU.UTF-8 far2l

Чтобы эту проблему решить навсегда, предлагаю вместо setlocale(LC_ALL, "");//otherwise non-latin keys missing with XIM input method при старте делать опрос альтернативных раскладок и если есть вторая раскладка (и только если их две) то вместо setlocale(LC_ALL, "");//otherwise non-latin keys missing with XIM input method прописывать локаль альтернативной раскладки setlocale(LC_ALL, DETECTED_ALTERNATIVE_LOCALE);

и тогда это зло отступит

LanThrusteR avatar Mar 09 '24 15:03 LanThrusteR

И даже есть ещё интересная находка что если закомментировать setlocale(LC_ALL, "");//otherwise non-latin keys missing with XIM input method то работает и env LC_COLLATE=ru_RU.UTF-8 far2l

т.е. чтобы поправить эту проблему нужно после setlocale(LC_ALL, "");//otherwise non-latin keys missing with XIM input method сделать setlocale(LC_COLLATE, DETECTED_ALTERNATIVE_LAYOUT_LOCALE);//otherwise non-latin keys missing with XIM input method где DETECTED_ALTERNATIVE_LAYOUTE_LOCALE : это альтернативная локаль (если есть) которая используется при перключении клавиатуры (в случае если две - что является подавляющем большинством случаев) т.е. в моем случае это выглядело бы как

setlocale(LC_ALL, "");//otherwise non-latin keys missing with XIM input method setlocale(LC_COLLATE, "ru_RU.UTF-8");

т.е. нужно добавить после LC_ALL установку LC_COLLATE, как вариант упрощенный, чтобы не связываться с определением альтернативной расскладки, можно из окружения брать LC_COLLATE и задавать её после

setlocale(LC_ALL, "");//otherwise non-latin keys missing with XIM input method setlocale(LC_COLLATE, CURRENT_LC_COLLATE_FROM_ENVIRONMENT);

LanThrusteR avatar Mar 09 '24 15:03 LanThrusteR

вот этот патч решит проблему для большинства пользователей:

заменить setlocale(LC_ALL, ""); // otherwise non-latin keys missing with XIM input method

на setlocale(LC_ALL, ""); // otherwise non-latin keys missing with XIM input method setlocale(LC_COLLATE, getenv("LC_COLLATE"));

--- /var/tmp/portage/app-misc/far2l-2.6.0_beta/work/far2l-v_2.6.0/far2l/src/.main.cpp	2024-02-19 22:32:19.000000000 +0300
+++ /var/tmp/portage/app-misc/far2l-2.6.0_beta/work/far2l-v_2.6.0/far2l/src/main.cpp	2024-03-09 18:59:32.000000000 +0300
@@ -759,6 +759,7 @@
 	umask(g_umask);
 
 	setlocale(LC_ALL, "");	// otherwise non-latin keys missing with XIM input method
+	setlocale(LC_COLLATE, getenv("LC_COLLATE"));
 
 	SetupFarPath(argv[0]);

patch.txt

LanThrusteR avatar Mar 09 '24 16:03 LanThrusteR

хм ревертнуть чтоли 786400ac4...

elfmz avatar Mar 10 '24 14:03 elfmz

как оно ща?

elfmz avatar Mar 10 '24 18:03 elfmz

как оно ща?

Хм. Перестало искать в тех же условиях, в каких раньше искало в принципе. Чекбокс "Учитывать регистр" снят, искомая строка "забросил", в тексте встречается "Забросил":

╔══════ Поиск ══════╗
║ Строка не найдена ║
║    "забросил"     ║
╟───────────────────╢
║      { OK }       ║
╚═══════════════════╝

Файл -- LF, UTF-8.

$ locale
LANG=ru_RU.UTF-8
LC_CTYPE="ru_RU.UTF-8"
LC_NUMERIC="ru_RU.UTF-8"
LC_TIME="ru_RU.UTF-8"
LC_COLLATE="ru_RU.UTF-8"
LC_MONETARY="ru_RU.UTF-8"
LC_MESSAGES="ru_RU.UTF-8"
LC_PAPER="ru_RU.UTF-8"
LC_NAME="ru_RU.UTF-8"
LC_ADDRESS="ru_RU.UTF-8"
LC_TELEPHONE="ru_RU.UTF-8"
LC_MEASUREMENT="ru_RU.UTF-8"
LC_IDENTIFICATION="ru_RU.UTF-8"
LC_ALL=

spnethw avatar Mar 10 '24 19:03 spnethw