
    9. РАБОТА СО СТРОКАМИ

    А. Введение
    Почти  все  коммерческие  библиотеки содержат разнообразные средства
для работы со строками и Object Professinal не  исключение.  Вы  найдете
все обычные функции для преобразования числовых данных в строковые с ис-
пользованием  различных  форматов,  изменения строк содержащих буквенные
символы ( латинский алфавит ), удаление лидирующих и хвостовых пробелов,
заполнение строк пробелами и сравнения строк.
    OPSTRING  состоит  из обычно используемых строковых функций, включая
все упомянутые выше. Модуль также содержит  большое  число  в  некотором
смысле  нетрадиционных  функций.  Наиболее неожиданными являются функции
работающие со строками, содержащими путь поиска и имена файлов. Они поз-
воляют добавлять и заменять расширения в именах файлов, отсекать  расши-
рение  и  путь  доступа к файлу, выделяя только имя файла и создавать из
нескольких строк строку, содержащую полный путь доступа к файлу  в  виде
"имя  диска:\путь\имя файла.расширение". OPSTRING также содержит функции
динамически распределяющие и очищающие память под строковые  переменные,
осуществляющие  поиск заданной строки в больших массивах и преобразующих
строки в так называемые "созвучные коды", позволяющие производить  поиск
однообразно звучащих имен, как "Smith" и "Smythe".
    Одна  из  наиболее удобных функций в OPSTRING   - Form, моделирующая
функцию Form для чисел в двоично-десятичном представлении в  Турбо  Пас-
каль  3.0. Form передаются два параметра, строковая маска и действитель-
ное число. Form возвращает строку в которой на указанные в  маске  места
будут  поставлены  цифры  действительного  числа.  Например,  при  маске
"$##,###,###.##" и  действительном  числе  12300.26666,  Form  возвратит
строку "$12,300.27".(Заметим что OPBCD содержит  похожую функцию для чи-
сел в двоично-десятичном представлении).
    Нельзя  не сказать об одном из недостатков Турбо Паскаля - это огра-
ничение длины строки 255 символами. Хотя 255 символов и не так уж  мало,
однако  если  вам нужно работать с более длинными строками вы заходите в
тупик. OPASCIIZ предоставляет вам всеобъемлющее решение этой проблемы. В
отличии от нормальной строки символов строка ASCIIZ не имеет байта  дли-
ны.  Вместо  этого  конец строки отмечается единственным пустым символом
(#0). Большим недостатком ASCIIZ строк является то, что некоторые опера-
ции, такие как вычисление длины строки, занимают больше времени, но зато
они могут быть более длинными (1024 символа по определению и при желании
можно использовать до  65520  символов).  Еще  один  большой  недостаток
ASCIIZ  строк  - Турбо компилятор их не поддерживает, но модуль OPASCIIZ
содержит все необходимое для работы с ними. Кроме того, он  поддерживает
все операции над строками из Турбо - Concat, Insert, Delete, Pos, Lenght
-  а  также аналоги большинства основных функций из OPSTRING. Важно, что
имеется возможность для чтения и записи ASCIIZ строк в текстовый файл.
    Крошечный модуль OPSTRDEV выполняет  единственную  функцию,  которая
позволяет  использовать  возможности  оператора Write для создания строк
заданного формата. Это особенно полезно,  если  вы  используете  функцию
FastWrite  (OPCRT), которая не работает с числовыми параметрами и с пус-
тыми строками. Например, если вы хотите преобразовать числа -354 и 41  в
одну  строку длиной 18 символов вам надо использовать функции Long2Str и
Pad из OPSTRING и затем использовать результат действия этих функций как
параметр для FastWrite. Если бы вы  использовали  OPSTRDEV,то  могли  бы
сделать это проще

        Write(TpStr,-357,41:14);
        FastWrite(ReturnStr,Row,Column,Attribute);

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

    В. OPSTRING: строковые операции

    Как отмечалось ранее, OPSTRING содержит не только  все  функции  для
операций со строками которые вы можете представить, но даже и те которые
вы  и не представляете. Мы думаем что вы найдете все необходимое для ва-
ших прикладных программ работающими со строками.  OPSTRING  работает  со
стандартными  256 символьными строками Турбо Паскаля. Если вам нужно ра-
ботать с более длинными строками обращайтесь к части руководства, описы-
вающей OPASCIIZ.
    Функции в OPSTRING делятся на несколько категорий  :  преобразование
чисел и форматирование; основные операции, такие как выбор удаление, за-
мена и центровка символов; сравнение и поиск строк; динамическое распре-
деление памяти для строк; анализ пути доступа для ДОС.

    Типы

           BTable = array[0..255] of Byte;
        Таблица используемая функцией поиска методом Боре-Мура.

           CharSet = set of char;
        Символьная константа множественного типа.

           CompareType = (Less,Equel,Greater);
        Результат сравнения двух переменных.

           ExtStr = string[ExtLen];
        Расширение файла ДОС.

           {$IFOPT N+}
           Float = Extended;
           {$ELSE}
           Float = Real;
           {$ENDIF}
        Если  OPSTRING  скомпилирован  с опцией {$N+} то тип с плавающей
        точкой определяется как с повышенной точностью, а не как вещест-
        венный. Определение типа с плавающей точкой  влияет  на  функции
        Real2Str и Str2Real.

           StringPtr = ^String;
        Указатель на строковую переменную.

    Константы

           CommaForPeriod : Boolean = False;
        Если  "Правда"  то  функция  Form возвращает "." и наоборот. Это
        позволяет немного проще писать программы использующие оба спосо-
        ба (Американский и принятый в некоторых других странах) разделе-
        ния десятичных чисел.

           ExtLen = 3;
        Длина расширения в имени файла.

           LetterValues : array['A'..'Z'] of Byte =
        (3 {A} , 6 {B} , 5 {C} , 4 {D} , 3 {E} , 5 {F} , 5 {G} , 4 {H} ,
         3 {I} , 8 {J} , 7 {K} , 4 {L} , 5 {M} , 3 {N} , 3 {O} , 5 {P} ,
         7 {Q} , 4 {R} , 3 {S} , 3 {T} , 4 {U} , 6 {V} , 5 {W} , 8 {X} ,
         8 {Y} , 9 {Z} );
        Таблица  используемая  CompareLetterSets  для  оценки сходства
        строк.

           MoneySIgn : Char = '$';
        Этот символ используется когда надо вывести значение в формате с
        долларами и центами. При необходимости вы  можете  вместо  этого
        символа использовать выражение #156, например, функция Form поз-
        воляет  отображать  заданную величину в английских фунтах а не в
        долларах.

    Синтаксис
        function AddBackSlash(DirName : string) : string;
    Назначение
        Добавляет обратный слэш к имени директория.
    Замечания
        Обратный слэш '\' отделяет имя директория ДОС от имени  файла  в
        этом  директории. Однако в некоторых случаях необходимо избегать
        простого присоединения этого символа к имени директория. Главный
        директорий ДОС адресуются только одним слэшом и было бы  ошибкой
        добавлять  еще  один.  Поэтому AddBackSlash добавляет символ '\'
        только в том случае, если имя директория не оканчивается на  не-
        го.
    Пример
          PathName := AddBackSlash('c:\')+'autoexec.bat';
        Результат - путь доступа 'C:\AUTOEXEC.BAT'.

          PathName := AddBackSlash('\turbo\test')+'dug.pas';
        Результат - путь доступа '\TURBO\TEST\BUG.PAS'.
    Смотри также
        FullPathName

    Синтаксис
        function BinaryB(B : Byte) : string;
    Назначение
        Возвращает  переменную В длиной в байт, преобразованную в двоич-
        ную строку.
    Замечания
        Возвращает двоичную строку 8-битовую строку, являющуюся двоичным
        представлением B. Лидирующие нули включаются.
    Пример
          BinaryB(0);
        Возвращает '00000000'.

          BinaryB($B1);
        Возвращает '10110001'.

    Синтаксис
        function BinaryL(L : Longint) : string;
    Назначение
        Возвращает переменную L типа длинное целое в двоичную строку.
    Замечания
        Возвращает двоичную 32-битовую строку, являющуюся двоичным пред-
        ставлением L. Разделительные символы не включаются в строку. Ли-
        дирующие нули включаются.
    Пример
          BinaryL(-1);
        Возвращает '11111111111111111111111111111111'.

          BinaryL(7);
        Возвращает '00000000000000000000000000000111'.

    Синтаксис
        function BinaryW(W : Word) : string;
    Назначение
        Возвращает переменную W длиной в слово в двоичную строку.
    Замечания
        Возвращает двоичную 16-битовую строку, являющуюся двоичным пред-
        ставлением W. Разделительные символы не включаются в строку. Ли-
        дирующие нули включаются.
    Пример
          BinaryW($B800);
        Возвращает '1011100000000000'.

          BinaryW(-1);
        Ошибка ! Так как тип длиной в слово не имеет знака.Для этого ти-
        па используйте функцию BinaryL.
    Смотри также
        BinaryB                      BinaryL

    Синтаксис
        procedure  BMMakeTable(MatchString  :  string;  var  BT  :
        BTable);
    Назначение
        Генерирует таблицу связи Боре-Мура.
    Замечания
        Алгоритм Боре-Мура является быстрым  алгоритмом  поиска  строки.
        Его  быстродействие основано на том факте, что нет необходимости
        проверять все элементы строки. Элементы, которые могут быть про-
        пущены, определяются по таблице связи, которая должна быть  сге-
        нерирована до начала поиска.
        Таблица  связи  представляет  собой массив из 256 элементов типа
        байт. Для каждого из 256 символов ASCII в таблице связи указыва-
        ется  признак   указывающий   на   необходимость   его   поиска.
        BMMakeTable   берет   в   качестве  строки  которую  надо  найти
        MatchString и возвращает сгенерированную для  нее  таблицу.  Эта
        таблица затем будет использована собственно для поиска по методу
        Боре-Мура.
        Эффективность  работы  BMMakeTable  повышается при использовании
        небольшого объема поиска. Важно, чтобы вы  минимизировали  число
        вызовов  BMMakeTable.  Если  вы  вынуждены использовать ее очень
        часто, то мы советуем вам воспользоваться функцией Search, кото-
        рая возможно окажется более эффективна в этом случае.
        Пример использования приведен при описании функции BMSearch.
    Смотри также
        BMSearch                     BMSearchUC

    Синтаксис
        function BMSearch(var Buffer; BufLenght : Word;
                        BT : BTable; MatchString : string) : Word;
    Назначение
        Ищет MatchString в Buffer с использованием алгоритма Боре-Мура.
    Замечания
        Данная функция возвращает тоже значения что  и  функция  Search,
        содержащаяся в OPSTRING. Однако BMSearch использует алгоритм Бо-
        ре-Мура  для поиска заданной строки, который в некоторых случаях
        является более эффективным чем Search.  BMSearch  отличается  от
        Search  количеством  передаваемых параметров. Подобно Search она
        осуществляет поиск в массиве Buffer с длинной BufLenght до 65534
        символов. В отличии от Search, функции в качестве  обязательного
        параметра передается таблица связи, сгенерированная BMMakeTable,
        и производится поиск стандартной для Турбо строки.
        BMSearch  возвращает  номер  первого символа в Вuffer, начиная с
        которого искомая строка входит в него. Если  строка  не  найдена
        возвращается  $FFFF.  Если искомая строка найдена в самом начале
        Buffer, то возвращается 0.
        Производительность метода Боре-Мура зависит от многих  факторов.
        Если размер Buffer не превышает нормальной для Турбо строки (255
        символов)  и для каждого нового поиска необходимо обновлять таб-
        лицу связи, то BMSearch  будет  всегда  работать  медленнее  чем
        простой  поиск  с  помощью  Search. С другой стороны, если поиск
        осуществляется в большом массиве и одна таблица связи  использу-
        ется  много  раз,  то эффективность BMSearch примерно в два раза
        выше чем у Search, в зависимости от  длина  MarchSearch.  Обычно
        чем длиннее MarchSearch, тем эффективнее использование BMSearch.
        Выражаем персональную благодарность Дону Стренксвилку за предос-
        тавление первоначальной версии функции, реализующей алгоритм Бо-
        ре-Мура.
    Пример
          function BMS(var Buffer; Buflenght : Word; MatchSt :
                       String) : Word;
          var
            LocalTable : BTable;
          begin
            BMMakeTable(MatchSt,LocalTable);
            BMS := BMSearch(Buffer,BufLenght,LocalTable,MatchSt);
          end;
        Эта подпрограмма получает от вызывающей программы таблицу связи.
        К  сожалению, она обновляет таблицу связи при каждом вызове, тем
        самым снижает эффективность работы программы.  Эта  подпрограмма
        предоставляет показывает неплохие результаты, если размер Buffer
        является большим. С другой стороны, подпрограмма непосредственно
        вызывает  функцию  BMMakeTable  и  использует сгенерированную ей
        таблицу столько раз, сколько нужно.
    Смотри также
        BMMakeTable      BMSearchUC       Search

    Синтаксис
        function BMSearchUC(var Buffer; BufLenght : Word;
                 BT : BTable; MatchString : string ) : Word;
    Назначение
        Производит поиск в Buffer MatchString , используя  алгоритм  Бо-
        ре-Мура без различия в строчных и заглавных буквах.
    Замечания
        Действие  этой  функции подобно BMSearch, с той разницей, что не
        делается различий при сравнении строчных  и  заглавных  букв.Для
        получения  большей информации смотри BMSearch. Важное замечание:
        Пользователь должен гарантировать, что MatchString не  превышает
        допустимую длину и очередность вызова BMMakeTable и BMSearchUC.
        BMSearchUC  почти  всегда  имеет  большую производительность чем
        SearchUC, даже если таблица связи ВТ будет строится  заново  для
        каждого нового поиска. Скорость BMSearchUC колеблется от немного
        меньшей чем у SearchUC до в 4 раза большей, в зависимости от как
        часто  обновляется  таблица связи, длины MatchStering и типа ис-
        пользуемых данных.
        Заметим, что BMSearchUC работает корректно со всеми  алфавитными
        символами ( 'A'..'Z' , 'a'..'z' , #128..#154 , #160..#167).
    Пример
          function  UCBMS(var  Buffer;  BufLenght : Word,  MatchSt :
                          string) : Word;
          var
            LocalTable : BTable;
          begin
           MatchSt := StUpCase(MatchSt); {перевод в строчные буквы}
           BMMakeTable(MatchSt,LocalTable); {строит таблицу связи}
           UCBMS := BMSearchUC(Buffer,BufLenght,LocalTable,MatchSt);
          end;

        Эта  функция реализует все подготовительные операции для исполь-
        зования метода Боре-Мура. Если таблица связи может быть  исполь-
        зована более одного раза - эта функция теряет преимущества, хотя
        и остается более быстрой чем все альтернативные варианты.
    Смотри также
        BMMakeTable       BMSearch         SearchUC

    Синтаксис
        function Center(S : string; Width : Byte) : string;
    Назначение
        Возвращает  строку  заданной  длины,  отцентрированную с помощью
        пробелов.
    Замечания
        Если длина S больше чем Width, то S не изменяется. Если S пустая
        строка, то возвращается строка, заполненная пробелами.
    Пример
          Center('hello',10);
        Возвращает строку '  hello   '.
    Смотри также
        CenterCh

    Синтаксис
        function CenterCh(S : string; Ch : char; Width : Byte)
                          : string;
    Назначение
        Возвращает строку заданной длины, отцентрированную с помощью за-
        данных символов.
    Замечания
        Если длина S больше чем Width, то S не изменяется. Если S пустая
        строка, то возвращается строка, заполненная символами Ch.
    Пример
          CenterСh('hello','-',10);
        Возвращает строку '--hello---'.
    Смотри также
        Center

    Синтаксис
        function CharStr(Ch : Char; Len : Byte) : string;
    Назначение
        Возвращает строку заданной длины Len заполненную символами Ch.
    Замечания
        Если Len равно 0, то возвращается пустая строка.
    Пример
          CharStr('-',10);
        Возвращает '----------'.
    Смотри также
        PadCh

    Синтаксис
        function CleanPathName(PathName : string) : string;
    Назначение
        Возвращает путь поиска для ДОС с отброшенными лишними символами.
    Замечания
        Вы должно быть заметили, что ДОС будет работать только с именами
        файлов состоящими не более чем из 8 символов и с расширениями не
        более чем из трех. Остальные символы просто  игнорируются.  Ска-
        занное относится и к названиям подкаталогов и каталогов, исполь-
        зуются ли они самостоятельно или как часть пути поиска. Если ва-
        ша программа выводит имена файлов, было бы глупо отображать сим-
        волы, которые игнорируются ДОС. CleanPathName автоматически убе-
        рет такие символы.
    Примеры
          CleanPathName('AUTOEXEC.BAT');
        Возвращает 'AUTOEXEC.BAT'.

          CleanPathName('AUTOEXEC.BAT1');
        Возвращает 'AUTOEXEC.BAT'.

          CleanPathName('D:\TEST1234\BUG.PAS');
        Возвращает 'D:\TEST1234\BUG.PAS'
   Смотри также
        FullPathName

   Синтаксис
        function CompareLetterSets(Set1, Set2 : LongInt) Word;
   Назначение
        Возвращает сумму значений одинаковых букв в строках Set1 и Set2.
   Замечания
        Функции  MakeLetterSet  и CompareLetterSets, соединенные вместе,
        представляют собой альтернативный алгоритму Soundex метод оценки
        совпадения двух слов или строк слов. Этот метод  был  разработан
        Микаэлом  Бикелем и подробно обсуждается в статье Джима Хаувелла
        "Альтернатива Soundex" (Dr.Dobb's Journal,ноябрь,1987).
        До вызова CompareLetterSets вы  должны  используя  MakeLetterSet
        создать  битовый  массив типа длинное целое ("буквенный набор"),
        показывающий, какие буквы присутствуют  в  данной  строке.  Этот
        процесс должен быть повторен для каждой новой строки. На основа-
        нии этих двух наборов CompareLetterSets найдет общее между двумя
        строками  ( буквы разделяются запятыми) и возвратит число, пока-
        зывающее близость сравниваемых строк. При вычислении этого числа
        используется таблица LetterValues  (описанная  в  OPSTRING.PAS),
        которая  присваивает большие значения редко встречающимся буквам
        ('J','Q','X','Z') и меньшие значения наиболее часто встречающим-
        ся  буквам  ('A','E','N','S','T').  Возвращаемое  значение  есть
        просто  сумма значений для каждого набора в объединении. Для оп-
        ределения максимального возможного значения, которое может  быть
        возвращено  в любой заданной ситуации, вы должны сравнить строку
        с самой собой.
            PossibleValue := CompareLetterSets(LetSet1,LetSet1);
        Результат сравнения с любой другой строкой будет находится в ин-
        тервале от 0 до PossibleValue. Чем больше возвращаемое  значение
        тем больше степень похожести строк.
        Несомненно,  что  не  существует какого-то определенного метода,
        позволяющего сказать, что возвращаемое CompareLetterSets  значе-
        ние  показывает реальную степень похожести строк. Поэтому мы со-
        ветуем вам поэксперементировать с этой функцией  и  решить,  как
        лучше  для вас ее использовать. Один из способов получения более
        информативного    результата    с     использованием     функции
        DissimilarityIndex показан в примере ниже. Эта функция возвраща-
        ет  значение  от  0  (высшая степень совпадения) до 130 (одна из
        строк пуста).(Одинаковые строки обычно будут иметь значение  0.3
        и  меньше) Вы можете также модернизировать эту программу с целью
        использования факторов, которые алгоритм Бикеля игнорирует (дли-
        ны строк равны ? первые символы совпадают ? и т.д.).  Для  более
        полного представления об алгоритме смотри указанную выше статью.
    Пример
          function DissimilarityIndex(S1, S2 : string) : real;
          var Set1,Set2 : LongInt;
              Possible, Actuel, Delta : Integer;
          begin
            Set1 := MakeLetterSet(S1);
            Set2 := MakeLetterSet(S2);
            Possible := CompareLetterSets(Set1, Set1);
            Actual   := CompareLetterSets(Set1, Set1);
            Delta : Possible - Actual;
            if Possible = 0 then
               DissimilarityIndex := 130;
            else
               DissimilarityIndex := Abs(Delta/Possible);
          end;
          var S1,S2 : string;
          begin
            repeat
              Write('Строка 1: '); ReadLn(S1);
              Write('Строка 2: '); ReadLn(S2);
              Set2 := MakeLetterSet(S2);
              WriteLn('Индекс  ',DissimilarityIndex(S1,S2):1:3);
            until False; {нажми ^C для остановки}
            end.
    Синтаксис
        function CompString(S1, S2 : string) : CompareType;
    Назначение
        Возвращает меньше, равно, больше если S1<S2, S1=S2, S1>S2.
    Замечания
        CompString  является  почти такой же что и стандартный инфиксный
        оператор сравнения строк в Турбо Паскале, но с одним преимущест-
        вом. CompString требуется только одна операция  сравнения  чтобы
        определить  результат,  в  то время как для инфиксного оператора
        требуется  по  крайней   мере   два   сравнения.   Следовательно
        CompString работает быстрее.
    Примеры
          var
            l1,l2 : string;
          case CompString(l1,l2) of
               Less :    writeln('l1 < l2');
               Equal:    writeln('l1 = l2');
               Greater : writeln('l1 > l2');
          end;
        Этот кусок программы может быть использован для иллюстрации всех
        трех результатов.

          CompString('aaa','aaaa');
        Возвращает Less (меньше).
          CompString('aaab','aaaa');
        Возвращает Greater (больше).
          CompString('Аaaa','aaaa');
        Возвращает Less (меньше).
    Смотри также
        CompStruct                           CompUCString

    Синтаксис
        function CompStruct(var S1, S2; Size : Word) : CompareType;
    Назначение
        Сравнение двух структур заданного размера.
    Замечания
        Паскаль не имеет встроенных средств сравнения структурных  типов
        данных,  таких  как  массивы или записи. В некоторых случаях это
        является очень важным. Например, запись содержит число и следую-
        щую за ним строку. Сравнивающая программа не имеет никакого  ра-
        зумного  способа  определить  что встроена строка и в результате
        посторонние символы на расстоянии  длины  текущей  строки  будут
        влиять на результат сравнения.
        Несмотря на все трудности сравнение структур необходимо. Функция
        CompStruct предоставляет такую возможность. Хотя CompStruct воз-
        вращает  результат  в виде Less (меньше), Equel (равно), Greater
        (больше),  в  большинстве  случаев  достаточно просто заключения
        равно или нет. CompStruct использует  побайтный  ASCII  алгоритм
        сравнения для определения больше или меньше.
        Заметим  что  могут  возникнуть проблемы при обработке вложенных
        строк. Отслеживание этих ситуаций возлагается на программиста.
        Size передает CompStruct число сравниваемых байт. Лучший  способ
        задания  Size является использование встроенной функции SizeOf()
        из Турбо.
    Примеры
          type
            ArrayType = array[1..3] of byte;
          const
            A1 : ArrayType = (0, 1, 2);
            A2 : ArrayType = (0, 1, 3);
            A3 : ArrayType = (0, 1, 2);
          CompStruct(A1, A2, SizeOf(ArrayType));
        Возвращает Less (меньше).
          CompStruct(A1, A3, SizeOf(ArrayType));
        Возвращает Equal (равно).

    Синтаксис
        function CompUCString(S1, S2 : string) : CompareType;
    Назначение
        Сравнивает две строки  игнорируя  различия  между  заглавными  и
        строчными буквами.
    Замечания
        CompUCString  переводит все строчные буквы в заглавные до начала
        сравнения. Хотя CompUCString работает медленнее чем CompString и
        встроенная функция сравнения строк в Турбо, это намного  быстрее
        чем  вызов StUpCase и затем нормальное сравнение строк. Заметим,
        что CompUCString работает корректно со всеми алфавитными  симво-
        лами ( 'A'..'Z' , 'a'..'z' , #128..#154 , #160..#167).
    Примеры
         CompUCString('AAA','aaaa');
        Возвращает Less (меньше).
         CompUCString('AAAВ','aaaa');
        Возвращает Greater (больше).
         CompUCString('Aааа','aaaa');
        Возвращает Equal (равно).

    Синтаксис
        function DefaultExtension(Name : string; Ext : ExtStr) : string;
    Назначение
        Возвращает имя файла или путь поиска с заданным расширением.
    Замечания
        Если Name уже содержит расширение то никаких изменений не произ-
        водится. В противном случае Ext добавляется. При этом Ext должна
        содержать не более трех символов и не начинаться с точки.
    Примеры
         DefaultExtension('TEST','pas');
        Возвращает 'TEST.pas'.
         DefaultExtension('TEST.','pas');
        Возвращает 'TEST.'.
    Cмотри также
        ForceExtension

    Синтаксис
        function Detab(S : string; TabSize : Byte) : string;
    Назначение
        Заменяет  символы  табуляции  в  строке S на указанное в TabSize
        число пробелов.
    Замечания
        DeTab убирает символы табуляции из строки заменяя их на  указан-
        ное  число  пробелов.  В отличии от EnTab DeTab обрабатывает все
        виды строк вне зависимости содержат ли  они  буквенные  символы.
        Для  большинства  текстовых  редакторов  TabSize  равно  8. Если
        TabSize равно 0, то ничего не вставляется.
    Пример
         var
           S : string;
         begin
           while not EOF(Input) do begin
             ReadLn(Input, S);
             WriteLn(Output, DeTab(S, 8));
           end;
         end.
        Программа реализующая замену символов табуляции на 8 пробелов  в
        любом текстовом файле.
    Смотри также
        EnTab

    Синтаксис
        procedure DiposeString(P : StringPtr);
    Назначение
        Освобождает память используемую для хранения строки c указателем
        Р.
    Замечания
        В прикладных программах обрабатывающих большие текстовые  данные
        лучше использовать строки как динамически распределяемые объекты
        а  не глобальные переменные. Динамическое распределение обладает
        двумя преимуществами : оно позволяет  использовать  все  640  Кб
        оперативной памяти и строки занимают только минимально необходи-
        мый  для их размещения объем, а не максимально возможный, равный
        длине наибольшей строки. Например,  допустим  мы  должны  читать
        строки  текстового  файла и размещать их в памяти для обработки.
        При хранении строк как глобальных данных даже на один символ  мы
        должны расходовать строку равную длине наибольшей строки из тек-
        стового  файла. Но при использовании динамического распределения
        для каждой строки мы выделим столько сколько ей точно  необходи-
        мо.  DisposeString  работает  вместе  с  функцией  StringToHeap.
        StringToHeap выделяет динамическую память для заданной строки  и
        возвращает  указатель  на  эту строку. DisposeString освобождает
        динамическую память связанную с заданным указателем. Если  пере-
        дается пустой указатель, то никаких действий не производится.
    Пример
         var
           P : pointer;
           S : string;
         begin
           P := StringToHeap('hello');
           S := StringFromHeap(P);
           DisposeString(P);
         end;
        Первый вызов StringToHeap выделяет 6  байт  динамической  памяти
        для   хранения   'hello'   и   еще   один  для  хранения  длины.
        StringFromHeap загружает 'hello' в S. DisposeString  освобождает
        занятую память.
    Смотри также
        StringFromHeap                        StringToHeap

    Синтаксис
        function EnTab(S : string; TabSize : Byte) : string;
    Назначение
        Заменяет  пробелы в строке на табуляторы с расстоянием табуляции
        заданным в TabSize.
    Замечания
        EnTab сжимает строку путем замены пробельных отрезков на символы
        табуляции. EnTab различает литеральные строки ограниченные  оди-
        нарными или двойными кавычками и не заменяет пробелы внутри них.
        Она также узнает управляющий С"escape" символ '\' . Для большинс
        тва  текстовых  редакторов TabSize равно 8. Если TabSize ноль то
        будет возвращена пустая строка.
    Пример
         var S : string;
         begin
           while not EOF(Input) do begin
             ReadLn(Input, S);
             WriteLn(Output, EnTab(S, 8));
           end;
         end.
        Программа сжатия текстового файла путем замены пробелов на табу-
        ляторы.
    Смотри также
        DeTab

    Синтаксис
        function ExtractWord(N : Byte; S : string;
                             WordDelims : CharSet) : string;
    Назначение
        Используя заданный набор разделителей слов возвращает N-е  слово
        в строке.
    Замечания
        Эта  функция  возвращает N-е слово в заданной строке. WordDelims
        является задаваемым пользователем набором  символов,  по  которым
        определяется начало и конец слов. Набор, по крайней мере, должен
        содержать  '.'. Если S содержит меньше чем N слов, то возвращен-
        ная строка будет пустой.
    Пример
         S := 'Four score and years ago, our forefathers...';
         SixthWord := ExtractWord(6, S, [' ',',','.']);
        Возвращает 'ago', так как символ ',' является разделителем.
    Смотри также
        WordCount                            WordPosition

    Синтаксис
        function ForceExtendsion(Name : string; Ext : ExtStr) : string;
    Назначение
        Присоединяет заданное расширение к имени файла.
    Замечания
        Вне   зависимости   имело   ли   передаваемое   имя   расширение
        ForceExtendsion возвращает новое имя файла с заданным расширени-
        ем.
    Примеры
         ForceExtendsion('TEST','pas');
        Возвращает 'TEST.pas'.
         ForceExtendsion('TEST.','pas');
        Возвращает 'TEST.pas'.
         ForceExtendsion('C:\AUTOEXEC.BAT','pas');
        Возвращает 'C:\AUTOEXEC.PAS'.
    Смотри также
        DefaultExtension

    Синтаксис
        function Form(Mask : string; R : Float) : string;
    Назначение
        Возвращает отформатированную в соответствии с маской Mask  стро-
        ку содержащую цифры из R.
    Замечания
        Form является эквивалентом функции Form для чисел в  двоично-де-
        сятичном представлении в Турбо 3.0 и для вещественных чисел соп-
        роцессора  8087 в Турбо Паскале версии 5.5 и выше. Form наиболее
        удобна при составлении различных финансовых отчетов.
        Так как Паскаль не позволяет использовать в функциях  определяе-
        мых  пользователем  переменное  число параметров, функция Form в
        Object Professional  использует  один  параметр  типа Real.
        Маска  Mask  представляет  собой произвольную комбинацию обычных
        символов и строго упорядоченную  последовательность  специальных
        символов  #,*,@,$,-,+. Эти специальные символы определяют число-
        вые поля в которые Form запишет реальные цифры. При  этом,  если
        число  содержит  больше десятичных цифр, чем отведенное для него
        поле, то оно округляется, а если оно слишком большое,  то  соот-
        ветствующее поле заполняется звездочками.
        Специальные символы означают следующее :
        # - позиция для цифры. Если цифровое поле не содержит символов *
        или  #, то неиспользуемые цифровые позиции замещаются пробелами.
        Если цифровое поле не имеет знаковой позиции (отмеченной  +  или
        -)  и  число отрицательное, то перед числом ставится знак минус.
        Примеры :
                 Form('####', 34.567) возвращает '  35'
                 Form('####.##', -12.3) возвращает ' -12.30'
                 Form('##.##', 1000) возвращает '**.**'
        * - позиция для цифры. Неиспользуемые цифровые позиции  заполня-
            ются  звездочками.  Достаточно только  одного символа, чтобы
            вызвать этот эффект. Знак числа не указывается, если поле  не
            содержит знаковой позиции (+ или -). Примеры :
                 Form('*##.#', 4.567) возвращает '**4.57'
                 Form('****', 123) возвращает '*123'
        @  - позиция для цифры. Неиспользованные цифровые позиции запол-
            няются в этом случае нулями. Достаточно только одного симво-
            ла чтобы вызвать этот эффект. Знак числа не указывается,если
            поле не содержит знаковой позиции (+ или -). Примеры :
                 Form('@##', 9) возвращает '009'
                 Form('@@@.@@', 12.3) возвращает '012.3'
        $ - позиция для цифры. Знак доллара ставится перед числом.  Дос-
            таточно  только  одного  символа  чтобы вызвать этот эффект.
            Примеры :
                 Form('$####.##', 123.45) возвращает ' $123.45'
                 Form('*$####.##', 12.34) возвращает '***$12.34'
        - - позиция для знака. Если число положительное, то в этой пози-
            ции выводится пробел, если отрицательное, то знак минус.
                 Form('-###.##', 1.2) возвращает '-  1.20'
                 Form('-###.##', 1.2) возвращает '   1.20'
        + - позиция для знака. Если число положительное, то в этой пози-
            ции выводится плюс, если отрицательное, то знак минус.
                 Form('+###.##', 1.2) возвращает '-  1.20'
                 Form('*$####.##+', -12.34) возвращает '***$12.34-'
        , - десятичная или разделительная запятая.
        . - десятичная или разделительная точка. В последнем разряде ис-
            пользуется разделительная запятая или точка в зависимости от
            определения. Примеры :
                 Form('##,###,###.##',12345678.91) возвращает
                                                       '12,345,678.91'
                 Form('$#.###.###,##',   -12345.6) возвращает
                                                       '  -$12.345,60'
        Замечание : Наиболее часто задаваемый вопрос о работе Form каса-
        ется следующего :
                 WritelnLn( Form('###,###,###', 1000.0);
        Большинство пользователей ожидают получить ' 1,000'. Но они  по-
        лучают ' 1,000,000'. И это не трюк. Такой результат связан с ра-
        ботой  функции Form из TURBOBCD 3.0 , которая рассматривала пос-
        леднюю точку или запятую в маске как указатель на десятичную за-
        пятую, это позволяло, в свою очередь, применять Form в  странах,
        где  запятая используется в местах на которых американцы исполь-
        зуют точку. Для получения ожидаемого результата  вам  необходимо
        добавить  десятичную точку в конце маски ('###,###,###.'), и за-
        тем убрать ее из возвращенной Form строки (это фактически то что
        делает LongIntForm).
    Смотри также
        Form(OPBCD)                             LongIntForm

    Синтаксис
        function FullPathName(FName : string) : string;
    Назначение
        По  заданному  в  FName пути поиска файла (он обязательно должен
        существовать) возвращает полный путь поиска к нему.
    Замечания
        FullPathName  не  осуществляет  поиск заданного файла (для этого
        служит ExistOnPath), а возвращает полный путь поиска к нему, ис-
        пользуя  заданный  относительный путь поиска, что в свою очередь
        позволяет уже найти файл. Полный путь поиска включает имя диска,
        путь по дереву каталогов и имя файла.
        Во многих случаях FullPathName должна опрашивать ДОС для опреде-
        ления текущего каталога и текущего имени драйвера. Поэтому  диск
        должен быть вставлен в дисковод, иначе возникнет ошибка.
    Примеры
         FullPathName('AUTOEXEC.BAT');
        Возвращает 'C:\AUTOEXEC.BAT', если текущий драйвер C:.
         FullPathName('D:..\TEST\CHECK.PAS');
        Возвращает 'D:\EXAMPLES\..\TEST\CHECK.PAS', если текущий каталог
        D:\EXAMPLES.
    Смотри также
        ExistOnPath (OPDOS)

    Синтаксис
        function HexB(B : Byte) : string;
    Назначение
        Возвращает строку с 16-ричным кодом для переменной типа байт.
    Замечания
        Возвращает строку длины два для переменной типа байт. Лидирующие
        нули включаются. Символы '$' и 'h' не включаются.
    Примеры
         HexB(0)
        Возвращает '00'.
         HexB(250)
        Возвращает 'FA'.
    Смотри также
        HexL

    Синтаксис
        function HexL(L : Longint) : string;
    Назначение
        Возвращает  строку с 16-ричным кодом для переменной типа длинное
        целое.
    Замечания
        Возвращает строку длины 8 для переменной типа длинное целое. Ли-
        дирующие нули включаются. Символы '$' и 'h' не включаются.
    Примеры
         HexL(0)
        Возвращает '00000000'.
         HexL(655360)
        Возвращает '000A0000'.
    Смотри также
        HexH

    Синтаксис
        function HexPrt(P : Pointer) : string;
    Назначение
        Возвращает строку с 16-ричным кодом для переменной  типа  указа-
        тель.
    Замечания
        По   заданному   указателю   HexPrt  возвращает  строку  в  виде
        'ssss:oooo', где 'ssss' - сегмент 'oooo' - смещение.
    Пример
         if (ErrorAddr <> nil) or (ExitCode <> 0) then begin
            { обход обработки нажатия ^Break }
            if ExitCode <> $FF then
              Writeln('Ошибка ',HexW(ExitCode),' в ',HexPtr(ErrorAddr));
            { предотвращение вывода ошибки второй раз }
              ErrorAddr := nil;
              ExitCode  := 0;
         end;
        Приведенная  выше  программа  может быть использована в качестве
        обработчика ошибок в программе пользователя. HexPtr используется
        для пересылки адреса ошибки в строку с  последующим  выводом  на
        экран.

    Синтаксис
        function HexW(W : Word) : string;
    Назначение
        Возвращает строку с 16-ричным кодом для переменной типа слово.
    Замечания
        Возвращает строку длины 4 для переменной типа слово.  Лидирующие
        нули включаются. Символы '$' и 'h' не включаются.
    Примеры
         HexW(0);
        Возвращает '0000'.
         HexB(MaxInt);
        Возвращает '7FFF'.
    Смотри также
        HexL                                    HexW

    Синтаксис
        function JustExtension(Name : string) : ExtStr;
    Назначение
        Возвращает расширение файла.
    Замечания
        Имя диска, имена каталогов и имя файла убираются из Name и возв-
        ращается  только  расширение  файла без точки. Если имя файла не
        содержит расширения, то возвращается пустая строка.
    Примеры
         JustExtension('TEST.PAs');
        Возвращает 'PAS'.
         JustExtension('C:\DATAF');
        Возвращает ''.
    Смотри также
        JustName                                 JustPathName

    Синтаксис
        function JustFilename(PathName : string) : string;
    Назначение
        Возвращает только имя файла с расширением.
    Замечания
        Имя диска и имена каталогов убираются из PathName.  Эта  функция
        эффективна  если обрабатывается полный путь поиска вместе с име-
        нами каталогов и именем файла. Если в  передаваемой  строке  нет
        символов ':' и '\', то никаких действий не производится.
    Примеры
         JustFilename('C:\AUTOEXEC.BAT');
        Возвращает 'AUTOEXEC.BAT'.
         JustFilename('test.');
        Возвращает 'test.'.
    Смотри также
        JustName                                 JustPathName

    Синтаксис
        function JustName(PathName : string) : string;
    Назначение
        Возвращает только имя файла без расширения.
    Замечания
        Имя диска и имена каталогов убираются из PathName и возвращается
        только имя файла без расширения.
    Примеры
         JustName('TEST.PAS');
        Возвращает 'TEST'.
         JustName('C:\AUTOEXEC.BAT');
        Возвращает 'AUTOEXEC'

    Синтаксис
        function JustPathname(PathName : string) : string;
    Назначение
        Возвращает только имя диска и имена каталогов.
    Замечания
        Имя файла и расширение убираются из PathName. Эта функция эффек-
        тивна  если  обрабатывается  полный путь поиска вместе с именами
        каталогов и именем файла. Если в передаваемой строке нет  симво-
        лов ':' и '\', то никаких действий не производится.
    Примеры
         JustPathname('С:\AUTOEXEC.BAT');
        Возвращает 'C:\'.
         JustPathname('..\test\bug.pas');
        Возвращает '..\test'.
    Смотри также
        JustExtension                            JustFilename

    Синтаксис
        function LeftPad(S : string; Len : Byte) : string;
    Назначение
        Возвращает строку дополненную слева до длины Len пробелами.
    Замечания
        Пробелы будут добавляться с левой стороны заданной строки до тех
        пор, пока ее длина не будет равна Len. Если L имеет длину  боль-
        шую чем Len, то никаких действий не производится.
    Примеры
         LeftPad('hello',7);
        Возвращает '  hello'.
         LeftPad('gargantuan',5);
        Возвращает 'gargantuan'.
    Смотри также
        Center                                   Pad

    Синтаксис
        function LeftPadCh(S : string; Ch : Char; Len : Byte) : string;
    Назначение
        Возвращает строку дополненную слева до длины Len символами Ch .
    Замечания
        Символы будут добавляться с левой стороны заданной строки до тех
        пор,  пока ее длина не будет равна Len. Если L имеет длину боль-
        шую чем Len, то никаких действий не производится. Если S  пустая
        строка, то возвращается строка заполненная символами Ch.
    Примеры
         LeftPadCh('hello','-',7);
        Возвращает '--hello'.
         LeftPadCh('gargantuan','-',5);
        Возвращает 'gargantuan'.
    Смотри также
        Center                                   Pad

    Синтаксис
        function LoCase(Ch : Char) : Char;
    Назначение
        Возвращает символ Сh переведенный в нижний регистр.
    Замечания
        LoCase  преобразует  символ  верхнего регистра в соответствующий
        символ нижнего регистра. В отличии от LoCaseMac функция коррект-
        но  работает  со  всеми  алфавитными  символами   (  'A'..'Z'  ,
        'a'..'z' , #128..#154 , #160..#167).
    Примеры
         LoCase('A');
        Возвращает 'a'.
         LoCase(#165); { 'N' с тильдой ('~') }
        Возвращает #164 ('n' с тильдой).
    Смотри также
        StLoCase                                 UpCase

    Синтаксис
        function LoCaseMac(Ch : Char) : Char;
    Назначение
        Возвращает символ Сh переведенный в нижний регистр.
    Замечания
        Встроенный макрос позволяет производить преобразование с  макси-
        мально возможной быстротой.
    Примеры
         LoCaseMac('A');
        Возвращает 'a'.
         LoCaseMac(#165);
        Возвращает #165.
    Смотри также
        UpCaseMac

    Синтаксис
        function Long2Str(L : LongInt) : string;
    Назначение
        Преобразует  передаваемое  значение типа длинное целое/слово/це-
        лое/байт/короткое целое в строку.
    Замечания
        Эта функция вызывает встроенную в Турбо процедуру  Str  и  затем
        возвращает  результат  обратно.  Возвращаемая строка не содержит
        лидирующих и хвостовых пробелов.
        Турбо автоматически определяет тип передаваемого выражения.
    Примеры
         Long2Str(1000);
        Возвращает '1000'.
         Long2Str(-1);
        Возвращает '-1'.
    Смотри также
        Str2Int

    Синтаксис
        function LongIntForm(Mask : string; L : LongInt) : string;
    Назначение
        Возвращает отформатированную в соответствии с маской Mask  стро-
        ку содержащую цифры из L.
    Замечания
        LongIntForm совпадает по результатам действия с  функцией  Form,
        за  исключением того, что все точки и запятые в маске рассматри-
        ваются как разделители.
    Примеры
         LongIntForm('@@@@@', 1234);
        Возвращает '01234'.
         LongIntForm('##,###,###',12345678);
        Возвращает '12,345,678'.
         LongIntForm('##,###.###',12345678);
        Неправильная маска ! LongIntForm  возвращает  '12,345.678',  так
        как '.' и ',' рассматриваются как разделители.
    Смотри также
        Form

    Синтаксис
        function MakeLetterSet(S : string) : LongInt;
    Назначение
        Возвращает  значение типа длинное целое, рассматриваемое как би-
        товый массив  характеризующий символы в строке S.
    Замечания
        MakeLetterSet создает битовый массив (в форме длинного  целого),
        показывающий,  какие  алфавитные  символы содержатся в строке S.
        Например, если строка состоит из  одного  символа  'A'('a'),  то
        MakeLetterSet  возвратит  $00000001;  если - 'ABC'то $00000007 и
        так  далее.  Максимально  возможное  возвращаемое   значение   -
        $003FFFFF  (первые  26  бит установлены). Для большей информации
        смотри CompareLetterSets.
    Смотри также
        CompareLetterSets

    Синтаксис
        function OctalB(B : Byte) : string;
    Назначение
        Возвращает строку с 8-ричным кодом B типа байт .
    Замечания
        Возвращает строку длины 3 с 8-ричным кодом передаваемого  значе-
        ния. Лидирующие нули включаются.
    Примеры
         OctalB(0);
        Возвращает '000'.
         OctalB(255);
        Возвращает '377'.

    Синтаксис
        function OctalL(L : LongInt) : string;
    Назначение
        Возвращает строку с 8-ричным кодом L типа длинное целое .
    Замечания
        Возвращает строку длины 12 с 8-ричным кодом передаваемого значе-
        ния. Лидирующие нули включаются.
    Примеры
         OctalL(0);
        Возвращает '000000000000'.
         OctalL(655360);
        Возвращает '000002400000'.
    Смотри также
        OctalW

    Синтаксис
        function OctalW(W : Word) : string;
    Назначение
        Возвращает строку с 8-ричным кодом W типа слово .
    Замечания
        Возвращает строку длины 6 с 8-ричным кодом передаваемого  значе-
        ния. Лидирующие нули включаются.
    Примеры
         OctalW(0);
        Возвращает '000000'.
         OctalW(65535);
        Возвращает '177777'.
    Смотри также
        OctalB                                       OctalL

    Синтаксис
        function Pad(S : string; Len : Byte) : string;
    Назначение
        Возвращает
        Возвращает строку дополненную справа до длины Len пробелами.
    Замечания
        Пробелы будут  добавляться  с  правой стороны заданной строки до
        тех пор,  пока ее длина не будет равна Len.  Если L имеет  длину
        большую чем Len, то никаких действий не производится.
    Примеры
         Pad('hello',8);
        Возвращает 'hello   '.
         Pad('gargantuan',8);
        Возвращает 'gargantuan'.
    Смотри также
        Center                                   LeftPad

    Синтаксис
        function PadCh(S : string; Ch : Char; Len : Byte) : string;
    Назначение
        Возвращает строку дополненную справа до длины Len символами Ch .
    Замечания
        Символы будут  добавляться  с  правой стороны заданной строки до
        тех пор,  пока ее длина не будет равна Len.  Если L имеет  длину
        большую  чем  Len,  то никаких действий не производится.  Если S
        пустая строка, то возвращается строка заполненная символами Ch.
    Примеры
         PadCh('hello','-',8);
        Возвращает 'hello---'.
         PadCh('gargantuan','-',8);
        Возвращает 'gargantuan'.
    Смотри также
        LeftPadCh

    Синтаксис
        function Real2Str(R : Float; Width : Byte;
                          Places : ShortInt) : string;
    Назначение
        Преобразует действительные числа в строку.
    Замечания
        Эта функция вызывает встроенную в Турбо процедуру  Str,  которая
        преобразует  R  в строку длины Width, и затем возвращает резуль-
        тат. Places показывает до какого  знака производить  округление.
        Если  Places  равно -1, то результат выдается в экспотенциальной
        форме.
        Примечание : Если OPSTRING скомпилирован  с опцией {$N+}, то эта
        функция работает с переменными типа повышенной точности, иначе с
        переменными вещественного типа .
    Примеры
         R := 1234.56789;
         Str(R:7:2, S);
         S := Real2Str(R, 7, 2);
        В обоих случаях будет возвращено '1234.57'.
         Real2Str(1.23456, 10, -1)
        Возвращает '1.235E+00' при {$N-} или '1.2E+0000' при {$N+}.

    Синтаксис
        function Search(var Buffer; BufLength : Word;
                        var Match; MatLength : Word) : Word;
    Назначение
        Ищет Match в Buffer.
    Замечания
        Это достаточно быстрая функция поиска работающая одинаково хоро-
        шо как со строками, так и с более длинными  последовательностями
        байтов. Переменная в которой производится поиск передается пара-
        метром  Buffer.  Длина  области поиска - в BufLenght. Строка для
        поиска - в Match. Число символов для поиска - в MatLength.
        Если строка Match находится, то Search возвращает номер  символа
        с  которого  начинается совпадение (может быть и 0). Если строка
        Match не найдена, то возвращается $FFFF.
    Примеры
         var
           S, T : string;
           Posn : Word;
         ...
           S := 'Now is the time for the show to start';
           T := 'Now';
           Posn := Search(S[1], Length(S), T[1], Length(T)); {Posn = 0}
           T := 'the';
           Posn := Search(S[0], Length(S), T[1], Length(T)); {Posn = 8}
           Posn := Search(S[Posn+1], Length(S)-Posn, T[1], Length(T));
                                                             {Posn = 13}
           T := 'zzz';
           Posn := Search(S[0],Length(S),T[1],Length(T)); {Posn = $FFFF}
        Начиная поиск с нулевой позиции  строки,  мы  заставляем  Search
        возвращать результат в виде как и у функция Pos из Турбо. Однако
        в  этом случае вас могут подстерегать неприятности, так как байт
        длины включается в  число  просматриваемых  символов.  Перемещая
        указатель  в Buffer, как показано в примере, мы можем пропустить
        ненужные сравнения.
    Смотри также
        BMSearch                                     PosAsc(OPASCIIZ)

    Синтаксис
        function SearchUC(var Buffer; BufLength : Word;
                          var Match; MatLength : Word) : Word;
    Назначение
        Осуществляет поиск  Match  в  Buffer  игнорируя  различие  между
        строчными и заглавными буквами.
    Замечания
        Эта  функция  аналогична  функции Search  с той разницей, что во
        время поиска заглавные и строчные буквы не различаются.  Символы
        в обеих строк Buffer и Match до поиска переводятся в верхний ре-
        гистр. Это преобразование осуществляется только для поиска, сами
        строки не изменяются.
        Если  строка Match находится, то Search возвращает номер символа
        с которого начинается совпадение . Если строка Match не найдена,
        то возвращается $FFFF.
        SearchUC в 2-4 раза медленнее Search из-за преобразования в вер-
        хний регистр.
        Заметим, что SearchUC работает корректно  со  всеми  алфавитными
        символами ( 'A'..'Z' , 'a'..'z' , #128..#154 , #160..#167).
    Смотри также
        BMSearchUC                                  Search

    Синтаксис
        function Soundex(S : string) : string;
    Назначение
        Возвращает  4-х символьный код звучания (soundex) для передавае-
        мой строки.
    Замечания
        Этот код часто используется для сравнения похожих имен.  Soundex
        возвращает  4-х  символьную строку содержащую код, полученный по
        soundex-алгоритму. Первым символом в этой строке является  пере-
        веденный  в  верхний  регистр первый символ передаваемой строки.
        Оставшиеся 3 символа представляют собой  цифровой  код  звучания
        этой строки. Похоже звучащие строки будут считаться одинаковыми.
        Сравнение методом похожести по звучанию  эффективно  только  для
        строк состоящих из алфавитных символов. Лидирующие пробелы долж-
        ны быть удалены до вызова Soundex. Soundex переводит все символы
        в строке в верхний регистр.
    Примеры
         Soundex('macintosh');
        Возвращает 'M253'.
         Soundex('montoch');
        Возвращает 'M253'.

    Синтаксис
        function StLoCase(S : string) : string;
    Назначение
        Преобразует символы в передаваемой строке из верхнего регистра в
        нижний.
    Замечания
        Заметим, что StLoCase преобразует  только  буквенные  символы  в
        строке S ( 'A'..'Z' , 'a'..'z' , #128..#154 , #160..#167).
    Примеры
         StLoCase('ABC');
        Возвращает 'abc'.
         StLoCase('!@# rats!');
        Возвращает '!@# rats!'.
    Смотри также
        LoCase                                     StUpCase

    Синтаксис
        function Str2Int(S : string; var I : Integer) : Boolean;
    Назначение
        Преобразует  строку  в  целое число и возвращает истину в случае
        успешного завершения.
    Замечания
        Эта функция вызывает встроенную в Турбо  процедуру  Val, которая
        передает численный результат в переменную, переданную в качестве
        второго параметра,  и возвращает информацию об успешности выпол-
        нения  операции  в  качестве булеана.  До вызова Val из строки S
        удаляются все хвостовые пробелы.
        Если Str2Int возвращает False (ложь), то параметр I будет содер-
        жать номер позиции в S где произошла ошибка.  Если  передаваемая
        строка начинается с символа '$', то число в ней интерпретируется
        как шестнадцатиричное. Передаваемая строка может содержать лиди-
        рующие пробелы.
    Примеры
         Str2Int('   123', I);
        Возвращает True ( истина ) и I = 123.
         Str2Int('$00F0', I);
        Возвращает True ( истина ) и I = 240.
         Str2Int('12z', I);
        Возвращает False ( ложь ) и  I = 3.

    Синтаксис
        function Str2Long(S : string; var I : LongInt) : Boolean;
    Назначение
        Преобразует  строку в длинное целое и возвращает истину в случае
        успешного завершения.
    Замечания
        Эта функция вызывает встроенную в Турбо  процедуру  Val  которая
        передает численный результат в переменную, переданную в качестве
        второго параметра,  и возвращает информацию об успешности выпол-
        нения  операции  в  качестве булеана.  До вызова Val из строки S
        удаляются все хвостовые пробелы.
        Если Str2Long возвращает False (ложь), то параметр I  будет  со-
        держать  номер позиции в S где произошла ошибка. Если передавае-
        мая строка начинается с символа '$', то число в ней  интерпрети-
        руется  как  шестнадцатиричное. Передаваемая строка может содер-
        жать лидирующие пробелы.
    Пример
         Str2Int('$A0000', I):
        Возвращает True ( истина ) и I = 655360.
    Смотри также
        Long2Str

    Синтаксис
        function Str2Real(S : string; var R : Float) : Boolean;
    Назначение
        Преобразует  строку в действительное число и возвращает истину в
        случае успешного завершения.
    Замечания
        Эта функция вызывает встроенную в Турбо  процедуру  Val  которая
        передает численный результат в переменную, переданную в качестве
        второго параметра,  и возвращает информацию об успешности выпол-
        нения  операции  в  качестве булеана.  До вызова Val из строки S
        удаляются все хвостовые пробелы.
        Если Str2Real возвращает False (ложь), то параметр R  будет  со-
        держать  номер позиции в S где произошла ошибка.
        Примечание : Если OPSTRING скомпилирован  с опцией {$N+}, то эта
        функция работает с переменными типа повышенной точности, иначе с
        переменными вещественного типа .
    Примеры
         Str2Real('  -.123', R);
        Возвращает True ( истина ) и R = -0.123.
         Str2Real('123.4567', R);
        Возвращает False ( ложь ) и R = 5.0.

    Синтаксис
        function Str2Word(S : string; var I : Word) : Boolean;
    Назначение
        Преобразует строку в данные типа слово  и  возвращает  истину  в
        случае успешного завершения.
    Замечания
        Эта функция вызывает встроенную в Турбо  процедуру  Val  которая
        передает численный результат в переменную, переданную в качестве
        второго параметра,  и возвращает информацию об успешности выпол-
        нения  операции  в  качестве булеана.  До вызова Val из строки S
        удаляются все хвостовые пробелы.
        Если Str2Word возвращает False (ложь), то параметр I  будет  со-
        держать  номер позиции в S где произошла ошибка. Если передавае-
        мая строка начинается с символа '$', то число в ней  интерпрети-
        руется  как  шестнадцатиричное. Передаваемая строка может содер-
        жать лидирующие пробелы.
    Пример
         Str2Word('  123', I);
        Возвращает True ( истина ) и I = 123.
         Str2Word('12z', I);
        Возвращает False ( ложь ) и  I = 3.
    Смотри также
        Long2Str

    Синтаксис
        function StringFromHeap(P : StringPtr) : string;
    Назначение
        Возвращает строку по заданному указателю.
    Замечания
        В  прикладных программах обрабатывающих большие текстовые данные
        лучше использовать строки как динамически распределяемые объекты
        а не глобальные переменные. Динамическое распределение  обладает
        двумя  преимуществами:   оно  позволяет  использовать все 640 Кб
        оперативной памяти и строки занимают только минимально необходи-
        мый для их размещения объем, а не максимально возможный,  равный
        длине  наибольшей  строки.  Например,  допустим мы должны читать
        строки текстового файла и размещать их в памяти  для  обработки.
        При  хранении строк как глобальных данных даже на один символ мы
        должны расходовать строку равную длине наибольшей строки из тек-
        стового файла. Но при использовании динамического распределения,
        для каждой строки мы выделим столько сколько ей точно  необходи-
        мо.
        StringFromHeap   работает   вместе   с   функцией  StringToHeap.
        StringToHeap выделяет динамическую память для заданной строки  и
        возвращает  указатель  на  эту строку. StringFromHeap возвращает
        саму строку для последующей обработки.
        Если  указатель  пуст,  то  возвратится  пустая   строка.
        StringFromHeap может использоваться в строковых выражениях.
    Пример
         var
           P : pointer;
           S : string;
         begin
           P := StringToHeap('PASFILE.INC');
           S := 'C:\'+StringFromHeap(P);
         end;
        StringТoHeap   выделяет   12   байт   динамической   памяти  для
        'PASFILE.INC' и еще один байт длины.  StringFromHeap  пересылает
        'C:\PASFILE.INC' в S.
    Смотри также
        DisposeString

    Синтаксис
        function StringToHeap(S : string) : StringPtr;
    Назначение
        Выделяет память для S и возвращает указатель. StringToHeap выде-
        ляет динамическую память для заданной строки и возвращает указа-
        тель на эту строку. StringFromHeap возвращает  саму  строку  для
        последующей обработки.
        Если  динамической  памяти  недостаточно для размещения заданной
        строки, то возвращается нулевой указатель.
    Пример
        Смотри выше.
    Смотри также
        DisposeString                                StringFromHeap

    Синтаксис
        function StUpCase(S : string) : string;
    Назначение
        Преобразует символы в передаваемой строке из нижнего регистра  в
        верхний.
    Замечания
        Заметим, что StUpCase преобразует  только  буквенные  символы  в
        строке S ( 'A'..'Z' , 'a'..'z' , #128..#154 , #160..#167).
    Примеры
         StUpCase('hello');
        Возвращает 'HELLO'.
         StLoCase('!@# drat!');
        Возвращает '!@# DRAT!'.
    Смотри также
        StLoCase                                     UpCase

    Синтаксис
        function Trim(S : string) : string;
    Назначение
        Возвращает  строку с удаленными лидирующими и хвостовыми пустыми
        участками.
    Замечания
        Под пустыми участками понимаются любые ASCII символы с кодами 32
        и меньше. Пустое пространство внутри S не удаляется. Если  пере-
        даваемая строка состоит из одних пустых участков, то возвращает-
        ся пустая строка.
    Примеры
         Trim('  hello  ');
        Возвращает 'hello'.
         Trim(^I^I'hello'^I^I);
        Возвращает 'hello'.

    Синтаксис
        function TriamLead(S : string) : string;
    Назначение
        Возвращает строку с удаленными лидирующими пустыми участками.
    Замечания
        Под пустыми участками понимаются любые ASCII символы с кодами 32
        и меньше. Пустое пространство внутри S не удаляется. Если  пере-
        даваемая строка состоит из одних пустых участков, то возвращает-
        ся пустая строка.
    Примеры
         TrimLead('  hello  ');
        Возвращает 'hello  '.
         TrimLead(^I^I'hello'^M^J);
        Возвращает 'hello'^M^J.

    Синтаксис
        function TrimSpaces(S : string) : string;
    Назначение
        Возвращает строку с удаленными лидирующими и хвостовыми пробела-
        ми.
    Замечания
        TrimSpaces идентична Trim, но удаляет только пробелы.  Управляю-
        щие символы (#0 - #31) не изменяются.
    Примеры
         TrimSpaces('   hello   ');
        Возвращает 'hello'.
         TrimSpaces('^I^I'hello'^M^J);
        Возвращает ^I^I'hello'^M^J.

    Синтаксис
        function TriamTrail(S : string) : string;
    Назначение
        Возвращает строку с удаленными хвостовыми пустыми участками.
    Замечания
        Под пустыми участками понимаются любые ASCII символы с кодами 32
        и меньше. Пустое пространство внутри S не удаляется. Если  пере-
        даваемая строка состоит из одних пустых участков, то возвращает-
        ся пустая строка.
    Примеры
         TrimTrail('  hello  ');
        Возвращает '   hello'.
         TrimTrail(^I^I'hello'^M^J);
        Возвращает ^I^I'hello'.
    Смотри также
        Trim                                     TrimLead

    Синтаксис
        function UpCase(Ch : Char) : Char;
    Назначение
        Возвращает Сh переведенный в верхний регистр.
    Замечания
        Эта  функция  переводит  символы в верхний регистр. В отличии от
        стандартной функции UpCase из SYSTEM и UpCaseMac,  наша  функция
        работает  корректно  со всеми алфавитными символами ( 'A'..'Z' ,
        'a'..'z' , #128..#154 , #160..#167).
    Примеры
         UpCase('a');
        Возвращает 'A'.
         LoCase(#164); { 'n' с тильдой ('~') }
        Возвращает #165 ('N' с тильдой).
    Смотри также
        LoCase                                           StUpCase

    Синтаксис
        function UpCaseMac(Ch : Char) : Char;
    Назначение
        Возвращает символ Сh переведенный в верхний регистр.
    Замечания
        Встроенный макрос позволяет производить преобразование с  макси-
        мально возможной быстротой.
    Примеры
         UpCaseMac('a');
        Возвращает 'A'.
         UpCaseMac(#164);
        Возвращает #164.
    Смотри также
        LoCaseMac

    Синтаксис
        function WordCount(S : string; WordDelims : CharSet) : Byte;
    Назначение
        Используя заданные разделители возвращает число слов в строке.
    Замечания
        Эта  функция  возвращает число слов в заданной строке. WordCount
        использует для идентификации начала и конца слова заданный поль-
        зователем набор разделителей. В этом наборе  должен  присутство-
        вать  по  крайней  мере пробел, но, при необходимости, вы можете
        задать большее число разделителей как в примере ниже.
    Пример
         var
           S : string;
         const
           WordDelims : CharSet =
            [#0..'"','.',',',':',';','?','(',')','[',']','{','}'];
           N : Word = 0;
         begin
           while not EOF(Input) do begin
             ReadLn(Input, S);
             Inc(N, WordCount(S, WordDelims));
           end;
           WriteLn(N, ' слов во входном файле');
         end.
        Простая программа подсчета слов в текстовом файле.
    Смотри также
        ExtractWord

    Синтаксис
        function WordPosition(N : Byte; S : string;
                              WordDelims : CharSet) : Byte;
    Назначение
        Используя заданные разделители  возвращает  номер  первой  буквы
        N-го слова в строке S.
    Замечания
        Эта функция возвращает номер позиции N-го слова в заданной стро-
        ке  S.  WordPosition использует для идентификации начала и конца
        слова заданный пользователем набор разделителей. В  этом  наборе
        должен  присутствовать, по крайней мере, пробел. Если S содержит
        меньше чем N слов, то WordPosition возвращает 0.
    Пример
         S := 'Four score and seven years ago, our forefathers...';
         I := WordPosition(7, S, [' ', ',', '.']);
        Возвращает 33 ( позиция буквы 'o' в 'our' ).

    Синтаксис
        procedure WordWrap(InSt : string; var OutSt, Overlap : string;
                           Margin : Byte; PadToMargin : Boolean);
    Назначение
        Урезает строку InSt до Margin и передает результат  в  OutSt,  а
        остаток в Overlap.
    Замечания
        Эта процедура берет в качестве входа текстовую строку ( InSt ) и
        возвращает выходную строку ( OutSt ), содержащую  не  более  чем
        Margin символов. Если край урезания приходится на середину слова
        (оно  определяется  как  цепочка символов ограниченных пробелами
        или одним из концов строки), то выходная строка будет  содержать
        все  предшествующие  слова, а разрезанное слово и вся оставшаяся
        информация будет возвращена в Overlap. Переменная  OutSt  должна
        быть  достаточно длинна для размещения строки в Margin символов,
        а Overlap должна быть по крайней мере не меньше InSt.
        Если входная строка не разбивается на слова (  если  длина  InSt
        больше  чем  Margin и  нет  пробелов  между символами  InSt[1] и
        InSt[Margin] ), то выходная строка будет содержать просто первые
        Margin символов из InSt.
        PadToMargin показывает, нужно ли дополнять выходную строку  про-
        белами до длины Margin.
    Пример
         var
           InputString, OutputString : string;
         begin
           while not EOF(Input) do begin
             ReadLn(Input, InputString);
             InputString := Detab(InputString, 8);
             repeat
               WordWrap(InputString, OutputString,InputString,40,False);
               WriteLn(Output, OutputString);
             until Lenght(InputString) = 0;
           end;
         end.
        Простая  программа-фильтр  для текстовых ASCII файлов заменяющая
        символы табуляции на нужное число пробелов и усекающая строки до
        40 символов.
    Смотри также
        Detab

    С. OPASCIIZ: Длинные ASCIIZ строки.

    OPASCIIZ  определяет новый строковый тип данных для Турбо Паскаля. В
отличии от обычных строк в Турбо, которые ограничиваются  длиной  в  255
байт, строки типа ASCIIZ могут быть длиной да 65,520 символов.
    ASCIIZ строки определяются таким образом, как если бы они  использо-
вались  МС-ДОС для внутренних операций или при программировании на языке
Си.  ASCIIZ  строка  - это просто массив символов оканчивающихся  пустым
символом ( ASCII #0 ).
    При использовании ASCIIZ строк возникают два отрицательных  момента.
Первый,  нельзя сразу определить длину такой строки. Для определения ее,
вам надо просчитать все символы до встречи с нулевым. OPASIIZ  реализует
эту  операцию  с  помощью встроенного макроса Турбо и использует команду
процессора 8088 SCASB, которая предоставляет лучшие возможности.  Следо-
вательно, вычисление длины не является сложной проблемой.
    Второй  отрицательный  момент  может  проявляться при  использовании
ASCIIZ строк в некоторых приложениях. Так как нулевой  символ  указывает
на  конец  строки,  то  он  не  может входить в нее как элемент. Поэтому
ASCIIZ строки не могут содержать последовательности расширенных скан ко-
дов (они начинаются с пустого символа), если не перевести пустые символы
в другие.
    Хотя  ASCIIZ  строки  могут содержать до 65,520 символов, в OPASCIIZ
максимальная длина ограничивается 1024 символами. Это ограничение позво-
ляет объявлять некоторое число ASCIIZ строк как  глобальные  переменные,
не выскакивая при этом за границу сплошного 64К сегмента. Если вы хотите
работать  с  более  длинными  строками - измените константу MaxAsciiz. В
этом случае ASCIIZ строки должны, по возможности, распределяться в дина-
мической памяти.

    Константы

       MaxAsciiz = 1024;
    Максимальная длина Asciiz строк. Может быть увеличена до 65520.
       NotFound = $FFFF;
    Значение переменной, возвращаемое PosAsc и PosStr если искомая подс-
трока не найдена.

    Типы

       Asciiz = array[0..MaxAsciiz] of Char;
    Внутреннее представление ASCIIZ строк. Дополнительно  распределяется
еще одна символьная позиция для хранения нулевого байта конца.
       AsciizЗек = ^Asciiz;
    Указатель на ASCIIZ строку. Так как строки довольно большие, то  же-
лательно размещать их в динамической памяти.

    Синтаксис
        function Asc2Str(var A : Asciiz) : string;
    Назначение
        Преобразует Asciiz строку в обычную Турбо строку.
    Замечания
        Если Asciiz строка содержит более 255 символов, то она предвари-
        тельно усекается до принятой в Турбо.
    Пример
         var
           A : Asciiz;
           S : string;
         ...
         Str2Asc('hello', A);
         S := Asc2Str(A); { S получает 'hello' }
    Смотри также
        Str2Asc

    Синтаксис
        procedure AscCenter(var A : Asciiz;Width : Word;var B : Asciiz);
    Назначение
        Возвращает  отцентрированную  пробелами до заданной длины Asciiz
        строку.
    Замечания
        Если А имеет длину большую чем  Width,  то  возвращается  Asciiz
        строка В совпадающая с А. В противном случае, В представляет со-
        бой отцентрированную с помощью пробелов до заданной длины строку
        А.
    Пример
         var A, B : Asciiz;
         ...
         Str2Asc('hello', A);
         AscCenter(A, 10, B); { В содержит '  hello   ' }
    Смотри также
        Center(OPSTRING)

    Синтаксис
        procedure AscCenterCh(var A : Asciiz; Ch : Char; Width : Word;
                              var B : Asciiz);
    Назначение
        Возвращает  отцентрированную  символами  Ch  до  заданной  длины
        Asciiz строку.
    Замечания
        Если А имеет длину большую чем  Width,  то  возвращается  Asciiz
        строка В совпадающая с А. В противном случае, В представляет со-
        бой  отцентрированную  с  помощью  символов Ch до заданной длины
        строку А.
    Пример
         var A, B : Asciiz;
         ...
         Str2Asc('hello', A);
         AscCenterCh(A, '-', 10, B); { В содержит '---hello--' }
    Смотри также
        CenterCh(OPSTRING)

    Синтаксис
        procedure AscCharStr(Ch : Char; Len : Word; var A : Asciiz);
    Назначение
        Возвращает Asciiz строку длины Len заполненную символами Ch.
    Замечания
        Если  Len  равна  нулю, то возвращается нулевая Asciiz строка. В
        противном случае, возвращается Asciiz строка длины Len заполнен-
        ная символами Ch.
    Пример
         AscCharStr('-', 10, A)
        Возвращает A вида '----------'.
    Смотри также
        CharStr(OPSTRING)

    Синтаксис
        procedure AscFromHeap(P : AsciizPtr; var A : Asciiz);
    Назначение
        Возвращает Asciiz строку из динамической памяти, и пустую строку
        если указатель пуст.
    Замечания
        Так как Asciiz строки могут быть достаточно длинными,  то  жела-
        тельно  размещать их в динамической памяти, а не в сегменте дан-
        ных, где они быстро исчерпают доступные 64 Кб.
        AscFromHeap работает вместе с AscТоHeap и DisposeAsc.
        AscТоHeap выделяет динамическую память для Asciiz строки и возв-
        ращает указатель на нее. AscFromHeap пересылает данные из  дина-
        мической  памяти  в указанную переменную. DesposeAsc освобождает
        более ненужное пространство динамической памяти.
        Если указатель пуст, то AscFromHeap возвращает пустую строку.
        Заметим, что выражение
           A := P^;
        и выражение
           AscFromHeap(P, A);
        приведут к одному результату.
        Однако AscFromHeap работает быстрее, так как передает только ре-
        альные данные , а не все байты содержащиеся в структуре.
    Пример
         var
           P : AsciizPtr;
           A : Asciiz;
         begin
           Str2Asc('hello', A);
           P := AscToHeap(A);
           AscFromHeap(P, A); { A получает 'hello' }
         end.
    Смотри также
        AscToHeap                              StrFromHeap(OPSTRING)
        DisposeAsc

    Синтаксис
        procedure AscLeftPad(var A : Asciiz; Len : Word;var B : Asciiz);
    Назначение
        Возвращает  в  B  Asciiz строку А дополненную слева до длины Len
        пробелами.
    Замечания
        Если A имеет длину большую или равную Len, то В просто совпадает
        с А. Иначе, содержимое А переносится в В и затем с левой стороны
        добавляются пробелы, пока длина В не будет равна Len.
    Примеры
         var A, B : Asciiz;
         ...
         Str2Asc('hello', A);
         AscLeftPad(A, 10, B); { B содержит '     hello' }
    Смотри также
        AscPad                                    LeftPad(OPSTRING)

    Синтаксис
        procedure AscLeftPadCh(var A : Asciiz; Ch : Char; Len : Word;
                               var B : Asciiz);
    Назначение
        Возвращает в B Asciiz строку А дополненную слева  до  длины  Len
        символами Ch.
    Замечания
        Если A имеет длину большую или равную Len, то В просто совпадает
        с А. Иначе, содержимое А переносится в В и затем с левой стороны
        добавляются символы Ch, пока длина В не будет равна Len.
    Примеры
         var A, B : Asciiz;
         ...
         Str2Asc('hello', A);
         AscLeftPadCh(A, '-', 10, B); { B содержит '-----hello' }
    Смотри также
        AscPadCh                                  LeftPadCh(OPSTRING)

    Синтаксис
        procedure AscLoCase(var A, B : Asciiz);
    Назначение
       Преобразует символы Asciiz строки А в нижний регистр и возвращает
       результат в В.
    Замечания
        Каждый символ из строки А переводится в нижний регистр и переда-
        ется в строку В. Заметим, что AscLoCase преобразует только алфа-
        витные символы ( 'A'..'Z' , 'a'..'z' , #128..#154 , #160..#167).
    Пример
         var A, B : Asciiz;
         ...
         Str2Asc('HELLO', A);
         AscLoCase(A, B); { B содержит 'hello' }
    Смотри также
        StLoCase(OPSTRING)

    Синтаксис
        procedure AscPad(var A : Asciiz; Len : Word;var B : Asciiz);
    Назначение
        Возвращает  в  B Asciiz строку А дополненную справа до длины Len
        пробелами.
    Замечания
        Если A имеет длину большую или равную Len, то В просто совпадает
        с А. Иначе, содержимое А переносится в В и затем с правой сторо-
        ны добавляются пробелы, пока длина В не будет равна Len.
    Примеры
         var A, B : Asciiz;
         ...
         Str2Asc('hello', A);
         AscPad(A, 10, B); { B содержит 'hello     ' }
    Смотри также
        AscLeftPad                                 PadCh(OPSTRING)

    Синтаксис
        procedure AscPadCh(var A : Asciiz; Ch : Char; Len : Word;
                               var B : Asciiz);
    Назначение
        Возвращает  в  B Asciiz строку А дополненную справа до длины Len
        символами Ch.
    Замечания
        Если A имеет длину большую или равную Len, то В просто совпадает
        с А. Иначе, содержимое А переносится в В и затем с правой сторо-
        ны добавляются символы Ch, пока длина В не будет равна Len.
    Примеры
         var A, B : Asciiz;
         ...
         Str2Asc('hello', A);
         AscPadCh(A, '-', 10, B); { B содержит 'hello-----' }
    Смотри также
        AscLeftPadCh                              PadCh(OPSTRING)

    Синтаксис
        function AscToHeap(var A : Asciiz) : AsciizPtr;
    Назначение
        Размещает Asciiz строку в динамической памяти и возвращает  ука-
        затель  на нее, в случае нехватки памяти возвращает нулевой ука-
        затель.
    Замечания
        Так как Asciiz строки могут быть достаточно длинными,  то  жела-
        тельно  размещать их в динамической памяти, а не в сегменте дан-
        ных, где они быстро исчерпают доступные 64 Кб.
        AscToHeap работает вместе с AscFromHeap и DisposeAsc.
        AscТоHeap выделяет динамическую память для Asciiz строки и возв-
        ращает указатель на нее. AscFromHeap пересылает данные из  дина-
        мической  памяти  в указанную переменную. DesposeAsc освобождает
        более ненужное пространство динамической памяти.
        Если для размещения строки не хватает  динамической  памяти,  то
        возвращается  нулевой указатель. Заметим, что AscТоHeap выделяет
        только минимально  необходимый  объем  памяти  для  передаваемой
        Asciiz строки. Если вместо этого вы хотите выделить пространство
        достаточное  для  размещения наибольшей Asciiz строки, вы должны
        использовать следующее выражение :
         New(P); { где Р типа AsciizPtr (указатель на Asciiz строку)}
    Пример
         var
           P : AsciizPtr;
           A : Asciiz;
         begin
           Str2Asc('hello', A);
           P := AscToHeap(A); { P^ содержит 'hello'#0 }
         end.
    Смотри также
        AscFromHeap                           StrFromHeap(OPSTRING)
        DisposeAsc

    Синтаксис
        procedure AscTrim(var A, B : Asciiz);
    Назначение
        Возвращает Asciiz строку с удаленными лидирующими  и  хвостовыми
        пустыми участками.
    Замечания
        Под пустыми участками понимаются любые ASCII символы с кодами 32
        и меньше, исключая символ #0 указывающий на конец Asciiz строки.
        Если передаваемая строка А состоит из одних пустых участков,  то
        В  возвращается  пустой строкой. Пустое пространство внутри А не
        удаляется.
    Примеры
         var A, B : Asciiz;
         ...
         Str2Asc(' hello world! ', A);
         AscTrim(A, B); { B содержит 'hello world!' }
    Смотри также
        AscTrimLead                              Trim(OPSTRING)
        AscTrimTrail

    Синтаксис
        procedure AscTrimLead(var A, B : Asciiz);
    Назначение
        Возвращает Asciiz строку с удаленными лидирующими пустыми участ-
        ками.
    Замечания
        Под пустыми участками понимаются любые ASCII символы с кодами 32
        и меньше, исключая символ #0 указывающий на конец Asciiz строки.
        Если передаваемая строка А состоит из одних пустых участков,  то
        В  возвращается  пустой строкой. Пустое пространство внутри А не
        удаляется.
    Примеры
         var A, B : Asciiz;
         ...
         Str2Asc('  hello world!  ', A);
         AscTrimLead(A, B); { B содержит 'hello world!  ' }
    Смотри также
        AscTrim                              TrimLead(OPSTRING)

    Синтаксис
        procedure AscTrimTrail(var A, B : Asciiz);
    Назначение
        Возвращает Asciiz строку с удаленными хвостовыми пустыми  участ-
        ками.
    Замечания
        Под пустыми участками понимаются любые ASCII символы с кодами 32
        и меньше, исключая символ #0 указывающий на конец Asciiz строки.
        Если передаваемая строка А состоит из одних пустых участков,  то
        В  возвращается  пустой строкой. Пустое пространство внутри А не
        удаляется.
    Примеры
         var A, B : Asciiz;
         ...
         Str2Asc(' hello world! ', A);
         AscTrimTrail(A, B); { B содержит ' hello world!' }
    Смотри также
        AscTrimLead                           TrimTrail(OPSTRING)

    Синтаксис
        procedure AscUpCase(var A, B : Asciiz);
    Назначение
        Преобразует  символы Asciiz строки А в верхний регистр и возвра-
        щает результат в В.
    Замечания
        Каждый символ из строки А переводится в верхний регистр и  пере-
        дается  в строку В. AscUpCase преобразует только алфавитные сим-
        волы ( 'A'..'Z' , 'a'..'z' , #128..#154 , #160..#167).
    Пример
         var A, B : Asciiz;
         ...
         Str2Asc('hello!', A);
         AscUpCase(A, B); { B содержит 'HELLO!' }
    Смотри также
        AscLoCase                             StUpCase(OPSTRING)

    Синтаксис
        function CompAsc(var A1, A2 : Asciiz) : AscCompareType;
    Назначение
        Возвращает меньше, равно, больше если A1<A2, A1=A2, A1>A2.
    Замечания
        Две Asciiz  строки сравниваются по тем же правилам что и обычные
        строки. Функция возвращает результат перечислимого типа принима-
        ющий  значения  AscLess (меньше),  AscEqual (равно),  AscGreater
        (больше).
    Примеры
        Смотри примеры для CompString(OPSTRING).
    Смотри также
        CompString(OPSTRING)

    Синтаксис
        function CompUCAcs(var A1, A2 : Asciiz) : AscCompareType;
    Назначение
        Сравнивает две Asciiz строки игнорируя различия между заглавными
        и строчными буквами.
    Замечания
        Две  Asciiz строки сравниваются по тем же правилам что и обычные
        строки. Во время сравнения все алфавитные символы переводятся  в
        верхний  регистр, но при этом сами строки не изменяются. Функция
        возвращает результат  перечислимого  типа  принимающий  значения
        AscLess   (меньше),   AscEqual   (равно),  AscGreater  (больше).
        СompUCAsc преобразует только алфавитные  символы  (  'A'..'Z'  ,
        'a'..'z' , #128..#154 , #160..#167).
    Примеры
        Смотри примеры для CompUCString(OPSTRING).
    Смотри также
        CompUCString(OPSTRING)

    Синтаксис
        procedure ConcatAsc(var A, B, C : Asciiz);
    Назначение
        Объединяет две Asciiz строки в возвращаемую третью.
    Замечания
        Эта процедура является аналогом выражения для обычных строк С :=
        А  +  В.  Если длина результирующей строки превышает максимально
        допустимую для Asciiz, то лишние символы отбрасываются.
    Пример
         var A, B, C : Asciiz;
         ...
         Str2Asc('hello ', A);
         Str2Asc('world!', B);
         ConcatAsc(A, B, C); { C содержит 'hello world!' }
    Смотри также
        ConcatStr

    Синтаксис
        procedure ConcatStr(var A : Asciiz; B : string; var C : Asciiz);
    Назначение
        Объединяет строку Asciiz с обычной строкой в возвращаемую третью
        типа Asciiz.
    Замечания
        Эта процедура является аналогом выражения для обычных строк С :=
        А  + В. В нашем случае объединяются строка типа Asciiz с обычной
        в Турбо строкой и результат  передается  в  третью  строку  типа
        Asciiz.  Если  длина результирующей строки превышает максимально
        допустимую для Asciiz, то лишние символы отбрасываются.
    Пример
         var A, B : Asciiz;
         ...
         Str2Asc('hello ', A);
         ConcatAsc(A, 'world!, B); { B содержит 'hello world!' }
    Смотри также
        ConcatAsc

    Синтаксис
        procedure CopyAsc(var A : Asciiz; Start, Len : Word;
                          var O : Asciiz);
    Назначение
        Возвращает подстроку из А.
    Замечания
        Эта процедура является аналогом функции Copy для обычных  строк.
        Len  символов  строки  А  начиная с позиции Start пересылаются в
        строку О. Заметим, что Start=0 указывает на первый символ в А.
        Если в Len задано больше символов чем в А доступно, возвращаются
        все которые доступны. Если Start больше чем длина у А, то  возв-
        ращается пустая строка.
    Пример
         var A, B : Asciiz;
         ...
         Str2Asc('hello ', A);
         CopyAsc(A, 1, 3, B); { B содержит 'ell' }
         CopyAsc(A, 4, 10, B); { B содержит 'о' }

    Синтаксис
        procedure DeleteAsc(var A : Asciiz; Start, Len : Word);
    Назначение
        Удаляет Len символов строки А, начиная с позиции Start.
    Замечания
        Эта  процедура  аналогична  функции Delete для нормальных строк.
        Len символов удаляются из строки А, начиная с позиции Start. Ес-
        ли Start=0, то удаление начинается с первого символа в  А.  Если
        запрашивается  для  удаления  больше символов чем существует, то
        удаляются все существующие, начиная с соответствующей позиции.
        Если Start больше чем длина строки, то А не изменяется.
    Пример
         var A : Asciiz;
         ...
         Str2Asc('hello ', A);
         DeleteAsc(A, 10, 10); { A не изменяется }
         DeleteAsc(A, 1, 1);   { A содержит 'hllo' }
         DeleteAsc(A, 0, 2);   { A содержит 'llo'  }

    Синтаксис
        procedure DisposeAsc(P : AsciizPtr);
    Назначение
        Удаляет из динамической памяти строку с указателем Р.
    Замечания
        Так как Asciiz строки могут быть достаточно длинными,  то  жела-
        тельно  размещать их в динамической памяти, а не в сегменте дан-
        ных, где они быстро исчерпают доступные 64 Кб.
        Dispose работает вместе с AscFromHeap и AscAscToHeap.
        AscТоHeap выделяет динамическую память для Asciiz строки и возв-
        ращает указатель на нее. AscFromHeap пересылает данные из  дина-
        мической  памяти  в указанную переменную. DesposeAsc освобождает
        более ненужное пространство динамической памяти.
        Если  указатель  пустой, то Dispose не производит никаких дейст-
        вий. Dispose не используется для освобождения  памяти  распреде-
        ленной  непосредственно  с  помощью оператора New. В этом случае
        используется встроенная в Турбо процедура Dispose.
    Пример
         var
           P : AsciizPtr;
           A : Asciiz;
         begin
           Str2Asc('hello', A);
           P := AscToHeap(A);
           DisposeAsc(P); { освобождает 6 байт динамической памяти и }
         end.             { обнуляет Р }
    Смотри также
        AscToHeap                              DisposeAsc(OPSTRING)

    Синтаксис
        procedure InsertAsc(var Obj, A : Asciiz; Start : Word);
    Назначение
        Вставляет Asciiz строку Obj начиная с позиции Start в строку А.
    Замечания
        Данная  процедура аналогична процедуре Insert для обычных строк.
        Строка Obj вставляется в  Asciiz  строку  А  начиная  с  позиции
        Start. Если Start=0, то вставка начинается с первой позиции в А.
        Если после вставки результирующая строка А превышает максимально
        допустимую  длину для Asciiz строк, то она усекается. Если Start
        превосходит длину строки А, то происходит присоединение Obj к А.
    Пример
         var A, B : Asciiz;
         ...
         Str2Asc('hello ', A);
         Str2Asc('world!', B);
         ConcatAsc(A, B, 0); { В содержит 'hello world!' }

    Синтаксис
        procedure InsertStr( Obj : string;var A : Asciiz; Start : Word);
    Назначение
        Вставляет  обычную  строку  Obj начиная с позиции Start в Asciiz
        строку А.
    Замечания
        Данная процедура аналогична процедуре Insert для обычных  строк.
        Обычная Турбо строка Obj вставляется в Asciiz строку А начиная с
        позиции  Start. Если Start=0, то вставка начинается с первой по-
        зиции в А.
        Если после вставки результирующая строка А превышает максимально
        допустимую  длину для Asciiz строк, то она усекается. Если Start
        превосходит длину строки А, то происходит присоединение Obj к А.
    Пример
         var A : Asciiz;
         ...
         Str2Asc('world!', A);
         ConcatAsc('hello ', A, 0); { A содержит 'hello world!' }

    Синтаксис
        function LenAsc(A : Asciiz) : Word;
    Назначение
        Возвращает длину заданной Asciiz строки.
    Замечания
        Длина Asciiz строки - это число входящих в нее символов,  исклю-
        чая  нулевой символ конца строки. Поэтому она находится в диапа-
        зоне от 0 до MaxAsciiz.
        Так как LenAsc является вычислительной процедурой, то она реали-
        зована как встроенный макрос на языке  ассемблера.  Поэтому  она
        занимает  на  12-14 байт больше в исполняемом модуле вашей прог-
        раммы, чем обычный вызов функции. Более того, каждое  сканирова-
        ние  требует времени, и следовательно вам следует минимизировать
        количество вызовов LenAsc для одной и той же строки.
    Примеры
         var A : Asciiz; L : Word;
         ...
         Str2Asc('hello', A);
         L := LenAsc(A); { L присваивается 5 }
         DeleteAsc(A, 0, 5);
         L := LenAsc(A); { L присваивается 0 }

    Синтаксис
        function PosAsc(var ObjA, A : Asciiz) : Word;
    Назначение
        Возвращает позицию начала ObjA в А.
    Замечания
        Функция PosAsc аналогична функции Pos для  стандартных  строк  в
        Турбо.  Она возвращает позицию начала ObjA в А. Первая позиция в
        строке А - 0. Если ObjA не найдена в  А,  то  PosAsc  возвращает
        $FFFF  (что  может  рассматриваться  как  определенная константа
        NotFound).
    Примеры
         var A, B : Asciiz; Posn : Word;
         ...
         Str2Asc('hello world!', A);
         Str2Asc('aardvark', B);
         Posn := PosAsc(B, A); { Posn присваивается $FFFF }
         Str2Asc('hello', B);
         Posn := PosAsc(B, A); { Posn присваивается 0 }
    Смотри также
        PosStr                                  Search(OPSTRING)

    Синтаксис
        function PosStr(Obj : string;var A : Asciiz) : Word;
    Назначение
        Возвращает позицию начала стандартной строки Obj в Asciiz строке
        А, NotFound - если не найдена.
    Замечания
        Функция PosStr аналогична функции Pos для  стандартных  строк  в
        Турбо. Она возвращает позицию начала стандартной для Турбо стро-
        ки  Obj  в  Asciiz строке А. Первая позиция в строке А - 0. Если
        Obj не найдена в А, то PosAsc возвращает $FFFF (что может  расс-
        матриваться как определенная константа NotFound).
    Примеры
         var
           A : Asciiz;
           Posn : Word;
         begin
           Str2Asc('hello world!', A);
           Posn := PosStr('aardvark, A); { Posn присваивается $FFFF }
           Posn := PosStr('hello', A);   { Posn присваивается 0 }
         end.
    Смотри также
        PosAsc                                  Search(OPSTRING)

    Синтаксис
        function ReadLnAsc(var F : Text; var A : Asciiz) : Boolean;
    Назначение
        Читает  а  Asciiz строку из текстового файла и возвращает True (
        истина ) в случае успеха.
    Замечания
        Эта функция позволяет вам читать  длинные  строки  из  текстовых
        файлов. F - текстовый файл, предварительно открытый для чтения с
        буфером любого размера. В параметр А передается Asciiz строка из
        текстового  файла, заканчивающаяся перед символом перевод строки
        ( ASCII #13#10 ).
        Если  возникает  ошибка  ввода/вывода,  то  ReadLnAsc возвращает
        False ( ложь ). Если  достигнут  конец  файла,  то  возвращается
        False и пустая строка. Если строка из текстового файла превышает
        максимальный размер для строк Asciiz, то остаток отбрасывается.
    Пример
         var
           F : Text;
           A : Asciiz;
         begin
           Assign(F, 'LONG.TXT');
           Reset(F);                           {открыть для чтения}
           while not eof(F) do begin        {читать пока не конец файла}
             if not ReadLnAsc(F, A) then       {читать следующую строку}
               halt;                           {закончить из-за ошибки}
             if not WriteAsc(Output, A) then   {вывести Asciiz на экран}
               halt;                           {закончить из-за ошибки}
             WriteLn;                          {добавить конец строки}
           end;
         end.
    Смотри также
        WriteAsc

    Синтаксис
        procedure Str2Asc(S : string; var A Asciiz);
    Назначение
        Преобразует обычную Турбо строку в строку Asciiz.
    Замечания
        Данная  процедура  предоставляет  удобный  способ  инициализации
        Asciiz  строк.  Она преобразует стандартную Турбо строку (длиной
        до 256 символов) в Asciiz строку. Процедура может  пригодится  и
        при организации взаимодействия процедур Турбо с различными функ-
        циями  ДОС. При использовании процедуры всегда помните, что вст-
        реченный в обычной Турбо строке пустой символ воспримется при ее
        преобразовании в строку Asciiz как указатель конца.
    Пример
         var A : Asciiz;
         ...
         Str2Asc('hello', A); { A содержит 'hello'#0 }
    Смотри также
        Asc2Str

    Синтаксис
        function WriteAsc(var F : Text; var A : Asciiz) : Boolean;
    Назначение
        Записывает Asciiz строку в текстовый файл и  возвращает  True  (
        истина ) в случае успеха.
    Замечания
        Это функция позволяет вам записывать длинные строки в  текстовый
        файл. F - любой текстовый файл, предварительно открытый для чте-
        ния. Asciiz строка А записывается в файл без отбрасывания пусто-
        го символа.  При возникновении ошибки ввода/вывода функция возв-
        ращает False ( ложь ).
    Пример
         var
           F : Text;
           A : Asciiz;
         begin
           Assign(F, 'LONG.TXT');
           Reset(F);                           {открыть для чтения}
           while not eof(F) do begin        {читать пока не конец файла}
             if not ReadLnAsc(F, A) then       {читать следующую строку}
               halt;                           {закончить из-за ошибки}
             WriteAsc(Output, A)               {вывести Asciiz на экран}
             WriteLn;                          {добавить конец строки}
           end;
         end.
    Смотри также
        ReadLnAsc

    D. OPSTRDEV : форматирование строк

    Как  отмечалось  ранее,  модуль OPSTRDEV является очень маленьким. В
нем определяется единственная глобальная переменная (TpStr) и содержится
две крохотные функции (ReadStr и ReturnStr). Но эта простота  обманчива.
OPSTRDEV  позволяет  использовать достоинства одного из самых полезных в
Турбо операторов - оператора Write, путем предоставления всех  его  воз-
можностей форматирования, без пересылки информации в файл или на устрой-
ство вывода.
    Пользоваться OPSTRDEV очень просто : все что вы должны сделать - это
добавить OPSTRDEV в предложение USES в начале вашей программы.  OPSTRDEV
инициализируется  автоматически при выполнении вашей программы, при этом
"устройство" TpStr рассматривается как часть языка. Для создания  строки
заданного  формата вы должны использовать обычный оператор Write. Напри-
мер :
    Write(TpStr, 'Время счета:', Hours:2, 'часов', Minutes:2, 'минут.');
    Вы можете выбрать отформатированную строку двумя способами : вызвать
ReadStr для пересылки ее в заданную переменную, или вызвать ReturnStr :
    ReadStr(MyString);
    MyString := ReturnStr;
    ReadStr более эффективна чем ReturnStr(с точки зрения скорости и ис-
пользования стека) если вам нужно только переслать строку в  переменную.
Но ReturnStr является более гибкой при использовании возвращаемой строки
в качестве аргумента процедуры или функции.

    Переменные

       TpStr : Text;
    Это  "устройство", записывая в которое, вы создаете в нем отформати-
рованную строку с использованием OPSTRDEV. Например ,
       Write(TpStr, Pi:0:2);
    создаст строку '3.14'.  (  Наименование,  между  прочим,  пришло  из
ТPSTRDEV предшественника OPSTRDEV. )

    Синтаксис
        procedure ReadStr(var S : string);
    Назначение
        'Читает' строку из нашего строкового буфера в S.
    Замечания
        ReadStr пересылает находящуюся в данный момент в строковом буфе-
        ре строку, буфер ассоциируется с TpStr, и очищает его. В случае,
        когда вы не используете результат немедленно, применение ReadStr
        эффективнее чем ReturnStr.
    Пример
         Real1 := 6.95;
         Write(TpStr, 'Ставка: $', Real1:0:2, ' в час.');
         ReadStr(MyString);
        MyString после вызова ReadStr содержит 'Ставка: $6.95 в час.'.

    Синтаксис
        function ReturnStr : string;
    Назначение
        Возвращает содержимое нашего строкового буфера.
    Замечания
        ReturnStr возвращает находящуюся в данный момент в строковом бу-
        фере  строку, буфер ассоциируется с TpStr, и очищает его.В отли-
        чии от ReadStr, использование функции  эффективно  для  передачи
        содержимого строкового буфера в качестве параметра процедуре или
        функции минуя промежуточную переменную.
    Пример
         Real1 := 6.95;
         Write(TpStr, 'Ставка: $', Real1:0:2, ' в час.');
         FastWrite(ReturnStr, 1, 1, TextAttr);
        FastWrite будет передана строка 'Ставка: $6.95 в час.'.





    10. РАБОТА С DOS И BIOS

    А. Введение
    Турбо  Паскаль,  до последнего времени, предоставлял простые возмож-
ности работы с ДОС и BIOS, но для большинства приложений от вас требова-
лось написание ваших собственных программ для  реализации  специфических
целей. Стандартный модуль DOS в Турбо Паскале, до некоторой степени, об-
легчает  жизнь программисту, но оставляет огромные число пробелов. OPDOS
в Object Professional предназначен для заполнения этих пробелов. В отли-
чии от OPCRT, который полностью заменяет собственный модуль CRT в Турбо,
OPDOS просто дополняет DOS. Дополняя друг друга, они содержат большинст-
во функций, которые помогут вам использовать возможности ДОС и BIOS.
    В OPDOS сразу привлекают внимание возможности  работы  с  файлами  и
дисковыми устройствами. Эти функции осуществляют: подсчет числа установ-
ленных  дисководов;  выбор  нового  дисковода; классификацию дисководов;
чтение и запись по абсолютным секторам; считывание и  установку  текущей
DTA  ( область обмена с диском ); контроль на присутствие файла в задан-
ном каталоге; прямой ввод/вывод текстовых файлов.
    Другая  группа функций позволяет вам пользоваться возможностями рас-
печатки файлов, имеющимся  в ДОС 3.х. Используя PrintInstalled, вы може-
те определить, установлена ли PRINT.COM; применяя SubmitPrintFile вы по-
сылаете файл в буфер на распечатку; вы можете очень просто прервать  пе-
чать  ,  используя  CancelPrint или CancelAllPrintFiles. Имеется возмож-
ность с помощью GetPrintStatus посмотреть очередь на печать.
    Другая, еще большая группа функций, дает вам почти  полный  контроль
за  операционной средой ДОС. Вы можете модифицировать программную среду,
создавать пользовательскую среду, с целью передачи  информации  дочерним
процессам, и даже изменять главную часть среды ДОС.
    Возможно,  наиболее  необычной  функцией  в  OPDOS,  вам   покажется
ExecDos.  Хотя  функция Exec из DOS является полезной, однако при ее ис-
пользовании возникают две проблемы. Первая, почти во  всех  случаях  вам
требуется найти COMMAND.COM, путем поиска в среде ДОС текущего состояния
COMSPEC;  если вы не знаете, как найти COMMAND.COM, вы не сможете 'пере-
запустить ДОС' и использовать Exec. Второе, на этапе трансляции вы долж-
ны установить максимальное количество динамической  памяти,  необходимой
вашей  программе;  если вы не запросите достаточного количества памяти ,
то тем самым ограничите возможности Exec.
    ExecDos решает обе проблемы. Она автоматически находит  COMMAND.COM.
Все, что вам нужно сделать, это передать имя команды ДОС для выполнения,
при этом булевый флаг показывает, указали ли вы полный путь  поиска  для
исполняемого  файла. Более важно, что ExecDos позволяет использовать всю
доступную вашей программе память. До исполнения  заданной  ДОС  команды,
ExecDos освобождает выделенную для Турбо, но не занятую, память для пос-
ледующего  перераспределения. После выполнения команды вся память, выде-
ленная для ДОС, перераспределяется в соответствии с предшествующим  сос-
тоянием, и ваша программа снова получает к ней доступ.
    Процедура ShellWithPrompt предоставляет другие  дополнительные  воз-
можности.  ExecDos  используется  вместе с некоторыми другими функциями,
манипулирующими со средой ДОС; ShellWithPrompt позволяет вам выдать  при
перезапуске ДОС заданное приглашение. Например,

 Status:=ShellWithPrompt('Введи "EXIT" для возврата в MYPROG'^M^J,nil );

    выдаст напоминание пользователю, что для возврата из ДОС в его прог-
рамму (MYPROG) необходимо использовать "EXIT".
    Перейдем  теперь к такой же хорошей как и ExecDos и ShellWithPrompt,
хотя наверное можно считать  и  самой  лучшей,  функции  ExecDosSwap  из
OPEXEC.  Помимо  того, что она как и функции из OPDOS возвращает для ис-
пользования ДОС всю незанятую память из вашей программы, она может выде-
лить ДОС и почти всю занятую вашей программой память. Этот сложный  про-
цесс  будет  описан  в  последующих  частях  книги.  Отметим только, что
ExecDosSwap позволяет при работающей программе использующей память в 450
Кб запустить вторую программу с 447 Кб используемой памяти без  заверше-
ния первой.
    OPENHKBD объединена с OPDOS, так как их главные функции взаимодейст-
вуют с BIOS. Подобно OPEXEC, OPENHKBD не содержит большого числа  проце-
дур.  Вместо этого устанавливается пара обработчиков прерываний, которые
перехватывают все сигналы, идущие от клавиатуры. Эх цель  выполнять  две
функции:  упростить написание программ для поддержки усовершенствованной
клавиатуры ( с 12 функциональными клавишами )  и  позволить  для  старых
клавиатур, где это возможно, использовать режим эмуляции более совершен-
ных моделей.

    В. OPDOS : Обслуживание работы с ДОС/BIOS.
    В этой части описываются все типы, переменные, константы,  процедуры
и функции содержащиеся в OPDOS.

    Типы

      ActionCodeType = ExecSaveScreen..ExecRestoreScreen;
    Код  активизации  для  ExecDos.  Смотри значения для ExecSaveScreen,
ExecShowMemory, ExecPauseAfterRun и ExecRestoreScreen ниже.
      DiskClass = (Floppy360, Floppy720, Floppy12, Floppy144,
                  OtherFloppy, Bernoulli, HardDisk, RamDisk, SubstDrive,
                  UnknownDisk, InvalidDrive);
    Этот перечислимый тип определяет 8 классов дисков, которые идентифи-
цируются функцией GetDiskClass, и показывает некоторые типы  возникающих
ошибок. Каждое значение расшифровывается ниже :
      Floppy360     5 1/4 флоппи диск 360  Кб
      Floppy720     3 1/4 флоппи диск 760  Кб
      Floppy12      5 1/4 флоппи диск 1.2  Мб
      Floppy144     3 1/4 флоппи диск 1.44 Мб
      OtherFloppy   другой тип флоппи диска ( включая односторонние )
      Bernoulli     устройство Бернулли
      HardDisk      любой жесткий диск
      RamDisk       виртуальный диск созданный c помощью VDISK.SYS,
                    RAMDRIVE.SYS и т.д.
      SubstDrive    логический дисковод созданный SUTST или ASSIGN
      UnknownDisk   диск не может быть классифицирован
      InvalidDrive  показывает, что дисковод не существует или не готов

      EnvRec =
        record
          EnvSeg : Word;       { сегмент среды }
          EnvLen : Word;       { возможная длина среды }
          EnvPtr : Pointer;    { пустой при динамическом распределении }
        end;
    Этот  тип  предназначен для хранения информации об среде ДОС. EnvSeg
содержит адрес сегмента среды. По этому адресу начинается список ненуле-
вых строк , которые могут расширятся до 32 Кб  символов.  EnvLen  хранит
максимально  возможную  длину  данной  среды (но не текущую). EnvPrt при
обычных условиях нулевой. Он  используется  только  когда  вы  выделяете
пространство из динамической области Турбо Паскаля для  новой  среды,  и
даже  в  этом  случае, вы  не захотите ссылаться непосредственно на поле
EnvPrt.
    При возникновении ошибок в  программе,  работающей  с  EnvRec,  поле
EnvSeg  принимает  значение  ноль. Вам не следует продолжать работать со
средой, если EnvRec у нее равно нулю.

      ExecDosProc = procedure(ActionCode : ActionCodeType;Param : Word);
    Процедура,  написанная  пользователем,  которая  производит заданные
действия при вызове ExecDos или ShellWithPrompt.

    Константы

      ExecSaveScreen    = 0;
      ExecShowMemory    = 1;
      ExecPauseAfterRun = 2;
      ExecRestoreScreen = 3;
    Код активизации передается в ExecDos ( или ShellWithPrompt) в качес-
тве  параметра, имеющего тип ExecDosProc. ExecSaveScreen передается тог-
да, когда вам нужно сохранить экран (например  при  помощи  SaveWindow).
Заметим,  что  экранный  буфер  для  этого должен быть выделен до вызова
ExecDos. Код ExecShowMemory передается только перед вызовом ДОС.  Второй
передаваемый  параметр (типа слово) показывает примерное количество дос-
тупной памяти (в килобайтах). Код ExecPauseAfterRun передается после за-
вершения работы ExecDos. Он позволит вам попросить пользователя "Нажмите
любую клавишу..." с тем, чтобы избежать стирания информации на экране до
того, как пользователь смог рассмотреть ее.  Код  ExecRestoreScreen  ис-
пользуется толь тогда, когда у вас есть возможность восстановить экран.
    Замечание  :  Код  ExecShowMemory  передается в ExecDos только когда
строка Command пуста;  код  ExecPauseAfterRun  передается  только  когда
строка Command не пуста .

      MinSpaceForDos : Word = 20000;
    Минимальное  число байт для запуска ДОС. Если ExecDos не может осво-
бодить столько памяти, то ДОС не запускается.

      StackSafetyMargin : Word =1000;
    Используется ЕxecDos при пересылке из памяти списка свободных блоков
Если SizeOf(список свободных блоков) + StackSafetyMargin  <=  SP(текущий
указатель  вершины  стека),  то список свободных блоков будет сохранен в
стеке, иначе - в динамической памяти.

      StdInHandle  =  0;
      StdOutHandle =  1;
      StdErrHandle =  2;
      StdPrtHandle =  4;
    Стандартные  файловые  устройства ДОС (стандартный ввод, стандартный
вывод, стандартный вывод ошибок, стандартный принтер).


    Синтаксис
        procedure CancelAllPrintFiles;
    Назначение
        Отменяет печать всех файлов из очереди.
    Назначение
        Все  файлы, ожидающие распечатки, убираются из очереди. PRINT не
        допечатывает текущий файл.

    Синтаксис
        procedure CancelPrintFile(FileMask : string);
    Назначение
        Отменяет печать всех файлов из очереди, имена которых подходят к
        заданной маской.
    Замечания
        Эта  процедура  позволяет вам убирать из очереди заданные файлы.
        FileMask - любая действительная для ДОС файловая маска, содержа-
        щая универсальные символы ('?' и '*'). Если печатающийся в  дан-
        ный  момент  файл подходит к маске, то ДОС немедленно прекращает
        печать и переходит к обработке следующего файла из очереди.
    Примеры
         CancelPrintFile('*.DOC');
        Отменяет печать всех файлов с расширением 'DOC'.
         if SubmitPrintFile(CurrentPrintFile) <> 0 then {ошибка};
         ...
         CancelPrintFile(CurrentPrintFile);
        Останавливает печать текущего файла.

    Синтаксис
        procedure CopyEnv(Src, Dest : EnvRec);
    Назначение
        Копирует содержимое среды Src в среду Dest.
    Замечания
        Копирует одно окружение в другое. Если  окружение  Dest  меньше,
        чем  Src,  то  СopyEnv  копирует что возможно, отсекая последний
        элемент. При этом, никогда не копируется информация о пути поис-
        ка, которую ДОС 3.0+ помещает в конце обычного  окружения.  Если
        эта информация вам необходима, то для ее копирования используйте
        функцию   SetProgramStr.   Смотри   пример   в   ShellWithPrompt
        (OPDOS.PAS), иллюстрирующий этот случай.
    Пример
         var CEnv, NEnv : EnvRec;
         ...
         CurrentEnv(CEnv);
         NewEnv(NEnv, CEnv.EnvLen);
         CopyEnv(CEnv, NEnv);
         ...
         DisposeEnv(NEnv);
        Создает копию текущего окружения в NEnv.
    Смотри также
        NewEnv                                 SetProgramStr

    Синтаксис
        function CopyFile(SrcPath, DestPath : string; Buffer : Pointer;
                          BufferSize : Word) : Word;
    Назначение
        Копирует файл, специфицированный по SrcPath в DestPath.
    Замечания
        Эта функция  копирует  файл,  специфицированный  по  SrcPath,  в
        DestPath. В DestPath должно быть указано полное имя файла, и оно
        не должно совпадать с именем дисковода или каталога. Buffer дол-
        жен  указывать  на уже выделенный участок памяти,  содержащий не
        менее чем BufferSize байт.
        Так как это функция низкого уровня,  то проверки на допустимость
        заданного пути поиска не производится. Если во время копирования
        произошла   ошибка,   то   файл,   куда   копируется  информация
        (DestPath),  удаляется и в качестве результата возвращается  код
        ошибки. Возможные коды ошибок приведены ниже :

         0  Успех
         1  Невозможно открыть исходный файл
         2  Невозможно открыть выходной файл
         3  Ошибка чтения в исходном файле
         4  Ошибка записи в выходном файле
         5  Ошибка при чтении метки даты/времени для исходного файла
         6  Ошибка при установки метки даты/времени для выходного файла
         7  Ошибка при закрытии выходного файла

        Одна из ошибочных ситуаций не обнаруживается CopyFile, а  именно
        случай, когда исходный и выходной файлы совпадают (т.е. совпада-
        ют  SrcPath и DeatPath ). Чтобы избежать такой опасной ситуации,
        мы рекомендуем вам, до вызова CopyFile вызвать функцию SameFile,
        сравнивающую два имени файла.
    Пример
         var Buffer : array[1..4096] of Byte;
             FName, NewName : string[79];
         ...
         NewName := 'A:'+JustFileName(FName);
         if (not SameFile(FName, NewName, Status)) and (Status = 0) then
           Status := CopyFile(FName, NewName, Buffer, SizeOf(Buffer));
        Копирует файл FName на диск А:. Функция JustFileName из OPSTRING.
           Status := CopyFile(FName, 'A:', Buffer, SizeOf(Buffer));
        Ошибка ! В DestPath должно указываться полное имя файла.
    Смотри также
        SameFile

    Синтаксис
        procedure CurrentEnv(var Env : EnvRec);
    Назначение
        Возвращает запись текущей среды.
    Замечания
        Возвращает запись для текущей программной среды. Остается  срав-
        нительно  мало  места для добавления в эту среду, и, кроме того,
        все произведенные изменения игнорируются после завершения  теку-
        щей программы.
    Пример
        Смотри пример в описании CopyEnv.
    Смотри также
        MasterEnv

    Синтаксис
        function DefaultDrive : Char;
    Назначение
        Возвращает текущий дисковод в виде заглавной буквы.
    Замечания
        DefaultDrive  возвращает букву в диапазоне от 'A'..'Z'. Для пре-
        образования результата в номер дисковода  используйте  следующую
        команду :
         DriveNumber := Ord(DefaultDrive).64;
    Пример
         WriteLn('Текущий дисковод : ', DefaultDrive);
        На экране появится : 'Текущий дисковод : С', если текущий диско-
        вод С:.
    Смотри также
        NumberOfDrivers                         SelectDrive

    Синтаксис
        procedure DisposeEnv(var Env: EnvRec);
    Назначение
        Удаляет из динамической памяти ранее распределенную среду.
    Замечания
        Удаляет из динамической памяти ранее  распределенную  с  помощью
        NewEnv среду. Использование DisposeEnv с главной или программной
        средой не производит никаких действий.
    Пример
        Смотри пример в описании CopyEnv.
    Смотри также
        NewEnv

    Синтаксис
        function DosVersion : Word;
    Назначение
        Возвращает номер версии ДОС.
    Замечания
        Результат  возвращается  в  двоично-десятичном ( BCD ) виде, где
        номер самой версии находится в старшем байте, а номер ее модифи-
        кации - в младшем. Например, при использовании ДОС 3.1 результат
        будет $030A ( $0A = 10 ); при ДОС 2.11 - $020B ( $0B = 11 ); при
        ДОС $031E ( $1E = 30 ); и так далее.
        Замечание : В библиотеку DOS в Турбо Паскале 5.0  фирмы  Борланд
        была  добавлена функция, имеющая тоже название - DosVerasion. Но
        к сожалению, она возвращает противоположный  результат  :  номер
        самой версии находится в младшем байте, а номер ее модификации -
        в  старшем.  Мы  рекомендуем  вам при использовании этих функций
        указывать   префикс   модуля   (    OpDos.DosVersion    или
        Dos.DosVersion ).
    Пример
         if OpDos.DosVersion >= $0400 then
           WriteLn('Внимание: Программа не работает с ДОС 4.0 и выше');
        Проверка на ДОС 4.0 и выше.

    Синтаксис
        procedure DumpEnv(Env : EnvRec);
    Назначение
        Отображает заданную среду на экране.
    Замечания
        Выводит  все строки, содержащиеся в заданном окружении, на экран
        ( если Output не был переопределен в файл ). Процедура сообщает,
        также, число неиспользованных байт в среде.
    Пример
         Смотри пример программы при описании SetEnvStr.
    Смотри также
        SetEnvStr

    Синтаксис
        procedure EndPrintStatus;
    Назначение
        Отменяет действие процедуры GetPrintStatus на запрет печати.
    Замечания
        Позволяет продолжить печать файлов из очереди, запрещенную вызо-
        вом GetPrintStatus.
    Смотри также
        GetPrintStatus

    Синтаксис
        function EnvFree(Env : EnvRec) : Word;
    Назначение
        Возвращает число свободных байт в операционной среде.
    Замечания
        EnvStr возвращает число свободных байт в выбранной  операционной
        среде.  Вам  может понадобится эта величина при добавлении новой
        строки в среду, хотя, надо заметить, SetEnvStr производит анало-
        гичную проверку.
    Пример
         S := 'New string';
         if EnvFree(Env) >= (Lenght('NEW='+S)+1) then
           Added := SetEnvStr(Env, 'NEW', S);
        Добавляет 'NEW=New string' к заданной среде.
    Смотри также
        SetEnvStr

    Синтаксис
        function ExecDos(Command : string; UseSecond : Boolean;
                         EDP : ExecDosProc) : Integer;
    Назначение
        Выполняет любую команду ДОС.
    Замечания
        ExecDos, которая представляет собой значительно улучшенную  про-
        цедуру  Exec из Турбо Паскаля, временно сжимает динамическую об-
        ласть с тем, чтобы освободить максимально возможный объем памяти
        для выполнения заданной программы или команды ДОС. После ее  вы-
        полнения, динамическая область восстанавливается в своем прежнем
        виде.
        Command - имя программы или команда ДОС, которая должна быть вы-
        полнена. Command может быть пустой строкой (означает  -  "запус-
        тить  ДОС"). UseSecond показывает, нужно ли загружать вторую ко-
        пию COMMAN.COM для обслуживания вызова Exec.  Если  он  False  (
        ложь  ), то Command должна представлять собой полный маршрут по-
        иска  для  выполняемой  программы  (  Смотри  описание   функции
        ExistOnPath  ). Параметр EDP указывает на пользовательскую прог-
        рамму, которая должна выдать информацию о состоянии и  т.д.  Она
        должна иметь вид
         {$F+}
         procedure MyExecDosProc(ActionCode : ActionCodeType;
                                 Param : Word);
         begin
         end;
        Программа  представляет собой глобальную ( не вложенную ) проце-
        дуру, скомпилированную с дальним типом обращения  (FAR  модель).
        Если  вы  не хотите использовать процедуру такого типа, то пере-
        дайте в качестве третьего параметра 'NoExecDosProc' (описанная в
        OPDOS  как  ничего  неделающая   процедура).   Смотри   описание
        ActionCodeType  для более подробного изучения кода активации для
        ExecDos.
        ExecDos может возвращать следующие значения :

          0  Успешное завершение
         -1  Недостаточно памяти для хранения таблицы  свободных  блоков
             Турбо
         -2  Ошибка ДОС до вызова EXEC
         -3  Ошибка ДОС после вызова EXEC (критическая ошибка)
         -4  Недостаточно памяти для выполнения команды ДОС
          и еще все коды ошибок ДОС.

        ExecDos вызывает функцию SwapVectors из модуля DOS, с тем, чтобы
        восстановить все значения векторов прерываний, перехваченных мо-
        дулем SYSTEM. Она, однако, не восстанавливает вектора,  изменен-
        ные другими модулями, например OPENHKBD. Забота об этом возлага-
        ется на программиста.
        Предупреждение ! Никогда не используйте ExecDos для запуска  ре-
        зидентных  программ.  ExecDos предоставляет пользователю для вы-
        полнения его программы всю возможную память, но, после ее выпол-
        нения, часть выделенной памяти передается снова  в  распоряжение
        вызывающей  программе. Если вы попытаетесь запустить резидентную
        программу, то, скорее  всего,  ваш  вызов  закончится  аварийно,
        обычно с кодом возврата -3.
        Заметим также, что ExecDos может не работать с программами из-за
        несовместимости  их  с  интегрированной  средой Турбо Паскаля. В
        случае использования таких программ  ExecDos,  вероятнее  всего,
        возвратит код ошибки -2.
    Примеры
         Code := ExecDos('C:\TURBO\TPC.EXE'+ProgName, False, NoExecDosProc);
        Вызывает  компилятор  Турбо  для  компиляции  ProgName.  Так как
        UseSecond имеет значение False ( ложь ),  то  мы  должны  задать
        полный маршрут поиска для TPC.EXE.
         Code := ExecDos('MAKEMENU', True, NoExecDosProc);
        Вызывает MAKEMUNU. Будет загружена вторая копия COMMAND.COM  для
        поиска и выполнения нашей программы.
         var
           P : Pointer;
           BufSize : Word;
           Code : Integer;
         {$F+}
         procedure MyExecDosProc(ActionCode : ActionCodeType; Param : Word);
         var
           Key : WOrd;
         begin
          case ActionCode of
           ExecSaveScreen : {не выделять буфера экрана,сохранить экран}
            if not SaveWindow(1, 1, ScreenWidth, ScreenHeight, False, P)
              then {не могу выполнить - буфер уже выделен}
           ExecShowMemory : {показать память доступную для ком.проц.}
            WriteLn('Примерно : ', Param, 'Кб доступно');
           ExecPauseAfterRun : {заставить экран не очищаться слишком быстро}
             begin
               Write('Нажми любую клавишу...');
               Key := ReadKeyWord;
             end;
           ExecRestoreScreen : {восстановить экран, не освобождать буфер}
             RestoreWindow(1, 1, ScreenWidth, False, P);
          end;
         end;
         {$F-}
         ...
         {выделить буфер экрана}
         BufSize := 2*ScreenWidth*ScreenHeight;
         GetMem(P, BufSize);
         Code := ExecDos('', True, MyExecDosProc);
         FreeMem(P, BufSize);
        Запускает командный процессор,  MyExecDosProc  обрабатывает  код
        активизации.
    Смотри также
        ExecDosSwap(OPEXEC)                   ShellWithPrompt
        ExistOnPath                           StackSafetyMargin
        MinSpaceForDos

    Синтаксис
        function ExistFile(FName : string) : Boolean;
    Назначение
        Возвращает True ( истина ), если файл FName найден.
    Замечания
        В  ExistFile  не  используются универсальные символы для задания
        маски. Функция просматривает  только  текущий  или  указанный  в
        FName каталог.
    Примеры
         Found := ExistFile('C:\AUTOEXEC.BAT');
        ExistFile будет осуществлять поиск файла 'AUTOEXEC.BAT' в 'C:\'.
         Found := ExistFile('AUTOEXEC.BAT');
        ExistFile  будет осуществлять поиск файла 'AUTOEXEC.BAT' в теку-
        щем каталоге.
         Found := ExistFile('*.DOC');
        Ошибка ! ExistFile не воспринимает универсальных символов.

    Синтаксис
        function ExistOnPath(FName : string; var FullName : string)
                            : Boolean;
    Назначение
        Возвращает  True ( истина ) и допустимый путь доступа, если файл
        FName найден.
    Замечания
        В отличии от процедуры ExistFile, эта процедура при поиске файла
        просматривает не только текущий каталог. Если FName содержит имя
        дисковода и/или путь поиска, то просматриваются только указанный
        дисковод  и  каталог.  Но  если  задано  только  имя  файла,  то
        ExistOnPath осуществляет поиск в следующем порядке :
         - текущий каталог
         - каталоги исполняемых программ (при ДОС 3.0 и выше)
         - все каталоги указанные в команде PATH.
        Использование  этой  функции  особенно  удобно для поиска файлов
        данных,  конфигурации,  оверлеев  и  т.д.   Как   и   ExistFile,
        ExistOnPath не работает с универсальными символами.
        ExistOnPath не возвращает полный путь поиска, если файл найден в
        текущем  каталоге. Причиной тому является применение пользовате-
        лем утилит "расширения маршрута"  (т.е.,  резидентных  программ,
        которые  предоставляет  различные  поисковые возможности ). Если
        используется такая утилита, то выражение типа
         ExistFile('MYPROG.DAT');
        возвратит True ( истина ), если даже MYPROG.DAT находится и не в
        текущем каталоге. ExistOnPath не сможет определить, где действи-
        тельно находится наш файл. При необходимости в этой ситуации по-
        лучить полный путь, вы должны для файла,  найденного  с  помощью
        ExistOnPath, использовать затем функцию FExpand из модуля DOS.
    Примеры
         Found := ExistOnPath('C:\AUTOEXEC.BAT', FullName);
        ExistOnPath будет осуществлять поиск файла 'AUTOEXEC.BAT' только
        в 'C:\'.
         Found := ExistOnPath('AUTOEXEC.BAT', FullName);
         if Found then FullName := FEpand(FullName);
        ExistOnPath будет осуществлять  поиск  файла  'AUTOEXEC.BAT'  по
        полной программе. Если он будет найден, то FullName будет содер-
        жать полный путь поиска.
         Found := ExistOnPath('*.DAT', FullName);
        Ошибка ! ExistOnPath не воспринимает универсальных символов.

    Синтаксис
        function FileHandlesLeft : Byte;
    Назначение
        Возвращает  число  файлов, которые можно открыть дополнительно к
        уже открытым.
    Замечания
        Эта  функция  просто пытается открыть до 20 файлов, и возвращает
        число успешно завершившихся попыток. Все файлы, открытые функци-
        ей, закрываются перед ее завершением. FileHandlesLeft предназна-
        чена , в основном, для целей отладки.
    Пример
         {$IFDEF Debug}
         Writeln('Еще можно открыть ', FileHandlesLeft, ' файлов');
         {$ENDIF}
        Пример использования FileHandlesLeft для выдачи сообщения о воз-
        можностях открытия дополнительных файлов.

    Синтаксис
        function FileHandlesOpen(CountDevices : Boolean) : Byte;
    Назначение
        Возвращает число файлов, открытых в данный момент в программе.
    Замечания
        Эта  функция возвращает число файлов, открытых в данный момент в
        программе. Параметр CountDevices показывает, нужно ли включать в
        это число стандартные устройства ДОС (с  номерами  в  промежутке
        StdInHandle..StdPrnHandle).  Возвращаемое  число  всегда будет в
        диапазоне 0..20, если CountDevices - True ( истина ),  и  0..15,
        если  -  False ( ложь ). Следует помнить, что это не гарантирует
        того, что вы можете открыть все 20 файлов в вашей программе, ес-
        ли не укажите в файле CONFIG.SYS "FILES=20" (или больше чем 20).
        По умолчанию значение FILES равно 8. FileHandlesOpen  предназна-
        чена, в основном, для целей отладки.
    Пример
         {$IFDEF Debug}
         Writeln('Открыто ', FileHandlesOpen(True), ' файлов');
         {$ENDIF}
        Пример использования FileHandlesOpen для выдачи сообщения о числе
        открытых файлов.

    Синтаксис
        function FlushDosBuffers(var F) : Boolean;
    Назначение
        Переносит активные буфера для выбранного файла на диск.
    Замечания
        Эта функция заставляет ДОС перенести  информацию  из  буфера  на
        диск для заданного файла. F объявлена как нетипизированный пере-
        менный  параметр, что позволяет одной функции работать с типизи-
        рованными ('F : File of Byte') и нетипизированными ('F :  File')
        файлами. FlushDosBuffers не используется для сброса буферов тек-
        стовых  файлов;  вместо  нее  должна  использоваться  TextFlush.
        Если произошла ошибка ввода/вывода, то FlushDosBuffers возвраща-
        ет False ( ложь ).
    Пример
         var F : File;
             Result : Boolean;
         ...
         Result := FlushDosBuffers(F);
        Правильная программа.
         var F : Text;
         ...
         Result := FlushDosBuffers(F);
        Ошибка ! FlushDosBuffers не используется для работы с текстовыми
        файлами. Используйте TextFlush.
    Смотри также
        TextFlush

    Синтаксис
        function GetDiskClass(Drive : Char; var SubstDriveChar : Char)
                              : DiskClass;
    Назначение
        Возвращает тип диска, используемого в дисководе с заданным  име-
        нем.
    Замечания
        Задавая дисковод посредством буквы ('A'..'Z'), эта функция возв-
        ращает  значение,  характеризующее  тип диска , установленного в
        нем. Возвращаемое  значение  описывается  при  определении  типа
        DiskClass.
        При  использовании GetDiskClass, вы должны помнить о двух специ-
        альных случаях. Первый, при помощи программы  ASSIGN  вы  можете
        переназначать дисковые устройства. Например,
         ASSIGN B=C
        направляет  все  запросы на ввод/вывод к диску на диск С. В тоже
        время, программа SUBST позволяет вам создавать новые  логические
        дисковые устройства из уже существующих или из каталогов.
        Например,
         SUBST H: C:\TURBO
        определяет каталог C:\TURBO как диск Н:.
        GetDiskClass определяет обе эти ситуации (хотя  и  не  различает
        их). В этом случае GetDiskClass возвращает в качестве результата
        'SubstDrive', и SubstDriveChar содержит действительное имя соот-
        ветствующего    логического    диска.    В   последнем   примере
        SubstrDriveChar представляет собой символ 'C', если передаваемый
        параметр будет 'H'.  Заметим,  что  если  результат  отличен  от
        'SubstDrive', то SubstDriveChar и Drive совпадают.
        Ограничения : GetDiskClass не распознает типа дискового устройс-
        тва,  а только тип установленного в него диска. Например, 1.2 Мб
        дисковод будет классифицирован как Floppy360, если в  нем  уста-
        новлен 360 Кб диск. GetDiskClass в настоящее время не распознает
        оптических  дисководов и некоторые устаревшие типы флоппи дисков
        (например односторонние).

    Синтаксис
        function GetDiskInfo(Drive : Byte; var ClustersAvailable,
                 TotalClusters, BytesPerSector,SectorsPerCluster : Word)
                             : Boolean;
    Назначение
        Возвращает техническую информации о выбранном дисководе.
    Замечания
        Эта функция возвращает информацию об организации заданного  дис-
        ковода.  Вы  можете использовать ее для вычисления общей емкости
        диска, объема свободного пространства или для  получения  данных
        для  последующего  использования  их  в функциях ReadDiskSectors
        и/или WriteDiskSectors.
        Drive - число, задающее дисковод : 0 - текущий, 1 - А, 2 -  В  и
        т.д.  Для преобразования имени дисковода в его номер используйте
        следующую формулу :
         DriveNumber := Ord(UpCase(DriveLetter))-64;
        Функция  возвращает  False  ( ложь ), если номер дисковода задан
        неправильно.   Иначе,   возвращаются   следующие   значения    :
        ClustersAvailable  (число  неиспользуемых  кластеров  на диске),
        TotalClusters (общее число кластеров на  диске),  BytesPerSector
        (число  байт  в  секторе,  почти  всегда 512), SectorsPerCluster
        (число секторов в кластере, обычно 1, 2 или 4).
        Формулы :
         BytesPerCluster := LongInt(SectorsPerCluster) *
                                                LongInt(BytesPerSector);
         DiskCapacity := LongInt(TotalClusters) * BytesPerSector;
         FreeSpace := LongInt(ClustersAvailable) * BytesPerSector;
    Пример
         var BytesPerSector, DiskCapacity, FreeSpace : LongInt;
             ClusterAvailable, TotalClusters,
             BytesPerSector, SectorsPerCluster : Word;
         ...
         if GetDiskInfo(0, ClustersAvailable, TotalClusters,
                        BytesPerSector,SectorsPerCluster) then begin
             BytesPerCluster := LongInt(SectorsPerCluster) *
                                            LongInt(BytesPerSector);
             DiskCapacity := LongInt(TotalClusters) * BytesPerSector;
             FreeSpace := LongInt(ClustersAvailable) * BytesPerSector;
             WriteLn('Информация о дисководе ', DefaultDrive, ':');
             WriteLn('Байт в секторе :', BytesPerSector);
             WriteLn('Байт в кластере:', BytesPerCluster);
             WriteLn('Объем диска    :', DiskCapacity);
             WriteLn('Байт свободно  :', FreeSpace);
          end;
    Смотри также
        ReadDiskSectors                       WriteDiskSectors

    Синтаксис
        procedure GetDta(var DTAptr : Pointer);
    Назначение
        Возвращает указатель на область обмена с диском ( DTA ).
    Замечания
        GetDta возвращает указатель на текущую область обмена с диском (
        DTA ). Эта функция необходима при временном переопределении  DTA
        с  помощью  SetDta,  и последующим ее восстановлением в первона-
        чальном виде.
        GetDta была создана для обеспечения совместимости с Турбо Паска-
        лем 5.0.
    Смотри также
        SetDta

    Синтаксис
        function GetEnvironmentString(SearchString : string) : string;
    Назначение
        Возвращает строку из текущей операционной среды.
    Замечания
        Функция позволяет находить значения строк, присвоенных  перемен-
        ным операционной среды, таким как 'COMSPEC', 'PATH' и  'PROMPT'.
        При  поиске, различия между строчными и заглавными буквами игно-
        рируются; и вам нет необходимости ставить '='  в  конце  искомой
        строки.
    Примеры
         WriteLn(GetEnvironmentString('comspec=');
         WriteLn(GetEnvironmentString('comspec');
         WriteLn(GetEnvironmentString('COMSPEC=');
         WriteLn(GetEnvironmentString('COMSPEC');
        При  успешном завершении, все операторы выведут один результат -
        'C:\COMMAND.COM'.
         WriteLn(GetEnvironmentString('COMS');
        Корректно только в том случае, если полное имя искомой  перемен-
        ной 'COMS'. 'COMSPEC' искаться не будет.
         WriteLn(GetEnvironmentString(' COMSPEC ');
        Ошибка ! Строка для поиска не должна содержать пробелов в конце.

    Синтаксис
        function GetEnvStr(Env : EnvRec; Search : string) : string;
    Назначение
        Возвращает строку из заданной операционной среды.
    Замечания
        GetEnvStr возвращает значение заданной строки в выбранной опера-
        ционной среде. Например, для проверки значения COMSPEC в главной
        операционной среде ДОС, вы должны выполнить следующее :
         var
           E : EnvRec;
         begin
          MasterEnv(E);
          WriteLn('COMSPEC для главной среды=', GetEnvStr(E,'COMSPEC'));
         end.
        В конце искомой строки нет необходимости ставить знак  '=',  так
        как  он будет добавлен автоматически. При поиске, различия между
        строчными и заглавными буквами игнорируются. Пустое пространство
        в искомой строке является значимым для поиска. Если GetEnvStr не
        найдет указанную строку в операционной  среде,  то  возвращается
        пустая строка.
    Пример
        Смотри пример в описании функции SetEnvStr.
    Смотри также
        SetEnvStr

    Синтаксис
        function GetFileMode(FName : string; var Attr : Word) : Byte;
    Назначение
        Возвращает атрибут заданного файла.
    Замечания
        Эта  функция  является  просто  "упрощением" функции GetFAttr из
        Турбо Паскаля. Возвращает для файла FName в Attr его атрибут , и
        код ошибки ДОС (DosError), как результат работы функции. Атрибу-
        ты закодированы битами и показаны в следующей таблице :
           Бит   Значение    Атрибут
            0       $01    только чтение
            1       $02    скрытый
            2       $04    системный
            3       $08    идентификатор тома
            4       $10    каталог
            5       $20    архивизация
        Чтобы проверить, например, является ли файл скрытым,  вы  должны
        использовать следующий тест :
         Hidden := (Attr and $02) <> 0
    Пример
         var
           FName : string;
           Attr : Word;
         begin
           Write('Введи имя файла:');
           Read(FName);
           if GetFileMode(FName, Attr) <> 0 then
             WriteLn('Файл не найден');
           else begin
             WriteLn(FName, ' есть ');
             if (Attr and $10) ,. 0 then
               WriteLn('каталог');
             else
               WriteLn( 'файл');
           end;
         end.

    Синтаксис
        function GetPrintStatus(var QPtr : Pointer) : Byte;
    Назначение
        Прекращает печать, возвращает код текущей ошибки, и устанавлива-
        ет указатель QPtr на очередь имен файлов.
    Замечания
        Эта функция устанавливает указатель на последовательность ASCIIZ
        строк, содержащих имена файлов из очереди на печать. Каждый эле-
        мент имеет размер 64 байта и конец очереди отмечается именем на-
        чинающимся пустым символом. Печать  останавливается  со  времени
        вызова GetPrintStatus до вызова функции EndPrintStatus. Заметим,
        что  вы  можете  легко преобразовать ASCIIZ строки в нормальные,
        используя функцию Asc2Str из OPASCIIZ. GetPrintStatus возвращает
        0 в случае успешного завершения.
    Пример
         var
           P : Pointer;
           AP : AsciizPtr absolute P;
           POffset : Word absolute P;
         begin
           if GetPrintStatus(P) = 0 then
             while Char(P^) <> #0 do begin {проверить на пустой}
               WriteLn(Asc2Str(AP^));      {показать текущий элемент}
               Inc(POffset, 64);           {указываем следующий элемент}
             end;
           EndPrintStatus;                 {освобождаем очередь}
         end.
    Смотри также
        Asc2Str(OPASCIIZ)                    EndPrintStatus

    Синтаксис
        function GetProgramStr(Env : EnvRec) : string;
    Назначение
        Возвращает имя программы, владеющей программной средой Env  (при
        ДОС > 3.0 ) .
    Замечания
        При использовании ДОС 3.0 и выше, функция возвращает  имя  прог-
        раммы, владеющей заданной программной средой.
    Пример
         ParentEnv(Env);
         S := GetProgramStr(Env);
         if S <> '' then
           WriteLn('Владелец - программа ', S);
    Смотри также
        SetProgramStr

    Синтаксис
        function HandleIsConsole(Handle : Word) : Boolean;
    Назначение
        Возвращает True ( истина ), если канал ввода/вывода -  стандарт-
        ное устройство.
    Замечания
        Помимо  всего прочего, HandleIsConsole позволяет определить, был
        ли переопределен программный ввод/вывод. Эта информация является
        особенно важной при использовании программ-фильтров, где необхо-
        димо точно знать, переопределил ли пользователь ввод или  вывод.
        В более общем плане, функция позволяет предотвратить копирование
        данных   на  устройство  'CON'.  Например,  OPEDITOR  использует
        HandleIsConsole до начала операций записи текстовых, так как ко-
        пирование на устройство 'CON' приведет к  выводу  информации  на
        экран дисплея.
    Примеры
         uses Dos;
         ...
         if HandleIsConsole( TextRec(Input).Handle ) then
            WriteLn('Ввод должен быть переопределен из файла');
        Тест на переопределение пользователем стандартного ввода.
         if HandleIsConsole( TextRec(Output).Handle ) then
            WriteLn('Вывод должен быть переопределен в файла');
        Тест на переопределение пользователем стандартного вывода.

    Синтаксис
        function IsDirectory(FName : string) : Boolean;
    Назначение
        Возвращает True ( истина ), если FName каталог.
    Замечания
        Эта функция может быть использована для определения, является ли
        имя  каталога  допустимым.  Название каталога не должно заканчи-
        ваться символом "\", за исключением главного каталога. Имя  дис-
        кового  устройства ('A:','B:','C:') считается допустимым катало-
        гом, если устройство существует.
    Примеры
         IsDirectory('C:\');
         IsDirectory('C:');
        Оба значения True ( истина ), если С допустимый дисковод.
         IsDirectory('C:\TEST');
        Возвращает True ( истина ), если дисковод и каталог существуют.
         IsDirectory('C:\TEST\');
        Возвращает False ( ложь ), т.к. присутствует недопустимый символ
        '\' в конце строки.
    Смотри также
        ValidDrive

    Синтаксис
        procedure MasterEnv(var Env : EnvRec);
    Назначение
        Возвращает запись для главной операционной среды ДОС.
    Замечания
        Возвращает  запись для главной операционной среды ДОС. Изменения
        в операционной среде возможны только после завершения этой прог-
        раммы. Поиск главной операционной среды осуществляется несколько
        необычным методом, и если по каким либо причинам он не  работает
        на  вашей системе, то поле EnvSeg в возвращаемой записи устанав-
        ливается в 0. Главная операционная среда обычно больше, чем  те-
        кущая  программная  среда - ДОС копирует только ту часть главной
        среды, которая действительно  используется  для  запуска  каждой
        программы.
    Пример
         var Env : EnvRec;
         ...
         MasterEnv(Env);
         if Env.EnvSeg <> 0 then
           DumpEnv(Env);
        Отображает содержимое главной операционной среду на экране.
    Смотри также
        CurrentEnv                             SetEnvStr

    Синтаксис
        procedure NewEnv(var Env : EnvRec; Size : Word);
    Назначение
        Распределяет новую среду в динамической области памяти.
    Замечания
        Наиболее  часто  эта  функция используется в программах, которые
        порождают другие программы и необходимо  передавать  им  большой
        объем  информации  о среде. Size - число байт, резервируемое для
        новой операционной среды. NewEnv фактически выделяет на 31  байт
        больше,  чем вы запрашиваете, с тем, чтобы быть уверенным в воз-
        можности выравнивания и создании фиктивного блока управления па-
        мятью , который сохраняет другие программы и функции. Если в ди-
        намической памяти недостаточно места для размещения новой среды,
        то NewEnv возвратит поле EnvSeg в записи Env равное нулю.
        После завершения работы функции, новая операционная среда запол-
        нена пустыми символами ( #0 ).  Для  копирования  из  какой-либо
        среды в новую используйте функцию CopyEnv.
    Пример
         Смотри пример для CopyEnv.
    Смотри также
        CopyEnv                                  DisposeEnv
        CurrentEnv                               SetCurrentEnv

    Синтаксис
        function NumberOfDrivers : Byte;
    Назначение
        Возвращает число логических дисковых устройств.
    Замечания
        При  использовании  ДОС  3.0  и  выше, возвращаемое значение, по
        крайней мере, не меньше 5, так как эти версии поддерживают диски
        , установленные с помощью SUBST. При ДОС 2.х возвращается  число
        физических дисководов.
    Пример
         WriteLn('Число дисковых устройств : ', NumberOfDrivers);

    Синтаксис
        function OpenStdDev(var F : Text; StdHandle : Word) : Boolean;
    Назначение
        Назначает  текстовый файл в качестве стандартного устройства ДОС
        : 0, 1, 2 или 4.
     Замечания
        Эта функция позволяет вам осуществлять простой доступ к стандар-
        тному вводу, стандартному выводу, стандартному выводу  ошибок  и
        стандартному  устройству печати. F - файловая переменная для лю-
        бого неоткрытого текстового файла, StdHandle - 0  (  StdInHandle
        ),  1  ( StdOutHandle ), 2 ( StdErrHandle ) или 4 ( StdPrnHandle
        ). Помимо всего прочего, OpenStdDev позволяет записывать в стан-
        дартное устройство  вывода  в  программах,  использующих  CRT  и
        OPCRT.  Функция  возвращает False ( ложь ) только в случае, если
        StdHandle имеет недопустимый номер.
    Пример
         var StdOut : Text;
         ...
         if not OpenStdDev(StdOut, StdOutHandle) then { ошибка };

    Синтаксис
        procedure ParentEnv(var Env : EnvRec);
    Назначение
        Возвращает запись для программной среды родительской программы.
    Замечания
        Возвращает запись для программной среды программы, которая  осу-
        ществляла  вызов  (родитель). Если запуск текущей программы осу-
        ществлялся из командной строки ДОС, то родительской средой будет
        главная операционная среда ДОС. В противном случае, родительской
        средой будет среда той программы, которая осуществила вызов ДОС.
    Пример
        Смотри пример для SetEnvStr.
    Смотри также
        MasterEnv

    Синтаксис
        function ParsePath(var InputPath, SearchPath, LeadInPath
                           : string) : Boolean;
    Назначение
        Используя  заданный пользователем маршрут поиска и файловую мас-
        ку, убирает пробелы и возвращает допустимый  глобальный  маршрут
        поиска для заданных файлов и допустимый путь к ним.
    Замечания
        Эта функция является дополнением к функциям FindFirst и FintNext
        из стандартного модуля DOS. ParsePath анализирует файловую маску
        (InputPath) также, как это делает команда ДОС COPY, и возвращает
        строку для последующей передачи FindFirst (SearchPath),  или  им
        аналогичным,  для  дальнейшей  обработки. Лидирующие и хвостовые
        пробелы отбрасываются и все  алфавитные  символы  переводятся  в
        верхний регистр. Например, при заданной строке '\dos', ParsePath
        возвратит  - '\DOS\*.*' в SearchPath, и '\DOS\' в 'LeadInPath. В
        случае, когда строка InputPath задана некорректно,  возвращается
        False ( ложь ).
        Заметим  что,  ParsePath  незаконченный программный продукт, она
        возвратить True ( истина ), если в InputPath задано  некорректно
        имя диска (например).
    Примеры
        Задавая в InputPath 'c:', ParsePath возвратит
              'C:*.*' { SearchPath }
              'C:'    { LeadInPath }
        Задавая в InputPath '*.COM', ParsePath возвратит
              '*.COM' { SearchPath }
              ''    { LeadInPath }

    Синтаксис
        function PrintInstalled : Boolean;
    Назначение
        Возвращает True ( истина ), если PRINT.COM установлена.
    Замечания
        Все программы работающие с буферизированным  выводом  на  печать
        (PRINT.COM)  работают только с ДОС 3.0 и выше. Если используется
        более ранняя версия, то PrintInstalled возвратит False ( ложь ).
        В других случаях False ( ложь ) возвращается  только  в  случае,
        если программа не резидентна.
    Пример
         if not PrintInstalled then
           WriteLn('PRINT.COM не резидентна');
    Смотри также
        CancelAllPrintFiles                        GetPrintStatus
        CancelPrintFile                            SubmitPrintFile
        EndPrintStatus

    Синтаксис
        function ReadDiskSectors(Drive : Word; FirstSect : Longint;
                                 NumSects : Word; var Buf) : Boolean;
    Назначение
        Читает дисковые сектора по абсолютному адресу.
    Замечания
        Эта  функция осуществляет доступ непосредственно к секторам дис-
        ка, позволяя вам даже контролировать  неиспользованное  дисковое
        пространство.  Drive  - число от 0 (= А:) до 25 (= Z:), задающее
        дисковод. Для преобразования имени дисковода в его номер исполь-
        зуйте следующую формулу :
         DriveNumber := Ord(UpCase(DriveLetter))-64;
        FirstSect - это номер сектора  с  которого  начинать  считывание
        (первый  сектор  на диске 0). Его значение может быть в пределах
        0..65535, но при использовании ДОС 3.31 и выше это  число  может
        быть  и  больше.  Если используется ДОС 3.3 и меньше, то большие
        значения для FirstSect параметра игнорируются.
        NumSects - число секторов для чтения. Buf - буфер для  пересылки
        данных,     он     должен     иметь,     по     крайней    мере,
        NumSects*BytesPerSector   байт   (смотри   GetDiskInfo).    Если
        ReadDiskSectors  заканчивается аварийно, то возвращается False (
        ложь ) и в DosError заносится код  ошибки,  который  может  быть
        следующий :

         Старший байт ( коды ошибок выдаваемых BIOS ) :
          128 Закончилось время : дисковод отказывается отвечать
          64  Ошибка установки головок
          32  Ошибка контроллера
          16  Ошибка четности при проверке CRC ( циклический избыточный
              код )
          8   Ошибка DMA (прямой доступ к памяти)
          4   Сектор не найден
          3   Попытка записи на защищенную дискету
          2   Неверный адрес: сектор помечен как ошибочный или не найден


         Младший байт ( коды ошибок выдаваемых ДОС )
          12  Общая ошибка
          11  Ошибка чтения
          10  Ошибка записи
          8   Сектор не найден
          7   Неизвестный носитель; не определяется формат диска
          6   Ошибка установки
          4   Ошибка при проверке CRC
          2   Дисковод не готов
          1   Неверный номер устройства
          0   Попытка записи на защищенную дискету

    Пример
         var Buffer : array[1..2048] of Byte;
             CA, TC, BPS, SPC : Word;
         ...
         if not GetDiskInfo(0, CA, TC, BPS, SPC) then begin
           WriteLn('Ошибка чтения с диска ', DefaultDrive); Exit;
         end;
         if not ReadDiskSectors(Ord(DefaultDrive)-Ord('A'), 0, 1,Buffer)
          then begin
          WriteLn('Ошибка ',DosError,'при чтении с диска',DefaultDrive);
          DosError := 0;
          Exit;
         end;
    Смотри также
        GetDiskInfo                                 WriteDiskSectors

    Синтаксис
        function SameFile(FilePath1, FilePath2 : string; var Errorcode
                          : Word) : Boolean;
    Назначение
        Возвращает True ( истина ), если FilePath2 и FilePath1 представ-
        ляют собой один и тот же физический файл.
    Замечания
        Эта функция,  в  основном,  используется   вместе   с   функцией
        CopyFile.  Она  проверяет,  являются  ли  два файла (FilePath1 и
        FilePath2) одним и тем же физическим файлом.  FilePath1 подразу-
        мевается как существующий файл.  FilePath2 не обязательно должен
        существовать,  но маршрут к нему,  если он присутствует,  должен
        быть допустимым.
        Так как простое сравнение двух имен файлов еще не  дает  опреде-
        ленного  ответа  на наш вопрос, SameFile решает эту задачу путем
        попытки получения атрибутов файлов. Если эта попытка  заканчива-
        ется   успешно,  то  SameFile  временно  изменяет  атрибуты  для
        FilePath1, и затем, снова считывает атрибуты  для  FilePath2.  В
        случае,  если атрибуты FilePath2 изменились, то SameFile возвра-
        щает True ( истина ), иначе - False ( ложь ).
        Возможные коды ошибок для SameFile

         0  Успешное завершение ( файлы различны или файл  FilePath2  не
            существует )
         1  Файл FilePath1 не существует или недоступен
         2  В FilePath2 неверно задан маршрут поиска или файл недоступен
         3  Ошибка при чтении/установке атрибутов файла

    Пример
        Смотри пример для CopyFile.
    Смотри также
        CopyFile

    Синтаксис
        procedure SelectDrive(Drive : Char);
    Назначение
        Делает заданный дисковод текущим, если возможно.
    Замечания
        Drive - буква, указывающая на дисковод, в диапазоне 'a'..'z' или
        'A'..'Z'. Если дисковое устройство не существует, то SelectDrive
        не производит никаких действий.
    Примеры
         SelectDrive('A');
         SelectDrive('b');
         SelectDrive('C');
    Смотри также
        DefaultDrive                               NumberOfDrives

    Синтаксис
        function SetBlock(var Paragraphs : Word) : Boolean;
    Назначение
        Изменяет  размер памяти, выделенной ДОС для выполняемой програм-
        мы.
    Замечания
        Эта функция предназначена, в основном, для внутреннего использо-
        вания функцией ExecDos. Она позволяет вам увеличивать или умень-
        шать  объем  памяти,  выделенной  ДОС   для   вашей   программы.
        Paragraphs - запрашиваемый новый объем памяти. Если ДОС не может
        выделить  запрашиваемую  память,  то  SetBlock возвратит False (
        ложь ) и Paragraphs будет содержать доступное число параграфов.
        Очень важное замечание ! Если вы изменили объем  выделенной  для
        программы памяти, то вы должны позаботиться о приведении в соот-
        ветствие  списка  свободных  блоков  Турбо  Паскаля. В процедуре
        ExecDos из OPDOS.PAS показано,  как  безопасно  перераспределить
        блоки памяти.
    Примеры
        Для примера смотри процедуру ExecDos в OPDOS.PAS.
    Смотри также
        ExecDos

    Синтаксис
        procedure SetCurrentEnv(Env : EnvRec);
    Назначение
        Определяет альтернативную среду для выполняемой программы.
    Замечания
        Определяет  альтернативную среду для выполняемой программы, аль-
        тернативная среда задается параметром Env. Вы  можете  проделать
        эту операцию после вызова NewEnv и инициализации новой среды, но
        до порождения дочернего процесса. ДОС копирует текущую программ-
        ную  среду  для  дочернего  процесса. Для сохранения целостности
        распределения памяти ДОС, вы всегда должны восстановить  текущую
        программную среду, установленную ДОС, до завершения программы.
    Пример
        Смотри вызов SetCurrentEnv в ShellWithPrompt (OPDOS.PAS).
    Смотри также
        NewEnv                               ShellWithPrompt

    Синтаксис
        procedure SetDta(DTAptr : Pointer);
    Назначение
        Устанавливает  текущую область обмена с диском ( DTA ) по указа-
        телю DTAptr.
    Замечания
        ДОС использует текущую область обмена с диском для большого чис-
        ла  дисковых операций, наиболее важная из них - сканирование ка-
        талогов. Общепринятым техническим  приемом  является  размещение
        DTA для ДОС в том месте, на которое накладывается область, адре-
        суемая Турбо Паскалем. Тем самым обеспечивается наиболее простой
        способ  доступа к данным. Фактически, этот технический прием ис-
        пользуется функциями FindFirst и FindNext из модуля ДОС, но  так
        как FindFirst и FindNext сбрасывают DTA автоматически, то вы ве-
        роятно  никогда  не  воспользуетесь  SetDta или ее комбинацией с
        функцией GetDta.
        GetDta была создана для обеспечения совместимости с Турбо Паска-
        лем 5.0.
    Смотри также
        GetDta

    Синтаксис
        function SetEnvStr(Env : EnvRec; Search, Value : string)
                                                              : Boolean;
    Назначение
        Устанавливает  новое  значение  заданной  строки среды, если это
        возможно.
    Замечания
        Устанавливает новое значение заданной строки среды. Заметим,  вы
        можете установить значение как в главной операционной среде, так
        и  текущей  среде, в зависимости от инициализации параметра Env.
        Search - задает имя изменяемой строки, например 'COMSPEC'. Value
        специфицирует ее новое значение. Если Value  пустая  строка,  то
        данный  пункт исключается из среды. Новое значение всегда добав-
        ляется в конец среды, после первого перемещенного нового  значе-
        ния  из середины. При нехватке памяти для нового значения среды,
        SetEnvStr возвращает False ( ложь ), в противном случае  True  (
        истина ).
        Работа  этой функции вызывает один побочный эффект. Если изменя-
        ется текущая среда, то SetEnvStr стирает путь поиска  программы,
        хранящийся за пределами среды, при работе с ДОС 3.0 и выше. Если
        вам  нужно  получить  доступ  к  нему,  вам  нужно  использовать
        'ParamStr(0) или GetProgramStr до вызова SetEnvStr (смотри  при-
        мер для SetEnvStr).
    Пример
         uses
           opstring, opdos, opcrt, opcmd, opsedit;
         var SLE : SimplLineEditor;
             E, S : string;
             Env : EnvRec;
         begin
           E := StUpcase(ParamStr(1));
           if E = '' then begin
             WriteLn('Обращение : EDITENV EnvironmentVariableName');
             WriteLn(' для редактирования EnvironmentVariableName');
             WriteLn('      или : EDITENV /D');
             WriteLn(' для отображения содержимого среды');
             Halt;
           end;
           ParentEnv(Env);
           if (E = 'D/') or (E = '-D') then begin
             DumpEnv(Env); Halt;
           end;
           S := GetEnvStr(Env, E);
           if S = '' then begin
             WriteLn('"', E,'" не найдена в данной среде'); Halt(1);
           end;
           SLE.Init(DefaultColorSet);
           WriteLn('Текущее значение: ', S);
           SLE.ReadString('Новое значение : ', WhereY, 1, 127,
                           ScreenWidth-16, S);
           if (SLE.GetLastCommand <> ccQuit) then begin
             WriteLn;
             if SetEnvStr(Env, E, S) then
               WriteLn('Строка среды изменена');
             else
               WriteLn('Невозможно изменить строку в среде');
           end;
         end.
        Простая программа позволяющая редактировать строки копии главной
        операционной среды ДОС (или программной среды, если вы работаете
        в перезапущенной ДОС) или выводить на дисплей ее содержимое.

    Синтаксис
        function SetProgramStr(Env : EnvRec; Path : string) : Boolean;
    Назначение
        Если возможно, добавляет имя программы в конец среды.
    Замечания
        Предоставляет  возможность  установить  путь  поиска  программы,
        обычно  доступный  при ДОС 3.0 и выше. Путь поиска добавляется к
        заданной программной среде, как это сделала бы ДОС. Если  исчер-
        пано  пространство, SetProgramStr не производит никаких действий
        и возвращает False ( ложь ).
        Заметим, эта функция никогда не должна использоваться для добав-
        ления в главную операционную среду ДОС, а только в текущую прог-
        раммную среду или специальную среду, созданную NewEnv.
    Пример
         S := GetProgramStr(Env);
         SetEnvStr(Env, 'NEW', 'new string');
         if not SetProgramStr(Env, S) then { исчерпана память };
        Показывает, как сохранить и восстановить имя программы при изме-
        нении строки среды с помощью SetEnvStr.
    Смотри также
        GetProgramStr                          SetEnvStr
        NewEnv

    Синтаксис
        procedure SetRawMode(var F : Text; On : Boolean);
    Назначение
        Включает и  выключает  режим "неструктурирования" для указанного
        текстового файла (должно быть устройство).
    Замечания
        Эта процедура позволяет вам изменять режим работы символьных ус-
        тройств (стандартный ввод, стандартный вывод, стандартный  прин-
        тер) путем изменения "подготовленные" на "неструктурированные" и
        наоборот. В первом режиме ("cooked'), ДОС производит  расширение
        символов  табуляции  и интерпретирует управляющие символы, такие
        как ^S и ^C, при чтении и записи на  символьное  устройсво.  При
        втором режиме ('raw'), все символы рассматриваются как данные.
        Параметр  F, передаваемый SetRawMode, должен быть открытым текс-
        товым файлом связанным с символьным устройством. Если F не  уст-
        ройство, то никаких действий не производится. Сообщения об ошиб-
        ках ввода/вывода описываются в Dos.DosError.
        Возможно одним из наиболее частых применений этой процедуры, яв-
        ляется  перевод  стандартного устройства печати в неструктуриро-
        ванный режим. SetRawMode также часто используется для увеличения
        скорости операций ввода/вывода при использовании устройств стан-
        дартного ввода и стандартного вывода.
    Пример
         var
           F : Text;
         begin
           Assign(F, 'LPT1');
           Rewrite(F);
           SetRawMode(F, True);
           ...
           Close(F);
           SetRawMode(F, False);
         end.
        Переводит устройство печати в неструктурированный режим в начале
        программы  и  восстанавливает  подготовленный  режим  в конце. В
        большинстве случаев необходимо устанавливать  обработчик  выхода
        из  программы, который восстанавливает первоначальный режим уст-
        ройства,  на  случай  преждевременного  (аварийного)  завершения
        программы.

    Синтаксис
        function ShellWithPrompt(Prompt : string; EDP : ExecDosProc)
                                 : Integer;
    Назначение
        Запускает ДОС с новым приглашением.
    Замечания
        Запускает  ДОС с приглашением, задаваемым специальным значением.
        Пользователь может выполнить команды ДОС до введения EXIT, после
        чего выполнение вызывающей программы будет продолжено. Эта функ-
        ция несколько отличается от ExecDos механизмом запуска командно-
        го процессора.
        Строка Prompt может  специфицировать  любое  приглашение  ДОС  и
        включать  метакоманды, такие как $p$g, и управляющие ANSI после-
        довательности, если ANSI установлен. Новое приглашение  заменяет
        старое до завершения работы командного процессора.
        ShellWithPrompt  выделяет  в динамической памяти место для новой
        среды, включая заданное Prompt. Динамическая  память  выделяется
        даже  в  том случае, когда новое приглашения совпадает с находя-
        щимся в текущей среде. Новая среда является просто копией  теку-
        щей, но с измененной PROMPT.
        ShellWithPrompt  возвращает  код  завершения. Его значение равно
        нулю в случае успешного запуска. Положительные значения рассмат-
        риваются как коды ошибок ДОС. Отрицательные - как  коды  ошибок,
        вырабатываемые  ExecDos и ShellWithPrompt (коды -1..-4 совпадают
        с кодами ExecDos, -5..-7 - добавляются ShellWithPrompt) :

          0  Успешное завершение
         -1  Недостаточно памяти для хранения таблицы  свободных  блоков
             Турбо
         -2  Ошибка ДОС до вызова EXEC
         -3  Ошибка ДОС после вызова EXEC (критическая ошибка)
         -4  Недостаточно памяти для выполнения команды ДОС
         -5  Не могу прочитать текущую среду
         -6  Недостаточно динамической памяти для новой среды
         -7  Ошибка вычисления памяти (не должна случаться)
          и еще все коды ошибок ДОС.

    Пример
         NewP := 'Введи "EXIT" для возврата в MYPROG'^M^J+
                 GetEnvironmentString('PROMPT');
         Status := ShellWithPrompt(NewP, NoExecDosProc);
        Запускает  ДОС  и выводит подсказку 'Введи "EXIT" для возврата в
        MYPROG' над обычным приглашением ДОС.
    Смотри также
        ExecDos


    Синтаксис
        function SubmitPrintFile(FileName : string) : Byte;
    Назначение
        Функция передает файл для печати PRINT.COM.
    Замечания
        Эта функция позволяет вам передавать файлы для параллельной  пе-
        чати с помощью установленной до этого PRINT.COM, при использова-
        нии ДОС 3.0 и старше.  До вызова функции вы должны быть уверены,
        что  оба эти условия выполнены (вы можете это сделать при помощи
        PrintInstalled).
        Если  запрос  может быть выполнен, то SubmitPrintFile возвращает
        ноль, в противном случае один из следующих кодов ошибок :

          1  Неправильная функция
          2  Файл не найден
          3  Маршрут поиска не найден
          4  Слишком много открытых файлов
          5  Обращение отвергнуто
          8  Очередь не печать полна
          9  Занято
         12  Имя слишком длинное
         15  Неправильное дисковое устройство

    Пример
         if not PrintInstalled then
           WriteLn('PRINT.COM не установлена');
         else if SubmitPrintFile('\AUTOEXEC.BAT') <> 0 then
           WriteLn('Нельзя нaпечатать файл');
    Смотри также
        PrintInstalled

    Синтаксис
        function TextFileSize(var F : Text) : LongInt;
    Назначение
        Возвращает размер текстового файла F.
    Замечания
        Эта функция позволяет вам определить текущий размер любого текс-
        тового файла, открытого для ввода или вывода. Текущее содержимое
        буфера для файла включается в размер. TextFileSize возвращает -1
        в случае возникновения ошибки ввода/вывода.
    Пример
         var MyFileSize : LongInt;
           F : Text;
         begin
           { -- открытие F -- }
           MyFileSize := TextFileSize(F);
           if MyFileSize = -1 then WriteLn(' Ошибка ');
           else WriteLn('Размер = ', MyFileSize);
         end;

    Синтаксис
        function TextFlush(var F : Text) : Boolean;
    Назначение
        Переносит активный буфер(а) для текстового файла на диск.
    Замечания
        Эта функция очищает буфер текстового файла. Если файл открыт для
        ввода,  то содержимое буфера записывается на диск; буфера откры-
        тые для файлов ДОС очищаются функциями DuplicateFileHandle ($45)
        и CloseFile ($3E) из DOS. Если файл открыт для вывода, то указа-
        тель в файле возвращается назад к символу,  который  должен  чи-
        таться  следующим  (положение, которое он занимал бы, если бы не
        было буфера). TextFlush возвращает False ( ложь ), если произош-
        ла ошибка ввода/вывода.
    Пример
         var F : Text;
         ...
         if not TextFlush(F) then WriteLn('Ошибка очистки буфера F');
         else WriteLn('Буфер для F очищен');

    Синтаксис
        function TextPos(var F : Text) : LongInt;
    Назначение
        Возвращает текущую позицию логического указателя файла.
    Замечания
        TextPos получает текущую позицию для физического указателя  фай-
        ла,  затем согласовывает это значение с текущим содержимым буфе-
        ра. Результатом является текущая позиция  логического  файлового
        указателя - позиция, на которую указывал бы физический указатель
        при  небуферизированном  вводе/выводе.  В  случае  возникновения
        ошибки ввода/вывода TextPos возвращает -1.  Для  примера  смотри
        описание TextSeek ниже.

    Синтаксис
        function TextSeek(var F : Text; Target : LongInt) : Boolean;
    Назначение
        Осуществляет прямой доступ к текстовому файлу, открытому для вы-
        вода.
    Замечания
        Эта  функция осуществляет прямой доступ к текстовому файлу, отк-
        рытому  для  вывода.  В случае возникновения ошибки ввода/вывода
        или когда файл не открыт TextSeek возвращает False ( ложь ). За-
        метим, что TextSeek иногда вынуждена освобождать буфер текстово-
        го файла, поэтому, было бы неразумным, использовать ее для  фай-
        лов с большими буферами, созданными SetTextBuf. Однако, TextSeek
        избегает  производить  эту  операцию  везде, где возможно : если
        данные для поиска уже находятся в буфере, то  происходит  просто
        перестановка указателя файлового буфера, а не поиск в физическом
        файле.
        Target задает смещение в байтах, а не номер строки.
    Пример
         var SeekDest : LongInt; F : Test;
         begin
           {-- открыть F --}
           Write('Введи позицию для поиска  :'); ReadLn(SeekDest);
           if not TextSeek(F, SeekDest) then
             WriteLn('Ошибка');
           else
             WriteLn(SeekDest: ', SeekDest, ' TextPos: ', TextPos(F));
         end;

    Синтаксис
        function TimeMs : LongInt;
    Назначение
        Возвращает время суток в милисекундах.
    Замечания
        Эта  функция  предоставляет  удобный способ отслеживания времени
        выполнения программы ( до сотых секунды ).
        Пожалуйста помните,  хотя значение возвращается в  милисекундах,
        точность его ограничивается точностью системного таймера ( около
        55  милисекунд или 1/18 секунды  ).  Если  вам  требуется  более
        высокая точность, вы должны использовать модуль TPTIMER, находя-
        щийся на диске BONUS.
    Пример
         var
           Start, Stop : LongInt;
         begin
           Start := TimeMs;
           {-- главная программа --}
           Stop := TimeMs;
           WriteLn('Программа работала : ', (Stop-Start)/ 1000.0);
         end;

    Синтаксис
        function ValidDrive(Drive : Char) : Boolean;
    Назначение
        Возвращает  True  ( истина ), если указанное дисковое устройство
        существует.
    Замечания
        ValidDrive определяет, является ли заданное дисковое  устройство
        ('A'..'Z')  допустимым в данной конфигурации системы. Она просто
        пытается переключиться на него с помощью SelectDrive.
    Пример
         for Ch := 'A' to 'Z' do
           if ValidDrive(Ch) then
             WriteLn(Ch, 'является допустимым дисковым устройством');
    Смотри также
        SelectDrive

    Синтаксис
        function WriteDiskSectors(Drive : Word; FirstSect : LongInt;
                                  NumSects : Word; var Buf) : Boolean;
    Назначение
        Осуществляет запись дисковых секторов по абсолютному адресу.
    Замечания
        Эта функция является противоположностью функции  ReadDiskSectors
        и почти всегда используется вместе с ней. При совместном исполь-
        зовании, они позволяет считывать содержимое выбранных секторов с
        диска  в  буфер, изменять информацию в буфере, затем перезаписы-
        вать измененную информацию на диск.
        Drive  -  число от 0 (= А:) до 25 (= Z:), задающее дисковод. Для
        преобразования имени дисковода в его номер используйте следующую
        формулу :
         DriveNumber := Ord(UpCase(DriveLetter))-64;
        FirstSect - это номер сектора с которого начинать запись (первый
        сектор на диске 0). Его значение может быть в пределах 0..65535,
        но при использовании ДОС 3.31 и выше  это  число  может  быть  и
        больше.  Если используется ДОС 3.3 и меньше, то большие значения
        для FirstSect параметра игнорируются.
        NumSects - число секторов для записи. Buf  -  буфер,  содержащий
        данные для записи.
        При успешном завершении WriteDiskSectors возвращает True ( исти-
        на ). В противном случае, возвращается False ( ложь ) и устанав-
        ливает  в  DosError  (глобальная  переменная  из модуля DOS) код
        ошибки. Возможные коды ошибок смотри в описании ReadDiskSectors.
    Пример
         var
           Drive : Byte;
           Buffer : array[1..2048] of Byte;
           CA, TC, BPS, SPC : Word;
         begin
           if not GetDiskInfo(0, CA, TC, BPS, SPC) then begin
             WriteLn('Ошибка чтения на диске ', DefaultDrive);
             Exit;
           end;
           Drive := Ord(DefaultDrive)-Ord('A');
           if not ReadDiskSectors(Drive, 0, 1, Buffer) then begin
             WriteLn('Ошибка ', DosError, 'при чтении с диска ',
                     DefaultDrive);
             DosError := 0; Exit;
           end;
           {-- редактирование содержимого буфера --}
           if not WriteDiskSectors(Drive, 0, 1, Buffer) then begin
             WriteLn('Ошибка ', DosError, 'при записи на диск ',
                     DefaultDrive);
             DosError := 0; Exit;
           end;
         end;
    Смотри также
        GetDiskInfo                               ReadDiskSectors

    C: OPEXEC : Управление освобождением памяти при вызове подпрограмм.

    OPEXEC  предоставляет возможность размещать больше исполняемых прог-
рамм в 640 Кб памяти ДОС. ExecDosSwap, главная процедура в  OPEXEC,  вы-
полняет  заданную  программу,  используя функцию Exec из DOS. Ее главное
преимущество перед другими разработками Exec то, что она  перемещает  из
оперативной памяти максимальное  количество информации в расширенную па-
мять или на диск, и предоставляет исполняемой программе всю освободивше-
юся  память.  Когда вызванная программа закончится, вызывающая программа
снова возвращается на свое место в оперативную память и продолжает  свою
работу.
    Этот технический прием особенно удобен  при  использовании  программ
выбора  из  меню, которые, в свою очередь, вызывают другие большие прог-
раммы, или в современных турбо-средах, в которых при  нажатии  различных
клавиш  инициализируются  огромные программы компиляции, загрузки и т.п.
Фактически, эта функция полезна в любой программе вызывающей другие.
    OPEXEC берет начало из двух более ранних модулей. Мы  написали  нашу
первую программу управления памятью для интегрированной среды Турбо Ана-
лизатор  4.0,  которая  вызывала  компилятор Турбо Паскаля, с тем, чтобы
увеличить размер  компилируемых  программ.  Эта  программа  поставлялась
вместе с исходной программой Анализатора, и не предназначалась для обще-
го использования отдельно. Однако ее возможности оказались настолько по-
пулярными,  что мы создали отдельную версию нашей программы для широкого
применения, и одновременно, опубликовали статью  в  "Dr.Dobbs  Journal".
Программа называлась EXECSWAP, и мало отличалась от своей предшественни-
цы  из  Турбо  Анализатора.  Хотя программа была документирована, она не
включала в себя все необходимые атрибуты, ожидаемые в продуктах для ком-
мерческого распространения. OPEXEC соединяет многие качества программ из
Анализатора и EXECSWAP, и добавляет несколько новых  возможностей,  пре-
доставляемых модулями OPDOS и OPSWAP из Object Professional.
    Процедура ExecDosSwap из OPEXEC работает,во многом,  подобно ее нео-
чищающему память аналогу  ExecDos  из  модуля  OPDOS.  Подобно  ExecDos,
ExecDosSwap переспределяет таблицу свободных блоков Турбо,  восстанавли-
вает векторы прерываний SYSTEM, находит  командный процессор  ДОС,  если
необходимо, и исполняет заданную команду ДОС или программу. В дополнении
к этому, ExecDosSwap распределяет расширенную память (EMS) или открывает
файл  на диске для временного хранения информации из оперативной памяти,
копирует выполняемую программу из оперативной памяти до  выполнения  за-
данных действий и затем,  возвращает ее снова в оперативную память после
их выполнения.  OPEXEC предоставляет вам ряд низкоуровневых процедур для
осуществления контроля за деталями этих операций.
    При использовании OPEXEC надо соблюдать следующие правила :
    - в главной программе в операторе USES модуль  OPEXEC  располагается
только последним;
    - главная программа должна быть как можно меньшей по размеру;
    - исключить   использование  всех функций, обрабатывающих прерывания
главной программы, до выполнения вызова;
    - установить максимальный объем динамически  распределяемой  области
памяти - 655360.
    Первые  два  требования тесно связаны. Выполняя их, вы минимизируете
объем памяти, оставляемой вашей главной программой, при выполнении вызы-
ваемой программы. Эти требования выполнены в полном объеме в приведенной
ниже программе :
     program SwapTest;
     uses
       Dos, OpExec;
     begin
       if ExecDosSwap('', True, nil, 'JUNK.SWP') <> 0 then
         WriteLn('Ошибка');
     end.
    Запустите эту программу и вы увидите, что SwapTest занимает только 4
Кб оперативной памяти, затем выделяется память COMMAND.COM, который  за-
бирает 36 Кб, и вся оставшаяся память доступна для исполнения любой вве-
денной вами команды ДОС.
    Если вы  зададите  OPEXEC  раньше  в операторе USES или ваша главная
программа будет содержать больше операторов,  то во время вызова она бу-
дет  занимать больше места в памяти.  Логика такая же ,  что и для рези-
дентных подкачивающихся программ,  смотри часть 11 для получения большей
информации. Одно замечание : если вы находите, что ваша вызывающая прог-
рамма занимает больше памяти,  чем вы ожидали,  получите при  компиляции
MAP  файл  (  /GS  опция  для TPC,  Options/Linker/Map File/Segments для
TURBO) и посмотрите, какие сегменты связываются раньше OPEXEC.
    Когда  вы поставите в операторе USES главной программы модуль OPEXEC
последним, вы сразу заметите, что вызов функций из OPEXEC может произво-
диться только из главной программы. И еще не забывайте про задачу - сох-
ранить главную программу как можно меньшей по объему. Вы имеете два пути
пути решения этой проблемы. Первый, добавить вызовы в главную  программу
и  смириться  с увеличением ее размера. Но этот путь приемлем только для
небольших программ.
    Второй, использовать процедурную переменную,  которая делает доступ-
ной ExecDosSwap из других подпрограмм.  Этот подход не приводит к увели-
чению занимаемой памяти. Пример,
     unit ExecAccess;
     interface
     uses Dos;
     var
       ExecDosSwap : function (Command : string; UseSecond : Boolean;
                       EDP : Pointer; SwapFName : PathStr) : Integer;
     implementation
     end.

     program MainProg;
     uses
       Dos,
       ExecAccess, {сохранить ее раньше, чем модули в которых она
                    используется}
       ...         {любые модули, используемые в программе}
       OpExec;     {сохранить последней}
     begin
       ExecAccess.ExecDosSwap := OpExec.ExecDosSwap
       ...
     end.
    ExexAccess крохотная программа,  которую вы создаете.  Она полностью
приведена выше. В главной программе вы инициализируете процедурную пере-
менную  оператором  присваивания.  Для вызова ExecDosSwap вы используете
модуль ExecAccess. Фактически вы вызываете ExecDosSwap косвенно, исполь-
зуя процедурную переменную с тем же именем, сохраненную в ExecAccess, но
это не имеет значения, результат будет такой же.
    OPEXEC взаимодействует с несколькими константами ( UseEmsIfAvailable
и NoSwapMsgForEms ), которые могут изменяться вами ко времени выполнения
вызова.  Если  это  так, то включите операторы присваивания сразу  после
инициализации процедурной переменной в главной программе.
    Первые два требования влияют на эффективность работы  OPEXEC.  Треть
правило  определяет,  будет ли нормально функционировать ваша машина или
нет. Помните, что во время  когда  работает  порожденный  процесс,  ваша
главная программа не находится в памяти; ее место занимает другая инфор-
мация.  В  результате,  вы не можете использовать некоторые общепринятые
приемы, такие как, установка обработчиков прерываний в вызывающей  прог-
рамме,  которые влияют на вызываемую, разделение данных между вызываемой
и вызывающей программами (за исключением передаваемых в командной  стро-
ке), и вызов подпрограмм в вызывающей программе из вызываемой.
    ExecDosSwap использует процедуру SwapVectors из Турбо Паскаля, кото-
рая  запрещает для вас использование стандартных обработчиков прерываний
из SYSTEM. Однако, на вас возлагается ответственность избежать использо-
вания  других  обработчиков  прерываний.  Заметим  что  модули  OPMACRO,
OPENHKBD, OPREPLAY, OPTSR и OPSWAP  из  Object  Professional  используют
векторы  прерываний,  которые  должны быть восстановлены. Модуль OPMOUSE
устанавливает драйвер мыши, если вы  вызовите  EnableEventHanding  прямо
или  косвенно;  эта ситуация является критической и вам следует ее избе-
гать. Для получения большей информации  об  избежании  этих  затруднений
смотри описание каждого модуля.
    Последнее  правило - установить максимальную границу для динамически
распределяемой области памяти в 655360 - вытекает  из  рекомендаций  для
ExecDos.  ExecDosSwap  автоматически  сжимает динамическую область Турбо
Паскаля до действительно используемого размера ко времени выполнения вы-
зова. Если вы уменьшите максимальную границу, то  тем  самым  ограничите
память,  доступную для вызываемой программы. Это требование прямо проти-
воположно тому, что рекомендуется при использовании  Борландовской  про-
цедуры Exec из модуля DOS.
    OPEXEC предоставляет некоторые дополнительные полезные возможности :
выдается  сообщение во время перекачки главной программы из или в опера-
тивную память; использование процедуры задаваемой пользователем  в  ука-
занный  момент  при выполнении вызова; контроль за использованием расши-
ренной памяти (EMS).
    Высвечиваемое сообщение  о  процессе  перекачки информации позволяет
пользователю чувствовать удобнее во время коротких задержек.  По опреде-
лению,  сообщение  о  перекачке появляется только когда OPEXEC сохраняет
информацию на диске. Вы можете вообще убрать сообщения (смотри процедуру
SetSwapMsgOn)  или заставить  появляться сообщение в обеих случаях:  при
сохранении на  диске  и  в  расширенной  памяти  (смотри  типизированную
константу NoSwapMsgForEms). Текст сообщения ('Перекачка из ...' и 'Пере-
качка в...') жестко задан в OPEXEC.ASM. Для его изменения вы должны исп-
равить сообщения в исходном файле и снова ассемблировать его.
    Когда  вы  вызываете  ExecDosSwap, она производит последовательность
строго определенных действий : выделение места для  временного  хранения
информации  из оперативной памяти, сжатие динамически распределяемой об-
ласти в Турбо и модификация распределения памяти ДОС, запуск  вызываемой
программы,  и восстановление динамической памяти. Иногда полезно для ва-
шей программы осуществлять контроль между фазами работы, например, отоб-
разить информацию состояния или, дать пользователю возможность прочитать
результаты работы вызванной  программы и так далее. Процедура определяе-
мая пользователем, указанная в ExecDosSwap, предоставляет вам такую воз-
можность. Они тождественны возможностям аналогичной функции для  ExecDos
из OPDOS.

    Константы

      ExecSaveScreen    = 0;
      ExecShowMemory    = 1;
      ExecPauseAfterRun = 2;
      ExecRestoreScreen = 3;
    Код  активизации  передаваемый  ExecDosSwap для функции определяемой
пользователем. Эта коды интерпретируются как соответствующий им  коды  в
модуле OPDOS. Смотри ExecDosSwap для примера использования этих кодов.

      UseEmsIfAvailable : Boolean = True;
    Если  константа  True  ( истина ), то при вызове PrepareExecWithSwap
или ExecDosSwap, OPEXEC попытается выделить место  в  расширенной  (EMS)
памяти  для хранения образа выполняемой программы. Использование EMS для
временного хранения информации является предпочтительным по ряду  причин
:  операции  выполняются  быстрее  и нет необходимости заменять диск или
удалять  файл  сохранения.  Следует  задавать   False   (   ложь   )   в
UseEmsIfAvailable  только  в  случае, если сама вызываемая программа ис-
пользует большое  количество EMS. Если UseEmsIfAvailable принимает  зна-
чение  True  (  истина  )  и  доступно достаточно EMS для сохранения, то
OPEXEC установит значение переменной EmsAllocated в True ( истина ).

      NoSwapMsgForEms : Boolean = True;
    Если значение константы True ( истина ), то OPEXEC никогда не выдаст
сообщения  при  перекачке информации в и из EMS. Глобальное разрешение и
запрещение  выдачи  данного  сообщения  осуществляется  вызовом  функции
SetSwapMsgOn. Для небольших приложений наиболее приемлема выдача сообще-
ния только при записи на диск.

    Типы

      ActionCodeType = ExecSaveScreen..ExecRestoreScreen;
    Код активизации для ExecDosSwap. Смотри описание для ExecSaveScreen,
ExecShowMemory, ExecPauseAfterRun и ExecRestoreScreen в OPDOS  и  пример
для ExecDosSwap ниже.

    Переменные

      NoOfBytesSwapped : LongInt;
    После вызова PrepareExecWithSwap эта переменная содержит число байт,
которые  будут  перекачиваться  на диск или EMS и затем назад. Процедура
определяемая пользователем может использовать эту переменную при переда-
че кода активации ExecShowMemory.

      EmsAllocated : Boolean; {True когда для хранения используется EMS}
      SwapFileAllocated : Boolean; {True - когда файл}
    После успешного вызова PrepareExecWithSwap, одна или другая перемен-
ная примет значение True ( истина ), показывающее место хранения перека-
чиваемой  информации.  Обработчик   выхода   из   OPEXEC   и   процедура
RemoveExecWithSwap используют значения переменных для определения метода
очистки.  Если  вы вызываете ExecDosSwap вместо низкоуровневой процедуры
из OPEXEC, то вы сможете обрабатывать только значение True ( истина )  в
вашей  пользовательской  процедуре,  так как ExecDosSwap освобождает EMS
или стирает файл сохранения до своего завершения.

    Синтаксис
        function ExecDosSwap(Command: string; UseSecond : Boolean;
                       EDP : Pointer; SwapFName : PathStr) : Integer;
    Назначение
        Выполняет  любую  команду ДОС после перекачки исходной программы
        из оперативной памяти.
    Замечания
        ExecDosSwap работает во многом подобно функции ExecDos из OPDOS.
        Как и ExecDos, она временно сжимает  динамически  распределяемую
        область  и  восстанавливает  ее после выполнения вызова. Однако,
        цель сжатия для ExecDosSwap другая. В ExecDos сжатие производит-
        ся с целью освобождения большей памяти для вызываемой программы;
        в ExecDosSwap - для сокращения размера файла сохранения или объ-
        ема памяти EMS,запрашиваемой для перекачки. Размер памяти,  дос-
        тупной  вызываемой  программе,  зависит исключительно от порядка
        связывания программных модулей (смотри рассуждения во введении к
        этой части).
        Command - имя программы или команда ДОС, которая должна быть вы-
        полнена. Command может быть пустой строкой (означает  -  "запус-
        тить  ДОС"). UseSecond показывает, нужно ли загружать вторую ко-
        пию COMMAN.COM для обслуживания вызова Exec.  Если  он  False  (
        ложь  ), то Command должна представлять собой полный маршрут по-
        иска для выполняемой программы, включая расширение.
        Параметр EDP - адрес пользовательской программы, которая  должна
        выдать информацию о состоянии и т.д. Она должна иметь вид
         {$F+}
         procedure MyExecDosProc(ActionCode : ActionCodeType;
                                 Param : Word);
         begin
         end;
        Программа  представляет  собой глобальную процедуру, скомпилиро-
        ванную с дальним типом обращения (FAR модель, получаемая при ис-
        пользовании при компиляции директивы {$F+} ). Если вы не  хотите
        использовать  процедуру  такого  типа,  то  передайте в качестве
        третьего параметра nil (пустой указатель). Для получения  инфор-
        мации о коде активации, смотри описание ActionCodeType в OPDOS и
        пример ниже.
        SwapFName - полный маршрут поиска и имя файла  сохранения.  Файл
        должен находиться на неперемещаемом устройстве (не флоппи диск),
        в противном случае,  ExecDosSwap закончиться аварийно. (Заметим,
        однако, что ExecDosSwap заканчивается аварийно не для всех типов
        перемещаемых устройств,  например, она классифицирует устройство
        Бернулли как неперемещаемое.) Устройство должно иметь достаточно
        места для хранения перекачиваемой информации, иначе, ExecDosSwap
        закончится  аварийно.  Существующий файл с тем же именем переза-
        писывается  без  предупреждения.  Файл  создается  с  атрибутами
        системный   и  скрытый,  поэтому  он  не  отображается  обычными
        средствами и не может быть случайно  уничтожен.  При  завершении
        работы ExecDosSwap стирает файл автоматически. При использовании
        EMS параметр SwapFName не используется.
        ExecDosSwap сохраняет участок памяти, который расположен начиная
        с  указателя  в  середине  модуля  OPEXEC (с метки FirstToSave в
        OPEXEC.ASM, если вы захотите посмотреть) до указателя высшей от-
        метки динамически распределяемой области памяти, HeapPtr,  после
        размещения  в  ней  таблицы свободных блоков. Она инициализирует
        переменную NoOfBytesSwapped, содержащую реальное  число  перека-
        ченных байт.
        ExecDosSwap возвращает следующие коды :
          0 : Успешное завершение
         -1 : Исчерпана память для хранения таблицы свободных блоков
         -5 : Невозможно распределить EMS или открыть файл сохранения
          и еще все коды ошибок ДОС.
        ExecDosSwap  вызывает  функцию SwapVectors из DOS для временного
        восстановления всех  векторов  прерываний,  захваченных  модулем
        SYSTEM.  Однако, она не может восстановить векторы, используемые
        другими модулями - такими как OPENHKBD, например, - и вы  должны
        сделать это там, где необходимо.
        ExecDosSwap  не  будет  работать некоторыми версиями популярного
        модуля EXTEND, который увеличивает  максимальное  число  файлов,
        доступных  программе.  Последняя версия EXTEND устраняет эту не-
        совместимость.  (Эта версия, называемая "4" по новой системе ну-
        мерации, основывается на библиотеке TLIB.  Версии  3.2  и  более
        ранние  не  работают  с ExecDosSwap.) Если вы не имеете доступ к
        версии 4 и старше, то перед вызовом ExecDosSwap обеспечьте  "не-
        расширенность".
        ExecDosSwap  оставляет  файл сохранения открытым в течении всего
        времени выполнения вызванной программы, поэтому  она  не  должна
        резервировать  места  для  маршрута поиска файла в части OPEXEC,
        остающейся резидентной. Так как файл остается  открытым,  мы  не
        советуем  вам  в  вызванной программе производить низкоуровневые
        модификации файловой системы ДОС. Избегайте включать в программы
        CHKDSK, дефрагментация диска, и производить физическую сортиров-
        ку каталогов (подобно Нортоновской DIRSORT).
        Предупреждение  : никогда не используйте ExecDosSwap для запуска
        резидентных программ. ExecDosSwap  перекачивает  большинство  из
        занимаемой вашей программой памяти, с условием, что сможет затем
        восстановить ее для дальнейшего использования. Если она не может
        сделать  этого при попытке перекачки назад в оперативную память,
        ExecDosSwap завершает вашу программу и возвращается к  командной
        строке ДОС.
        Заметим, что ExecDosSwap не может использоваться программами за-
        пускаемыми  "в память" внутри интегрированной среды Турбо Паска-
        ля. При такой попытке, ExecDosSwap возвратит код ошибки,  обычно
        1.
    Примеры

         Code := ExecDosSwap('D:\OPRO\MAKEMENU.EXE',False,nil,'JUNK.SWP');
        Выполняет  MAKEMENU  без запуска командного процессора ДОС. Файл
        сохранения, если будет использоваться,  разместиться  в  текущем
        каталоге.

         program SwapTest;
         uses Dos, OpCrt, OpExec;
         var
           P : Pointer;
           BufSize, Code : Integer;

         {$F+}
         procedure MyExecDosProc(ActionCode : ActionCodeType; Param : Word);
         begin
          case ActionCode of
           ExecSaveScreen : {не выделять буфера экрана,сохранить экран}
            if not SaveWindow(1, 1, ScreenWidth, ScreenHeight, False, P)
              then {не могу выполнить - буфер уже выделен}
           ExecShowMemory :
             begin
               if EmsAllocated then
                 WriteLn('Перекачка в EMS...');
               else
                 WriteLn('Перекачка на диск...');
               WriteLn('NoOfBytesSwapped, 'байт перекачано');
               WriteLn('Примерно : ', Param, 'Кб RAM доступно');
             end.
           ExecPauseAfterRun :
             begin
               Write('Нажми <Enter>...');
               ReadLn;
             end;
           ExecRestoreScreen : {восстановить экран, не освобождать буфер}
             RestoreWindow(1, 1, ScreenWidth, False, P);
          end;
         end;
         {$F-}
         begin
           UseEmsIfAvailable := False;
           SetSwapMsgOn(False);
           {распределить буфер экрана}
           BufSize := 2*ScreenWidth*ScreenHeight;
           GetMem(P, BufSize);
           {выполнить команду DIR}
           Code := ExecDosSwap('DIR', False, @MyExecDosProc,'JUNK.SWP');
           case Code of
              0 : {Успех}
             -1 : WriteLn('Исчерпана память для хранения таблицы
                                                      свободных блоков ');
             -5 : WriteLn('Невозможно распределить EMS или открыть
                                                       файл сохранения ');
           else
             WriteLn('Ошибка ДОС ', Code);
           end;
           {освободить буфер экрана}
           FreeMem(P, BufSize);
         end.

        Выполняет  команду  ДОС  RUN. В этом примере всегда производится
        сохранение на диске и не выдается сообщение о перекачке.
        MyExecDosProc обрабатывает код активизации функции пользователя.
        Вы  могли бы использовать эту функцию и в других модулях, вместе
        с вызовом ExecDosSwap, не использующих модуль  OPEXEC.  Для  ис-
        пользования  в  MyExecDosProc переменной NoOfBytesSwapped в этом
        случае, вам необходимо делать ссылку на нее через указатель. До-
        бавьте следующее определение  переменной  в  модуль  ExecAccess,
        приведенный ранее :
         var
           NoOfBytesSwappedPtr : ^LongInt;
        Добавьте  следующей оператор инициализации в главный блок основ-
        ной программы
           NoOfBytesSwappedPtr := @OpExec.NoOfBytesSwappedPtr
        И последнее, измените в обработчике кода активизации на
           WriteLn('NoOfBytesSwapped^, 'байт перекачано');
    Смотри также
        ExecDos(OPDOS)                          PrepareExecWithSwap

    Синтаксис
        procedure ExecWithSwap(Path, CmdLine : string);
    Назначение
        Запускает ДОС с перекачкой содержимого на диск или в EMS.
    Замечания
        Эта  процедура  выполняет  один из этапов работы ExecDosSwap. Вы
        найдете ее полезной если, а) вы хотите распределить файл  сохра-
        нения  или  EMS  только один раз и оставить это распределение на
        все время работы программы, или б) вы  хотите  получить  больший
        контроль  над размером перекачиваемой памяти. ExecWithSwap пред-
        полагает, что устройство для сохранения информации уже определе-
        но и открыто  вызовом  PrepareExecWithSwap.  Вы  должны  вызвать
        RemoveExecWithSwap для закрытия и очистки устройства сохранения.
        Параметры  для  ExecWithSwap интерпритируются как и для подобной
        ей процедуры Exec из DOS. Path - полный маршрут поиска  для  вы-
        полняемой  программы.  CmdLine  -  командная строка для передачи
        этой программе. Заметим, что ExecWithSwap не  находит  командный
        процессор ДОС или не строит соответствующей командной строки для
        передачи ему (как это делают ExecDosSwap и ExecDos).
        Для определения исхода работы ExecWithSwap проверяйте переменную
        DosError.  Коды ошибок соответствуют кодам ошибок ДОС. Для более
        подробной информации смотри Справочное Руководство по Турбо Пас-
        калю, раздел "Ошибки Исполнения".
        Смотри PrepareExecWithSwap для большей информации и примеров ис-
        пользования.
    Смотри также
        PrepareExecWithSwap                     RemoveExecWithSwap

    Синтаксис
        function PrepareExecWithSwap(LastToSave : Pointer;
                                     SwapFileName : PathStr) : Boolean;
    Назначение
        Подготавливает условия для запуска командного процессора с пред-
        варительной откачкой содержимого оперативной памяти, и в  случае
        успешного завершения возвращает True ( истина ).
    Замечания
        Функция  PrepareExecWithSwap  выполняет  один  из  этапов работы
        ExecWithSwap. Вы найдете ее полезной если, а) вы хотите  распре-
        делить  файл  сохранения  или EMS только один раз и оставить это
        распределение на все время работы программы, или  б)  вы  хотите
        получить  больший  контроль  над размером перекачиваемой памяти.
        Параметр LastToSave задает адрес последней ячейки памяти,  кото-
        рую PrepareExecWithSwap будет сохранять и затем восстанавливать.
        Начальный  адрес  всегда один и тот же : середина модуля OPEXEC.
        Что вы выберете в качестве LastToSave  будет  влиять  только  на
        размер  файла  сохранения  или размер необходимой EMS памяти, но
        никогда не будет влиять на размер резидента, оставляемого в  па-
        мяти во время выполнения вызова.
        Существует  три приемлемых значения для LastToSave. Определяя ее
        как переменную HeapOrg из модуля SYSTEM, мы заставляем OPEXEC не
        сохранять любую часть динамически  распределяемой  области;  эта
        лучшая  возможность  для  программ, которые вообще не используют
        динамическую память. Определяя ее  как  HeapPtr,  мы  заставляем
        OPEXEC  сохранять только распределенные участки динамической па-
        мяти. Так как будет проигнорирован только список свободных  бло-
        ков,  следовательно  эта  возможность приемлема только для прог-
        рамм, которые не будут не распределять ни освобождать пространс-
        тво в динамической памяти после вызова  ExecWithSwap.  Определяя
        ее   как  выражение  Ptr(Seg(FreePtr^)+$1000,0),  мы  заставляем
        OPEXEC сохранять всю динамически распределяемую область  памяти,
        включая  список  свободных блоков. Это наиболее консервативный и
        безопасный прием, но он может привести к увеличению файла сохра-
        нения до 640 Кб.
        Когда ExecDosSwap вызывает PrepareExecWithSwap, то она  передает
        HeapPtr в качестве LastToSave. Но перед тем как делать это, она,
        однако,  выделяет  пространство  в динамической памяти для копии
        списка свободных блоков. После завершения вызываемой  программы,
        она  восстанавливает  список свободных блоков и освобождает вре-
        менный буфер. Таким путем ExecDosSwap минимизирует размер  файла
        сохранения,  одновременно не ограничивая возможности использова-
        ния динамически распределяемой области памяти до и после вызова.
        SwapFileName задает имя и маршрут для файла сохранения. Требова-
        ния для этого файла те же самые, что описаны в ExecDosSwap.
        PrepareExecWithSwap вычисляет число байт для перекачки и  хранит
        это значение в NoOfBytesSwapped. Если UseEmsIfAvailable принима-
        ет значение True ( истина ) и необходимая память в EMS доступна,
        то  она  выделяет в ней необходимое пространство. Иначе, функция
        создает файл сохранения и оставляет его открытым.  Если  никакая
        из  этих  операций невозможна, то PrepareExecWithSwap возвращает
        False ( ложь ).
    Пример
         if not PrepareExecWithSwap(Ptr(Seg(FreePtr^)+$1000,0),
                                    'JUNK.SWP') then
           WriteLn('Невозможно выделить память для перекачки');
         else begin
           ExecWithSwap('D:\OPRO\MAKEMENU.EXE', '');
           if DosError <> 0 then
             WriteLn('Ошибка выполнения', DosError);
           RemoveExecWithSwap;
         end;
        Показан   надлежащий   порядок    вызова    PrepareExecWithSwap,
        ExecWithSwap и RemoveExecWithSwap.
    Смотри также
        ExecDosSwap

    Синтаксис
        procedure RemoveExecWithSwap;
    Назначение
        Освобождает память EMS или удаляет файл сохранения, в зависимос-
        ти от того, что из них было распределено.
    Замечания
        RemoveExecWithSwap осуществляет освобождение памяти после работы
        PrepareExecWithSwap. Вам не  надо  вызывать  RemoveExecWithSwap,
        если вы используете только ExecDosSwap. OPEXEC тоже содержит об-
        работчик  выхода  из  программы,  который автоматически вызывает
        RemoveExecWithSwap при завершении программы.
        Для    примеров    и    дополнительной     информации     смотри
        PrepareExecWithSwap.
    Смотри также
        ExecDosSwap

    Синтаксис
        procedure SetSwapMsgOn(On : Boolean);
    Назначение
        Разрешает и запрещает выдачу сообщения об перекачке информации.
    Замечания
        По  умолчанию  сообщение  выдается всегда. Константа типа булеан
        NoSwapMsgForEms определяет появление сообщения при  перекачке  в
        EMS.
        OPEXEC  передает сообщение на устройство StdErr (стандартный вы-
        вод ошибок), используя возможности ДОС. Во время пересылки  дан-
        ных  из  оперативной памяти, перед вызовом дочерней программы, в
        текущей позиции курсора появляется сообщение "Перекачка  из...".
        После  завершения  процесса перекачки информации OPEXEC посылает
        символ возврата каретки и достаточное  количество  пробелов  для
        очистки сообщения. Важное замечание : для обеспечения правильной
        работы  при выдаче сообщения курсор должен находиться в 1 колон-
        ке.
        После завершения вызванной  программы  OPEXEC  посылает  символы
        "конец  строки" и "возврат каретки" (<CR><LF>) и затем сообщение
        "Перекачка в...",  которое забивается пробелами по окончании пе-
        рекачки.
    Пример
         SetSwapMsgOn(False);
        Запрещает выдачу сообщения о перекачке.

        D. OPENHKBD : Интерфейс расширенной клавиатуры.

    Хотя  расширенная  клавиатура (с 12 функциональными клавишами вместо
10) быстро становится стандартным оборудованием для новых машин, сущест-
вует все еще сравнительно небольшое число программ, полностью  поддержи-
вающих ее. На это существует три причины. Первая, с тем, чтобы прочитать
все  клавиши  расширенной  клавиатуры вы должны использовать специальный
вызов функции BIOS. Второе, прежде чем использовать этот вызов вы должны
удостовериться, установлена ли на вашем компьютере расширенная клавиату-
ра, при  этом  не  существует  стандартных  методов  обнаружения  этого.
Третье,  достаточно трудно писать программы, работающие одинаково хорошо
на расширенных клавиатурах и клавиатурах "старого стиля", так  как  мно-
жество  специальных  комбинаций  нажатых  клавиш,  таких  как <AltEsc> и
<CtrlTab>, распознаваемых расширенной клавиатурой, не распознаются  ста-
рой.
    OPENHKBD  решает эти проблемы путем распознавания и активации расши-
ренной клавиатуры на вашей машине, если она ее  имеет,  и  моделирование
ее, если установлена старая модель. Когда OPENHKBD установлен, расширен-
ные  скан  коды  будут  возвращаться всеми процедурами, которые читают с
клавиатуры : ReadKey(CRT/OPCRT), ReadKeyWord(OPCRT)  и  любыми  другими,
использующими  стандартные  возможности ДОС/BIOS для клавиатуры. Вам нет
необходимости запускать какие-либо процедуры : модули инициализируются и
удаляются  из памяти автоматически, и эти операции полностью переносятся
в программы их использующие.

    Как работает OPENHKBD.

    OPENHKBD выполняет свои функции путем инициализации двух  обработчи-
ков прерываний. Первый использует прерывание $16, прерывание BIOS клави-
атуры,  и перехватывает все запросы к BIOS клавиатуры на ввод. Если рас-
ширенная клавиатура установлена, то обработчик прерываний будет перенап-
равлять все обращения к стандартным функциям клавиатуры ($00, $01 и $02)
к соответствующим функциям расширенной клавиатуры ($10, $11 и $12).
    Второй обработчик прерываний использует  прерывание  $9,  аппаратное
прерывание,  которое вызывается каждый раз при нажатии и отпускании кла-
виши. Он  проверяет на определенные комбинации, которые в обычных  усло-
виях не возвращаюся BIOS. Если одна из комбинаций обнаружена, то она об-
ходит  стандартный обработчик прерываний клавиатуры BIOS, и посылает со-
ответствующий комбинации код (смотри таблицу ниже) в буфер клавиатуры.

    Коды клавиш

    Приведенная таблица содержит коды , которые генерируются при нажатии
одной клавиши или их комбинации при использовании  OPENHKBD.  Все  числа
представлены  в шестнадцатиричной системе и представляют собой значения,
которые были бы возвращены функцией ReadKeyWord из OPCRT.  Если  вы  ис-
пользуете  функцию  ReadKey (из CRT или OPCRT) для получения введенных с
клавиатуры символов и возвращаемый символ #0 (представляет младший  байт
кода клавиши), то второе обращение к ReadKey возвратит скан код (старший
байт).  Клавиши, не представленные в таблице, возвращаюся в обычном виде
(смотри коды клавиш в Приложении С в  Справочном  руководстве  по  Турбо
Паскалю  5.0 или быстрой справке в DESKPO). Обратите внимание на замеча-
ния после таблицы, на которые ссылаются при помощи специальных символов,
следующих после кодов.

    Клавиша                       Shift  Control   Alt

    F11                   8500%   8700%   8900%   8B00%
    F12                   8600%   8800%   8A00%   8C00%
    Esc                   011B    011B    011B    0100*
    `                     2960    297E    2960    2900*
    Backspaсe  (Возврат)  0E08    0E08    0E7F    0E00*
    Tab                   0F09    0F00    9400*   A500*
    (                     1A5B    1A7B    1A1B    1A00*
    )                     1B5D    1B7D    1B1D    1B00*
    \                     2B5C    2B7C    2B1C    2B00*
    ;                     273B    273A    ....    2700*
    '                     2827    2822    ....    2800*
    Enter                 1C0D    1C0D    1C0A    1C00*
    ,                     332C    333C    ....    3300*
    .                     342E    343E    ....    3400*
    /                     352F    353F    ....    3500*
    Insert                5200    5230    9200*   A200#
    Del                   5300    532E    9300*   A300#
    Home                  4700    4737    7700    9700#
    End                   4F00    4F31    7400    9F00#
    PgUp                  4900    4939    8400    9900#
    PgDn                  5100    5133    7600    A100#
    Вверх                 4800    4838    8D00*   9800#
    Вниз                  5000    5032    9100*   A000#
    Лево                  4B00    4B34    7300    9B00#
    Право                 4D00    4D36    7400    9D00#
    * (на цифровой)       372A    !!!!    !!!!    3700# (дополнительная
    - (на цифровой)       4A2D    4A2D    8E00*   4A00#  цифровая
    + (на цифровой)       4E2B    4E2B    9000*   4E00#  клавиатура)
    5 (на цифровой)       4C00*   4C35    8F00*   9C00#

    Замечания :
    ....   Эти нажатия клавиш игнорируются.
    *      Эти нажатия клавиш в обычном режиме не обрабатываются
           "старой" клавиатурой.
    #      Эти нажатия клавиш в обычном режиме не обрабатываются
           расширенной клавиатурой.
    !!!!   Эти нажатия клавиш управляют печатью экрана и эхом на
           принтере. Они не могут моделировать эффект расширенной клави-
           атуры, при котором клавиши * и PrtSc разделены.
    %      F11 и F12 возвращаются если они действительно присутствуют на
           клавиатуре.

    За  некоторым исключением, модуль OPENHKBD возвращает значения иден-
тичные тем, что были бы на расширенной клавиатуре. Одно различие  делает
расширенную клавиатуру проще для использования в программах: скан слова,
которые  в обычном режиме содержат $E0 в младшем байте для индикации то-
го, что клавиша характерна только для  расширенной  клавиатуры  (подобно
выделенным  клавишам  управления  курсором), будут иметь нулевой младший
байт после обработки OPENHKBD.
    Коды,  отмеченные  знаком  #, в обычном режиме игнорируются BIOS-сом
расширенной клавиатуры. Следовательно, дополнительная цифровая клавиату-
ра, при нажатой клавише <Alt>, не способна вводить произвольные символы.
В приложениях возможность использования дополнительной цифровой  клавиа-
туры совместно с нажатыми Alt+Shift, обычно, более полезна. Заметим, од-
нако,  что  такая  возможность у вас есть. Например, для ввода символа с
кодом #196 вы  должны,  держа  нажатыми  левой  рукой  клавиши  <Alt>  и
<LeftShift>,  ввести правой рукой 196 на дополнительной цифровой клавиа-
туре, и затем отпустить <Alt> и <LeftShift>.
    Заметим, что быстрая справка в DESKPOP  отображает  все  специальные
коды, возвращаемые OPENHKBD. Если вы выведите DESKPOP, открыв справочное
окно,  и посмотрите на колонку "Расширенные", то все специальные клавиши
имеют повышенную интенсивность или белый цвет, делающий их отличными  от
стандартных и не стандартных клавиш.

    Смешанные вопросы

    Тест, используемый OPENHKBD, для обнаружения присутствия расширенной
клавиатуры,     идентичен     тому,     который    использует    функция
EnhancedKbdInstalled из OPCRT, и он является не совсем простым. Для  об-
суждения  теста смотри часть "Поддержка расширенной клавиатуре" в описа-
нии модуля OPCRT.
    OPENHKBD должн, по возможности, быть первым в  операторе  USES.  Это
обстоятельство  особенно важно для резидентных программ. Если вы исполь-
зуете OPENHKBD в программе, которая также работает с  OPTSR,  вы  должны
поставить  OPENHKBD  в  операторе  USES до OPTSR, тем самым гарантировав
восстановление векторов прерываний в надлежащем порядке.
    Важное  замечание : Так как OPENHKBD использует прерывание $9, то он
может разрушить систему, в случае, если установлен SideKick и после это-
го , но перед активацией OPENHKBD, была загружена резидентная программа,
использующая прерывание $9. (Поэтому Борланд всегда  рекомендует  загру-
жать  SideKick последним.) Вы должны проявлять подобную осторожность при
использовании этого модуля в программах,  которые  должны  перехватывать
прерывание  $9  для других целей. Это замечание не касается программ ис-
пользующих модули OPTSR и OPSWAP, так как  они  автоматически  отключают
обработчик  прерывания $9 в SideKick, создающий все проблемы; это обычно
не касается SideKickPlus.
    Однако, это важно в программах, использующих OPENHKBD, и запускающих
другие программы (путем вызова Exec, ExecDos, ExecDosSwap и т.д.). В та-
ких программах вы должны следовать следующей стратегии :
     {восстановить вектора клавиатуры, захваченные OPENHKBD}
     RestoreKbdVectors;
     {--- выполнение другой программы ---}
     {восстановление обработчика прерываний для OPENHKBD}
     InitKbdVectors;
    Следуя этой схеме вы избежите возникновения проблем, даже при работе
загруженного ранее SideKick и запущенных вами программ, также использую-
щих прерывание $9.

    Константы

     EnableEnhanced : Boolean = True;
    Устанавливая ее в False ( ложь ), вы тем самым временно  преостанав-
ливаете работу обработчиков прерываний OPENHKBD.

    Переменные

     HasEnhancedKbd : Boolean;
    Эта  переменная принимает значение True ( истина ), если расширенная
клавиатура обнаружена. Переменная предназначена, в основном, для  инфор-
мационных  целей.  Принудительное изменение ее значения может привести к
нежелательным последствиям.

    Синтаксис
        procedure InitKbdVectors;
    Назначение
        Сохраняет и  устанавливает  векторы   прерываний,   используемые
        OPENHKBD.
    Замечания
        Эта  процедура  предназначена  для использования только в паре с
        процедурой RestoreKbdVectors. Она вызывается автоматически с по-
        мощью кода активизации OPENHKBD, и не должна вызываться снова до
        вызова  RestoreKbdVectors.  Вызов   InitKbdVectors   до   вызова
        RestoreKbdVectors приведет к зависанию системы сразу после нажа-
        тия на любую клавишу.
        InitKbdVectors предназначена только для одной цели  :  позволить
        вам  восстановить векторы прерываний, измененные OPENHKBD (вызо-
        вом RestoreKbdVectors), и позднее снова возобновить  работу  его
        обработчиков  прерываний. Для детальной информации смотри секцию
        "Смешанные вопросы" выше.

    Синтаксис
        procedure RestoreKbdVectors;
    Назначение
        Восстанавливает оригинальные векторы прерываний $09 и $16.
    Замечания
        Эта  процедура  восстанавливает векторы прерываний, которые были
        изменены OPENHKBD в начале  выполнения  программы.  Эти  векторы
        восстанавливаются  автоматически  при  завершении  программы, но
        иногда требуется восстановить их вручную, путем вызова этой про-
        цедуры. Такая необходимость возникает в  резидентных  программах
        при  вызове  DisableTSR для перемещения их из оперативной памяти
        (для примера смотри файл SMACS.PAS), но это  одинаково  важно  и
        для  программ,  запускающих  во  время  своего выполнения другие
        программы (смотри секцию "Смешанные вопросы" выше).
        Однажды  вызвав  RestoreKbdVectors, вы можете возобновить работу
        обработчиков прерываний OPENHKBD вызовом InitKbdVectors. Если же
        вам нужно только временно преостановить  преобразование  функций
        клавиатуры,  осуществляемое обработчиками прерываний, то устано-
        вите значение глобальной переменной  EnableEnhanced  в  False  (
        ложь  ),  и  затем,  когда снова захотите возобновить их работу,
        снова в True ( истина ).
    Пример
         uses OpEnhKbd, OpTsr;
         ...
         if DisableTSR then
           RestoreKbdVectors;
         else
           {выдача сообщения об ошибке -- небезопасно выгружать резиден-
            тную программу}
        В приведенном примере RestoreKbdVectors вызывается перед выгруз-
        кой  резидентной  программы  из  оперативной  памяти.   Заметим,
        OPENHKBD должен стоять в операторе USES перед OPTSR, для обеспе-
        чения  восстановления  векторов  прерываний,  изменяемых  обеими
        программами, в надлежащем порядке.
    Смотри также
        Disable(OPTSR)