elfmz / far2l

Linux port of FAR v2
GNU General Public License v2.0
1.76k stars 171 forks source link

Editor/Viewer Codepages - проблемы и предложения по улучшению #1179

Closed akruphi closed 1 year ago

akruphi commented 2 years ago

1) В редаторе/просмотрощике По нажатию F8 сейчас как и windows Far меняется кодировка ANSI<->OEM. На UTF-8 переключаться уже только через Shift+F8 Предлагаю по F8 сделать ANSI<->OEM<->UTF-8

2) Не мгновенная смена кодировки в редакторе для файла более сотни байт или с оформлением! При открытии в far2l по F4 совсем маленького файла (или без применения цветовой кодировки) изменение кодировки (по F8 или Shitf+F8) происходит на мгновенно. Но если файл хоть чуть-чуть большой или с вариантами оформления требующими цветовой кодировки (например, внутри фрагмент в кавычках "..."), то для применения кодовой страницы нужно выйти и по новой войти в файл, либо ещё раз переключить кодировки туда-сюда. Это очень сильно напрягает - я в спешке несколько файлов так испортил - не обратил внимание, что кодировка не-до-переключилась и начал вносить измененя и сохранять.

unxed commented 2 years ago

по F8 сделать ANSI<->OEM<->UTF-8

Лайк!

singalen commented 2 years ago

Может, вообще потерять ANSI из F8?

akruphi commented 2 years ago

Может, вообще потерять ANSI из F8?

Ни в коем случае! Например, мне приходится поддерживать разный написанный 15-5 лет назад windows софт, конфиги+ввод/вывод которого как раз в ANSI (cp1251). А вот OEM (cp866) уже почти не встречается. Но из F8 исключать и ANSI и OEM пока точно не стоит.

unxed commented 2 years ago

Вообще, наверное, идеально было бы сделать список кодировок, переключаемых по F8, настраиваемым. А по дефолту, да, положить туда ANSI и UTF8.

Хотя для linux-софта, конечно, там должно быть не ANSI, а ну я не знаю KOI8 например... но она хоть где-нибудь по факту есть сейчас, эта KOI8? А вот ANSI и правда в большом количестве легаси софта имеется.

elfmz commented 2 years ago

настраиваемым можно, насчет UTF8 - есть ньюанс - при просмотре в hex режиме UTF8 не включабелен по объективным причинам

unxed commented 2 years ago

Тогда две настройки, для hex и просто

singalen commented 2 years ago

Две настройки - это худший вариант: вместо упрощения, система усложняется.

Отображать utf-8 в hex можно, потому что текст в hex всегда длиннее, чем в utf8. Если какой-то символ мультибайтовый, то нарисовать его напротив первого байта, а остальные забить символами whitespace (пробел с точечкой, https://ux.stackexchange.com/questions/91255/how-can-i-best-display-a-blank-space-character)

Вообще, в списке кодировок заявлена кнопка Del, но сейчас она ничего не делает. Почему бы ей не убирать кодировку из избранных по F8? А Ins, наоборот, добавлять в избранные. Screen Shot 2022-01-06 at 11 57 11

Но меня устроит и вариант – просто удалить откуда-нибудь из конфигов.

alk0 commented 2 years ago

Отцы, а почему у нас наглухо пропали все East Asian codepages? В WinPort/wineguts/libwineguts.a они вроде вкомпилируются (вот прям явно собрал с -DEACP=yes, чтоб уж наверняка), но по Shift-F8 их нет. Да, я помню, я первый стоял в очереди с хотелкой, чтоб их выпилить, но теперь вот внезапно снова надо :) Речь о 932, 936, 949, 950, 1361, 10001, 10002, 10003, 10008, 20932. Или я чего-то не догоняю.

Предложение про какой-нибудь механизм для избранных кодировок яростно двачую — почти никому ведь не надо все, а нужные у всех разные.

elfmz commented 2 years ago

Ctrl+H чтобы появились..

alk0 commented 2 years ago

Ctrl+H чтобы появились..

Не помогает. По Ctrl-H прячутся/отображаются все Other (37, 424, …, 28606 - штук 60), но вот китайских-японских-корейских среди них ни одной. Что я делаю не так?

unxed commented 2 years ago

Там, кстати, почему-то ещё и DOS в блоке Unicode

elfmz commented 2 years ago

Не помогает. По Ctrl-H прячутся/отображаются все Other (37, 424, …, 28606 - штук 60), но вот китайских-японских-корейских среди них ни одной. Что я делаю не так?

Хех, это изза этого - https://github.com/elfmz/far2l/blob/master/far2l/src/locale/codepage.cpp#L367 ~Мопед не мой~ оно там так изначально было

unxed commented 2 years ago

Неужели даже в Far3 не поправили о_О

alk0 commented 2 years ago

Штош… то есть, они никогда и не работали? Ну, тогда смысла собирать с EACP вообще нет, получается? (А по дефолту оно включено, и в ридми упомянуто.)

Ладно. Всё равно без подержки fullwidth символов в far2l смотреть на японские и китайские тексты очень грустно, переживём пока.

elfmz commented 2 years ago

В третьем фаре работает - видимо пофиксили это. Смысла похоже нет, пока оно не пофикшено тут. Я тогда беру EACP из ридми, сделаю его в cmake в NO по дефолту и в пометочку рядом поставлю - почему так..

unxed commented 2 years ago

без подержки fullwidth символов в far2l смотреть на японские и китайские тексты очень грустно

А почему грустно? В utf-8 нормально же показываться должны

unxed commented 2 years ago

Хм, некоторые проблемки и правда есть.

  1. Открываем far2l в GNOME Terminal
  2. Открываем этот файл в редакторе jp_sample.txt
  3. Нажимаем стрелку вниз на клавиатуре
  4. Видим артефакты

(сэмпл отсюда: http://kawanet.github.io/iconv-cp932/demo/)

alk0 commented 2 years ago

Потому что символы отображаются вчетверо (0.5x0.5) меньше положенного, там писельных коллизий получается очень уж много :) Так-то и "нормальный" привычный нам размер чуток маловат для не-носителя языка. Сверху текст нормального человека, ниже - текст курильщика. Размер и гарнитура шрифта одинаковые.

image

unxed commented 2 years ago

А, ага, ну это бекэнд-специфическая проблема. В GNOME Terminal нормальный размер.

изображение

Но там свои баги, вот выше описал один

elfmz commented 2 years ago

На самом деле проблема не бэкенда а фара общая - он не умеет рассчитывать длину элементов гуя в реальных знакоместах. wx-овый бэкенд это workaround-ит путем утаптывания иероглифов в одно знакоместо, зато ничего не наезжает. В терминале же неизбежны глюки с наезжанием текста.

alk0 commented 2 years ago

Реальные знакоместа - штука такая, мутная. Есть шрифты, где fullwidth два знакоместа ровно занимает, а есть всякие 2/3, 4/5 и прочая дичь. Для этого вроде как есть правильные подходы - вроде как у шрифта можно запросить метрики именно в разрезе fullwidth для CJK, но я в это всё не умею :(

Ну и как решать проблему "нарисовать рамку псевдографикой вокруг текста, если длина текста невыразима целым числом знакомест" - тоже не понимаю.

unxed commented 2 years ago

Ну в редакторе mc в GNOME Terminal тот же файл открывается нормально, редактируется нормально, ничто никуда не наезжает. Как они это делают?

alk0 commented 2 years ago

Магия?..

elfmz commented 2 years ago

не магия, просто надо переделать код фара который интерфейс составляет, чтобы когда надо учитывал именно визуальную длину строки а не тупо wcslen

alk0 commented 2 years ago

А серьёзно, есть подозрение, что это там работает только для duospaced fonts - то есть тех, где ширина ханьцзы/кандзи/буквы каны/буквы хангыля составляет ровно два человеческих знакоместа, и баста. А monospaced, но при том не duospaced шрифты - для извращенцев.

alk0 commented 2 years ago

Для общего развития вот тут можно глянуть - https://en.wikipedia.org/wiki/Duospaced_font#In_CJK_typography

elfmz commented 2 years ago

Да это все понятно, тут вот какой файл есть на эту тему - https://github.com/elfmz/far2l/blob/master/WinPort/src/Backend/TTY/IsUnstableWidthChar.cpp но не надо пугаться длине ифа, он автосгенеренный - https://github.com/elfmz/far2l/blob/master/WinPort/src/Backend/TTY/IsUnstableWidthChar_mk.cpp Проблема не в определении длины строк, а в рефакторе кода самого фара

unxed commented 2 years ago

Тут предложение имеется по поводу ветки iconv. Сейчас она как-то бестолково подвисла в неопределенном состоянии. А что если сделать выбор бекенда конверсии кодировок, wine или iconv, с wine по умолчанию? Ну и вмержить код из iconv ветки так. Если на каких-то corner cases wine будет работать плохо, или если кому-то понадобится максимально сократить бинарник в ущерб скорости - будет выбор

ivanshatsky commented 1 year ago

Некоторое время назад совершенно случайно узнал, что в Far 3 уже некоторое время как завезли вот такой параметр:

image

С просмотром в hex-режиме всё понятно, но ведь даже сейчас при переключении в него из обычного режима с включенной кодировкой UTF-8 кодировка изменяется на однобайтную. Почему бы не добавить аналогичный параметр в far2l и просто не игнорировать многобайтные кодировки в hex-режиме просмотра?

akruphi commented 1 year ago

Наконец-то в коде посмотрел как захардкорить навешивание на F8 ещё одной кодовую страницы UTF8 - с первого взгляда просто.

Для просмотрощика сработало заменой строки https://github.com/elfmz/far2l/blob/b8182b71cd3d025f2907ec6960899d119b80cb87/far2l/src/viewer.cpp#L1405 на

            //VM.CodePage = VM.CodePage == WINPORT(GetOEMCP)() ? WINPORT(GetACP)() : WINPORT(GetOEMCP)();
            if (VM.CodePage == CP_UTF8)
                VM.CodePage = WINPORT(GetACP)();
            else if (VM.CodePage == WINPORT(GetACP)() )
                VM.CodePage = WINPORT(GetOEMCP)();
            else // if (VM.CodePage == WINPORT(GetOEMCP)() )
                VM.CodePage = VM.Hex ? WINPORT(GetACP)() : CP_UTF8; // STUB - для hex UTF8/UTF32 сейчас не работает

и с hex-режимом тут вроде корректно обходимся.


А вот для редактора словил баг. Замена в https://github.com/elfmz/far2l/blob/b8182b71cd3d025f2907ec6960899d119b80cb87/far2l/src/fileedit.cpp#L1173 только строки

                if (Key == KEY_F8) {
                    codepage = (m_codepage == WINPORT(GetACP)() ? WINPORT(GetOEMCP)() : WINPORT(GetACP)());
                } else {

на

                if (Key == KEY_F8) {
                    //codepage = (m_codepage == WINPORT(GetACP)() ? WINPORT(GetOEMCP)() : WINPORT(GetACP)());
                    if (m_codepage == CP_UTF8)
                        codepage = WINPORT(GetACP)();
                    else if (m_codepage == WINPORT(GetACP)() )
                        codepage = WINPORT(GetOEMCP)();
                    else // if (m_codepage == WINPORT(GetOEMCP)() )
                        codepage = CP_UTF8;
                } else {

приводит к странному багу: переключение ANSI->OEM срабатывает полноценно, однако далее после любого переключение на/с UTF8 отваливается перерисовка редактора (как текста, так и titlebar; keybar при этом меняется), причём сама кодировка при этом переключается и запоминается для файла. Для пропихивания перерисовки достаточно вызвать любое диалоговое окно (F7, F9, F11, Shift-F8 и т.п.) и просто закрыть диалог по ESC без каких-либо изменений.

Без понимания как обходится с багом не стал далее навешивать третий текст UTF8 на кнопку F8 в Viewer::ChangeViewKeyBar() и FileEditor::SetEditKeyBarStatefulLabels().

Буду благодарен @elfmz за разъяснения причин бага и корректных способов работы с таким поведением редактора.

akruphi commented 1 year ago

Вроде доделал в #1700 Надеюсь ничего по ходу не сломал.

unxed commented 1 year ago

Про пункт 2. Он не очень понятный. Вот бы приложить пример файла, и описать алгоритм действий, при которых файл портится из-за недопереключившейся кодировки. Чтоб можно было и воспроизвести, и убедиться, что решение работает.

akruphi commented 1 year ago

Ну всё закрываю. Наконец-то доделан UTF8 в F8. А проблема "2. не мгновенная смена кодировки" была решена ещё давно, кажется исправлением #1233 или где-то рядом.