
     G. OPHELP: Система Подсказки
     ───────────────────────────────────────────────────────────

     Если вы   когда-либо   разрабатывали   контекстно-зависимые
системы  подсказки  для  прикладных  программ,  то  вы  наверное
знаете,  что надо приложить значительные усилия,  чтобы написать
удовлетворительную  и  простую  в использовании систему.  Модуль
OPHELP  предлагает  вам  мощный   и   удобный   инструмент   для
подсоединения экранов с подсказкой к программам.

     Существует три,  может быть четыре,  шага,  необходимых для
разработки систем подсказки.

     1.  Написать текст подсказки

     2.  Преобразовать текстовый файл в сжатый,  индексированный
         файл с подсказкой

     3.  Применить соответствующий  OPHELP-метод  для управления
         окном подсказки

     4.  Использовать средства CommandProcessor  для подключения
         окна подсказки к другим объектам программы

     Для написания  текста  подсказки  можно  использовать любой
текстовый редактор на подобии редактора из пакета  Turbo. Каждый
файл   подсказки  может  содержать  необходимое  вам  количество
пунктов.  OPHELP быстро обращается к каждому пункту по имени или
номеру.  Ниже  будет  описан формат текстового файла.  Для того,
чтобы преобразовать текст надо  использовать  утилиту  MAKEHELP,
поставляемую с пакетом.
     OPHELP предоставляет три приема для управления окнами. Один
из   них,  AbstractHelpWindow,  представляет  собой  абстрактный
объект,  который  предоставляет  методы  доступа   к   бинарному
текстовому   файлу,   но   не   реализует   методы  визуализации
информации.  Два другие,  PagedHelpWindow и ScrollingHelpWindow,
предлагают два различных пути визуализации справочной информации
и  взаимодействия  с  пользователем.  PagedHelpWindow   работает
подобно программе TPHELP из пакета Turbo Professional: подсказка
выдается постранично. Клавиши PgUp и PgDn позволяют пролистывать
страницы,  а клавиши передвижения курсора перемещают высвеченную
полоску от одной перекрестной ссылки  к  другой.  В  отличии  от
этого объекта,    ScrollingHelpWindow    предлагает   построчную
вертикальную  и  горизонтальную  прокрутку.  Аппаратный   курсор
остается  видимым  и  передвигается с помощью клавиш перемещения
курсора для  того,  чтобы  сделать  выбор  перекрестной  ссылки.
Объект ScrollingHelpWindow   больше  подходит  для  современного
программного  обеспечения,  которое   использует   регулируемые,
настраиваемые   окна.   Мы   выбрали  его  для  использования  в
электронном справочном руководстве POPHELP.
     По желанию    сжатый   файл   с   подсказкой   может   быть
непосредственно включен в программу.  В  этом  случае  не  нужны
никакие дополнительные файлы для этого программного обеспечения.
При  громоздких  файлах  с  подсказкой  или  больших  прикладных
пакетах  файл хранится отдельно и OPHELP читает из него в память
по частям при необходимости.
     Система подсказки позволяет создавать до 10 тысяч пунктов в
одном файле. Каждый пункт может содержать перекрестные ссылки на
другие пункты,  до 50-ти перекрестных ссылок  на  каждый  пункт.
(Эти ограничения  могут  быть  уменьшены  заданием  константы  в
OPHELP.)  Подсказка  выводится  в  выкидное окно,  через которое
пользователь может ее просматривать.  Управляемое форматирование
позволяет  выдавать  подсказку  с использованием шести различных
видео   атрибутов.   Преобразователь   подсказки   автоматически
переносит  слова  и  размечает  страницы  начального  текста под
управлением директив, которые вы задали.
     Вы можете  выбрать  для  каждого  пункта  различные  приемы
визуализации: непосредственно по номеру пункта, по имени пункта,
сканированием  контекстных  слов  текущего  экрана,  выбором  из
главного индекса, по перекрестной ссылке на связанные пункты или
по  ссылке  на набор пунктов подсказки,  выбранных перед текущим
пунктом.  Большинство этих приемов обрабатывается  автоматически
без каких-либо  усилий  с  вашей  стороны.  Система OPHELP также
полностью  поддерживает  управление  мышью,   позволяя   сделать
систему подсказки более дружественной.
     Текстовые файлы,  используемые для ввода в систему  OPHELP,
совместимы со  старыми,  которые  используются  в  системе Turbo
Professional.  Кроме  того,  в  систему  OPHELP  добавлено   еще
несколько  новых  команд,  но все старые при этом работают также
как и раньше.  Система MAKEHELP из Object Professional позволяет
производить  усовершенствованное сжатие и имеет некоторые другие
новые возможности.  Для того,  чтобы использовать старые файлы с
подсказкой, надо их сначала перекомпилировать.
     Остальные разделы этого введения содержат  пример,  который
вы можете запустить,  и рассказывают о том, как делать текстовые
файлы с  подсказкой,  а  затем  преобразовывать  их  с   помощью
MAKEHELP. Затем   эта  информация  применяется  либо  в  объекте
PagedHelpWindow, либо  в  объекте  ScrollingHelpWindow,  которые
используют одни и те же входные файлы.  Обратите внимание на то,
что  форматирование  файла  можно  оптимизировать   на   предмет
наилучшего расположения на экране или по другим параметрам.
     После этого  начального  материала  мы  продолжим  в   трех
разделах описание объектов AbstractHelpWindow, PagedHelpWindow и
ScrollingHelpWindow, а затем покажем несколько процедур, которые
система  OPHELP  использует  для  выбора более предпочтительного
вида окна подсказки конкретного файла помощи.

     Простой Пример Подсказки
     ──────────────────────────────────────────────────────────-

     Следующая короткая  программа  показывает как выбрать пункт
подсказки из   главного   индекса,   показать    вспомогательную
информацию по  этому  пункту  и  интерпретировать коды выхода из
метода Process. Мы будем использовать объект PagedHelpWindow, но
для объекта    ScrollingHelpWindow    подходит   та   же   самая
методология.  Если  вы  хотите  запустить  программу,   обратите
внимание  на  то,  что  вместе  с  программным  файлом ENTRY.EXE
используется  файл  помощи  ENTRY.HLP.   Файл   ENTRY.TXT   тоже
присутствует   и   вы   можете  ссылаться  на  него  в  процессе
последующей дискуссии.

     program HelpExample; {EXHELP1.PAS}
     uses
       OpCrt, OpRoot,  OpCmd,  OpMouse, OpFrame, OpWindow,
       OpPick, OpHelp;
     var
       PH : PagedHelpWindow;
       Finished : Boolean;
     begin
       {Создать страничное окно подсказки с оконными параметрами}
       if not PH.InitCustom(9, 8, 72, 18,     {Координаты окна}
                            DefaultColorSet,  {Цвета}
                            DefWindowOptions  {Параметры окна}
                            or wBordered,
                            'ENRTY.HLP',      {Файл с подсказкой}
                            PickVertical)     {Направленность}
       then begin
         WriteLn('Ошибка при определении страничного окна подсказки,
                  Статус =', InitStatus);
         Halt;
       end;

       {Добавим некоторые возможности}
       PH.EnableExplosions(10);
       PH.wFrame.AddHeader(' Индекс пунктов', heTC);
       PH.AddMoreHeader(' ││ - следующее', heBR, #24, #25, '', 2, 3, 0);
       PH.AddTopicHeader(1, 60, heTC);
       PH.AddMoreHelpHeader(
          ' PgUp/PgDn - следующее', heBR, 'PgUp', 'PgDn', '/', 2, 7, 6);
       PH.wFrame.AddScrollBar(frRR, 0, MaxLongInt, DefaultColorSet);
       PH.hwFrame.AddScrollBar(frRR, 0, MaxLongInt, DefaultColorSet);

       {Цикл по системе подсказки}
       Finished := False;
       repeat

         {Вывести главный индекс и выбрать пункт подсказки}
         PH.SetTopic(PickTopic);
         PH.Process;
         case PH.GetLastCommand of
           ccError,
           ccQuit :
             Finished := True;
           ccSelect :
             begin
               PH.SetTopic(PH.GetTopicChoice);
               repeat
                 PH.Process;
                 case PH.GetLastCommand of
                   ccError :
                     Finished := True;
                   ccQuit :
                     if not PH.InHelpMode then
                       {Уйти из выбранного окна подсказки}
                       Finished := True;
                   {...другая подсказка или команды выхода...}
                 end;
               until Finished or (PH.GetLastCommand = ccQuit);
             end;
           {...другие команды выхода...}
         until Finished;

         PH.Done;
       end.

     PH.InitCustom определяет    координаты    активного    окна
подсказки, используемые    цвета,    параметры     окна,     имя
преобразованного файла  подсказки  и направление списка главного
индекса подсказки.  Как и с любым  другим  оконным  объектом  мы
можем добавлять  заголовки  и  использовать  другие  специальные
эффекты. Обратите внимание на то,  что AddMoreHeader  наследован
из PickList,  который  является  предком  PagedHelpWindow.  Этот
заголовок появляется только,  когда окно подсказки  находится  в
режиме "выбора" - термин, определенный для того, чтобы показать,
что выведен главный индекс ,  в отличии от  режима  "подсказки",
применяемом  при  выводе  текста  подсказки.  Для окна подсказки
определены еще   два   специализированных   типа   заголовка   -
AddTopicHeader, который  выводит  имя  текущего  пункта в режиме
подсказки, и AddMoreHelpHeader,  который похож на AddMoreHeader,
но указывает,  что за экраном осталась еще какая-то часть текста
подсказки.
     Точно также мы можем добавить прокручивающиеся полоски,  но
с некоторой уловкой.  Обычно окна имеют два объекта  типа  Frame
(рамка), которые  определяют  окна:  wFrame  и  aFrame (смотрите
OPWINDOW). Окно  подсказки  добавляет  третий  объект:  hwFrame.
Объект hwFrame  выводится  только тогда,  когда окно находится в
режиме подсказки,  в то время как объект wFrame выводится, когда
окно находится  в  режиме выбора.  Имея две отдельных рамки,  мы
можем использовать  специализированные   заголовки,   применимые
только каждый   к  своей  рамке.  В  некоторых  случаях,  как  с
прокручивающимися полосками,  мы должны сдублировать возможности
рамок для  того,  чтобы убедиться в их появлении в обеих режимах
окон.
     Если вы  сомневаетесь,  то  можно отменить индекс выбора из
окна подсказки и использовать его  в  не  таком  шизофреническом
режиме. Вы  можете  делать  это  динамически,  удаляя  параметры
подсказки для hwPickIndex или  не  индексируя  все  пункты,  как
будет показано в разделе "Директивы для Файла Подсказки".
     Цикличность объекта Process снова указывает на двойственную
природу  окна  подсказки.  При  прохождении  в примере по особым
номерам пунктов  PickTopic  (который  равен  нулю)  к  SetTopic,
Process переключает окно в режим выбора и выдает список главного
индекса.  При  обнаружении  ошибки  или  нажатии   пользователем
клавиши <Esc>,  Finished устанавливается в истину для прерывания
программы. В противном случае, программа устанавливает выбранный
пункт как  выдаваемый  функцией  GetTopicChoice и начинает новый
цикл, который интерпретирует команды выхода уже  по  другому.  В
этом цикле,  если  пользователь  нажимает  клавишу  <Esc> и окно
находится в  режиме  подсказки,   то   производится   выход   из
внутреннего цикла  и  управление  передается во внешний цикл для
того, чтобы  сделать  выбор  нового  пункта.  Если  пользователь
нажимает клавишу  <esc>  в  окне  в режиме выбора,  то программа
заканчивается.
     Как же  можно получить режим выбора во внутреннем цикле?  В
режиме подсказки командный процессор интерпретирует клавишу <F1>
как требование  пользователя  выдать  главный  индекс подсказки.
Если эта клавиша нажата,  то из Process не происходит выхода для
переключения в режим выбора.
     Эти вложенные циклы могут быть более сложные,  чем  требует
ваша прикладная  программа.  Если  вы уже знаете пункт,  который
нужен (в зависимости от контекста ситуации) и вы  не  определили
особых команд  для  выхода  из  окна  подсказки,  то  все  циклы
исчезают:

     PH.SetTopic(TopicYouWant);
     PH.Process;
     if PH.GetLastCommand = ccError then
       {Нет доступа к подсказке--гудок или вывод сообщения};

     Директивы для Файла Подсказки
     ──────────────────────────────────────────────────────────-

     Информация, выводимая  системой  подсказки,  начинается   с
текстового файла,  который вы должны написать. Вам надо при этом
вставить в  этот  текст  директивы  для  того,   чтобы   указать
компилятору как форматировать и интерпретировать файл.
     Обычно используется расширение .TXT для того, чтобы указать
на текстовый файл подсказки,  и подготавливается расширение .HLP
для бинарного файла,  преобразованного программой MAKEHELP. Хотя
система подсказки не требует этих расширений, программа MAKEHELP
использует их по умолчанию.
     Директивы в   текстовом  файле  помечаются  восклицательным
знаком в  первой  позиции  строки,  за  ним  сразу  следует  имя
директивы, а  затем  параметры модификации,  отделенный от имени
директивы одним или несколькими  пробелами.  В  имени  директивы
значимыми являются только первые пять символов.
     Далее следует      описание      директив,      принимаемых
преобразователем подсказки.  Обратитесь  к  файлу  ENTRY.TXT  за
реальным примером использования этих директив.

     !WIDTH Width
     ──────────────────────────────────────────────────────────-

     Определяет число  позиций  занимаемых активной порцией окна
подсказки. По умолчанию,  когда подсказка выводится,  она  будет
отделена от  краев окна одной позицией с каждой стороны.  Однако
действительная ширина  текста  равна  (Width-2)   позиций.   При
включении переноса  слов,  MAKEHELPбудет  переносить слова после
позиции (Width-2). Если не указана директива !WIDTH, то MAKEHELP
устанавливает ширину окна на 40 позиций.
     Так как MAKEHELP переносит слова в тексте,  то  определение
ширины системы  подсказки должно быть встроено в файл подсказки.
При выводе подсказки уже нельзя переделать переноса слов. Однако
ширина видимого  окна подсказки может быть выбрана независимо от
ширины переноса.  Это  имеет  особый  смысл  при  выводе   файла
подсказки с помощью объекта ScrollingHelpWindow.
     MAKEHELP автоматически не вставляет разделители  страниц  в
текст подсказки, поэтому вы должны сделать эти разделители сами,
используя директиву !PAGE.
     Директива !WIDTH  должна  применяться  до  первой директивы
!TOPIC.

     Пример

          !WIDTH 70

     MAKEHELP будет оставлять максимум  68  символов  на  каждой
строке текста подсказки при переносе слов.

     !NOWRAP
     !WRAP
     ──────────────────────────────────────────────────────────-

     Директива !NOWRAP  отменяет  перенос  слов,  который обычно
производит MAKEHELP.  Строки  подсказки  переносятся  прямо   из
входного текстового   файла   в   бинарный  файл  подсказки  при
выключенном переносе слов.
     Директива !WRAP снова разрешает перенос слов.  По умолчанию
перенос слов включен.  Если вы отформатировали  текст  подсказки
так, как  вы  хотите,  то  перед  тем  как  запустить  MAKEHELP,
используйте директиву !NOWRAP.

     !SCROLLING
     ──────────────────────────────────────────────────────────-

     Эта директива просто устанавливает флаг ( в заголовке файла
подсказки), который указывает на то, что текст был оптимизирован
для ScrollingHelpWindow.  Процедуры  в  OPHELP  могут обнаружить
этот флаг и использовать соответствующий объект для того,  чтобы
показать подсказку.  Файл  подсказки  по  умолчанию работает без
прокрутки. Выходной файл,  создаваемый MAKEHELP,  будет  тем  же
самым (за    исключением    флага),    а    PagedHelpWindow    и
ScrollingHelpWindow могут читать файлы любого вида.

     !TOPIC Номер [Имя]
     ──────────────────────────────────────────────────────────-

     Каждый пункт   подсказки   должен  начинаться  с  директивы
!TOPIC. Обычно пункты подсказки выводятся в  восходящем  порядке
номеров, начиная с номера 1. Пропуск большого количества номеров
пунктов влечет  за  собой  затраты  пространства  как  в   файле
подсказки, так  и  в  памяти.  (Объем  пропущенного пространства
значительно сокращается в системе  Object  Professional.)  Номер
пункта 0 зарезервирован системой подсказки.
     Директива !TOPIC может также  специфицировать  имя  пункта,
которое начинается  с  первого непустого символа,  следующего за
номером пункта.  Имя  может  содержать  пробелы  и  будет  затем
появляться на  экране  точно  так  же,  как  было введено в этой
директиве. (Имя пункта обычно выводится как заглавие окна помощи
и является точкой входа в индекс пунктов.)
     Общий объем  имен  в  файле  подсказки  ограничен   до   64
килобайтов. Имена упаковываются один за другим в файл,  поглощая
длину строки плюс байт,  эта длина записана.  MAKEHELP следит за
тем, чтобы не превысить ограничение в 64 килобайта.
     Строки (даже пустые), следующие сразу за директивой !TOPIC,
начинают текст подсказки этого пункта,  который протягивается до
следующей директивы !TOPIC или до конца текстового файла.
     Каждый файл  подсказки  должен  иметь  по крайней мере один
пункт и соответственно директиву !TOPIC.

     Пример

           !TOPIC 1 Первый раздел подсказки
           !TOPIC 22

     Пункт 1  имеет  имя,  которое  может появиться как заглавие
окна подсказки при выводе этого  пункта.  Верхняя  граница  окна
подсказки для  пункта  22  всегда будет оставаться пустой и этот
пункт не будет присутствовать в главном индексе подсказки.

     !INDEX Индексный_Номер
     !NOINDEX
     ──────────────────────────────────────────────────────────-

     Эта директива  управляет  появлением  частного   пункта   в
главном индексе пунктов и если да, то где именно внутри индекса.
Директивы !INDEX  и  !NOINDEX  при  использовании  должны   быть
введены на  строке,  которая  следует  сразу  же  за  директивой
!TOPIC. Если этих директив нет для данного пункта,  то  MAKEHELP
проиндексирует этот пункт и отсортирует его в алфавитном порядке
в главном индексе.
     Любое имя пункта может быть исключено из главного индекса с
помощью директивы !NOINDEX.
     Изменить порядок  расположения  пунктов  в  главном индексе
можно с  помощью  директивы   !INDEX   и   следующего   за   ней
Индексного_Номера. Пункты  с  более  низкими индексными номерами
будут выводиться в начале главного индекса пунктов,  а с высшими
в конце  индекса,  не  обращая  внимания  на  обычный алфавитный
порядок. Пункты  в  главном  индексе  сортируются  в   следующем
порядке:

       1.Пункты с   Индексными_Номерами  <  $7777  в  восходящем
                числовом порядке
       2.Пункты без  директив  !INDEX  в  восходящем  алфавитном
                порядке
       3.Пункты с   Индексными_Номерами  >  $7777  в  восходящем
                числовом порядке

     Как можно заметить MAKEHELP кладет каждому пункту индексный
номер $7777 (30583 в десятичном виде) по умолчанию,  а директива
!INDEX переписывает  эти  значения.  Когда  MAKEHELP   сортирует
пункты для индекса подсказки,  то использует индексный номер как
первичный ключ, а алфавитные имена пунктов как вторичный ключ.
     Не определяйте  индексный  номер  $FFFF (65535 в десятичном
виде), так как MAKEHELP использует это особое значение для того,
чтобы отменить индексирование пункта.

     Примеры

             !TOPIC 1 Помощь по Подсказке
             !INDEX 1
             ...
             !TOPIC 2 Самый Второстепенный Подпункт
             !NOINDEX
             ...
             !TOPIC 3 Алфавитный Подход
             ...
             !TOPIC 4 Заключительное Слово
             !INDEX 32000
             ...


     Мы хотим,  чтобы пункт "Помощь по  Подсказке"  был  выведен
первым  в  индексе  пунктов,  поэтому  за директивой !TOPIC идет
директива !INDEX, определяя пункт под номером 1.
     Пункт 2  описывает самый второстепенный подпункт,  которому
совсем не следует появляться в  индексе,  что  мы  и  сделали  с
помощью директивы !NOINDEX.
     Пункт 3  должен  присутствовать  в  индексе   подсказки   в
нормальном алфавитном   порядке,   поэтому  не  требует  никаких
индексный директив.
     Пункт 4  должен быть последним пунктом в индексе подсказки,
поэтому мы дали ему большой индексный номер.

     !LINE
     ──────────────────────────────────────────────────────────-

     Эта директива  заставляет MAKEHELP закончить текущую строку
текста, вставив   разделитель   строк.    Так    как    MAKEHELP
автоматически заполняет  текст  и  делает  перенос  слов в вашем
изначальном файле   подсказки,   то   разделители   строк    при
окончательном появлении подсказки на экране не обязательно будут
такими же как и  в  изначальном  текстовом  файле  (если  только
перенос не  выключен).  Команда !LINE позволяет вам осуществлять
соответствующее управление  при  необходимости.  MAKEHELP  также
вставляет разделители   строк  всегда,  когда  достигает  пустой
строки или строки,  которая начинается с одного  или  нескольких
пробелов.

     !PAGE
     ──────────────────────────────────────────────────────────-

     Эта директива   заставляет   MAKEHELP   закончить   текущую
страницу текста,   вставив  разделитель  строк.  Обычно  система
OPHELP расставляет страницы в  тексте  подсказки  только  тогда,
когда  текст  выводится  на  экран.  Для того,  чтобы этот текст
выглядел лучше,  вы можете сами расставить разделители страниц в
вашем  файле  подсказки и тем самым заставить MAKEHELP закончить
текущую страницу в том  месте,  где  вы  поставили  разделитель.
Однако   объект   ScrollingHelpWindow  не  отличает  разделители
страниц от разделителей строк.

     !INCLUDE Имя_Включаемого_Файла
     ──────────────────────────────────────────────────────────-

     С того места, где поставлена эта директива в нормальный ход
текста подсказки   будет    считываться    определенный    файл.
Возможность подключения   файлов   позволяет   создавать   более
объемистые системы  подсказки  без  использования   виртуального
текстового редактора.
     MAKEHELP позволяет  включать  только  один  уровень   таких
файлов, без  вложений,  то  есть  включаемые файлы не могут сами
содержать в себе и использовать директиву !INCLUDE.  Вложенность
может быть легко увеличена изменением константы (MaxIncludeNest)
в исходном тексте программы MAKEHELP.PAS.

     Пример

           !WIDTH 50
           !NOWRAP
           !INCLUDE HELP.TX1
           !INCLUDE HELP.TX2

     Эти два  файла  дополняют  главный  файл с текстом какой-то
системы подсказки.  Все пункты содержатся  в  двух  подключаемых
файлах HELP.TX1 и HELP.TX2.

     !BIAS Величина_Смещения
     ──────────────────────────────────────────────────────────-

     Величина_Смещения является     целочисленным     значением,
заключенным между -65000 и +65000. Все ссылки на номера пунктов,
следующие за  этой  директивой,  будут  смещены   на   указанную
величину. Эта   директива   полезна  при  составлении  различных
независимых файлов подсказки в один большой файл (как например в
POPHELP).

     Пример

           !BIAS 500

     Добавляет 500  ко  всем номерам пунктов в тексте,,  которые
следуют за этой директивой.  Обратите внимание на  то,  что  как
перекрестные ссылки  на  пункты  так  и сами определения пунктов
перенастраиваются после этой директивы.
     Вы можете  ввести  комментарии  в  текстовый  файл - они не
появляются на   экране   при   выводе   подсказки.   Комментарий
начинается с точки с запятой в первой позиции любой строки.

          ;ЛЮБОЙ ТЕКСТ ПОСЛЕ ТОЧКИ С ЗАПЯТОЙ ИГНОРИРУЕТСЯ

     Управляющие Символы Файла Подсказки
     ──────────────────────────────────────────────────────────-

     Особые управляющие символы  позволяют  разнообразить  вывод
файла подсказки  на  экран.  С  их  помощью  вы можете добавлять
специальные видео атрибуты или  определять  перекрестную  ссылку
перехода к пунктам другой подсказки.
     Сначала мы опишем символы,  которые управляют особыми видео
атрибутами. Вот три из них:

     ^A включает специальный атрибут A
        ColorSet.FlexAHelpColor, FlexAHelpMono

     ^B включает специальный атрибут B
        ColorSet.FlexBHelpColor, FlexBHelpMono

     ^C включает специальный атрибут C
        ColorSet.FlexCHelpColor, FlexCHelpMono

     При построении  окон  подсказки  специальные  поля   данных
собираются по  переменным  ColorSet  для того,  чтобы можно было
использовать эти особые атрибуты.
     Поместим где-нибудь  в тексте подсказки управляющие символы
(но только не внутри директив,  конечно же). Сами эти символы не
будут выведены  на  экране  подсказки и не будут влиять на длину
строк при переносе слов.  Управляющие символы  будут  заставлять
выводить последующий   за   ними   текст   определенным  цветом.
Следующее включение  этого   символа   отключит   данный   цвет,
возвращая активный   цвет,   который   был   включен  предыдущим
управляющим символом. Использование этих переключений может быть
вложенным, но  максимум до 4-рех уровней.  При этом логика такая
же как и в процедуре OPCRT FlexWrite.
     Для того,   чтобы  ввести  управляющие  символы,  используя
редактор системы Turbo Pascal,  сначала  надо  нажать  сочетание
клавиш  <Ctrl+P>,  а  затем,  удерживая клавишу <Ctrl>,  выбрать
нужный символ. Например, для того, чтобы ввести ^A в текст, надо
нажать сочетание клавиш <Ctrl+P><Ctrl+A>.
     Два дополнительных   управляющих    символа    активизируют
возможность перекрестных ссылок системы подсказки.  Перекрестная
ссылка - это переходный текст, который указывает на другой пункт
внутри системы  подсказки.  Пока  подсказка находится на экране,
пользователь может  с   помощью   клавиш   перемещения   курсора
передвигать высвеченную   полосу   (для   PagedHelpWindow)   или
аппаратный курсор  (для  ScrollingHelpWindow)  по   перекрестным
ссылкам. Затем  надо  нажать  клавишу  <Enter>  для того,  чтобы
выбрать сопутствующий пункт и просмотреть  информацию  по  этому
пункту и  многим другим,  относящимся к данной теме пунктам.  По
умолчанию любой  пункт  подсказки   может   определять   до   50
перекрестных ссылок.
     Вы можете  использовать  возможность установки перекрестных
ссылок для достижения следующих  двух  эффектов.  Первый  -  это
создание локальных индексов: целый пункт подсказки может быть на
самом деле списком каких-либо других имен пунктов. В этом случае
вы  могли  бы  получить  иерархические  индексы,  причем главный
индекс показывал бы лишь самые общие  темы,  а  каждый  из  этих
пунктов  содержал  бы  локальный  индекс,  указывающий  на более
детальную информацию.  Второй эффект  -  это  так  называемый  в
народе "гипертекст"
     В этом случае текст в одном пункте используется как связное
звено в  относящиеся  к   нему   пункты,   позволяя   при   этом
пользователю проходить    через    весь    текст   подсказки   в
само-определенной манере.   ENTRY.TXT    демонстрирует    эффект
"гипертекста". Кроме  того  база  данных  с  подсказкой в пакете
Object Professional использует тот же прием локальных индексов в
процедуре POPHELP.
     Управляющие символы внутри текста подсказки должны  поэтому
давать два   сигнала   системе  OPHELP.  Во-первых,  они  должны
указывать, что пункт подсказки будет активизирован, когда данная
перекрестная ссылка  выбрана.  Во-вторых,  они  должны  замечать
протяженность выделенного пути текста.  Для этой  цели  MAKEHELP
использует следующую схему:

     ^Dnnnn^Etext^E

     Управляющий символ ^D предшествует ссылочному номеру пункта
"nnnn", который выражается  десятичными  цифрами.  Номер  пункта
заканчивается с  ^E,  за  которым  непосредственно следует текст
перехода, который надо высветить.  Второй символ ^E  заканчивает
выделенный текст.  Обратите внимание на то, что символ ^E должен
быть сбалансирован,  в то время как символ ^D стоит в  одиночку.
Далее приведен пример двух перекрестных ссылок:

     ^D10^EКомпиляцию^E текста подсказки легко
           использовать^D5^EMAKEHELP^E.

     В настоящем  тексте   подсказки   символы,   показанные   с
крышечкой  будут  в  действительности  конечно  же  управляющими
символами. Если пользователь переместит  высвеченную  полосу  на
слово MAKEHELP  и  нажмет  клавишу  <Enter>,  то  появится пункт
подсказки номер 5.
     Текст, помеченный    символом   ^E,   выводится   с   двумя
атрибутами. Когда     выбрана     перекрестная     ссылка     (в
PagedHelpWindow), текст       появляется       с       атрибутом
ColorSet.SelXrefColor (или  SetXrefMono).   Когда   перекрестная
ссылка не     выбрана,    текст    появляется    с    атрибутами
ColorSet.UnselXferColor (или UnselXrefMono).
     Ноль имеет  особое  значение  при  использовании как номера
пункта в перекрестной ссылке.  После  выбора  этой  перекрестной
ссылки, вместо  того,  чтобы получить новый пункт,  пользователь
получает главный индекс пунктов (а окно подсказки  переключается
в режим   выбора).   Окно  подсказки  делает  тоже  самое,  если
пользователь нажимает клавишу <F1>,  но использование для  этого
особой перекрестной  ссылки позволяет пользователю более простым
способом попасть в главный индекс.
     Управляющий символ  ^F предлагает путь внедрения конкретных
буквенных символов в  текст  подсказки,  которые  иначе  нелегко
описать:

     ^Fnnnn

     "nnnn" представляет  собой любую последовательность из цифр
(0-9),  которые определяют  ASCII  код  символа.  Однако  нельзя
использовать символ ^F для того,  чтобы заставить систему OPHELP
выдавать экранные образы  символов  ^A..^F,  ^L  и  ^M.  Система
OPHELP будет   все  равно  интерпретировать  их  обычным  путем.
Вероятно наиболее значимый путь использования параметром символа
^F - это определить строку

     ^F26

     которая будет  выдавать  символ  ^Z.  Символ  ^Z  закрывает
текстовые файлы так, что уже нельзя вставить буквенные символы в
файл подсказки.  Символ  ^Z  выдает  символ  стрелка  вправо при
выводе на экран,  но впрочем,  иногда приятно иметь его в тексте
подсказки.

     Одно заключительное замечание
     ──────────────────────────────────────────────────────────-

     Вы можете  использовать  символы  псевдографики (или другие
ASCII символы после 128 кода) в вашем файле  подсказки.  Система
OPHELP будет выводить их в буквенном виде. Большинство текстовых
редакторов (включая   Turbo   Pascal)  позволяет  вводить  такие
символы, удерживая клавишу <Alt>, набирать ASCII код на цифровой
части клавиатуры, а затем отпускать клавишу <Alt>.

     Запуск программы MAKEHELP
     ──────────────────────────────────────────────────────────-

     Программа MAKEHELP.EXE является  управляемой  из  командной
строки утилитой,   которая   читает   созданный   вами   файл  в
соответствии с только что  описанными  правилами,  а  записывает
бинарный файл   подсказки   для   того,  чтобы  его  можно  было
использовать в    программе.    Вызов     программы     MAKEHELP
осуществляется из командной строки ДОСа следующим образом:

  MAKEHELP [Параметры] Текст_Файл_Подсказки [Бин_Файл_Подсказки]

     MAKEHELP читает    из    текстового    файла    с    именем
Текст_Файл_Подсказки и    создает    новый     бинарный     файл
Бин_Файл_Подсказки. При  этом  для текстового файла по умолчанию
применяется расширение  .TXT.  Если  бинарный  файл  не  указан,
программа MAKEHELP  использует  то  же  имя,  что и у текстового
файла, но добавляет к нему расширение .HLP.  Программа  MAKEHELP
переписывает любые существующие бинарные файлы с таким же именем
без предупреждения.  Входной  и  выходной  файлы  должны   иметь
различные имена. Например:

     MAKEHELP DEMO.TXT DEMO.HLP
     MAKEHELP DEMO

     Эти две команды выполняют одну и ту же операцию.

     Программа MAKEHELP поддерживает следующие параметры:

     /L запись списка перекрестных ссылок пункта в файл имя.LST

     /Q не выводит предупреждения (молчаливый режим)

     /S сортировка списка перекрестных ссылок в индексном порядке

     Если ваш  файл  подсказки  имеет   множество   перекрестных
ссылок, то параметр /L может оказаться полезным.  Он покажет все
связи между пунктами.  Приведем  часть  примера,  созданного  из
ENTRY.TXT.

                 Topic Cross-Reference
                 Topic    Index    Topic Name

                     1  <alpha>    Name field
                     2  <alpha>    Address field
                                        to:     6
                     3  <alpha>    City field
                     4  <alpha>    State field
                     5  <alpha>    Zip code field
                     6  <alpha>    Phones field
                                        to:     16    17
                                      from:      2    15    24

     Пункты расположены  в  числовом  порядке.   Колонка   Index
показывает как   главный   индекс  пунктов  будет  упорядочивать
пункты: по  алфавиту  (alpha),  по  числам  (показывает  позиция
Index) или  вообще  без порядка (пусто в этой колонке).  Колонка
Topic Name показывает  присвоенное  пункту  имя  или  <no  topic
name>, если  у  пункта нет имени.  Если пункт имеет перекрестные
ссылки, как номер  2,  в  списке  показываются  номера  пунктов,
которые связаны  с  этим  пунктом.  Если  другие пункты содержат
перекрестные ссылки на этот пункт, как номер 6, то строка "from"
указывает пункты, которые ссылаются на этот пункт.
     Параметр /S вместе с параметром /L выдает такой же  список,
отсортированный в  таком  порядке,  в  котором  будет появляться
главный индекс пунктов.
     Параметр /Q   отменяет  вывод  сообщений  MAKEHELP  (но  не
ошибок).

     Программа MAKEHELP производит только два вида сообщений:

     Перекрестные Ссылки Между Разделителями Строк
     ──────────────────────────────────────────────────────────-
     Когда текст,  заключенный  между  символами  ^E,  находится
между несколькими строками, то можно его разбить на две страницы
(только  при  выводе PagedHelpWindow).  Текст на второй странице
будет нормально выведен, но система OPHELP не будет выбирать там
соответствующие  пункты.  Это предупреждение можно игнорировать,
так как
     а) маловероятно, что разбитая строка будет с двух сторон от
        разделителя страниц и
     б) даже если так, то проблему легко устранить.

     Перекрестная ссылка на себя
     ──────────────────────────────────────────────────────────-
     Номер перекрестной ссылки определяет тот же пункт, где была
обнаружена эта  перекрестная ссылка.  При этом не будет никакого
побочного эффекта,  но  это  возможно  сконфузит   пользователя.
Обратите внимание,   что   программа  MAKEHELP  не  обнаруживает
непрямые зацикливания перекрестных ссылок,  то есть  такие  вещи
как А ссылается на пункт Б, который ссылается на пункт А.
     При запуске программы MAKEHELP происходит два прохода через
входной текст:  один  для  подсчета  различных единиц подсказки,
таких как номера пунктов,  а второй для форматирования текста  и
записи в сжатом виде.

     Если программа  MAKEHELP  находит  фатальные  ошибки,   она
останавливается и выдает тип ошибки и номер строки внутри вашего
текстового файла  с  подсказкой.  MAKEHELP   выдает   ошибки   в
следующих ситуациях:

     Недопустимый параметр командной строки
     ──────────────────────────────────────────────────────────-
     Любой параметр, определенный вместе с программой MAKEHELP в
командной  строке  ДОСа,  кроме  параметров /L,  /Q и /S,  будет
приводить к этому виду ошибки.
     
     Слишком много имен файлов определено
     ──────────────────────────────────────────────────────────-
     В командной  строке  ДОСа  вместе  с  программой   MAKEHELP
определено больше чем два имени файла как входные параметры.
     
     Имена входного и выходного файлов должны быть различными
     ──────────────────────────────────────────────────────────-
     Нельзя записывать   выходную   информацию  после  обработки
программой MAKEHELP  во  входной  файл.  (Вы   можете   обмануть
проверку на эту ошибку, если попытаетесь, но мы не советуем!)
     
     Проблемы ввода/вывода на диск
     ──────────────────────────────────────────────────────────-
     Убедитесь, что  дисковод  готов к работе и есть достаточное
количество места на диске для хранения выходного файла.
     
     Массив имен пунктов достиг 64К
     ──────────────────────────────────────────────────────────-
     Используйте более  короткие  имена  пунктов  или  уменьшите
число пунктов в файле подсказки.
     
     Недостаточно памяти
     ──────────────────────────────────────────────────────────-
     Программа MAKEHELP  не имеет достаточного количества памяти
для хранения временных результатов.  Освободите память,  выкинув
резидентные программы, или сократите размер файла подсказки.
     
     Массив индекса файла достиг 64К
     ──────────────────────────────────────────────────────────-
     Сократите наибольший   номер   пункта  в  файле  подсказки.
(Каждый элемент в массиве индексов файла использует 6 байтов.)
     
     Число перекрестных ссылок достигло 16380
     ──────────────────────────────────────────────────────────-
     Перекрестных ссылок больше,  чем можно обработать в  списке
по параметру  /L.  Не  указывайте  параметр  /L и файл подсказки
будет успешно преобразован.
     
     Слишком много вложенных файлов
     ──────────────────────────────────────────────────────────-
     Подключаемый файл содержит директиву !INCLUDE внутри  себя.
Устраните вложенность  или  увеличьте константу MaxIncludeNest и
перезапустите программу MAKEHELP.
     
     Не указан ни один пункт подсказки
     ──────────────────────────────────────────────────────────-
     По-видимому, во входном файле подсказки не указано ни одной
директивы пункта !TOPIC.
     
     Недопустимый номер пункта по перекрестной ссылке
     ──────────────────────────────────────────────────────────-
     Номер, следующий за символом ^D, не допустим.
     
     Недопустимый буквенный символ
     ──────────────────────────────────────────────────────────-
     Число, следующее за символом ^F, не допустимо.
     
     Недопустимая ширина
     Недопустимый элемент
     Недопустимый индекс
     ──────────────────────────────────────────────────────────-
     Число, следующее   за  директивой  подсказки,  не  является
допустимым.
     
     Повторение номера пункта подсказки
     ──────────────────────────────────────────────────────────-
     Один и тот же индекс был использован для более  чем  одного
пункта подсказки.
     
     Оператор WIDTH   должен   предшествовать   первому   пункту
     подсказки
     ──────────────────────────────────────────────────────────-
     Переставьте директиву !WIDTH в начало файла подсказки.
     
     Оператор INDEX должен следовать за оператором TOPIC
     ──────────────────────────────────────────────────────────-
     Каждая директива !INDEX или !NOINDEX  должна  следовать  за
директивой !TOPIC, к которой она относится.
     
     Неопознанная директива
     ──────────────────────────────────────────────────────────-
     Позиция 1 файла подсказки содержит восклицательный знак, но
текст, который непосредственно следует за ним,  не  представляет
осмысленной допустимой директивы.
     
     
     После успешного завершения  процесса  с  файлом  подсказки,
программа MAKEHELP выдает некоторую статистику. Приведем пример,
выдаваемый входным файлом ENTRY.TXT:
     
     Summary ..............................
     
       525 total lines in help file
        24 topic slots used                  HighestTopic
        24 indexed topics                    PickTopics
        31 cross-references
        48 bytes in topic name index         SizeOf(Topic Name Index)
       398 bytes in packed topic name table  SizeOfNames
        48 bytes in sorted topic map         SizeOf(Master Topic Index)
       144 bytes in help index               SizeOf(Disk Index)
      3682 bytes in largest topic (topic 15) BiggestTopic
        62 bytes in longest line of help
         5 most cross-refs in a topic (topic 13)
     17562 uncompressed help bytes
     12537 compressed help bytes
      0.71 compression factor

     Имена справа  в  списке  обсуждаются в разделе "Организация
Файла Подсказки".      Большинство     из     этих     элементов
само-объясняющиеся.  Несколько замечаний можно сказать о  "Topic
slots" - это тоже самое, что и наибольший номер пункта. Обратите
внимание на  то,  что  программа  подсчитывает  неиспользованные
номера пунктов.  "Index topics" подсчитывает число поименованных
пунктов, для которых не была специфицирована директива !NOINDEX.
Размер  "рacked  topic  name  table"  -  это  длина всех строк с
именами пунктов,  включая байт  длины  для  каждого.  Наибольший
размер  пункта  дается  в  несжатых байтах и включает пробел для
"decompression overlap" (смотрите ниже). Длина наибольшей строки
(после переноса слов) может помочь вам определить,  какой ширины
должно быть окно вашей подсказки.  Число "most  cross-references
in  a topic" должно быть меньше чем константа MaxXrefsPerSection
в системе OPHELP,  иначе  некоторые  перекрестные  ссылки  будут
игнорированы.  Байты  сжатой подсказки показывают как много байт
файла  подсказки  в  действительности  использовано  для  текста
подсказки без индексирования и информации по именам пунктов.
                                                                
     
     Встраивание Подсказки в Программу
     ──────────────────────────────────────────────────────────-
     
     Система OPHELP может непосредственно использовать  бинарный
файл, сделанный  программой  MAKEHELP  без каких-либо дальнейших
изменений. Однако,  если файл подсказки  относительно  маленький
(определенно меньше  чем 64К),  вы можете подключить его прямо в
прикладную программу и не  нужны  будут  никакие  дополнительные
файлы.
     Это можно сделать с помощью программы  утилиты  BINOBJ.EXE,
которую фирма   Borland   поставляет  с  пакетом  Turbo  Pascal.
Программа BINOBJ преобразует бинарный файл подсказки в объектный
модуль, который может быть подключен внутрь вашей программы.
     Давайте рассмотрим пример для того, чтобы показать, как это
работает. Предположим, что у вас есть текстовый файл подсказки с
именем MYHELP.TXT.  Первый  шаг  -  надо   запустить   программу
MAKEHELP для того, чтобы создать бинарный файл подсказки:
     
     MAKEHELP MYHELP.TXT MYHELP.HLP
     
     Затем запускаем  программу  BINOBJ для того,  чтобы создать
объектный модуль:
     
     BINOBJ MYHELP.HLP MYHELP.OBJ MYHELP
     
     Третий параметр программы BINOBJ  определяет  имя  внешнего
идентификатора, с  помощью которого программа может ссылаться на
содержимое объектного файла.
     Теперь внутри  вашей  прикладной  программы  надо  вставить
следующую строку исходного текста:
     
     ($L MYHELP.OBJ)
     procedure MyHelp; external;
     
     Директива $L  говорит  компилятору,  что  надо подсоединить
файл MYHELP.OBJ.  Фиктивная процедура MyHelp позволяет программе
ссылается на содержимое объектного файла.
     В итоге,   для   того,   чтобы   инициализировать   систему
подсказки, вы  можете  вызвать  один  из  составителей  InitMem,
InitMemCustom или InitMemDeluxe. Например,
     
   if not PH.InitMem(X1, Y1, X2, Y2, @MyHelp, PickVertical) then
      (ошибка инициализации);
     
     Обозначение "@MyHelp"  передает адрес подсоединяемого файла
подсказки составителю,  который допускает,  что в данной позиции
стоит правильно отформатированные данные подсказки.
     Таким образом, использование метода подсоединения подсказки
как объектного   модуля  дает  такой  же  эффект,  как  если  бы
подсказка хранилась в файле на диске.
     
     Использование системы OPHELP с
     CommandWindows и CommandProcessors
     ──────────────────────────────────────────────────────────-
     
     Каждая производная  из  объекта  CommandWindow   (PickList,
DirList,  Memo, TextEditor, Menu и так далее) связана с объектом
CommandProcessor. Каждый      CommandProcessor      поддерживает
контекстно-зависимую привязку   подсказки.   Если   используется
привязка, то управляющая строка,  связанная с командой ccHelp из
CommandProcessor будет давать Process из CommandWindow для того,
чтобы вызвать  написанную   пользователем   процедуру,   которая
выводит контекстно-зависимую   подсказку.   Приемы   активизации
привязки описаны в главе OPCMD.
     Наилучшим действием,  которое  может предпринять написанная
пользователем процедура,  - это побудить систему OPHELP  вывести
пункт подсказки определенного содержания. Это очень естественно,
если вы  предпринимаете  некоторое  планирование   вперед.   При
использовании в   комбинации   с   системой   OPHELP  написанная
пользователем процедура принимает вид:
     
     ($F+)
     procedure MyGetHelpProc(UnitCode : Byte; IdPtr : Pointer;
                                              HelpIndex : Word);
     begin
       if HelpIndex <> 0 then begin
         MyHelpWindow.SetTopic(HelpIndex);
         MyHelpWindow.Process;
         MyHelpWindow.Erase;
       end;
     end;
     
     Эта простая процедура рассчитана на два фактора:
     первое, что    окно    подсказки    (MyHelpWindow)     было
инициализировано раньше в программе и
     второе, что  каждому  объекту   типа   окно   соответствует
промежуток уникальных  номеров  пунктов  подсказки,  для которых
файл подсказки содержит информацию.  Таким  образом,  HelpIndex,
по которому    идет    пользовательская    процедура,   является
достаточным  для  того,  чтобы  точно  определить  какой   пункт
подсказки надо выводить.
     Некоторые окна  и  типы   редакторов   -   Memo,   Browser,
LineEditor и  так  далее  -  будут  требовать  только один пункт
подсказки для описания.  Вы укажете этот  номер  пункта  вызовом
SetHelpIndex из CommandWindow или LineEditor.  Обратите внимание
на то, что каждая инстанция объекта может иметь уникальный пункт
подсказки при   желании.   Таким   образом,  различные  строчные
редакторы могут иметь различную вспомогательную  информацию  или
или довольствоваться  только  стандартным описанием редакционных
управляющих команд и клавиш.
     Другие типы окон - PickList,  Menu,  EntryScreen и другие -
требуют нескольких  пунктов  для   каждой   инстанции   объекта.
Например, Menu  может требовать пункт для каждого элемента меню.
Каждый из  этих  объектов  предлагает   путь   для   определения
уникальных номеров пунктов для каждого элемента по желанию.
     Если нужен уникальный пункт подсказки для каждого  элемента
из PickList,  то понадобятся дополнительные усилия для написания
процедуры привязки подсказки. Причина в том, что PickList кладет
номер пункта  равным номеру элемента,  который всегда изменяется
от 1 до номера элементов.  Если есть только один PickList, то вы
можете зарезервировать пункты подсказки, начиная с 1 для списка.
Если есть больше чем один,  вы должны пойти по  основной  схеме:
пункты PickListA  в  диапазоне PickABase+1..PickABase+NumberInA,
пункты PickListB в диапазоне PickBBase+1..PickBBase+NumberInB  и
так далее.  Этого  вполне достаточно,  но требует,  чтобы имелся
глобальный доступ  к  переменным  выбора  или  некоторым  другим
глобальным флагам.    Предположим,    что    это   есть,   тогда
процедура подсказки будет выглядеть так:
     
     
     ($F+)
     procedure MyGetHelpProc(UnitCode : Byte; IdPtr : Pointer;
                                              HelpIndex : Word);
     begin
       if HelpIndex <> 0 then begin
         if UnitCode = ucPick then begin
           {Требование на подсказку пришло от OPPICK}
           if IdPtr = @PickListA then
             inc(HelpIndex, PickABase)
           else if IdPtr = @PickListB then
             inc(HelpIndex, PickBBase);
           {иначе взять проходящий HelpIndex}
         end;
         MyHelpWindow.SetTopic(HelpIndex);
         MyHelpWindow.Process;
         MyHelpWindow.Erase;
       end;
     end;
     
     Запомните, что требование  подсказки  по  объекту  проходит
UnitCode, который  указывает из какого модуля пришло требование,
и IdPtr,  который вообще равен адресу инстанции объекта.  В  это
примере можно сдвинуть номер HelpIndex, сравнивая IdPtr с каждым
возможным PickList, который может потребовать подсказку.
     Конечно, существуют    другие    пути   для   сопоставления
контекстно-зависимой подсказки объектам программы,  но  они  все
основаны на прохождении по номерам пунктов в особой манере.

     1. AbstractHelpWindow: Доступ к Файлу Подсказки
     ───────────────────────────────────────────────────────────

     AbstractHelpWindow -  это некоторый абстрактный объект:  вы
не можете  определить  переменную  такого   типа.   Однако,   он
обеспечивает  большое  количество функциональных свойств для его
"детей"  -  функций   PagedHelpWindow   и   ScrollingHelpWindow.
Фактически,  эти  два  наследника  имеют  только несколько своих
собственных  не  внутренних  методов,  большинство  из   которых
определяется  их  потребностями.  Как результат,  многие методы,
которые вы будете  использовать  для  системы  подсказки,  будут
определены  в этом разделе,  то есть нам не надо будет повторять
их для каждого  типа  окна  подсказки.  Мы  отложим  законченные
примеры   программ  для  рассмотрения  в  последующих  разделах;
частичные примеры показаны для каждого метода,  применительно  к
каждому рассматриваемому объекту, исключая установленные.
     Рассматривая функцию AbstractHelpWindow,  обратите внимание
на  то,  что  она  происходит  из объекта PickList.  То есть она
наследует возможности высвечивания и выбора пунктов  из главного
индекса.  То, что AbstractHelpWindow добавляет - это возможность
доступа к файлу подсказки  и  загрузка  определенного  пункта  в
буфер памяти.    Функции   PagedHelpWindow   ScrollingHelpWindow
добавляют затем код для высвечивания информации в этом  буфере и
доступ команд  пользователя  для  пролистывания  и выбора других
пунктов по косвенным ссылкам.
     Снова заметим,    что    типы   окна   подсказки   являются
"двух-режимными" окнами.  Если вы вызываете  метод  Process  для
заново сконструированного окна подсказки, это будет работать так
же как PickList для высвечивания пунктов  из  главного  индекса;
такой  способ  называется режимом "Выбора".  Если вы используете
SetTopic для определения доступного номера пункта перед  вызовом
Process,  будет высвечен текст подсказки; такой режим называется
режимом подсказки.  Если пользователь выполняет команду  ccIndex
(помечая  клавишей  <F1> по умолчанию) в режиме подсказки,  окно
автоматически переключится обратно к режиму Выбора.

     Организация Файла Подсказки
     ───────────────────────────────────────────────────────────

     Для вас не важно знать,  как организован файл подсказки, но
это  может  быть  полезным  для  оптимизации  и  понимания вашей
системы подсказки.  Как мы уже замечали до этого, для всех типов
окон подсказки  OPHELP используется один и тот же  формат файла.
AbstractHelpWindow поддерживает методы доступа к файлу, чтения и
сжатия и раскрытия текста подсказки в буфере.
     Файл подсказки,  созданный  с   помощью   MAKEHELP,   можно
разделить на следующие разделы:

     Раздел                    Размер
     ───────────────────────────────────────────────────────────
     HelpHeader                Sizeof(HelpHeader)
     Topic Name Index          HighestTopic*SizeOf(Word)
     Topic Name Buffer         SizeOfNames
     Master Topic Index        PickTopics*SizeOf(Word)
     Disk Index                HighestTopic*SizeOf(HelpIndexRec)
     Help Topics               varies

     Файл начинается с заголовка фиксированной длины (34 байта).
Этот заголовок включает в себя строку ('OPH1'), используемую для
опознавания действительного файла подсказки,  а  также  содержит
различную информацию о числе пунктов и длине следующих разделов.
Важным полем является HighestTopic,  который содержит наибольший
номер пункта, найденного в исходном тексте файла подсказки. (Для
получения более   подробной   информации   обратитесь   к   типу
HelpHeader ниже.) При открытии  нового  файла  подсказки  OPHELP
считывает заголовок  для  распознавания  файла  и для начального
размещения в памяти структур объектов файла.
     Следующий  раздел - Topic Name Index (Индекс Имени Пункта),
который является массивом Слов,  изменяющихся от 1 до наивысшего
номера пункта.  Каждый элемент в этом массиве говорит OPHELP где
искать строку имени пункта в следующим за ним разделе Topic Name
Buffer   (Буфер  Имени  Пункта).  Для  других  пунктов,  которые
не используются или не имеют имени, в разделе Topic  Name  Index
устанавливается  $FFFF;  иначе  в  Буфере  Имени устанавливается
смещение имени (начинающееся с 0).
     Имена пунктов   хранятся   в  Буфере  Имени  в  стандартном
строковом формате Turbo Pascal -  байт  длины  располагается  за
незашифрованной,    несжатой   строкой.   Строки   упаковываются
немедленно одна за другой таким  образом,  чтобы  в  массиве  не
осталось  промежутков.  Этот массив использует байты SizeOfNames
(Размер Имени), где SizeOfName - другое поле, которое хранится в
заголовке   подсказки   и   сообщено   MAKEHELP.  OPHELP  всегда
осуществляет доступ к Буферу  Имени  непосредственно,  используя
Индекс  Имени  Пункта.  Эти  имена  используются для обеспечения
необязательных заголовков  пунктов  в  окне  подсказки   и   для
выбора строки в списке главного индекса пунктов.
     Master Topic Index (Главный  Индекс  Пунктов)  представляет
собой  массив  Слов,  который  содержит список выбранных номеров
(1..PickTopic) для связывания  с  номером  пункта.  Этот  массив
отфильтровывает  неиспользуемые  и  неиндексированные  пункты  и
производит упорядочение по алфавиту и нумерации индекса пунктов.
     Раздел Disk Index (Индекс Диска) сообщает  OPHELP  в  каком
месте он  может найти текст для каждого пункта подсказки. Каждый
элемент в этом массиве является записью,  длинной  в  6  байтов,
которая устанавливает поиск смещения LongInt (Длинное Целое) для
начала пункта и поиск Слова,  которое  определяет  число  сжатых
байт текста.  Поиск  смещения  для не существующего  пункта дает
значение $FFFFFFFF.
     Из организации файла вы можете заметить, что промежуток в 8
байтов отводится для каждого  неиспользуемого  номера  пункта  в
интервале  1..HieghestTopic.  Этого не достаточно для волнения о
маленьких  промежутках  в  последовательности  номеров,  но  это
делает  показательным  то,  что  вы хотите избежать - три пункта
файла  подсказки  с  номерами  пунктов  1000,  5000   и   10000.
(Результатом было бы почти 80000 лишних байтов в файле).
     Следующий раздел  Disk Index (Индекс Диска) - это текст для
каждого пункта.  Данные  сжимаются  с  использованием  быстрого,
простого  метода  подобно  тому,  как  и в Borland's Word Wizard
Toolbox.  Коротко:  15 наиболее часто используемых  символов  во
всем  файле  подсказки заменяются на 4-х битовый код в интервале
0..14. Оставшиеся 246 символов кодируются 12 битами каждый: за 4
-х  битовым значением 15 следует 8-и битовый код самого символа.
Таблица кодирования хранится в заголовке файла  подсказки.  Этот
алгоритм результативен в 30%  от общего сжатия. Сжатие, конечно,
осуществляется MAKHELP.  OPHELP разжимает  каждый  пункт  тогда,
когда это требуется.
     OPHELP размещает  структуры в буфере памяти.  Это позволяет
осуществлять доступ к заголовку  подсказки  так  часто,  что  он
немедленно  копирует  эту маленькую запись в пространство памяти
по мере  того,  как  файл  подсказки  будет  открыт.  Если  окно
подсказки   используется   в   режиме  выбора,  OPHELP  временно
размещает буфера для поддержки  Индекса  Имени  Пунктов,  Буфера
Имени  Пункта  и  Главного  Индекса Пунктов.  Если не существует
достаточного пространства памяти под эти структуры, вы не можете
использовать  режим  выбора.  Эти  структуры  должны храниться в
памяти для PickList  для  того,  чтобы  осуществлять  адекватные
преобразования.
     Если функция   hwStaticNameBuffer   не   доступна,   OPHELP
размещает и инициализирует эти три буфера по мере того, как файл
подсказки  будет  открыт и оставляет их размещенными до тех пор,
пока окно не  будет  уничтожено.  Эта  функция  сохраняет  время
чтения  этих  структур  при требовании главного индекса пунктов.
Это особенно хорошая идея для  TSR,  который  использует  OPHELP
(например  POPHELP);  так  как  пространство  памяти  может быть
зарезервировано  где  угодно,  почему  бы   не   сохранить   его
размещенным?
     OPHELP размещает  один  дополнительный блок памяти - сжатый
буфер, величина которого больше,  чем достаточно для  размещения
самого большого пункта в файле подсказки после его раскрытия. Он
считывает каждый сжатый пункт в вершину буфера,  затем разжимает
текст  в  нижней  части  буфера.  Разница  между  действительным
размером буфера и размером  самого  большого  пункта  называется
"перекрытием разжимания";  лишнее  пространство памяти сохраняет
текст  при  перезаписи  сжатого  текста  во  время   разжимания.
MAKEHELP  сообщает  действительный размер блока и в общем случае
BiggestTopic.
     Когда файл  подсказки  привязан  к  некоторому  применению,
OPHELP  размещает в пространстве только сжатый буфер.  Он просто
хранит указатели на другие разделы "файл", которые уже находятся
в памяти.  В  этом  случае,  функция hwStaticNameBuffer не имеет
действия.

     Стек Предыдущего Пункта
     ───────────────────────────────────────────────────────────

     Когда пользователи   понимают   преимущества   возможностей
перекрестных ссылок гипертекста,  часто они хотят  и  в  системе
подсказки  вернуться  назад к тому пункту,  который был до этого
высвечен.  AbstractHelpWindow  поддерживает   эту   возможность,
используя   структуру   данных,  называемую  Стеком  Предыдущего
Пункта.  Эта  структура  реализована  посредством  использования
объекта OPROOT StaticQueue, который согласно его названию хорошо
работает для определенных типов стеков.
     Когда вы вызываете конструктор окна подсказки, он размещает
StaticQueue  с  запасом  для   размещения   MaxPreviousTopic   -
константа,  которая по умолчанию равна 20.  Пространство памяти,
используемое   под   StaticQueue    является    различным    для
PagedHelpWindow   и   ScrollingHelpWindow,  поэтому  они  должны
хранить  различное  количество   информации   для   возврата   к
предыдущему пункту.
     Каждый раз,  когда  пользователь   выделяет   новый   пункт
подсказки,   статус  предыдущего  пункта  (номер  пункта,  номер
страницы или позиция  прокрутки,  текущая перекрестная связь или
позиция  курсора)  выносится  в  стек  предыдущего пункта.  Если
пользователь вводит команду ccPrevTopic  (по  умолчанию  нажимая
клавиши <AltF1>), самый последний пункт выталкивается из вершины
стека и окно подсказки обновляется для того,  чтобы показать эту
информацию.  Если  стек пуст,  команда ccPrevTopic игнорируется.
Если стек полон,  самый старый пункт вытесняется при поступлении
нового пункта.
     По умолчанию,  OPHELP  сохраняет  содержимое  стека  пункта
между одним и другим вызовом Process. Вы можете заставить OPHELP
очищать стек каждый раз  при  выходе  из  Process,  устанавливая
функцию hwClearStackAtExit.

     Поддержка Мыши
     ───────────────────────────────────────────────────────────

     Поддержка мыши   осуществляется   внутри   объектов    окна
подсказки; все, что вам надо - это активизировать их. Для этого,
добавим после  вызова  PH.InitCustom следующие строки в исходный
пример HelpExample:

     if MouseInstalled then begin
        with DefaultColorSet do
          SoftMouseCursor($0000,(ColorMono(MouseColor,MouseMono)
          shl 8)+$04);
        HelpCommands.cpOptionsOn(cpEnableMouse);
        PH.hwFrame.AddHotSpot(frTL, #4, DefaultColorSet);
        PH.setPrevTopicHotSpot(hsSpot, frTL);
     end;

     Эта программа  сначала  убеждается  в  том,  что  мышь была
инсталлирована.  Если да, то определяются характеристики курсора
мыши. Этот  шаг  по  умолчанию устанавливает типовое программное
обеспечение мыши,  но возможно вы захотите установить свой  цвет
для закрашивания,  используя параметр ColorSet. Вы всегда должны
использовать   программное   обеспечение   (а   не    аппаратное
обеспечение)  курсора  мыши  с  объектами  окна  подсказки.  Для
получения более  детальной  информации  об  определении  курсора
мыши, обратитесь к функции OPMOUSE.
     Вызов функции    HelpCommands.cpOptionsOn    инициализирует
командный процессор  окна  подсказки  для  поддержки  мыши.  Для
получения более подробной информации,  смотрите  функцию  OPCMD,
особенно, если вы используете фоновые программы.
     Наконец, эта программа добавляет и  активизирует специально
предназначенную горячую  точку  для  окна  подсказки.  В  данном
случае горячей точкой является символ  #4  (бриллиант),  который
находится в  левом  нижнем углу окна.  Горячая точка добавляется
функцией hwFrame,  поэтому она появляется  только  тогда,  когда
окно находится  в режиме подсказки.  Функция SetPrevTopicHotSpot
помечает эту горячую  точку для предыдущей команды  пункта  окна
подсказки. В  этом  случае,  метод Process окна подсказки знает,
вершину стека пункта,  в котором пользователь нажал  на  горячую
точку в левом нижнем углу окна.
     Мышь в окне подсказки также  работает  с  прокручивающимися
полосками.   В  нашем  примере  мы  уже  добавили   вертикальные
прокручивающиеся полоски, поэтому нам не надо добавлять их  тут.
Обычно,    Если   прокручивающаяся   полоска   была   добавлена,
минимальные (0) и максимальные (MaxLongInt) пределы пользователя
произвольны;  окно  подсказки  обновит  их  тогда,  когда узнает
больше о пункте  подсказки.  Функция  PagedHelpWindow  в  режиме
подсказки  поддерживает  вертикальные  прокручивающиеся полоски;
горизонтальная  прокрутка  ненужна.  Функция ScrollingHelpWindow
поддерживает    как    горизонтальные,    так   и   вертикальные
прокручивающиеся  полоски.  Скольжения  обеих   прокручивающихся
полосок  изменят вашу страницу или текущую информацию подсказки.
Если   возможно   использование   функций    ScrollingHelpWindow
hwMousePage, при нажатии на стрелки вверх/вниз, прокручивающаяся
вертикальная полоска выведет на экран новую  страницу подсказки;
иначе, подсказка будет прокручиваться строка за строкой.
     Вы можете  выбрать  ссылающиеся  друг  на   друга   пункты,
используя мышь  в  окне  подсказки  любого типа.  Первое нажатие
клавиши мыши на ссылку пункта переместит высвеченную полоску или
курсор в  позицию  мыши.  Повторное  нажатие  в  этом  же  месте
осуществит выбор пункта,  на который ссылается  исходный  пункт,
подобно нажатию клавиши <Enter>.
     Нажимая обе кнопки мыши,  вы переключите окно подсказки  из
режима подсказки  в  режим  выбора,  высвечивая  главный  индекс
пунктов.

     Специализированные Заголовки Окна
     ───────────────────────────────────────────────────────────

     Два специализированных  типа  заголовков  предназначены для
зрительного увеличения  окон  подсказки,  работающих  в   режиме
подсказки. (В   режиме   выбора   специализированные   заголовки
применимы для функции PickList, используемой как обычно).
     Первый новый  заголовок похож на заголовок функции PickList
"more  header"  ("добавочный  заголовок"),  но  он   показывает,
существует   ли   еще   текст   за  пределами  окна.  Это  можно
использовать вместо прокручивающейся полоски.  Добавим заголовок
"more  help header" ("добавочный заголовок подсказки") используя
следующий способ:

     procedure AddMoreHelpHeader(PromptStr: String80;
                                          Posn: HeaderPosType;
                                 UpStr,DnSTR,SepStr: String10;
                                    UpPos,DnPos,SepPos: Byte);
     
     {-Добавление специального   дополнительного  заголовка  для
                          обозначения дополнительной подсказки-}

     Вместо добавления  заголовка  к  главному   окну   (функция
wFrame),    процедура    AddMoreHelpHeader   добавляет   его   к
специальному окну режима подсказки - hwFrame.  вводная программа
HelpExample показывает, как это сделать:

     PH.AddMoreHelpHeader('  PgUp/PgDn for more  ', heBR,
                                  'PgUp', 'pgDn', '/', 2, 7, 6);

     Параметры здесь интерпретируются таким же образом, как и  в
функции AddMoreHeader в PickList.
     Второй новый заголовок - заголовок имени  пункта.  Если  вы
хотите, чтобы  имя  каждого  пункта  появлялось при высвечивании
этого пункта на экране, вы можете использовать данный заголовок.
Добавим заголовок имени пункта следующим способом:

     procedure AddTopicHeader(PadSize: Byte; MaxLen: Byte;
                                     Posn: HeaderPosType);
     
     {-Добавление заголовка для высвечивания имени пункта-}

     Параметр PadSize - число пробелов, окружающих  имя  пункта;
MaxLen -  наибольшая  допустимая  длина  (более  длинные   имена
усекаются); параметр   Posn   определяет   положение  рамки  для
заголовка. Снова,  пример  HelpExample   показывает,   как   это
сделать:

     PH.AddTopicHeader(1, 60, heTC);

     В этом случае, заголовок будет размещен по центру в верхней
строке окна, длина имени пункта будет ограничена 60-ю символами,
а слева и справа от него будут помещено по одному пробелу.

     Перемещение Привязки Пользователем
     ───────────────────────────────────────────────────────────

Окна подсказки  наследуют  возможности  пользователя  перемещать
привязку из  PickList.  Смотрите  там  обсуждение  для  фонового
режима.   Когда   он   применим   к  окну  подсказки,  процедура
перемещения должна определять текущий режим окна для того, чтобы
получить    правильную    информацию.    Для    этих   целей   в
AbstractHelpWindow определена функция InHelpMode:

     function InHelpMode : Boolean;
     {-Возвращает значение True (Истинно),  если окно показывает
                                 подсказку, а не список выбора-}

     Соответствующая программа перемещения может  быть  написана
следующим образом:

     {$F+}
     procedure MyMoveProc(P : PickListPtr);
     begin
       if AbstractHelpWindowPtr(P)^.inHelpMode then
         {-выполнить действия, соответствующие режиму подсказки-}
       else
         {-выполнить действия, соответствующие режиму выбора-}
     end;

     Заметим, что определение типа режима  требуется  для  того,
чтобы  сообщить  компилятору,  что  указатель ссылается на адрес
AbstractHelpWindow  вместо   адреса   PickList.   Дополнительная
установка   типа  может  быть  необходима  в  том  случае,  если
процедура  перемещения  ссылается  на  PageHelpWindow   или   на
ScrollingHelpWindow.

     Вложенная Функция Привязки
     ───────────────────────────────────────────────────────────

     Вложенная функция  привязки  является  программой,  которую
вызывает Process при обнаружении команды ccNested. По умолчанию,
команда ccNested  не  помечена  какой-либо  клавишей.  Вложенная
функция  должна  быть откомпилирована под управлением модели FAR
(с директивой компилятору {$F+}),  она должна быть  глобальна  и
иметь параметры, которые сравнимы со следующим образцом:

     procedure SetNestedFunc(NF : hwNestedFunc);
       {-Установить функцию на вызов вложенной команды xref-}

     Указатель при подходе к вложенной  функции  содержит  адрес
текущего окна   подсказки.  Если  вложенная  функция  возвращает
значение True  (Истинно),  Process  будет  завершен,   возвращая
управление вашей  программе.  Если вложенная функция не изменяет
значения хранящегося  кода  команды,  окончанием  команды  будет
ccNested. Если функция возвращает значение False (Ложь), Process
будет зацикливаться до получения дополнительных команд.
     Для чего нужна эта функция?  Говоря откровенно,  мы никогда
не использовали ее, кроме как для тестирования программ, но идея
состоит  в  следующем:  вложенная  функция  могла бы определить,
какая перекрестная ссылка будет высвечена  в  качестве  текущей.
Далее,   она  могла  бы  "выкинуть"  приглашение  для  получения
дальнейшей информации от пользователя. Оригинальное предложение,
которым обосновывалось это свойство,  было "умная форма":  текст
подсказки обеспечивал бы инструкции о том, как заполнить форму и
перекрестные  связи,  и  перекрестные  связи выступали бы в роли
окон для ввода данных.
     Для использования  преимуществ   вложенной   функции  будет
необходимо какое-либо наращивание знаний об объектах  окна. Если
вы реализуете  что-нибудь  "оригинальное"  с использованием этой
функции, нам было бы интересно услышать об этом.

     Константы
     ───────────────────────────────────────────────────────────

     hwStaticNameBuffer = $0001; {Предразмещение   и   хранение
                                         буферов имени постоянно}
     hwPickIndex        = $0002; {Возможна команда ccIndex}
     hwClearStackAtExit = $0004; {Очистить  стек   предыдущего
                                  пункта при выходе из подсказки}
     hwMousePage        = $0008; {Перемещение прокручивающейся
                                   полосы, прокрутка на страницу}
     hwAdjustScroll     = $0010; {Автоматическая установка пределов
                                        горизонтальной прокрутки}
     hwBlockMark        = $0020; {Возможно пометить блок}

     Это параметры,     которые     влияют     на      поведение
AbstractHelpWindow,   PagedhelpWindow   и   Scrollinghelpwindow.
Функция hwStaticnameBuffer принуждают  каждый  конструктор  окна
подсказки   размещать  пространство  памяти  для  индекса  имени
пункта, буфера имени пункта и главного индекса пунктов (смотрите
выше  раздел "Организация Файла Подсказки"),  а также немедленно
загружать эти  буфера.  Это  пространство  буферов  должно  быть
размещено  до  тех  пор,  пока  окно  не будет уничтожено.  Если
функция hwStaticNameBuffer не доступна, окна подсказки размещают
и загружают эти буфера только тогда,  когда необходимо высветить
или найти главный индекс пунктов, и высвобождают их только после
окончания операции.
     Функция hwPickList делает возможной команду  ccIndex.  Если
функция hwPickList  не  доступна,  пользователю будет недоступен
доступ к главному индексу пунктов из окна подсказки.
     Если параметр   hwClearStackAtExit   установлен,   Process
очищает стек предыдущего пункта во время выхода.
     Параметр hwMousePage     влияет     только     на   функцию
ScrollingHelpWindow. Если он установлен, поместив курсор мыши на
стрелку   вверх/вниз  и  нажав  клавишу  мыши,  прокручивающаяся
вертикальная полоска прокрутит окно до его полной  высоты; иначе
будет прокручена только одиночная строка.
     Параметр hwAdjustScroll  также  влияет  только  на  функцию
ScrollingHelpWindow.   Если   он  установлен,  конструктор  окна
подсказки  автоматически  устанавливает  пределы  горизонтальной
прокрутки  окна для сопоставления с самой длинной строки в файле
подсказки (сохраненной MAKEHELP).  Если параметр  не установлен,
окно   разрешает   по   существу  неограниченную  горизонтальную
прокрутку, если пределы  не  были  установлены  вызовом  функции
SetMaxScroll.
     Параметр hwBlockMark определяет,  были ли команды выделения
блока доступны в ScrollingHelpWindow.

     DefHelpOptions: Word=hwPickIndex+hwAdjustScroll;

     Параметры для окна подсказки, установленные по умолчанию.

     BadHelpOptions: Word=hwModeChangePending+hwProcessingHelp+
                              hwHelpframeInit+hwHelpModeActive+
                                    hwHelpFileOpen+hwHelpInMem+
                                                 hwNamesLoaded;

     Параметры используются  применительно  к  окну   подсказки.
Методы  hwOptionsOn и hwOptionsOff не будут изменять данные биты
в слове функции окна подсказки.

     HelpKeyMax = 196;
     HelpKeyID  : string[16] = 'ophelp key array';
     HelpKeySet : array[0..HelpKeyMAx] of Byte = (...);
     HelpCfgEnd : Byte = 0;

     HelpKeyID -  это  строка  ID,  используемая для обозначения
начала область  данных  конфигурации  для   OPHELP;   HelpCfgEnd
обозначает конец   области   данных   конфигурации.  Между  ними
находится HelpKeySet    -    таблица    команд,     используемая
HelpCommands. HelpKeyMax  является последним допустимым индексом
в таблице.

     HelpFileOpenMode : Byte = $20;
     {Режим FileMode: только считывание, чтение запрещено}

     Filemode используется   для   открытия   файла   подсказки.
Конструкторы окна подсказки при запуске используют это значение.
Если версия DOS меньше, чем 3.0, конструкторы переопределяют эти
величины и устанавливают их 0 - только считывание, это связано с
тем,  что  более  ранние  версии DOS не поддерживали расширенные
режимы.

     MaxPagesPerSection = 20;

     Это максимальное число страниц  в  пункте  подсказки.  Этот
предел  применяется только для объекта PagedhelpWindow. Страница
прерывается в том случае,  когда число  строк  превышает  высоту
окна   (если   пункт   был  загружен)  или  встречается  неявное
прерывание страницы (как результат директивы  !PAGE  в  исходном
тексте     подсказки).     Страницы,     превышающие    параметр
MaxPagesPerSection, игнорируются.

     MaxXrefsPerSection = 50;

     Это максимальное число перекрестных ссылок  в  пункте.  Это
ограничение применимо     к     функции     PagedHelpWindow    и
ScrollingHelpWindow.   Перекрестные   ссылки,   число    которых
превышает MaxXrefsPerSection, изображаются со специальными видео
атрибутами для невыделенных связей,  но они уже  не  могут  быть
выделены.

     MaxPreviousTopics  = 20;

     Это вместимость стека предыдущего пункта.  Когда стек полон
и поступает  новый   пункт,   самый   старый   пункт   в   стеке
выталкивается из стека и теряется.

     FlexStackSize      =  4;

     Это максимальное  число  вложенных атрибутов.  Высвечивание
подсказки с помощью символов ^A,  ^B и ^C, может быть вложенным.
Например, строка

     ^Anext word ^Bis drawn in ^Canother ^Cvideo
     ^Battribute ^Aaltogether.

     высветила бы слово 'another' с атрибутом ^C,  слово 'video'
с атрибутом   ^B,  'attribute'  с  ^A  и  слово  'altogether'  с
нормальным текстовым  атрибутом.  Этот  пример  использует   три
уровня вложенности.

     Attr1Toggle   = ^A; {Символ переключает специальный атрибут 1}
     Attr2Toggle   = ^B; {Символ переключает специальный атрибут 2}
     Attr3Toggle   = ^C; {Символ переключает специальный атрибут 3}
     IndexMarker   = ^D; {Символ помечает номер следующего пункта}
     XtrefToggle   = ^E; {Символ переключает высвечивание xref}
     LiteralMarker = ^F; {Символ помечает помечает следующие за
                                       ним буквенные ASCII символы}
     LineBrkMark   = ^M; {Обозначает конец строки подсказки}
     PageBrkMark   = ^L; {Обозначает конец страницы подсказки}
     SectEndMark   = #0; {Обозначает конец раздела подсказки}

     OPHELP переводит эти символы в  формат  и  высвечивает  ваш
текст подсказки. Их значения описаны в предыдущем разделе.

     HelpId : array[0..3] of Char = 'OPH1';

     Преобразованные нужным образом файлы подсказки начинаются с
этой последовательности из четырех символов.

     NoHelpAvailable = $FFFFFFFF;

     Поиск смещения (в HelpIndexRec),  которое  показывает,  что
для данного номера пункта подсказка недоступна.

     NoTopicName     = $FFFF;

     Смещение имени    (в   индексе   имени   пункта),   которое
показывает, что для данного номера пункта имя пункта недоступно.

     XrefForIndex    = 0;

     Если перекрестная связь определяет номер пункта, при выборе
этой ссылки, OPHELP высветит главный индекс пунктов.

     PickTopic       = 0;

     Если этот  номер  пункта  определен  при  вызове  SetTopic,
последующий вызов  Draw  или  Process  высветит  главный  индекс
пунктов.

     HelpExitCommands : ByteSet = [ccPrevTopic];

     Динамический команды    выхода,    которые    обуславливают
завершение Process главного индекса пунктов PickList.

     WordChars : string[127] = 'ABCDEFGIHJKLMNOPQRSTUVWXYZ
                                                   _0123456789';

     Символы верхнего  регистра,  используемые  при формировании
слов для грамматического разбора ScreenWordXY.

     Типы
     ───────────────────────────────────────────────────────────

     XlateArray = array[0..15] of Byte;

     Это таблица   кодирования,   используемая   для   сжатия  и
раскрытия текста подсказки.  Элемент 0 - символ,  наиболее часто
встречающийся в отдельном файле подсказки. Элемент 1 - следующий
наиболее  часто  встречающийся  и  т.д.  Элемент  номер  15   не
используется.

     HelpHeaderPtr = ^HelpHeader;
     HelpHeader =
       record
         ID           : longInt;    {Помечает версию файла подсказки}
         HighestTopic : Word;       {Старший номер пункта}
         BiggestTopic :  Word;      {Размер самого большого пункта в
                                                   несжатых байтах}
         PickTopics   : Word;       {Номер пункта в индексе выбора}
         SizeOfNames  :  Word;      {Байты  во  всех  номерах пунктов
                                             (упакованная таблица)}
         LongestName  : Byte;       {Самое длинное имя пункта}
         LongestPick  :  Byte;      {Самое  длинное  имя  в   индексе
                                                            выбора}
         WindowWidth  :   Byte;     {предпочитаемая   ширина   окна
                                                         подсказки}
         Scrolling    :   Boolean;  {Истинно,   если   установлена
                                                         прокрутка}
         MaxLineLen   : Integer;    {Максимальная длина строки}
         XlateTable   : XlateArray; {Таблица для раскрытия}
     end;

     Заголовок, находящийся  в  начале  файла  подсказки и часто
используемый для  управления  окном   подсказки.   Методы   окна
подсказки осуществляют доступ к необходимым вам полям записи.

     BytePtr      = ^Byte;
     CharArray    = array[0..65520] of char;
     CharArrayPtr = ^CharArray;
     WordArray    = array[1..(65521 div SizeOf(Word))] of Word;
     WordArrayPtr = ^WordArray;
     FilePtr      = ^File;

     Тут представлены  разнообразные  типы данных,  используемые
для управления различными символьными буферами и картами номеров
пунктов.  Когда  типы  CharArray и WordArray размещены в памяти,
они  расходуют  только   необходимый   размер   памяти,   а   не
максимальные размеры памяти, описанные этими определениями типа.

     HelpIndexRec =
       record
         Start   : LongInt;  {}
         CompLen : Word;   {}
       end;
     HelpIndex = array[1..(65521 div  SizeOf(helpIndexRec))]  of
                                                   HelpIndexRec;
     HelpIndexPtr = ^HelpIndex;

     Типы данных для управления индексом диска  файла подсказки,
которые определяют  положение  файла  и  длину сжатых данных для
каждого текста пункта.  Полный индекс диска  не  считывается  из
памяти, если целиком файл подсказки не был привязан к некоторому
применению.

     HelpFileSection =(hwHeader,     {Фиксированный размер заголовка}
                       hwNameIndex,  {Смещение     индекса    для
                                             упакованных имен пункта}
                       hwNames,      {Упакованные имена пункта}
                       hwTopicIndex, {Упорядоченный       индекс
                                           пунктов для списка выбора}
                       hwFileIndex); {Индекс для пунктов подсказки}

     Перечисленные типы обозначают компоненты файла подсказки.

     hwMatchFunc     = function(VaryingName, FixedName : String;
                         HPtr : AbsatractHelpWindowPtr):Boolean;

     Шаблон, для  написанной  пользователем   функции,   который
помогают  искать в пункте его имя.  Для получения дополнительной
информации, смотрите метод FindTopic.

     hwNestedFunc=function(HPtr:AbstractHelpWindowPtr):Boolean;

     Это процедура  типа  "вложенной  функции   привязки".   Для
дополнительной информации смотрите изложенное выше.

     AbstractHelpWindow = ^AbstractHelpWindow;
     AbstractHelpWindow =
       object(PickList)
       ...
       end;

     Это объект абстрактного окна подсказки.

     Xref = 0..MaxXrefsPerSection;

     Определяет допустимый интервал перекрестных индексов.

     FlexStack = array[0..FlexStackSize] of Char;

     Определяет стек кодов атрибутов, используемых для изменения
способов написания текста подсказки.  Обратите внимание  на  то,
что стек  содержит  управляющие  символы (^A,  ^B и т.д.) вместо
видео атрибутов.

     Переменные
     ───────────────────────────────────────────────────────────

     HelpCommands : CommandProcessor;

     По умолчанию    CommandProcessor    для   окна   подсказки.
Переменные  устанавливаются  инициализирующим   блоком   OPHELP.
Смотрите OPHELP.ICD для детального назначения клавиш.

Описание
     procedure AddMoreHelpHeader ( PromptStr : String80;
                                   Posn : HeaderPosType;
                                   UpStr, DnStr, SepStr : String10;
                                   UpPos, DnPos, SepPos : Byte );

Назначение
     Добавление специального заголовка продолжения для указания
     возможности получения дополнительной подсказки.

Описание
     Работает подобно процедуре AddMoreHeader PickList, за
     исключением того, что заголовок, добавленный к окну
     подсказки объекта hwFrame лучше, чем добавленный к окну
     помощи wFrame и содержимое заголовка больше зависит от
     текста подсказки, чем от содержимого списка выбора.

Пример
     PH.AddMoreHelpHeader(
       ' PgUp/PgDn for more ', heBR, 'PgUp', 'PgDn', '/', 2, 7, 6);

     Добавляет заголовок продолжения в правый нижний угол окна
     подсказки. В результате, по мере необходимости на экран
     будут выводится строки 'PgUp' и 'PgDn'. Если обе указанные
     строки выводятся на экран, между ними помещается
     строка-разделитель '/'.

Смотри также
     InitHelpFrame                  PickList.AddMoreHeader

----------------------------------------------------------------

Описание
     procedure AddTopicHeader ( PadSize : Byte;
                                MaxLen : Byte;
                                Pos : HeaderPosType );

Назначение
     Добавление заголовка для вывода на экран имени темы.

Описание
     OPHELP изменяет данный заголовок когда система подсказки
     загружает новую тему. Если тема не имеет имени, заголовок не
     появляется. В противном случае, имя темы усекается до
     MaxLen-2*PadSize символов ( если это необходимо ) и
     дополняется PadSize пробелами с двух сторон. Заголовок
     выводится на экран с позиции, определенной параметром Posh
     ( heTL, heTC, heTR, heBL, heBC или heBR ).

     Вы можете иметь не более одного заголовка темы для каждого
     окна подсказки.

     Если имеет место недостаток памяти, AddTopicHeader будет
     генерировать ошибку epFatal+ecOutOfMemory.

Пример
     PH.AddTopicHeader( 1, 60, heTC );

     Добавляет заголовок для вывода на экран имени текущей темы,
     центрированный в строке верхней рамки. Заголовок будет
     выделятся одним пробелом с каждой стороны; максимальная
     длина заголовка будет составлять 60 символов.

----------------------------------------------------------------

Описание
     function CurrentTopic : Word;

Назначение
     Возвращает номер темы, загруженной в данный момент в буфера
     подсказки.

Описание
     Данная функция используется в написанных пользователями
     вложенных процедурах-функциях. Она возвращает номер
     последней загруженной и развернутой в окне подсказки темы.

Пример
     См. SetNestedFunc для примера.

Смотри также
     SetTopic

----------------------------------------------------------------

Описание
     function CurrentXrefTopic : Word; virtual;

Назначение
     Возвращает тему подсказки для текущей перекрестной ссылки
     или $FFFF при ее отсутствии.

Описание
     Данная функция используется в написанных пользователями
     вложенных процедурах-функциях и функциях предварительного
     изменения состояния. Если текущее окно подсказки имеет связи
     перекрестных ссылок и курсор помещен на одной из них,
     CurrentXrefTopic возвратит тему, на которую указывает связь.
     В противном случае, функция возвращает $FFFF. Обратите
     внимание, что в случае, когда CurrentXrefTopic возвращает 0,
     выбор данной перекрестной ссылки будет активизировать
     основной индекс темы.

Смотри также
     SetNestedFunc

----------------------------------------------------------------

Описание
     destructor Done; virtual;

Назначение
     Закрывает и удаляет окно подсказки.

Описание
     Если имеется открытый файл подсказки, он закрывается. Все
     динамически выделенные буфера для окна подсказки
     освобождаются.

Пример
     PH.Done;

     Освобождает всю память, динамически отведенную для
     использования PH.

Смотри также
     PickList.Done

----------------------------------------------------------------

Описание
     procedure Draw; virtual;

Назначение
     Выбирает соответствующую рамку и рисует окно подсказки или
     индекса выбора.

Описание
     Если режим окна изменялся, Draw подкачивает объекты hwFrame
     и hwFrame. На экран выводится соответствующая рамка и
     содержимое окон обновляется ( при помощи UpdateContents )
     для вывода на экран либо основного индекса темы, либо
     текущей темы подсказки.

     Сама процедура Draw не загружает тему подсказки.
     Следовательно, указанная далее последовательность не будет
     приводить к ожидаемому результату:

     PH.SetTopic (100);
     PH.Draw;               ( неверно )

     Единственный способ загрузить новые темы - вызов процедуры
     Process. Ниже приводится правильная последовательность для
     вывода на экран темы 100:

     PH.SetTopic(100);
     PH.Process;

     Если вы хотите вывести на экран тему подсказки без ожидания
     ввода с клавиатуры, вы можете использовать процедуру
     ProcessAutoPilot:

     const
       QuitRightAway : Byte = ccQuit;
     ...
     PH.SetTopic(100);
     PH.ProcessAutoPilot(QuitRighAway, 1);

     Если окно находится в режиме выбора во время вызова Draw,
     может возникнуть необходимость выделения и заполнения
     буферов динамической памяти. Следовательно, после Draw
     нужно проверить, не была ли сгенерированна ошибка ( при
     помощи вызова GetLastError ).

     Как правило, Draw используется внутри объектов подсказки.
     Описание данной процедуры в этом разделе указывает на
     возможность исключения из этого правила.

Смотри также
     Process                          UpdateContents

----------------------------------------------------------------

Описание
     function FindTopic (Name : String; MatchFunc : hwMatchFunc)
                                                 : Word; virtual;

Назначение
     Возвращает номер темы подсказки с указанным именем или 0,
     если тема не найдена.

Описание
     FindTopic сканирует все именованные темы, начиная с первой
     и далее, проверяя соответствие их имен, имени, указанному в
     качестве параметра процедуры. Соответствие проверяется при
     помощи указанной функции сравнения. Если искомая тема
     найдена, FindTopic возвращает ее номер, в противном случае -
     0.

     MatchFunc должна быть глобальной функцией,
     откомпилированной в FAR модели (при помощи директивы {$F+})
     и соответствовать следующему определению прототипа:

     {$F+}
     function TopicMatchFunc ( VaryingName, FixedName : String;
                      HPtr : AbstractHelpWindowPtr ) : Boolean;

     Назначение функции MatchFunc заключается в сравнении
     VeryingName с FixedName и возвращении True ( истина ), если
     соответствие найдено. Данная функция может использовать для
     сравнения различные правила: она может различать или не
     различать большие и маленькие буквы, она может искать
     полное или частичное соответствие, она может использовать
     технологию "sounds-like" ("сходство по звучанию"), и т.д.
     Параметр FixedName всегда соответствует строке Name,
     передаваемой в FindTopic, а параметр VaryingName принимает
     значения имен всех проверяемых тем. HPtr является адресом
     окна подсказки для вызывающего функцию экземпляра.

     OPHELP предоставляет пользователю функцию сравнения по
     умолчанию, называемую DefaultTopicMatch. Данная функция
     проверяет на точное соответствие две строки, предварительно
     преобразованные к верхнему регистру.

     Если параметр hwStaticNameBuffer недоступен, FindTopic
     должна динамически получить память для загрузки трех ранее
     описанных массивов имен. Если ей это не удается, или если
     происходит ошибка Ввода/Вывода, функция генерирует ошибку,
     значение которой может быть определено с помощью вызова
     функции GetLastError.

Примеры
     PH.SetTopic(FindTopic('notes field', DefaultTopicMatch));

     В данном примере используется встроенная в OPHELP функция
     сравнения строк (DefaultTopicMatch) для поиска темы с
     именем, точно соответствующим строке 'notes field'
     (различия больших и малых букв игнорируются).

       uses
         OpCtr, OpRoot, OpString, OpCmd, OpFrame, OpWindow, OpPick,
                                                            OpHelp;
       var
         PH : PagedHelpWindow;
         {$F+}
         function MyTopicMatch(VaryingName, FixedName : String;
                          HPtr : AbstractHelpWindowPtr) : Boolean;
         begin
           MyTopicMatch :=(CompUstring(Copy(VaryingName, 1, 5),
                               Copy(FixedName, 1, 5)) = Equal);
         end;
         {$F-}
       begin
         PH.InitCustom(5, 8, 75, 18, DefaultColorSet, DefWindowOptions
                       or wBordered, 'ENTRY.HLP', PickVertical);
         PH.AddTopicHeader(1, 60, heTC);
         PH.SetTopic(FindTopic('notes', MyTopicMatch));
         PH.Process;
         PH.Done;
       end.

     Пример демонстрирует применение пользовательской функции
     сравнения. MyTopicMatch возвращает True ( истина ) для
     первой темы, у которой первые 5 символов соответствуют
     заданной строке ( без учета регистра ).

Смотри также
     ScreenWordXY

----------------------------------------------------------------

Описание
     function GetTopicChoice : Word;

Назначение
     Возвращает тему, выбранную из списка выбора

Описание
     Данная функция должна вызывается в режиме выбора после
     вызова процедуры Process. Она возвращает номер темы
     подсказки, которую запросил пользователь. Переменная, к
     которой обращается GetTopicChoice не будет
     инициализироваться до тех пор, пока пользователь не выйдет
     из списка выбора, не используя команды ccQuit или ccError.

     Следует отметить, что PickList.GetLastchoice не возвращает
     номера темы подсказки. Она возвращает некоторый индекс,
     который использовать прямо нельзя.

Пример
     PH.SetTopic(PickTopic);
     PH.Process;
     case PH.GetLastCommand of
       ccError,
       ccQuit :
         {нет выбора}
       ccSelect :
         begin
           PH.SetTopic(PH.GetTopicChoice);
           PH.Process;
         end;
     end;

     Первый вызов процедуры Process выводит на экран основной
     индекс темы и отслеживает выбор темы пользователем. Второй -
     выводит на экран тему подсказки, которая была выбрана.

Смотри также
     Process

----------------------------------------------------------------

Описание
     function HighestTopic : Word;

Назначение
     Возвращает наибольший номер темы в системе подсказки.

Описание
     Данная функция возвращает последний номер темы, изначально
     сохраненный в заголовке файла подсказки. Если происходит
     обращение к процедуре SetTopic с номером темы большим, чем
     HighestTopic, будет генерироваться ошибка.

Пример
     if PH.HighestTopic > 100 then
       { выполнить некоторые действия };

     В приведенном примере выполняются определенные действия при
     условии, что наибольший номер темы больше 100. Возможно,
     это указывает на то, что пользователем загружен другой
     набор подсказки.

Смотри также
     PickTopics

----------------------------------------------------------------

Описание
     function hwOptionsAreOn (OptionFlags : Word) : Boolean;

Назначение
     Возвращает True ( истина ), если все указанные параметры
     подсказки включены.

Описание
     Данная функция проверяет параметры подсказки, описанные в
     начале данного раздела.

Пример
     if PH.hwOptionsAreOn (hwMousePage) then
       { выполнить некоторые действия };

     Выполняются некоторые действия, если доступна прокрутка при
     помощи мыши.

----------------------------------------------------------------

Описание
     procedure hwOptionsOff (OptionFlag : Word );

Назначение
     Отключает заданные параметры.

Описание
     Данная процедура отключает заданный параметр (параметры),
     исключая те, которые обозначены как BadHelpOptions ( см.
     раздел Константы, приведенный выше )

     Если указан параметр hwStaticNameBuffer, hwOptionsOff
     немедленно освобождает буфера имени темы.

Пример
     SH.hwOptionsOff(hwMousePage);

     Отключает прокрутку страниц при помощи мыши.

----------------------------------------------------------------

Описание
     procedure hwOptionsOn (OptionFlag : Word );

Назначение
     Подключает заданные параметры.

Описание
     Данная процедура подключает заданный параметр (параметры),
     исключая те, которые обозначены как BadHelpOptions ( см.
     раздел Константы, приведенный выше )

     Если указан параметр hwStaticNameBuffer, hwOptionsOn
     немедленно выделяет и загружает буфера имени темы.

Пример
     SH.hwOptionsOn(hwMousePage+hwStaticNameBuffer);

     Подключает прокрутку страниц при помощи мыши и буфера
     статических имен.

----------------------------------------------------------------

Описание
     finction InHelpMode : Boolean;

Назначение
     Возвращает True ( истина ), если окно содержит подсказку, а
     не список выбора.

Описание
     Данная функция проверяет внутренний флаг, который
     указывает, содержал ли последний вывод на экран в окно
     подсказки непосредственно текст подсказки или основной
     индекс темы. Вновь инициализированное окно подсказки
     возвращает False ( ложь ).

     Эта функция обычно используется в двух случаях: для
     интерпретации команды ccQuite после вызова Process (см.
     пример из введения) или для принятия решения о том, что
     должна делать процедура перемещения пользователя (см.
     раздел "Превязки изменения состояния пользователя",
     приведенный выше).

Пример
     if PH.InHelpMode then
        PH.SetTopic(PickTopic)

     Если Process завершен при выводе на экран текста подсказки,
     при следующем вызове Process произойдет переключение на
     список выбора. Такое использование функции InHelpMode
     приводится в цикле Process программы предисловия.

Смотри также
     Process                      SetTopic

----------------------------------------------------------------

Описание
     constructor Init(X1, X2, Y2 : Byte;
                      HelpFile : PathStr;
                      PickOrientation : pkGenlProc);

Назначение
     Инициализирует окно подсказки и открывает файл подсказки.

Описание
     Данный конструктор создает экземпляр окна подсказки,
     используя принятые по умолчанию параметры окна
     (DefWindowOptions), набор цветов (DefaultColorSet),
     параметры выбора (DefPickOptions) и параметры подсказки
     (DefHelpOptions). См. описание InitDeluxe для получения
     более подробной информации.

Пример
     if not PH.Init(9, 8, 72, 18,       {Координаты окна}
                    'ENTRY.HLP',        {Файл подсказки}
                    PickVertical,       {Ориентация выбора}
     then begin
       WriteLn('Failed to Init PagedHelpWindow,
               Status = ', InitStatus);
       Halt;
     end;

     Пример демонстрирует инициализацию PH (PagedHelpWindow) с
     использованием цветов и параметров окна, принятых по
     умолчанию. В примере считывается внешний файл подсказки с
     именем ENTRY.HLP и используется вертикальная ориентация
     списка выбора.

Смотри также
     InitDeluxe                  InitMem

----------------------------------------------------------------

Описание
     constructor InitCustom(X1, X2, Y2 : Byte;
                            var Colors : ColorSet;
                            Options : LongInt;
                            HelpFile : PathStr;
                            PickOrientation : pkGenlProc);

Назначение
     Инициализирует окно подсказки и открывает файл подсказки.

Описание
     Данный конструктор создает экземпляр окна подсказки,
     используя заданные параметры окна (Options), заданные цвета
     (Colors) и принятые по умолчанию параметры выбора
     (DefPickOptions) и параметры подсказки (DefHelpOptions). См.
     описание InitDeluxe для получения более подробной
     информации.

Пример
     if not PH.InitCustom(9, 8, 72, 18,        {Координаты окна}
                          DefaultColorSet,     {Набор цветов}
                          DefWindowOptions
                          or wBordered,        {Параметры окна}
                          'ENTRY.HLP',         {Файл подсказки}
                          PickVertical)        {Ориентация выбора}
     then begin
       WriteLn('Failed to Init PagedHelpWindow,
               Status = ', InitStatus);
       Halt;
     end;

     Пример демонстрирует инициализацию PH (PagedHelpWindow) с
     использованием окна с рамкой и принятых по умолчанию
     цветов. В примере считывается внешний файл подсказки с именем
     ENTRY.HLP и используется вертикальная ориентация списка
     выбора.

Смотри также
     InitDeluxe                  InitMemCustom

----------------------------------------------------------------

Описание
     constructor InitDeluxe(X1, Y1, X2, Y2, : Byte;
                            var Colors : ColorSet;
                            Options : LongInt;
                            HelpFile : PathStr;
                            PickOrientation : pkGenlProc;
                            HelpOptions : Word);

Назначение
     Инициализирует окно подсказки и открывает файл подсказки.

Описание
     Это наиболее общий конструктор для окна подсказки, который
     считывает данные подсказки из внешнего файла. Все остальные
     конструкторы для окна подсказки выполняют специфический
     вызов данного конструктора.

     X1, Y1, X2 и Y2 определяют координаты активного окна, в
     котором будут появляться текст подсказки и индекс темы.

     Для построения окна подсказки InitDeluxe использует
     некоторые поля из указанного ColorSet. Кроме них для общих
     окон и для PickList, InitDeluxe заполняет следующие поля
     экземпляра окна подсказки:

         TextColor,  TextMono             обычный текст подсказки
         FlexAHelpColor, FlexAHelpMono    текст подсказки, помеченный ^A
         FlexBHelpColor, FlexAHelpMono    текст подсказки, помеченный ^B
         FlexCHelpColor, FlexAHelpMono    текст подсказки, помеченный ^C
         UnselXrefColor, UnselXrefMono    невыделенный текст перекрестных
                                          ссылок
         SelXrefColor, SelXrefMono        выделенный текст перекрестных
                                          ссылок (только для PagedHelpWindow)
         BlockColor, BlockMono            помеченный блок
                                          (только для ScrollingHelpWindow)

     Данные параметры представляют собой битовые флаги, которые
     используются в объектах, производных от RawWindow, таких как
     wBordered. Для получения более подробной информации
     обратитесь к разделу констант RawWindow. InitDeluxe
     устанавливает флаг wUserContents в состояние "on"
     ("включено"), т.к. окно подсказки поддерживает метод
     UpdateContents, который может регенерировать при
     необходимости содержимое окон.

     HelpFile является именем файла DOS, который содержит текст
     подсказки. HelpFile должен содержать расширение имени файла,
     использование какого-либо расширения по умолчанию не
     предусмотрено. Если HelpFile не содержит описания дисковода
     и имени каталога, InitDeluxe сначала просмотрит текущий
     каталог, затем каталог, содержащий файл программы, с
     расширением EXE (только для DOS 3.0 и более поздних версий),
     и, в заключении, каталоги, определенные командой DOS PATH.
     HelpFile должен был быть создан компилятором MAKEHELP;
     он должен начинаться строкой заголовка HelpId. InitDeluxe
     открывает данный файл в режиме, определенном константой
     HelpFileOpenMode.

     PickOrientation описывает ориентацию списка выбора основного
     индекса темы. Возможно использование одной из следующих
     величин: PickVertical, PickHorizontal или PickSnaking. Для
     получения более полной информации необходимо обратится к
     разделу "Ориентация списка выбора" во введении к объекту
     PickList.

     HelpOptions позволяет описывать параметры окна подсказки.
     Для получения более полной информации необходимо обратиться
     к разделу описания констант.

     Следует отметить, что InitDeluxe использует принятые по
     умолчанию параметры выбора (DefPickOptions) для окон
     подсказки в режиме выбора. Однако, InitDeluxe устанавливает
     параметр pkMinHeight в состояние "on" ("включено") для
     избежания конструктором PickList модификации заданных
     координат окон.

     Командный процессор HelpCommands определяется окном
     подсказки. Окну присваивается код ucHelp (с целью
     идентификации окна в заголовках подсказки и ошибки). Для
     PagedHelpWindow по умолчанию, аппаратный курсор
     устанавливается в режим cuHidden, для ScrollingHelpWindow,
     курсор устанавливается в режим cuNormal.

     InitDeluxe использует следующие блоки динамически
     распределяемой памяти:

     - Заголовок подсказки, SizeOf(HelpHeader) байт

     - Переменная файла, не имеющая типа, SizeOf(File) байт

     - Буфер для распаковки данных, BiggestTopic байт

     - если параметр hwStaticNameBuffer доступен, буфера для
       загрузки имен тем.

     Для получения более полной информации необходимо
     ознакомиться с разделом "Организация Файла подсказки". Если
     конструктор дает сбой, необходимо проверить переменную
     InitStatus для выявления кода ошибки.

Пример
     if not PH.InitDeluxe(9, 8, 72, 18,        {Координаты окна}
                          DefaultColorSet,     {Набор цветов}
                          DefWindowOptions
                          or wBordered,        {Параметры окна}
                          'ENTRY.HLP',         {Файл подсказки}
                          PickVertical,        {Ориентация выбора}
                          hwStaticNameBuffer)  {Параметры подсказки}
     then begin
       WriteLn('Failed to Init PagedHelpWindow,  Status = ', InitStatus);
       Halt;
     end;

     Пример демонстрирует инициализацию PH (PagedHelpWindow) с
     использованием окна с рамкой и принятых по умолчанию
     цветов. В примере считывается внешний файл подсказки с
     именем ENTRY.HLP и используется вертикальная ориентация
     списка выбора. Выделяются и загружаются буфера имени темы.
     Параметр hwPickIndex, который по умолчанию принимает
     значение "on" ("включено"), отключен: это не позволяет
     пользователям обращаться к основному индексу темы во время
     работы в режиме подсказки.

Смотри также
     PickList.InitDeluxe

----------------------------------------------------------------

Описание
     procedure InitHelpFrame;

Назначение
     Делает рамку окна подобной wFrame.

Описание
     Окно подсказки содержит три объекта Frame: wFrame, aFrame и
     hwFrame. wFrame выводится на экран когда окно находится в
     режиме выбора, hwFrame - когда окно находится в режиме
     подсказки, aFrame - когда установлен флаг wAltFrame и окно
     является активным но не текущим. Возможна независимая
     инициализация всех этих объектов. Во многих случаях, wFrame
     и hwFrame могут быть одинаковыми, за исключением
     незначительных отличий (например, hwFrame может иметь
     "заголовок продолжения", а wFrame - не иметь его). При
     вызове InitHelpFrame, OPHELP клонирует текущий объект wFrame
     в hwFrame. Возможно добавление дополнительных различий для
     этих двух объектов.

     Нельзя использовать Frame.fCopy для выполнения того же
     действия. InitHelpFrame устанавливает внутренний флаг,
     который в дальнейшем использует OPHELP.

Пример
     PH.Init(5, 8, 75, 18, 'ENTRY.HLP', PickVertical);
     { ... }
     wOptionsOn(wBordered);
     InitHelpFrame;
     { ... }

     Создается экземпляр окна подсказки с принятыми по умолчанию
     параметрами окна, что подразумевает использование окна без
     рамки. Далее рамка добавляется при помощи wOptionsOn.
     InitHwFrame синхронизирует рамку режима подсказки и рамку
     режима выбора.

----------------------------------------------------------------

Описание
     constructor InitMem(X1, Y1, X2, Y2 : Byte; HelpAddr : Pointer;
                         PickOrientation : pkGenlProc);

Назначение
     Инициализирует окно подсказки используя подсказку,
     расположенную в коде.

Описание
     Данный конструктор создает экземпляр окна подсказки,
     используя принятые по умолчанию параметры окна
     (DefWindowOptions), набор цветов (DefaultColorSet),
     параметры выбора (DefPickOptions) и параметры подсказки
     (DefHelpOptions). См. описание InitMemDeluxe для получения
     более подробной информации.

Смотри также
     InitMemDeluxe

----------------------------------------------------------------

Описание
     constructor InitMemCustom(X1, X2, Y2 : Byte;
                               var Colors : ColorSet;
                               Options : LongInt;
                               HelpAddr : Pointer;
                               PickOrientation : pkGenlProc);

Назначение
     Инициализирует окно подсказки используя подсказку,
     расположенную в коде.

Описание
     Данный конструктор создает экземпляр окна подсказки,
     используя заданные параметры окна (Options), заданные цвета
     (Colors) и принятые по умолчанию параметры выбора
     (DefPickOptions) и параметры подсказки (DefHelpOptions). См.
     описание InitMemDeluxe для получения более подробной
     информации.

Смотри также
     InitMemDeluxe

----------------------------------------------------------------

Описание
     constructor InitMemDeluxe(X1, Y1, X2, Y2, : Byte;
                               var Colors : ColorSet;
                               Options : LongInt;
                               HelpAddr : Pointer;
                               PickOrientation : pkGenlProc;
                               HelpOptions : Word);

Назначение
     Инициализирует окно подсказки используя подсказку,
     расположенную в коде.

Описание
     Данный конструктор работает подобно InitDeluxe, за
     исключением того, что файл подсказки располагается
     непосредственно в исполняемом файле программы, а не является
     внешним файлом. В результате, не происходит обращений к
     внешнему файлу, подсказка реализуется быстрее, проще и менее
     подвержена ошибкам системы.

     InitMemdeluxe использует только один буфер динамически
     выделяемой памяти размером BiggestTopic - для распаковки
     данных. Использование остальных буферов динамической памяти,
     которые выделяются InitDeluxe, заменяется непосредственным
     указанием на встроенный файл.

Пример
     var
       PH : PagedHelpWindow;
       Finished : Boolean;

       {$L ENTRYHLP.OBJ}
       procedure EntryHlp; external;

     begin
       if not PH.InitMemDeluxe(9, 8, 72, 18,        {Координаты окна}
                               DefaultColorSet,     {Набор цветов}
                               DefWindowOptions
                               or wBordered,        {Параметры окна}
                               @EntryHlp,           {Адрес данных подсказки}
                               PickVertical,        {Ориентация выбора}
                               hwPickIndex+
                               hwClearStackAtExit)  {Параметры подсказки}
       then begin
         WriteLn('Failed to Init PagedHelpWindow,  Status = ', InitStatus);
         Halt;
       end;
       { ... }
       PH.Done;
     end.

     Программа компонует файл подсказки во время компиляции. Файл
     ENTRYHLP.OBJ был создан при помощи утилита BINOBJ фирмы
     Borland. При этом использовалась следующая командная строка
     DOS:

        BINOBJ ENTRY.HLP ENTRYHLP.OBJ ENTRYHLP

     См. вводный раздел "Компоновка подсказки в программу" для
     получения дополнительной информации.

Смотри также
     InitDeluxe
----------------------------------------------------------------

Описание
     procedure ItemString(Item : Word; Mode : pkMode;
                          var IType : pkItemType;
                          var IString : String); virtual;

Назначение
     Выдает каждую строку элемента при переборе или выводе на
     экран основного индекса темы.

Описание
     Данный виртуальный метод переписывает принятую по умолчанию
     версию PickList в порядке, обеспечивающим форматирование
     имен тем подсказки для основного индекса темы.

     Возможно переопределение данного метода для настройки
     основного индекса темы. Например, демонстрационная программа
     ENTRY переопределяет метод для выделения некоторых пунктов в
     индексе. См. определение CustomHelpWindow в ENTRY.PAS.

Смотри также
     PickList.ItemString

----------------------------------------------------------------

Описание
     constructor Load(var S : IdStream);

Назначение
     Загружает систему подсказки из потока.

Описание
     S является допустимым инициализированным объектом потока
     (например, файл потока, открытый для чтения). Следует
     отметить, что S может быть потомком типа IdStream, который
     включает DosIdStream, BufIdStream и MemIdStream.

     Load считывает следующую последовательность байт из
     заданного потока. Эти байты должны были быть записаны
     предшествующим вызовом метода Store окна подсказки.
     Первоначально Load вызывает PickList.Load для загрузки
     содержимого PickList. Далее Load считывает данные,
     характерные для окна подсказки.

     Следует отметить, что поток окна подсказки не сохраняет сам
     файл подсказки. Он сохраняет только описание окна подсказки,
     его заголовков и конфигурации. Кроме того, он сохраняет либо
     имя файла подсказки (только имя, без маршрута), либо
     указатель кода встроенной подсказки.

     Процедурой регистрации потока для PagedHelpWindow является
     PagedHelpWindowStream, а для ScrollingHelpWindow -
     ScrollingHelpWindowStream. Также существует один или
     несколько указателей процедуры, которые регистрируются
     независимо. В приведенной ниже программе демонстрируется как
     это делается. Для получения более полной информации см.
     раздел Store.

Пример
     uses
       OpCrt, OpRoot, OpCmd, OpFrame, OpWindow, OpPick, OpHelp;
     var
       PH : PagedHelpWindow;
       S : BufIdStream;
     begin
       {Загрузка PH из потока}
       S.Init('HELP.STM', SOpen, 1024);
       S.RegisterHeir(PagedHelpWindowStream);
       S.RegisterPointer(ptPickVertical, @PickVertical);
       S.Get(PH);
       S.Done;

       {Проверка окна подсказки}
       PH.SetTipic(0);
       PH.Process;
       if PH.GetLastCommand <> ccQuit then begin
         PH.SetTipic(PH.GetTopicChoice);
         PH.Process;
       end;
       PH.Done;
     end;

     Создается экземпляр PH из потока, созданного в примере Store
     при помощи вызова метода потока Get, которая вызывает Load.
     Следует отметить, что процедура ориентации PickList должна
     быть зарегистрирована.

     См. BufIdStream (в OPROOT) для проверки характерных ошибок
     использования потоков.

     Единственное отличие загрузки ScrollingHelpWindow
     заключается в использовании ScrollingHelpWindowStream,
     вместо PagedHelpWindowStream.

Смотри также
     PickList.Load

----------------------------------------------------------------

Описание
     function PickTopics : Word;

Назначение
     Возвращает число индексированных тем подсказки в системе
     подсказки.

Описание
     Данная функция возвращает число пунктов, которые будут
     появляться в основном индексе темы.

Пример
     if PH.PickTopics < 25 then
        PH.hwOptionsOn*hwStaticNameBuffer);

     Проверяется число индексированных тем в данном файле
     подсказки, и в случае, когда их число относительно невелико,
     запрашиваются статические буфера для их имен.

Смотри также
     HighestTopic

----------------------------------------------------------------

Описание
     procedure Process; virtual;

Назначение
     Активизирует индекс подсказки или текущую тему

Описание

     Процедура окна подсказки Process следует общей модели,
     описанной в CommandWindow.Process, но имеет следующие
     особенности:

     Она обрабатывает команды, описанные в разделах "Команды
     страничных окон подсказки" и "Команды прокручиваемых окон
     подсказки" для PagedHelpWindow и ScrollingHelpWindow,
     соответственно.

     Process выводит на экран тему, взятую из вершины стека тем.
     (Тема может быть помещена в вершину стека при помощи
     процедуры SetTopic или оставлена здесь ранее вызванным
     Process.) Если стек не пустой и тема на вершине стека не
     является PickTopic(0), Process активизирует режим подсказки,
     загружает и развертывает тему, обрабатывает команды,
     поддерживаемые в режиме подсказки. В противном случае,
     Process активизирует окно режима выбора, загружает буфера
     имен (если они не были загружены ранее) и вызывает
     PickList.Process.

     Process может вызывать некоторые определенные пользователем
     подпрограммы. Для окна подсказки доступна вложенная функция
     перекрестных ссылок. Для PickList доступны функция поиска
     строки и процедура преддвижения. Процедура обработки ошибок
     наследуется от CommandWindow. И контекстно-зависимые, и
     клавиатурные процедуры фоновой обработки наследуются от
     CommandProcessor. (Следует обратить внимание на то, что
     возможно обеспечить контекстно-зависимую подсказку, даже для
     окна подсказки, хотя процедура Process не реентерабельна.)

Пример
     PH.SetTopic(100);
     PH.Process;

     Выводится на экран тема 100 и пользователю предлагается
     просмотреть систему подсказки.

     PH.SetTopic(PickTopic);
     PH.Process;
     if PH.GetLastCommand = ccSelect then
       ChosenTopic := PH.GetTopicChoice;

     Выводится на экран основной индекс темы, принимается выбор,
     и сохраняется в переменной ChosenTopic. Пример полной
     программы приводится во введении в данный раздел.

Смотри также
     PickList.Process                         SetTopic

----------------------------------------------------------------

Описание
     function ScreenWordXY(XPos, YPos : Byte;
                           ScanBack, ScanForward : Boolean) : String;

Назначение
     Анализирует слово с экрана от абсолютных координат (XPos,
     YPos).

Описание
     ScreenWordXY используется для написания систем подсказок,
     контекстно-зависимых от информации, выведенной на экран.
     Утилита POPHELP, поставляемая вместе с Object Professional
     является примером такой программы. ScreenWordXY определена в
     объекте AbstractHelpWindow только для удобства; она не
     присоединена непосредственно к объекту.

     XPos и YPos указывают абсолютные координаты экрана, с
     которых должен начаться анализ. Эти координаты обычно
     получаются из текущих координат аппаратного курсора или
     координат курсора мыши.

     ScreenWordXY определяет "слово" как непрерывную
     последовательность символов, содержащихся в строке
     WordChars. Данная строка по умолчанию содержит символы
     "A" ... "Z", "_" и "1" ... "9". Поскольку WordChars является
     глобальной константой для OPHELP, пользователь может
     модифицировать ее, включив в нее при необходимости
     дополнительные символы (максимум до 127 символов).

     Если символ в позиции (XPos, YPos) не содержится в WordChars
     а параметр ScanBack равен True (истина), ScreenWordXY будет
     сканировать строку начиная с заданного символа до начала
     строки, пока не найдет нужный символ. Если же нужный символ
     не будет найден и параметр ScanForward равен True (истина),
     процедура будет сканировать строку от заданного символа по
     направлению к концу строки, пока не достигнет ScreenWidth
     или не найдет нужный символ. Затем будет найдена
     максимальная по длине строка символов, которая будет
     возвращена в качестве результата функции. Если процедура не
     найдет слова для анализа, будет возвращена пустая строка.

Пример
     WhereXYAbs(X, Y);
     T := PH.FindTopic(ScreenWordXY(X, Y, True, False),
                       DefaultTopicMatch);
     if T = 0 then begin
       PH.SetTopic(PickTopic);
       PH.Process;
       PH.SetTopic(PH.GetTopicChoice);
     end else
       PH.SetTopic(T);
     PH.Process;
     PH.Done;

     Считывается слово начиная с текущей позиции курсора, или,
     при необходимости, с символа, найденного при сканировании по
     направлению к началу строки. FindTopic сравнивает найденное
     слово со всеми темами подсказки. Если соответствия с темой
     не найдено, T становится равным нулю и на экран выводится
     индекс. Если FindTopic находит соответствие, найденная тема
     фиксируется и на экран выводится подсказка.

Смотри также
     FindTopic

----------------------------------------------------------------

Описание
     procerure SetHelpPadSize(Pad : Byte);

Назначение
     Устанавливает число символов пробела от краев окна подсказки.

Описание
     По умолчанию, при выводе в окно текст подсказки выделяется
     одним символом пробела (с цветом фона) с обоих сторон.
     Данная процедура позволяет изменить указанный параметр.
     Следует отметить, что MAKEHELP обеспечивает значение данного
     параметра по умолчанию равным единице при помощи разбиения
     текста подсказки на строки, длинна которых на 2 символа
     меньше, чем параметр, заданный командой !WIDTH.

Пример
     PH.SetHelpPadSize(2);

     Добавляет пустое поле шириной в два символа с обеих сторон
     окна подсказки.

Смотри также
     SetPickPadSize

----------------------------------------------------------------

Описание
     procedure SetNestedFunc(NF : hwNestedFunc);

Назначение
     Устанавливает функцию для вложенных команд перекрестных
     ссылок.

Описание
     Функция NF должна быть откомпилирована в FAR модели (при
     помощи команды компилятора {$F+}) и должна соответствовать
     следующему определению прототипа:

     {$F+}
     function MyNestedFunc(Hptr : AbstractHelpWindowPtr) : Boolean;

     Для получения более полной информации см. содержимое раздела
     "Привязки вложенных функций", который расположен в начале
     данной главы.

Пример
     {$F+}
     function MyNestedFunc(Hptr : AbstractHelpWindowPtr) : Boolean;
     begin
       FastText('Current topic:       '+HexW(HPtr^.Current), 24, 1);
       FastText('Cross-reference topic: '+HexW(HPtr^.CurrentXrefTopic),
                 25, 1);
       MyNestedFunc := False;
     end;
     {$F+}
     ...
     HelpCommands.AddCommand(ccNested, 1, Ord(^M), 0);
     HelpExitCommands := [ccPrevTopic, ccNested];
     PH.SetNestedFunc(MyNestedFunc);
     ...

     Нажатию клавиши <Enter> приписывается команда ccNested,
     которая блокирует нормальную команду ccSelect. Для того,
     чтобы было возможно осуществить выбор в основном индекса
     темы, к динамическому набору команд выхода добавляется
     команда ccNested. SetNestedFunc активизирует функцию
     MyNestedFunc, которая выводит на экран при нажатии
     пользователем клавиши <Enter> в окне подсказки номер текущей
     темы и темы, связанной с текущей перекрестной ссылкой.
     Если нет активных перекрестных ссылок, SetNestedFunction
     выводит на экран FFFF. MyNestedFunc возвращает False (ложь)
     для указания на то, что метод Process не будет завершен.

Смотри также
     CurrentXrefTopic

----------------------------------------------------------------

Описание
     procedure SetPickPadSize(PadSize : Byte);

Назначение
     Устанавливает число символов отступа для элементов выбора.

Описание
     PadSize символов фона будут добавлены с двух сторон для
     каждой строки имени при выводе на экран основного индекса
     темы.

Пример
     PH.SetPickPadSize(5);

     Добавляется пять пустых символов для всех тем в основном
     индексе.

Смотри также
     SetHelpPadSize

----------------------------------------------------------------

Описание
     procedure SetPrevTopicHotSpot(SpotNum : Byte;
                                   Posn : FrameCharType);

Назначение
     Активизирует область активации для команды предыдущей темы.

Описание
     SpotNum - некоторый код, связанный с областью активации,
     которая была ранее добавлена к hwFrame. Для областей
     активации размером в один символ, добавленных при помощи
     метода AddHotSpot, значение величины SpotNum равно hsSpot.
     Для более общих областей активации, величина SpotNum
     определяется hsRegion1, hsRegion1 и т.д., заданных при
     вызове AddHotRegion.

     Posn является позицией относительно рамки, используемой при
     добавлении области активации - сторона или угол рамки.

     SetPrevTopicHotSpot сохраняет данные параметры во внутренних
     полях данных объектов окна подсказки. При обнаружении
     методом Process нажатия кнопки мыши в области активации,
     Process сравнивает описание данной области активации с
     данными в объекте. При их совпадении происходит
     преобразование нажатия кнопки мыши в команду ccPrevTopic,
     что приводит к повторному выводу на экран последней темы.

     Любое окно подсказки может иметь более одной области
     активации для обращения к предыдущей теме.

Пример
     PH.hwFrameAddHotSpot(frTL, #4, DefaultColorSet);
     PH.SetPrevTopicHotSpot(hsSpot, frTL);

     Добавляется область активации с символом "ромб" в левый
     верхний угол рамки окна подсказки и активизируется для
     выбора предыдущих тем.

Смотри также
     FrameAddHotRegion               FrameAddHotSpot

----------------------------------------------------------------

Описание
     procedure SetTopic(Topic : Word);

Назначение
     Задает тему или индекс (при PickTopic), которые будут
     выводится далее на экран.

Описание
     SetTopic помещает номер указанной темы в стек предыдущих
     тем. Следующее обращение к Process снимает этот номер со
     стека. Если была сохранена тема PickTopic(0), на экран
     выводится основной индекс темы и активизируется режим
     выбора. Если была сохранена не нулевая тема, Process
     загрузит и выведет на экран подсказку для этой темы.

     Следует отметить, что многократное обращение к SetTopic
     обеспечивает сохранение в стеке нескольких тем. При этом,
     последняя занесенная в стек тема будет выведена на экран
     первой. К остальным темам пользователь может вернуться при
     помощи команды ccPrevTopic (по умолчанию соответствующей
     нажатию клавиш <AltF1>).

     SetTopic проверяет заданный номер темы только на то, чтобы
     он не превосходил значение HighestTopic для текущего файла
     подсказки. Если это условие не выполняется, SetPopic
     генерирует ошибку epNonFatal+ecNoHelpForTopic. Если номер
     лежит в заданном диапазоне, но не существует подсказки для
     данной темы, ошибка не будет генерироваться пока Process
     не попытается загрузить ее.

Пример
       PH.SetTopic(PickList);

     В качестве следующей темы устанавливается индекс. При
     последующем вызове Process на экран будет выведен индекс.

       PH.SetTopic(PH.GetTopicChoice);

     В качестве темы, которая будет выведена на экран
     устанавливается последняя выбранная тема. При последующем
     вызове Process на экран будет выведена эта тема.

Смотри также
     Process

----------------------------------------------------------------

Описание
     procedure Store(var S : IdStream);

Назначение
     Сохраняет систему подсказки в потоке.

Описание
     S является допустимым инициализированным объектом потока
     (например, файл потока, открытый для чтения). Следует
     отметить, что S может быть потомком типа IdStream, который
     включает DosIdStream, BufIdStream и MemIdStream (однако,
     обычно нет необходимости писать в MemIdStream).

     Store записывает образ окна подсказки в поток S. Выполнение
     начинается вызовом PickList.Store, затем продолжается
     запись данных характерных для окна подсказки.

     Следует отметить, что поток окна помощи не сохраняет сам
     файл подсказки. Он сохраняет только описание окна подсказки,
     его заголовков и конфигурации. Кроме того, он сохраняет либо
     имя файла подсказки (только имя, без маршрута), либо
     указатель кода встроенной подсказки.

     Для проверки ошибок, которые могут иметь место во время
     работы Store, необходимо вызвать функцию потока GetStatus.

     Процедурой регистрации потока для PagedHelpWindow является
     PagedHelpWindowStream, а для ScrollingHelpWindow -
     ScrollingHelpWindowStream. Также существует один или
     несколько указателей процедуры, которые регистрируются
     независимо. В приведенной ниже программе демонстрируется как
     это делается.

     Процедура ориентации для основного PickList (PickVertical,
     PickHorizontal или PickSnaking) должна быть
     зарегистрирована. Если это не будет сделано, то при загрузке
     потока будет сгененрирована ошибка epFatal+ecBadPickOrient.

     Процедура регистрации потока окна подсказки автоматически
     регистрирует обработчик команд PickList (SingleChoice).
     Окна подсказки используют виртуальный метод для определенной
     пользователем процедуры обработки строк, в результате чего,
     необходимость ее регистрации отпадает.

     Если файл подсказки не был привязан к исполняемому файлу (с
     расширением EXE) должен быть зарегистрирован адрес
     подсказки.

     При использовании некоторых из следующих написанных
     пользователем процедур, они должны быть зарегистрированы,
     или не должны активизироваться при перезагрузке потока. К
     ним относятся: вложенная функция, процедура копирования
     блока (только для ScrollingHelpWindow), процедура
     предварительного изменения состояния и функция поиска
     индекса темы.

     Если окно подсказки использует любой отличный от принятого
     по умолчанию CommandProcessor (HelpCommands), адрес этого
     объекта должен быть зарегистрирован. Для примера см.
     CommandWindow.Store.

Пример
     uses
       OpCrt, OpRoot, OpCmd, OpFrame, OpWindow, OpPick, OpHelp;
     var
       PH : PagedHelpWindow;
       S : BufIdStream;
     begin
       {Инициализация окна подсказки}
       PH.InitCustom(9, 8, 72, 18, DefaultColorSet,
                     DefWindowOptions+wBordered,
                     'ENTRY.HLP', PickVertical);
       PH.AddTopicHeader(1, 60, heTC);
       PH.wFrame.AddHeader(' Topic Index ', heTC);
       PH.AddMoreHeader(' || for more ', heBR, #24, #25, '', 2, 3, 0);
       {Сохранение PH в потоке}
       S.Init('HELP.STM', SCreate, 1024);
       S.RegisterHeir(PagedHelpWindowStream);
       S.RegisterPointer(ptPickVertical, @PickVertical);
       S.Put(PH);
       S.Done;
       PH.Done;
     end.

     Инициализируется PH, добавляются некоторые детали, а затем
     PH сохраняется в потоке. См. Load для ознакомления с
     программой для загрузки окна из этого потока. Единственное
     отличие сохранения ScrollingHelpWindow заключается в
     использовании ScrollingHelpWindowStream, вместо
     PagedHelpWindowStream.

     См. BufIdStream (в OPROOT) для проверки характерных ошибок
     при использовании потоков.

     Если файл подсказки был встроен в исполняемую программу,
     необходимо добавить оператор, подобный следующему:

       S.RegisterPointer(2000, @EntryHlp);

     для последовательности регистраций. 2000 является кодом
     регистрации указателя, который может быть любым уникальным
     для потока числом от 1000 и больше. EntryHlp является именем
     пустой процедуры, используемой для связи в файле подсказки
     (см. связанный с этим вопросом пример в InitMemDeluxe).

Смотри также
     Load                       PickList.Store

----------------------------------------------------------------

Описание
     function TopicStackPtr : StaticQueuePtr;

Назначение
     Возвращает указатель на стек темы.

Описание
     Каждое окно подсказки содержит экземпляр объекта
     StaticQueue, который используется для управления стеком
     ранее выведенных на экран тем. TopicStackPtr возвращает его
     адрес для возможности работы со стеком различных методов
     StaticQueue.

Пример
     if (PH.TopicStackPtr^.Elements = 0 then
       {стек пуст};

     Проверяется наличие тем в стеке.

     var
       StackRec : phStackRec;
     ...
     PH.TopicStackPtr^.PeekTail(StackRec);
     if StackRec.STopic = 0 then
     {элемент в вершине стека является запросом выбора, удалить его }
     PH.TopicStackPtr^.PopTail(StackRec);

     Считывается запись из вершины стека PagedHelpWindow. Если
     номер темы равен 0, запись удаляется из стека.

Смотри также
     StaticQueue.Elements                 StaticQueue.PeekTail

----------------------------------------------------------------

Описание
     procedure UpdateContents; virtual;

Назначение
     Обновляет содержимое окна подсказки в режиме подсказки или
     выбора.

Описание
     Нет необходимости вызывать UpdateContents прямо. Вместо
     этого вызывается Process.

     UpdateContents выполняет следующие операции:

     Если окно находится в режиме подсказки и ранее на экран был
     выведена тема, UpdateContents выводит ее и обновляет
     заголовки и шкалу прокрутки. Если окно находится в режиме
     выбора, UpdateContents при необходимости загружает буфера
     имен и вызывает PickList.UpdateContents. Если буфера имен не
     были ранее выделены, UpdateContents освобождает их перед
     использованием.

Смотри также
     Draw                          Process
     PickList.UpdateContents


     2. PagedHelpWindow: Постраничная подсказка
     ------------------------------------------------------------

     Возможности PagedHelpWindow  во  многом подобны возможностям
блока TPHELP в Turbo Professional 5.0.  Прокрутка возможна только
по   страницам;   горизонтальная   прокрутка  не  поддерживается.
PagedHelpWindow   наследует   все    функции,    описанные    для
AbstractHelpWindow.  Оно  обеспечивает  алгоритмы  для  вывода на
экран текста подсказки и для управления  перемещением  выделенной
области   от   одной   перекрестной   ссылки   к   другой.   Т.к.
PagedHelpWindow  не  обеспечивает  новых  общих  методов,  данный
раздел не содержит описания методов.


     Команды окна постраничной подсказки.
     ------------------------------------------------------------

     Метод Process  объекта  PagedHelpWindow поддерживает команды
для просмотра текста подсказки и выбора перекрестных ссылок,  для
перемещению  по  стеку  тем,  для обеспечения выбора из основного
индекса темы.  В приводимом ниже списке эти  команды  разбиты  на
несколько  классов.  Для  всех  команд в первой строке дается имя
команды и клавиша (клавиши),  приписываемые по  умолчанию  данной
команде.  Во  второй  и  в  последующих строка приводится краткое
описание команды.  Клавиши,  приписываемые командам по  умолчанию
хранятся в константе глобального типа HelpKeySet (в OPHELP.ICD).
                                                                 
     Прокрутка страниц подсказки
     
     ccPageUp             <PgUp>, <CtrlR>
     Выводит на экран предыдущую страницу подсказки текущей темы.

     ccPageDn             <PgDn>, <CtrlC>
     Выводит на экран следующую страницу подсказки текущей темы.

     ccHome, ccTopOfFile  <Home>, <CtrlQ><S>, <CtrlPgUp>, <CtrlQ><R>
     Выводит на экран первую страницу подсказки текущей темы.

     ccEnd, ccEndOfFile   <End>, <CtrlQ><D>, <CtrlPgDn>, <CtrlQ><C>
     Выводит на экран последнюю страницу подсказки текущей темы.

     Перемещение выделенной области перекрестных ссылок

     ccUp, ccScrollUp <Up>, <CtrlE>, <CtrlW>
     Перемещает выделенную  область  к  предыдущей   перекрестной
     ссылке в вертикальном направлении.

     ccDn, ccScrollDn     <Down>, <CtrlX>, <CtrlZ>
     Перемещает выделенную  область  к   следующей   перекрестной
     ссылке в вертикальном направлении.

     ccLeft, ccPrevXref <Left>, <CtrlS>, <ShiftTab>
     Перемещает выделенную  область  к  предыдущей   перекрестной
     ссылке по   горизонтали.   Циклически   переходит   к  концу
     предыдущей строки,  когда выделенная область достигает самой
     левой перекрестной ссылки.

     ccRight, ccNextXref  <Right>, <CtrlD>, <Tab>
     Перемещает выделенную  область  к   следующей   перекрестной
     ссылке   по   горизонтали.  Циклически  переходит  к  началу
     следующей строки,  когда выделенная область достигает  самой
     правой перекрестной ссылки.

     Остальные

     ccSelect <Enter>
     Если имеется видимая выделенная область,  загружается  тема,
     соответствующая  выделенной  перекрестной  ссылке и на экран
     выводится первая страница  данной  темы.  Если  номер  темы,
     указанной   перекрестной   ссылкой  равен  нулю,  происходит
     переключение в режим выбора и на  экран  выводится  основной
     индекс  темы.  Если  же окно уже находилось в режиме выбора,
     загружается тема, соответствующая текущему элементу выбора и
     на экран выводится ее первая страница.

     ccMouseSel <ClickLeft>
     Перемещает выделенную   область   к   перекрестной   ссылке,
     указанной   при   помощи   мыши,  если  это  возможно.  Если
     выделенная область уже совпадает  с  указанной  перекрестной
     ссылкой,  работает  аналогично  команде  ccSelect для данной
     ссылки.  Кроме того,  данная команда может быть использована
     для прокрутки окна подсказки, если кнопка мыши нажимается на
     линейки прокрутки,  или для  повторной  загрузки  предыдущей
     темы,  если  кнопка  мыши  нажимается  в  области  активации
     предыдущей  темы  (см.   SetPrevTopicHotSpot).   Если   окно
     подсказки  находится  в  режиме  выбора,  мышь действует как
     описано для команд списка выбора.

     ccPrevTopic <AltF1>
     Загружает, если   возможно,  тему  подсказки,  которая  была
     загружена  перед  текущей,  выводит   на   экран   последнюю
     просмотренную  страницу  с последней выделенной перекрестной
     ссылкой.  Данная команда также может быть активизирована при
     помощи области активации предыдущей темы.

     ccIndex <F1>
     Если параметр hwPickList доступен,  переключает окно в режим
     выбора и выводит на экран основной индекс темы.

     ccNested нет приписанных клавиш
     Вызывает написанную  пользователем  вложенную  функцию.  См.
     описание этой функции в начале раздела.

     ccQuit <Esc>, <ClickRight>
     Выходит из окна подсказки или основного индекса темы.

     ccHelp <ClickBoth>
     Подсказка. Если написанная пользователем процедура подсказки
     была  установлена  при  помощи  вызова  SetHelpProc,  данная
     команда  выполнит  обращение  к  этой  процедуре.  Процедуре
     подсказки передаются три следующих параметра:  ucHelp, @Self
     и  номер  темы  подсказки,  организованный  как  индекс окна
     подсказки  (см.  CommandWindow.SetHelpIndex)  и  равный   по
     умолчанию     0.     Следует     отметить,     что     метод
     AbstractHelpWindow.Process          не          обеспечивает
     реентерабельности;  команда  ccHelp  не  может  генерировать
     вызов, который относится к тому же объекту OPHELP.

     Типы

     Pages = 0..MaxPagesPerSection;

     Определяет диапазон допустимых значений номеров страниц  для
каждой темы.

   phStackRec =
     record
       STopic : Word;          {Какая тема}
       SPage  : Pages;         {Страница в теме}
       SXnum  : Xrefs;         {Выбран элемент Xref}
     end;

     Определяет информацию,  сохраняемую с стеке тем  для  каждой
предыдущей темы.

   phPageRec =                 {Состояние экрана от начала
                                данной страницы}
     record
       TextOfs : Word;         {Смещение в восстановленном после
                                сжатия тексте}
       FlexSP  : Byte;         {Указатель гибкого стека}
       FlexStk : FlexStack;    {Стек активных индексов атрибутов}
     end;
   phPageArray = array[1..MaxPagesPerSection]

     Информация, используемая  внутри PagedHelpWindow для быстрой
постраничной прокрутки  темы.  phPageArray  инициализируется  при
загрузке текущей темы.

  phXrefRec =                  {Описывает данную перекрестную ссылку}
    record
      XrefPage :  Pages;       {Какая страница содержит ссылку}
      XrefRow  :  Byte;        {Какая колона в окне}
      XrefCol  :  Byte;        {Какой столбец в окне}
      XrefOfs : Word;          {Смещение в буфере восстановленного
                               после сжатия тексте}
      XrefTopic : Word;        {На какую тему указывает
                               перекрестная ссылка}
    end;
  phXrefArray = array[1..MaxXrefsPerSection] of phXrefRec

     Информация, используемая внутри PagedHelpWindow для быстрого
перемещения   выделенной   области   по   перекрестным   ссылкам.
phXrefArray инициализируется при загрузке текущей темы.

  PagedHelpWindowPtr = ^PagedHelpWindow;
  PagedHelpWindow =
    object(AbstractHelpWindow)
      ...
    end;

     Объект постраничного окна подсказки.


     3. ScrollingdHelpWindow: Построчная подсказка
     ------------------------------------------------------------

     Кроме предложенных  возможностей горизонтальной и построчной
прокрутки,  ScrollingHelpWindow добавляет команды для  пометки  и
копирования    блоков.   При   помощи   совмещения   возможностей
копирования  блоков  OPHELP  с  возможностями  модуля   OPREPLAY,
POPHELP   переносит   выделенные  фрагменты  текста  подсказки  в
используемое программное обеспечение,  как  правило  в  текстовой
редактор.  Реализация этой возможности в подгружаемых резидентных
программах,  подобных POPHELP,  является сложным упражнением и мы
отсылаем  вас  к исходным текстам POPHELP для ознакомления с тем,
как это можно сделать.  Когда система подсказки интегрируется для
обычного   программного   обеспечения,  процедура  вставки  ранее
помеченного текста может быть реализована значительно проще,  как
это показано ниже.

     В ScrollingHelpWindow  перекрестные  ссылки  выбираются  при
помощи перемещения аппаратного курсора по  выделенному  тексту  и
последующего нажатия клавиши <Enter>.  Перекрестные ссылки всегда
выводятся   на   экран   с    невыделенными    атрибутами    (см.
AbstractHelpWindow.InitDeluxe    для   получения   более   полной
информации).

     Команды прокручиваемых окон подсказки.
     ------------------------------------------------------------

     Метод Process   объекта   ScrollingHelpWindow   поддерживает
команды для просмотра  текста  подсказки  и  выбора  перекрестных
ссылок,  для перемещению по стеку тем,  для обеспечения выбора из
основного индекса темы.  В приводимом  ниже  списке  эти  команды
разбиты  на  несколько  классов.  Для всех команд в первой строке
дается  имя  команды  и  клавиша  (клавиши),   приписываемые   по
умолчанию  данной  команде.  Во  второй  и  в  последующих строка
приводится  краткое  описание  команды.  Клавиши,   приписываемые
командам  по  умолчанию  хранятся  в  константе  глобального типа
HelpKeySet (в OPHELP.ICD).  Следует отметить, что PagedHelpWindow
и  ScrollingHelpWindow совместно используют один CommandProcessor
и набор клавиш.

     В режиме  выбора  все   соответствующие   команды   работают
согласно описанию для PickList.

     Перемещение курсора и прокрутка

     ccUp                 <Up>, <CtrlE>
     Перемещает курсор на одну строку вверх,  прокручивает  текст
     окна подсказки, когда курсор достигает верхней строки окна.

     ccScrollUp           <CtrlW>
     Прокручивает текст подсказки на одну строку вниз.

     ccDown               <Down>, <CtrlX>
     Перемещает курсор  на  одну строку вниз,  прокручивает текст
     окна подсказки, когда курсор достигает нижней строки окна.

     ccScrollDn           <CtrlZ>
     Прокручивает текст подсказки на одну строку вверх.

     ccLeft               <Left>, <CtrlS>
     Перемещает курсор на один столбец влево,  прокручивает текст
     окна   подсказки,  если  курсор  достигает  крайнего  левого
     столбца и столбец 1 текста в настоящий момент невидим.

     ccRight              <Right>, <CtrlD>
     Перемещает курсор на один столбец вправо, прокручивает текст
     окна  подсказки,  если  курсор  достигает  крайнего  правого
     столбца  и текст в настоящий момент не прокручен до придела,
     установленного для горизонтальной прокрутки.

     ccPageUp             <PgUp>, <CtrlR>
     Прокручивает текст вниз на высоту окна.

     ccPageDn             <PgDn>, <CtrlC>
     Прокручивает текст вверх на высоту окна.

     ccHome               <Home>, <CtrlQ><S>
     Перемещая курсор на первый столбец текущей строки.

     ccTopOfFile          <CtrlPgUp>, <CtrlQ><R>
     Перемещает курсор на первый  столбец  первой  строки  текста
     подсказки, при необходимости выполняя прокрутку.

     ccEnd                <End>, <CtrlQ><D>
     Перемещает курсор на конец текущей строки.

     ccEndOfFile          <CtrlPgDn>, <CtrlQ><C>
     Перемещает курсор   на   конец   последней   строки   текста
     подсказки, при необходимости выполняя прокрутку.

     ccScreenTop          <CtrlHome>, <CtrlQ><E>
     Перемещает курсор   на   первую  строку  окна  подсказки  не
     выполняя прокрутки и не изменяя столбца курсора.

     ccScreenBot          <CtrlEnd>, <CtrlQ><X>
     Перемещает курсор  на  последнюю  строку  окна  подсказки не
     выполняя прокрутки и не изменяя столбца курсора.

     ccWordLeft           <CtrlLeft>, <CtrlA>
     Перемещает курсор на одно слово влево. Если курсор находится
     в начале  строки,  перемещает  курсор  на  конец  предыдущей
     строки.

     ccWordRight           <CtrlRight>, <CtrlF>
     Перемещает курсор  на  одно  слово   вправо.   Если   курсор
     находится  в  конце  строки,  перемещает  курсор  на  начало
     следующей строки.

     ccPrevXref           <ShiftTab>
     Перемещает курсор  не  предыдущую  перекрестную ссылку,  при
     необходимости  прокручивая  текст  окна.   Если   предыдущей
     перекрестной ссылки нет, ничего не делает.

     ccNextXref           <Tab>
     Перемещает курсор  не  следующую  перекрестную  ссылку,  при
     необходимости   прокручивая   текст   окна.  Если  следующей
     перекрестной ссылки нет, ничего не делает.

     Операции с блоками

     Операции с блоками являются активными, только когда параметр
hwBlockMark доступен.

     ccBlkBegin           <F7>, <CtrlK><B>
     Помечает текущую позицию  курсора  как  начало  блока.  Если
     маркер  начала  блока расположен перед маркером конца блока,
     блок выделяется.

     ccBlkEnd             <F8>, <CtrlK><K>
     Помечает текущую  позицию  курсора как конец блока.  Следует
     отметить,  что последним выделенным символом  будет  символ,
     непосредственно предшествующий позиции курсора. Если позиция
     курсора выходит за конец строки,  блок  будет  заканчиваться
     последним непустым символом этой строки.

     ccBlkToggle          <CtrlK><H>
     Переключает выделение помеченного блока.

     ccBlkCopy            <CtrlK><C>
     Если блок выделен правильно и он является видимым,  вызывает
     написанную  пользователем  функцию  копирования   блока.   В
     противном случае игнорирует команду.

     Остальные

     ccSelect             <Enter>
     Если курсор расположен над выделенной перекрестной  ссылкой,
     загружается и выводится на экран указанная тема.  Если номер
     темы,  указанной перекрестной ссылкой равен нулю, происходит
     переключение  в  режим  выбора и на экран выводится основной
     индекс темы.  Если же окно уже находилось в  режиме  выбора,
     загружается тема, соответствующая текущему элементу выбора и
     на экран выводится ее первая страница.

     ccMouseSel           <ClickLeft>
     Перемещает курсор в позицию, указанную при помощи мыши. Если
     курсор  уже  находится   перекрестной   ссылкой   и   команд
     ccMouseSel  выполняется второй раз,  она работает аналогично
     команде ccSelect  для  данной  ссылки.  Кроме  того,  данная
     команда   может   быть   использована   для  прокрутки  окна
     подсказки, если кнопка мыши нажимается на линейки прокрутки,
     или для повторной загрузки предыдущей темы, если кнопка мыши
     нажимается  в  области  активации   предыдущей   темы   (см.
     SetPrevTopicHotSpot). Если окно подсказки находится в режиме
     выбора, мышь действует как описано для команд списка выбора.

     ccPrevTopic          <AltF1>
     Загружает, если   возможно,  тему  подсказки,  которая  была
     загружена перед текущей и  прокручивает  текст  до  позиции,
     которая  была при последнем просмотре.  Данная команда также
     может  быть  активизирована  при  помощи  области  активации
     предыдущей темы.

     ccIndex              <F1>
     Если параметр hwPickList доступен,  переключает окно в режим
     выбора и выводит на экран основной индекс темы.

     ccNested             нет приписанных клавиш
     Вызывает написанную  пользователем  вложенную  функцию.  См.
     описание этой функции в начале раздела.

     ccQuit               <Esc>, <ClickRight>
     Выходит из окна подсказки или основного индекса темы.

     ccHelp               <ClickBoth>
     Подсказка. Если написанная пользователем процедура подсказки
     была  установлена  при  помощи  вызова  SetHelpProc,  данная
     команда  выполнит  обращение  к  этой  процедуре.  Процедуре
     подсказки передаются три следующих параметра:  ucHelp, @Self
     и  номер  темы  подсказки,  организованный  как  индекс окна
     подсказки  (см.  CommandWindow.SetHelpIndex)  и  равный   по
     умолчанию     0.     Следует     отметить,     что     метод
     AbstractHelpWindow.Process          не          обеспечивает
     реентерабельности;  команда  ccHelp  не  может  генерировать
     вызов, который относится к тому же объекту OPHELP.

     Использование привязки копирования блока

     Если параметр   hwBlockMark   доступен,   блок   помечен   и
пользователь   выполнил   команду   ccBlkCopy,   OPHELP  вызывает
написанную  пользователем   функцию,   известную   как   привязка
копирования блока.  Эта функция должна быть откомпилирована в FAR
модели (при помощи  команды  {$F+}),  должна  быть  глобальной  и
должна  иметь  параметры,  которые соответствуют приводимому ниже
прототипу:

   {$F+}
   function MyCopyFunc(T : CharArrayPtr; Len : Word;
                       SH : ScrollingHelpWindowPtr) : Boolean;

     Когда OPHELP  вызывает  эту  функцию,  ей  передается  адрес
первого   помеченного  символа  в  качестве  параметра  T,  число
помеченных символов в качестве параметра Len и адрес объекта окна
подсказки   в  качестве  параметра  SH.  MyCopyFunc  отвечает  за
пересылку символов или в файл,  или в другое окно,  или  в  буфер
клавиатуры.  При желании,  она может отменить выделение блока или
скрыть его,  обновить экран,  вызвать  завершение  работы  метода
Process.   Если  MyCopyFonc  возвращает  True  (истина),  Process
завершит работу после  выполнения  команды  ccBlkCopy;  если  она
возвращает  False  (ложь),  Process будет выполнять цикл ожидания
следующих команд.

     Для передачи управления копированием  функции  пользователя,
необходимо использовать метод SetSendFunc:

   procedure SetSendFunc(SF: shSendFunc);
     {Устанавливается функция, которая будет вызываться командой
     CopyBlock}

     Копирование символов  из буфера T^ может оказаться несколько
сложнее,  чем это может показаться на первый взгляд.  Несмотря на
то,  что  буфер содержит "простой",  восстановленный после сжатия
текст,  он все  равно  содержит  различные  управляющие  символы,
используемые  для  изменения  видеоатрибутов  и реализации связей
перекрестных  ссылок.  Это  требует  от   функции   осуществления
фильтрации или преобразования указанных символов.

     Далее приводится   пример   программы,   которая   добавляет
помеченный фрагмент текста подсказки в текстовой файл.

program HelpBlokExample;     {EXHELP.PAS}
uses
  OpCrt, OpRoot, OpCmd, OpMouse, OpFrame, OpWindow, OpPick, OpHelp;
const
  HelpFile  = 'ENTRY.HLP';
  BlockFile = 'ENTRY.BLK';
var
  SH : ScrollingHelpWindow;

  {$F+}
  function MyCopyFunc(T : CharArrayPtr; Len : Word;
                      SH : ScrollingHelpWindowPtr) : Boolean;
  var
    I : Word;
    F : Text;
  begin
    {Не завершать метод Process}
    MyCopyFunc := False;

    {$I-}
    {Добавление к файлу блока}
    Assign(F, BlockFile);
    Append(F);
    if IoResult <> 0 then
      Rewrite(F);
    {$I+}

    {Сканирование информации подсказки}
    I := 0;
    repeat
      case T^[I] of
        Attr1Toggle..Attr3Toggle,
        XrefToggle :              {Изменение видеоатрибутов}
          ;
        IndexMarker :             {Следует перекрестная ссылка темы}
          Inc(I, 2);

        LineBrkMark,              {Конец строки}
        PageBrkMark               {Конец страницы. В данном случае,
                                   действует как конец строки}
          WriteLn(F);

      else
        {Обычный текст}
        Write(F, T^.[I]);
      end;
      Inc(I);
    until I >= Len;
    WriteLn(F);
    Close(F);

    {Отмена выделения блока и обновление окна}
    SH^.HideBlock;
    SH^.Draw;
  end;

begin
  if not SH.InitDeluxe(9, 8, 72, 18,
                       DefaultColorSet,
                       DefWindowOptions or wBordered,
                       HelpFile,
                       PickVertical,
                       hwStaticNameBuffer+hwPickIndex+hwBlockMark)
  then begin
    WriteLn('Error initializing help window: ', InitStatus);
    Halt;
  end;

  {Добавление некоторых особенностей}
  SH.AddTopicHeader(1, 60, heTC);
  SH.wFrame.AddHeader(' Topic Index ', heTC);
  SH.wFrame.AddScrollBar(frRR, 0, MaxLongInt, DefaultColorSet);
  SH.hwFrame.AddScrollBar(frRR, 0, MaxLongInt, DefaultColorSet);
  SH.hwFrame.AddScrollBar(frBB, 0, MaxLongInt, DefaultColorSet);

  SH.SetBlockAttr($70, $70);
  SH.SetSendFunc(MyCopyFunc);

  {Вывод на экран темы 1}
  SH.SetTopic(1);
  SH.Process;

  {Освобождение окна подсказки}
  SH.Done;
end.

     В данном примере MyCopyFunc никогда не  вызывает  завершения
метода   Process,   т.к.  всегда  возвращает  False  (ложь).  Она
открывает выходной файл и пытается добавить  в  него  информацию;
если  в  данный  момент файл не существует,  она создает его.  (В
данном   примере   производится   минимально   удовлетворительная
проверка ошибок Ввода/Вывода; реальная программа должна выполнять
значительно больше проверок.)

     Цикл repeat демонстрирует как необходимо  сканировать  текст
подсказки.    Нулевое   значение   индекса   массива   T   всегда
соответствует ссылке на первый символ  помеченного  фрагмента.  В
данном  примере,  T^[I]  указывает  на следующий интерпретируемый
символ.  Символы  от  Attr1Toggle  до  Attr3Toggle  и  XrefToggle
являются  управляющими  и должны в данном примере игнорироваться.
Другим управляющим символом является IndexMark.  Данный символ не
должен  записываться  в  текстовой  файл,  а следующие за ним два
символа,  которые являются номером связанной перекрестной ссылкой
темы   (в   двоичном  формате),  необходимо  пропустить.  Символы
LineBrkMrk и PageBrkMrk  указывают  на  конец  строки  и  при  их
обнаружении   необходимо   использовать   команду   WriteLn   для
текстового файла.  Цикл продолжается,  пока индекс I  больше  или
равен заданной длины фрагмента (Len).

     Когда все    символы   будут   записаны,   вывод   фрагмента
завершается  командой  WriteLn  и  файл  закрывается.   Процедура
копирования завершается вызовом двух методов ScrollingHelpWindow:
HideBlock  который  делает  только  что  скопированный   фрагмент
невидимым  во  избежании  его  повторного  копирования,  и  Draw,
который обновляет окно подсказки для отображения этого изменения.
Следует  отметить,  что  функция  копирования  может  вызывать  и
некоторые  другие  методы  ScrollingHelpWindow,   которые   после
завершения оставляют неизменными координаты текущего окна.

     Основное тело  программы  активизирует  блочные  команды при
помощи указания параметра hwBlockMark в конструкторе окна. В теле
программы    устанавливаются    обратные    видеоатрибуты   ($70)
помеченного фрагмента как для  цветных,  так  и  для  черно-белых
мониторов, и вызывается SetSendFunc для указания на необходимость
вызова MyCopyFunc для команды ccBlkCopy.

Типы

   shStackRec =
     record
       STopic : Word;          {Какая тема}
       First  : shLineRec;     {Состояние первой строки}
       Last   : shLineRec;     {Состояние последней строки}
       HorOfs : Word;          {Горизонтальное смещение экрана}
       CursX  : Byte;          {Координата X позиции курсора}
       CursY  : Byte;          {Координата Y позиции курсора}
     end;

     Определяет информацию,  сохраняемую с стеке тем  для  каждой
предыдущей темы.

   shLineRec =
     record
       TextOfs : Word;         {Смещение в восстановленном после
                                сжатия тексте}
       FlexSP  : Byte;         {Указатель гибкого стека}
       FlexStk : FlexStack;    {Стек активных индексов атрибутов}
     end;

     Информация, используемая  внутри PagedHelpWindow для быстрой
построчной прокрутки темы.

  shSendFunc = function (T : CharArrayPtr; Len : Word;
                         SH : ScrollingHelpWindowPtr) : Boolean;

     Тип процедуры   для   привязки   копирования  блоков.  Более
подробно данная процедура обсуждается выше.

  ScrollingHelpWindowPtr = ^ScrollingHelpWindow;
  ScrollingHelpWindow =
    object(AbstractHelpWindow)
      ...
    end;

     Объект прокручиваемого окна подсказки.

----------------------------------------------------------------

Описание
     procedure HideBlock;

Назначение
     Делает текущий блок невидимым.

Описание
     Данный метод обычно используется внутри написанной
     пользователем функции копирования. Он просто сбрасывает
     внутренний флаг, который определяет, является ли блок
     видимым или нет. Если блочные команды не были
     активизированы, HideBlock ничего не делает. Для обновления
     окна необходимо вызвать Draw.

Пример
       SH^.HideBlock;

     Делает невидимым блок для ScrollingHelpWindow, которое
     адресуется по SH. Полностью пример приводится в разделе
     "Использование привязок копирования блоков".

----------------------------------------------------------------

Описание
     procedure ResetBlock;

Назначение
     Очищает текущий блок. Не обновляет экрана.

Описание
     Работает подобно HideBlock, но в дополнение устанавливает
     внутренние маркеры начала и конца блока в 0.

----------------------------------------------------------------

Описание
     procedure SetBlockAttr(Color; Mono : Byte);

Назначение
     Устанавливает атрибуты для блока.

Описание
     Принятыми по умолчанию атрибутами блока являются поля
     BlockColor и BlockMono в ColorSet, используемые при
     инициализации окна подсказки. SetBlockAttr позволяет
     изменять принятые по умолчанию атрибуты на другие.

Пример
       SH.SetBlockAttr($02, $70);

     Устанавливает атрибут для вывода на экран помеченного блока
     зеленым цветом на черном фоне для цветного монитора и
     обратным цветом для черно-белого.

Смотри также
     AbstractHelpWindow.InitDeluxe

----------------------------------------------------------------

Описание
     procedure SetMaxScroll(MaxFirstCol : Word);

Назначение
     Устанавливает новое значение для предела горизонтальной
     прокрутки.

Описание
     Если параметр hwAdjustScroll доступен, предел горизонтальной
     прокрутки устанавливается с таким расчетом, чтобы самая
     длинная строка текста подсказки могла бы быть полностью
     просмотрена при текущей ширине окна подсказки. Если
     указанный параметр недоступен, горизонтальная прокрутка
     существенно не ограничена. Именно в этом случае имеет смысл
     использование SetMaxScroll для ограничения прокрутки. Если
     MaxFirstCol равен 1, горизонтальная прокрутка отключается.

Пример
     SH.SetMaxScroll(50);

     Подсказка будет прокручиваться по горизонтали не более чем
     на 49 символов.

----------------------------------------------------------------

Описание
     procedure SetSendFunc(SF : shSendFunc);

Назначение
     Устанавливает функцию, которая будет вызываться командой
     ccBlkCopy.

Описание
     Функция SF должна быть откомпилирована в FAR модели (при
     помощи команды {$F+}), должна быть глобальной и должна иметь
     параметры, которые соответствуют приводимому ниже прототипу:

       {$F+}
       function MyCopyFunc(T : CharArrayPtr; Len : Word;
                           SH : ScrollingHelpWindowPtr) : Boolean;

     Более подробная информация и весь пример приводятся в
     разделе "Использование привязок копирования блоков".

Смотри также
     HideBlock


     4. Процедуры и функции
     ------------------------------------------------------------

     Кроме упоминавшихся  выше  процедур  регистрации  потока   и
пользовательских  подпрограмм  привязки,  принятых  по умолчанию,
OPHELP  предоставляет  некоторую   функцию,   которая   позволяет
определить   "предпочитаемый   объект"   для   конкретного  файла
подсказки.  Некоторые файлы подсказки могут иметь  структуру  для
лучшей работы с ScrollingHelpWindow,  другие - с PagedHelpWindow.
Разработчики  архитектуры   файла   подсказки   могут   указывать
предпочтительное  использование  при  помощи  команды !SCROLLING.
Возможность  определить  способ  использования  файла   актуальна
только  для утилит,  подобных POPHELP,  которая имеет возможность
считывать различные файлы подсказки,  написанные разными  людьми.
Для   других   программных   продуктов  тип  используемого  файла
подсказки заведомо известен.


Описание
     function ScrollingHelpFile(HelpFile : PathStr) : Boolean;

Назначение
     Возвращает False (ложь) в случае, когда HelpFile разработан
     для прокручиваемого окна подсказки.

Описание
     ScrollingHelpFile открывает указанный файл подсказки также,
     как это делает конструктор окна подсказки: он сначала
     просматривает заданный каталог, а в случае, если HelpFile не
     содержит описания дисковода и имени каталога - каталог,
     содержащий файл программы и каталоги, определенные командой
     DOS PATH. Затем ScrollingHelpFile открывает файл (используя
     HelpFileOpenMode), считывает его заголовок и закрывает файл.
     Если флаг Scrolling в заголовке файла доступен,
     ScrollingHelpFile возвращает True (истина). Если же данный
     флаг не установлен или если во время открытия или чтения
     файла подсказки имела место какая-либо ошибка,
     ScrollingHelpFile возвращает False (ложь).

Пример
       program PageOrScrollExample;     {EXHELP3.PAS}
       uses
         OpCrt, OpRoot, OpCmd, OpMouse, OpFrame, OpWindow, OpPick, OpHelp;
       const
         HelpFile  = 'ENTRY.HLP';
       var
         H : AbstractHelpWindow;
         Scrolling : Boolean;
       begin
         {Определение, является ли данный файл предусмотренным
          для прокрутки}
         Scrolling := ScrollingHelpFile(HelpFile);
         {Выделение окна подсказки в соответствии с типом файла}
         if Scrolling then
           H := New(ScrollingHelpWindowPtr,
                    InitDeluxe(9, 8, 72, 18,
                               DefaultColorSet,
                               DefWindowOptions or wBordered,
                               HelpFile, PickVertical,
                               hwStaticNameBuffer+hwPickIndex))
         else
           H := New(PagedHelpWindowPtr,
                    InitDeluxe(9, 8, 72, 18,
                               DefaultColorSet,
                               DefWindowOptions or wBordered,
                               HelpFile, PickVertical,
                               hwStaticNameBuffer+hwPickIndex));
         if H = nul then begin
           WriteLn('Error initializing help window: ', InitStatus);
           Halt;
         end;
         {Добавление некоторых особенностей}
         H^.AddTopicHeader(1, 60, heTC);
         H^.wFrame.AddHeader(' Topic Index ', heTC);
         H^.wFrame.AddScrollBar(frRR, 0, MaxLongInt, DefaultColorSet);
         H^.hwFrame.AddScrollBar(frRR, 0, MaxLongInt, DefaultColorSet);
         if Scrolling then
           {Горизонтальная линейка прокрутки только для
           прокручиваемого окна подсказки}
           H^.hwFrame.AddScrollBar(frBB, 0, MaxLongInt, DefaultColorSet);
        {Вывод на экран темы 1}
        H^.SetTopic(1);
        H^.Process;
        {Освобождение окна подсказки}
        Dispose(H, Done);
      end.

     В разделе объявления необходимо определить указатель на окно
     подсказки для объекта, который может быть инициализирован
     либо как постраничное, либо как прокручиваемое окно
     подсказки. Для определения структуры указанного файла
     используется ScrollingHelpFile. Если файл является
     прокручиваемым, вызывается конструктор ScrollingHelpWindow,
     в противном случае - PagedHelpWindow. Вызов New выделяет
     необходимое количество байт для каждого типа объекта. Если
     конструктор отработает успешно, возможности полиморфизма
     обеспечат использование одного указателя для постраничного
     или прокручиваемого окна подсказки, даже при видимом вызове
     одинаковых методов. Единственное место, где еще раз
     приходится проверять флаг прокрутки - это место, где
     происходит добавление горизонтальной линейки прокрутки, т.к
     PagedHelpWindow не нуждается и не поддерживает
     горизонтальную прокрутку.

Смотри также
     AbstractHelpWindow.InitDeluxe


     Н.Утилиты и примеры программ.
     ───────────────────────────────────────────────────────────

     В этой   главе  рассматриваются  три  программы:  MAKEMENU,
утилита,   позволяющая   в    интерактивном    режиме    строить
меню-системы;    PSCREEN,    резидентная    программа,   которая
"захватывает" экран, находящийся в текстовом режиме, и сохраняет
его   в  файле  на  диске;  и  WINWOW,  пример,  демонстрирующий
некоторые возможности, доступные через модуль OPWINDOW. Заметим,
что   MAKEHELP,  другая  утилита,  используемая  для  компиляции
текстов подсказки модуля OPHELP, уже обсуждалась в этой главе.

     1. MAKEMENU
     ───────────────────────────────────────────────────────────

     MAKEMENU - интерактивный генератор иерархических меню-систем.
Он поможет Вам визуально строить такие  системы,  быстро  и  легко
устанавливать  соответствующие  местоположения,  цвета  и  внешние
оформления, которые требовали более длительного времени при работе
с  временными  структурами.  После  того,  как  Вы  удовлетворены,
утилита  MAKEMENU  будет  записывать   поточную   библиотеку   или
генерировать исходный текст Паскаль-программы,  который может быть
объединен с Вашей собственной программой.
     Хотя Вы   можете   использовать    утилиту    OPMENU    без
возможностей, предоставляемых утилитой MAKEMENU,  и хотя утилита
MAKEMENU не дает доступа к  каждому  свойству  меню-объекта,  Вы
определенно захотите  изучить как использовать эту утилиту. Если
у Вас  есть  небольшой   опыт   работы,   Вы   вероятно   можете
использовать его даже не читая этой документации, но может быть,
Вы обнаружите,  что можете облегчить себе работу,  следуя данным
здесь рекомендациям. Если Вы уже работали с утилитой MAKEMENU из
Turbo Professional,  то эта новая версия покажется Вам знакомой;
но в  то  же  время,  она  содержит  новые свойства,  которые Вы
захотите проверить.
     Читая дальше, Вы обнаружите, что эту главу легче понять, если
Вы уже ознакомились с документацией по утилитам OPFRAME,  OPWINDOW
и OPMENU. В дальнейшем мы будем предполагать, что Вы уже знакомы с
окнами,  границами,  подменю, пунктами меню и так далее. Некоторое
знакомство  с  понятием  объектной  библиотеки  (реализованной   в
утилите OPROOT) также будет полезно.

     Начало
     ───────────────────────────────────────────────────────────
     Ознакомление с  утилитой  MAKEMENU мы начнем с рассмотрения
примера меню-системы,  которую мы приготовили для этой цели. Для
этого упражнения Вам необходимы два файла:  MM.EXE и SAMPLE.OPL.
Предполагая, что  оба  они  расположены  в  текущей  директории,
просто введите в командной строке DOS
     MAKEMENU
Вы увидите на экране что-то подобное:

╒═════════════ Object Professional Menu Maker 1.00 ════════════╕
│    Defaulrs     Submenu     Item      Object     Library     │
╘═══════════════════════════════════════════════╤════════════╤═╛
                                                │ Load   <F3>│
                                                │ New        │
╒══════════════════════  Load library ══════════╧════════════╧═╕
│ Filename [.OPL] : *.OPL                                      │
╘═══════════════════════════════════════════════╤════════════╤═╛
                                                │ Quit <AltX>│
                                                ╘════════════╛

     Пункт Load   подменю   Library  был  предопределен,  и  Вам
остается только ввести имя новый или уже существующей библиотеки
("OPL" означает  Object Professional Library).  В этой строке мы
можем написать "SAMPLE" -  расширение  "OPL"  предполагается  по
умолчанию, но   вместо   этого  давайте  просто  нажмем  клавишу
<Enter>. Тогда  на  экране  появится  список   всех   файлов   с
расширением "OPL"  из  текущей  директории.  Даже  если  у Вас в
текущей директории имеется несколько файлов с расширением "OPL",
Вы можете выбрать "SAMPLE.OPL", снова нажав клавишу <Enter>.
     Тогда на   экране   появится   список   всех   меню-систем,
определенных в файле SAMPLE.OPL.  В файле также могут находиться
бибилиотечные объекты других типов,  как в нашем случае,  но  Вы
увидите  на  экране  только  имена меню-систем.  Список выглядит
примерно так:

╒═══════════════════════╕
│  Name           Size  │
├───────────────────────┤
│  MENU1          1158  │
│---------- NEW --------│
╘═══════════════════════╛

     В этом  случае  у  Вас  есть  две  возможности  продолжения
работы. Вы можете создать новую меню-систему,  выбрав "New", или
загрузить существуюший объект "MENU1". Для работы с существующим
объектом нажмите  клавишу  <Enter>.  Когда Вы выберите из списка
MENU1, объект появится на вершине экрана с падающим меню под ним
(по умолчанию  фон  падающего  меню  - точечный) и меню-системой
утилиты MAKEMENU сверху.  Чтобы покинуть меню-систему MAKEMENU и
войти в режим Тестирования, нажмите клавишу <F10>. Нажав еще раз
клавишу <Enter>, Вы увидите на экране

╒══════════════════════  Main Menu ════════════════════════════╕
│  File           Options                                      │
╘═╤═══════╤════════════════════════════════════════════════════╛
  │ Load  │
  │ Store │
  ├───────┤
  │ Quit  │
  └───────┘

     В этом         примере          меню-система          имеет
горизонтально-ориентированной верхний   уровень   меню  с  двумя
пунктами; каждый  пункт  меню  верхнего  уровня  имеет  падающее
подменю. На рисунке видно,  что подменю 'File' имеет три пункта.
Пункт 'Options'имеет другие  два  пункта  меню,  которые  нельзя
увидеть до тех пор, пока подменю не станет активным.
     В нижней части экрана имеется строка,  напоминающая Вам как
вернуться назад к главному меню или выйти из MAKEMENU.

     Вы можете  использовать клавиши управления курсором, <Esc>,
<Enter> для просмотра меню-системы.  Нажатие <F10> вернет Вас  к
главному меню.  Также Вы можете обнаружить, что нажатиие клавиши
<Esc>  на верхнем уровне меню нашего примера или клавиши <Enter>
на любом пункте,  которое не имеет подменю, будет возвращать Вас
к главному меню.
     Режим Тестирования дает Вам возможность испытать Вашу меню-
систему и определить:  как она будет работать при внедрении ее в
Вашу собственную   программу.   Также   он   предоставляет   Вам
возможность определить местоположение высвеченной полоски внутри
частного   подменю  на  определенном  пункте  -  MAKEMENU  будет
использовать это   местоположение  для  определения  содержимого
Ваших  команд,  которые  Вы  задаете   при   модификации   Вашей
меню-системы.
     Теперь мы  готовы,  чтобы   попытаться   немного   изменить
имеющуюся  меню-систему.  Для  начала пролистайте меню до пункта
File-Store (Файл-Сохранить) и нажмите клавишу <F10>.  На  экране
вновь появится меню система утилиты MAKEMENU.
     Предположим Вы  хотите  изменить  имя  пункта  'Store'   на
'Save'. Для      этого      выберите      команду      Item-Edit
(Пункт-Редактировать). Так   как   высвеченная   полоска    была
установлена на пункт 'Store',  то система знает какой пункт меню
необходимо редактировать,  поэтому  на  экране   появится   окно
запроса с   напечатанным   в   нем  'Store'.  Используя  клавишу
'BackSpase', удалите  имя  'Store',  вместо   него   напечатайте
'Save' и нажмите <Enter>.  Меню будет обновлено, и все изменения
сразу появятся на экране.
     Заметим, что  если у Вас имеется Мышь,  совместимая с Мышью
фирмы MicroSoft,  то Вы можете  использовать  ее  для  работы  с
MAKEMENU. Нажатие левой кнопка Мыши эквивалентно нажатию клавиши
<Enter>, а правая кнопка Мыши эквивалентна <Esc>.  Нажатие обеих
кнопок Мыши  одновременно  есть  то  же,  что  и  нажатие <F10>.
Передвигая Мышь,  Вы можете выбирать пункты  меню  MAKEMENU  или
Вашего спроектированного  меню  (если только Вы не заблокировали
работу с Мышью).  Мышь может также перемещать  меню  или  пункты
меню по экрану - что она делает будет понятно и очевидно для Вас
при ее использовании.
     Теперь, когда  Вы заменили 'Store' на 'Save',  Вы заметили,
что подменю  имеют большое пустое пространство с правой стороны.
Давайте используем  MAKEMENU,  чтобы  устранить  этот  небольшой
недостаток,   выбрав  подменю  Submenu-Resize  (Подменю-Изменить
размер). Главное меню исчезнет, оставив мигающий курсор в нижнем
 правом углу   примера.  Нажмите  клавишу  <стрелка  влево>  для
уменьшения размеров меню,  а затем  -  <Enter>  для  запоминания
результата.
     К настоящему   моменту   Вы   заметили,   что  все  подменю
меню-системы имеют  падающие  тени.   MAKEMENU   позволяет   Вам
использовать различные   специальные   эффекты,  как  тени,  для
каждого меню в отдельности или для  всех  одновременно.  Давайте
рассмотрим  различные  возможности  изменения теней.  Во-первых,
выберем         команду         Submenu-Settings-Effects-Shadows
(ПодменюУстановки-Эффекты-Тени).    Это   меню   позволяет   Вам
переключаться между тремя состояниями:  None  (нет  теней),  Big
(большие  тени),  Small (малые тени).  Повторное нажатие клавиши
<Enter> дает  возможность  увидеть  разницу  между  состояниями.
Остановитесь  при  вторичном  получении состояния 'Big'.  Как Вы
видели,  команды Submenu-Settings (Подменю-Установки)  применимы
только      к      текущим      подменю.     Теперь     выберите
Defaults-Effects-Shadows (По умолчанию-Эффекты-Тени)  и  нажмите
<Enter>. Меню MAKEMENU будет выглядеть следующим образом:

╒═════════════ Object Professional Menu Maker 1.00 ════════════╕
│    Defaulrs     Submenu     Item      Object     Library     │
╘═╤═════════════╤══════════════════════════════════════════════╛
  │ Backdrop    │
  │ Border      │
  │ Colors      │     ╒═════════════════════════════╕
  │ ╒═══════════╧═════╡ Apply changes globally? [N] │
  │ │ Delay       0   ╘═╤═══════════════════════════╛
  │ │ Explosions  No    │
  │ │ Shadows     Small │
  │ │ Sound       No    │
  ╘═╡ Left select    '' │
    │ Right select   '' │
    ╘═══════════════════╛

     Если в  ответ  на  запрос вы введете <Y>,  то система будет
изменять у каждого подменю примера тени на малые. В нашем случае
давайте поступим  как описано выше и нажмем клавишу <Enter>.  Вы
увидите, что и верхнее меню и подменю изменились.  То  же  самое
произошло и с другими подменю, хотя Вы не увидите их до тех пор,
пока не выберите эти  подменю.  Способность  MAKEMENU  выполнять
глобальные обновления,  подобно как  мы  только  что  произвели,
является  очень  мощным  средством,  но  Вы  должны  быть  очень
внимательны при ее использовании,  так как не существует команды
отмены,   за  исключением, как  вновь  считать  меню-систему  из
библиотеки.
     Если вместо <Y> мы нажали бы <Enter> или <N>, то не увидели
бы никаких  изменений.  В  этом  случае  изменились  бы   только
значения, установленные  по  умолчанию:  так если бы мы добавили
новое подменю,  то у него была бы  малая  тень.  Такое  различие
между глобальными  обновлениями и значениями,  установленными по
умолчанию, применяется к большинству пунктов подменю Defaults.
     Все эти    изменения    мы    собираемся   произвести   над
этой меню-системой.  Мы могли бы сохранить ее под старым именем,
просто нажав <Enter>,  но Вы должно быть захотите повторить этот
урок, поэтому  давайте  сохраним  ее  неизменной.  А  измененной
системе дадим новое имя, выбрав команду Object-Save. В запрос на
имя, введите 'MENU2'.  Вы увидите на экране сообщение о том, что
объект был сохранен.
     Мы не полностью  проработали  пример,  так  как  ничего  не
сделали, чтобы  использовать  наш  пример в программе.  Выберите
команду Object-Write   (Объект-Записать)    для    генерирования
исходного текста. Затем Вы увидите окно, запрашивающее у Вас имя
файла:
     Name of source file [.PAS] : MENU2.PAS
     (Имя исходного файла)

     Для выбора  ответа  по  умолчанию  нажмите  <Enter>.  Через
несколько секунд   Вы   увидите   сообщение,    что    программа
сгенерирована. Результат  - готовая к обработке программа. Чтобы
проверить как она  работает,  нажмите  <Alt  X>  для  выхода  из
системы MAKEMENU,  затем  используйте компилятор (TURBO или TPC,
последний предпочтительнее) для получения EXE  файла.  Выполните
файл MENU2.EXE  и Вы увидите на экране нашу меню-систему (только
на черном фоне), из которой Вы можете сделать выбор для возврата
к DOS. Вероятно вы захотите взглянуть на исходный текст, который
был сгенерирован,  но в настоящий  момент  это  недоступно  Вам.
Более подробно о получении исходного текста мы поговорим позднее.

     Ваша Первая Меню-система
     ───────────────────────────────────────────────────────────
     Как Вы    видели,   модифицировать   существующую   систему
достаточно легко.  Но  и  создание  новой  системы  не   намного
сложнее, этим мы и займемся в настоящей главе.
     Первый шаг  -  загрузка  библиотеки.  Мы  уже  изучили  как
загрузить существующую  библиотеку,  поэтому  на сей раз давайте
создадим новую. В начале работы, когда система запрашивает у Вас
имя библиотеки, не  нажимайте <Enter>,  иначе Вы получите список
директорий. Вместо этого  введите  новое  имя,  скажем  'MyLib'.
Конечно, MAKEMENU не сможет найти файл 'MyLib.OPL' и спросит Вас:
не хотите ли создать новую библиотеку.  Нажмите <Enter> или <Y>.
Затем Вас  спросят о количестве входных директорий в библиотеке.
Эта величина определяет как много  объектов  может  храниться  в
библиотеке. Чтобы установить значение 15, принятое по умолчанию,
нажмите <Enter>.  Как  и  ранее  Вы  увидите  на  экране  список
меню-систем для  загрузки.  Однако  к этому моменту список будет
пуст, и Вы можете  лишь  выйти  из  системы,  нажав  <Esc>,  или
указать, что  создаете  новую  библиотеку,  нажав  <Enter>.  При
нажатиии клавиши   <Enter>   появится   запрос    имени    Вашей
меню-системы. Будьте  здесь  внимательны.  Хотя  Вам разрешается
вводить строку длиной до 12 символов,  наверное,  Вы никогда  не
захотите определить строку такой длины. Имя, определенное здесь,
в дальнейшем будет использовано  как  имя  вашей  программы  при
генерации исходного текста,  поэтому  правильнее  ввести  строку
длиной не более 8 символов, что будет разумно как для DOS, так и
для компилятора.
     После того,  как вы ввели имя, Вы увидите пустое окно рядом
с левым  углом,  ожидающее  введения  пунктов меню.  В настоящий
момент Вам не нужно заботиться о размерах окна, так как MAKEMENU
будет автоматически  расширять  его при добавлении новых пунктов
меню. Вы можете передвинуть  пункт  или  изменить  размеры  окна
немного позднее.
     Для начала давайте создадим несколько  пунктов  на  верхнем
уровне меню. Из меню MAKEMENU выберите Item-Add (Пункт-Добавить)
и в ответ на запрос  введите  имя  'Ledger'.  Нет  необходимости
заключать имя в апострофы; они используются только для выделения
строки в  этом  руководстве.   Вы   увидите,   что   Ваше   меню
увеличилось, чтобы охватить имя вновь созданного пункта, которое
теперь высвечивается как текущий пункт меню.
     Если Вы  планируете  сгенерировать исходный текст для этого
меню - что неплохо в начале работы - выберите  теперь Item-Name,
чтобы сопоставить   пункту   меню   паскалевскую  константу.  Вы
увидите, что MAKEMENU дает ей по умолчанию имя  'miLedger'.  Оно
получено конкатенацией  строк  'mi'(от mENU iTEM),  имени Вашего
пункта и числового ключа  пункта,  который  для  первого  пункта
равен 1.  Если  Вы можете гарантировать,  что в меню системы
будет только один пункт 'Ledger' (как в нашем случае),  то лучше
подобрать имя  константы,  которое  не  включает  действительный
номер пункта.  Таким образом когда Вы внесете имена  констант  в
Вашу программу,  а  затем  внесете  изменения  в  меню-систему и
измените номера  пунктов,  то  Вашей  программе  не  потребуются
никакие изменения. В нашем случае измените имя на 'miLedger'.
     Давайте добавим еще два пункта к меню верхнего уровня:
Item-Add'Receivables' (Пункт-Добавить'Receivables')            и
Item-Add'System'(Пункт-Добавить'System). Теперь у нас три пункта
меню на  верхнем  уровне,  а  меню увеличилось почти до размеров
половины ширины экрана.  Последний  обновленный  пункт  'System'
высвечивается как текущий.
     В этой программе мы хотим переместить пункт меню 'System' в
правый конец  экрана  и увеличить верхний уровень меню на полную
ширину экрана.   Для   достижения   этого   выберите   Item-Move
(Пункт-Передвинуть) и,   используя   клавишу  <стрелка  вправо>,
переместите пункт  'System'   как   можно   дальше.   Меню   при
перемещении пункта  будет растягиваться.  Перед нажатием <Enter>
для запоминания такого расположения,  передвиньте пункт влево на
10 столбцов.  Мы  хотим  оставить  место  под  этим  пунктом для
падающего подменю.
     Пункт 'System'  есть  логически  нечто  отличное  от других
пунктов меню верхнего уровня,  поэтому давайте  отделим  его  от
остальных разделителем  -  вертикальной  полоской,  состоящей из
зарисованных линий.  Для получения  разделителя  выберите  пункт
Submenu-Settings-Spans-Add
(Подменю-Установки-Разделители-Добавить). По  умолчанию MAKEMENU
выберет зарисованные  линии  (позднее,  по  желанию  Вы  сможете
изменить их)   и   разместит   их  справа  от  текущего  пункта.
Используйте   клавишу   <стрелка   влево>,   чтобы   передвинуть
разделитель    левее   пункта   'System'   и   для   запоминания
местоположения нажмите <Enter>.
     Давайте также воспользуемся возможностью добавить заголовок
к верхнему уровню меню. Выберите Submenu-Settings-Header-Add
(Подменю-Установки-Заголовок-Добавить). Другое    меню     будет
демонстрировать возможное  размещение заголовка.  Выберите пункт
'Top Left' и в ответ на запрос заголовка введите  строку 'Object
Accounting 1.0'.   Появившийся   заголовок   будет  иметь  цвет,
установленный для заголовков по умолчанию.
     Итак, верхний   уровень   меню  имеет  нормальный  вид.  По
необходимости в любое время мы сможем вернуться для модификации.
Теперь давайте  создадим  вложенное  подменю  к текущему пункту,
которым остается  'System'.  Для  этого   выберите   Submenu-Add
(Подменю-Добавить). Ниже  пункта  сразу появится пустое подменю.
Перед внесением пунктов в это подменю давайте  сначала установим
его характеристики.
     Во-первых, мы хотим,  чтобы подменю имело границу,  которая
сливалась бы с верхним уровнем меню. Для установки такой границы
выберите команду                         Submenu-Settings-Border
(Подменю-Установки-Граница). Появится  другое  меню  со  списком
возможных границ.  Выберите одну по Вашему усмотрению  (в  нашем
случае нас устраивает восьмой пункт) и нажмите <Enter>.
     Во-вторых, мы  хотим  использовать  различные   цвета   для
невыбранных пунктов               подменю.              Выберете
Submenu-Settings-Colors-Text для   изменения   частного    цвета
пункта. Вы увидите

╒═════════════ Color ═════════════╕
│                                 │
│  *   *   *   *   *   *   *   *  │
│                                 │
│  *   *   *   *   *   *   *   *  │
│    ┌───┐                        │
│  * │ * │ *   *   *   *   *   *  │
│    └───┘                        │
│  *   *   *   *   *   *   *   *  │
│                                 │
│  *   *   *   *   *   *   *   *  │
│                                 │
│  *   *   *   *   *   *   *   *  │
│                                 │
│  *   *   *   *   *   *   *   *  │
│                                 │
│  *   *   *   *   *   *   *   *  │
│                                 │
│  *   *   *   *   *   *   *   *  │
│                                 │
│  *   *   *   *   *   *   *   *  │
│                                 │
│  *   *   *   *   *   *   *   *  │
│                                 │
│  *   *   *   *   *   *   *   *  │
│                                 │
│  *   *   *   *   *   *   *   *  │
│                                 │
│  *   *   *   *   *   *   *   *  │
│                                 │
│  *   *   *   *   *   *   *   *  │
│                                 │
│  *   *   *   *   *   *   *   *  │
│                                 │
│                                 │
╘═════════════════════════════════╛

     Используя клавиши    управления    курсором,    передвиньте
маленькую рамку в середину того же столбца.  Значение  в  нижней
части границы   будет  18  (в  шестнадцатиричном  формате),  что
соответствует темно-серому цвету на  синем  фоне.  Этот  атрибут
будет использоваться при работе с системой, поддерживающей цвет.
Для запоминания атрибута нажмите <Enter>.  Затем  Вам  предложат
выбрать атрибут для монохромной системы (наверху экрана появится
указатель 'MONO').  В  этом  случае   нажмите   <Enter>,   чтобы
установить атрибут, принятый по умолчанию, так как в монохромном
режиме нет больших возможностей для вариаций.  В цветной системе
центр нового   подменю  изменит  цвет  в  соответствии  с  новым
атрибутом.
     В-третьих, мы  хотим,  чтобы  падающее  подменю высвечивало
свои пункты в вертикальном формате.  Так как по умолчанию принят
горизонтальный формат,   мы   хотели   изменить   это   подменю,
переключив                          Submenu-Settings-Orientation
(Подменю-Установки-Направление) с состояния 'H' на 'V'.
     Есть множество  других  возможностей,  которые   мы   можем
установить  в  данный  момент  -  тени,  выбор  цветовой  гаммы,
символов -  но  давайте  продолжим  добавлять  пункты  к  новому
подменю.
     Выберите Item-Add  (Пункт-Добавить)  и введите 'DOS Shell'.
Сопоставьте пункту константу,  выбрав  Item-Name  (Пункт-Имя)  и
напечатайте 'miDosShell'.  Повторите  эти  шаги,  чтобы добавить
пункт 'Quit'.
     Теперь мы  имеем  достаточное  количество пунктов.  Давайте
протестируем систему.  Для передачи управления  от  меню-системы
MAKEMENU  Вашей   системе  нажмите  клавишу  <F10>  (или  при
использовании Мыши нажмите обе кнопки одновременно).  Когда Ваша
система впервые  получила  управление,  последний Вами созданный
пункт 'Quit', будет текущим. Попытайтесь передвинуть высвеченную
полоску к  'Ledger',  'Receivables' и снова к 'Quit',  используя
клавишу <стрелка влево>.
     Что?! Когда  Вы  вернулись  к 'Quit',  подменю этого пункта
больше не появилось,  а вместо него  Вы  получили  'System'?  Не
беспокойтесь; MAKEMENU имеет средства, которые контролируют такое
поведение  системы.  Для проверки,  во-первых,  нажмите <F10> для
передачи управления снова меню MAKEMЕNU,  затем выберите Defaults
-Toggles-Remember (По умолчанию-Переключатели-Запомнить).  Теперь
снова протестируйте  Вашу  меню-систему.  Вы  увидите,  что  Ваша
система "запоминает", что Вы выдвигали подменю.
     Осталось сделать только два шага.  Во-первых, нажмите <F2>,
чтобы сохранить  систему,  которую  Вы  только  что  создали (Вы
можете сделать это во время отладки Вашей  меню-системы  или  во
время работы с меню MAKEMENU). Во-вторых, войдите в главное меню
и выберите  Object-Write  (Объект-Записать)  для   генерирования
исходного текста.
     Вот и все.  Вы закончили Вашу  первую  меню-систему,  а  мы
закончили наше небольшое обучение.  Есть несколько других команд
и меню выбора,  которые Вам конечно необходимо  изучить,  однако
основной этап  ознакомления  у Вас позади. Накопив небольшой опыт
работы и  прочитав  оставшуюся  часть  этой  главы,  Вы  сможете
изучить  как использовать другие свойства программы в применении
к Вашей собственной программе.

     Меню-система MAKEMENU
     ───────────────────────────────────────────────────────────

     Все возможности MAKEMENU доступны через  ее  систему  меню.
Многие  команды  имеют  также  управляющие  клавиши,  так что Вы
можете сэкономить время,  однажды ознакомившись с сиcтемой.  Эта
глава  является  кратким обзором всех возможностей меню-системы.
Если есть управляющая клавиша, связанная с определенным пунктом,
то она высвечивается справа от имени пункта меню.
     Заметим, что  если  объект загружен,  то <F10> работает как
переключатель, который передает управление  между  меню-системой
MAKEMENU и  меню  Вашей  собственной  системы.  Клавиши  <Esc> и
<правая кнопка> Мыши работают также,  но  сначала  они  пытаются
подняться на  один  уровень  вверх  по  иерархии меню;  только в
случае, если активным является самое верхнее меню  они  передают
управление другому  меню.  Также  заметим,  что  если у Вас есть
Мышь, то одновременное нажатие обеих кнопок эквивалентно нажатию
<F10>.

     Defaults (значения по умолчанию)
     ───────────────────────────────────────────────────────────

     Установки, принятые для этого пункта, применяются для Вашей
системы в целом.  Изменение  значений,  принятых  по  умолчанию,
имеет   две   возможности.   Во-первых,  изменяемые  значения  в
дальнейшем применяются для всех подменю и  пунктов,  которые  Вы
создаете  во  время сеанса работы с MAKEMENU.  Во-вторых,  после
того,  как  Вы  сделали  изменения,  когда  это   имеет   смысл,
появляется окно запроса  "Apply  changes  globally?"  (Выполнять
изменения глобально?).   Если   Вы   отвечаете   "Y",  то  после
Ваших модификаций MAKEMENU изменяет все подменю/пункты меню.
     Система показывает значение,  установленное  по  умолчанию,
справа от большинства пунктов. Когда Вы впервые начинаете работу
с MAKEMENU,  она использует значения по умолчанию, установленные
производителем  системы.  Когда  Вы считываете меню существующей
системы,  MAKEMENU  устанавливает  значения   по   умолчанию   в
соответствии   с  установками  меню  верхнего  уровня  считанной
системы.  При  создании  новой  системы  значения  по  умолчанию
сохраняют свои предыдущие значения.


Backdrop (фон падающего меню)

Позволяет выбирать один из трех типов фона:  точечный, абсолютно
черный, заштрихованный.


Border (граница)

Выбирает границу окна. Верхняя часть списка выбора демонстрирует
пример, как будет появляться граница.


Сolors (цвета)

Эти меню   позволяют  устанавливать  различные  видео  атрибуты.
Список  ниже   содержит   имена   всех   вариантов   выбора,   с
соответствующими  полями  из  ColorSet (смотрите документацию по
утилите OPCRT):

     Text                  TextColor                TextMono
     Border                BorderColor              BorderMono
     Header                HeaderColor              HeaderMono
     Shadow                ShadowColor              ShadowMono
     Highlight character   HighItemColor            HighItemMono
     Selected item         SelItemColor             SelItemMono
     Protected item        ProItemColor             ProItemMono
     Mouse cursor          MouseColor               MouseMono
     Helpline              (хранится только в Menu object)


Эффекты

     Delay (задержка)

     Запрос на   задержку   (в   миллисекундах)   между   каждым
     состоянием.


     Explosions (раскрытие)

     Переключение между раскрывающимися и нераскрывающимися окнами.


     Shadows (тени)

     Переключение между большими, маленькими тенями и состоянием
     без теней.


     Sound (звук)

     Включение и выключение звуковых эффектов. Имеет значения On
     (включить звук во время раскрытия окон) и  Off (выключить
     звук).


     Left select (выбор левого символа)

     Запрос символа,  который   будет   появляться   слева   от
     выбранного пункта  меню.  Для  выбора  высвечивается полный
     набор ASCII символов; #0 означает отсутствие символа.


     Right select (выбор правого символа)

     Запрос символа,  который   будет   появляться   справа   от
     выбранного пункта меню.


Help  (подсказка)

     Active (активна)

     Переключение между двумя  состояниями:  высвечивать  строку
     подсказки или  нет.  Текст  подсказки  для  каждого  пункта
     вводится командой   Item-Help    (Пункт-Подсказка).    Если
     подсказка активна,  то  MAKEMENU  генерирует исходный текст
     процедуры текущего пункта,  которая выводит на экран строку
     подсказки.


     Row (строка)

     Запрос номера  строки,  в  которой  будет выводиться строка
     подсказки. В MakeMenu для подсказки  зарезервирована полная
     строка. Вы  можете  изменить сгенерированный исходный текст
     для показа подсказки в окне с  рамкой  или  создать  другие
     обычные эффекты.


Orientation (ориентация)

     Переключение между    горизонтальным     и     вертикальным
     типами размещения  пунктов меню.


Source (исходный текст)

     Color constants (константы цвета)

     Значение этой  функции  влияет  на  генерирование  исходного
     текста.  Если  оно  есть  On  ('Y'),  то  все видео атрибуты
     представляются в виде имен констант,  определенных в OPCOLOR
     (например,  'WhiteOnBlack'),  и  в  списке USES используется
     OPCOLOR.  Если же значение есть Off ('No'),  то используются
     шестнадцатиричные константы (такие как $0F).


     User proc hooks (пользовательские процедуры)

     Эта функции определяет будет или нет  сгенерированный  текст
     программы     включать    оболочки    процедур,    созданных
     пользователем,  таких  как  изменение  строк  пунктов  меню,
     обработка ошибок, контекстно-зависимая подсказка.


     Case statement (команда Case)

     Эта функция определяет будет или нет  сгенерированный  текст
     включать  команду  Case  для  обработки  управляющих клавиш,
     которые   могут   быть   получены   как   результат   вызова
     Menu.Process.


     String constants (строковые константы)

     Если эта функция  запрещена,  то  сгенерированная  программа
     считает все строковы имена пунктов и строки текста подсказки
     типизированными  константами  и  будет  использовать  скорее
     AddItemPtr    (и    AddItemHelpPtr)    нежели   AddItem   (и
     AddItemHelp).   Такой   подход    уменьшает    использование
     программой динамической памяти за счет исходного текста, что
     приводит к небольшим затруднениям при чтении и модификациях.


Toggles (переключение)

Это меню позволяет  Вам  делать  активными/неактивными  различные
параметры  пунктов меню.  Список,  представленный ниже,  содержит
имена вариантов вместе с соответствующей функцией меню(  смотрите
раздел  OPMENU,  ранее  описанный  в этой главе).  Поддержка Мыши
влияет на получение исходного текста,  но не оказывает  реального
влияния на сам объект.
     Arrow pull down              mnArrowSelect
     Character match              mnAlphaMatch
     Character select             mnSelectMatch
     Erase safter select          mnPopOnSelect
     Item key help topic          mnUseItemForTopic
     Mouse support                mnMouseSupport
     Remember pulldown            mnAllowPending
     Select on click              mnSelectClick

     Submenu
     ────────────────────────────────────────────────────────────────

Add (добавить)

     Добавляет вложенное  подменю  к  текущему пункту меню.  Для
одного пункта меню Вы можете сделать это только один  раз. После
того, как  Вы создали подменю,  MAKEMENU рисует маленькую рамку,
которая указывает,  где появится Ваше подменю (для  подменю  без
границы рамка  будет невидимой,  если Вы используете одноцветный
фон и черный цвет для текста меню).  Подменю будет автоматически
увеличиваться при  внесении в него новых пунктов,  или Вы можете
изменить размер вручную, используя команду Submenu-Resize.


Drag (изменить положение)

     Изменение положения  текущего  подменю  и любого вложенного
под ним подменю.  Вы не увидите явного  передвижения  вложенного
подменю, но  в  следующий  раз,  когда Вы обратитесь к нему,  то
увидите разницу.
     Для передвижения  подменю  доступны следующие команды.  Для
указания того, что подменю передвигается (а не изменяется размер
подменю),  курсор размещается в левом верхнем углу. Заметим, что
если Вы используете Мышь,  курсор можно  передвигать  с  помощью
Мыши.
     <Left>, <CtrlS>
     Курсор влево на один столбец.

     <Right>, <CtrlD>
     Курсор вправо на один столбец.

     <Up>, <CtrlE>, <CtrlW>
     Курсор вверх на один ряд.

     <Down>, <CtrlX>, <CtrlZ>
     Курсор вниз на одну строку.

     <Home>, <CtrlQ> <S>
     Курсор на крайнюю левую позицию.

     <End>, <CtrlQ> <D>
     Курсор на крайнюю правую позицию.

     <ShiftTab>, <CtrlLeft>, <CtrlA>
     Курсор в   предыдущую   горизонтальную   позицию  табуляции
     (каждые 8 столбцов).

     <Tab>, <CtrlRight>, <CtrlF>
     Курсор в следующую горизонтальную позицию табуляции.

     <PgUp>, <CtrlR>
     Курсор в предыдущую вертикальную позицию  табуляции (каждые
     5 строк).

     <PgDn>, <CtrlC>
     Курсор в следующую вертикальную позицию табуляции.

     <CtrlHome>, <CtrlPgUp>, <CtrlQ> <E>, <CtrlQ> <R>
     Курсор в самую верхнюю строку.

     <CtrlEnd>, <CtrlPgDn>, <CtrlQ> <C>, <CtrlQ> <X>
     Курсор в самую нижнюю строку.

     <AltH>
     Центрирование строки по горизонтали.

     <AltV>
     Центрирование строки по вертикали.

     <AltC>
     Центрирование строки как по вертикали, так и по горизонтали.

     <Enter>, <ClickLeft>
     Запомнить размер/положение.

     <Esc>, <ClickRight>
     Отмена изменений (не разрешается для Drag).


Move  (передвинуть)                  <AltM>

Изменение расположения  текущего  подменю  без  передвижения его
"потомков". Команды управления курсором те же, что и для команды
Drag.


Resize (изменить размер)             <AltR>

Изменение размера текущего подменю. Число и длина строк текущего
пункта меню имеют  минимальный  доступный  для  подменю  размер.
Команды управления курсором, показаны в списке команды Drag.


Settings (установки)

Эти установки применимы только для текущего подменю и его списка
пунктов.  Чтобы получить глобальные изменения,  смотрите команду
Defaults.


     Border (граница)

     Выбор границы окна.


     Colors (цвета)

     Это меню позволяет Вам выбирать различные  видео  атрибуты.
     Список цветов тот же, что и для Defaults-Colors.


     Effects (эффекты)

     Это меню  позволяет Вам изменить различные эффекты.  Список
     тот же,  что  и для Defaults-Effects,  за исключением,  что
     добавлена возможность  заполнения  пробелами   -   Padding,
     которая запрашивает   число   пробелов,   используемых  для
     отделения имен пунктов.


     Headers (заголовки)

       Add (добавить)

       Высвечивает подменю,  показывающее  6  возможных  позиций
       заголовка.  Как  только  Вы  выбрали   месторасположение,
       появляется  запрос  содержимого  заголовка,  а  затем Вам
       предоставляется возможность выбора цвета.


       Edit (редактировать)

       Появляется список  существующих  заголовков.  Передвиньте
       курсор к заголовку,  который Вы  хотите  редактировать  и
       нажмите  клавишу  <Enter>.  Вы  можете изменить как текст
       заголовка, так и цвета.


       Remove (удалить)

       Появляется список  существующих  заголовков.  Передвиньте
       курсор к заголовку,  который Вы хотите удалить и  нажмите
       <Enter>.



     Orientation (ориентация)

     Изменяет ориентацию текущего подменю.  Заметим, что граница
     окна будет иметь размеры в соответствии с его пунктами.


     Spans (разделители)

       Add (добавить)

       Определяет символы  разделителя  в  соответствии с рамкой
       окна и по умолчанию размещает разделитель после  текущего
       пункта   меню.   Используйте   управляющие   клавиши  для
       размещения разделителя и нажмите <Enter>.


       Edit (редактировать)

       Показывает список существующих разделителей.  Передвиньте
       курсор к разделителю,  который Вы хотите редактировать  и
       нажмите <Enter>. Используйте клавиши управления стрелками
       для изменения положения  разделителя  и  нажмите  клавишу
       <Enter>.  Выберите множество новых символов разделителя и
       новые видео атрибуты из таблицы цветов.


       Remove (удалить)

       Показывает список существующих разделителей.  Передвиньте
       курсор и нажмите клавишу <Enter>.


Kill (уничтожить)

Уничтожает текущее  подменю,  его  пункты  и все вложенные с ним
подменю. Вам  предоставляется  возможность  подтверждения   этой
операции.

     Item (пункт)
     ───────────────────────────────────────────────────────────

Name (имя)

Запрос символического  имени,  которое  будет  использоваться для
ссылки  на  это  пункт   меню.   Имя   должно   быть   допустимым
идентификатором  Паскаля  (MAKEMENU  проверяет  это) и оно должно
быть уникальным (MAKEMENU это не проверяет).  Ввод имени является
необязательным.  Если Вы не определили имя,  то в сгенерированной
программе этот пункт будет фигурировать под именем  'miXxxxxNnn',
где  'Xxxxx'  заменяет 10 допустимых символов строки высвеченного
пункта, 'Nnn' - номер ключа пункта.


Edit (редактировать)

Редактирование высвеченной строки текущего пункта меню.


Key (ключ)

Изменить ключ   текущего    меню.    MAKEMENU    последовательно
присваивает ключи  пунктам  меню по мере добавления пунктов и по
требованию будет     перенумеровывать      пункты      (смотрите
Object-Rekey). Номер  справа  от  Key  есть ключ текущего пункта
меню.


Select char (выбрать символ)

Выбор различных  символов  для текущего пункта меню.  Используйте
клавиши управления курсором  или  Мышь  для  изменения  положения
высвеченного символа.  Передвиньте курсор влево,  чтобы запретить
выбор пункта по символу.


Help text  (текст подсказки)

Присвоить текст   подсказки   текущему  пункту.  MAKEMENU  будет
запрашивать новый   текст   или   позволит   Вам   редактировать
существующий. Текст подсказки будет появляться на экране только,
если Вы     установили      соответствующее      значение      в
Defaults-Help-Active.


Move (передвинуть)

Изменение позиции  текущего  пункта  меню.  Используйте  клавиши
управления стрелками и нажмите клавишу <Enter>,  чтобы запомнить
изменения. Позиция любого подменю, связанного с текущим пунктом,
не изменяется.
     Заметим, что  Move  не  изменяет  порядок связанного списка
пунктов, поэтому  ошибочно  передвигать  пункт,   предыдущий   к
окружающим его  пунктам.  Если  Ваше  намерение  как сделать это
неизменно, используйте команду Reorder (переупорядочить).


Reorder (переупорядочить)

Определить относительную  позицию  текущего  пункта  в   связном
списке пунктов.


Drag (изменить положение)

Одновременно установить местоположение всех пунктов меню.


Kill (уничтожить)

Уничтожить текущий  пункт.  Если он имеет подменю,  Вас попросят
подтвердить Ваши действия,  так как все вложенные подменю  будут
также уничтожены.

     Object (объект)
     ───────────────────────────────────────────────────────────

Load (загрузить)

Загрузить существующую  меню-систему  из библиотеки или создать
новую.


Save (сохранить)                             <F2>

Сохранить текущую меню-систему.


Rename  (переименовать)

Изменить имя текущей меню-системы.


Save as (сохранить как)

Сохранить текущую меню-систему под новым именем.


Info (информация)                              <AltI>

Показать информацию  о  созданном  объекте.  Заметим,  что  если
объект не загружен,  то будет высвечиваться информация о текущей
библиотеке (смотрите ниже Library-Info).


Test (тест)                                   <F10>

Тестировать спроектированную меню-систему.


Write source (записать исходный текст)

Сгенерировать исходный текст для текущей меню-системы.


Document (документ)

Создать документ для текущей меню-системы.


Rekey (изменить ключ)

Присвоить новые значения ключей всем пунктам меню,  начиная с 1,
и последовательно двигаясь слева направо, увеличивать на 1.


     Library (библиотека)
     ───────────────────────────────────────────────────────────

Load (загрузить)                              <F3>

Загрузить новую или существующую библиотеку. Если указанный файл
не существует, Вас спросят не хотите ли создать новую.


New (создать)

Создать новую библиотеку.  Если указанный файл  уже  существует,
Вас спросят не хотите ли Вы переписать его.


Delete (уничтожить)

Высвечивается список  всех объектов библиотеки.  Нажмите клавишу
<Enter>,  чтобы пометить объект на удаление (метка появится  вне
имени) или удалить существующую метку.  Нажмите клавишу <Enter>,
когда  Вы  закончили  маркировку  имен  объектов.  Заметим,  что
объекты  физически  не будут удаляться из библиотеки до тех пор,
пока они упакованы.


Info (информация)                        <AltI>

Показать информацию о текущей библиотеке.  Заметим,  что  <AltI>
будет выполнять эту команду только в том случае,  если объект не
загружен; в противном случае будет показана информация о текущем
объекте (смотрите Object-Info).


Pack (упаковать)

Если необходимо,  упаковать текущую библиотеку. Упаковка очищает
библиотеку от старых версий объекта и от объектов, помеченных на
удаление.


Quit (выход)

Выход из программы.


     Генерирование исходного текста
     ───────────────────────────────────────────────────────────

     Как мы видели, получить исходный текст достаточно легко. Вы
просто выбираете соответствующий пункт меню и вводите имя файла,
в  который  будет  записан  полученный текст.  Если файл с таким
именем уже существует,  Вас спросят не хотите ли  Вы  переписать
его. Будьте   внимательны  в  этом  случае.  Вы  же  не  желаете
переписывать "реальную" программу с таким  же  именем.  По  этой
причине  разумно  давать  Вашему  меню  имя,  отличное  от имени
программы, в которой меню будет использовано, особенно, если все
Ваши файлы расположены в одной директории.
     Мы хотели  бы  напомнить,  то  в  MAKEMENU  имеется   шесть
вариантов меню,   которые   влияют  на  генерирование  исходного
текста: "Color   constants",   "User    proc    hooks",    "Case
statement","String constants", "Mouse support" (в Default-Source),
"Help-Active" (в   Defaults-Help)   и   (Defaults-Toggles).   За
исключением строковых констант все варианты, разъясненные ранее,
имеют по умолчанию значение On.

     Генерирование документов
     ───────────────────────────────────────────────────────────

     Кроме исходного  текста  MAKEMENU  также  может   создавать
"документ": краткий    отчет,    показывающий    информацию    о
меню-системе и пунктах,  содержащихся в ней.  Если бы Вы создали
документ  для  входного  экрана MENU1 (из SAMPLE.OPL),  отчет бы
выглядел следующим образом:

  Menu System Documentation
  _________________________
  Object:               MENU1
  Library:              SAMPLE.OPL
  Size when last saved: 1213

  Menu items:              7
  Highest item key:        7
  Submenus:                3
  Item name:                       X    Y    Const         Number
  _____________________________  ___  ___  ______________  ______
  ' File '                         5    2  miFile            = 1
      'Load'                       4    5  miLoad            = 2
      'Store'                      4    6  miStore           = 3
      'Quit'                       4    8  miQuit            = 4
  ' Options '                     19    2  miOptions         = 5
      'Colors'                    18    5  miColors          = 6
      'Directories'               18    6  miDirectories     = 7

     Первая часть отчета содержит информацию о  меню-системе как
объекте: имя оъекта, имя библиотеки, в которой находится объект,
и размер объекта.
     Во второй  части находится список пунктов меню,  наибольший
номер ключа (часто тот же самый,  что  и  номер  пункта,  но  не
всегда) и число подменю (считая верхний уровень меню).
     Последняя часть отчета есть список пунктов меню-системы. По
каждому пункту дается следующая информация: строка имени пункта,
координаты,  где на экране будет расположен  данный  пункт,  имя
паскалевской константы для ключа пункта и значение ключа. Абзацы
в расположении имен определяют разбиение подменю  по  группам  и
иерархию: имена, имеющие одинаковый абзац в таблице, находятся в
одном подменю;  "родитель" подменю есть следующий пункт, имеющий
меньший отступ от края таблицы.
     Обычно отчет записывается в текстовый  файл  с  расширением
"DOC". По  желанию  Вы можете послать файл на принтер,  введя на
запрос имени файла строку "PRN." (или "LPT1." или "LPT2.").

     Прямое использование библиотеки MAKEMENU
     ───────────────────────────────────────────────────────────

     Если прикладная  программа использует несколько меню-систем
или одну очень большую систему,  то для Вас может  быть  удобнее
загрузить меню прямо из библиотеки,  а не генерировать с помощью
MAKEMENU исходный текст,  который Вы включаете в свою программу.
Будет  ли  это нарушать распределение памяти зависит от размеров
меню.  При загрузке из библиотеки компилятору нет  необходимости
подсоединять  некоторые методы,  используемые для получения меню
исходного текста,  например,  AddItem  и  AddSubMenu.  С  другой
стороны,  компилятору  необходимы  методы  для открытия и чтения
библиотек.   Когда   меню   получаются   достаточно    большими,
библиотечный  подход  становится  более приемлемым,  так как нет
необходимости в повторных обращениях к AddItem  и  AddSubMenu  и
многих  символьных  строках,  которые дублируются в динамической
памяти.
     Для Вашей программы  совсем  несложно  считать  библиотеку,
созданную   MAKEMENU.   Пример   программы,   приведенной  ниже,
показывает как это сделать:

     program LoadMenuFromLibrary;
     uses
       Dos, OpRoot,OpFrame, OpCrt, OpWindow, OpMenu;
     var
       M : Menu;
       Status : Word;

     function IntMenuFromLib(LibName : PathStr;
                             ObjName : DirEntryName;
                             var M : Menu) : Word;
         { Инициализировать меню из библиотеки }
     var
       Lib : Library;
       Code, Version, Status : Word;
     begin
       { Открыть библиотеку и регистры, необходимые для меню }
       if not Lib.Init(LibName, SOpen, 4096, '') then begin
         InitMenuFromLib := InitStatus;
         Exit;
        end;

        Lib.RegisterHier(MenuStream);
        Lib.RegisterHier(ExplodingWindowStream);

        { Подтверждение и загрузка определенной меню-системы }
        Lib.GetCodeAndVersion(ObjName, Code, Version);
        if Code <> otMenu then begin
          { Вернуть код, указывающий на объект неизвестного типа }
          InitMenuFromLib := epFatal+ecIdNotRegistered;
          Exit;
        end;
        Lib.GetEntry(ObjName, M);
        InitMenuFromLib := Lib.GetStatus;

        { Закрыть библиотеку }
        Lib.Done;
      end;

      begin
        { Загрузить меню-систему }
        Status := InitMenuFromLib('SAMPLE.OPL', 'MENU1', M);
        if Status <> 0 then begin
      WriteLn('Нельзя инициализировать меню, Status=', Status);
          Halt(1);
         end;

         { Испытать меню-систему }
         M.Process;
         M.Erase;
         M.Done;
       end.

     В примере открывается определенный файл библиотеки (в нашем
случае 'SAMPLE.OPL',  по  желанию Вы можете попытаться выполнить
его). Для увеличения скорости чтения из  библиотеки определяется
буфер  размером 4 К.  Так как MAKEMENU не записывает специальный
символ в библиотечные файлы,  то последним параметром к Lib.Init
должна быть пустая строка.  Следующие в примере - регистры типов
данных меню-объекта.  Если в Вашей меню-системе не  используются
раскрывающиеся окна, то Вам нет необходимости заносить в регистр
иерархию ExplodingWindowStream.
     GetCodeAndVersion возвращает коды,  которые  указывают  тип
точки   входа  для  определенной  библиотеки.  Если  в  реальной
прикладной программе сложно закодировать  имя  меню-объекта,  Вы
можете  опустить  проверку  вводимых данных.  GetEntry считывает
библиотечный файл для  подтверждения  меню-объекта  М.  GetEntry
инициирует  серию  вызовов  к  Menu.Load  и к Load конструкторов
других  связанных   объектов.   Как   только   меню-объект   был
инициализирован,    библиотечный    файл    закрывается,   чтобы
"высвободить"  указатель  номер  файла  и  динамическую  память,
связанную с файлом.
     В конце  примера  с помощью метода Process демонстрируется,
что меню-система была успешно загружена.
     Если Вашей прикладной программе требуются свойства, которые
MAKEMENU не может хранить в библиотеке,  возможно активизировать
их после  загрузки  меню.  После  обращения к InitMenuFromLib Вы
вставляете обращения     к     другим     методам     меню     -
EnableAllAlternateOpen, SetCurrentItemProc, SetCustomStringProc,
ProtectItem, DefaultItem  -  точно  также, как  если   бы   меню
инициализировалось командами из исходного текста.

     Ограничения
     ───────────────────────────────────────────────────────────

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

     2. PSCREEN
     ───────────────────────────────────────────────────────────

     PSCREEN - утилита, предназначенная для использования вместе
с модулем  OPWINDOW.  Она  также  имеет  два  режима  работы.  В
резидентном режиме PSCREEN позволяет Вам "захватывать" текстовые
экраны,  видео атрибуты  и  все,  что  находится  в  упакованном
формате, и сохранять их на диске. В нерезидентном режиме PSCREEN
предоставляет возможность просмотреть упакованное  окно, которое
предварительно было    записано   в   файл.   Это   может   быть
использовано, например, для создания красочных командных файлов.
Объект   PackedWindow  из  OPWINDOW  также  позволяет  читать  и
показывать на экране содержимое файлов с упакованными  окнами из
прикладной программы.

     Использование PSCREEN
     ───────────────────────────────────────────────────────────

     Для работы  с PSCREEN в резидентном режиме просто введите в
командную строку DOS
     PSCREEN
без параметров.  PSCREEN есть подкачиваемая TSR (смотрите  главу
11), которая  использует только 6 К памяти DOS;  остальная часть
программы хранится в расширенной (EMS) памяти или на  диске.  Вы
можете ввести после PSCREEN один из следующих параметров:
     /Е          не использовать EMS
     /М          запретить подкачку сообщений
     /N          запретить подкачку
     /Pпуть      определить путь, чтобы использовать для подкачки
     /U          удалить PSCREEN из памяти
     /?          показать экран подсказки

/Е запрещает  PSCREEN  использовать  память EMS под подкачку.  В
противном случае,  PSCREEN будет выделять,  если доступно,  48 К
EMS.

/М запрещает  сообщения 'Swapping in',  'Swapping out',  которые
обычно PSCREEN  выводит  на  экран  при  подкачке  на  диск.  /М
особенно  полезно,  если  Вы  подкачиваете на диск RAM,  который
является настолько быстрым, что сообщения становятся помехой.

/N запрещает все подкачки. В этом случае PSCREEN будет занимать
около 52 К DOS RAM.

/Р позволяет  Вам  определить  альтернативное  размещение файлов
подкачки. Есть две области,  каждая размером по 45 К байтов.  По
умолчанию подкачиваемые файлы находятся  в  корневой  директории
диска С.  Определите  сразу  после  параметра  /P  устройство   и
директорию. Подкачиваемые файлы всегда имеют имена 'PSCREEN1.$$$'
'PSCREEN2.$$$',  но они могут иметь метки скрытых файлов, поэтому
Вы можете не увидеть их.

/U удаляет  PSCREEN  из  памяти.  Подобно  другим   TSR из Object
Professional, PSCREEN будет выполнять эту операцию,  только если
это безопасно.

/? высвечивает на экране краткую подсказку по параметрам.

     Когда Вы  захотите  сохранить  упакованное  окно  на диске,
нажмите управляющие   клавиши   PSCREEN,   такие   как
<Alt><LeftShift><P>. Курсор в этом случае станет мигающим.
     Для выбора  области  экрана  (то  есть 'окна'),  которую Вы
хотите  сохранить,  передвиньте  курсор  в  верхний  левый  угол
области  и  нажмите  <Enter>,  затем передвиньте курсор в нижний
правый угол и снова нажмите <Enter>.  Если Вы двигаете курсор по
кругу,  то  текущая  выбранная  область  будет изменять цвет для
указания границ окна. Если Вы желаете сбросить операцию, нажмите
<Enter>.  Для  удаления PSCREEN из памяти вместо <Enter> нажмите
<AltU>.
     Как только  Вы выбрали окно,  Вас попросят ввести имя файла
для записи окна.  Снова,  если Вы  желаете  удалить  PSCREEN  из
памяти,  то  в  ответ  на  запрос имени нажмите <AltU>,  если же
хотите сбросить операцию, нажмите клавишу <Esc>.
     Чтобы посмотреть   упакованный  экран  с  помощью  PSCREEN,
напечатайте в командной строке DOS
     PSCREEN имя_файла.расширение
PSCREEN будет просто выводить содержимое файла на  экран, ожидая
нажатия клавиши для продолжения просмотра.

     Программа просмотра файла с упакованным окном
     ───────────────────────────────────────────────────────────

     Просмотреть файл,  созданный PSCREEN достаточно легко. Ниже
приведен краткий пример программы просмотра,  где FName есть имя
файла с упакованным окном.

     program DisplayPackedWindow;
     uses OpCrt, OpWindow;
     const FName = 'TEST.PWF';
     var   PW : PackedWindow;
     begin
       if PW.Read(FName) then
         PW.Display
       else
         WriteLn('', InitStatus, '', Fname);
      end.

     Также возможно  привязать  файл  с  упакованным окном к EXE
файлу прикладной программы. Смотрите PackedWindow.InitFromMemory
из примера части С настоящей главы.

     3. WINWOW
     ───────────────────────────────────────────────────────────

     Утилита WINWOW  не  делает  ничего полезного,  тем не менее
вероятно  она  даст  Вам  время   для   обдумывания,   пока   Вы
откладываете  написание сложной документации.  Мы также считаем,
что WINWOW  будет  полезна  как  демострационная  программа  для
изменяющихся   (имеющих   более  высокое  разрешение)  текстовых
режимов,  поддерживаемых платами EGA  и  VGA.  В  начале  работы
WINWOW  сама  настраивает  сколько  доступно  рядов  и  столбцов
экрана.
     WINWOW демонстрирует  некоторые  выразительные  возможности
модуля OPWINDOW.  В начале  работы  создаются  8  выкидных  окон
случайных размеров и цветов, затем они начинают передвигаться по
экрану с бешеной скоростью - с прокруткой,  раскрытием и сжатием
окон во время передвижения.  Для прерывания выполнения программы
и возвращения к DOS  необходимо  любую  нажать  клавишу.
     Ниже представлен  список  возможностей Object Professional,
использование которые демонстрирует WINWOW:
     -  основные и изменяющиеся рамки окон
     -  добавление теней и заголовков
     -  выбор  не  установленных  по  умолчанию  значений  видео
        атрибутов окна
     -  запрещение раскрытий окон
     -  создание виртуального экрана и запись в него
     -  копирование из виртуального экрана в окно для достижения
        эффектов прокрутки
     -  передвижение и изменение размеров окна
     -  помещение в стек окон случайного доступа
     -  стирание всех окон из стека






