                             ГЛАВА 19.

                           ВВОД И ВЫВОД.

               Драйверы устройств текстового файла.

     Как сказано в главе 10 "Модуль System", Turbo Pascal позволяет
Вам  определить  Ваш собственный драйвер текстового файла.  Драйвер
текстового файла -  это  4  функции,  которые  полностью  реализуют
интерфейс между   файловой   системой  Turbo  Pascal  и  каким-либо
устройством.
     Драйвер на  любое  устройство определяется 4 функциями:  Open,
InOut, Flush и Close. Каждая функция имеет заголовок:

     function DeviceFunc(var F : TextRec) : Integer;

     где TextRec - это тип записи  текстового  файла,  определенный
ранее в  разделе  "Файловые типы" в главе 3.  Каждая функция должна
быть откомпилирована в состоянии {$F+},  для использования  дальней
модели   вызова.   Значение,   возвращаемое   функцией,  становится
результатом,  который возвращает IOResult.  Значение 0  говорит  об
успешной операции.
     Для связи функций интерфейса с устройством с  заданным файлом,
Вы должны написать свою процедуру Assign (как процедура AssignCrt в
модуле Crt). Процедура Assign должна присваивать адреса 4-х функций
интерфейса с  устройством  4-м  указателям  на функции в переменной
текстового файла.  Дополнительно она  должна  запоминать  константу
fmClosed  в  поле  Mode,  размер буфера текстового файла в BufSize,
указатель на буфер текстового файла в BufPtr и очищать строку Name.
     Например, предположим,  что 4 функции интерфейса с устройством
называются DevOpen,  DevInOut, DevFlush, DevClose, процедура Assign
будет:

     procedure AssignDev(var F: Text);
     begin
        with TextRec(F) do
        begin
          Mode      := fmClosed;
          BufSize   := SizeOf(Buffer);
          BufPtr    := @Buffer;
          OpenFunc  := @DevOpen;
          InOutFunc := @DevInOut;
          FlushFunc := @DevFlush;
          CloseFunc := @DevClose;
          Name[0]   := #0;
        end;
     end;

     Функции интерфейса  с  устройством  могут  использовать   поле
UserData в файловой записи для хранения своей информации.  Это поле
никогда не модифицируется файловой системой Turbo Pascal.


                           Функция Open.

     Функция Open   вызывается   стандартными   процедурами  Reset,
Rewrite и  Append  для  открытия  текстового  файла,  связанного  с
устройством.  При  входе  поле  Mode  содержит  константу  fmInput,
fmOutput или fmInOut, показывающую что функция Open была вызвана из
Reset, Rewrite или Append.
     Функция Open готовит  файл  для  ввода  или  вывода,  согласно
значению  Mode.  Если  Mode  задает  fmInOut  (Open была вызвана из
Append), то она должна быть изменена на  fmOutput  до  возврата  из
Open.
     Open всегда вызывается до любой другой  функции  интерфейса  с
устройством. По  этой  причине  Assign  инициализирует  только поле
OpenFunc,  предоставляя инициализацию  остальных  векторов  функции
Open.  Основываясь  на  значении Mode,  Open может затем установить
указатели либо на  функции  ввода,  либо  на  функции  вывода.  Это
сохраняет  функции  InOut,  Flush  и  Close от определения текущего
режима.


                          Функция InOut.

     Функция Inout  вызывается стандартными процедурами и функциями
Read, Readln, Write, Writeln, Eof, Eoln, SeekEof, SeekEoln и Close,
когда необходим ввод или вывод с этого устройства.
     Когда режим  -  fmInput,  функция  InOut  читает  до   BufSize
символов  в  BufPtr^  и  возвращает  число  прочитанных  символов в
BufEnd.  Дополнительно она устанавливает BufPos в 0.  Если  функция
InOut  возвращает 0 в BufEnd в результате запроса на ввод,  Eof для
этого файла становится True.
     Когда Mode   -   fmOutput,  функция  InOut  записывает  BufPos
символов из BufPtr^ и возвращает 0 в BufPos.


                          Функция Flush.

     Функция Flush вызывается в конце каждой Read,  Readln,  Write,
Writeln. Она может, кроме того, вытеснять буфер текстового файла.
     Если Mode  равно  fmInput,  функция  Flush может устанавливать
BufPos, BufEnd  в  0  для  выталкивания  оставшихся   (несчитанных)
символов в буфер. Эта возможность используется редко.
     Если Mode  -  fmOutPut,   функция   Flush   может   записывать
содержимое буфера,   точно   так   же,   как   функция  InOut,  что
гарантирует,  что  текст  записанный  в  устройство,  появится   на
устройстве немедленно.  Если Flush ничего не делает, текст не будет
передаваться на устройство до тех пор, пока буфер не заполнится или
пока не закроется файл.


                          Функция Close.

     Функция Close  вызывается  стандартной  функцией   Close   для
закрытия  текстового  файла,  связанного с устройством.  (Процедуры
Reset,  Rewrite и Append также вызывают Close,  если файл,  который
они  открывают  уже  открыт).  Если Mode - fmOutPut,  то - файловая
система Turbo Pascal,  до вызова  функции  Close,  вызывает  InOut,
чтобы гарантировать, что все символы были записаны на устройство.


                      Прямой доступ к портам.

     Для доступа к портам процессора 80х86,  Turbo Pascal реализует
два  предопределенных  массива  Port  и  PortW.  Оба  -  одномерные
массивы,  каждый элемент которых представляет  порт,  причем  адрес
порта соответствует  его  индексу.  Тип  индекса - слово.  Элементы
массива Port - типа байт и элементы массива PortW - типа слово.
     Когда элементу  Port  или  PortW  присваивается значение,  это
значение записывается в указанный  порт.  Когда  элемент  Port  или
PortW  используется  в  выражении - значение читается из указанного
порта. Примеры:

     Port[$20] := $20;
     Port[Base] := Port[Base] xor Mask;
     while Port[$B2] and $80 = 0 do    {ожидание};

     Массивы Port и PortW можно использовать только  в присваивании
и  в  выражениях,  таким  образом,  элементы  Port  и  PortW нельзя
использовать  как  изменяемые   параметры.   Более   того,   нельзя
обращаться ко всему массиву Port или PortW.
