Справочник программиста на персональном компьютере фирмы IBM. Клавиатура - Ожидать ввод символа и не выводить его на экран

ОГЛАВЛЕНИЕ

     3.1.3 Ожидать ввод символа и не выводить его на экран.


   Обычно  вводимые символы выводятся на экран, чтобы было видно,
что напечатано.  Но иногда  автоматическое  эхо на экране нежела-
тельно.  Например, выбор пункта меню по нажатию клавиши.   Иногда
надо сначала проверить вводимые  символы  на ошибку перед выводом
на экран.  В частности, любая программа, обрабатывающая расширен-
ные коды, должна избегать  автоматического  эха, так как при этом
первый  байт  этих  кодов (ASCII 0) будет  выводиться  на  экран,
вставляя пробелы между символами.

   Высокий уровень.


   Функция Бейсика INKEY$ не дает эхо на терминал. Она возвращает
строку  длиной  1 байт для символов ASCII и  длиной 2  байта  для
расширенных кодов. INKEY$ не ожидает нажатия клавиши, до тех пор,
пока она не помещена в цикл, в котором ожидается нажатие клавиши.
Цикл работает, обращаясь к  INKEY$, а затем присваивая возвращае-
мую  им строку переменной, в данном случае C$.  Если  клавиша  не
была нажата, то INKEY$  возвращает  нулевую  строку, т.е.  строку
длиной ноль символов, которая обозначается двумя знаками кавычек,
между которыми ничего нет (""). До тех пор пока INKEY$ возвращает
"" - цикл повторяется: 100 C$=INKEY$:IF C$="" THEN 100.
   В нижеприведенном примере предполагается, что вводимые символы
выбирают одну из  возможностей  меню  и  каждый  выбор приводит к
выполнению  определенной  процедуры программы.  Выбор может  быть
сделан за счет нажатия клавиш  A,  B, C ... (давая 1-байтные коды
ASCII) или Alt-A, Alt-B, Alt-C ...  (давая 2-байтные  расширенные
коды). Для их  распознавания  используется  функция  LEN, которая
определяет была ли строка длиной в 1 или 2 байта.  В случае кодов
ASCII набор операторов  IF...THEN  сразу начинает проверять какая
клавиша была нажата, отсылая программу на соответствующую  проце-
дуру. В случае 2-байтных  кодов  управление  передается отдельной
процедуре.  В этой процедуре функция RIGHT$ убирает левый символ,
который просто равен нулю  и  только  отмечает  расширенный  код.
Затем используется функция ASC для преобразования строки из  сим-
вольной формы в числовую.  И,  наконец,  вторая  серия операторов
IF...THEN проверяет получившееся число на соответствующие  Alt-A,
Alt-B и т.д.

100 C$ = INKEY$:IF C$="" THEN 100   'ожидаем нажатия клавиши
110 IF LEN(C$)=2 THEN 500           'если расш. код - на 500
120 IF C$="a" OR C$="A" THEN GOSUB 1100 'это A?
130 IF C$="b" OR C$="B" THEN GOSUB 1200 'это B?
140 IF C$="c" OR C$="C" THEN GOSUB 1300 'это C?
 .
 .
500 C$=RIGHT$(C$,1)        'получаем второй байт расш. кода
510 C=ASC(C$)              'преобразуем его в число
520 IF C=30 THEN GOSUB 2100  'это Alt-A?
530 IF C=48 THEN GOSUB 2200  'Alt-B?
540 IF C=46 THEN GOSUB 2300  'Alt-C?

Отметим,  что в строке 120 (и последующих) можно также  использо-
вать числовые значения кодов ASCII:

120 IF C=97 OR C=65 THEN GOSUB 1100

Конечно надо сначала  преобразовать  C$ в форму целого числа, как
это сделано в строке 510. В программах, в которых требуется длин-
ная цепочка таких операторов,  можно  сэкономить место, изменяя C
таким  образом,  чтобы она всегда соответствовала либо  верхнему,
либо нижнему регистру.  Сначала  нужно  только проверить, что код
ASCII  C$  находится в правильном диапазоне.   Затем  установить,
меньше ли этот код 91, тогда  мы  имеем  дело с символом верхнего
регистра.   Если это так, то надо для перевода в  нижний  регистр
добавить 32.  В противном  случае,  оставить все как есть.  После
этого  будет достаточно более короткого оператора, такого как  IF
C=97 THEN ... Вот код этой процедуры:

500 C=ASC(C$)         'получаем ASCII код символа
510 IF NOT ((C>64 AND C<91)OR(C>96 AND C<123)) THEN ...
520 IF C<91 THEN C=C+32  'приводим все к нижнему регистру
530 IF C=97 THEN ...     '... начинаем проверку значений

   Средний уровень.


   Функции 7 и 8 прерывания 21H ожидают ввода символа, если буфер
клавиатуры пуст, а когда он появляется, то не выводится на экран.
При этом функция 8 определяет Ctrl-Break  (и инициирует процедуру
обработки Ctrl-Break[3.2.8]), а функция 7 не реагирует на него. В
обоих случаях символ  возвращается  в AL. Когда AL содержит ASCII
0, то получен расширенный код.  Повторите прерывание и в AL  поя-
вится второй байт расширенного кода.

;---получаем введенный символ
      MOV  AH,7           ;номер функции
      INT  21H            ;ожидаем ввод символа
      CMP  AL,0           ;проверка на расширенный код
      JE   EXTENDED_CODE  ;если да, то на особую процедуру
       .                  ;иначе, код символа в AL

;---процедура обработки расширенных кодов
EXTENDED_CODE:  INT  21H        ;берем второй байт кода
                CMP  AL,75      ;проверяем на "стрелку-влево"
                JNE  C_R        ;если нет, то след. проверка
                JMP  CURSOR_LEFT;если да, то на процедуру
C_R:            CMP  AL,77      ;сравниваем дальше и т.д.

   BIOS обеспечивает процедуру,  которая предоставляет те же воз-
можности, что и функции MS DOS.  Поместите 0 в AH и вызовите пре-
рывание 16H. Функция ожидает ввода символа и возвращает его в AL.
В этом случае и расширенные коды обрабатываются за одно  прерыва-
ние. Если в AL  содержится  0,  то  в  AH будет содержаться номер
расширенного кода. При это не обрабатывается Ctrl-Break.

;---ждем нажатия клавиши
   MOV  AH,0       ;номер функции ожидания ввода
   INT  16H        ;получаем введенный код
   CMP  AL,0       ;проверка на расширенный код
   JE   EXTENDED_CODE   ;если да, то на спец. процедуру
    .                   ;иначе символ в AL

;---процедура обработки расширенного кода
EXTENDED_CODE:  CMP  AH,75   ;берем расширенный код из AH
                             ;и т.д.