вторник, 19 марта 2019 г.

MiniM. Как получить значения $Y и $X для телнета

Стандарт языка MUMPS не гарантирует, что MUMPS-система имеет возможность всегда корректно самостоятельно вычислить положение каретки (курсора) на экране при работе с телнет-клиентом, в частности после вывода кодов символов и применения мнемоник.

В определении языка MUMPS не содержится строгое определение алгоритма как именно MUMPS система может определить положение каретки (курсора), отображаемого на экране телнет-клиента. Во многих случаях это может зависеть от особенностей используемого телнет-клиента.

При выполнении команд вывода спецсимволов и выполнения мнемоник
w *char
w /MNEMONIC[(params)]
клиентская сторона имеет право менять положение каретки способом, неизвестным серверной стороне.

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

В случае, если прикладной системе необходимо выполнить отсчет от именно текущего положения каретки, необходимо получить корректные значения системных переменных $Y и $X.

Для этого наилучшим способом является запрос этого положения у самого телнет-клиента. В протоколе телнет для этого предусмотрена специальная эскейп-последовательность
ESC [ 6 n
В случае если телнет клиент поддерживает эту команду, он должен ответить эскейп-последовательностью, содержащей координаты каретки в формате
ESC [ YY ; XX R
Для того, чтобы прочитать эскейп-последовательность, пришедшую от телнет-клиента, в MiniM нужно выполнить команду чтения одного символа, и в случае если код символа равен 27, прочитать значение системной переменной $key.

Пример демонстрационной рутины, получающей значения $Y и $X для телнет-клиента отправкой ему запроса положения каретки:
YX
 ; this only for TNT device
 q:$p($io,"|",2)'="TNT" ""
 n ch,ans
 ; send query to telnet client
 w *27,"[6n"
 ; get answer as an escape sequence
 r *ch s ans=$s(ch=27:$key,1:"")
 ; remove unneed symbols
 s ans=$tr(ans,$c(27)_"[R")
 ; return $Y + $X delimited by ;
 q ans
Y
 ; return only $Y
 q $p($$YX,";",1)
X
 ; return only $X
 q $p($$YX,";",2)
Здесь функцией $select выполняется проверка является ли ответ телнет-клиента эскейп-последовательностью.

Приведенный код удаляет неиспользуемые символы ответа с помощью функции $translate. В случае если телнет-клиент не придерживается стандарта и отвечает в ином формате, могут быть использованы регулярные выражения для получения списка числовых последовательностей:
YXRE
 ; this only for TNT device
 q:$p($io,"|",2)'="TNT" ""
 n ch,ans
 ; send query to telnet client
 w *27,"[6n"
 ; get answer as an escape sequence
 r *ch s ans=$s(ch=27:$key,1:"")
 ; return all number sequences as $list structure
 q $zpcres(ans,"\d+","g")
YRE
 ; return only $Y
 q $lg($$YXRE,1)
XRE
 ; return only $X
 q $lg($$YXRE,2)
Также возможна ситуация, что телнет клиент совсем не поддерживает ответ на такой запрос, в этом случае необходимо выполнять чтение символа с таймаутом.

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

Комментариев нет:

Отправить комментарий