IPB
ЛогинПароль:

> 

Наладить общение поможет, если вы подпишитесь по почте на новые темы в этом форуме.

 
 Ответить  Открыть новую тему 
> Вопрос о ncurses
сообщение
Сообщение #1


Новичок
*

Группа: Пользователи
Сообщений: 23
Пол: Мужской

Репутация: -  0  +


На мой предыдущий вопрос ответа нет (или никто ничего не знает). Зайду к моей проблемке с другой стороны.
Нигде не нашел информации об использовании ncurses в паскале. Есть малость для Си. Но это для меня сложно.
Есть ли где-то какая-нибудь информация именно для паскаля?

Сообщение отредактировано: camac -
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #2


Большевик–концептуал
***

Группа: Пользователи
Сообщений: 180
Пол: Мужской
Реальное имя: Иван Левашев
Jabber: octagram@jabber.ru
Skype: i.levashew
QQ: 3152538431
WeChat
Ада: Сторонник
Embarcadero Delphi: Сторонник
Free Pascal: Разработчик
Turbo Pascal: Установлен

Репутация: -  1  +


Я знаю, что в самом ncurses есть привязки для языка Ada, но я так посмотрел, там юникод не в явном виде. Сергей Дюков Unicode для ncurses делал, но для Windows. Не знаю, как это далеко от порта на Linux.

Цитата
информации об использовании ncurses в паскале. Есть малость для Си. Но это для меня сложно


Напрасно. Надо уметь переводить с Си в Паскаль на автомате. В этом вопросе я могу помочь. Пишите, что нужно перевести.


--------------------
If you want to get to the top, you have to start at the bottom
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #3


Новичок
*

Группа: Пользователи
Сообщений: 23
Пол: Мужской

Репутация: -  0  +


Цитата(OCTAGRAM @ 7.06.2019 12:00) *

Надо уметь переводить с Си в Паскаль на автомате.


Я престарелый гуманитарий. Изучением Паскаля я занялся, потому что так захотелось. Пытался Си, но не идет. Какой-то он бардачный, сумбурный и корявый. А Паскаль в отличие от Си более стройный, логичный и понятный.

Изучаю самостоятельно, продираясь через откровенную макулатуру и выискивая ценную информацию.
Спасают, в основном, форумы. Этот сайт, в частности, очень помогает. Правда информация не редко подается слишком сжато. Хотелось бы некой разжеванности.
В интернете полезной информации практически не найти. Поиск выдает совершенно не нужную/неверную информацию (коммерция, что поделаешь). И эта тенденция растет год от года. Жаль.

По теме. О ncurses есть, например, очень не плохой сайт. Но сугубо для Си.
Что-то пытался, но ступорится уже на подключении модуля. Сам ncurses установлен.

Спасибо за отзыв.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #4


Большевик–концептуал
***

Группа: Пользователи
Сообщений: 180
Пол: Мужской
Реальное имя: Иван Левашев
Jabber: octagram@jabber.ru
Skype: i.levashew
QQ: 3152538431
WeChat
Ада: Сторонник
Embarcadero Delphi: Сторонник
Free Pascal: Разработчик
Turbo Pascal: Установлен

Репутация: -  1  +


Надо понимать, что там за кулисами, и 1:1 переписывать. Машинный фундамент у Паскаля и Си общий.

Цитата
Что-то пытался, но ступорится уже на подключении модуля.


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

По ссылке я увидел:

main(int argc,char *argv[])
{
// инициализация (должна быть выполнена
// перед использованием ncurses)
initscr();

// перемещение курсора в стандартном экране y=10 x=30
move(10,30);

printw("Hello world !!!"); // вывод строки
refresh(); // обновить
getch(); // ждём нажатия символа

endwin(); // завершение работы с ncurses
}


Здесь используются функции initscr, move, printw, refresh, getch, endwin.

Смотрим их прототипы на Си:

extern NCURSES_EXPORT(WINDOW *) initscr (void); /* implemented */


NCURSES_EXPORT — судя по названию, это макрос, который навешивает компилятороспецифичные атрибуты, а также они зависят от того, компилируется ли ncurses DLL или какой-то другой код, который от DLL зависит. Внутри этого макроса некий «WINDOW *», то есть, указатель на что-то. В примере на Си, как видно, результат отбрасывается, так что и WINDOW * полноценно можно не переносить. Впрочем, может, и не нужно переносить. Вот в Win32API все структуры достаточно стабильны, и если переписать их с Си на Делфи или Аду, то они сохраняют актуальность, а вот другие програиисты на Си такой дисциплиной не отличаются, и у них и размер, и прочее может без предупреждения меняться.

Короче, пишем:

const
Ncurses = 'ncurses.so';

type
PCursesWindow = Pointer;

function initscr: PCursesWindow; cdecl; external Ncurses name 'initscr';


Идём дальше.

#define move(y,x) wmove(stdscr,(y),(x))


Макрос. Ясно. Значит, на самом деле нужен wmove. Ищем wmove.

extern NCURSES_EXPORT(int) wmove (WINDOW *,int,int); /* implemented */


Мда, названия бы аргументов бы ещё найти. Надо найти реализацию, в реализации-то они точно будут:

NCURSES_EXPORT(int)
wmove(WINDOW *win, int y, int x)


Переписываем на Паскаль:

function wmove(win: PCursesWindow; y, x: Integer): Integer; cdecl; external Ncurses name 'wmove';


Далее нужно понять, что такое stdscr.

#if NCURSES_REENTRANT
NCURSES_WRAPPED_VAR(WINDOW *, stdscr);
#define stdscr NCURSES_PUBLIC_VAR(stdscr())
#else
extern NCURSES_EXPORT_VAR(WINDOW *) stdscr;
#endif



Блин, тяжёлый случай. Я вот вижу этот код первый раз и без понятия, объявлен ли NCURSES_REENTRANT. Лучше бы ему быть объявленным, потому что Паскаль умеет импортировать только процедуры и функции. Переменные и константы умеет экспортировать, но не импортировать. В Win32 API такой фигни нет. Лишний повод понять, до чего же хорошо в Microsoft пишут на Си, кое-кому бы поучиться.

Понадеемся, что объявлен.

Тогда:

function stdscr: PCursesWindow; cdecl; external Ncurses name 'stdscr';


Теперь возвращаемся к макросу:

function move(y, x: Integer): Integer; inline;
begin
Result := wmove(stdscr, y, x);
end;


Идём далее.

extern NCURSES_EXPORT(int) printw (const char *,...)			/* implemented */
GCC_PRINTFLIKE(1,2);


Какие же козлы. Ну как им объяснить, что нельзя использовать varargs. В хороших языках программирования именно ради безопасности его нет, но вдруг приходится обращаться к библиотеке на Си, и тут же там какой-то козёл написал varargs. Вот в Win32 API такого почти не бывает. Я только одну функцию навскидку знаю. До чего же хорош Microsoft.

В языке Ада их нормально ни вызвать, ни реализовать. В Delphi можно вызвать, но нельзя реализовать. В FPC, наверное, тоже.

Так как в Паскале вызвать можно (синтаксис будет cdecl; varargs;), я подумал, может, так и сделать. Но потом решил сделать как надо. А будет лучше заменить printw на addstr, а форматирование, если хочется, через SysUtils.Format всегда доступно.

Итак.

#define addstr(str) waddnstr(stdscr,(str),-1)


Ладно. Макрос, так макрос.

extern NCURSES_EXPORT(int) waddnstr (WINDOW *,const char *,int); /* implemented */


Опять без имён параметров.

NCURSES_EXPORT(int)
waddnstr(WINDOW *win, const char *astr, int n)


Вот это уже можно переписать на Паскаль:

function waddnstr(win: PCursesWindow; const astr: PAnsiChar; n: Integer): Integer; cdecl; external Ncurses name 'waddnstr';


Теперь макрос:

function addstr(const str: PAnsiChar): Integer; inline;
begin
Result := waddnstr(stdscr, str, -1);
end;


Попутно я понял, зачем тут n и -1. Это же длина в байтах. Но это небезопасно, и мы же не хотим, чтоб процессор лишний раз бегал по строке, ведь у нас полноценный язык программирования, способный на такой подвиг, как запомнить длину строки. Значит, лучше будет

#define addnstr(str,n) waddnstr(stdscr,(str),(n))


function addnstr(const str: PAnsiChar; n: Integer): Integer; inline;
begin
Result := waddnstr(stdscr, str, n);
end;


Идём дальше.

#define refresh() wrefresh(stdscr)

extern NCURSES_EXPORT(int) wrefresh (WINDOW *); /* implemented */


Переписываем:

function wrefresh(win: PCursesWindow): Integer; cdecl; external Ncurses name 'wrefresh';

function refresh: Integer; inline;
begin
Result := wrefresh(stdscr);
end;



Дальше getch.

#define getch() wgetch(stdscr)
extern NCURSES_EXPORT(int) wgetch (WINDOW *); /* implemented */


function wgetch: Integer; cdecl; external Ncurses name 'wgetch';

function getch: Integer; inline;
begin
Result := wgetch(stdscr);
end;


И endwin.

extern NCURSES_EXPORT(int) endwin (void); /* implemented */


function endwin: Integer; external Ncurses name 'endwin';


Всё вместе:



const
Ncurses = 'ncurses.so';

type
PCursesWindow = Pointer;

function initscr: PCursesWindow; cdecl; external Ncurses name 'initscr';

function stdscr: PCursesWindow; cdecl; external Ncurses name 'stdscr';

function wmove(win: PCursesWindow; y, x: Integer): Integer; cdecl; external Ncurses name 'wmove';

function move(y, x: Integer): Integer; inline;
begin
Result := wmove(stdscr, y, x);
end;

function waddnstr(win: PCursesWindow; const astr: PAnsiChar; n: Integer): Integer; cdecl; external Ncurses name 'waddnstr';

function addnstr(const str: PAnsiChar; n: Integer): Integer; inline;
begin
Result := waddnstr(stdscr, str, n);
end;

function wrefresh(win: PCursesWindow): Integer; cdecl; external Ncurses name 'wrefresh';

function refresh: Integer; inline;
begin
Result := wrefresh(stdscr);
end;

function wgetch: Integer; cdecl; external Ncurses name 'wgetch';

function getch: Integer; inline;
begin
Result := wgetch(stdscr);
end;

function endwin: Integer; external Ncurses name 'endwin';

// выше была копия
// ниже вспомогательный код и переписанный пример

function addustr(const Str: UTF8String): Integer;
begin
Result := addnstr(PAnsiChar(Str), Length(Str));
end;

begin
// инициализация (должна быть выполнена
// перед использованием ncurses)
initscr;

// перемещение курсора в стандартном экране y=10 x=30
move(10, 30);

addustr('Hello world !!!'); // вывод строки
refresh; // обновить
getch; // ждём нажатия символа

endwin; // завершение работы с ncurses
end.



Скорее всего, это не заработает с первого раза. Я никогда не писал на Паскале под Linux. Но по ошибкам компиляции, думаю, смогу починить.

Добавлено через 17 мин.
Я сейчас прочитал, что ncursesw нужно подключать, а не ncurses.

const
Ncurses = 'ncursesw.so';


--------------------
If you want to get to the top, you have to start at the bottom
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 

 Ответить  Открыть новую тему 
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 





- Текстовая версия 22.10.2019 3:12
500Gb HDD, 6Gb RAM, 2 Cores, 7 EUR в месяц — такие хостинги правда бывают
Связь с администрацией: bu_gen в домене octagram.name