5 - 3 - Аннотация Настоящий документ содержит описание общей структуры и принципов функциониро вания СУБД Ratbase, динамической среды выполнения программ, описание языка RatBasic. Документ предназначен для программистов, разрабатывающих приложения под управлением СУБД RatBase. - 4 - Общее описание RatBase RatBase это многоцелевая СУБД, позволяющая решать различные задачи обработки дан ных. К особенностям RatBase можно отнести: - работу на различных платформах: IBM-PC, VAX, Sun, под управлением ОС MS-DOS, MS-WINDOWS (на IBM-PC) и Unix- совместимых ОС. - многопользовательский режим работы под управлением UNIX- совместимых ОС. - экономичное (по сравнению с распостраненными СУБД) хранение данных на внешнем носителе. - объектно-ориентированный язык описания приложений, обладающий большими выра зительными средствами. RatBase не обладает встроенными диалоговыми возможностями (как например СУБД FoxPro). Работа запущенного под управлением RatBase приложения полнностью определяется программой написанной на языке RatBasic - входном языке СУБД. Таким образом последовательность действий при разработке приложения на RatBase следующая: - создаются, так, как это описано ниже, файлы данных; - создаются (или модифицируются существующие) текстовые файлы, содержащие про грамму на RatBasic-е; - запускается задача RatBase с именем файла, содержащего текст программы, в качестве аргумента; - при наличии синтаксических ошибок в программе повторяются предыдущие два шага; - при отсутствии синтаксических ошибок начинается выполнение приложения, в соответ ствии со введенной программой; - в случае необходимости повторяются последние три шага. Перед вводом программы написанной на RatBasic в СУБД она (программа) может быть ЗАШИФРОВАНА с помощью утилиты шифрования CRP, входящей в комплект поставки. Это делается для обеспечения возможности поставки конечному пользователю закрытых от изме нения приложений. - 5 - Запуск программы и ключи командной строки Формат командной строки запуска RatBase следующий 1: ratbase <файл приложения> [ключи...] Файл приложения содержит (возможно зашифрованную) программу на языке RatBasic. Допустимы следующие ключи (могут задаваться как строчными, так и прописными буквами, кроме того вместо символа / может применяться символ минус 2): /L:filename - указание файла листинга. /L без аргумента выводит листинг на экран. Лис тинг содержит нумерацию строк программы, а также отдельную нумерацию строк для каждой процедуры. /P:path - путь к базе, т.е. имя каталога, в котором содержатся файлы данных приложе ния. /I:path - путь к файлам, включаемым в текст программы по директиве #include препро цессора, по умолчанию этот каталог совпадает с каталогом, в котором содержится главный файл приложения. /C:key - ключ расшифровки приложения, дложен указываться, если текст программы был зашифрован утилитой CRP. При отсутствии этого ключа вводится незашифрован ный текст. /N[:полное имя файла замка] - с этим ключом программа должна запускаться при мно гопользовательской работе - в сети или под ОС Unix. О назначении файла замка см. ниже. /B:nnn - размер буфера записей (байт). /R:nnn - максимальный размер записи (байт). /A:nnn - начальный размер памяти под приложение (байт). /S:nnn - размер стека задачи. Ключи /B, /A, /R, /S применяются для оптимизации работы RatBase с динамической памятью, и могут не использоваться, если проблем с памятью нет. 1 При работе под MS Windows выполняемый файл называется rbw.exe. 2 При запуске RatBase под управлением ОС Unix в качестве признака ключа допускается только символ "-". - 6 - Если вводимая программа на RatBasic содержит синтаксические ошибки, то на экран выводится имя файла, содержащего ошибку, номер ошибочной строки в этом файле, сама эта строка и сообщение о типе ошибки. После этого выполнение программы прекращается. При отсутствии ошибок в тексте программы поведение запущенного приложения полностью опре деляется введенной программой. - 7 - Отношения, дескрипторы отношений, утилита rdbutil В этом разделе описано понятие отношения в RatBase, а также процесс создания и мо дификации файлов данных, представляющих собой отношения. Понятие ОТНОШЕНИЯ в RatBase в общем совпадает с общепринятым понятием реляци онного отношения - это набор ЗАПИСЕЙ , каждая из которых содержит одинаковый набор поименованных полей. В каждом поле могут находиться данные (соответствующего этому по лю типа), либо поле может иметь НЕОПРЕДЕЛЕННОЕ ЗНАЧЕНИЕ , т.е. не содержать ника ких данных. Отношение RatBase соответствует реально хранимым на носителе данным, и представлено несколькими файлами, содержащими дескриптор отношения, собственно данные и индексы (некоторые поля отношеня могут быть проиндексированы для обеспечения воз можности быстрого поиска записи по значению поля). Именование отношений Отношения именованы. Полное имя отношения состоит из префикса (имени каталога, в котором хранятся файлы данных) и собственно имени отношения. В полном имени отношения префикс и собственно имя соединяются знаком ~ (тильда). Пример полного имени отноше ния 3: 3 Во всех дальнейших примерах имена файлов приводятся в форме принятой в MS DOS, т.е. имена каталогов разделены символом обратного слэша. Естественно, что в Unix-е это будет символ прямого слэша (/). - 8 - d:\rdb\exper~a Если в имени отношения префикс не указан, то берется значение префикса по умолчанию. Это значение задается двумя способами. Во- первых начальное значение префикса имен отношений можно указать после ключа -p в командной строке запуска задачи RatBase. Так, если RatBase запущена командной строкой ratbase a.dat -p:\rdb\exper а файл a.dat - программа на RatBasic-е - содержит команду (имеющую аргументом пол ное имя отношения) rel a - 9 - то в действительности агументом команды будет имя отношения \rdb\exper~a. Второй путь задания префикса имен отношений - использование в тексте программы команды base. Она имеет следующий формат: base <префикс имен отношений> Если файл a.dat из вышеприведенного примера содержит такой фрагмент текста: base /data . . . rel a то аргументом команды rel будет полное имя отношения /data~a. Дескрипторы отношений Каждому отношению соответствует файл описания отношения, называемый также деск риптором отношения. Этот файл должен содержаться в каталоге, составляющем префикс полного имени отношения, имя файла совпадает с собственно именем отношения, а расшире ние имени файла - ".rdb". В частности, дескриптор отношения с полным именем /rdb/exper~a должен находиться в файле /rdb/exper/a.rdb. Дескриптор отношения - это текстовый файл, содержащий информацию о количестве и типах полей и индексов отношения, а также имени файла данных отношения. Первая строка дескриптора отношения имеет вид: - 10 - <имя файла данных> <количество полей> <количество индексов> Имя файла данных как правило, хотя и не обязательно, совпадает с именем дескрипто ра отношения и имеет расширение .hp (расширение указывается явно). Остальные строки дес криптора отношения содержат информацию о полях отношения, и количество этих строк должно быть равным указанному в первой строке дескриптора. Формат строк описания полей отношения: <имя поля> <формат> [<описание индекса>] Имя поля - строка произвольных печатных символов не содержащая пробелов. Маси мальная длина имени поля - 24 символа. Формат определяет тип поля и, возможно, некото рые дополнительные его характеристики. Например для строчного поля в формате задается максимальная длина строки. Описание индекса задается только для индексированных полей. Общее число описателей индекса в дескрипторе отношения должно совпадать с количеством индексов, указанным в первой строке дескриптора. Подробно формат поля и описание индек са описаны ниже. ВНИМАНИЕ ! Не забывайте изменять количество полей и индексов в первой строке дескриптора при изменении их реального количества в дескрипторе. - 11 - Формат поля, типы данных в RatBase Как уже говорилось, формат поля в дескрипторе отношения определяет его тип и до полнительные характеристики. Ниже приведены допустимые типы данных полей в отношениях RatBase и соответствующие им форматы. %d целое число со знаком в диапазоне от -32768 до +32767 (16 двоичных разрядов). %ld длинное целое со знаком в диапазоне от -???? до +???? (32 двоичных разряда). %[]s текстовая строка длиной до len символов. По умолчанию len принимается равным 80. %lf число с плавающей точкой в диапазоне от -1.7e-308 до +1.7e308. Допустимо указы вать этот формат в виде %.lf, где nn - количество десятичных цифр после точки при изображении этого поля. По умолчанию оно равно трем. Подчеркнем, что указание точности влияет только на изображение, но никак не на точность хранимого числа. %D календарная дата. Формат %D определяет представление даты в виде dd.mm.yy, где dd, mm и yy - номера дня, месяца и последние две цифры номера года, соответ ственно. Если номер года меньше 1900 или больше 2000, то год представляется четырьмя цифрами. Представление даты можно изменить, задавая между % и D следующие символы: Y - номер года всегда представляется полностью m - месяц представляется своим кратким латинским названием (Jan, Feb, ...) M - месяц представляется полным русским названием (января, февраля, ...) -,/,. - при текстовом представлении месяца (m или M) поля в дате разделя ются пробелом. Если указан один из символов . / -, то поля будут разделяться этим символом. %T время дня %[]b массив байт, длиной до len символов. По умолчанию len принимается рав ным 80. Описание индекса Описание индекса в дескрипторе отношения представляет собой двухбуквенное описа ние типа индекса, за которым (без разделяющих пробелов) может следовать дополнительный числовой параметр. Предполагается, что читатель знаком с терминами "В-дерево", "хэш- таб лица", "хэш-функция" и общими принципами организации индексов в СУБД. - 12 - Возможны следующие типы индексов: BF - Индекс организован как B-дерево. Индексируемое поле может быть любого типа. Возможны повторяющиеся значения ключей. Значение параметра, если есть, опре деляет число первых байт поля, участвующих в индексировании (например индекс по первым нескольким буквам фамилии). Если параметр опущен - индексирование по всему полю. BW - индексируемое поле должно быть строкового типа. Оно разбивается на слова (по пробелам), и для каждого слова строится элемент индекса. Возможны повторяю щиеся значения ключей. Смысл параметра тот же, что и в предыдущем случае. HF - поле должно быть типа целое или длинное целое. Возможны повторяющиеся значения ключей. Индекс реализован с помощью хэш-таблицы, причем значение хэш-функции в этом случае совпадает со значением поля. Параметр, если есть, указывает, ожидаемое количество записей с одинаковыми значениями ключа. HS - индексируемое поле должно иметь строковый тип. Индекс реализован с помощью хэш-таблицы, причем хранимый ключ образуется путем применения к значению поля хэш-функции. Возможны повторяющиеся значения ключей. Параметр указы вает количество элементов хэш-таблицы. DF - поле должно быть типа целое или длинное целое. Индексирование идет по значению поля через таблицу, где каждому возможному значению поля соответ ствует ссылка в файл данных. Значения поля НЕ МОГУТ ПОВТО Р_ТЬС_ . Параметра нет. Некоторые из этих типов индексов могут применяться как для поиска записи по значению поля, так и для упорядоченного (по возрастанию значения поля) просмотра отно шения. Это типы BF, DF, HF. Индексы типов HS и BW могут применяться только для поиска, но не для упорядоченного просмотра. Пользователю, неискушенному в ТЕОРИИ ВЫСШИХ ИНДЕКСОВ , можно посоветовать употреблять тип индексов BF без параметра. Все остальные типы могут применяться для оп тимизации скорости доступа, объема данных и пр. Утилита rdbutil Входящая в комплект поставки RatBase утилита rdbutil предназначена для создания, модификации и "ремонта" файлов, составляющих отношение RatBase. Формат командной строки запуска rdbutil следующий 4: 4 Под MS WIndows выполняемый файл утилиты называется rbuw.exe. - 13 - rdbutil <команда> <имя дескриптора отношения> [<параметр>] [ключи] Команда - символ, определяющий выполняемую утилитой операцию. Возможны следу ющие команды: N - создание нового (или пересоздание имеющегося) отношения. Параметр, если есть, представляет собой ключ шифровки данных в отношении. Параметр может быть текстовой строкой. В дальнейшем при работе с зашифрованным отношением надо будет указать такой же ключ. A - добавление новых полей в отношение. Параметр (число) определяет количество до бавляемых полей. Если параметр опущен, то добавляется одно поле. Добавленные в дескриптор поля имеют имена вида FIELD1, FIELD2 ... и формат %d. После опе рации добавления полей нужно отредактировать дескриптор отношения изменив имена и типы добавленных полей на необходимые. ВНИМАНИЕ! Добавление полей в отношение не сводится только к редактирова нию дескриптора, а может потребовать изменения файлов данных. Поэтому до бавление полей в отношение необходимо производить только с помощью утили- ты. V - "ремонт" поврежденного файла данных. К этой команде следует прибегать только в качестве крайней меры, так как файл данных может быть поврежден настолько се рьезно, что никакой ремонт ему уже не поможет. Параметра нет. D - копирование данных из одного отношения в другое. Параметр обязателен, и пред ставляет собой имя целевого отношения. S - сжатие файла данных отношения за счет освобождения неиспользуемого места. Сжа тие может давать заметный эффект после активного удаления записей из отноше ния. Параметра нет. I - переиндексирование отношения. Параметр (число) определяет номер пересоздаваемо го индекса. При опущенном параметре пересоздаются все индексы отношения. T - проверка целостности данных в отношении. Параметра нет. Имя дескриптора (второй аргумент команды) приводится без расширения .rdb. Допускаются следующие ключи (для ключей в скобках указано, при каких командах они могут встречаться): - 14 - [число полей] (A,D,S) - попутно с выполнением основной команды добавить указанное количество (по умолчанию 1) полей в отношение. /b (A,S) - сохранять предыдущие версии файлов после выполнения команды. /с (A,D,S) /d (S) /e[:num] (A,D,S) /i[:num] (A,D,S,V) /q[:num] (A,D,S,V) В случае успешной отработки утилита выводит сообщение "All done" и завершает рабо ту. Результатом ее работы является создание или модификация файла данных и файлов ин дексов. Файл данных имеет имя и расширение, указанные в первой строке дескриптора. Фай лы индексов имеют то же имя, что и файл дескриптора. Расширения их начинаются с букв I, V, L, за которыми следует двухсимвольный номер поля, к которому относится данный ин декс. Например файл индекса с именем a.i01 относится к первому полю отшения, описанного в файле дескриптора a.rdb. Краткую справку о работе с утилитой можно получить подав команду rdbutil без параметров. Утилита rbuw, предназначенная для работы под MS WIndows не содержит пара метров в командной строке запуска. Команды, параметр и ключи задаются путем выбора в dialog box-е. Кроме того имеются возможности выбора дескриптора отношения стандартным для Windows способом (Browse) и редактирования фай ла дескриптора (Edit). Редактирование происходит с помощью текстового ре дактора notepad.exe, который должен быть установлен в системе. - 15 - Пример описания и создания отношения Предположим, что нам надо создать отношение, имеющее следующие поля: num типа целое, name - строка до 30 символов длиной, addr - строка до 80 символов длиной, born - календарная дата. Мы знаем, что поле значения поля num в отношении не будут дублиро ваться, и по значению этого поля будет требоваться быстрый поиск записей. Отношение должно иметь имя persons. С помощью текстового редактора создаем файл persons.rdb: persons.hp 4 1 num %d DF name %30s addr %s born %D После этого запускаем rdbutil: rdbutil n persons После того, как утилита выдаст "All done" все файлы отношения будут созданы, и из RatBase можно будет работать с новым отношением. - 16 - Описание языка RatBasic Этот раздел содержит полное описание языка RatBasic, обильно уснащенное примерами использования различных его элементов. Понятия и термины, специфичесие для RatBase вво дятся по мере необходимости. Препроцессор Программа на RatBasic-е содержится в одном или нескольких текстовых файлах, кото рые могут быть созданы любым текстовым редактором 5. Агрегатирование, т.е. сборка их вое дино, производится с помощью препроцессора, входящего в состав языкового интерпретатора RatBase. Директивы препроцессора не являются элементами собственно RatBasic-а. В общем они похожи на широко известные директивы препроцессора языка C. Все директивы препро- цессора начинаются с символа # в первой позиции строки. За этим символом (возможно через несколько пробелов или символов табуляции) следует ключевое слово директивы, а также возможные аргументы. Препроцессор RatBase обрабатывает следующие директивы: #include <имя файла> Аналогична директиве include C-препроцессора, т.е. приводит к включению в текст про граммы содержимого указанного файла. В отличие от C-препроцессора имя файла не заключается в кавычки или угловые скобки. Включаемый файл также может содержать ди рективу #include, и т.д. - максимально до десятого уровня вложенности. ВНИМАНИЕ ! При работе под управлением MS DOS и MS Windows необходимо удваи вать символы обратного слэша(\) в полных именах файлов. Например, если нужно под ключить файл c:\data\a.app надо 5 При работе под MS DOS файлы должны быть набраны в альтернативной кодировке, под Unix-ом - в кодировке KOI-8, а под MS Windows - в кодировке ANSI. - 17 - задать директиву #include c:\\data\\a.app. Причины этого объясняются ниже. #define <имя> Имя представляет собой строку символов, не содержащую пробелов. Действие дирек тивы состоит в том, что ИМЯ становится определенным при вводе текста, следующего после этой директивы. Определенность (неопределенность) имени может быть проверена директива ми #ifdef и #ifndef. #define <имя> <значение> Если директива #define содержит аргументы после определяемого имени, то кроме то го, что имя становится определенным, оно получает значение, равное остатку строки после имени начиная с первого непробельного символа. В дальнейшем тексте программы все вхож дения указанного имени будут заменяться на его значение (макроподстановка). В отличие от C-препроцессора невозможны макроопределения с аргументами. #undef <имя> Если указанное имя было определено ранее с помощью директивы #define, то после упоминания его в директиве #undef оно становится неопределенным. Естественно, что макро подстановка этого имени в дальнейшем также не происходит. #ifdef <имя> Аналогична такой же директиве C-препроцессора. Текст, следующий за директивой #ifdef будет передаваться на вход RatBase только если указанное имя было ранее определено директивой #define (условная трансляция). Текст после директивы #ifdef должен завершаться директивой #endif или #else. #ifndef <имя> Похожа на #ifdef, но дальнейший текст будет обрабатываться только при неопределен ности указанного имени (имя могло быть вообще не определено, либо разопределено дирек тивой #undef). #else Эта директива может завершать фрагмент текста, следующий за #ifdef или #ifndef. Смысл ее очевиден - инвертируется условие обработки текста. #endif Завершает фрагмент текста, следующий за #ifdef, #ifndef или #else. Допустимо вложение (до десяти уровней) таких "#if-блоков" текста. - 18 - #askdef <имя> [ <умолчание> [<подсказка>] ] Эта директива позволяет оператору задавать (не)определенность указанного имени при обработке файла с программой утилитой CRP. На экран при этом выводится строка "<подсказка> <имя> (y/n) <умолчание>". Умолчание - 0 или 1, определяет, будет имя опре- делено (1) или нет (0), если оператор введет в ответ на подсказку пустую строку. Чтобы оп ределить имя оператор должен ввести "y" или "Y". Если подсказка опущена, то выводится текст "Определять переменную ?". #askval <имя> [ <умолчание> [<подсказка>] ] Директива askval подобна askdef, но позволяет в диалоге с оператором задавать значение имени. Если оператор вводит пустую строку, то принимается значение по умолчанию. Если опущена подсказка, то выводится текст "Значение переменной". Две последние директивы работают только при обработке файла программы утилитой CRP. При вводе программы непосредственно в RatBase директива #askdef игнорируется, а #askval <имя> <умолчание> эквивалентна #define <имя> <умолчание>. Кроме имен, определяемых директивами #define, #askdef и #askval в среде препроцес сора определено одно из имен, определяющих операционную систему, в которой выполняется программа. Это следующие имена: __MSDOS__ - при работе под управлением MS-DOS; _Windows - при работе под оболочкой WINDOWS; __unix__ - при работе под UNIX-подобными ОС. Приведем пример использования директив препроцессора. Пусть текст программы содержится в файлах a.dat и b.dat, а файл c.dat содержит фрагменты текста, необходимые только в отдельных случаях. Содержимое файла a.dat (главного файла, имя которого передается в качестве аргумента программе RatBase): - 19 - #include b.dat #ifdef __unix__ #define __SPARC__ #endif . . . #ifdef __SPARC__ # include c.dat #else . . . #endif Кроме описанных средств препроцессора язык RatBasic содержит средства дина мического (в процессе выполнения программы) определения имен. Об этом см. описание опе ратора !DEFINE. Общие сведения о RatBasic-е Текст программы на RatBasic-е состоит из КОМАНД , каждая из которых располагается на отдельной строке (команда не может занимать несколько строк). Команды начинаются с ключевого слова, за которым могут следовать операнды. Количество и типы операндов при ведены в описании команд. Ключевые слова и операнды команд могут располагаться с любой позиции в строке, и должны разделяться хотя бы одним пробелом или символом табуляции. Пробелы в теле операндов должны быть заменены на символ "$". Большинство команды име ют значения операндов по умолчанию. Эти операнды могут быть либо опущены (если за ними нет других явно указанных операндов), либо вместо них можно указать символ "_" (значение по умолчанию). Допустимы пустые строки. Команда с ключевым словом "--" считается комментарием (все ее операнды просто игнорируются). Многострочный комментарий начинается командой "/*", и заканчивается командой "*/". Обращаем внимание на то, что команды начала и конца многострчного комментария, как и любые другие, должны быть первыми в строке, и отде ляться от других элементов в этой строке хотя бы одним пробелом. - 20 - Программа на RatBasic-е состоит из описаний данных и описаний процедур. К данным относятся формы, списки, переменные и case- дескрипторы. Процедуры состоят из последова тельности операторов RatBasic-а, и определяют действия выполняемые программой. Команды, втречающиеся в теле процедур будем называть ОПЕРАТОРАМИ . Кроме того имеется не сколько дополнительных служебных команд. Ключевые слова команд, как правило, представляют собой последовательность латинс ких букв, и могут набираться как на верхнем, так и на нижнем регистре. Операнды команд, пердставлящие собой имена каких-либо объектов языка, должны набираться в точности на том регистре, как они были объявлены, т.е. имена чувствительны к регистру набора. Так, на пример команды listof proc a и LISTOF proc a обозначают одно и тоже, а команды listof proc a и listof proc A различны. В данном документе команды языка RatBasic описываются в таком формате: - 21 - ключевое_слово операнд1 (умолчание) операнд2 (умолчание) Описание операндов в столбик используется только из-за недостатка места в строке документа, т.е. на самом деле все операнды располагаются в одной строке. Умолчание указы вается только для операндов его (умолчание) имеющих. Операнды не имеющие умолчания не могут быть опущены. Чтобы явно указать использование умолчательного значения операнда используется символ "_". Следует сказать еще несколько слов по поводу записи операндов в RatBasic-е. В стро ковых значениях допускается запись управляющих символов, аналогичная принятой в языке Си. Возможна запись следующих символов: \n - перевод строки \t - горизонтальная табуляция \r - возврат каретки \v - перевод страницы Символ обратной косой черты, стоящий перед некоторыми другими символами отменя ет их специальное значение. Имеют смысл следующие сочетания: \' - апостроф \$ - знак доллара \\ - обратная косая черта (см. замечание об именах файлов в описании директивы #include). Кроме этого допустимо записывать в строках непосредственно коды символов. Код символа представляет собой последовательность цифр после символа '\'. Если первая из цифр - 0, то код считается восьмеричным, длиной до трех символов (не считая самого 0). Если за '\' следует одна из цифр 1 - 9, то это десятичный код, длиной также до трех симво лов. Если же после '\' следуют символы 0x или 0X, то следующие два сиимвола рассматри ваются как шестнадцатеричный код. Еще одно замечание по поводу операндов целого типа в RatBasic-е. Кроме целого числа с возможным знаком в позиции целого операнда допустим одиночный символ, заключенный в апострофы ('). В частности ' ' эквивалентно 32 (код символа пробел). Сообщения периода загрузки (message, typefile) Процесс загрузки большой программы на RatBasic может быть довольно длительным. Для его "оживления" можно воспользоваться командами: - 22 - message <строка> и typefile <имя текстового файла> Команды немедленно после своей загрузки в RatBase из текста программы выводят строку или содержимое текстового файла на экран. После этого прекращается индикация на экране количества загруженных строк. Пример: message Пошла$загрузка$!!! . . . <операторы (много)> . . . message Скоро$уже$закончится$!!! Эти сообщения будут выведены на консоль во время загрузки программы на RatBasic. Предописание (define) Зачастую некоторые объекты (формы, процедуры или списки) должны быть упомянуты ранее своего описания. Чтобы сделать это возможным имеется команда define proc | list | form <имя определяемого элемента> - предописание, соответственно, процедуры, списка или формы. После этого можно использовать это имя в соответствующем контексте. Естественно, что для формы, до ее пол ного описания, можно упоминать только ее имя, но никак не имена ее полей. - 23 - Описание списка (listof, endlist, copy) В RatBasic возможны списки процедур или форм. Назначение их двоякое. Во-первых списки являются основой для формирования меню (форм или процедур) при выполнении опе раторов CHOICE_EDIT и CHOICE_DO. Во-вторых с помощью списков процедур задаются списки редактирующих процедур для экранного редактирования формы. Описание списка начинается командой listof proc | form <имя определяемого списка> и заканчивается командой endlist Между listof и endlist располагаются имена членов списка, по одному на строке. Есте ственно это должны быть имена того сорта объектов из которых состоит список. После имени элемента на той же строке может быть указана строка, которая и будет текстом пункта меню. Если дополнительная строка не указана, то в текст меню попадает соб ственно имя элемента. Кроме того в теле описания списка возможна команда copy <имя списка> которая полностью копирует указанный список в определяемый. Пример: - 24 - listof form toedit acc Счета persons Физические$Лица org Юридические$Лица counts endlist Впоследствии по этому списку можно будет через меню выбрать форму (одну из acc, persons, org или counts) для редактирования. В меню выбора формы acc, persons и org будут представлены соотвественно строками "Счета", "Физические Лица" и "Юридические Лица", а форма counts - строкой counts, т.к. для нее не указана дополнительная строка. Замечание. Упоминание еще не описанных имен в списках процедур эквивалентно пре дописанию этих процедур. Форма Форма - одно из основных понятий RatBasic-а. С ее помощью производятся все мани пуляции с данными в RatBase. Формы служат для доступа к хранимым данным (отношениям), для организации ввода- выода, генерации отчетов и организации среды данных в программах на RatBasic. Форма, как и отношение, содержит набор типизированных и поименованных полей и позволяет осуществлять доступ к некоторому множеству записей. Доступ осуществлется по записно, посредством ТЕКУЩЕЙ записи, представленой значениями полей формы Поля формы делятся на СОБСТВЕННЫЕ, принадлежащие только данной форме, и НЕСОБСТВЕН НЫЕ, связанные с каими-либо внешними по отношению к форме объектами. Для формы определены такие операции, как сдвиг на следующую / предыдущую записи, добавление, удаление, модификация записей и пр.. Последовательность записей формы замк нута в кольцо через ПУСТУЮ ЗАПИСЬ . Сдвиг на следующую запись относительно пустой - 25 - приводит к установке на первую запись, а сдвиг на предыдущую - к установке на последнюю запись формы. Форме может СООТВЕСТВОВАТЬ некоторое отношение. В этом случае множеством за писей формы будет подмножество записей отношения. Для таких форм набор и имена полей не обязательно совпадают с полями этого отношения. В форму могут входить не все поля отношения, она может содержать поля не входящие в отношение (собственные). Поле формы, входящее в соответствующее ей отношение может иметь имя (но не тип) отличное от имени поля в отношении . В формах, не имеющих соотвествующего отношения как правило есть всего одна за пись, и операции сдвига не определены. Такие формы используются для ввода-вывода и хра нения переменных периода исполнения программы. Кроме этого форма задает экранное представление (образ карточки, представляющей одну запись на экране и таблицы), связи и списки обмена, списки редактирующих клавиш (см. ниже) и пр. Важным свойством форм является возможность их ЭКРАННОГО РЕДАКТИРОВА НИ_ - т.е. изображения на экране части данных, хранящихся в форме и их просмотра / модификации путем нажатия РЕДАКТИРУЮЩИХ КЛАВИШ . Набор редактирующих клавиш и действия связанные с ними указываются при описании формы. При экранном редактировании возможно представление данных в одном из двух видов - бланк (он же карточка) и таблица. При представлении в виде бланка на экране изображены поля, образующие одну запись. Их расположение и фон задаются описанием формы. При представлении в виде таблицы на экране изображены данные, соответствующие нескольким записям - по одной на строку. Одноименные поля записей сгруппированы в колонки. При экранном редактировании поля формы могут обладать некоторыми свойствами, по отношению к редактированию и изображению их на экране. В частности поле может быть не редактируемым (в него никогда не попадает курсор), можно указать, что в поле необходимо наличие непустого значения по заполнению бланка и пр. Также для конкретного поля можно указать, что оно не входит в бланк и/или таблицу. Подробнее об этом написано ниже, при описании команды fld. В языке RatBasic имеются объектно-ориентированные возможности, а именно наследо вание. Наследование, в смысле ООП, реализуется механизмом базирования - форма может (но не обязана) БАЗИРОВАТЬС_ на другой форме. Форма НА которой базируется другая называется родительской формой или предком, а форма КОТО РАЯ базируется на другой - производной формой или потомком. Производная форма наследует от родительской все ее атрибуты - набор полей, связи (см. ниже), экранное представление. В производной форме можно: - добавлять новые поля - 26 - - заменять экранное представление т.е. размеры и расположение полей и изображение фона (если в производной форме описывается ее экранное представление, то оно полностью заменяет экранное представление родительской формы). - заменять описание отчета - добавлять новые условия связей - добавлять новые элементы к списку обмена - добавлять новые связи - подменять унаследованые связи на новые - подменять хуки и списки редактирующих клавиш Подчеркнем еще раз: форма это аналог не ПЕРЕМЕННОЙ, а ТИПА. Переменным же, т.е. представителям этих типов, соответствуют описанные ниже выборки. Описание формы (form, Form, endform) В программе на RatBasic форма вводится своим описанием. Описание формы - это фрагмент текста на RatBasic заключенный между командами form и endform. Формат команды form: form <имя определяемой формы> <базовая форма> (никакой) <форма представления> (TB) <окно> (рабочая область) <права доступа> (RDUAL) Как уже говорилось, форма может базироваться на другой форме. Имя этой "родительской" формы и указывается вторым параметром. Если оно не указано, описываемая форма не имеет предков, и все ее атрибуты определяются следующим за командой form опи санием. Если имя родительской формы указано, то определяемая форма наследует от роди тельской ВСЕ ее атрибуты. Дальнейшее же описание может изменять некоторые из них и до бавлять новые. Пример наследования: - 27 - form a rel a allflds endform -- описана форма, которой соответствует отношение а, -- и содержащая все поля этого отношения form aa a endform -- форма аа в точности совпадает с формой а, т.к. ее -- собственное описание пусто form aaa a rel b fld i %d endform -- форма b похожа на форму а, но связана с другим -- отношением. Кроме того в ней добавлено еще одно поле -- с именем i и типом целое (см. команду fld) Форма представления - это строка букв TB, BT, T или B. Форма представления опреде ляет допустимые виды экранного редактирования формы, т.е. указывает, можно редактиро вать форму в табличном (T) или (и) бланковом (B) виде. Если приведено TB или BT, первая буква указывает начальное представление. Окно - это конструкция вида <строка> : <колонка> : <высота> : <ширина>, например 1:1:10:60. Окно определяет подобласть экрана, которая будет занята формой при ее редакти ровании. Строка и колонка определяют верхний левый угол окна, Если указано слишком большое окно, то оно будет обрезано по границам рабочей области экрана. Если опущены высота и/или ширина, то они будут установлены по размерам, требуемым для бланка. Если строка или колонка меньше 0, то форма располагается с нулевой колонки второй строки (в левом верхнем углу рабочей области экрана). Права доступа - это строка из букв R, D, U, A, L, G. Они определяют, какие операции будут допустимы с этой формой - добавление / удаление / модификация записей, и пр. R - право на чтение, D - на удаление записи, U - на модификацию записи, A - на добавление за писи, L - на переход ИЗ ДАННОЙ ФОРМЫ по связи, G - указание, что В ЭТУ ФОРМУ нельзя переходить по связи. - 28 - Команда form имеет вариант Form с теми же операндами. Единственное отличие заключается в том, что формы, описан ные через Form не попадают в меню при выборе в "списке всех форм". Заканчивается описание формы командой endform без аргументов. Между этими двумя командами располагаются приведенные ниже команды описания форм. Описание отношения соответствующего форме (rel, private, psw) Как уже говорилось, форме может соответствовать отношение. Для указания того, ка кое отношение соответствует описываемой форме служит команда rel <имя отношения> В этой команде (см. примеры из раздела об отношениях) указывается собственно имя отношения, полное или частичное (без префикса). Так, если в каталоге d:\rdb\exper имеется файл дескриптора отношения a.rdb, то корректно описание: base d:\rdb\exper form f1 rel a . . . endform Имя отношения, соответствующего форме, является одним из атрибутов, наследуемых формой, производной от данной. В частности для производной формы можно указать другое имя соответствующего ей - 29 - отношения. Более того, имя отношения можно не задавать вплоть до операции открытия выборки (см. оператор OPEN). Возможно указание того, что отношение, соответствующее форме будет открываться в монопольном режиме. Это значит, что даже при работе в многопользовательском режиме (в сети или под ОС Unix) работать с таким отношением может одновременно не более одного приложения. Для обеспечения монопольной работы с отношением служит команда private в описании формы. Данные в отношении могут быть зашифрованы (если задавался параметр при создании отношения утилитой rdbutil). Если это так, то невозможен доступ к отношению без указания ключа шифровки отношения. Для этого служит команда psw <ключ> Ключ - это строка. Описание полей формы Описание всех полей соответствующего отношения (allflds) Простейшим случаем описания полей является групповое описание всех полей отноше ния, соответствующего форме. Естественно, что эта команда может применяться только для форм, имеющих соответствующее отношение. Формат команды: allflds Команда вводит в описание формы все поля отношения, соответствующего форме. При этом: - вводятся описания полей отношения, имена которых не совпадают с именами уже опи санных (командой fld) полей формы. - имена и типы определяемых полей формы совпадают с именами и типами полей отно шения. - в экранном представлении бланка поля располагаются в столбик, одно под другим, начиная с 20-й позиции, а их имена расположены слева от полей. - при экранном редактировании все поля "обычные", т.е. они редактируемые, не требуют обязательного заполнения и пр. Приведенных сведений о RatBasic-е уже достаточно для того, чтобы написать мини мальное корректное приложение. После того как мы создали (см. раздел об отношениях) от ношение persons можно смело написать следующую программу на RatBasic: - 30 - -- файл a.dat form persons rel persons allflds endform После этого достаточно подать командную строку ratbase a.dat чтобы вводить и просматривать данные в этом отношении ! Рассмотрим теперь команды, служащие для более "тонкого" описания полей формы. Описание единичного поля формы (fld) Поле формы может быть собственным и несобственным. Несобственное поле формы - это поле, которому соответствует некоторое поле соответствующего форме отношения. В частности все поля, описание котроых вводится командой allflds - несобственные. Кроме та ких полей форма может содержать собственные поля, которые не связаны ни с каким полем отношения, и являются "принадлежностью" только самой этой формы. Описанная ниже ко манда fld служит как для описания новых собственных полей формы, так и - 31 - для изменения некоторых характеристик (расположения, свойств редактирования и значения по умолчанию) полей, унаследованных данной формой от формы-предка. Формат команды fld: fld <имя определяемого поля> <внешнее имя или формат> (то же,что и имя определяемого поля) <место поля> (автоматически) <ред. свойства> (обычное поле) <значение по умолчанию> (никакого) <ид control-a> (0) Если вторым операндом указывается формат (описание форматов полей приведено в разделе об отношениях), то команда определяет собственное поле формы. Если у формы-предка определяемой формы было поле с тем же именем, то новое поле полностью "заслоняет" унаследованное. Пример описания собственных полей и их наследования: - 32 - form a fld i %d fld s %30s endform /* Описана форма, не имеющая соответствующего ей отношения, и содержащая два собственных поля - i типа целое и s - строка длиной до 30 символов. */ form aa a fld i %ld endform /* Форма аа наследуется от а, но описание поля i изменено. Теперь это поле типа длинное целое. Тип поля s в форме аа остается без изменений, т.е. это такая же строка. */ form aaa aa fld s %D fld t %T endform /* В форме ааа изменено описание наследованного поля s (теперь это поле типа да та), кроме того добавлено описание нового собственного поля t типа время. */ Если второй аргумент команды fld не формат (т.е. он не начинается с символа %), то он рассматривается как внешнее имя поля. Внешнее имя поля может быть одним из: - именем поля отношения, на котором базируется форма; - имнем поля формы - предка определяемой; - именем глобальной переменной описанной командой var; - полным именем переменной, т.е. конструкцией <имя выборки>.<имя поля>; - специальным именем (о специменах см. ниже, при описании вывходного потока); Во всех этих случаях тип описываемого поля определяется типом объекта, именуемого внешним именем. Команда fld в этом случае позволяет изменить свойства поля - его распо ложение, - 33 - характеристики редактирования и значение по умолчанию. Приведем пример описа ния полей с использованием внешних имен. - 34 - form pers rel persons allflds endform /* Это наша любимая форма, с соответствующим ей отношением persons из раздела об отношениях. Она (как и отношение) содержит поля num, name, addr, born. */ form персоны persons fld имя name fld адрес addr fld номер num fld рожд born endform /* В качестве внешнего имени во всех командах fld использовано имя поля соответ ствующего форме отношения. Всем полям базовой формы (persons) даются русские имена. */ var today %D /* Описана глобальная переменная today типа дата. Об описании переменных см. ниже. */ form accounts . . . fld sum . . . . . . endform /* Это некоторая "посторонняя" форма, в которой нам важно то, что в ней присут ствует поле sum. */ form см_персоны персоны fld номер номер _ E fld сегодня today fld на_счету accounts.sum fld pgz #PgSize endform /* В первой команде fld в качестве внешнего имени использовано имя поля роди тельской формы (в данном случае к тому же результату привела бы команда fld но мер _ _ E). Результат команды - запрет редактирования поля "номер" в форме см_персоны. Вторая команда использует в качестве внешнего имени имя описанной ранее глобальной переменной. В результате поле "сегодня" будет совпадать по значению с переменной today. Более того - это в действительности два имени для именования одного и того же объекта. - 35 - Похожая картина в третьем случае. Отныне поле "на_счету" - это то же самое (по значению) что и поле sum формы accounts. Четвертая команда fld здесь достаточно бессмысленна, и приведена только для иллюстрации. #PgSize - это специальное имя, соответствующее установленной в вы ходном потоке высоте страницы. Теперь к этому значению возможен доступ через поле pgz. */ Место поля (третий аргумент команды fld) - конструкция <строка>:<колонка>:<длина>:<высота>, например 10:10:20. Аргумент определяет положение и длину поля на экране при экранном редактировании в виде бланка. Для "длинных" строк может иметь смысл указать и высоту поля - при этом поле действительно будет занимать в бланке более одной строки. Отметим, что "экранная" длина поля может быть как больше, так и меньше необходимой для его изображения. Если этот аргумент опущен, то: - при описании собственного поля формы оно размещается автоматически, под после дним имеющимся полем бланка, начиная с 20-й колонки. - при использовании команды fld для модификации характеристик унаследованного поля расположение поля также наследуется. Свойства редактирования поля - это строка из букв E, Z, C, B, T. Каждая из букв ус танавливает полю некоторый признак, определяющий "поведение" поля при экранном редак тировании. Смысл букв: E - поле нередактируемое, при редактировании в бланковом виде курсор в это поле по падать не будет, тем самым оператор не сможет изменять его значение. Z - поле не очищается при выполнении оператора "очистка бланка". Это может быть удобно, если форма предназначена для ввода записей с повторяющимися значениями полей - те поля формы, значения которых будут изменяться редко можно сделать "неочищаемыми", и не заполнять их каждый раз при вводе новой записи. C - при вводе или модификации записи в процессе экранного редактирования поле, об ладающее данным признаком обязательно должно быть определенным, т.е. содер жать непустое значение. B - при экранном редактировании поле не входит в бланк, изображающий запись формы и в таблицу, представляющую множество записей. T - при экранном редактировании в табличном виде поле в таблицу не входит. Заметим, что в таблицу могут входить только поля, входящие в бланк. - 36 - Значение по умолчанию это строка, представляющая собой значение, которое будет присваиваться полю при выполнении оператора "заполнить бланк (или поле) значениями по умолчанию". Последний аргумент команды fld имеет смысл только при работе под MS WIndows и только если указано имя внешнего dialog box-a в описании формы (команда picfile). В этом случае аргумент является идентификатором control-a соответствующего описываемому полю формы. Подробнее о взаимодействии с внешним dialog box-ом см. описание команды picfile. Поля типа выбор, case-дескрипторы (casefld, case, endcase) Часто встречается ситуация, когда строковое поле принимает значения из небольшого множества. Пример - пол (мужской / женский), тип документа (паспорт / свидетельство о рождении / справка об освобождении) и т.п. Для удобства представления и компактного хра нения таких полей в RatBase применяются поля типа выбор (они же case-поля). Перед объявлением поля полем типа выбор необходимо явно перечислить те строковые значения, которые может принимать поле. Это делается путем описания (вне описания фор мы!) так называемого case-дескриптора. Описание case-дескриптора выглядит следующим об- разом: case <имя case-дескриптора> . . . варианты текстовых значений поля, по одному на строку . . . endcase В частности case-дескрипторы для вышеприведенных примеров запишутся так: - 37 - case sex_case мужской женский endcase case doc_type паспорт свидетельство$о$рождении справка$об$освобождении endcase Напомним, что знак доллара ($) в текстах на RatBasic-е обозначает пробел. После опи сания case-дескриптора его имя можно использовать для объявления какого-либо поля фор мы полем типа выбор. Для этого предназначена команда casefld в описании формы. Ее фор мат: casefld <имя поля> <имя case-дескриптора> Указанное поле определяется как поле типа выбор, с приведенным дескриптором. При этом: - если поле с указанным именем уже было описано, то оно должно иметь целый или строковый тип, - если же такого поля в имени формы еще не было, то автоматически создается (собственное) поле с данным именем и целым типом. Например, если мы захотим ввести в форму persons информацию о сексуальной при надлежности персоны, то: - В отношение persons надо добавить поле типа целое, с именем, например, sex. - В программе привести указанное выше описание case- дескриптора. - В описании формы persons иметь строку - 38 - casefld sex sex_case Заметим также, что следующие описания эквивалентны: form ... . . . fld i %d casefld i sex . . . endform и - 39 - form ... . . . casefld i sex . . . endform Еще два замечания относительно полей типа выбор. 1) Команда casefld может встречаться не только в описании формы но и на верхнем уровне описания (в этом случае она относится к глобальным переменным), и в описании про цедур (при этом команда описывает локальную переменную процедуры). В этих случаях также создается новая переменная целого типа, если ее до сих пор не было. 2) Как было сказано аргументом команды casefld может быть и поле строкового типа. Объявление строкового поля полем типа выбор только упрощает ввод в это поле одного из значений case- дескриптора (см. о экранном редактировании). В остальном это поле не изме няет своих свойств. Поля-массивы (array) В RatBasic-е есть возможность работы с переменными-массивами. Понятие массива в общем совпадает с общепринятым - это переменная, содержащая набор однотипных значений, обращение к которым возможно по их номеру, называемому индексом массива. Для описания массива служит команда array, а для работы с элементами массива слу жат операторы getel и putel (см. раздел "Операторы"). Команда array, так же, как и команда casefld может встречаться не только в описании формы, но и на внешнем уровне описаний, и в теле процедур. Формат команды array: - 40 - array <имя переменной> <тип элемента> <размерность> () Переменная, имя которой указывается первым параметром, должна иметь тип массива байтов. Если такой переменной нет, то она создается (как и в случае с casefld). Тип элемента задается форматом, как для виртуальных полей. Размерность - число, определяющее количество элементов в массиве. Если команда array применяется к уже существующей переменной, то происходит проверка на возможность размещения в этой переменной нужного числа элементов массива. В этом случае размерность может быть опущена, количество элементов будет определено исходя из реального размера переменной. Если при выполнении команды array происходит создание новой переменной, то раз мерность обязательна, и определяет реальное количество элементов массива. Пример: form a . . . fld ar1 %100b array ar1 %d -- массив целых из 50 (100 / длину целого) элементов array ar2 %20s 100 -- массив из 100 строк длиной до 20 символов каждая . . . endform Уникальное поле, автоматическая генерация значений поля (uniq) Часто всречается ситуация, когда значение какого-либо поля формы должно быть уни кально в пределах отношения, соответствующего этой форме. С этим требованием бывает связана необходимость автоматической генерации таких уникальных значений при добавлении - 41 - новых записей в форму. Команда uniq в описании формы реализует эти возможности. Ее формат: uniq <имя индексированного поля отношения> <префикс ключа> () ВНИМАНИЕ! Первый параметр - это имя поля ОТНОШЕНИЯ, соответствующего фор ме, а не самой формы. Поле это обязательно должно быть индексировано. Допустимый тип поля - целое, длинное целое или строка. В описании формы может быть не более одного описания unic-поля. Команда указывает, что значения в указанном поле должны быть уникальны в пределах отношения. Действие команды слегка различается, в зависимости от того, указан ли второй аргумент. Если второй параметр не указан, то единственное к чему приводит описание поля как unic - контроль уникальности значения поля при добавлении и модификации записей соот ветствующими операторами. Попытки добавления / модификации записи такие, что нару шится уникальность значений данного поля, будут неудачны. Если второй параметр указан, то кроме контроля на уникальность значений поля про изводится автоматическая генерация этих значений при занесении новых записей. Для полей типа целое и длинное целое значение префикса ключа не важно, а значения записей будут генерироваться начиная с 1. Каждая новая добавляемая запись будет содер жать в этом поле значение, равное максимальному из имеющихся плюс 1. Для поля типа строка второй параметр действительно определяет префикс генерируе мого значения поля. Так, для префикса ABC в текстовом поле шириной 8 символов при до бавлении записей в поле будут записываться значения ABC00001, ABC000002 и т.д. Заметим, что автоматическая генерация значений поля позможна только для тех полей, индексы по которым поддерживают упорядоченность, т.е. для типов индексов BF, DF, HF (см. об описании индексов в отношении). Предположим, что в нашей форме persons мы хотим иметь автоматическую генерацию значений в поле num при добавлении записей. Для этого надо: - иметь поле num в отношении индексированным, например индексом типа DF, как наи более подходящим для данного случая; - в описании формы persons записать: - 42 - form persons rel persons allflds fld num num _ E uniq num A endform Заметим, что так как поле num типа целое, то значение указанного префикса роли не играет. Поле num в форме описано нередактируемым, чтобы отмести попытки самому зано сить в него значения - все равно они будут неудачны. Поле - счетчик изменений (updcnt) При многопользовательской работе (а RatBase - многопользовательская СУБД) воз можна одновременная модификация разными операторами одной и той же записи отношения. Для отслеживания таких ситуаций (а на самом деле и не только для этого) служат команды updcnt и same. Формат команды updcnt: updcnt <имя поля отношения> ВНИМАНИЕ! Параметр - это имя поля ОТНОШЕНИЯ, а не формы. Поле должно иметь тип целое или длинное целое. Данная команда объявляет поле "счетчиком изменений записи", т.е. при каждой модификации записи значение в этом поде будет увеличиваться на 1. В форме может быть не более одного поля, описанного как updcnt. "Неизменяемое" поле, защита от одновременных изменений (same) "Неизменяемое" заключено в кавычки не напрасно - конечно это поле можно изменять, но при модификации записи в форме содержащей - 43 - такое поле возможна проверка - измени лось ли значение поля во время между считыванием записи и ее модификацией. Формат ко манды: same <имя поля отношения> ВНИМАНИЕ! Параметр - это имя поля ОТНОШЕНИЯ, а не формы. Команда указывает, что данное поле должно сохранять свое значение при модификации записи. Оператор моди фикации (см. ниже об операторах") имеет режим, который позволяет отследить попытки мо- дификации таких полей. В форме может быть не более одного поля, описанного как updcnt. Совместное использование команд same и updcnt позволяет обнаружить попытки одно временной модификации записей разными пользователями. Предположим, что мы хотим за щитить от такой модификации записи формы persons. Для этого достаточно иметь следующее описание формы persons (предположим, что отношение и форма содержат поле chk типа це лое): form persons rel persons allflds fld chk _ _ B updcnt chk same chk endform При модификации записей в этой форме надо пользоваться вариантом оператора мо дификации, проверяющим неизменность same- поля (см. ниже). Если после чтения записи пользователем другой пользователь изменит ее, то при этом увеличится значение updcnt- поля. При попытке модификации записи первым пользователем будет обнаружено неравен ство значений same-поля (все того же поля chk) считанного и текущего. Еще раз к этой теме мы вернемся при описании операторов модификации записей. - 44 - Поле типа указатель (ptr) Описание всех типов полей, рассмотренных до сих пор было полностью определенным в том смысле, что после описания формы известны все характеристики всех ее полей. В от личие от этого некоторые характеристики рассматриваемого здесь поля типа указатель (а именно тип поля и связанная с полем переменная) после описания формы осаются неизвест ными, и должны быть установлены впоследствии при выполнении какой-либо процедуры. Формат описания поля типа указатель следующий: ptr <имя поля> <расположение> (по умолчанию) <ред. свойства> (нормальное поле) После описания поле типа указатель не связано ни с какой реальной переменной или полем формы. Перед любым использованием формы, в которой есть поля типа указатель их надо привязать к каким-либо переменным или полям формы оператором LNK_PTR. В даль- нейшем можно изменять привязку таких полей, т.е. одно и то же поле формы в разные мо менты может быть связано с разными переменными, и принимать значения разных типов ! Смысл и возможные значения второго и третьего параметров совпадают с такими же параметрами в команде fld. Указание порядка записей в форме (index) Строго говоря команда index в описании формы не относится к описанию полей, но так как она имеет аргументом имя поля отношения, то и приведена в полразделе "описания полей". При последовательном просмотре записей формы они располагаются в некотором по рядке, определяемом реализацией файлов данных RatBase. Это не всегда удобно, и часто хочется иметь возможность просмотра записей, упорядоченных по значению одного из полей. Для этого и служит команда index. Ее формат: index <имя поля отношения> ВНИМАНИЕ! Параметр - это имя индексированного поля ОТНОШЕНИЯ, а не формы. Индекс по указанному полю отношения должен иметь тип BF, DF или HF, т.е. поддерживать порядок. В форме может быть не более одной команды index. Последовательный просмотр записей в форме, описание которой содержит команду index будет производиться именно в порядке, определяемом этим индексом, т.е. по возраста нию значений поля. - 45 - Дизайн экрана Под дизайном экрана, применительно к описанию форм, подразумевается: - указание окна на экране, в котором происходит экранное редактирование формы; - описание бланка, т.е. расположения полей и фона; - описание таблицы, включающее описание заголовка таблицы и символа раделителя ко лонок в таблице; - описание цветов объектов, представляющих собой изображение бланка и / или табли цы; - описание кнопок, находящихся в бланке при экранном редактировании. Общий вид экрана при работе RatBase, экранное редактирование После запуска RatBase 6 экран разделен на три области. Верхние две строки экрана предназначены для вывода служебной информации. В частности, во вторую строку выводятся имена редактируемых форм. В нижней строке экрана при экранном редактировании формы находится строка "mini-help"-а, т.е. названия доступных редактирующих клавиш и краткое описание их действия (F2-доб F3- след ...). Вся остальная область экрана - это рабочая область, в которой и произво дится экранное редактирование форм. При экранном редактировании бланк или таблица, представляющие форму располага ются в рабочей области экрана, или в некоторой ее прямоугольной подобласти, называемой окном. Окно может быть окружено одинарной или двойной рамкой. На верхней стороне окна может находиться заголовок совпадающий с именем редактируемой формы, или явно задан ный при описании формы. Размеры и расположение окна, предназначенного для экранного редактирования формы описываются не отдельной командой, а четвертым аргументом команды form (см. выше об этой команде). Если этот аргумент опущен, то ей придается окно, размера минимального для размещения бланка формы, и размещенное в левом верхнем углу рабочей области экрана. 6 Под MS DOS и Unix - 46 - Описание элемента фона бланка (txt) Как уже не раз говорилось, бланк есть совокупность совместно редактируемых полей и фона - т.е. различных надписей, рамок, линий и пр. Если не принимать специальных мер, то поля бланка располагаются одно под другим, начиная с 20-й позиции в окне, а фон представ лен именами полей, расположенными слева от них. Расположение полей в бланке можно изменить, явно задавая указывая третий яргумент (расположение поля) в команде fld. Для того, чтобы описать фон бланка можно воспользо ваться командой txt. Ее формат: txt <строка> <координаты> Координаты (как нетрудно догадаться) - это конструкция <строка> : <колонка>. Они задают расположение строки - первого аргумента - в окне редактирования. Если в описании формы есть хотя бы одна команда txt, то именно она, а не умолчание, будет определять фон бланка. Например описание формы persons, в том виде, как оно приводилось раньше, породит примерно следующий бланк (точками указано расположение полей): num ..... name .............................. addr ...... (80 символов длиной)............. born .......... Если в описание формы добавить команды - 47 - txt Сведения$о$клиентах 5:10 txt ------------------- 6:10 то бланк примет следующий вид: ..... .............................. ...... (80 символов длиной)............. .......... Сведения о клиентах ------------------- Полное описание бланка (pic / endpic) Формирование бланка с помощью задания расположения полей в команде fld и исполь зования команды txt для задания фона неудобно - надо заранее высчитывать (а при модифи кации бланка изменять) координаты всех составляющих бланка. Возможен более простой путь - использование для описания бланка команды pic в описании формы. Описание бланка начинается командой pic и заканчивается командой endpic. Их форматы: - 48 - pic <код разделителя> (2) <длина разделителя> (2) endpic Между pic и endpic располагаются строки описания экранного представления - фон бланка и расположение полей, т.е. собственно "картинка" видимая на экране. В тех местах, где должны располагаться поля должно быть записано имя поля, окруженное последователь ностями символов-разделителей. Такая последовательность должна начинаться с символа с кодом, указанным первым параметром команды pic, а ее длина должна быть равна второму параметру. За именем поля (до завершающей последовательности) может присутствовать нужное число пробелов. Приведем пример описания бланка для формы persons: form persons rel persons allflds pic '#' 1 ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД? 3 Сведения о клиентах 3 ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД' 3 Имя #name # Дата рождения #born # 3 3 3 3 Адрес #addr # 3 3 Примечание #comment # 3 3 #comment # 3 3 3 АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ endpic frame NO endform Обратим внимание на следующие моменты: - в описании формы указано отсутствие рамки (frame NO), чтобы не дублировать рамку, нарисованную в описании бланка; - поле num в описании бланка не встречается, и на экране отображаться не будет; - 49 - - "экранная" длина полей name и addr меньше их реальной длины (30 и 80 символов, со ответсвенно), при экранном редактировании этих полей будет происходить скрол линг; - "излом" правой границы рамки связан с тем, что символы разделители (#) в выводими ом на экран бланке не содержатся, а занимают место только в строке описания бланка, поэтому правая линия рамки сдвинута на число позиций, равное количеству символов разделителей в строке; - "двойное" описание поля comment приведет к тому, что в бланке это поле будет зани мать две строки. На самом деле удобнее в качестве разделяющих последовательностей применять коман ды смены шрифтов, выводимые в выходной файл многими текстовыми редакторами (которыми и производится набор программы на RatBasic). К таким редакторам относятся, в частности, Лексикон и (любимый авторами RatBase) Микромир. Последовательности смены шрифтов, как правило начинаются с какого-либо управляющего символа (в частности для Микромира - символа с кодом 2), и имеют фиксированную длину. Преимущество шрифтового оформления полей в том, что редакторы не отображают на экране символы смены шрифтов, и картинка не искажается (так, как в примере). Кроме того поля в картинке четко выделяют ся типом шрифта или цветом. В частности при подготовке текста программ на RatBasic с помощью Микромира в при веденном выше примере надо сделать следующие изменения: - команду pic '#' 1 заменить на pic 2 2, или просто pic без аргументов - никаких знаков # не ставить - все что находилось между символами разделителями (имена полей и пробелы) офор мить с каким-либо шрифтом, например жирным. При редактировании Микромиром символы текста с "ненормальным" шрифтом выделя ются цветом, что очень удобно при прорисовке экранного представления бланка. Заметим еще, что описание полей бланка после pic "сильнее" чем указание (не)вхождения в бланк в командах fld. Иначе говоря, если в описании формы присутствует команда pic, то в бланк (и таблицу) будут входить ТОЛЬКО поля, присутствующие в описа нии экранного представления. Описание внешнего dialog box-a (picfile, только для MS Windows) При работе под MS WIndows также возможно формирование внешнего вида бланка всеми (почти) командами, описанными в данном разделе. В частности создается бланк по умолчанию, действительны команды txt, pic и пр. Но гораздо удобнее для дизайна бланков применять имеющиеся в MS Windows средства конструирования dialog box-ов, такие напри мер как Resource Workshop фирмы Borland и подобные ему. - 50 - Для использования созданного такими внешними средствами dialog box-a надо проде лать следующие шаги: С помощью Resource Workshop или другого редактора dialog box- ов создать .rc файл, содержащий описание необходимых dialog-box-ов. Посредством какого-либо компилятора построить динамически загружаемую библиотеку (DLL), содержащую в своем проекте .rc файл созданный на первом шаге. Эта DLL может не содержать ничего кроме описаний dialog-box-ов. Функция LibMain, ко торая должна быть в составе любой DLL может быть либо пустой, либо произво дить загрузку других DLL, например BWCC.DLL, содержащую описание оконных классов для оформления dialog-box-а "в стиле Borland". И наконец в описании формы в программе на RatBasic-е указать имя этого dialog-box-а аргументом команды picfile 7. Формат этой команды: picfile <имя dialog-box-а> Имя dialog-box-а имеет формат <имя файла библиотеки (без расширения .DLL)>.<имя dialog-box-а в этой библиотеке>. Например form peoples . . . picfile example.peoples . . . Эффектом такого описания будет то, что бланк описываемой формы будет представлен именно в виде указанного dialog-box-а. В частности dialog-box-ом полностью определяются расположение бланка на экране, (не)редактируемость полей, наличие меню, порядок прохода по полям клавишей и пр. Возникает вопрос - откуда форма "узнает" о control-ах соответствующим ее полям и кнопкам? Идентификаторы control-ов в этом случае указываются последними аргументами в командах fld и 7 При работе в ОС отличных от MS Windows команда picfile также допустима, но не оказывает никакого эффекта. - - 51 button в описании формы или в команде onedit при описания процедуры как редактирующей. Разумеется возможно не любое сочетание типов полей формы RatBase и ти пом control в dialog-box- е. Допустимы следующие соответствия: Поле фромы RatBase типа: Может отображаться на control типа: строка, целое, длинное целое, EDIT дата, время строка, описанная как casefld Combo Box поле типа выбор (casefld), Combo Box, Check Button, 3- целое state Check Button, Radio Button кнопка Push Button Об отображении полей типа выбор. Еще несколько слов о назначении идентификаторов элементам бланка. Полям бланка идентификаторы могут быть назначены ТОЛЬКО командой fld в описании формы. Идентификаторы кнопкам, входящим в бланк, назначаются тремя способами: - процедурам, входящим в стандартный список редактирующих процедур (см. стр. 56 ) идентификаторы назначаются по умолчанию, их значения приведены в описании списка STD_ACTION. - пользовательской редактирующей процедуре идентификатор может быть назначен в команде onedit (стр. ). 75 - наконец можно определить или изменить идентификатор "процедурной" кнопки командой button в описании формы (стр. 57 ). При создании dialog box-а целесообразно включать в проект соответствующего файла ресурсов файл заголовков с именем rdbctlid.h rdbctlid.h rdbctlid.h , входящий в поставку системы. Этот файл содержит #define - описания идентификаторов стандартных редактирующих процедур. Описание символа-заполнителя полей бланка (fld_filler) При работе на монохромном терминале удобно, когда знакоместа в полях бланка, не занятые собственно данными, заполнены каким- либо символом, отличным от пробела. Для этого служит команда ВЕРХНЕГО УРОВНЯ! ( ) - 52 - fld_filler <код символа> Указанный символ будет заполнителем для всех полей всех бланков, за исключением нередактируемых полей, для которых этот символ будет пробелом. Описание таблицы (header / sepch) По умолчанию таблица, представляющая данные формы, обладает следующими качествами: - в таблицу входят все поля бланка, не имеющие признака "Т" среди редактирующих свойств поля (четвертый параметр команды fld); - таблица имеет двухстрочную шапку, в которой заголовки столбцов совпадают с имена ми соответствующих полей формы, а вторая строка - подчеркивающая горизон тальная линия; - столбцы таблицы разделены вертикальными линиями. С помощью команды header можно изменить или отменить шапку таблицы. Формат ко манды: header <текст шапки> (никакого) Если аргумент не задан, то таблица не будет иметь шапку. Если же аргумент команды задан, то он определяет новые заголовки столбцов таблицы. Первый символ текста шапки - символ разделитель, которым далее разделяются заголовки отдельных столбцов. Например, для задания форме persons русских заголовков столбцов, в описание формы можно добавить строку (предполагаем, что поле num в таблицу не входит): header /Имя/Адрес/Дата$рождения Если число заголовков столбцов не равно числу самих столбцов в таблице, то "лишние" заголовки столбцов игнорируются, а "недостающие" принимаются состоящими из пробелов. На ширину столбцов таблицы команда header не влияет. - 53 - Для управления разделительными линиями между столбцами служит команда sepch. Ее формат: sepch <код символа> (код пробела) Аргумент команды - десятичный код символа, которым будут разделяться столбцы таб лицы, если аргумент опущен, то столбцы разделяются пробелами, т.е. разделительных линий нет. Логические цвета экрана (color) По умолчанию все экранные объекты в RatBase имеют цвет белый на черном, а курсор (когда его ширина больше одного символа) наоборот - черный на белом. Эту палитру можно изменить описанными ниже командами. Имеется некоторое множество логических цветов, или атрибутов, таких, как "цвет кур сора", "цвет фона бланка" и т.п. Этим логическим цветам можно (командой color) назначить конкретные "физические" цвета, например задать цвет фона бланка зеленым на белом. После этого, если не принимать дополнительных мер, цвет фона бланка во ВСЕХ редактируемых формах будет именно таков. Назначение физических цветов атрибутам производится ВНЕ описания форм. Для этого служит команда color, формат которой: color <атрибут> <цвет фона> <цвет символа> Первый аргумент может принимать одно из следующих значений: NORMAL - обычный символ CURSOR - цвет "широкого" курсора ERROR - цвет сообщения об ошибке MENU - цвет окон меню QUERY - цвет диалогового запроса (оператор query) INFO - цвет информационной строки (вторая строка экрана) и цвет сообщений, выдавае мых оператором mess BL_TXT - цвет элементов текстового оформления бланка, т.е. надписей и линий BL_FLD - цвет обычного поля бланка BL_PRT - цвет нередактируемого поля бланка BL_BUT - цвет кнопок в бланке SHADOW - цвет тени от окон ATTR1, ATTR2, ATTR3, ATTR4 - дополнительные логические цвета, они не являются умолчаниями ни для каких экранных объектов, но их можно использовать (как и все остальные) для "раскраски" форм. - 54 - Два замечания по поводу атрибутов. Не все логические цвета относятся к объектам, входящим в бланк или таблицу (и не все из этих объектов были описаны до сих пор). Про меню, операторы и пр. говорится ниже. Второе замечание - операторы, использующие атри- буты (меню, запрос и пр.) имеют аргументы, позволяющие изменять цвет используемого эк ранного объекта, по сравнению с умолчательным. Цвет фона и цвет символа задаются одной из строк: BLACK - черный BLUE - синий GREEN - зеленый CYAN - салатный RED - красный MAGENTA - малиновый BROWN - коричневый LIGHTGRAY - светло-серый DARKGRAY - темно-серый LIGHTBLUE - голубой LIGHTGREEN - светло-зеленый LIGHTCYAN - CYAN, но светлый LIGHTRED - розовый LIGHTMAGENTA - светло-малиновый YELLOW - желтый WHITE - белый Приведем пример приятной для глаза палитры (взятой из реального приложения): color NORMAL LIGHTGRAY BLACK color BL_FLD BLUE YELLOW color BL_TXT LIGHTGRAY BLACK color BL_PRT LIGHTGRAY BLACK color BL_BUT MAGENTA YELLOW color MENU BLUE YELLOW color CURSOR GREEN BLACK color ERROR RED YELLOW color QUERY RED YELLOW color INFO BLUE YELLOW - 55 - Стили оформления окон форм (style, endstyle, txtattr, fldattr, prtattr, butattr, frmattr, titattr, frame) Окна для экранного редактирования форм допускают более тонкую настройку цветов, а также вида рамки, с использованием СТИЛЕЙ ОФОРМЛЕНИ_ ОКОН , которые в дальнейшем будем называть просто стилями. Стиль содержит информацию о цветах фона, простых и защищенных от редактирования полей бланка, кнопок, рамки и надписи на рамке. Кроме того стиль определяет наличие и вид рамки и тени от окна. Стили поименованы. Изначально имеется один предопределенный стиль с именем STD_STYLE. В программе на RatBasic-е пользователь может определять новые стили, произ водя их от уже существующих. Для определения нового стиля служит команда (верхнего уровня, а не в описании формы!): style <имя определяемого стиля> <стиль-предок> (STD_STYLE) При описании нового стиля стиль-предок копируется в него. Заканчивается описание стиля командой endstyle без аргументов. Между командами style и endstyle располагаются описанные ниже ко манды описания стиля. txtattr <цвет> (BL_TXT) fldattr <цвет> (BL_FLD) prtattr <цвет> (BL_PRT) butattr <цвет> (BL_BUT) frmattr <цвет> (BL_TXT) titattr <цвет> (BL_TXT) Цвет - это или имя атрибута, например BL_TXT, или конструкция <цвет фона>:<цвет символа>, где в качестве этих цветов указываются имена физических цветов (BLACK, RED...). Эти команды определяют: txtattr - цвет фона и текстовых элементов бланка fldattr - цвет "обычных", т.е. редактируемых полей prtattr - цвет полей, защищенных от редактирования butattr - цвет кнопок frmattr - цвет рамки titattr - цвет заголовка рамки - 56 - Кроме цветов стиль определяет тип рамки окна. Для его задания служит команда frame <свойство рамки> (SINGLE) <свойство рамки> () <свойство рамки> () <свойство рамки> () Для определения типа или отсутствия рамки служат следующие свойства: NO - окно без рамки SINGLE - одиночная рамка DOUBLE - двойная рамка Если окно должно быть с тенью, то необходимо указать свойство SHADOW. Для опре деления выравнивания или отстутствия заголовка на верхней границе рамки служат свойства: NO_TITLE - заголовок отсутствует LEFT_TITLE - заголовок выровнен к левой границе окна RIGHT_TITLE - заголовок выровнен к правой границе окна Если не указано ни одно из этих свойств, то заголовок располагается посередине вер хней границы рамки. Следует заметить, что команды описания стиля могут всречаться на верхнем уровне и в теле описания формы. Если эти команды встречаются на верхнем уровне, то они переопреде ляют "умолчательный" стиль STD_STYLE. Если же эти команды встечаются в описании фор мы, то они переопределяют стиль именно этой формы. Использование стилей в описании формы (style) После определения стиля его можно использовать при описании формы. Для этого служит команда style В ОПИСАНИИ ФОРМЫ . Не путайте ее с командой описания стиля! Формат команды: style <имя стиля> <заголовок окна> () Аргументы команды - имя стиля, применяемого для оформления данной формы, и нео бязательная строка - заголовок окна. Если заголовок не указан, то заголовком (если он во обще разрешен) будет имя формы. Явное указание заголовка перекрывает свойство рамки NO_TITLE, т.е. даже при установленном NO_TITLE заголовок будет выведен. - 57 - Описание цвета отдельного поля формы (fldcolor) Как уже говорилось, с использованием стилей возможно задать цвета для двух типов полей бланка - редактируемых (fldattr) и нередактируемых (prtattr). Кроме того можно явно задать цвет конкретного поля. Для этого применяется команда fldcolor <имя поля> <цвет> () Цвет (как и в командах описания стилей) это либо атрибут, либо конструкция <цвет фона>:<цвет символа>. Списки редактирующих процедур (editby) Забегая несколько вперед скажем несколько слов о процедурах, что необходимо для понимания изложенного далее. В RatBasic-е процедура определяет последовательность дей ствий, производимых над различными объектами среды выполнения. Для нас пока важно знать, что каждая процедура имеет уникальное имя. Процесс экранного редактирования основан на вызове некоторых процедур в ответ на нажатия клавиш. При описании процедуры она может быть "оснащена" кроме имени связан ной с ней клавишей, и "кратким именем" (например "След", "Пуст"). С каждой формой свя зан список процедур, которые могут быть вызваны при ее редактировании в ответ на нажатие клавиш. Этот список называется списком редактирующих процедур. Как описываются процедуры, предназначенные для экранного редактирования формы описано далее - в разделе о процедурах. Здесь рассмотрим то, как процедуры формируются в списки, и как такие списки привязываются к форме. Для группировки процедур в списки служит описанные выше команды описания списка (listof proc, endlist, copy). Для того, чтобы указать, с помощью какого списка процедур дол жна редактироваться описываемая форма, служит команда editby в описании формы. Ее формат: editby <имя списка процедур> Приведем пример описания списка редактирующих процедур. - 58 - define proc compute define proc find define proc addnew /* Задано предописание процедур, а сами они должны быть описаны где-то дальше в программе. Смысл процедур для этого примера не важен. */ listof proc pers_ed compute find addnew endlist /* Список из описанных выше процедур */ form persons . . . editby pers_ed . . . endform /* Указано, что форма persons редактируется списком процедур pers_ed. */ Стандартный список редактирующих процедур Если описание формы не содержит команду editby, то по умолчанию форма снабжается "стандартным" списком редактирующих процедур. Этот список имеет имя STD_ACTIONS, и доступен точно так же, как и все остальные списки процедур. В следующей таблице приведено краткое описание процедур, входящих в список STD_ACTIONS, а также связанных с ними идетификаторов control-ов (для работы в MS Windows). Фактически эта таблица содержит аргументы команд onedit, вызываемых после описания соответствующих процедур. - - 59 Краткое Полное название Клави Идентификат Значение название ша ор идентификат ора Спис Таблица F1 TOTABLE_ID 210 Карт Бланк F1 TOBLANK_ID 211 Возврат Перенос Enter RETLINK_ID 213 След Следующая запись PgDow NEXTREC_ID 214 n Пред Предыдущая запись PgUp PREDREC_ID 215 Ввод Добавить или F2 ADDUPDREC_I 216 изменить D Пуст Пустая запись F5 EMPREC_ID 217 Уд Удалить запись F8 DELREC_ID 218 Связь Выбор и переход по Sh GOLINK_ID 219 формы связи F10 Связь Переход по связи F10 GOFLDLINK_I 220 D Усл Ввод условия Sh F3 GETCND_ID 221 Кроме редактирования посредством редактирующих процедур имеется ряд клавиш, про извлдящих некоторые низкоуровневые операции редактирования. К ним относятся: F6 - очистка единичного поля бланка F4 - вызов меню редактирующих клавиш. По нажатию этой клавиши на экран выводится меню, состоящее из названий редактирующих процедур для данной формы. По на жатию Enter на какой-либо строке вызывается соответствующая процедура, по нажатию Esc - ничего не происходит. ShF4 - "раскрытие" поля типа выбор или текстового поля, максимальная длина которого больше, чем размер поля в бланке. Поверх бланка накладывается дополнительное окно. Для поля типа выбор в этом окне все варианты выводятся в менюподобном виде. Для длинного текстового поля в дополнительном окне работает простой тек стовый редактор. Tab - переход к следующему полю бланка. ShTab - переход к предыдущему полю бланка. - 60 - Кнопки в бланке (button) До сих пор почти не упоминался такой элемент экранного представления формы как кнопка. Кнопка - это поле бланка специального вида, связанное с одной из редактирующий процедур формы. Если при редактировании бланка курсор находится на поле - кнопке, то после нажатия в этот момент Enter вызываентся соответствующая процедура. В бланке поля -кнопки заключены в квадратные скобки. Рассмотрим процесс попадания кнопок в бланк. Множество кнопок бланка образуют те из редактирующих процедур описываемой формы, чьи краткие имена начинаются с точки. По умолчанию кнопки располагаются в первой строке бланка. Если первая строка бланка была занята полями или фоном, то все изображение бланка смещается на экране вниз на одну строку. Текст в кнопке образуется из краткого имени соответствующей процедуры (без начальной точки) и названия клавиши, запускающей эту процедуру. Изменить расположение кнопки и ее текст можно с помощью команды button в описа нии формы. Ее формат: button <краткое имя процедуры> <текст кнопки> (совп. с именем) <координаты> (в первой строке) <ид control-a> (0) Если в описании формы применяется команда pic, то удобнее указывать размещение кнопок непосредственно на картинке бланка. Кнопки в картинке выделяются так же, как и поля (символами разделителями). Первым символом в изображении поля-кнопки должна быть "[", а последним - "]". Последний аргумент команды button совпадает с таковым в команде fld и имеет смысл только при работе под MS WIndows и только если указано имя внешнего dialog box-a в опи сании формы (команда picfile). В этом случае аргумент является идентификатором control-a соответствующего описываемой кнопке. Подробнее о взаимодействии с внешним dialog box-ом см. описание команды picfile. Если у процедуры "привязываемой" к кнопке уже задан (командой onedit) идентификатор control-a, то явно заданный в команде button идентифика тор перекрывает прежнее описание. В качестве идентификатора может быть указано либо целое число, либо одна из строк: IDOK, IDCANCEL, TOTABLE_ID, TOBLANK_ID, NEXTFLD_ID, RETLINK_ID, IDOK, IDCANCEL, TOTABLE_ID, TOBLANK_ID, NEXTFLD_ID, RETLINK_ID, IDOK, IDCANCEL, TOTABLE_ID, TOBLANK_ID, NEXTFLD_ID, RETLINK_ID, NEXTREC_ID, PREDREC_ID, ADDUPDREC_ID, EMPREC_ID, DELREC_ID, NEXTREC_ID, PREDREC_ID, ADDUPDREC_ID, EMPREC_ID, DELREC_ID, NEXTREC_ID, PREDREC_ID, ADDUPDREC_ID, EMPREC_ID, DELREC_ID, GOLINK_ID, GOFLDLINK_ID, GETCND_ID GOLINK_ID, GOFLDLINK_ID, GETCND_ID GOLINK_ID, GOFLDLINK_ID, GETCND_ID . Описание отчетов Одним из наиболее "мощных" операторов вывода является оператор вывода отчета - report. Для использования всех его - 61 - (оператора) возможностей в описание формы вводятся специальные конструкции, описанные в данном разделе. Секции и команды в описании бланка В описании экранного представления бланка с помощью команды pic кроме описания собственно экранных элементов (полей, фона и кнопок) могут встречаться строки специаль ного вида, управляющие выводом отчета основанного на описываемой форме (оператор report), и выводом изображения формы (команда out_form). Такие строки содержат в первой позиции символ точки ("."). Специальные строки бывают двух видов: команды и заголовки секций. При выводе формы, содержащей строки с командами (операторами report и out_form) вместо вывода бу дут выполняться эти команды. Заголовки секций разбивают всю картинку на несколько частей, называемых секциями. Секция начинается со строки, следующей за ее заголовком, и оканчивается перед следующим заголовком секции (или последней строкой, если секций больше нет). Команда в описании бланка - это одна из следующих строк: .cont - если эта команда указывается перед строкой картинки, содержащей поля, реаль ная длина которых больше экранной длины поля, то эта строка "размножается" число раз, нужное для того, чтобы длинное поле полностью вывелось в выходной поток. При этом "размножаются" только собственно поля, но не элементы фона в этой строке. Команда .cont действует только на одну, следующую за ней строку. .contb - подобна команде .cont, за исключением того, что элементы фона в строке, сле дующей за командой, также "размножаются". Это удобно, например, при выводе колоночных отчетов, когда выводимая строка содержит символы - разделители колонок. .squ - включает режим сжатия пробелов, при этом последовательности пробелов в выво димых строках (кроме самой первой) будут ужиматься до одного пробела. .nosqu - отменяет режим сжатия пробелов. .call <имя процедуры> - вместо вывода этой строки происходит вызов процедуры с ука занным именем. .split - объявляет, что секция, в которой содержится эта команда, может разрываться при выводе переводом страниц. Этот режим включен по умолчанию для каждой секции. .nosplit - указывает, что секция не должна (по возможности) разрываться переводами страниц. Если начиная с текущей строки на странице не хватает места для разме щения секции, то секция печатается с новой страницы. Если эта команда задана, то она должна следовать непосредственно за заголовком секции. .page - выполнение этой команды состоит в переводе страницы (и печати завершителя и заголовка страниц в отчете, если они заданы). .header_page_off - при переводе страницы в процессе печати секции не будут выводиться завершитель и заголовок - 62 - страницы, даже если они заданы в отчете. Отметим, что если секция в самом начале содержит команды .header_page_off и .page, то завер шитель предыдущей страницы будет (или не будет) выдан в соответствии с режи мом, установленным при выводе предыдущей секции. .header_page_on - включает режим вывода заголовков и завершителей страниц. Этот ре жим действует по умолчанию для каждой секции. Все остальные строки, содержащие точку в первой позиции считаются заголовками секций. Именем секции считается строка после точки. Разбиение картинки на секции приме няется при выводе отчета, а также в качестве аргумента команды out_form. Если первая строка картинки не является заголовком секции, то считается, что с первой строки начинается неименованная секция. Пример разбиения картинки на секции и применения команд см. в разделе об отчетах. Команды описания отчетов (group, sum, num) Одной из важнейших функций СУБД является выдача отчетов, т.е. создание текстовых файлов, содержащих определенным образом структурированную информацию из базы данных. RatBase также позволяет делать это. Вообще-то любой отчет можно получить, написав соот ветствующую программу на RatBasic-е, но для двух (весьма распостраненных) типов отчетов процесс их получения может быть заметно упрощен путем описания отчетов и вызова (одного) соответствующего оператора. RatBase поддерживает автоматическую выдачу простых, или линейных отчетов, которые мы будем называть далее просто отчетами, и кросс-отчетов. Кросс-отчеты описаны в следу ющем разделе. Вывод простого отчета состоит в линейном проходе по всем записям формы, и выводу каждой записи. ВНИМАНИЕ! Обращаем внимание на то, что при выводе отчета записи выводятся в по рядке их ПОСЛЕДОВАТЕЛЬНОГО ПРОСМОТРА . Переупорядочения записей при этом не происходит. Если этот порядок не подходит, то надо воспользоваться опцией S оператора report (см. стр. 116 ), которая вызовет предварительную сортировку записей в нужном порядке. Введем понятие группы отчета. Группой отчета по некоторому полю будем называть непрерывную последовательность записей формы, в которых значение этого поля одинаково. Группы могут быть вложены - например группировка по подразделениям предприятия, а внутри них - по отделам. Как правило в начале и конце групп должны выводиться какие-то заголовки и завер шители. Кроме того очень часто необходимо - 63 - производить суммирование некоторых полей в пределах группы (итого по отделу...) и нумерацию выводимых записей и групп. Описание отчетов в RatBasic состоит из указания команд group, sum и num в описании формы и специальном разбиении картинки, заданной командой pic. Команда group в описании формы имеет формат: group <имя поля описываемой формы> <поле с предыдущим значением> () Она указывает, что при выводе отчета будет производиться группирование по этому полю. В описании формы допускается до пяти вложенных групп. Вложенность групп опреде ляется последовательностью команд group. Для того, чтобы отслеживать изменение значения поля группы необходимо при перехо де от записи к записи иметь его предыдущее значение. Имя поля, в котором будет храниться это значение указывается вторым аргументом команды. Если второй аргумент опущен, то в форму автоматически добавляется поле с именем равным первому аргументу команды, зак люченному в круглые скобки. Тип и характеристики этого поля те же, что и у поля группы. Если второй аргумент указан явно, то тип этого поля должен совпадать с типом поля группы. Команда sum служит для указания полей, в которых будут автоматически суммиро ваться значения некоторых числовых полей формы. Она имеет формат: sum <имя числового поля> <сумматор по всему отчету> () <сумматор по 1-й группе> () <сумматор по 2-й группе> () <сумматор по 3-й группе> () <сумматор по 4-й группе> () <сумматор по 5-й группе> () Первым аргументом команды указывается имя числового поля группы, значение кото рого на каждом шаге вывода отчета (т.е при переходе к очередной записи формы) будет при бавляться к сумматорам, заданным остальными аргументами. Сумматоры должны быть также числовыми полями той же формы. Нумерация групп определяется порядком команд group. В начале вывода отчета все сумматоры обнуляются. "Групповые" сумматоры также обнуляются перед началом вывода следующей группы - своей или более высокого уровня. Если некоторые сумматоры не указаны, то суммирования по этим группам (или по всему отчету) не происхо дит. В команде sum должен быть указан хотя бы один сумматор. В описании формы допус тимо до пяти команд sum. Для автоматической нумерации выводимых записей и групп служит команда num. Ее формат: - 64 - num <номер по отчету> () <номер в группе> () <номер 1-й группы> () <номер 2-й группы> () <номер 3-й группы> () <номер 4-й группы> () <номер 5-й группы> () Все аргументы команды - имена полей целого или длинного целого типа из определяе мой формы. Должен быть задан хотя бы один аргумент. В начале вывода отчета всем счетчикам приваивается 0. Номер по отчету увеличивается на 1 перед выводом каждой записи (сквозная нумерация). Номер в группе определяет нумерацию записей в пределах самой младшей группы, и сбрасывается при начале вывода каждой группы. Остальные счетчики оп ределяют нумерацию соответствующих групп в пределах группы более старшего уровня. Вид информации представляющей отчет определяется специальным разбиением на сек ции изображения формы, задаваемого командой pic (о секциях см. в предыдущем разделе). В описании картинки можно задать следующие секции (приводятся их имена и описание): .header - заголовок отчета, выводится в самом начале вывода отчета, до вывода первой записи. .footer - завершитель отчета, выводится после вывода всех записей. .header_имя_группы - заголовок группы, выводится перед выводом последовательности записей, составляющих группу. Имя_группы - это имя переменной, указанной в одной из команд group. .footer_имя_группы - завершитель группы, выводится после вывода всех записей, со ставляющих группу. .item - эта секция будет выводиться при выводе каждой записи отчета. Если секция с именем .item не задана, то будет выводиться неименованная секция картинки. .header_page - заголовок страницы, если эта секция задана, то она будет выводиться в начале каждой выводимой страницы. .footer_page - завершитель страницы, если эта секция задана, то она будет выводиться в конце каждой выводимой страницы. Приведем пример описания отчета с использованием указанных команд. Для примера возьмем все ту же форму persons с данными о сотрудниках. Дескриптор ее отношения следу ющий: - 65 - persons.hp 7 0 name %s dep %d salary %lf sex %d marr %d born %D childr %d Мы предполагаем, что записи в форме упорядочены нужным образом. Программа, печатающая отчет по сотрудникам с подведением итогов по зарплате и количеству детей как по каждому отделу, так и по всему предприятию может иметь вид: -- описание дескрипторов case-типов case sex мужской женский endcase case marr холост женат разведен вдов endcase case dep социального$обеспечения программного$обеспечения иностранных$сношений БУХГАЛТЕРИЯ endcase form r_persons - 66 - rel persons allflds casefld sex sex casefld marr marr casefld dep dep /* описание виртуальных полей - сумматоров по отчету и группе */ fld dep_child %d fld dep_salary %lf fld tot_child %d fld tot_salary %lf fld today %D -- группируем по отделам group dep -- указываем сумматоры для зарплаты и количества детей sum salary tot_salary dep_salary sum childr tot_child dep_child -- Поле для номера страницы fld pgn #PgNum /* Приводим картинку с разбиением на секции */ pic '#' 2 .header Отчет о сотрудниках за ##today ## .header_dep .page Ъ ------ ------ ------ ------ ------ ------ ------ ----c _ Отдел ##dep ## _ Г ------ ------ ------ ---В-- ------ -В---- ------ ----_ _Имя _Оклад _детей _ .item _ ##name ##_##salary ##_##childr ## _ .footer_dep Г ------ ------ ------ ---Б-- ------ -Б---- ------ ----_ _ Итого по отделу ##(dep) ##: _ - - 67 - - А - -- - - - - - - -- - - - - - - - - - - - - - - - -- - - - - - - - - - -Щ - - - - - - .footer Суммарный оклад по предприятию: ##tot_salary##, всего ##tot_child## детей .header_page Страница ##pgn ## endpic _ ##dep_salary## ##dep_child## _ endform /* Главная процедура открывает форму и выводит отчет оператором report. */ proc main output 'rep.txt 100 open r_persons today r_persons.today report r_persons out_close close r_persons endproc В результате получится отчет примерно такого вида: Отчет о сотрудниках за 04.11.93 [* Перевод страницы *] Страница 2 - - - - - Ъ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -c - - - - - - _ Отдел программного обеспечения _ - - - - - Г - - - - - - - - - - -В - - - - - - - - - - - - - -В - - - - - - - -_ - - - - - - _Имя _Оклад _детей _ _ Лазарев _100000.00_10 _ _ Моностырский _200000.00_1 _ _ Талалаев _300000.00_1 _ _ Орищенко _20000.00 _ _ - Г - - - - - - - - -- - - - -Б - - - - - - - - - - - - - - - -Б - - - - - - -- -- -_ - - _ Итого по отделу программного обеспечения : _ _ 620000.00 12 _ - - А - -- - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - 68 - - Ъ - -- - - - - - - -- - - - - - - - - - - - - - - - -- - - - - - - - - - -c - - - - - - _ Отдел социального обеспечения _ Страница 3 - - - - - Г - - - - - - - - -В - - - - - - - - - - - - - - - - - - - - - - -В -_ - - - - - - _Имя _Оклад _детей _ _ Колобова _250000.00_11 _ _ Сажнева _120000.00_100 _ - - - - - Г - - - - - - - - -Б - - - - - -- - - - -- - - - - - - - - - - -Б -_ - - - - -- _ Итого по отделу социального обеспечения : _ _ 370000.00 111 _ -- А - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - -Щ - - - - - Суммарный оклад по предприятию: 990000.00 , всего 123 детей Связи Одно из важнейших понятий в RatBase - это СВ_ЗЬ между формами называемая далее просто связью. Связь соединяет две (не обязательно различных) формы. Связь несимметрична, одна из форм называется главной, а вторая связан ной. Связь включает в себя УСЛОВИЕ СВ_ЗИ СПИСОК ОБ и МЕНА . Назначение условия связи - определение подмножества записей связанной формы. Список обмена можно представить себе как канал переноса информации между формами, со ставляющими связь. Связи применяются для: - реализации одного (но весьма частого) метода автоматического вычисления полей форм, при котором значения полей копируются из связанной формы в главную по спискам обмена; - перехода от экранного редактирования главной формы к редактированию связанной, при этом множество "видимых" записей в связанной форме ограничено условием связи; - 69 - - определения подформ, т.е. отображения в табличном или бланковом виде записей, со держащихся в связанной форме, и изменение этого изображения синхронно с из менением главной формы. Элементы описания одной связи встречаются при описании как главной, так и связан ной форм. Описание связей в главной форме (link, Link) В главной форме при опиании связей могут встречаться команды link и Link. Они слу жат для указания форм, связанных с определяемой и для (необязательгного) придания имени связи. Формат этих команд: link (или Link) <имя формы> <имя связи> (первый аргумент) Команды указывают, что от данной формы есть связь к форме - первому аргументу. Такая форма не обязана уже быть описана - если это так, то происходит неявное предописа ние предописание формы. Имя связи - это строка, которой идентифицируется связь среди других связей определяемой формы. Если имя связи явно не указано, то имя связи совпадает с именем связанной формы. Кроме того имя связи появляется в меню при выборе среди всех связей формы. Команда Link полностью аналогична link, за тем исключением, что такая связь не появ ляется в меню "всех связей формы". Описание условия связи и списка обмена (==, !=, >, >=, <, <=, *, *=, ->, ?, !?, #, mainform) В связанной форме определяются условие связи и список обмена по связи. Условие связи определяется с помощью последовательности следующих команд: - 70 - == <имя поля> <переменная> != <имя поля> <переменная> >= <имя поля> <переменная> <= <имя поля> <переменная> > <имя поля> <переменная> < <имя поля> <переменная> * <имя поля> <переменная> *= <имя поля> <переменная> # <имя поля> <переменная> Первый операнд этих команд - имя поля определяемой формы. Естественно, что это поле уже должно быть введено в описание формы тем или иным способом. Вторым операндом могут быть переменные (описанные через var), константы или поля любых уже описанных форм. Для сокращения записи команд условия можно использовать команду mainform <имя формы> В этом случае при записи второго операнда в конструкции <имя формы>.<имя поля> может быть опущено имя формы и точка. Второй операнд при этом будет сначала искаться среди полей последней заданной mainform, а если не будет найден - среди переменных. В описании формы можно записывать несколько команд mainform. Операции == (равно), != (не равно), >= (больше или равно), <= (меньше или равно), < (меньше), > (больше) имеют обычный смысл. Сравнение для строк понимается в лексикогра фическом порядке. Операция * истинна, если первый операнд является подстрокой второго, а *= истинна если второй операнд начинается с первого. Операция # истинна, если второй операнд содержит в себе первый, рассматриваемый как слово (последовательность символов, не содержащая пробелов). Эту операцию условия имеет смысл применять для полей, индекси рованных по словам, т.е. с типом индекса BW (см. о типах индексов). - 71 - В описании формы может быть несколько команд задания единичных условий связи, общее условие связи объединяет их логическим "И". Кроме описанных выше команд, определяющих единичные условия как логическое от ноношение над двумя аргументами имеются еще две команды, которые позволяют задать ус ловие вида "поле (не)определено". Это команды ? <имя поля> и !? <имя поля> Команда "?" задает условие определенности указанного поля, а команда "!?" - его нео пределенности. Список обмена описывается с помощью команды -> <имя поля> <имя поля главной формы> Вторым операндом этой команды может быть ТОЛЬКО поле другой формы, но не пе ременная или константа. Действие mainform распостраняется также и на команду ->. Более того, так как в команде -> второй аргумент это собственно имя поля главной формы (не префиксированный ее именем и точкой), то использование команды mainform перед -> стано вится обязательным. Следует иметь в виду, что команда ==, имеющая в качестве аргументов поля главной и связанной форм, неявно описывает и элемент списка обмена с теми же аргументами. Описание индексирующей формы (indexed_by) Если имеются главная и связанная с ней форма, то связанную форму можно объявить ИНДЕКСИРОВАННОЙ главной. Это означает, что порядок перебора записей в связанной форме будет определяться порядком записей в главной (индексирующей) форме. Чтобы указать индексирующую форму, в описании связанной формы применяется ко манда indexed _by <имя формы> Пример индексирования. Предположим имеется форма, содержащая информацию о клиентах (persons), и в ней имеется поле, содержащее, как составную часть адреса клиента, номер улицы. Имеется также справочник улиц (форма streets), определяющий связь между названием и номером улицы. Следующий фрагмент текста на RatBasic-е приведет к тому, что перебор записей о клиентах будет происходить в алфавитном порядке их улиц. - 72 - form streets fld strtn . . . fld street . . . link persons index street endform form persons . . . fld strtn . . . == strtn streets.strtn indexed_by streets . . . endform Разбиение экрана для изображения подформ (swnd) Как уже говорилось, одно из назначений связей - образование подформ. Подформа отображается в прямоугольной подобласти окна главной формы. Для определения разбиения окна формы служит команда swnd. Эта команда должна указываться в описании главной формы после команд link или Link, и относится к только что определенной связи. Формат команды: swnd <номер подокна> (главное окно) <разбиение> (5) Первый аргумент команды указывает, какое из уже имеющихся подокон (образовнанных предыдущими командами swnd) подвергается дальнейшему разбиению. Соб ственно окно формы имеет номер 0. Каждая команда swnd определяет новое окно, с последо вательно увеличивающимися номерами. Второй аргумент определяет, как надо разделить ука занное подокно для получения нового. Если он больше 0 - то это номер строки по которой делится подокно, а если меньше 0 - номер колонки. Бланковое или табличное представление подформы определяется третьим аргументом открывающей ее команды form. Если он равен T - 73 - или TB - подформа представляется в табличном виде, если B или BT - в бланковом. Пример разбиения экрана и образования подокон: form f . . . link a swnd _ 12 -- делим окно формы в 12-й строке, получаем окно 1 link b swnd _ -40 -- делим главное окно в 40-й колонке, получаем окно 2 link c swnd 1 -40 -- делим окно 1 в 40-й колонке, получаем окно 3 endform В результате этого описания получим такой экран: - 74 - 40 колонка ЪДДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДД? 3 окно главной 3 связь b 3 3 формы 3 3 3 3 3 ГДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДД' 12 строка 3 связь a 3 связь c 3 3 3 3 3 3 3 3 3 3 АДДДДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДДДЩ Пример описания связи Для примера воспользуемся все той же формой persons, содержащей данные о неких клиентах. Предположим, что эта форма содержит еще два поля целого типа с именами acc и total. Смысл поля acc - номер счета клиента, а поля total - общая сумма на счету клиента (будем считать, что разрядности целого хватит для обрабатываемых сумм). Данные об опера циях со счетом хранятся в форме accounts, по одной записи на операцию. Эта форма содер жит следующие поля: Имя поля Тип Назначение accnum целое номер счета date дата дата проведения операции sum целое списано / зачислено (со знаком) opnum целое порядковый номер операции Допустим также, что мы хотим в одном из полей формы persons иметь процент начисления по вкладу клиента. Этот процент зависит от суммы на счету, причем данные об этой зависимости хранятся в форме depo, имеющей следующие поля: Имя поля Тип Назначение - 75 - sum целое при вкладе >= этой суммы percent целое начислить такой процент Опишем связи указанных трех форм необходимые для решения поставленной задачи: - 76 - form persons . . . fld perc %d link accounts swnd _ 10 Link depo . . . endform /* Добавлено собственное поле perc, пересылка значений в это поле будет произво диться за счет списка переноса в описании связи. Связь с формой depo описана ко мандой Link, для того, чтобы к редактированию этой формы нельзя было перейти из редактирования формы persons. */ form accounts _ TB . . . == accnum persons.acc . . . endform /* Описано условие связи, т.к. здесь всего одна команда описания условия, то можно обойтись без mainform. */ form depo . . . index sum mainform persons >= sum total -> percent perc . . . endform /* Описано условие связи и список обмена, для списка обмена (и для удобства) применена команда mainform. */ В результате этого описания: - в поле perc формы persons будет "подтягиваться" по связи нужное значение из формы depo; - 77 - - при экранном редактировании формы persons в подокне (которое будет начинаться с 10-й строки окна формы persons) будут отображаться в табличном виде записи о счетах клиента; - по нажатию клавиши F10 (переход по связи) начнется экранное редактирование формы accounts. Описание хуков (on) Хуками называются процедуры, автоматически вызываемые при наступлении определен ных событий. К таким событиям относятся в частности: переход на следующую / предыдущую запись, добавление новой записи и т.п. По умолчанию форма снабжаются "стандартным" на бором хуков, который можно изменить командой on <имя хука> <имя процедуры> Имя хука может быть именем поля формы. В этом случае хук будет вызываться при выходе из этого поля в процессе экранного редактирования описываемой формы. Такой хук может, например, производить некоторый дополнительный контроль значения в поле. Кроме того именем хука может быть одно из: read (чтение), write (запись), next (переход на следующую запись), pred (переход на предыдущую запись), emp (переход на пустую запись), add (добавление новой записи), del (удаление записи), upd (модификация записи). not_emp (проверка на "пустоту" записи оператором NOT_EMP) Указанная процедура будет вызываться при соответствующей операции с определяемой формой. Отметим, что стандартные хуки состоят в выполнении соответствующего действия (например перехода на следующую запись) и выполнении оператора GET_LINKED. Замечение 1. Даже если поле определено как обязательное к заполнению (флаг C), при наличии хука автоматической проверки на определенность поля не производится. В завмси мости от успеха / неуспеха выполнения хука (подробнее см. о выполнении процедур) про изойдет или нет выход из поля. Замечание 2. Упоминание неописанного имени в качестве имени хука эквивалентно пре дописанию процедуры с таким именем. Описание всех форм базы (allrels) Команда - 78 - allrels неявно описывает формы, соответствующие тем отношениям в базе, имена которых не совпадают с уже имеющимися именами форм. Процедура Как уже говорилось, процедуры в RatBasic-е - "активное начало", определяющее вы полняемые действия. Процедуры вводятся в программу на RatBasic-е посредством описания процедур. Выполнение процедуры может быть инициировано следующими способами: - если в программе имеется процедура с именем main, то она начинает выполняться сра зу же после загрузки программы; - процедура может быть вызвана из другой процедуры посредством оператора call; - если процедура входит в список редактирующих процедур формы, то она будет вызва на при нажатии клавиши, соответствующей данной процедуре. - процедура объявленная как хук автоматически вызывается при наступлении соответ ствующего события (перехода к новой записи, выхода из поля после его модифи кации и пр.); - процедура, упомянутая в команде .call в описании картинки будет вызвана при выводе соответствующей строки командами out_form или report. Кроме того в RatBasic-е имеются средства работы с "экземплярами" процедур, позво ляющие организовать многопроцессную работу на уровне RatBase. Эти средства описаны в соответствующем параграфе раздела "Операторы RatBasic-а". Процедура может иметь параметры. Подробнее параметры процедур описываются ниже, здесь же отметим, что вызов процедур с параметрами возможен ТОЛЬКО оператором call. Во всех остальных случаях должны применяться процедуры без параметров. Описание процедуры (proc, endproc) Описание процедуры начинается командой proc, и заканчивается командой endproc. Последовательность команд, расположенных между этими двумя командами называется телом процедуры. В теле процедуры могут встречаться операторы, некоторые команды и управляю щие конструкции. Команда proc имеет такой формат: proc <имя процедуры> <опция сохранения> () off | line | full (текущий) Опция сохранения - это либо буква S (от слова save), либо пусто. Если вторым пара метром указана буква S, то при каждом - 79 - вызове этой процедуры она сохраняет, а при возвра те восстанавливает текущий контекст активности (о контексте активности см. ниже). Третий параметр определяет уровень отладочной информации для данной процедуры. Работа с инте рактивным отладчиком и описание уровней отладочной информации также приведены ниже. В большинстве случаев второй и третий параметры могут быть опущены. Завершается описание процедуры командой endproc не имеющей аргументов. Описание процедуры как редактирующей (onedit) Частое применение процедур - это использование их в качестве редактирующих для ка кой-либо формы. Чтобы процедура могла быть использована в качестве редактирующей не посредственно после описания процедуры надо записать команду onedit, определяющую "редактирующие" свойства процедуры. Формат команды onedit: onedit () <клавиша> <область применения> (TB) <права> () <ид. control-a> (0) help-строка содержит краткое описание процедуры (например "ввод"). Если эта строка не начинается с точки, то она появится, наряду с другими, в нижней строке экрана при ре дактировании. Если же название help-строки начинается с точки, то в бланке, построенном на редактируемой форме появится кнопка, содержащая ее текст (без начальной точки). Клавиша - одна из следующих строк: NoKey NoKey NoKey Bs Bs Bs Enter Enter Enter Esc Esc Esc Tab Tab Tab ShTab ShTab ShTab Up Up Up Left Left Left Right Right Right Down Down Down Alt-Up Alt-Up Alt-Up Alt-Left Alt-Left Alt- Left Alt-Right Alt-Right Alt-Right Alt-Down Alt-Down Alt-Down Ins Ins Ins Del Del Del Home Home Home End End End Alt-Ins Alt-Ins Alt-Ins Alt-Del Alt-Del Alt-Del Alt-Home Alt-Home Alt-Home Alt-End Alt-End Alt-End PgUp PgUp PgUp PgDown PgDown PgDown Alt-PgUp Alt-PgUp Alt-PgUp Alt-PgDown Alt-PgDown Alt-PgDown F1 F1 F1 F2 F2 F2 F3 F3 F3 F4 F4 F4 F5 F5 F5 F6 F6 F6 F7 F7 F7 F8 F8 F8 F9 F9 F9 F10 F10 F10 ShF1 ShF1 ShF1 ShF2 ShF2 ShF2 ShF3 ShF3 ShF3 ShF4 ShF4 ShF4 ShF5 ShF5 ShF5 ShF6 ShF6 ShF6 ShF7 ShF7 ShF7 ShF8 ShF8 ShF8 ShF9 ShF9 ShF9 ShF10 ShF10 ShF10 - 80 - Alt-F1 Alt-F1 Alt-F1 Alt-F2 Alt-F2 Alt-F2 Alt-F3 Alt-F3 Alt-F3 Alt-F4 Alt-F4 Alt-F4 Alt-F5 Alt-F5 Alt-F5 Alt-F6 Alt-F6 Alt-F6 Alt-F7 Alt-F7 Alt-F7 Alt-F8 Alt-F8 Alt-F8 Alt-F9 Alt-F9 Alt-F9 Alt-F10 Alt-F10 Alt-F10 Ctrl-A Ctrl-A Ctrl-A Ctrl-B Ctrl-B Ctrl-B Ctrl-C Ctrl-C Ctrl-C Ctrl-D Ctrl-D Ctrl-D Ctrl-E Ctrl-E Ctrl-E Ctrl-F Ctrl-F Ctrl-F Ctrl-G Ctrl-G Ctrl-G Ctrl-H Ctrl-H Ctrl-H Ctrl-I Ctrl-I Ctrl-I Ctrl-J Ctrl-J Ctrl-J Ctrl-K Ctrl-K Ctrl-K Ctrl-L Ctrl-L Ctrl-L Ctrl-M Ctrl-M Ctrl-M Ctrl-N Ctrl-N Ctrl-N Ctrl-O Ctrl-O Ctrl-O Ctrl-P Ctrl-P Ctrl-P Ctrl-Q Ctrl-Q Ctrl-Q Ctrl-R Ctrl-R Ctrl-R Ctrl-S Ctrl-S Ctrl-S Ctrl-T Ctrl-T Ctrl-T Ctrl-U Ctrl-U Ctrl-U Ctrl-V Ctrl-V Ctrl-V Ctrl-W Ctrl-W Ctrl-W Ctrl-X Ctrl-X Ct rl-X Ctrl-Y Ctrl-Y Ctrl-Y Ctrl-Z Ctrl-Z Ctrl-Z Alt-A Alt-A Alt-A Alt-B Alt-B Alt-B Alt-C Alt-C Alt-C Alt-D Alt-D Alt-D Alt- E Alt-E Alt-E Alt-F Alt-F Alt-F Alt-G Alt-G Alt-G Alt-H Alt-H Alt-H Alt-I Alt-I Alt-I Alt- J Alt-J Alt-J Alt-K Alt-K Alt-K Alt-L Alt-L Alt-L Alt-M Alt-M Alt-M Alt-N Alt-N Alt-N Alt- O Alt-O Alt-O Alt-P Alt-P Alt-P Alt-Q Alt-Q Alt-Q Alt-R Alt-R Alt-R Alt-S Alt-S Alt-S Alt- T Alt-T Alt-T Alt-U Alt-U Alt-U Alt-V Alt-V Alt-V Alt-W Alt-W Alt-W Alt-X Alt-X Alt-X Alt- Y Alt-Y Alt-Y Alt-Z Alt-Z Alt-Z Область применения - строка B, T, BT или TB. Область применения определяет, будет указанная процедура доступной при редактировании бланка (B), таблицы (T) или их обоих (TB или BT). Права - строка из символов R, D, U, A, L, G. Если указана, то требуется, чтобы у формы, редактируемой с помощью этой процедуры были указанные права доступа. Подробнее о правах доступа см. в описании команды form. В частности, если в команде onedit в качестве прав указать A, то процедура, к которой относится эта команда будет применима только к формам, имеющим право на добавление записей. Последний параметр - идентификатор control-a - имеет смысл только при работе под MS Windows, хотя его можно указывать и при работе в других операционных средах. Более подробно об использовании этих идентификаторов можно прочитать в описании команд picfile (стр. 47) и button (стр. 57). Если описываемая процедура используется в качестве ре дактирующей, и командой button идентификатор не переопределен, то именно он будет ис пользоваться в качестве идентификатора кнопки, соответствующей данной процедуре. Идентификатором может быть либо целое число, либо одна из строк IDOK IDOK IDOK, IDCANCEL IDCANCEL IDCANCEL , либо, наконец, один из идентификаторов стандартных процедур, описанных в таблице на стр. 56. Выполнение процедур, режимы выполнения (brk_on, brk_off) Рассмотрим процесс выполнения процедур в среде RatBase. Оператор - минимальная единица выполнения в RatBasic-е. Выполнение каждого опера тора (и процедуры в целом) может завершиться успешно или нет. При успешном выполнении оператора выполняется следующая за ним команда - оператор или управляющая конструкция. Если же оператор завершился неуспехом, то дальнейшее поведение системы зависит от ре жима выполнения. Процедуры могут выполняться в обычном или специальном режимах, причем по ходу выполнения возможна смена режима. - 81 - В обычном режиме неуспешное выполнение оператора приводит к завершению выполне ния процедуры (также неуспешному) перед выполнением следующего оператора. В специальном режиме неуспех выполнения оператора не приводит к завершению про цедуры, а результат (успех / неуспех) выполнения оператора запоминается в специальном ре гистре (будем называть его регистром условия). Состояние этого регистра в дальнейшем можно проанализировать с помощью управляющих конструкций языка. Для установки режима служат следующие операторы brk _on - перевод выполнения в обычный режим brk _off - перевод выполнения в специальный режим. В начаче своего выполнения каждая процедура находится в обычном режиме. Выше было сказано, что в обычном режиме после неудачного выполнения оператора выполнение процедуры завешается. Из этого правила есть важное исключение: если оператор, следующий за неуспешно выполнившимся, есть условный оператор или начало условного блока (THEN, ELSE), то выполнение переводится в специальный режим, и этот условный оператор или блок выполняется (или нет) в зависимости от состояния регистра условия. Уровень отладочной информации При отладке программ на RatBasic возможно использование встроенного интерактивно го отладчика (см. стр. 124 ). Следующая команда (применяемая вне тела процедур!) указывает, насколько подробной должна быть отладочная информация для процедур RatBasic- а: debug off | line | full (line) Смысл аргумента: off - отсутствие отладочной информации, при работе отладчика выводятся только назва ния выполняемых операторов; line - кроме названий выполняемых операторов при работе отладчика кроме названий операторов выводятся номера строк (соответствующие указанным в листинге); full - кроме номеров строк выводится исходный текст выполняемых операторов. Естественно, что более подробная отладочная информация требует большего расхода памяти. - 82 - Если команда debug не указана, то действует уровень line. Уровень отладки не меняет ся до следующей команды debug. Кроме того для отдельных процедур можно установить соб ственный уровень отладки заданием третьего аргумента команды proc. Управляющие конструкции Как правило операторы, составляющие тело процедуры выполняются последовательно, один за другим. Выполнение процедуры заканчивается либо после выполнения последнего ее оператора, либо (в обычном режиме) после неудачного выполнения очередного оператора. Управляющие конструкции RatBasic-а служат для изменения "естественного" порядка выпол нения операторов. Возврат (return) Команда return приводит к немедленному окончанию выполнения процедуры. Ее фор мат: return <число> (1) Аргумент определяет успех / неуспех выполнения процедуры. return с ненулевым аргу ментом приводит к успешному окончанию выполнения, а с нулевым - к неуспешному. Переход (goto, :) Простейшая конструкция, управляющая ходом выполнения процедуры - это переход. Его формат: goto <имя метки> Аргумент команды - имя метки, расположенной в теле выполняемой процедуры. Имя метки это произвольная строка символов длиной до шести знаков. Для определения метки служит команда ":" (двоеточие). Ее формат <имя метки> Команда определения метки (как и любая другая) занимает отдельную строку. Двое точие длжно быть отделено хотя бы одним пробелом от аргумента. Выполнение команды goto состоит в передаче управления на оператор, следующий за меткой-аргументом. Имена меток в пределах одной процедуры должны быть уникальны. RatBasic не накладывает ограничения на допустимые переходы, в частности возможны пере ходы внутрь циклов и условных блоков. - 83 - Условные операторы (then, else) В RatBasic-е возможно условное выполнение двух типов: условные операторы и услов ные блоки. Условные операторы позволяют управлять выполненим единичного оператора в зависи мости от состояния регистра условия. К условным операторам относятся then и else. Формат этих конструкций: then <любой оператор> else <любой оператор> Оператор, следующий после then будет выполняться только в случае успешного выпол нения предыдущего оператора. Оператор, следующий после else, наоборот будет выполняться только при неуспехе выполнения предыдущего оператора. Оператор, следующий за then или else может быть действительно любым (кроме друго го условного оператора!), в том числе и управляющей конструкцией. Условные блоки (then, else, endif) Кроме управления выполнением единичного оператора возможно управление выполне нием группы операторов в зависимости от состояния регистра условия. Для этого пред назначены так называемые условные блоки. Условный блок может иметь один из двух форма тов: then . . . <последовательность операторов 1> . . . endif и then . . . <последовательность операторов 1> . . . else . . . <последовательность операторов 2> . . . endif Как видно в условных блоках используются те же ключевые слова (then, else), что и в условных операторах. Отличие в том, что then и else в условных блоках не имеют после себя никаких операндов. - 84 - Смысл условных блоков достаточно очевиден. Если к моменту начала выполнения ус ловного блока регистр условия был установлен в истину, то выполняется <последовательность операторов 1>. В противном случае выполняется <последовательность операторов 2>, если она имеется (второй вариант условного блока). Если условный блок не содержит else-части, то выполнение процедуры продолжается со следующего, после услов ного блока, оператора. Последовательности операторов, содержащиеся в условных блоках могут содержать любые управляющие конструкции, в том числе циклы и другие условные блоки. Цикл (loop, endloop, break, continue) Циклическое выполнение последовательности операторов в RatBasic-е можно организо вать с помощью условных операторов и оператоов перехода. Но кроме этого для организации циклов имеется специальная конструкция, облегчающая их программирование. Цикл в RatBasic-е имеет следующий вид: loop . . . <последовательность операторов> . . . endloop Операторы, заключенные между loop и endloop выполняются "бесконечно", т.е. после выполнения последнего оператора в <последовательности операторов> управление передается на оператор, следующий после loop. Изменить порядок выполнения цикла (кроме очевидного применения меток) можно применением управляющих конструкций break и continue. Они имеют следующий формат: break continue Конструкция break вызывает немедленное окончание выполнения цикла, т.е. переход на оператор следующий за endloop. Конструкция continue приводит к переходу на первый опера тор цикла, т.е. на оператор, следующий за loop. break и continue могут находиться только внутри loop-блока. <Последовательность операторов> может включать любые управляющие конструкции, в том числе и вложенные циклы. Среда выполнения в RatBase Прежде чем переходить к рассмотрению операторов RatBasic-а опишем те объекты (кроме уже описанных), которыми они манипулирут. Это выборки, переменные и константы. - 85 - Выборка, хэндл, активность, контекст активности, именование выборок Все эти понятия тесно связаны, поэтому их описание приведено в одном параграфе. Если форма соответствует типу данных, то ВЫБОРКА - динамически создаваемая пе ременная (объект) этого типа, а ХЭНДЛ ВЫБОРКИ - указатель на него. В процессе работы программы на RatBasic-е ВЫБОРКИ ОТКРЫВАЮТСЯ НАД ФОРМА МИ ИЛИ НАД ДРУГИМИ ВЫБОРКАМИ . Над одной формой можно открыть несколько выборок. После открытия выборке при писывается некоторое уникальное число - ХЭНДЛ ВЫБОРКИ , который доступен из программы, и который можно использовать для обращения к выборке. Хэндлы описываются в программе на RatBasic наряду с другими переменными. Как правило, хэндлы типизированы, в том смысле, что каждая переменная-хэндл предназначена для указания на выборки открытые над конкретной формой (или производными от нее - еще одна аналогия с указателями на объекты в С++). Кроме типизированных хэндлов возможны нетипизированные, которые мо гут указывать на любую выборку. Естественно, что нетипизированные хэндлы могут приме няться только в контекстах, где не требуется указание имен полей, связей и другой конкрет ной информации о форме. Кроме именования с помощью хэндлов выборка в программе на RatBasic может имено ваться именем той формы, на основе которой она создана. Как уже говорилось, над одной формой может быть открыто несколько выборок. Возникает проблема - какая же из них бу дет именоваться именем соответствующей формы ? Для решения этой проблемы вводится по нятие АКТИВНОСТИ ВЫБОРОК . В каждый момент времени с любой формой связано не бо лее одной выборки, называемой АКТИВНОЙ ДЛ_ ЭТОЙ ФОР МЫ. Именно эта выборка (если она есть) именуется именем соответствующей ей формы. Введем еще одно понятие - КОНТЕКСТ АКТИВНОСТИ . Его можно представить как таблицу, где для каждой формы указана ее активная выборка, причем для некоторых форм активных выборок может и не быть. Итак еще раз: в программе на RatBasic конкретная выборка может именоваться либо своим хэндлом, если он доступен, либо названием формы, над которой открывалась выборка. В последнем случае должна существовать активная для указанной формы выборка. Везде, где требуется указание выборки эти два метода равноценны. Кроме множества активных в понятие среды выполнения входит еще одна выборка, на зываемая ТЕКУЩЕЙ . Многие команды RatBasic по умолчанию работают с текущей выборкой. Наличие текущей выборки позволяет не именовать каждый раз в программе нужную выборку. - 86 - Поясним сказанное на примере. Пример содержит некоторые, описанные ниже опера торы, но думается, что он будет понятен. Напомним, что форма persons содержит в числе прочих поле name. - 87 - form persons . . . endform handle pers_hnd persons -- описываем хэндл с именем pers_hnd, предназначенный для -- указания на выборки, открытые именно над формой persons. handle any_hnd -- хэндл, пригодный для указания на любую выборку -- далее приведен фрагмент процедуры, работающей с -- описанными объектами, оператор OPEN описан на стр. Error! Error! Error! Bookmark not defined. Bookmark not defined. Bookmark not defined. proc work OPEN persons -- открываем выборку над формой persons, т.к. никакой хэндл -- не указан, выборка становится активной для этой формы, -- и доступна по имени формы (выборка 1) OPEN persons pers_hnd -- открываем еще одну выборку (выборку 2) -- над persons, т.к. указан хэндл, то он -- устанавливается "указывающим" на эту -- выборку, изменения активной выборки для persons при -- этом не присходит OPEN persons any_hnd -- отрываем третью выборку (выборка 3) над persons -- используя нетипизированный хэндл = persons.name 'John$Smith -- присвоение значения полю выборки 1, именуемой именем -- своей базовой формы = pers_hnd.name 'Mary$Brown -- присвоение значения полю выборки 2, именуемой -- своим хэндлом, значение того же поля -- выборки 1 при этом не изменяется = any_hnd.name 'Ivan$Petroff -- ошибка, нетипизированный хэндл "ничего не знает" -- про имена полей той выборки на которую он указывает OPEN persons -- открываем очередную выборку (4) над persons, -- т.к. хэндл не указан, эта выборка становится активной - 88 - -- для persons вместо выборки 1, которая после этого -- перестает быть доступной CLOSE persons -- закрываем выборку 4, после этого для формы persons -- нет активной выборки CLOSE pers_hnd -- выборку 2 CLOSE any_hnd -- и выборку 3 -- а выборка 1 так и осталась в просаке - надо -- было быть осторожнее endproc Активация Некоторые операторы RatBasic изменяют среду выполнения, т.е. меняют активные для различных форм выборки. Возможны два варианта активации выборки. Во-первых выборка может стать активной только для своей базовой формы. Это про исходит например при открытии выборки если не указан хэндл, как в примере из предыдуще го раздела для выборок 1 и 4. Во-вторых выборка может стать активной как для своей базовой формы, ТАК И ДЛ_ ВСЕХ ЕЕ ПРЕДКОВ . Это происходит при выполнении оператора ACTIVATE RatBasic-а. После этого работа с выборками, именуемыми формами - предками активируемой выборки, приводит к работе с самой этой выборкой. Пример: - 89 - form persons rel persons -- почти та же форма, что в предыдущем примере, -- только базирующаяся на отношении persons -- экранное представление для нее не указано, принимается -- по умолчанию - поле на строку fld name name fld address address -- поля name и address содержатся в отношении persons fld num %d -- num - виртуальное поле endform form people persons -- форма people - производная от persons, наследует от -- нее поля и экранное представление -- переопределяем экранное представление, т.е. создаем -- свою картинку для формы people, подробности -- команды pic здесь не важны pic 36 1 $num $ $name $ $address $ endpic endform proc report -- процедура выдачи простого отчета по форме persons -- здесь опускаем открытие выходного потока. Для этого -- примера также неважен способ организации цикла по -- выборке -- перед вызовом процедуры должна быть активная выборка -- для persons EMP_REC persons BRK_OFF = persons.num 1 -- начальное значение счетчика : Loop NEXT_REC persons ELSE Ex OUT_FORM persons -- главный для данного примера оператор - -- в выходной поток выводится изображение карточки -- с текущими значениями полей, т.е. что то вроде -- name James Brown -- address Santa Barbara - 90 - -- num 1 -- name Mary Poppins -- address Littletown -- num 2 -- name Wasya -- address Rostov-on-Don -- num 3 + persons.num 1 -- увеличение счетчика GOTO Loop : Ex endproc proc peoplerep -- процедура выдачи отчета по форме people точно такая же, -- что и для persons, но отличается выводимой карточкой. -- чтобы не переписывать заново похожую процедуру -- используем оператор ACTIVATE (предполагаем, что есть -- активная выборка для people) ACTIVATE people -- выборка, активная для people, становится активной и -- для persons, после этого можно смело вызывать процедуру -- report - она выполнит тот же цикл, но выводить будет в -- карточку в формате people CALL report -- в результате получим вывод -- 1 James Brown Santa Barbara -- 2 Mary Poppins Littletown -- 3 Wasya Rostov-on-Don endproc Кроме того выборка автоматически активируется при вызове процедур, назначенных на функциональные клавиши при редактировании выборки. Описание глобальных переменных (var, handle) В RatBasic-е имеются как глобальные так и локальные (в пределах одной процедуры) переменные. Используемые переменные должны быть явно описаны ранее по тексту. Допусти мые типы переменных те же, что и у полей. Переменные описываются командой (которая может встречаться и в теле процедур): - 91 - var <имя переменной> <формат переменной> Формат переменной описывался при Кроме того имеется команда handle <имя переменной> <имя формы> () которая создает переменную - хэндл. Если задан второй параметр команды, то описы ваемый хэндл типизирован именем указанной формы, в противном случае описывается нети пизированный хэндл. Команда handle также допустима в теле процедур. Хэндлы по присваи ванию совместимы с целыми, но сим фактом лучше не злоупотреблять. Локальные переменные процедур, формы, ассоциирован ные с процедурами Как говорилось выше в процедурах допустимы локальные переменные, описываемые командами var, casefld, array и handle в теле процедуры. Локальные переменные "не видны" вне своей процедуры, кроме того они "заслоняют" собой одноименные с ними глобальные пе ременные (обычное в языках программироания правило экранирования имен). Результатом описания локальных переменных является создание формы, одноименной с описываемой про цедурой, и содержащей поля - локальные переменные. Такую форму назовем АССОЦИИРО ВАННОЙ с данной процедурой. На момент описания локальной переменной в процедуре воз можны следующие ситуации: - ассоциированная форма вообще ранее не упоминалась либо была предописана командой define form, в этом случае она создается, и содержит только поля - локальные пе ременные; - форма была полностью описана ранее, при этом ее поля будут локальными перемен ными процедуры, но в самой процедуре нельзя описывать новые локальные пере менные командой var - это попытка изменить уже описанную форму. Если при вызове процедуры не было активной выборки для ее ассоциированной формы, то эта выборка открывается, и становится активной, а при выходе из процедуры - закрывает ся. Если же такая активная выборка была, то с ней ничего не делается при вызове процедуры и возврате из нее. В этом случае значения локальных переменных процедуры определяются текущей записью выборки, открытой над формой, ассоциированной с процедурой. Следует иметь в виду, что формы ассоциированные с процедурами - это точно такие же формы, как и все остальные, и с ними возможны те же операции, что и с другими. В частности такая форма может иметь соответствующее ей отношение. В этом случае запись такой формы можно рассматривать как сохраненный локальный контекст процедуры, т.е. значения локальных переменных для различных вариантов вызова процедуры. - 92 - Форму, ассоциированную с процедурой можно явно указать командой use <имя формы> в описании процедуры. После использования этой команды к полям указанной формы можно обращаться так же, как к локальным переменным (и между ними действительно нет никакой разницы). Примеры описаний процедур и ассоциированных форм: - 93 - var i %d -- глобальная переменная proc a = i 1 -- присваивание глобальной переменной endproc -- процедура не имеет локальных переменных, и -- ассоциированной с ней формы не создается proc b var i %d -- локальная переменная = i 1 -- присваивание локальной переменной -- (на самом деле полю i формы b), -- глобальное i "экранировано" локальным endproc -- процедура имеет локальные переменные, будет -- создана форма b, содержащая поле i, эта форма -- не будет иметь соответствующего ей отношения form c rel crel fld i %d endform -- форма, имеющая соответствующее ей отношение proc c = i 1 -- присваивание полю i формы c, так как эта форма -- одноименна процедуре, то она является -- ассоциированной с ней endproc proc d use c = i 1 -- то же, что и для формы с, но ассоциированная -- форма указана явно командой use endproc proc work call b -- перед вызовом процедуры открывается выборка над -- формой b, и становится активной для этой формы, -- после выхода из процедуры выборка закрывается, -- локальные для процедуры b переменные имеют неопределенные -- значения - 94 - call c -- перед вызовом процедуры открывается выборка над -- формой c, и становится активной, -- после выхода из процедуры выборка закрывается, -- локальные для процедуры c переменные имеют значения -- из первой записи выборки с, либо неопределены, если -- выборка пустая OPEN c NEXT_REC c NEXT_REC c -- "вручную" открываем выборку над формой с (она становится -- активной для с), и сдвигаемся на третью запись в ней call c -- при вызове процедуры с выборка не открывается, т.к. -- уже есть активная для формы с call d -- то же, что и в предыдущем случае, локальная переменная -- в данном случае ТА ЖЕ, что и в процедуре с CLOSE c endproc Параметры процедур Процедура может иметь параметры, передаваемые ей при вызове оператором call. Па раметры описываются командой param <параметр 1> <параметр 2> () <параметр 3> () <параметр 4> () <параметр 5> () <параметр 6> () <параметр 7> () <параметр 8> () Аргументы команды представляют собой имена формальных параметров процедуры. Па раметры реализуются добавлением в форму, ассоциированную с процедурой полей типа ука затель (ptr). При вызове процедуры оператором call эти указатели автоматически - 95 - связывают ся с соответствующими им фактическими параметрами. Из такой реализации параметров сле дует, что: - описание формальных параметров допустимо там же, где допустимо описание локаль ных переменных; - фактическими параметрами могут быть только те объекты, к которым можно привязать указатель, т.е. поля форм, глобальные переменные, константы. - параметры нетипизированы, при вызове процедуры не происходит никаких проверок на соответствие типов формальных и фактических параметров (однако жив же еще великий язык FORTRAN, в котором то же самое, и даже хуже!). Команда handle в теле процедуры может иметь аргументом имя одного из параметров. В этом случае объявляется, что этот параметр - именно переменная-хэндл, и ее имя можно использовать для именования выборок. Напомним, что обычно команда handle создает НО ВОЕ поле формы, ассоциированной с процедурой. Если при вызове процедуры опущен некоторый фактический параметр, то соответству ющий ему формальный параметр (т.е. указатель) останется непривязанным, иначе - пустым или нулевым. Некоторые операторы допускают в качестве аргументов пустые параметры. Умолчание для опущенных параметров можно изменить, использовав команду dfltpar <умолчание 1-го пар> () <умолчание 2-го пар> () <умолчание 3-го пар> () <умолчание 4-го пар> () <умолчание 5-го пар> () <умолчание 6-го пар> () <умолчание 7-го пар> () <умолчание 8-го пар> () Умолчания будут подставляться на место опущенных фактических параметров. Пример использования процедур с параметрами. proc ms param a b c -- описано три параметра процедуры dfltpar 'One$ 'Two$ -- заданы умолчания для первых двух - - 96 conc s b a c mess s endproc /* Оператор conc заносит в свой первый аргумент строковую конкатенацию своих остальных аргументов, mess выдает на экран сообщение, заданное его аргументом. */ var s %s proc main s %s var call ms -- выводит One Two call ms 'Один -- выводит Один Two call ms _ 'Два 'Три -- выводит One Два Три = s 'Все$остальное -- выводит Все остальное Two call ms s endproc - 97 - Операторы RatBasic Как уже упоминалось, операторы - это элементы построения процедур. Выполнение каждого оператора может быть успешным или нет. При описании операторов, если не указа но иного, считается что он всегда успешен. Напомним что <выборка> в описании операторов соответствует либо имени формы - и тогда именует активную для данной формы выборку - либо хэндлу, который указывает на ка кую-либо выборку. Открытие, закрытие и активация выборок OPEN <имя формы> (посл. выбранная) <имя хэндла> (никакого) <имя отношения> (никакого) Открывает выборку над указанной формой. Если хэндл не указан - делает ее активной для этой формы. Если хэндл указан - он устанавливается на открытую выборку, активной она при этом не становится. Третий параметр - строчная переменная или константа. Если он ука зан, то открываемой выборке соответствует именно отношение, указанное здесь, а не задан ное командой rel в описании формы. Это дает возможность работать с помощью одной и той же формы с разными отношениями, более того, можно программно опредлять имя отноше ния, которое должно соответствовать форме. OPEN_BY_NAME <имя формы> (посл. выбранная) <имя хэндла> (никакого) <имя отношения> (никакого) Этот оператор аналогичен оператору open, но имя формы задается строчной перемен ной или константой, что дает возможность динамически, в процессе выполнения программы, определить имя открываемой формы. CLOSE <выборка> Закрывает указанную выборку. ACTIVATE <выборка> (текущая) Делает указанную выборку активной как для той формы, над которой она открыта, так и для всех предков этой формы. - 98 - SET_CURRENT <выборка> (текущая) Делает указанную выборку текущей. GET_HND <выборка> (текущая) <хэндл> Во второй параметр записывается хэндл выборки - первого параметра. OPEN_VIEW <выборка> <имя формы> <имя хэндла> () Открыть выборку, определяемую формой - вторым аргументом, над уже открытой вы боркой (первый аргумент). Если указан третий аргумент, то в него записывается хэндл этой новой выборки. OPEN_VIEW_BY_NAME <выборка> <имя формы> <имя хэндла> () Аналогичен оператору open_viev, но первый аргумент, задающий выборку, задается строчной переменной или константой, что позволяет динамически, в процессе выполнения программы, определить имя выборки, над которой открывается новая выборка. Редактирование EDIT <выборка> (текущая) <0 или 1> (0) Экранное редактирование указанной выборки. Если выборка указана явно именем фор мы (а не хэндлом), и для данной формы нет текущей, то открывается и становится активной выборка над этой формой. Если второй параметр равен 1 - то открывает новую в любом случае, даже если была активная. Если при выполнении команды была открыта новая выбор ка, то по выходу из редактирования она закрывается. EDIT_BY <выборка> (текущая) <имя списка процедур> () <доступ> () <нач. представление () <окно> () Установление выборке (которая должна быть уже открыта) параметров экранного ре дактирования отличных от тех, что были заданы при ее описании. Если некоторые из аргу ментов опущены, то соответствующие параметры выборки не изменяются. - 99 - CHOICE_EDIT <имя списка форм> (все формы) <тип меню> (V) <строка:колонка> (5:5) <0 или 1> (1) Выбор в меню форм и редактирование выбранной формы. Тип меню может содержать следующие опции: V - вертикальное меню G - горизонтальное меню N - меню без рамки D - меню с двойной рамкой T - меню без заголовка S - меню без тени По умолчанию меню вертикальное, окружено одиночной рамкой, с тенью и заголовком. Расположение меню на экране определяется третьим параметром. Выбор в меню и ре дактирование формы повторяются циклически до отказа выбора в меню. Последний параметр определяет, должно ли меню убираться с экрана после выбора (1) или нет (0). SHOW <выборка> (текущая) <опции> (никаких) Показать выборку - первый аргумент в ее текущем представлении (табличном или блан ковом). Опции - строка из букв N, P, R. Они определяют некоторые особенности показа: N - при показе в бланковом виде запись не пересчитывается из отношения, показывают ся текущие значения полей; P - управление содержимым экрана, занимаемым окном выборки при ее "гашении" (см. описание оператора HIDE); R - при показе в табличном виде происходит позиционирование на начало таблицы. HIDE <выборка> (текущая) Убрать с экрана изображение выборки, выведенное ранее оператором SHOW. Если этот оператор имел опцию P, то место на экране, занимаемое окном выборки просто очистится. Если же в операторе OPEN не было опции P, то восстановится предыдущее содержимое эк рана в месте расположения окна выборки. GO_LINK Выбрать с помощью меню связь в списке всех связей ТЕКУЩЕЙ выборки (если связь всего одна, она выбирается автоматически, если связей нет вообще - оператор оканчивается неудачей) и начать экранное редактирование связанной формы. Напомним, что в список всех связей формы попадают связи, определенные в описании формы командой link, а не Link. - 100 - GO_FLINK При редактировании - если есть связи от текущего (того в котором находится курсор) поля выборки, то происходит выбор связи среди связей текущего поля и переход к редакти рованию связанной выборки. Если от текущего поля связей нет - оператор эквивалентен GO_LINK. Под "связями от поля" полразумеваются те связи формы, для которых данное по ле входит в условие связи. RET_LINK <0 или 1> (1) При редактировании - окончание редактирования связанной выборки (которое было вызвано операторами GO_LINK или GO_FLINK) и возврат к редактированию главной. Пара метр указывает - надо ли (1) или нет (0) при возврате переносить значения из связанной формы в главную по списку обмена той связи, по которой ранее происходил переход в свя занную форму. CHNG_SHOW <выборка> (текущая) <0 или 1> (0) При редактировании выборки сменить форму ее экранного представления на противо положную (бланк<->таблица), если это допустимо. Второй параметр имеет смысл при пере ходе в табличное представление. Если он не равен 0, то курсор в таблице будет установлен на первую запись (переустановка таблицы). IS_TAB <выборка> (текущая) Оператор выполняется успешно, если текущее экранное представление выборки - таб лица, и неуспешно, если текущее представление - бланк. IS_UPD <выборка> (текущая) Оператор выполняется успешно, если при экранном редактировании было изменено хо тя бы одно поле текущей записи. Если значения полей не изменялись оператор выполнется неуспешно. DFLT <выборка> (текущая) Заполняет поля выборки значениями по умолчанию заданными при описании полей формы над которой открыта указанная выборка. SET_FLD <имя поля формы> Имя задается в виде <выборка>.<имя поля>. Оператор устанавливает "текущее" поле выборки. При экранном редактировании после данного оператора курсор будет вначале нахо дится в указанном поле. Если экранное редактирование уже происходит, то курсор просто переместится в указанное поле. - 101 - BLN-> <выборка> (текущая) <0 или 1> (0) Считать значения "с экрана" (после их изменения в ходе экранного редактирования) в поля выборки. Оператор выполняется неуспешно, если хотя бы одно поле содежит неверное значение, например в поле целого типа содержится строка "12+34". Этим оператором надо пользоваться каждый раз, когда после изменения полей на экране (что можно узнать с по мощью оператора IS_UPD) нужно получить их новые значения. Второй параметр управляет контролем за "обязательными" полями. Если он равен 0, то отсутствие значения в поле, обя зательном для ввода (имеющем признак C в описании поля) считается ошибкой. Если этот параметр не равен 0, то контроля на "обязательность значений" не производится. EXIT <код возврата> (0) Завершить редактирование текущей формы. Код возврата определяет успех (1) или не успех (0) вызвавшего редактирование оператора (EDIT, CHOICE_EDIT и пр.). Работа с условием Набор записей выборки определяется условием связи "входящей" в нее. Если такой связи нет, то набор записей выборки как правило совпадает с записями "ее" отношения. При экранном редактировании можно наложить на выборку дополнительное условие, которое (возможно) сузит набор записей, входящих в выборку. CND <0 или 1> (0) Ввод условия с помощью бланка ТЕКУЩЕЙ выборки. Перед вводом условия бланк очищается. Условие вводится следующим образом: - в нужные поля выборки записываются операции условия и значения, по которым про изводится отбор; - в одно поле можно записать несколько операций условия, разделив их знаком &; - ввод условия завершается нажатием Enter, отказ от ввода услови - Esc. Отсутствие операции условия понимается как условие по равенству. Параметр опера тора определяет, как производится отбор записей. Если он равен 1, то поиск записи проис ходит в той же выборке, и при нахождении записи, удовлетворяющей условию она становит ся текущей. Если параметр равен 0, то происходит "ужесточение" условия наложенного на текущую выборку, т.е. она будет содержать только записи удовлетворяющие условию. Впос- ледствии по нажатию Esc можно вернуться к редактированию исходной выборки. - 102 - CND_SET <выборка> (текущая) <0 или 1> (0) Также ввод условия с помощью бланка выборки - аргумента. Отличие от оператора CND в том, что условие формируется из значений полей в бланке на экране на момент вызо ыв этого оператора, т.е. предполагается, что условие в бланк было записано ранее. Второй аргумент имеет тот же смысл, что и аргумент оператора CND. SELECT Вводит условие не производя преобразования из бланка. Условие образуется из значений определенных полей текущей записи выборки на момент вызова оператора. Строчные поля могут содержать кроме значения также и операцию условия (в том же виде, в каком она вводится в бланк). При отсутствии операции условия для строчных полей, а также для всех нестрочных, определяется условие по равенству. CND_RESET <выборка> (текущая) Оператор сбрасывает условие, наложенное на выборку одним из операторов, описанных в этом параграфе. Работа с открытыми выборками GET_POS <выборка> (текущая) <имя переменной> В указанной переменной (любого типа) запоминается положение текущей записи вы борки. Впоследствии можно будет восстановить эту позицию оператором SET_POS. Оператор заканчивается неудачей, если размер указанной переменной недостаточен для сохранения по зиции. Реально для сохранения позиции достаточна либо переменная типа длинное целое, ли бо строковая, длиной не менее четырех символов. SET_POS <выборка> (текущая) <имя переменной> () Восстановить позицию, ранее сохраненную в переменной оператором GET_POS. Если второй аргумент опущен, то происходит позиционирование на ту же запись в выборке, иначе говоря пересчитывание текущей записи. NEXT_REC <выборка> (текущая) <1 или -1> (1) Сдвинуться на следующую (1) или предыдущую (-1) запись указанной выборки. Опера тор неуспешен, если невозможно сдвинуться на "нормальную", т.е. непустую запись. ADD_REC <выборка> (текущая) Добавить в выборку новую запись с текущими значениями полей. - 103 - UPD_REC <выборка> (текущая) Модифицирует текущую запись в выборке в соответствии с текущими значениями по лей. Если текущей записью является пустая запись, то оператор выполняются неуспешно. DEL_REC <выборка> (текущая) Удалить текущую запись в указанной выборке. Оператор успешен, если это непустая запись. EMP_REC <выборка> (текущая) <опции> (FP) Очистить текущую запись. Очистку можно понимать двояко - как установку на пустую (расположенную между последней и первой) запись выборки, и как очистку всех полей. Про цессом очистки управляют опции - F и/или P. Их смысл: F - происходит очистка полей P - происходит установка на пустую запись. Как видно из описания, по умолчанию происходит и то, и другое. NOT_EMP_REC <выборка> (текущая) Успех, если текущая запись указанной выборки не пустая. DEL_ALL <выборка> (текущая) Удалить все записи выборки. Будте осторожны - никаких переспросов не происходит! REFRESH_VIEW <выборка> (текущая) <0 или 1> (0) Первым аргументом должна быть выборка, открытая над другой выборкой с помощью оператора OPEN_VIEW. Если это не так, то оператор завершается неудачей. Выполнение оператора состоит в совмещении позиций (т.е. установке на одну и ту же запись) в указан ной выборке и в ее выборке-родителе. Второй аргумент определяет тип совмещения позиций: 0 - текущей в выборке - аргументе становится та же запись, что и в ее родительской выборке; 1 - текущей в родительской выборке становится та же запись, что и выборке - аргу менте. GET_LINKED Подтянуть по всем связям (точне по спискам обмена всех связей) ТЕКУЩЕЙ выборки значения полей. - 104 - SET_LINKED <выборка> (текущая) Выполнение этого оператора происходт в несколько этапов. 1) По спискам обмена всех связей указанной выборки происходит перенос значений в связанные выборки. Не переносятся значения неопределенных полей. 2) В каждой связанной выборке происходит следующее: если текущей записью в ней бы ла пустая, то происходит добавление новой записи с перенесенными значениями полей, в противном случае (при непустой записи) происходит модификация записи в связанной форме. 3) По спискам обмена главной выборки происходит перенос значений из связанных вы борок в главную. <== <выборка> (текущая) ==> <выборка> (текущая) Выборка - аргумент рассматривается как связанная. Операторы переносят по списку обмена связи "входящей" в эту выборку значения в главную выборку (<==) или же в выборку - аргумент (==>). COPY_BY_NAME <выборка 1> <выборка 2> Копирует значения одноименных полей из выборки 2 в выборку 1. Модификации на диске при этом не происходит - для этого надо воспользоваться операторами модификации или добавления данных. DIFF_RECS <выборка 1> <выборка 2> "Вычитание" текущей записи второй выборки из текущей записи первой. Оператор сравнивает одноименные поля выборок, и если их значения совпадают, то в первой выборке полю прсваивается непределенное значение. Результат оператора - успех, если среди полей первой выборки, одноименными со второй, остались определенные поля. Если все такие поля имеют неопределенное значение, то выполнение оператора неуспешно. UNLOAD <выборка> (текущая) <переменная или константа> (rbd.sav) <опции выгрузки> () <маска полей> (все поля) <разделители> (~\n\n) Оператор служит для выгрузки данных из выборки (первый аргумент) в текстовый файл, имя которого задается вторым аргументом. Посредством оставшихся аргументов мож но изменять формат выходного файла. В число опций могут входить следующие символы: - 105 - A - перед выводом собственно полей выборки в файл выводится шапка, содержащая ин формацию о применяемых разделителях и именах выводимых полей. Впоследствии эта шапка может быть использована оператором load. 1 или + - если задана одна из этих опций, то происходит дописывание в конец суще ствующего файла, если нет - всегда создается новый. При дописывании файла шапка в него не записывается. S - выводится только одна (текущая) запись, а не все записи выборки. D - выгрузка производится в формате для загрузки в Dbase- совместимые системы: запись на строку, поля разделяются запятыми, текстовые поля заключаются в кавычки. Маска полей определяет множество полей выборки, подлежащих выгрузке. Она пред ставляет собой строку из символов, определяющих редактирующие свойства поля (E, Z, C, T, B). Перед отдельными символами могут стоять знаки + и - (например +ET-C). Смысл аргу- мента: выгрузка происходит из полей, которые обладают признаками "с плюсом" и не обла дают признаками "с минусом". В частности маска +ET-C означает выгрузку из полей, защи щенных от редактирования, не входящих в таблицу и не обладающих признаком "обязательного ввода". Разделители - это строка длиной до трех символов, а именно: - символ, на который заменяется перевод строки при выводе в текстовый файл "длинных" строк, т.е. строк, содержащих символ перевода строки; - символ - разделитель полей в выходном файле; - символ - разделитель записей. Принятые по умолчанию разделители задают вывод файла в формате поле на строку. В длинных строках перевод строки заменяется на тильду (~). В индикаторе прогресса, находящемся на экране во время выгрузки выводится ко личество выгруженных записей. Выгрузка может быть прекращена нажатием клавиши Esc. LOAD <выборка> (текущая) <переменная или константа> <опции загрузки> (F) <маска полей> (все поля) <разделители> (~\n\n) Оператор служит для загрузки данных из текстового файла, созданного выполнением оператора unload или некоторой внешней программой. Выбороку, в которую происходит заг рузка, определяет первый аргумент, а имя текстового файла - второй. Опции определяют реакцию на неверный формат вводимых данных, а также задают об работку шапки файла (см. описание load). В число опций входят: - 106 - F - при ошибке ввода операция загрузки прекращается, оператор завершается неуспешно. I - неверное значение поля игнорируется, поле остается неопределенным. K - при ошибке ввода пропуск текущей записи, операция загрузки продолжится со стро ки текстового файла, соответствующей следующей записи. A - во входном файле ожидается наличие шапки. S - загружается только первая запись файла Маска полей имеет тот же формат, что и в операторе load, и определяет набор полей, в которые происходит загрузка. Если файл не имеет шапки, то предполагается, что он со держит информацию именно из полей, определяемых маской. Если файл имеет шапку, то множество полей определяется шапкой, а маска полей может еще сузить это множество. Если использована опция A, но во входном файле нет шакпи, то выдается предупреж дение и загрузка выполняется так же, как и в отсутствие опции A. Разделители - те же, что и в операторе load, задают формат входного файла. Если входной файл содержит шапку, то разделители игнорируются. Во время выполнения загрузки на экране находится индикатор прогресса (см.стр. Error! Bookmark not defined. Error! Bookmark not defined. Error! Bookmark not defined. ), в котором индицируется информация о количестве введенных из текстового файла ПОЛЕЙ . Загрузка может быть прекращена нажатием клавиши Esc. При этом происходит переспрос - прекращать ли загрузку, и если да, то выполнение оператора завершается неуспешно. Замечание: case поля должны быть представлены во входном файле своими текстовыми значениями. COPY_ALL <выборка 1> (текущая) <выборка 2> <строка> ('Скопировано:) Копирование всех записей формы 2 в форму 1. Копируются только одноименные поля. Третий параметр определяет текст индикатора прогресса (см.стр. Error! Bookmark not defined. Error! Bookmark not defined. Error! Bookmark not defined. ), который будет находиться на экране в это время, и в котором будет указываться количество скопированных записей. Операция копирования может быть прекращена нажатием клавиши Esc. При этом происходит переспрос - прекращать ли копирование, и если да, то выполнение оператора завершается неуспешно. TEST_CHANGE <выборка> (текущая) Оператор успешен, если произошло изменение указанной выборки другим пользовате лем (при многопользовательской работе). - 107 - OPEN_IDX <выборка> (текущая) Оператор предназначен для ускорения работы при массовой модификации отношения. Его действие состоит в том, что одновременно открываются файлы соответствующие всем индексам отношения (обычно бывает открыт только один из них). Выполнение данного опе ратора повышает скорость работы за счет расхода памяти. CLOSE_IDX <выборка> (текущая) Возвращает работу с индексами отношения к обычному для RatBase виду, когда открыт только один из индексов отношения. Это замедляет работу при массовой модификации дан ных в отношении, но экономит память. Операторы вызова хуков Как уже говорилось (см. стр. Error! Bookmark not defined. Error! Bookmark not defined. Error! Bookmark not defined. ), каждая форма имеет на бор процедур-хуков, которые автоматически вызываются при некоторых действияях с выбор кой, открытой над этой формой. Этот набор может быть либо стандартным, либо изменен ным пользователем при описании формы. Операторы, описанные в данном разделе, позволяют явно вызывать хуки, определенные для некоторой выборки. Необходимо понимать разницу между операторами "семейства" NEXT_REC, ADD_REC и пр. и операторами данного раздела. Так, например, выполнение опе- ратора NEXT_REC состоит в переходе на следующую запись выборки. Выполнение же опера тора NEXT (описанного ниже) состоит в вызове определенной для указанной выборки проце дуры-хука, связанной с переходом на следующую запись. Эта процедура (если данный хук за- давался пользователем), вообще говоря, может выполнять произвольные действия, в частности и переход на следующую запись. В RatBasic имеются следующие операторы явного вызова хуков (после названия опера торов указана ситуация, в которой эти хуки вызываются автоматически): NEXT <выборка> (текущая) При переходе на следующую запись. PRED <выборка> (текущая) При переходе на предыдущую запись. EMP <выборка> (текущая) При переходе на пустую запись. DEL <выборка> (текущая) При удалении записи. - 108 - ADD <выборка> (текущая) При добавлении записи без предварительного преобразования "с экрана". ADD_FROM_BLN <выборка> (текущая) При добавлении записи с предварительным преобразованием "с экрана". UPD <выборка> (текущая) При модификации записи без предварительного преобразования "с экрана". UPD_FROM_BLN <выборка> (текущая) При модификации записи с предварительным преобразованием "с экрана". NOT_EMP <выборка> (текущая) При проверке не "непустоту" записи. FIRST <выборка> (текущая) При установке на первую запись. Работа с переменными и полями = <переменная> <переменная или константа> ?= <переменная> <переменная или константа> Присваивание значения второго аргумента первому. = присваивает всегда, а ?= только если первый аргумент неопределен. Допустимо присваивание строчным переменным значений любых типов (при этом они преобразоввываются к строчному представлению). Строчные значения можно присваивать другим типам переменных, при условии, что строка содержит допустимую константу типа-получателя. Например можно перемнной типа дата присвоить строку, содержащую "01/01/79". Оператор завершается неуспехом при невозможности кор- ректного преобразования значения второго операнда к типу первого. SET_BLANK <переменная> Установить переменной непределенное значение. NOT_BLANK <имя переменной> Успех, если переменная определена. - 109 - ABS_TIME <переменная> В указанную переменную (типа длинное целое) записывается значение текущего времени в секундах от "сотворения мира" (как всем известно, сотворение мира произошло 1.01.1970). TODAY <переменная> В переменную (типа дата) записывается текущяя (получаемая от операционной системы) дата. BASENAME <строчная переменная> Оператор записывает в переменную - аргумент текущее значение префикса имен отно шений (см. раздел об отношениях). COUNT_REC <выборка> (текущая) <переменная> В переменную, которая должна быть целого или длинного целого типа заносится число записей в выборке - первом аргументе. COUNT_FLD <выборка> (текущая) <переменная> В переменную, которая должна быть целого или длинного целого типа заносится число полей в выборке - первом аргументе. GET_FLD_NUM <поле выборки> <номер поля> Во второй аргумент (целого типа) заносится номер поля - первого аргумента - в его выборке. SET_FLD_NUM <выборка> (текущая) <номер поля> (0) Устанавливает поле, заданное выборкой и номером поля в ней, текущим для этой вы борки. FLD_INFO <выборка> (текущая) <номер поля> (0) <имя поля (строка)> () <ширина (целое)> () <маска (строка)> () В третий, четвертый и пятый аргументы (которые должны быть переменными) зано сится информация о поле, заданном именем выборки и номером поля в этой выборке. Каж дый из выходных аргументов может быть опущен. В третий аргумент заносится имя поля, в четвертый - его ширина на экране, а в пятый - маска редактирующих свойств поля, имющая тот же формат, что и чеветртый аргумент команды fld в описании формы. - 110 - FORM_INFO <выборка> (текущая) <число полей> () <имя формы> () <имя отношения> () Во второй, третий и четвертый аргументы (которые должны быть переменными) запи сывается информация о выборке - первом аргументе. Любые из выходных аргументов могут быть опущены. IS_FLD_UPD <переменная> (текущее поле) Оператор выполняется успешно, если указанная переменная (по умолчанию текущее по ле текущей выборки) было изменено после считывания записи. RET_CODE <целая переменная> Оператор заносит в переменную значение 1, если предыдущий оператор выполнился ус пешно и 0 в противном случае. Сам этот оператор не изменяет значение "регистра успеха". LINK_PTR <поле типа указатель> <строчная переменная или константа> () Оператор осуществляет привязку поля типа указатель (описанного командой ptr в опи сании формы) к конкретной переменной. Если в качестве второго аргумента указана перемен ная, то именно ее значение (а не ее имя!) рассматривается как имя привязываемой к указа телю переменной. Если второй аргумент опущен, то происходит привязка к текущему полю текущей выборки. LNK_NUM <переменная - указатель> <выборка> (текущая) <номер поля> (0) Привязывает указатель к полю выборки, заданному ее именем и номером поля в ней. IS_CASE_FLD <переменная> (текущее поле) Оператор выполняется успешно, если указанная перемнная (по умолчанию - текущее поле текущей выборки) есть поле типа выбор. Арифметика Для выполнения арифметических действий служат следующие операторы: - 111 - + <переменная> <переменная или константа> - <переменная> <переменная или константа> * <переменная> <переменная или константа> / <переменная> <переменная или константа> % <переменная> <переменная или константа> Эти операторы реализуют арифметические операции. Их операнды должны быть целого или длинного целого типов. Выполнение их состоит в произведении операции над первым и вторым операндом, и присваивании результата первому операнду. При операции деления ос- таток отбрасывается. Операция % означает получение остатка от деления нацело. Работа со строками CONC <строчная переменная> <переменная или константа> () <переменная или константа> () <переменная или константа> () <переменная или константа> () Строковые значения второго .. пятого аргументов (которые могут быть любого типа) "сцепляются" и получившаяся строка присваивается первому аргументу. Если результирующая строка слишком длинная, чтобы поместиться в первом аргументе, то она усекается. SUBSTR <строчная переменная> <строчная переменная или константа> <переменная или константа> (-1) <переменная или константа> (-1) Выделение части строки заданной вторым аргументом в первый. Третий аргумент ука зывает позицию начала подстроки (начиная с 0), а четвертый - длину подстроки. По умолчанию подстрока начинается с начала строки-аргумента и продолжается до ее конца. REPLACE <строчная переменная> <целая переменная или константа> (0) <строчная переменная или константа> Заменяет подстроку в первом аргументе. Позиция начала подстроки определяется вто рым аргументом, а длина - длиной третьего аргумента. - 112 - STRLEN <строчная переменная или константа> <целая переменная> Второму аргументу присваивается значение длины строки - первого аргумента. STRSTR <строчная переменная или константа> <строчная переменная или константа> <целая переменная> () Поиск позиции подстроки (второго аргумента) в строке (первом аргументе). Оператор завершается успешно, если подстрока найдена. Если задан третий аргумент, то ему присваи вается номер позиции в строке, с которой начинается подстрока. STRFILL <строчная переменная> <ширина> (0) <символ заполнитель> (пробел) Оператор служит для выравнивания строки - первого агумента в зависимости от значения ширины (которая должна быть целой переменной или константой). Если ширина равна 0, то в строке пожимаются начальные и концевые пробелы. Если ширина больше 0, то содержимое строки пожимается к правому краю поля указанной ширины, а если меньше 0 - то к левому. "Пустое место" в строке заполняется символом заполнителем. CHR <строчная переменная> <целая переменная или константа> Первому аргументу присваивается строка из одного символа, код которого задан вто рым аргументом. ORD <целая переменная> <строчная переменная или константа> Первому аргументу присваивается значение кода первого символа второго аргумента. Наверное (???) завершается неуспехом, если второй аргумент пуст. SPELL_NUM <строчная переменная> <числовая переменная или константа> <0 или 1> (0) Первому аргументу присваивается "произнесенное" словами значение второго (сумма прописью). Если второй аргумент имеет целый или длинный целый тип, то результат содер жит только значение второго. Третий аргумент при этом определяет грамматический род, 0 - мужской, 1 - женский. Если же второй аргумент имеет плавающий тип, то результат пред ставляется в виде ". . . руб . . . коп", третий аргумент при этом значения не имеет. - 113 - Работа с датой MK_DATE <переменная типа дата> <целая переменная или константа> <целая переменная или константа> <целая переменная или константа> Сбор первого аргумента из значений остальных - дня (второй аргумент), месяца (третий аргумент) и года (четвертый аргумент). SEP_DATE <переменная или константа типа дата> <строчная переменная> <строчная переменная> <строчная переменная> Разбор даты (первого аргумента) на значения дня (второй аргумент), месяца (третий аргумент) и года (четвертый аргумент). DIFF_DATE <целая переменная> <переменная или константа типа дата> <переменная или константа типа дата> Первому аргументу присваивается значение разности в днях между вторым и третьим аргументами. Работа с элементами массива Для работы с элементами массива, т.е. переменной, описанной как array служат опера торы getel (взять значение элемента) и putel (записать значение элемента). Их формат: GETEL <переменная> <массив> <индекс> (0) В переменную (первый аргумент) записывается значение <индекс>-го (по умолчанию нулевого) элемента <массива>. Если переменная-массив не определена, то полученный эле мент также будет неопределен. Оператор завершается неуспехом при выходе индекса за гра ницы массива. Индексом может быть числовая переменная или константа. PUTEL <переменная> <массив> (0) <индекс> В элемент массива, определяемый индексом, записывается значение переменной. Если переменная была определена, то после этого оператора массив также будет определен. Кроме этих операторов имеется операто - 114 - DIM <числовая переменная> <переменная-массив> который записывает в переменную количество элементов в массиве. Таким образом идиома цикла по элементам массива может быть одной из следующих: array ar %d 100 proc a var i %d var j %d var el %d = i 0 -- вариант 1 - прекращение цикла по невозможности -- взятия очередного элемента loop getel el ar i else break -- обработка элемента el + i 1 endloop -- вариант 2 - явное определение размерности массива dim ar j = i 0 loop getel el ar i -- обработка элемента el if i >= j then break + i 1 endloop endproc Диалоговые операторы Операторы, описанные ниже служат для организации интерактивного диалога с пользо вателем, а также для вывода некоторой информации о текущем состоянии RatBase - 115 - CHOICE <имя списка форм> (список всех форм) <тип меню> (V) <координаты> (5:5) <0 или 1> (0) По заданным координатам выводится меню содержащее имена всех форм заданного списка. Описание типа меню см. в операторе CHOICE_EDIT. При выборе в меню то, что выб рали становится "последним выбранным". С последней выбранной формой работает оператор OPEN, если ему не задано имя формы. Последний параметр определяет убирать (0) или нет (1) меню с экрана после выбора. MEM В нижнюю строку экрана выводится сообщение, содержащее следующую информацию: - общий размер свободной памяти; - количество форм и объем памяти, занимаемый описаниями форм; - количество процедур, и занимаемая ими память. FORM_NAMES <0 или 1> Включить(1)/выключить(0) режим индикации имен форм в статусной строке. По умолчанию этот режим включен. При этом во второй строке экрана выводятся имена редак тируемых форм, через которые мы "прошли" путем перехода по связям. Например, если ре- дактировалась форма "a", а затем из нее по связи перешли к редактированию формы "b", то в статусной строке будет содержаться: a b При выключенном режиме индикации форм содержимое статусной строки формируется программно, с помощью оператора SHOW_MODE. SHOW_MODE <строка или переменная> Дописать указанный текст (или переменную любого типа, преобразованную к тексту) в статусную строку. По выходу из процедуры, содержащей этот оператор, содержимое статус ной строки восстанавливается - 116 - MESS <переменная или константа> <строка:колонка> (строка сообщений) <атрибут> (цвет сообщений) Выводит текстовое значение первого аргумента (который может быть любого типа) по указанным координатам. Цвет определяется третьим параметром. Для продолжения работы необходимо нажать любую клавишу на терминале. QUERY <переменная или константа> ("Вы уверены ?") <умолчание> (1) В центре экрана выводится горизонтальное меню, содержащее пункты "Да" и "Нет". Текстовое значение аргумента служит заголовком этого меню. Оператор выполняется успеш но при выборе в меню "Да", иначе (при выборе "Нет" или отказе от выбора нажатием Esc) - неуспешно. Второй аргумент указывает начальное положение курсора в меню: 1 - да, 0 - нет. SCALE <переменная или константа> <переменная или константа> Этот оператор вместе с оператором CHK_SCALE служит для организации "индикатора прогресса" (к сожалению не существует общепринятого русского термина, соответствующего английскому "progress indicator"). Индикатор прогресса служит для динамического отобра жения на экране изменения каой-либо числовой величины. Широко известным примером ин дикатора прогресса может служить "ползущая" шкала при копировании файлов с помощью Norton Commander-а. Данный оператор служит для задания параметров индикатора, а CHK_SCALE - для ука зания текущего значения индицируемой величины. Первый аргумент оператора содержит текст в заголовке индикатора. Второй (целое число) определяет формат индикатора. Если он > 0, то определяет верхнюю границу значений индикатора, при этом будет выводится "ползущая" линейка (похожая на Norton Commander). Если второй аргумент < 0, то значения индикатора будут выводиться в виде чисел там же, где и линейка. При равенстве 0 второго параметра в строке сообщений будет выводиться текущее значение индикатора. CHK_SCALE <переменная или константа> <переменная или константа> (1) Этот оператор служит для вывода в индикатор прогресса, заданный с помощью опера тора SCALE текущего значения индицируемой величины. Аргументы должны иметь целый или длинный целый тип. Первый аргумент - текущее значение индицируемой величины. При его равенстве нулю индикатор прогресса снимается с экрана. Второй аргумет определяет шаг - через сколько единиц будет реально изменяться состояние индикатора на экране. При инди цировании быстроизменяющейся величины целесообразно задавать шаг большим единицы. Оператор завершается неуспешно, если к моменту его выполнения на терминале была нажата клавиша Esc. Типичное действи - 117 - после неуспеха оператора CHK_SCALE - завершить (возможно с переспросом) цикл, в котором он вызывается. BEEP <целое> <целое> Издать на консольном терминале звуковой сигнал с частотой первого аргумента (Гц) и длительностью второго (мс). PLAY <переменная или константа> Сыграть музыку, заданную строкой - аргументом. Формат этой строки есть тайна вели кая. Вывод информации на внешние носители Вывод информации из RatBase в файлы или на принтер производится через использо вание выходного потока. RatBasic содержит как низкоуровневые операторы вывода (отдельных символов и строк), так и высокоуровневые, позволяющие вывести изображение бланка формы или получить полный отчет. Параметры выходного потока (специмена) Выходной поток - средство вывода из RatBase информации на внешние носители. В от личие от привычной в языках программирования работы с текстовыми файлами выходной по ток всего один, но он может программно назначаться на различные файлы или принтер. В выходной поток можно выводить как отдельные строки и символы, так и изображение блан ка или строки таблицы целиком. При работе с выходным потоком следует иметь в виду, что собственно вывод происхо дит при выполнении операторов OUT_CR, OUT_FORM, OUT_TAB, OUT_FLUSH, а также при закрытии и переоткрытии выходного потока. Остальные (низкоуровневые) операторы этого раздела только формируют выходную строку. В частности можно сначала прописать строку некоторым символом-заполнителем, а затем наложить сверху какой-либо текст. Формируемый выходной поток может автоматически разбиваться на страницы, кроме того страницы могут автоматически нумероваться. Для задания различных характеристик вы ходного потока, таких, как высота страницы, включение нумерации страниц, а также для по- лучения информации о текущем состоянии выходного потока (например номер текущей стра ницы) служит аппарат специальных имен. Как уже говорилось, единственным контекстом упоминания специмени может быть внешнее имя поля в команде fld описания формы. Таким образом доступ к значениям пере менных, обозначаемых специменами возможен только через включение из в какую-либо фор му. Ниже перечислены специмена и их значение - 118 - #LeftMargin - отступ левого края выводимого текста относительно левого края страни цы. Если он > 0, то текст будет выводиться начиная с #LeftMargin позиции листа. Если < 0 (отступ текста влево от листа), то в вывод попадут только символы начиная с #LeftMargin позиции текста. #RightMargin - правая граница листа, в выходную строку будет помещаться не более #RightMargin символов. #PgSize - высота страницы. Если она больше 0, то после вывода каждых #PgSize строк будет производиться перевод страницы. Если меньше 0, то разбиения на страницы не происходит. #PgNum - номер текущей выводимой страницы, при открытии выходного потока уста навливается в 1. #PgNumOn - включен (1) / выключен (0) режим автонумерации страниц. Если включен, и в выходном потоке не назначен хук на перевод страницы, то в начале каждой страницы помещает ее номер посередине листа. #LineInPage - количество строк, выведенных на текущую страницу. Низкоуровневые операторы вывода OUTPUT <переменная или константа> <переменная или константа> (132) <0 или 1> (0) Направить выходной поток в файл. Первый аргумент задает имя файла, второй - шири ну страницы в знакоместах. Третий указывает, всегда создавать новый файл (0) или дописы вать уже существующий, если файл с таким именем уже существовал (1). При выполнении этого оператора предыдущий выходной поток закрывается, если он был открыт. OUT_PRN <переменная или константа> (65) Направить выходной поток на принтер. Задается ширина страницы. При выполнении этого оператора (так же, как и при выполнении оператора OUTPUT) предыдущий выходной поток закрывается, если он был открыт. OUT_CLOSE Закрыть выходной поток. OUT <переменная или константа> <переменная или константа> () <переменная или константа> () <переменная или константа> () <переменная или константа> () Вывести в выходной поток значения аргументов. Все аргументы, кроме первого могут быть опущены. Перед выводом все аргументы преобразуются к текстовому виду - 119 - OUT_FILL <переменная или константа> (пробел) <переменная или константа> (-1) Первый аргумент должен иметь строковый тип. Оператор вызывает заполнение строки вывода значениями первого символа этой строки на длину, равную второму аргументу. Если второй аргумент опущен, или меньше 0, то строка вывода заполняется на всю ширину. OUT_CR <кол-во строк> (1) Вывод накопленной к этому времени строки вывода и перевод строки в выходном по токе. Если аргумент указан, то после вывода строки в выходной поток будет выведено еще (аргумент-1) пустых строк. OUT_POS <переменная или константа> <переменная или константа> Текстовое значение второго аргумена заносится в выходную строку с позиции, опреде ляемой первым аргументом. Оператор позволяет формировать выходную строку по частям, и не обязательно слева направо. OUT_TAB <выборка> (текущая) В выходной поток выводится изображение строки таблицы, соответствующей текущей записи указанной выборки. Этот оператор приводит к реальному выводу на носитель, после чего в выходном потоке производится перевод каретки. OUT_IN_COL <имя переменной> <имя строчной переменной или константы> С помощью этого оператора удобно выводить заголовки таблиц в выходных докумен тах. Первый аргумент - имя поля, соответсвующего одному из столбцов таблицы. Оператор выводит в выходной поток второй аргумент с позиции, определяемой положением в таблице столбца, соответствующего первому аргументу. OUT_CODE <код символа> Вывод в выходной поток символа с указанным кодом. OUT_FLUSH Производится вывод в выходной поток выходной строки, накопленной до сих пор. OUT_FORMFEED <строчная переменная или константа> () Оператор вызывает перевод страницы в выходном потоке (предварительно автома тически выполняется OUT_FLUSH). Если аргумент задан, то перед началом вывода новой страницы выполняется оператор QUERY с этим аргументом (например "Принтер готов Да / Нет?). Если оператор отвечает "нет" или нажимает Esc, то OUT_FOMFEED оканчивается не удачей - 120 - ON_FF <имя процедуры> Оператор позволяет задать хук - процедуру, которая будет автоматически вызываться при заполнении страницы выходного потока. По умолчанию вызывается оператор OUT_FORMFEED. Процедура - хук может выводить шапку страницы и пр., в частности опять же вызывать OUT_FORMFEED. OUT_FF Вызов процедуры - хука перевода страницы в выходном потоке. Эта процедура либо умолчательная, либо определена ранее оператором ON_FF. Высокоуровневые операторы вывода OUT_FORM <выборка> (текущая) <целая переменная или константа> (-1) <имя секции> () В выходной поток выводится изображение бланка указанной выборки со значениями полей, соответствующими текущей записи выборки. Количество выводимых строк ограничено вторым аргументом. Если изображение бланка содержит меньше строк, чем указано во вто- ром аргументе, то выводится нужное число пустых строк. Если же второй аргумент меньше реальной высоты бланка, то "лишние" строки не выводятся. Если второй аргумент <= 0, то количество выводимых строк равно высоте бланка. Третий аргумент определяет имя секции бланка, выводимой в выходной поток. По умолчанию выводится неименованная секция. REPORT <выборка> (текущая) <опции> () Наболее "мощный" оператор вывода, выдает в выходной поток отчет, сформированный из указанной выборки. Об описании отчета, а также примеры см. параграф " Команды описания отчетов (group, sum, num) " на стр. 59. Если в качестве выборки указано имя формы, и для этой формы не было активной, то выборка открывается, а после вывода отчета закрывается. Опциями могут быть символы S и P. Если указана опция S, то перед выводом отчета происходит сорти ровка записей по значениям "групповых" полей отчета. Если эта опция не указана, то записи выводятся в порядке их линейного просмотра. При задании опции P прибавление новых значений к полям-сумматорам происходит ПЕРЕД выводом записи. Если же эта опция не задана, то суммирование происходит ПОСЛЕ вывода записи. При выводе отчета на экране находится "индикатор прогресса", сообщающий, сколько записей выведено. При выводе отчета оператор может нажать Esc, после чего возможно пре кращение выдачи отчета - 121 - Работа с именами файлов Описанные здесь операторы поволяют формировать новые уникальные имена файлов, а также производить программный просмотр каталогов диска. TMP_NAME <имя файла> <расширение> () В первый аргумент (строчная переменная) записывается уникальное имя файла, гаран тируется, что файла с таким именем еще не существует. Второй аргумент, если задан, опре деляет расширение (тип) этого файла. FINDFIRST <имя файла> () <образец> (*.*) <0 или 1> (0) <директория> () Оператор заносит в первый аргумент (строчная переменная) имя найденного файла, со ответсвующнго образцу. Третий аргумент указывает, производить поиск собственно файлов (0) или каталогов (1). Четвертый аргумент перед вызовом оператора задает каталог, в кото ром производится поиск, после выполнения оператора он содержит найденный каталог. Опе ратор успешен, если найден файл, удовлетворяющий условию. Если не задан первый аргу мент, оператор может применяться для проверки существования файла (файлов). FINDNEXT <имя файла> () <0 или 1> (0) Оператор должен вызываться после успешного вызова FINDFIRST. В первый аргумент (строчная переменная) заносится имя очередного файла, удовлетворяющего условиям, задан ным в операторе FINDFIRST. Второй аргумент имеет тот же смысл, что и в FINDFIRST - по иск файлов или каталогов. Оператор успешен, если найден очередной файл. Таким образом типичный цикл "прохода" по файлам выглядит примерно так - 122 - var s %s findfirst s, '*rdb then mess s findnext s else break endif FILE_CHOICE <имя выбранного файла> <образец имени> (*.*) <заголовок> (Выбор файла) <список типов> () Оператор служит для выбора имени существующего или ввода нового имени файла в "бланково-табличном" виде, принятом в порядочных программах. Под MS Windows выбор ре ализован с помощью стандартного для Windows dialog box-а. Первый аргумент - строчная пе ременная, в которую помещается имя выбранного файла. Остальные аргументы - строчные пе ременные или константы. Образец имени определяет множество файлов для просмотра (в частности устройсво и каталог). Заголовок появляется вверху окна выбора файла. Последний аргумент имеет смысл только для MS Windows. Он определяет содержимое окошка типов файлов в dialog box-е. Формат этого аргумента: {<разделитель><название типа файлов><разделитель><образец имени>} например - 123 - var s %s file_choice s *.rdb 'Имя$отношения '@Отношения@*.rdb@Все$файлы@*.* При работе не под MS Windows переход из строки имени файла в список файлов и ка талогов происходит по нажатию Enter Enter Enter (если имя файла содержит метасимволя, такие, как *), обратно - по Esc Esc Esc. Оператор успешен, если выбрано или введено корректное имя файла. Работа с экраном Операторы этого раздела не действуют под MS Windows. SCR_CLR Очистка экрана терминала. SCR_FILL <окно> (весь экран) <код символа> (пробел) <атрибут> (нормальный) Указанное окно на экране заливается указанным же символом (заданным своим кодом) с не менее указанным атрибутом. SCR_WRITE <имя переменной или константа> <имя переменной или константа> <имя переменной или константа> <атрибут> (нормальный) Вывести текст (первый аргумент) в координатах <второй аргумент>:<третий аргумент>. Второй и третий аргументы должны иметь целый тип. Цвет выводимого текста определяется четвертым аргументом. Работа с отладчиком BP Этот оператор включает работу с интерактивным отладчиком (см. стр 124 ) - 124 - BRK_MSG <строка или переменная> Назначить сообщение, выдаваемое при неуспешном окончании содержащей этот опера тор процедуры. Управление выполнением TRUE FALSE Всегда выполняются успешно и неуспешно, соответственно. IF <имя переменной или константа> <операция сравнения> (!=) <имя переменной или константа> (0) Операция сравнения - одна из ==, !=, <, <=, >, >=, *, *=. Успех оператора совпадает с истинностью операции сравнения. Работа с клавиатурой KB_PRESSED <0 или 1> (0) Оператор завершается успешно, если к моменту его выполнения была нажата (и еще не обработана) клавиша на клавиатуре терминала. Если аргумент равен 0, то информация об этой клавише "пропадает" из очереди введенных клавиш, т.е. она в дальнейшем не будет об- работана. Если же он равен 1, то нажатая клавиша будет в дальнейшем обработана - напри мер редактирующими процедурами. TIME_OUT <целое> <обозначение клавиши> Эмулируется циклическое нажатие клавиши через абсолютное значение <арг1> секунд. В случае положительного значения аргумента этот процесс прекращается по реальному нажа тию любой клавиши. Если аргумент отрицателен, то эмуляция нажатий клавиш прекращается только после выполнения оператора TIME_OUT с первым аргументом равным 0. KB_UNGET <обозначение клавиши> Эмулируется однократное нажатие указанной клавиши. Работа с экземплярами процедур INST_MAKE <текстовая переменная или константа> <переменная> Во второй аргумент, который должен иметь длину, достаточную для размещения кон текста выполнения процедуры, записываетс - 125 - начальное значение этого контекста для проце дуры, имя которой задается первым параметром. INST_IN_RUN <переменная> Переменная должна содержать контекст выполнения процедуры. Оператор завершается успешно, если экземпляр процедуры был приостановлена вызовом SLEEP, и неуспешно, если его выполнение еще не начиналось, либо произошел выход из процедуры. INST_CALL <переменная> Переменная должна содержать контекст выполнения процедуры. Этот оператор иници ирует продолжение (или начало, если экземпляр процедуры еще не выполнялся) выполнения экземпляра процедуры. SLEEP Если этот оператор встречается в процедуре, вызванной по call, то он ничего не дела ет. Если же он вызывается из экземпляра процедуры, запущенного через INST_CALL, то он приводит к "засыпанию" экземпляра и возврату управления на оператор, следующий за INST_CALL. Впоследствии выполнение экземпляра может быть продолжено новым вызовом INST_CALL. INST_GET_POS <переменная> <контекст выполнения> Оператор записывает в переменную позицию в отношении, связанном с контекстом вы полнения процедуры. INST_SET_POS <контекст выполнения> <переменная> Оператор записывает в контекст выполнения значение переменной, которое должно быть идентификатором записи. Динамическая загрузка приложений Как уже говорилось, имя файла, содержащего программу на RatBasic-е указывается в командной строке запуска RatBase. Кроме этого имеется возможность в процессе выполнения программы загружать файлы, содержащие программы на RatBasic-е. Для этого служит опера тор APP_LOAD <строчная переменная или константа> Аргумент оператора содержит имя загружаемого файла. При динамической загрузке приложений следует иметь в виду такие моменты: - описывать глобальные переменные командами var, casefld, array и handle можно только в "корневом" файле, т.е. в файле указанном в командной строке запуска - 126 - - допускается предописывать (командой define proc) процедуры, тела которых будут ре ализованы в динамически загружаемом файле. Для форм это неверно, т.е. все пре дописанные формы должны быть полностью описаны в том же файле, в котором содержится их предописание (команда define form). Оператор завершается неуспешно, если загружаемое приложение содержит синтак сические ошибки (о чем выдается диагностика) или же не хватает памяти для загрузки. Динамически загруженный фрагмент приложения можно выгрузить, освободив тем са мым память занимаемую им. Для выгрузки приложения, ранее загруженного оператором app_load служит оператор APP_UNLOAD Дисциплина загрузки / выгрузки приложений - "последним пришел - первым ушел", т.е. оператор app_unload выгружает приложение, загруженное последним. Допускается до 10 уровней вызовов app_load. Как было сказано выше, в загружаемом файле могут быть реализованы тела ранее пре дописанных процедур. Для того, чтобы узнать, реализовано ли тело некоторой процедуры в момент выполнения служит оператор PROC_IS_DEF <имя процедуры> Имя процедуры - строчная переменная или константа. Оператор выполняется успешно, если указанная процедура полностью определена. !DEFINE <имя препроцессора> <значение имени> Оператор служит для динамического определения имен препроцессора. Его аргументы - текстовые переменные или константы. После выполнения оператора имени будет присвоено значение. В загружаемых после этого оператором APP_LOAD оверлеях приложения будет действительно новое определение имени. Оставшиеся операторы RUN <выборка> (текущая) Тестовое действие - последовательный перебор записей с выводом статистики. Пара метры перебора вводятся в диалоге. AUTO_FLUSH <0 или 1> (1) Включает (1) отключает (0) режим автофлаша. Выборки, открытые при включенном ре жиме постоянно сохраняют свою актуальность на физическом носителе. В начале выполнения режим автофлаша отключен - 127 - CHOICE_DO <имя списка процедур> <тип меню> (V) <строка:колонка> (5:5) <0 или 1 > (0) Циклический выбор в списке действий и выполнение выбранного действия. Тип меню - см. в операторе CHOICE_EDIT. EXIT_MENU Вызывает выход из первого меню (по CHOICE_DO или CHOICE_EDIT), к выбору в ко тором вернется управление после выполнения данного оператора. GET_VER <строчная переменная> (никакой) <переменная> (никакой) Если первый аргумент задан, то в него записывается строка, идентифицирующая при меняемую версию программы RatBase. Во второй аргумент (целого или строчного типа) запи сывается ключ зашифровки работающего приложения. Напомним, что шифровка приложения производится утилитой CRP, входящей в комплект поставки. Если запущенное приложение не зашифровано, то во второй параметр записывается 0. SYSTEM <строчная переменная или константа> () Оператор позволяет передать команду для выполнения операционной системе, в кото рой выполняется RatBase. Аргумент должен содержать имя выполняемой программы и ее ар гументы. Если аргмент не указан, то вызывается командный интерпретатор соответствующей ОС - COMMAND.COM для MSDOS и sh для Unix. Для возврата в RatBase после работы в этом интерпретаторе надо выполнить команду exit. GET_ENV <строчная переменная> <строчная переменная или константа> Оператор позволяет получить в первый аргумент значение переменной окружения опе рационной системы, имя которой задано вторым аргументом. Например в ОС Unix оператор get_env s 'HOME позволяет получить в s название рабочего каталога пользователя - 128 - Интерактивный отладчик При работе программы на RatBasic можно воспользоваться встроенным интерактивным отладчиком. Переход в отладочный режим происходит в двух случаях: - если в процедуре был выполнен оператор BP; - если процедура была определена с отладочной информацией, и при выполнении одного из ее операторов произошла ошибка приведшая к выводу сообщения об ошибке. При работе в отладочном режиме в нижней строке экрана выводится: - состояние регистра условия (T - успех, F - неуспех); - имя выполняемой процедуры; - номер строки (-1 если уровень отладки off); - название следующего выполняемого оператора (при уровне отладки off или line) 8 или полный текст строки процедуры (при уровне отладки full). В ответ на приглашение отладчика можно нажать: пробел - выполнение следующего оператора, если выполняется оператор call, то проис ходит "вход" в вызываемую процедуру. P (лат) - то же, но входа в вызываемую процедуру по call не происходит, после call от ладчик останавливается на следующем за ним операторе вызывающей процедуры. Enter - просмотр открытых выборок и переменных. Выводится меню, содержащее имена всех открытых выборок с их номерами. После номера выборки следует одно или несколько имен форм, разделенных двоеточием. Это формы, для которых данная выборка является активной. 8 Следует иметь ввиду, что условные блоки транслируются в совокупность условных переходов, поэтому при уровне отладки off или line вместо then и else в условных блоках названием оператора будет goto - 129 - Esc - прекращение работы с отладчиком. После нажатия Enter в меню всех выборок можно выбрать одну из них, также нажати ем Enter. На экран выводится бланк, который содержит ВСЕ поля выборки и их текущие значения. Глобальным переменным соответствует выборка с именем формы VARS - 130 - 131 - Указатель ключевых слов языка RatBasic В данном предметном указателе операторы набраны на верхнем регистре (CHOICE_DO), а остальные ключевые слова - на нижнем (casefld). != .............51 AUTO_FLUSH....101 DIFF_RECS .....81 !? .............52 base...........10 DIM ...........90 # ..............51 BASENAME.......86 EDIT ..........75 #askdef .........6 BEEP...........93 EDIT_BY .......75 #askval .........6 BLN->..........77 editby ........40 #define .........5 BP.............97 else ..........62 #else ...........6 break..........64 EMP ...........85 #endif ..........6 brk............60 EMP_REC .......80 #ifdef ..........5 BRK_MSG........98 endform .......19 #ifndef .........6 butattr........38 endlist .......15 #include ........5 button.........42 endproc .......58 #undef ..........5 casefld........26 endstyle ......38 % ..............87 CHK_SCALE......92 EXIT ..........78 * ..........51, 87 CHNG_SHOW......77 EXIT_MENU ....101 *= .............51 CHOICE.........91 FALSE .........98 + ..............87 CHOICE_DO.....101 FIRST .........85 - ..............87 CHOICE_EDIT....75 fld ...........22 -> .............52 CHR............88 fld_filler ....35 / ..............87 CLOSE..........74 fldattr .......38 < ..............51 CLOSE_IDX......84 fldcolor ......40 <= .............51 CND............78 form ......18, 19 <== ............81 CND_RESET......79 FORM_NAMES ....91 = ..............85 CND_SET........78 frame .........39 == .............51 color..........36 frmattr .......38 ==> ............81 CONC...........88 GET_ENV ......101 > ..............51 continue.......64 GET_HND .......74 >= .............51 copy...........15 GET_LINKED ....80 ?