Вывод данных или специальных командных кодов на принтер через связанный с ним файл Lst или ему подобный — не единственный способ управлять печатью. Существует и другой путь посылки символа или их последовательности в принтер — через прерывание БСВВ 17H. Кроме того, используя это прерывание, можно опрашивать состояние устройства печати.
Прерывание 17H обеспечивает доступ к трем функциям обслуживания принтера:
— печати символа на принтере (функция номер 0);
— инициализации порта принтера (функция номер 1);
— чтению состояния принтера (функция номер 2).
При вызове прерывания регистр процессора AH должен содержать номер функции, а регистр DX — номер параллельного порта (0 соответствует LPT1, 1 — LPT2, 2 — LPT3). При вызове функции 0 надо дополнительно загрузить в регистр AL ASCII-код посылаемого в принтер символа. Прерывание после выполнения всегда возвращает в регистре AH байт состояния принтера. Некоторое исключение составляет функция 0. Если она закончилась неудачей, то после небольшой задержки в регистре AH вернется значение 01H.
Наиболее полезна для программ, работающих с принтерами, функция номер 2, опрашивающая байт состояния принтера. Этот байт имеет следующую структуру (рис. 17.2).
Бит 7
Бит6
Бит 5
Бит 4
Бит 3
Бит 2
Бит 1
Бит 0
— принтер занят (0) или ждет символ (READY) (1)
— если 1, то принтер подключен
— если 1, то кончилась бумага (PAPER OUT)
— если 1, то принтер в состоянии принять сигнал
— если 1, то ошибка ввода-вывода
— не используется (зарезервирован)
— не используется (зарезервирован)
— если 1, то задержка (timeout)
Рис. 17.2 {388}
В специальной литературе оговаривается, что результаты опроса состояния принтера через прерывание 17H могут меняться на различных ПЭВМ и с различными принтерами. Это не значит, что прерывание нельзя использовать. Практически всегда должно выполняться условие возможности получения очередного символа на бумаге. Оно заключается в том, что перед выводом символа на печать биты 4 и 7 байта состояния принтера должны содержать единицы, т.е. в регистре AH после опроса должно быть значение 10H+80H=90H. Более «тонкие» проверки следует протестировать на конкретных ПЭВМ. На рис. 17.3 приводится пример функции опроса состояния принтера и связанной с ней процедуры печати файла из программы. В большинстве случаев эти подпрограммы должны работать корректно.
USES
DOS, CRT, Printer;
{ Функция возвращает код состояния принтера LPT1 (PRN).
При работе требуется подключение модуля DOS. }
FUNCTION TestPrinter : ShortInt;
VAR
R : Registers; { служебная переменная }
BEGIN
TestPrinter := 100; { исходное значение }
R.AH:=$02; { функция номер 2 }
R.DX:=$00; { принтер в LPT1 }
Intr( $17, R ); { прерывание 17H }
if (R.AH and $10) = $00 { проверка наличия }
then begin
TestPrinter := -1; { принтер не подключен }
Exit { выход из функции }
end;
if (R.AH and $80) = $00 { проверка готовности: }
then TestPrinter := 0 { подключен, но OFF LINE }
else TestPrinter := +1; { подключен, и ON LINE }
END;
{ Процедура печатает файл FileName на принтере, подключенном к LPT1, анализируя состояние принтера. Можно прервать процедуру, нажав клавишу Esc. X и Y - координаты сообщения на экране. Для работы нужны модули Printer и CRT. }
Рис. 17.3 {389}
PROCEDURE PrintFile( X, Y : Byte; FileName : String );
LABEL
mStop; { метка выхода no Esc }
VAR
f : Text; s : String; { служебные переменные }
Т : ShortInt; { результат опроса принтера }
BEGIN
REPEAT { цикл опроса состояния LPT1 }
Т := TestPrinter; { см. предыдущую страницу }
if KeyPressed { опрос клавиш }
then if ReadKey=#27 then Exit; { Esc – выход }
GotoXY( X,Y );
case Т of { анализ LPT1: }
-1 : Write( ' ПРИНТЕР НЕ ПОДКЛЮЧЕН...' );
0 : Write( ' НАЖМИТЕ <ON LINE> !... ');
+1 : Write( ' РЕЗУЛЬТАТЫ ВЫВОДЯТСЯ... ' );
else Write( ' ПРОБЛЕМЫ С ПРИНТЕРОМ... ' );
end;
Write( ' (ОТКАЗ - Esc)' );
UNTIL ( T=1 ); { при Т=1 уже можно печатать }
Assign( f, FileName ); { связывание файла FileName }
Reset( f ); { открытие его для чтения }
while not EOF(f) do begin { печать файла по строкам }
ReadLn( f, s ); { чтение строки }
if KeyPressed then { опрос клавиш }
if ReadKey=#27 then Goto mStop; { Esc – выход }
WriteLn( 1st, s ) { печать строки }
end; {while} { конец цикла печати файла }
mStop : Close( f ) { закрытие файла FileName }
END;
BEGIN
PrintFile(10,10, 'ris17-3.pas'); { печать текст-файла }
END.