Программа PRINTFL
Приведем исходный текст программы PRINTFL, которая распечатывает содержимое файла с использованием функции 0 прерывания INT 17h (листинг 7.1).
Листинг 7.1. Файл printfl\printfl.с
// =====================================================
// Печать на принтере с помощью функций BIOS
//
// (C) Фролов А.В, 1997
//
// E-mail: frolov@glas.apc.org
// WWW: http://www.glasnet.ru/~frolov
// или
// http://www.dials.ccas.ru/frolov
// =====================================================
#include <dos.h>
#include <stdio.h>
#include <conio.h>
union REGS rg;
int printchar(int chr);
int error(char chr, int status);
int main(int argc, char *argv[])
{
FILE *srcfile;
// Открываем файл, заданный первым параметром
// в командной строке.
// Если при запуске программы оператор забыл
// указать имя файла, выводим напоминающее сообщение
if( (srcfile = fopen( argv[1], "rb" )) == NULL )
{
printf("\nЗадайте имя файла в качестве параметра");
return (-1);
}
// Читаем файл по одному символу, полученный из файла
// символ выводим на принтер при помощи функции printchar
for(;;)
{
printchar(fgetc(srcfile));
if(feof(srcfile))
break;
}
// Закрываем файл
fclose(srcfile);
return 0;
}
// ------------------------------------
// Эта функция выводит один символ
// на первый принтер (LPT1)
// ------------------------------------
int printchar(int chr)
{
int status;
// Повторяем в цикле выдачу символа на принтер
// до тех пор, пока он не будет выведен без
// ошибок, либо пока оператор не отменит
// распечатку файла
for(;;)
{
// Дублируем распечатываемый символ на экране
putch(chr);
// Вызываем функцию 00h прерывания INT 17h -
// распечатка символа на принтере.
// В регистре DX задаем номер принтера LPT1 - это 0
rg.h.ah = 0;
rg.h.al = chr;
rg.x.dx = 0;
int86(0x17, &rg, &rg);
// Запоминаем байт состояния принтера
// после вывода символа
status = rg.h.ah;
// Проверяем наличие ошибок. Нас интересуют биты:
//
// 0 - задержка при печати
// 3 - ошибка ввода/вывода
// 4 - принтер в состоянии ONLINE (1) или OFFLINE (0)
// 5 - конец бумаги
if((status & 0x39) != 0x10)
{
// Вызываем функцию обработки ошибки error(). Эта
// функция возвращает 0, если оператор желает
// повторить печать символа, или 1 - если
// оператор отменяет печать
if(error(chr, status))
{
printf("\nПечать завершилась аварийно");
return -1;
}
}
else
break;
}
}
// ------------------------------------
// Функция выводит на экран состояние
// принтера и запрашивает у оператора
// требуемые действия - повторить
// печать символа или отменить печать
// ------------------------------------
int error(char chr, int status)
{
// Выводим состояние принтера после ошибки
printf("\nОшибка принтера %02.2X"
"\n\nСостояние принтера:"
"\n-------------------", status);
if(status & 1)
printf("\nТаймаут при печати");
if(status & 8)
printf("\nОшибка ввода/вывода");
if(!(status & 0x10))
printf("\nПринтер находится в состоянии OFFLINE");
if(status & 0x20)
printf("\nКонец бумаги");
printf("\n\nДля отмены печати нажмите клавишу ESC,"
"\nдля повтора - любую другую клавишу\n");
if(getch() == 27)
return 1;
else
return 0;
}
Программа считывает по байтам содержимое файла, открытого в двоичном режиме. Считанные байты передаются в качестве параметра функции printchar, которая и выводит их на принтер.
После вызова прерывания INT 17h функция printchar проверяет состояние принтера.При возникновении ошибки ввода/вывода вызывается обработчик - функция error. Эта функция выводит на экран состояние принтера (в развернутом виде с объяснением каждого бита в байте состояния), а также запрашивает пользователя о дальнейших действиях.
Если пользователь может устранить причину ошибки (перевести принтер в состояние online, вставить бумагу, если она кончилась и так далее), он нажимает любую клавишу, кроме <Esc>. В этом случае функция error возвращает 0. Иначе возвращается значение 1.
Если пользователь решил повторить печать, и, соответственно, если функция error возвратила значение 0, функция printchar повторяет печать символа. При отмене печати выдается сообщение об ошибке и работа программы завершается.