LINUX.ORG.RU

C, ncurses, кириллица ? или я чего-то не понимаю или одно из двух


0

0

Извиняюсь, я на таких форумах новичок, не уверен как лучше сформулировать свою проблему и реально ли получить помощь от местной публики

Предыстория: у меня огромная прога (учетная система для торговли) созданная на C с нуля еще до эпохи Windows. Потом переделана как консольное приложение Win32, теперь вот есть идея для Linux адаптировать. Фактически только модуль ввода-вывода и требуется переделать.

И вот уже неделю я парюсь с выводом кириллицы. В теории (описания и маны) все понятно очевидно и легко. При выводе латинских букв - тоже все соответствует описанию, как только выводятся кириллические (кодируемые в UTF 2ми байтиками) - какие-то глюки

Стал смотреть тогда дамп экрана (scr_dump) Во-первых, оказалось его размер -8К . т.е. разработчики отводят 4байта на знакоместо. Ну это я понимаю. ОК. 3 знака на код символа UTF + байт цветового атрибута. Ан нет! при выводе кириллицы 4байта отводится на кадый байт кодировки!!! т.е. 8 байт на символ Но тогда буфер экрана в 8К не хватит, если достаточно много кириллических символов И его таки не хватает На каждой строке экрана корректно выводится 40 кириллических знаков, а не 80 как хотелось бы!

Подозреваю, у меня как-то криво собрана библиотека ncurses, либо она не соответствует UTF кодировке И сразу вдогонку вопрос - может UTF и ни к чему? Вообще-то меня бы вполне устроила кодировка 866 кодовой таблицы.


Ответ на: комментарий от LebedevRI

2.6.26-2-686 #1 SMP Thu Mar 26 01:08:11 UTC 2009 i686 GNU/Linux Debian

CoGo
() автор топика

Имхо - забить на UTF! Использовать ncurses + 8-битную кодировку (да хоть и 866) и запускать свою прогу через LANG=cp866; proga. Вообщето, когдато давно при переносе на Линукс досовской проги, использующей библиотеку текстового интерфейса Vitamin я использовал прямую запись в буфер консоли через /dev/vcsa. Правда это работает только для текстового режима экрана и не работает в xterm. Поэтому текстовый интерфейс затем был переделан на графический. А вам еще можно подумать про Web-интерфейс через встроеный в вашу прогу www-сервер ну или CGI-модули.

sigurd ★★★★★
()
Ответ на: комментарий от CFA

Да, я встречал упоминания ncursesw Только вот откуда он берется?

-lncursesw cannot found

apt-get install ncursesw тоже ничего про нее не знает

ну попробую поискать ссылки

CoGo
() автор топика
Ответ на: комментарий от CoGo

apt-cache show libncursesw5

Package: libncursesw5
Priority: important
Section: libs
Installed-Size: 656
Maintainer: Daniel Baumann <daniel@debian.org>
Architecture: amd64
Source: ncurses
Version: 5.7+20090523-1
Depends: libc6 (>= 2.3.4)
Recommends: libgpm2
Filename: pool/main/n/ncurses/libncursesw5_5.7+20090523-1_amd64.deb
Size: 378846
MD5sum: ddd7c0f74f1dffbe44cfe0b6aff7a3f8
SHA1: 235e1159019c8336e31b95fdd57d579bfe86cf33
SHA256: 0e527283ac58cea158be14df617a2d8c87e102890c914adca72a5d0c37af1f2f
Description: shared libraries for terminal handling (wide character support)
 This package contains the shared libraries necessary to run programs
 compiled with ncursesw, which includes support for wide characters.
Homepage: ftp://invisible-island.net/ncurses/
Tag: devel::library, role::shared-lib, uitoolkit::ncurses

blackice
()
Ответ на: комментарий от blackice

Да, спасибо,

ncursesw

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

CoGo
() автор топика
Ответ на: комментарий от CFA

Та же проблема с ncursesw Все-таки я каких-то глубин не понимаю

Чтобы как можно короче сформулировать проблему- задам вопрос таким образом:

Существует ли какое-нибудь значение переменной chout, чтобы нижеприведенная прога вывела на экран к примеру русскую букву Б в кодировке UTF ?

....... chtype chout;

....... addch(chout);

как я понял экспериментальным путем, функции типа waddchstr при выводе русских букв требуют по 2 элемента chtype. и отсюда уже вся остальная кривизна

вот к примеру

................ chtype chout[3];

chout[0]=0xd0; chout[1]=0xa0; chout[2]=0;

addchstr(chout); ................

это выводит символ "Р" большую русскую

CoGo
() автор топика
Ответ на: комментарий от CoGo

Не уверен, что в тему, но всё-таки. У меня есть выгрызок из моей программы, который нормально выводит «Здравствуй, мир!» в ncurses
под Slackware 12.1 с локалью ru_RU.UTF-8.

Собирается командой
g++ ./n.cpp -Wall -lncursesw -o ./n.elf && ./n.elf

#define _XOPEN_SOURCE_EXTENDED
#if ENABLE_NLS != 1
  #undef ENABLE_NLS
  #define ENABLE_NLS 1
#endif
#define _GNU_SOURCE

#include <ncurses.h>
#include <wchar.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>

// i18n support
#include <locale.h>
#include <libintl.h>
#define _(msg) gettext(msg)
#define N_(msg) msg

#define global
#define use_global extern

enum {AK_CONTIN, AK_EXIT, AK_EXITNOW};

void init_curses(void);
void deinit_ncurses(void);
void curs_anykey(int beh);
void any_key(int beh);

global char * gp_progfname = (char *)"n"; // program filename
global bool g_ncurses_inited = false; // for correct cleanup on fatal errors

//----------------------------------------------------------------------------

int main (int argc, char **argv) {

  setlocale(LC_ALL, "");

  init_curses();

  printw("Здравствуй, мир!\n");
  curs_anykey(AK_CONTIN);

  deinit_ncurses();
  return 0;

} // end function main

//----------------------------------------------------------------------------

void init_curses(void) {

  use_global char * gp_progfname;
  use_global bool g_ncurses_inited;

  if (initscr() == NULL) { // Start curses mode
    fprintf(stderr,
      _("%s: error: can't initialize ncurses (pseudographics low-level engine)\n"),
      gp_progfname
    );
    any_key(AK_EXIT);
    exit(1);
  }
  g_ncurses_inited = true;

  if (cbreak() == ERR) {  // determine that line buffering (and some other stuff) is disabled
    fprintf(stderr, _("%s: warning: can't disable line buffering\n"), gp_progfname);
    curs_anykey(AK_CONTIN);
  }

  if (noecho() == ERR) {  // symbols that user type will not be echoed on the screen
    fprintf(stderr, _("%s: warning: can't disable input symbols echoing\n"), gp_progfname);
    curs_anykey(AK_CONTIN);
  }

  if (start_color() == ERR) {
    fprintf(stderr, _("%s: warning: can't enable color mode\n"), gp_progfname);
    curs_anykey(AK_CONTIN);
  }

  if(curs_set(0) == ERR) {
    fprintf(stderr, _("%s: warning: can't hide cursor\n"), gp_progfname);
    curs_anykey(AK_CONTIN);
  }

} // end func init_curses;

//----------------------------------------------------------------------------

void curs_anykey(int beh) {

  // Эта функция выводит приглашение нажать любую клавишу
  // и ожидает её нажатия.
  //
  // Вход:
  //   beh:
  //     AK_CONTIN - продолжить работу после нажатия клавиши
  //     AK_EXITNOW - вызвать функцию exit(1) после нажатия клавиши
  //
  // Должны быть включены режимы cbreak и noecho.

  wint_t wint;

  if (beh != AK_EXITNOW) {
    printw(_("Press any key to continue...\n"));
    refresh();
    get_wch(&wint);
  } else {
    printw(_("Press any key to exit...\n"));
    refresh();
    get_wch(&wint);
    // endwin();  // End curses mode.
    // curses mode will be stopped with atexit()-registered final_cleanup()
    exit(1);
  }

} // end func curs_anykey;

//----------------------------------------------------------------------------

void any_key(int beh) {
  printf(_("(wait for any key was not made yet)\n"));
  fflush(stdout);
} // end func any_key;

//----------------------------------------------------------------------------

void deinit_ncurses(void) {

  use_global bool g_ncurses_inited;

  if (g_ncurses_inited == true) endwin();

}

sergey_feo
()
Ответ на: комментарий от sergey_feo

Спасибо! сегодня я уже разобрался, что к чему.

Резюмируя свои выводы для будущих читателей, озаботившихся аналогичным вопросом:

1) необходимо установить ncursesw и линковать прогу с ней

2) в тексте проги желательно подключить <locale.h> и выдать setlocale(LC_CTYPE, "ru_RU.UTF8");

3) при выводе на консоль функциями типа waddstr каждый символ кириллицы кодируется 2мя байтами от D090 до D0BF (А...п) потом от D180 до D18f (от р до я)

осталась проблема: не ясно как кодировать chtype при выводе функциями типа waddchstr, я бы предпочел их использовать как более скоростные

CoGo
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.