spamsink: (lenin)
[personal profile] spamsink


Понадобилось мне давеча спортировать одно консольное приложение под винды (Win7). Ну что, приложение как приложение, ничего особенного. Ну пользуется юникодом, ну пользуется ESC-последовательностями, казалось бы, делов-то куча. Ан нет.

Засада номер 1: На середине второго десятилетия XXI века надо руками включать юникод (chcp 65001).

Засада номер 2: Если байты UTF-8, относящиеся к одному символу, разорваны на два системных вызова write, то на экране получаем козью морду, а не символ юникода. Пришлось плюнуть и на chcp 65001, и на системный вызов write, и воспользоваться WriteConsoleW (для этого пришлось написать функцию сбора юникода из байтиков, естественно).

Засада номер 3: Из-за большого ума Майкрософт решил не реализовывать ESC-последовательности в консольном окне. Пользуйтесь, дескать, разработчики дорогие, нашим всемогущим console API и не выпендривайтесь.
— Что? Переносимость? Какая в подоконник переносимость?
Ну ладно, так и быть, нашел я https://github.com/adoxa/ansicon

Итого, убил полдня на то, что должно было просто работать™, причем так мало исключительно благодаря ansicon. И так у них всё

Date: 2015-01-06 02:55 am (UTC)
From: [identity profile] yatur.livejournal.com
Ты еще пожалуйся на слэши не в ту сторону :)

Консоль в виндах по большей части для обратной совместимости с ДОСом и досообразными утилитами под Windows 3.1. Поэтому полный Юникод там по умолчанию выключен - ну какой в ДОСе может быть Юникод?

В Юниксе виндузятнику тоже бывает не слишком уютно. Во-первых, там нет диска C:... :D

Date: 2015-01-06 02:58 am (UTC)
From: [identity profile] archaicos.livejournal.com
Файлы с UNIX slash'ами открываются нормально ещё со времён дремучего DOS'а.

Date: 2015-01-06 02:59 am (UTC)
From: [identity profile] archaicos.livejournal.com
Это всё фигня. Но вот выбрать Unicode шрифт программным образом без хаков нельзя в принципе. Нет публичного документированного API. :)

Date: 2015-01-06 03:09 am (UTC)
vak: (Default)
From: [personal profile] vak
Может, есть какой-нибудь альтернативный cmd.exe?

Date: 2015-01-06 03:34 am (UTC)
From: [identity profile] yatur.livejournal.com
Это смотря где :)
C:\>dir c:/bin
Ошибка в формате параметра: "bin".

Date: 2015-01-06 03:44 am (UTC)
vak: (Default)
From: [personal profile] vak
Тоже вариант.

Date: 2015-01-06 04:14 am (UTC)
From: [identity profile] fatoff.livejournal.com
Да вроде в Windows 10 они слегка подтянули консоль до. Но не смотрел пока.
Никогда не пользуюсь системными вызовами, что отрабатывать UTF8. Лучше всего это сделано в библиотеке Qt.

А у меня из-за апгрейда ядра Linux с одного минорного индекса вроде Major.Minor -> Major.Minor + 3 отключился WiFi, и единственный способ получить его снова - грузиться в Major.Minor - 3 нынешний. 3.13.0-40 -> 3.13.0-43 -- позор джунглям!
Edited Date: 2015-01-06 04:38 am (UTC)

Date: 2015-01-06 04:25 am (UTC)
ak_47: (default)
From: [personal profile] ak_47
Справедливо. Консоль в Винде совершенно позорная.

Date: 2015-01-06 05:19 am (UTC)
From: [identity profile] sab123.livejournal.com
write() - НЕ системный вызов в виндах.

Правильно выводить 16-битный юникод на стандартный вывод так: у stdout включается режим Юникода через _setmode(), и потом туда можно писать через wprintf() и тому подобное. Еще желательно посылать первый символ 0xFEFF (или наоборот 0xFFFE, не помню), иначе если устраивать конвейер, не все программы прочухают юникодность. Для конверсии из UTF-8 есть готовые функции, вроде MultiByteToWideChar() правиальная.

Date: 2015-01-06 05:31 am (UTC)
From: [identity profile] fatoff.livejournal.com
За долгие годы чего-то делания в том числе с UTF8 меня ни разу не посетила идея использовать для того вызов API. И всегда успешно обходился. При том, что по сей день приходится довольно часто пользоваться API.

Date: 2015-01-06 05:35 am (UTC)
From: [identity profile] archaicos.livejournal.com
Человек же не скрипт или комманду пишет. А CreateFile переварит.

Date: 2015-01-06 05:35 am (UTC)

Date: 2015-01-06 06:18 am (UTC)
From: [identity profile] archaicos.livejournal.com
Ошибка в библиотеке (или где там, т.к. WriteConsole() — это под низом библиотеки) — это по нашему. :)

Date: 2015-01-06 07:13 am (UTC)
From: [identity profile] archaicos.livejournal.com
Состоял ли анекдот в интимной связи с темой? Если да, можно поподробней?

Date: 2015-01-06 07:44 am (UTC)
From: [identity profile] archaicos.livejournal.com
Но беда в том, что по умолчанию там вовсе не Unicode шрифт.

Date: 2015-01-06 07:46 am (UTC)
From: [identity profile] archaicos.livejournal.com
Это если поставишь подсистему для UNIX приложений, может и будет работать. А так это Windows. :)

Date: 2015-01-06 08:30 am (UTC)
From: [identity profile] ilya-dogolazky.livejournal.com
а сигвинчиком теперь не модно пользоваться?

Date: 2015-01-06 09:10 am (UTC)
From: [identity profile] archaicos.livejournal.com
Напиши Линусу, что он нехороший человек.

Date: 2015-01-06 10:12 am (UTC)
From: [identity profile] archaicos.livejournal.com
Где обещан?

Date: 2015-01-06 10:21 am (UTC)
From: [identity profile] archaicos.livejournal.com
Где-то хранит настройки в своих закромах. Выбрать можно ручками и по умолчанию шрифт растровый и не Unicode'ный:
http://superuser.com/questions/104030/what-font-does-cmd-exe-use-by-default-for-output-in-windows-xp

Если не ручками, то как я уже писал, здравствуй, опа, новый г@д:
http://blogs.microsoft.co.il/pavely/2009/07/23/changing-console-fonts/

Date: 2015-01-06 03:33 pm (UTC)
From: [identity profile] fatoff.livejournal.com
В мире Линуса есть только эльфы и феи. Как в нормальном безусловно демократическом.

Date: 2015-01-06 03:55 pm (UTC)
From: [identity profile] vaddimka.livejournal.com
ой, там проще конвертировать UTF-8 в двубайтовый юникод и писать системными вызовами (на виндовсе) и гнать UTF-8 напрямую (макось и линукс)
у меня так нормально работает и в макоси и в виндовсе (и в линуксе наверное тоже, но не проверял еще)
есть обертка для плюсов, называется Boost.Nowide
Edited Date: 2015-01-06 03:57 pm (UTC)

Date: 2015-01-06 05:42 pm (UTC)
From: [identity profile] sab123.livejournal.com
Я в смысле про "правильно" - не "так и должно быть", а "как заставить его работать". А ты можешь дать маленький пример? Я его попробую на 10, и если эффект все еще проявляется, зафайлю баг с ним. Вроде они нынче внезапно взялись улучшать консоль.

Date: 2015-01-06 09:07 pm (UTC)
From: [identity profile] sab123.livejournal.com
Да, на 10 - та же фигня. Я подозреваю, что они конвертируют текст через MultiByteToWideChar(), а в ней не видно возможности обнаружить частичные символы на хвосте.

Кстати, а вот скажи как юникодный эксперт, есть ли простой способ обнаружить частичные символы, сканируя строку с хвоста? Чтоб их оторвать и сохранить до следующего вызова.

И бонус, как воткнуть в текст программы строку "Привет\n", чтобы компилятор VS ее не испортил: надо или записать файл как "UTF-8 without signature", и тогда компиятор ее молча прожует, или использовать

#pragma execution_character_set("utf-8")

Если же записать файл как "UTF-8 with signature", компилятор проявит интеллект, скажет, что такие буквы не поддерживаются в кодировке, и заменит их на 0x3ff. Но видимо в "UTF-8 without signature" не получится использовать родные широкие строки (L").

Date: 2015-01-06 10:13 pm (UTC)
From: [identity profile] sab123.livejournal.com
> В противном случае, если в найденном байте количество старших бит 1 равно количеству итераций

В смысле, в том, который (0xC0 <= байт < 0xF8)?

> В юниксе я отлично пишу в файле в формате UTF-8 без сигнатур L"Привет" и получаю массив wchar_t.

Это потому что компилятор по умолчанию предполагает кодировку UTF-8. В Виндовсе если поставить такую кодировку во всей системе (но непонятно, как именно), то компилятор тоже будет такое предполагать. Он берет кодировку, выбранную в системе как умолчальную. Чтобы это явно поменять, надо использовать прагму.

Date: 2015-01-06 10:29 pm (UTC)
From: [identity profile] sab123.livejournal.com
Ну, в-общем, я ввел баг в систему, а уж будут ли его починять - отдельный вопрос.

Date: 2015-01-06 10:31 pm (UTC)
From: [identity profile] sab123.livejournal.com
Если очень захотеть, можно сделать свою реализацию stdio (ну, то есть, взять какую-нибудь готовую, и присобачить трансляцию UTF в multibyte). Ну, и заодно write() с друзьями, если оно нужно.

Date: 2015-01-06 10:54 pm (UTC)
From: [identity profile] ilya-dogolazky.livejournal.com
странно, что сигвинчик не умеет всё собирать в один большой экзешник, польза была б

Date: 2015-01-06 11:12 pm (UTC)
From: [identity profile] vaddimka.livejournal.com
да, бардак
низкоуровневые языки заставляют ломать голову над маразмами платформы

Profile

spamsink: (Default)
spamsink

February 2026

S M T W T F S
12345 67
8 91011 121314
15161718 192021
22 2324 25262728

Most Popular Tags

Page Summary

Style Credit

Expand Cut Tags

No cut tags
Page generated Mar. 5th, 2026 06:01 pm
Powered by Dreamwidth Studios