Что такое код ncurses_ungetmouse

Содержание

Getch() + ncurses = НЕ ожидает нажатие символа

Linux на удалённой машине, g++, установлен ncurses, код программы такой:

Компилирую g++ с параметром -lncurses.

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

Добавлено через 6 минут
В приведённом выше коде забыл точку с запятой после c = getch(), но в моей программе она есть, так что на это не обращайте внимания.

09.03.2015, 15:13

getch(); ожидает ESC и при этом ест вводимый символ
кусочек программы словаря процедура перевода слов с английского на русский struct types <.

Как реализовать движение символа по экрану? ncurses.h
Здравствуйте, друзья! Нужна помощь с ncurses. Подскажите пожалуйста, как реализовать движение.

Аналог getch или русские буквы в getch
Здравствуйте, уважаемые господа. Существуют ли какие-нибудь аналоги getch () и _getch, которые.

Удаление символа в веб-форме, эмулируя нажатие клавиатуры
Здравствуйте! Помогите, пожалуйста, с вопросом. Как можно удалить из веб-формы одну букву.

scanf не ожидает ввода
Привет всем, я в первый раз на этом форуме. Вопрос следующий: в программе учета бюджета глючит.

10.03.2015, 10:52 2

Для начала нужно инициализировать библиотеку. Ну и в конце деинициализировать соответственно.
Для вывода нужно использовать функции библиотеки.

10.03.2015, 12:25 [ТС] 3 10.03.2015, 12:25

Скрипт ожидает ввода данных
Нужна помощь! Хочу допилить скрипт, который делает настройку таким образом, чтобы после его.

Програма не ожидает ввода пользователя
Доброго времени суток! Суть вопроса в следующем: пользователь должен ввести имя а потом суму.

Консольные приложения на Curses

Приложения с текстовым интерфейсом, работающие в терминале, по-прежнему очень популярны и отлично конкурируют с приложениями с графическим интерфейсом. Mutt , irssi , vim , tmux и многие другие являются незаменимыми в повседневной работе. На CPAN есть модули, позволяющие создавать приложения с текстовым интерфейсом, в том числе модуль Curses , являющийся обвязкой к распространённой C-библиотеке ncurses .

История

Для самых ранних ЭВМ в качестве ввода/вывода информации использовались электромеханические телетайпы (Teletype, или сокращённо TTY), которые позволяли вводить текст с клавиатуры и печатать на бумаге символ за символом, полученные от ЭВМ. Позже телетайп был заменён терминалом, где принтер заменил ЭЛТ-экран, на который на фиксированные позиции можно было выводить символы. Самым первым компьютерным терминалом стал DataPoint 3300, который имел экран, позволяющий выводить 25 рядов по 72 символа. Примечательно, что этот терминал был создан на основе обычных TTL-микросхем, а дальнейшие попытки упростить логику и уменьшить размер внутренней начинки терминала стали одной из побуждающих причин разработки микропроцессоров.

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

Стандартом де-факто на долгие времена стал терминал VT100, созданный компанией DEC в 1978 г. Терминал подключался к вычислительной машине через последовательный интерфейс, позволял выводить 80 или 132 символа в ряд и использовал для кодировки символов стандарт ASCII, а также набор управляющих последовательностей (escape-последовательностей), которые были стандартизованы ANSI в виде стандарта ECMA-48. Escape-последовательности получили своё название от кода клавиши Escape, который предварял набор кодов, определяющих управляющую последовательность. Управляющие последовательности позволяли передвигать курсор, очищать экран, задавать толщину символов или даже делать мигающую строку, на цветных терминалах появилась возможность задавать цвет фона и символа. Например, последовательность кодов ESC[1m задаёт жирный шрифт для последующих выводимых символов, а ESC[0m сбрасывает все установленные атрибуты.

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

С ростом числа терминалов стала возникать проблема с поддержкой всех их видов внутри программ. В 1978 г. Билл Джой, при работе над текстовым радактором vi для Berkeley Unix, выделил код для поддержки разных типов терминалов в отдельную библиотеку под названием termcap, которая стала базой данных описаний существующих терминалов и позволяла реализовывать программы, независимые от типа терминала. Termcap давал возможность программе узнать ширину терминала, правильную последовательность escape-кодов для перемещения курсора и т.д. Вслед за termcap появилась библиотека terminfo, которая являлась улучшенной реализацией termcap с более быстрым доступом к описанию терминала. Именно terminfo получила максимальное распространение в UNIX-системах.

В 1980 г. большую популярность получила игра Rogue, которая дала старт целому жанру rogue-подобных игр, в которой игровой персонаж исследует подземелья, сражается с монстрами и ищет сокровища. Игра для вывода использовала текстовую консоль, монстры обозначались заглавными буквами, коридоры и границы подземелий прорисовывались ASCII-символами | и — . Один из разработчиков, Кен Арнольд, специально для игры создал библиотеку, которая абстрагировалась от работы с конкретным типом терминала, вводила абстрактные понятия окон как матриц символов, забирая на себя все заботы по выводу и обновлению экрана. Библиотека получила название curses («проклятие»), что является каламбуром на словосочетание «cursor optimization». Первоначально curses была основана на termcap. В отличие от termcap, которая фактически являлась текстовой базой данных о свойствах терминалов, curses предоставляла довольно внятное C API.

Позже появились библиотеки pcurses и PDcurses, которые являлись свободными альтернативами BSD curses. В 1991 г. работа над pcurses была продолжена, а в 1993 г. она была переименована в ncurses, что было сокращением от new curses (новая curses), и стала развиваться в рамках проекта GNU. Со временем к ncurses появились обертки для других языков программирования, в том числе и Perl-модуль Curses, который позволяет использовать библиотеку в Perl-программах.

Широкое использование аппаратных терминалов прекратилось после появления видеодисплеев, но тем не менее простота интерфейса и количество существующих для него программ привело к тому, что были созданы эмуляторы терминала — программы, которые эмулировали видеотерминал внутри другой видео системы, например, X Window. Это позволяло продолжать использовать программы, заточенные для работы в терминале, и в других системах. Наиболее популярные графические эмуляторы терминала — xterm, rxvt, а также современные gnome-terminal и konsole.

Использование консольных приложений с текстовым интерфейсом актуально и на сегодняшний день. Такие приложения как top, vim, emacs, mutt, irssi, moc, midnight commander используют многие и просто не представляют себе другой альтернативы. Терминальное приложение может работать поверх последовательных линий и поверх сети на очень низких скоростях, которые недоступны VNC или RDP. А в отличие от веб-интерфейсов, не требуют от клиента наличия гигабайтов оперативной памяти и многоядерных процессоров для того, чтобы удовлетворить системным требованиям современных браузеров.

Устройство терминала

Поскольку исторически терминалы являлись внешними устройствами с посимвольным обменом информации по последовательным линиям, то в UNIX-системах каждому терминалу соответствовал файл устройства вида /dev/tty* . Системные консоли были доступны на /dev/tty[0..NN] , последовательные порты на /dev/ttyS[0..NN] и т.д. (вариация названия зависела от конкретной реализации UNIX-системы). Для каждого такого устройства существует возможность установки скорости обмена, управляющих последовательностей и других настроек. Текущие настройки любого такого устройства можно увидеть с помощью утилиты stty :

Для процессов, которым необходима работа с терминалом, не связанным с каким-то физическим устройством, создаются так называемые псевдотерминалы. В современных UNIX-системах для эмулятора терминала по запросу создаётся файл устройства псевдотерминала в файловой системе devpts, например /dev/pts/0 , c которым ассоциируются стандартные файловые дескрипторы ввода/вывода STDIN , STDOUT и STDERR запускаемых эмулятором дочерних процессов. Эмулятор терминала определяет, каким будет тип терминала, каков будет размер экрана (количество строк и символов в строке) и другие параметры. Для запущеного же в псевдотерминале приложения нет никакого отличия работает ли он в псевдотерминале или на любом другом реальном терминале.

Perl Curses

Perl-модуль Curses является низкоуровневой обвязкой к С-библиотеке ncurses. Из существующей POD-документации практически невозможно понять, как программировать приложения на Curses , поскольку подразумевается, что вы будете использовать документацию по самой C-библиотеке ncurses.

Помимо Curses , на CPAN существуют ещё несколько дистрибутивов, которые позволяют разрабатывать приложения с текстовым интерфейсом. Часть их используют Curses , но имеют более высокоуровневый интерфейс, удобный для разработки. Это такие модули как Curses::UI и Curses::Toolkit . Есть также модули, которые вообще не привязаны к ncurses, например, Tickit . Если вы планируете создание сложных консольных приложений, где будут активно использоваться примитивы окон, диалогов, меню, форм, функции обратного вызова на события, то эти модули, вероятно, наиболее лучший выбор для использования. Если же стоит задача создания тривиального позиционного вывода информации, как, например, в приложении top , то использование Curses может быть целесообразнее.

Библиотека Curses работает с экраном, который представляется в виде прямоугольной матрицы, каждый элемент которой связан с позицией на экране для вывода символа. Начало координат, позиция (0,0), задаёт левый верхний угол экрана. На экране могут быть заданы одно или несколько окон и субокон — прямоугольных областей, для которых определены свои свойства вывода.

Илон Маск рекомендует:  Создание дистрибутива приложениямастер установки

Старт с Curses

Несколько функций библиотеки инициализируют работу приложения в текстовом режиме:

initscr — функция инициирует режим curses, создаёт окно по умолчанию, производит очистку экрана и устанавливает текущую позицию курсора в левый верхний угол (0,0);

cbreak и raw — функции отключают буферизованный ввод, и приложение сразу получает информацию о нажатых клавишах, при этом raw также перехватывает и специальные сочетания клавиш, такие как Ctrl+C и Ctrl+Z ;

echo и noecho — включают и отключают режим «эха», т.е. вывод на экран вводимых с клавиатуры символов.

Библиотека Curses имеет ОО-интерфейс, в этом случае вместо инициализации окна по умолчанию через initscr можно использовать вызов new :

Многие функции С-библиотеки ncurses имеют различные вариации одной и той же функции с префиксами w, mv, и wmv. Префикс подразумевает, что появляется какой-либо дополнительный параметр: w — объект окна, mv — координаты y, x позиции курсора. В Perl-библиотеке Curses такие вариации функций были объединены в одну, но с опциональными параметрами окна и координат:

Такие функции получили название унифицированных, и их можно использовать как методы при программировании с использованием ОО-интерфейса. В документации Curses приведён полный список функций и указано, какие из них являются унифицированными, а какие — нет. Во всех последующих примерах будет использоваться ОО-интерфейс, поэтому если используется прямой вызов функций, то это явно подразумевает, что функция не является унифицированной.

Рассмотрим пример приложения, которое выводит сообщение в центр экрана, ожидает ввод пользователя и завершает работу:

Приложение создаёт окно. Метод keypad со значением истины в параметре включает обработку специальных клавиш, таких как F1 , F2 и т.д. Метод getmaxyx позволяет определить максимальные значения координат на экране, т.е. размер текущего терминала. Метод addstr позволяет вывести строку по заданным начальным координатам. Метод refresh отображает всё то, что мы вывели на экран. Метод getch ожидает нажатия клавиши и возвращает введённый символ. Функция endwin завершает режим curses, возвращая предыдущее содержимое экрана.

Окна и субокна

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

Для создания нового окна используется функция newwin :

где $rows , $cols — определяют высоту и ширину окна, а $y , $x — положение окна на экране.

Окна могут перекрываться, при этом в месте пересечения будет отображаться контент того окна, которое было обновлено последним. Если требуется создать окно внутри другого окна, то можно использовать функцию создания субокна subwin или derwin :

Отличие subwin и derwin в том, что в derwin координаты субокна задаются относительно верхнего левого угла родительского окна.

Для удаления окна или субокна используется функция delwin

Окно можно перемещать по экрану с помощью функции mvwin ( mvderwin — для субкона):

Очистить содержимое окна можно с помощью функции clear :

Существует возможность отобразить границы окна с помощью функции box :

где первый параметр определяет символ для вертикальных линий, а второй — горизонтальных. Если используется значение 0 (или undef ), то используются символы границ по умолчанию.

Если требуется задать различные символы для всех сторон и углов окна, то можно воспользоваться функцией border :

Атрибуты

Для каждого выводимого символа может быть установлены атрибуты, в том числе:

  • A_BOLD — режим повышенной яркости;
  • A_NORMAL — нормальный режим яркости;
  • A_DIM — режим пониженной яркости;
  • A_UNDERLINE — подчёркнутый текст;
  • A_REVERSE — инверсный текст;
  • A_BLINK — мерцающий текст;
  • A_INVIS — невидимый текст.

Не все терминалы поддерживают указанные атрибуты (как правило, A_NORMAL совпадает с A_DIM , а некоторые атрибуты могут заменяться цветовым выделением).

Установить конкретный атрибут или набор атрибутов можно функцией attron :

После чего при выводе текста в данное окно начинают применяться указанные атрибуты. Также для установки атрибутов можно использовать функцию attrset , но данная функция сбросит все другие атрибуты, которые были до этого установлены:

Для отключения определённых атрибутов используется функция attroff :

Цвета

Многие терминалы имеют поддержку цвета. Для того, чтобы определить, поддерживает ли терминал цвет, можно использовать функцию has_colors . Если поддержка цветов в терминале присутствует, то перед работой с цветовой палитрой требуется инициализировать цвета вызовом функции start_color :

Для создания палитры из двух цветов (цвет фона и цвет текста) используется функция init_pair :

Установить указанную палитру цветов для вывода можно всё той же функцией attron :

Цветовая палитра ограничена 16 цветами, причём базовых цветов только 8, а дополнительные цвета получаются за счёт использования повышенной яркости ( A_BOLD ):

Существует возможность переопределить любой базовый цвет с помощью функции init_color , которая для заданного базового цвета устанавливает значения интенсивности соответственно красного, зелёного и синего цветов в диапазоне от 0 до 1000:

Не все терминалы поддерживают такую возможность, поэтому перед изменением цветов палитры следует выяснить, присутствует ли такая возможность в текущем терминале, с помощью функции can_change_color .

Обработка ввода

Для получения значения введённого символа используется метод getch . В случае если была активирована обработка специальных клавиш ( F1 , PgUp , PgDown и т.д.) с помощью keypad(1) , то getch возвращает числовой код специальной клавиши, например, значение 338 для PgDown . Если же обработка специальных клавиш отключена, то getch() вернёт лишь первый код из escape-последовательности клавиши.

Если на вводе оказывается символ Unicode, то getch воспринимает лишь первый байт последовательности. Соответственно для обработки Unicode-символа, имеющего внутреннее представление из двух байт, потребуется два последовательных вызова getch :

В Curses определены константы для функциональных клавиш, а также функция KEY_F , возвращающая код F* -клавиш. Названия констант можно найти в документации Curses , все они имеют префикс KEY_ .

В С-библиотеке ncursesw, есть функция get_wch , которая может обрабатывать ввод «широких» символов, но, к сожалению, она не перенесена в Perl-обвязку Curses .

С помощью функции halfdelay можно указать, какое время (в десятых долях секунды) getch должен ожидать ввода символа. Если после истечения таймаута клавиша не нажата, getch вернёт значение ERR (-1).

Для получения строки символов до символа переноса строки (или EOF ) может использоваться функция getstr :

Управление курсором

Получить текущие координаты курсора можно с помощью getyx :

Если вызывается какая-либо функция вывода на экран без указания координат, то вывод производится начиная с текущей позиции курсора. Курсор можно передвигать по экрану с помощью функции move :

Очистка экрана

Существует возможность очистки экрана или его части. Под очисткой понимается заполнение его пробельными символами.

Функция clear очищает окно целиком:

Функции clrtoeol и clrtobot очищают экран, начиная с текущей позиции курсора до конца строки и конца окна соответственно:

Функции deleteln и delch удаляют строку и символ соответственно на текущей позиции курсора:

Функция insdelln вставляет указанное число пустых строк, начиная с текущей позиции курсора (или удаляет, если аргумент отрицательный).

Обработка событий мыши

Curses позволяет обрабатывать события, возникающие при использовании мыши, такие как нажатие клавиш и перемещение указателя. Перед началом обработки действий мыши необходимо задать маску событий, которые будет фиксировать программа. Делается это с помощью функции mousemask :

Фиксировать наличие действий, произведённых мышью, можно всё той же функцией getch . Функция getmouse позволяет получить структуру произошедшего события, куда входит информация об идентификаторе устройства мыши (их может быть несколько), координатах мыши в трёх измерениях и непосредственно типе события.

Изменение размера экрана

Поскольку зачастую консольные приложения запускаются внутри графического окна эмулятора терминала, то во время работы приложения может происходить изменение размеров экрана, когда пользователь растягивает окно терминала или наоборот уменьшает. Для этих случаев существует сигнал SIGWINCH , которым эмулятор терминала оповещает запущенные приложения об изменении размера экрана.

Библиотека Curses устанавливает обработчик этого сигнала и пытается адаптировать существующие окна под новый размер экрана. Конечно не всегда это может быть выполнено корректно, поэтому для пользовательского приложения реализована возможность получить оповещение об произошедшем изменении размеров экрана — функция getch возвращает значение KEY_RESIZE :

Не стоит переопределять обработчик сигнала SIGWINCH в коде приложения, поскольку это приведёт к завершению работы приложения после получения сигнала.

Панели, меню и формы

В рамках проекта ncurses существуют дополнительные библиотеки, расширяющие возможности ncurses:

  • Панели. Представляют собой окна, которые могут перекрывать друг друга, при этом можно указать в каком порядке следуют панели, т.е. указывается третье измерение — глубина. Панели можно скрывать, отображать, перемещать наверх в стопке.
  • Меню. Позволяет реализовывать внутри ваших приложений привычные меню с поддержкой вложенности.
  • Формы. Позволяют создавать привычные элементы для ввода данных в виде текстовых полей, которые можно заполнять и редактировать.

Подробное описание этих расширений может стать темой для ещё одной статьи, но вполне возможно, если приложение требует подобного функционала, стоит посмотреть на более мощные альтернативы на CPAN, например, Curses::UI или Tickit .

Введение в ncurses на C++

В универе задали лабораторную: реализовать элемент интерфейса “всплывающее окно с сообщением” под DOS на C++, используя ООП подход. Ну спасибо тебе за актуальность, дорогой универ, нынче DOS и Turbo Vision наше всё, такой ценный опыт… К счастью, преподаватель отнёсся с пониманием и разрешил использовать современную кроссплатформенную библиотеку ncurses для рисования псевдографики, о ней я сегодня и расскажу.

Что такое ncurses и где оно обитает

Ncurses (произносится “энкёрсиз”) – это библиотека, которая существенно упрощает создание интерфейсов на псевдографике и позволяет при разработке вообще не думать о том, например, какую экранирующую последовательность символов нужно послать терминалу для того, чтобы текст выводился ^[[ 0 ; 31 ; 40 mКРАСНЫМ цветом. Мало того, что эти закорючки тяжело осмыслить, так они еще и для разных терминалов разные бывают. Вообще, чтобы как-то облегчить жизнь, разработчики UNIX решили хранить в специальном файле termcap (а в будущем terminfo) все те возможности, которые предоставляет конкретный терминал. Этот файл позволяет приложениям смотреть, какие экранирующие последовательности можно посылать, в него смотрит и библиотека ncurses, избавляя пользователя-программиста от написания лишнего кода для, так скажем, кросс-терминальности. Пожалуй, самыми известными программами, в которых для интерфейса используется ncurses, являются htop, GNU Midnight Commander и инструмент графической настройки конфигурации ядра Linux, хоть с какой-то из них сталкивался каждый.

Как установить

Linux

Windows

Под Windows и DOS есть PDCurses, которая практически полностью совместима с ncurses. Одной строчкой не ставится, вот тут есть вся необходимая информация по ней.

Илон Маск рекомендует:  Описание PHP и MySQL

Написание программ

При компиляции программ важно не забывать приписать флаг -lncurses , чтобы всё нормально залинковалось. Разберем простейшую программу с комментариями и пояснениями, и заглянем глубже.

Hello World!

Вот тот странный момент с printw и refresh , да, сейчас объясню. Дело в том, что для производительности будет лучше, если программист сначала сделает все необходимые операции по изменению данных на воображаемом экране (в буффере), и только потом (после refresh ) на настоящем экране обновятся те участки, которые действительно изменились в конечном итоге.

Инициализация

Помимо initscr есть и другие функции, которые можно повызывать для кастомизации текущей сессии. Рассмотрим лишь некоторые из них, чтобы статья не превратилась в документацию.

raw и cbreak

Обычно, терминал буфферит символы, которые набирает пользователь до переноса строки, но большинству программ набираемые символы требуются сразу же во время их набора. Указанные выше функции позволяют управлять буфферизацией. Разница заключается в том, как будут обрабатывается управляющие последовательности вроде CTRL-Z и CTRL-C. В raw режиме они попадают в программу, не генерируя сигналов, а в cbreak режиме они интерпретируются драйвером терминала и генерируют соответствующие им сигналы.

echo и noecho

Эти функции контролируют вывод напечатанного на экран. noecho отключает вывод, echo наоборот включает. Обычно в программах используется noecho и вывод производится другими, более гибкими средствами.

keypad

Позволяет чтение клавиш F1, F2, стрелок и тд. Чтобы включить для стандартного экрана, вызывается как keypad (stdscr, TRUE) .

curs_set;

Включает и отключает отображения курсора на экране, чтобы отключить курсор вызывается curs_set (FALSE)

Цвета

В ncurses есть удобный механизм для работы с цветами. В первую очередь, для того, чтобы проверить, поддерживается ли в текущем терминале функция цветов вообще, есть функция has_colors () , если вернулась истина, то start_color() и погнали. Важное понятие в ncurses – это цветовые пары, они определяют, каким цветом мы выводим и на каком фоне. Парам присваивают целочисленные значения:

Мы сделали цветовую пару, которая пишет красным по черному, кстати, если лень писать константы, можно писать просто соответствующие им циферки:

Цвет Циферка
COLOR_BLACK
COLOR_RED 1
COLOR_GREEN 2
COLOR_YELLOW 3
COLOR_BLUE 4
COLOR_MAGENTA 5
COLOR_CYAN 6
COLOR_WHITE 7

Ну а если стандартные цвета недостаточно кислотные для вашей хакерской проги, то можно сделать свои! Вот так это делается:

RGB-значения лежат в интервале от 0 до 1000. Если что-то пошло не так, или ваш терминал не умеет работать с цветами, то функция init_color вернет ERR .

Окна – это воображаемые экраны, определенные в curses. Окно в данном контексте не означает то окно с рамочкой в Turbo Pascal, которое можно таскать по экрану. При инициализации ncurses, создается воображаемое окно stdscr , которое является представлением открытого терминала (настоящего экрана) размером с этот терминал. На это окно уже можно сразу выводить строки или другие окна, передавать его как параметр в функцию и тд.

Данный код выведет строку в stdscr в текущей позиции курсора. Аналогично вызов refresh , работает только с stdscr .

После создания нового окна, для выполнения таких же действий с ним, а не с stdscr , вызывают функции, которые начинаются на w и принимают как параметр окно, с которым производятся действия, вот так для окна с именем win :

Окно с именем win имеется в виду, что это имя указателя на память данных с окном в куче. Такая конвенция именования соблюдается во всех функциях, которые можно применить и к stdscr , и к другим окнам.

Таким образом, библиотека предоставляет разработчику все необходимые механизмы для создания интерфейсов в терминале, код своей сделанной лабораторной с комментариями я привел ниже.

Использование ncurses в PHP

Как программист и веб-разработчик, вы наверное время от времени пишете программы на php для администрирования сайта из консоли. Средствами языка можно сделать только выводящую/читающую из консоли программу, но с помощью библиотеки ncurses можно создать консольную утилиту с довольно сложным внешним видом, которая будет одинаково выглядеть в разных видах терминалов.

PHP очень гибок и расширяем, с его помощью можно создавать скрипты, которыми можно заменить аналогичные на других языках (Perl/bash-скрипты и прочее). Функциональность ncurses поразительна и действительно выводит возможности работы с терминальным php-приложением на новый уровень.

Предназначение статьи — дать вам «толчок» в сфере написания консольных утилит на php, которые будут использовать возможность этой библиотеки. Я собираюсь показать только самое важное, относящееся к самой библиотеке, и надеюсь дать вам базу для использования ncurses в вашем приложении.

Для кого предназначена статья

Изучаемые темы

Определения

От автора

Документация по функциями ncurses в php сильно ограничена. Некоторые функции использованные в данной статье отсутствуют на официальном сайте. Приложения с ncurses следуют стилю программирования на C, как если бы они были настоящими программами, а не скриптами.

Если у вас есть опыт программирования в C или C++, возможно вы уже знакомы с ncurses и можете представить, каким полезным инструментом может быть ncurses при использовании с интерпретируемым языком, таким как PHP.

Что нужно знать

Вам нужен PHP, скомпилированный с опцией -with-ncurses на unix-подобной системе. Не все терминалы поддерживают цветной вывод, поэтому я не стал включать использование цветов в статью.

Знайте, что вам может понадобиться «сбрасывать» ваш терминал командной reset. Если возникнет какая-либо ошибка и ncurses_end() не будет вызван, то ваш терминал будет работать неправильно.

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

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

Простой пример с окнами

Сначала создадим основное окно, которое будет использовать всё доступное пространство. Потом добавим меньшее окно посередине экрана и поместим туда строчку текста. Чтобы получилось вот так:

Начать нужно с вызова ncurses_init(); , чтобы перейти в режим ncurses. Без этого при вызове функций библиотеки PHP будет падать с ошибкой.

Сценарий для вывода двух окон и строки

Попробуйте изменить размеры окна и запустить скрипт ещё раз. Основное окно опять будет занимать ровно всё пространство.

Теперь вы может захотите увидеть какое-нибудь действо при нажатий на клавишу, или вы хотите сделать возможность выхода из приложения при нажатии на какую-либо кнопку. Я предпочитаю использовать для этого esc (27 ascii-код).
Чтобы добавить возможность выхода по нажатию на ESC, добавьте данный код вместо $pressed = ncurses_getch();

Теперь если вы нажмёте esc, программа завершится, в ином случае ascii-код нажатой клавиши будет отображён в маленьком окне.

Можно добавить заголовок, поместив код перед вызовом ncurses_refresh(); :

Вы не ограничены режимом REVERSE (цвет и фон меняются местами), также есть DIM, UNDERLINE и другие.

Можно повысить комфорт, добавив интерактивный выбор из меню.

Создаём меню

Многие программы имеют меню и возможность выбора из него. В прошлом на «чистом» PHP мы могли лишь выводить список вариантов, и давать возможность ввести номер нужного. Такой неудобный выбор одного варианта можно заменить более интуитивно понятным.

Сценарий вывода меню с возможностью выбора

По получившемуся меню можно перемещаться кнопками со стрелками и выходить с помощью esc.

Сейчас вы возможно думаете о консольных приложениях, которые вы можете создать, зная только несколько выше использованных функций. Далее по тексту мы создадим полезное приложение, которое будет стартовой точкой дальнейшей разработки.

Всё вместе

На сайте php.net перечислены 119 функций библиотеки ncurses. В нижеприведённой таблице есть список использованных функций и ссылки на документацию. Замечу, что четыре из перечисленных функций отсутствуют в официальной документации. (прим. переводчика: в настоящий момент все функции содержаться в документации на php.net, правда без подробного описания).

Функция Описание Документация
ncurses_init Инициализирует ncurses www.php.net/manual/en/function.ncurses-init.php
ncurses_newwin Создаёт новое окно www.php.net/manual/en/function.ncurses-newwin.php
ncurses_getmaxyx(resource window, int
return Y, int return X);
Записывает в переменные X и Y максимальных размеров терминала
ncurses_border Рисует рамку вокруг основного окна www.php.net/manual/en/function.ncurses-border.php
ncurses_refresh Обновляет основное окно. Для перерисовки второстепенных окон используйте ncurses_wrefresh www.php.net/manual/en/function.ncurses-refresh.php
ncurses_attron Применяет атрибут к выводимому тексту www.php.net/manual/en/function.ncurses-attron.php
ncurses_attroff Отключает применение атрибута www.php.net/manual/en/function.ncurses-attroff.php
ncurses_mvaddstr Выводит строку www.php.net/manual/en/function.ncurses-mvaddstr.php
ncurses_wborder (resource window, int
left, int right, int top, int bottom, int tl_corner, int tr_corner, int
bl_corner, int br_corner);
Рисует рамку для второстепенного окна.
ncurses_wattron(resource window, int
attribute)
Идентично ncurses_attron, только применяется для окна window
ncurses_mvwaddstr Помещает строку во второстепенное окно www.php.net/manual/en/function.ncurses-mvwaddstr.php
ncurses_wattroff (resource window, int
attribute)
Идентично ncurses_wattroff, только применяется для окна window
ncurses_wrefresh Перерисовывает второстепенное окно. www.php.net/manual/en/function.ncurses-wrefresh.php
ncurses_getch Ждёт ввода с клавиатуры или мыши. www.php.net/manual/en/function.ncurses-getch.php

Улучшенный traceroute

Сейчас создадим действительно полезную программу: traceroute с выводом whois-информации о каждом прыжке.

Этот скрипт запускает traceroute до zend.com (макс 10 прыжков) и показывает результаты в одном окне. По элементам можно переходить с помощью стрелок. При нажатии на enter информация о данном ip будет показана в нижнем окне. По нажатию на esc произойдёт завершение работы программы.

В заключение

Выше изложенный код довольно прост и может послужить базой для вашего приложения с использованием ncurses.

Мы не рассматривали использование мыши, цветов и многих других функций вывода.

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

SYNOPSIS¶

typedef unsigned long mmask_t;

DESCRIPTION¶

mousemask¶

As a side effect, setting a zero mousemask may turn off the mouse pointer; setting a nonzero mask may turn it on. Whether this happens is device-dependent.

Mouse events¶

Name Description
BUTTON1_PRESSED mouse button 1 down
BUTTON1_RELEASED mouse button 1 up
BUTTON1_CLICKED mouse button 1 clicked
BUTTON1_DOUBLE_CLICKED mouse button 1 double clicked
BUTTON1_TRIPLE_CLICKED mouse button 1 triple clicked
BUTTON2_PRESSED mouse button 2 down
BUTTON2_RELEASED mouse button 2 up
BUTTON2_CLICKED mouse button 2 clicked
BUTTON2_DOUBLE_CLICKED mouse button 2 double clicked
BUTTON2_TRIPLE_CLICKED mouse button 2 triple clicked
BUTTON3_PRESSED mouse button 3 down
BUTTON3_RELEASED mouse button 3 up
BUTTON3_CLICKED mouse button 3 clicked
BUTTON3_DOUBLE_CLICKED mouse button 3 double clicked
BUTTON3_TRIPLE_CLICKED mouse button 3 triple clicked
BUTTON4_PRESSED mouse button 4 down
BUTTON4_RELEASED mouse button 4 up
BUTTON4_CLICKED mouse button 4 clicked
BUTTON4_DOUBLE_CLICKED mouse button 4 double clicked
BUTTON4_TRIPLE_CLICKED mouse button 4 triple clicked
BUTTON5_PRESSED mouse button 5 down
BUTTON5_RELEASED mouse button 5 up
BUTTON5_CLICKED mouse button 5 clicked
BUTTON5_DOUBLE_CLICKED mouse button 5 double clicked
BUTTON5_TRIPLE_CLICKED mouse button 5 triple clicked
BUTTON_SHIFT shift was down during button state change
BUTTON_CTRL control was down during button state change
BUTTON_ALT alt was down during button state change
ALL_MOUSE_EVENTS report all button state changes
REPORT_MOUSE_POSITION report mouse movement

getmouse¶

ungetmouse¶

wenclose¶

wmouse_trafo¶

mouse_trafo¶

mouseinterval¶

has_mouse¶

Note that mouse events will be ignored when input is in cooked mode, and will cause an error beep when cooked mode is being simulated in a window by a function such as getstr that expects a linefeed for input-loop termination.

RETURN VALUE¶

mousemask returns the mask of reportable events.

mouseinterval returns the previous interval value, unless the terminal was not initialized. In that case, it returns the maximum interval value (166).

wenclose and wmouse_trafo are boolean functions returning TRUE or FALSE depending on their test result.

PORTABILITY¶

SVr4 curses had support for the mouse in a variant of xterm. It is mentioned in a few places, but with no supporting documentation:

    the “libcurses” manual page lists functions for this feature which are prototyped in curses.h:

the “terminfo” manual page lists capabilities for the feature

  • the interface made assumptions (as does ncurses) about the escape sequences sent to and received from the terminal.
  • For instance the SVr4 curses library used the get_mouse capability to tell the terminal which mouse button events it should send, passing the mouse-button bit-mask to the terminal. Also, it could ask the terminal where the mouse was using the req_mouse_pos capability. Those features required a terminal which had been modified to work with curses. They were not part of the X Consortium’s xterm.

    When developing the xterm mouse support for ncurses in September 1995, Eric Raymond was uninterested in using the same interface due to its lack of documentation. Later, in 1998, Mark Hesseling provided support in PDCurses 2.3 using the SVr4 interface. PDCurses, however, does not use video terminals, making it unnecessary to be concerned about compatibility with the escape sequences.

    The feature macro NCURSES_MOUSE_VERSION is provided so the preprocessor can be used to test whether these features are present. If the interface is changed, the value of NCURSES_MOUSE_VERSION will be incremented. These values for NCURSES_MOUSE_VERSION may be specified when configuring ncurses:

    The order of the MEVENT structure members is not guaranteed. Additional fields may be added to the structure in the future.

    Under ncurses(3NCURSES), these calls are implemented using either xterm’s built-in mouse-tracking API or platform-specific drivers including

    • Alessandro Rubini’s gpm server
    • FreeBSD sysmouse
    • OS/2 EMX

    If you are using an unsupported configuration, mouse events will not be visible to ncurses(3NCURSES) (and the mousemask function will always return ).

    If the terminfo entry contains a XM string, this is used in the xterm mouse driver to control the way the terminal is initialized for mouse operation. The default, if XM is not found, corresponds to private mode 1000 of xterm:

    The mouse driver also recognizes a newer xterm private mode 1006, e.g.,

    The z member in the event structure is not presently used. It is intended for use with touch screens (which may be pressure-sensitive) or with 3D-mice/trackballs/power gloves.

    The ALL_MOUSE_EVENTS class does not include REPORT_MOUSE_POSITION. They are distinct. For example, in xterm, wheel/scrolling mice send position reports as a sequence of presses of buttons 4 or 5 without matching button-releases.

    Mouse events under xterm will not be detected correctly in a window with its keypad bit off, since they are interpreted as a variety of function key. Your terminfo description should have kmous set to “\E[M” (the beginning of the response from xterm for mouse clicks). Other values for kmous are permitted, but under the same assumption, i.e., it is the beginning of the response.

    Because there are no standard terminal responses that would serve to identify terminals which support the xterm mouse protocol, ncurses assumes that if kmous is defined in the terminal description, or if the terminal description’s primary name or aliases contain the string “xterm”, then the terminal may send mouse events. The kmous capability is checked first, allowing the use of newer xterm mouse protocols such as xterm’s private mode 1006.

    Что такое код ncurses_ungetmouse

    (PHP 4 >= 4.2.0, PHP 5)

    ncurses_ungetmouse — Pushes mouse event to queue

    Description bool ncurses_ungetmouse ( array mevent )

    This function is EXPERIMENTAL . The behaviour of this function, the name of this function, and anything else documented about this function may change without notice in a future release of PHP. Use this function at your own risk.

    Pushes a KEY_MOUSE event onto the unput queue and associates with this event the given state sata and screen-relative character cell coordinates, specified in mevent .

    Parameters

    An associative array specifying the event options:

    «id» : Id to distinguish multiple devices

    «x» : screen relative x-position in character cells

    «y» : screen relative y-position in character cells

    iOS Manual Pages

    • Table of Contents
    • Download Sample Code
    Warning
    ADC Home>Reference Library> Reference > Mac OS X > Mac OS X Man Pages

    This document is a Mac OS X manual page. Manual pages are a command-line technology for providing documentation. You can view these manual pages locally using the man(1) command. These manual pages come from many different sources, and thus, have a variety of writing styles.

    For more information about the manual page format, see the manual page for manpages(5).

    Sending feedback…

    We’re sorry, an error has occurred.

    Please try submitting your feedback later.

    Thank you for providing feedback!

    Your input helps improve our developer documentation.

    Что такое код ncurses_ungetmouse

    ncurses_ungetmouse — Pushes mouse event to queue

    Description bool ncurses_ungetmouse ( array mevent)

    This function is EXPERIMENTAL . The behaviour of this function, the name of this function, and anything else documented about this function may change without notice in a future release of PHP. Use this function at your own risk.

    «id» : Id to distinguish multiple devices

    «x» : screen relative x-position in character cells

    «y» : screen relative y-position in character cells

    «z» : currently not supported

    «mmask» : Mouse action

    ncurses_ungetmouse() returns FALSE on success, otherwise TRUE .

    sylt / ncurses_mouse_movement.c

    Warning
    // I had problems getting mouse movement events working in ncurses, but after
    // some research, it seems as if this is how you can do it. The magic is in the
    // printf(«\033[?1003h\n») which was the missing piece in the puzzle for me
    // (see console_codes(4) for more information). 1003 means here that all events
    // (even position updates) will be reported.
    //
    // This seems to work in at least three X-based terminals that I’ve tested:
    // xterm, urxvt and gnome-terminal. It doesn’t work when testing in a «normal»
    // terminal, with GPM enabled. Perhaps something for the next gist version? :)
    # include curses.h >
    # include stdio.h >
    int main ()
    <
    initscr ();
    cbreak ();
    noecho ();
    // Enables keypad mode. This makes (at least for me) mouse events getting
    // reported as KEY_MOUSE, instead as of random letters.
    keypad (stdscr, TRUE );
    // Don’t mask any mouse events
    mousemask (ALL_MOUSE_EVENTS | REPORT_MOUSE_POSITION, NULL );
    printf ( » \033 [?1003h \n » ); // Makes the terminal report mouse movement events
    for (;;) <
    int c = wgetch (stdscr);
    // Exit the program on new line fed
    if (c == ‘ \n ‘ )
    break ;
    char buffer[ 512 ];
    size_t max_size = sizeof (buffer);
    if (c == ERR) <
    snprintf (buffer, max_size, » Nothing happened. » );
    >
    else if (c == KEY_MOUSE) <
    MEVENT event;
    if ( getmouse (&event) == OK) <
    snprintf (buffer, max_size, » Mouse at row= %d , column= %d bstate=0x %08lx » ,
    event. y , event. x , event. bstate );
    >
    else <
    snprintf (buffer, max_size, » Got bad mouse event. » );
    >
    >
    else <
    snprintf (buffer, max_size, » Pressed key %d ( %s ) » , c, keyname (c));
    >
    move ( 0 , 0 );
    insertln ();
    addstr (buffer);
    clrtoeol ();
    move ( 0 , 0 );
    >
    printf ( » \033 [?1003l \n » ); // Disable mouse movement events, as l = low
    endwin ();
    return 0 ;
    >

    This comment has been minimized.

    Copy link Quote reply

    GaryCot commented Nov 1, 2020 •

    Best concise example of curses mouse code I have seen! Thanks for posting!
    Question for you.. where did you find out what strings to printf to the xterm to turn on and off mouse movement reporting?

    This comment has been minimized.

    Copy link Quote reply

    TReed0803 commented Jan 14, 2020

    Thanks, this solved my troubles with ncurses mouse movement events.
    Another quick tip is to set mouseinterval(0); to get snappier button press/release events.

    ncurses_ungetmouse

    (PHP 4 >= 4.2.0, PHP 5 = 1.0.0)

    ncurses_ungetmouse — Pushes mouse event to queue

    Описание

    Эта функция является ЭКСПЕРИМЕНТАЛЬНОЙ. Поведение этой функции, ее имя и относящаяся к ней документация могут измениться в последующих версиях PHP без уведомления. Используйте эту функцию на свой страх и риск.

    Pushes a KEY_MOUSE event onto the input queue and associates with this event the given state data and screen-relative character cell coordinates, specified in mevent .

    Список параметров

    An associative array specifying the event options:

    «id» : Id to distinguish multiple devices

    «x» : screen relative x-position in character cells

    «y» : screen relative y-position in character cells

    «z» : currently not supported

    «mmask» : Mouse action

    Возвращаемые значения

    Returns FALSE on success, TRUE otherwise.

    Илон Маск рекомендует:  Что такое код setusercharsize
    Понравилась статья? Поделиться с друзьями:
    Кодинг, CSS и SQL