InitList

/* ***********************************
 InitList() - описание интерфейса
 ***********************************

 FUNCTION InitList(
   01.nTop      - верхняя строка
   02.nBottom   - нижняя строка
   03.cColHead  - строка или массив строк - заголовок над полями,
   или если число, тогда считается, что заголовка нет и это
   ширина области вывода InitList
   04.aBlockCols - массив блоков кода для QBrowse() - см.S_Browse.prg
   05.cCurProc   - сопроцедура для QBrowse() - см.S_Browse.prg
   06._aHeads - Массив описания области ввода:
   {{блок->cтроку,имя поля,использование при вводе,исп-е.в фильтре,исп-е.в подсчете сумм}} или
   {{Строка,имя поля,использование при вводе,исп-е.в фильтре,исп-е.в подсчете сумм}} или
   {{y,x},
   имя поля или имя PRIVATE переменной или
   указание на элемент многомерного массива
   причем если массив не определен он инициализируется
   ,...}
   Необязательные параметры (по умолчанию '1'):
   элемент N
   3   Использование при вводе/корректировке:
   '0'-не используется
   '1'-используется
   4   Использование в фильтре:
   '0'-не используется
   '1'-используется, если тип-строка, то проверяется на принадлежность ($)
   '2'-используется, если тип-строка, то проверяется на равно слева (для счетов)
   5   Использование в подсчете сумм (если тип-число):
   '0'-не используется
   '1'-используется
   6   строка для подстановки фильтра
   в ней могут участвотать конструкции вызова массива aIn
   (заменяются на соотв.значения элементов)
   в виде aIn[x,y],aIn[x], но не aIn[x][y], а если
   использование aIn не явно, то предусмотреть, что
   его может не существовать после установки фильтра
   7  блок кода для суммирования
   8  кол-во строк занимаемых элементом aHeads (0 невыводятся)
   Пример 1:
   aInputHeads:={;
   {'Группа.................... ','Grup'},;
   {/номер................... ','NNum'},;
   {'Кол-во на начало периода.. ','Kol0'},;
   {'Цена   на начало периода.. ','Cena0'},;
   {'Склад..................... ','Sklad'},;
   {'Место хранения............ ','Mesto'};
   }
   В этом случае координаты ввода и вид картинки строится программно.
   Пример 2:
   aInputHeads:={;
   {{4,5},'Grup'},;
   {{4,25},'NNum'},;
   {{5,5},'Kol0'},;
   {{5,25},'Cena0'},;
   {{6,5},'Sklad'},;
   {{6,25},'Mesto'};
   }
   В этом случае картинку можно построить с помощью _bScrInit, а
   GETы будут располагаться в соответствии с указанными координатами.
   Если используется вывод заголовков посредством bSayHead,
   то aHeads обязательно ручной с координатами
   07._aRef      - массив имен справочников для полей ввода (построение - см.S_Refer);
   08._aPict     - массив шаблонов ввода;
   09._aWhen     - массив предусловий для ввода;
   10._aValid    - массив постусловий;
   В When-Valid функциях могут использоваться PRIVATE переменные:
   - nApp - режим ввода:
   0-ввод значений для фильтрации,
   1-корректировка,
   2-дополнение базы,
   - aIn[LEN(_aHeads)] - массив вводимых значений,
   - aLastIn[LEN(_aHeads)] - массив исходных значений (перед вводом)
   11._nUniMode  - режим проверки на уникальность:
   0 - не проверяет,
   1 - предупреждает,но позволяет вводить записи с одинаковыми ключами,
   2 - сообщает и не позволяет вводить записи с одинаковыми ключами.
   12._bDelInit  - блок проверки на возможность удаления текущей записи,
   выполняющийся перед запросом на удаление.
   Если возвращает (.F.), то дальнейшие действия не производятся,
   в противном случае может возвратить  наименование запроса на
   уничтожение ("Удалить документ?" и т.п.)
   13._bScrInit  - блок,выполняющийся перед построением картинки ввода, может исполь-
   зоваться для построения индивидуальных картинок ввода или для
   других предварительных действий;
   Возвращаемое значение:
   - 0 - дальнейший ввод не производится (запрет);
   - 1 - после EVAL(_bScrInit) выполняется стандартный ввод со
   стандартной картинкой и скроллингом;
   - 2 - после EVAL(_bScrInit) выполняется стандартный ввод
   по заданным в _aHeads координатам без построения
   стандартной картинки,но со скроллингом, в этом случае
   программист должен позаботиться,чтобы область ввода не
   пересекалась с областью скроллинга (списка);
   - 3 или NIL - то же самое, что и 2, но без скроллинга.
   - 4 - то же самое, что и 1, но без скроллинга.
   14._aSortSeek - массив сортировок и характеристик поиска.
   Если присутствует, то будет осуществляться поиск и
   выбор вида сортировки с соответствующей сменой главного индекса.
   Кол-во элементов равно кол-ву видов сортировки.
   Структура элемента:
   {
   1.строка в меню выбора,
   2.указание при вводе искомого значения,
   3.макровыражение для инициализации исходного значения aIn[1],
   4.макровыражение для SEEK-поиска после ввода aIn[1] или после поиска в связанной базе,
   5.cPicture-шаблон для ввода искомого значения,
   6.cValid для ввода искомого значения,
   7.cRef - имя справочника при вводе искомого значения,
   8.nOrd - имя тэга поиска/сортировки
   (по умолчанию - порядковый номер строки массива)
   если указывать в качестве 11 элемента массива
   имя тэга и не указывать 10 элемент, то 11 элемент
   используется для установки тэга поиска, а 8 для
   сортировки
   9.aGetBlock - массив oGet:bBlock
   10.алиас связанной базы
   - алиас дочерней базы по которой производится поиск
   11.тэг для поиска в родительской базе
   - имя тэга который выставляется перед поиском
   значения полученного выполнение 12 параметра
   12.макровыражение для SEEK-поиска в родительской базе
   - значение выражения используется для поиска записи
   в родительской базе
   13.признак сортировки - если .F., то по данному описанию
   производится только поиск и никакой сортировки
   14.макровыражение сортировки ключа для сортировки -
   если указано, то поиск по данной позиции некогда не выполняется
   15.признак отмены поиска - если .T., то  исключаем
   позицию из поиска
   }
   ВЫПОЛНЯЮТСЯ ПОСТРОЕНИЯ ВРЕМЕННЫХ СОРТИРОВОК В ВАРИАНТАХ :
   ПЕРВЫЙ ВАРИАНТ (сортировка снизу вверх) :
   Если aSortSeek[n,14] = NIL или не указан, то
   При указании алиаса связанной базы (10-12-ты элементы)
   производится поиск в дочерней базе
   по aSortSeek[n,4] и возврат
   по aSortSeek[n,12] в родительскую
   с учетом Scope и FILTER в родительской базе
   Производится поиск с учетом связей 1:1,1:M и M:1 (с возможностью
   найти следующую запись)
   Производится сортировка с учетом связей 1:1 и M:1, но не 1:M !
   Если требуется сортировка по связанной базе, то указание 8,10,11
   параметров обязательно.
   Причем при использовании связанной базы в родительской
   базе со scope тип scope должен быть символьный
   ПРЕИМУЩЕСТВА : быстрый поиск, медленная сортировка
   ВТОРОЙ ВАРИАНТ :
   Если aSortSeek[n,14] = макровыражение ключа сортировки, то
   Поиск не производится, производится сортировка
   При указании алиаса связанной базы (10-12-ты элементы)(можно не указывать)
   производится поиск в связанной базе по ключу
   по aSortSeek[n,12] и вычисление aSortSeek[n,14]
   для использования результата в качестве ключа для
   сортировки.
   Производится поиск с учетом связей 1:M
   Производится сортировка с учетом связей  M:1 !
   ПРЕИМУЩЕСТВА : поиск отсутствует, относительно быстрая сортировка
   МИНИМАЛЬНЫЙ ПРИМЕР ИСПОЛЬЗОВАНИЯ :
   Номер строки массива соответствует номеру индекса (если нет nOrd).
   Если производится поиск сразу по нескольким полям, то подэлементы
   2-3,5-7 должны быть массивами.
   Ввод искомых значений производится в PRIVATE-массив aIn, если
   одно значение, то - в элемент aIn[1].
   Пример:
   aSortSeek:={;
   {'- по кодам        ','Введите искомый код','Cod','UPPER(aIn[1])'},;
   {'- по наименованиям','Введите пеpвые символы наименования',;
   'LEFT(Name,5)',TRIM(UPPER(aIn[1]))}}
   15._aPHeads   - массив описания полей для печати:
   Простая структура,если последовательность полей в отчете соответ-
   ствует последовательности в базе данных:
   {Наименование отчета,наименование 1 поля,наименование 2 поля,...}
   Пример:
   aPHeads:=;
   {'Справочник групп товаров','Код','Наименование','Счет'}
   Более сложная структура:
   {
   Наименование отчета,;
   {наименование 1 поля,имя 1 поля в базе,шаблон вывода,признак суммирования},;
   {наименование 2 поля,имя 2 поля в базе,шаблон вывода,признак суммирования},;
   {блок кода возвращающий наименование 3,имя 3 поля в базе,шаблон вывода,признак суммирования},;
   ...
   }
   Пример:
   aPHeads:=;
   {"КАPТОТЕКА УЧЕТА ТМЦ НА СКЛАДЕ,{'Группа','Grup','XXXXXX'},;
   {'Н/ном','NNum'},{'Наименование','MLabel->Name'},;
   {{|| IF(n=1,"
Тест 1","Тест 2" },'MLabel->Name'},;
   {'Нач.остаток','Kol0',,.T.},{'Тек.кол-во','KolTek','99999999',.T.}}
   16._bPost     - постблок, выполняющийся после записи (REPLACE) данных в базу
   17._bDelPost  -блок,выполняющийся после запроса на удаление записи перед непосред-
   ственным удалением текущей записи
   18._aGetBlock - массив блоков считываания-записи для Get-объектов.Если указан,то
   заменяет стандартные блоки,формируемые автоматически.
   ему передается три параметра :
   1) x    - присваемое значение или NIL
   2) oGet - get объект (см. в конце описания доп.информацию)
   3) i    - второй индекс aIn[x,i] (в случае фильтра) или ноль
   если элемент aIn одномерный
   4) lDisplay - флаг первой прорисовки GetList
   ВНИМАНИЕ !!
   Если требуется подменить стандартно формируемые блоки кода
   в фильтре (при nApp = 0), своими , то требуется
   дополнительно передать в qInput параметр lGetBlock равный .T.
   19.bColor    - блок кода,возвращающий цвет для каждого поля вывода.
   Если указан, то по результату его выполнения будет устанавливаться
   цвет  при выдаче каждого в QBrowse() элемента строки (позволяет
   делать разноцветные строки и графы - см.также S_Browse)
   20.bColor1  - блок кода,возвращающий цвет для каждого поля вывода,аналогичный
   bColor, только для активной строки (см.также S_Browse)
   21.nLeftBrd - левая граница для Browse (при необходимости располагать не по центру)
   22.bScrPost - блок,выполняющийся после возврата из стандартной функции ввода/редакт
   23.cFindMacro - выражение поиска в символьном виде для функций Find(),FindFilter()
   искомая строка - PRIVATE cFind - вводится пользователем
   24.cCol_Browse - цвета для qBrowse(), по умолчанию COL_BROWSE
   25.lYesClear - если присутствует, то QBrowse() при скроллировании сначала очищает
   область, а потом отображает данные
   26.bPreGet - блок кода выполняемый пеpед каждым выполнением READ, до
   пpоpисовки GetList (при необходимости заранее проинециализировать aIn,
   а так же для навески SetKey'ев и формирования связанных таблиц до
   непосредственного редактирования)
   В блок кода передается флаг выхода по сслыке
   если его сбросить в .T. то быдет произведен выход из qInput
   не выполняя bPostGet
   В блок кода вторым параметром передается текущий aHeads
   27.bPostGet - блок кода выполняемый после каждого завеpшения READ,
   ему пеpедается флаг сохpанения данных .T. - данные были записаны в базу
   .F. - данные не были записаны в базу (выполняется после возможного
   выполнения bPost ),флаг изменения данных и флаг циклического
   ввода по ссылке, если его сбросить в -1 то циклического ввода не будет
   Если bPostGet вернет .F., то произойдет повторный вход в редактирование
   тем самым дается возможность не выпускать пользователя из режима редактирования
   пока он не исправит ошибки или вообще не будет сохранять данные
   Можно использовать для каких либо завершающих действий, в независимости
   от того, захотел ли пользователь сохранить данные или нет (например удаления
   проводок сформированных при добавлении документа и т.п.).
   28.nTag     - номер тега, по которому проверяется уникальность индекса
   29.nDispRow  - активная строка на экране (по умолчанию первая)
   30.aHotKey   - Массив описания "
ГОРЯЧИХ" клавиш
   { ;  // CTRL
   { 'F8:Удаление документа',;
   { 'F8:Удаление документа', K_CTRL_F8, {||DelDoc}, 1 },;
   { {|| IF( lTrue,'F8:Удаление документа', )}, ;
   K_CTRL_F8, {||DelDoc}, 2 },;
   { '', 555, , 3 } ;
   },;
   {},;   // SHIFT
   {} ;   // ALT
   }
   Где:
   (1) 'F8:Удаление документа' - Подсказка
   {|| ... }               - блок кода возвращающий подсказку
   или NIL, если подсказка ненужна
   (2) K_CTRL_F8               - Код горячей клавиши
   555                     - Признак, что подсказку нужно
   дополнить '-----'
   (3) {|| DelDoc }            - Блок кода выполняемы при нажатие
   клавиши, если он неуказан
   будет выполнен SetKey( )
   (4) 1                       - Порядок для сортировки
   подсказок на экране
   31.bRestSave - блок кода для восстановления и сохранения окружения GetList
   ему передается массив новых параметров или NIL, а он должен
   переопределить их и возвратить массив старых параметров
   32. bPostRead  - Блок кода выполняемый после READ
   Ему передаются два параметра: lUpdate, nLastKey
   Должен вернуть: .T. / .F.
   Если .F. - Возврат в READ
   Если .T. - Пошли на запись
   Пример:
   { |lUpdate, nLastKey| IF( nLastKey == K_ESC, .T., !EMPTY( aIn[1] ) ) }
   33.lSubIndex - .T. построение субиндекса при установке фильтра
   иначе ручного индекса (актуально только при фильтре и ручной сортировке)
   34.[bSayHead] - Блок вывода заголовка по ключу bKeyHead, если не выводить
   то должен вернуть NIL, выполняется только при смене ключа.
   (длина стоки = длине строки BlockCols,;
   рисует начиная от nLeftBrd).
   Получает параметры текущего ключа, и предидущего.
   (PreFiltOrd()- имя тэга до установки фильтра)
   35.[bKeyHead] - Блок ключа заголовка. ({|| UPPER(Grup)})
   Если не рисовать вернуть NIL.
   используется для прямого позиционирования по GetList
   (сбрасывается после обработки)
   используется для перезапука ReadModal() без выполнения чего либо
   (сбрасывается после обработки)
   Информация по обработке в qInput :
   ---------------------------------
   В каждом obj - get объекте дополнительно в name хранится специальная информация
   obj:name хранится массив структуры :
   {
   <имя aIn[индекс_1,индекс_2] - строка символов     >,;
   <ссылка на массив спец.информации (см.ниже)       >,;
   <индекс_1 - число                                 >,;
   <индекс_2 - число                                 >,;
   <предыдущее значение (до выполнение bGetBlock )   >,;
   <технологический  массив информации
   для обмена oGet:reader <-> oGet:block на уровне
   расширителей Get системы                        >,;
   <пользовательский зарезервированный элемент       >,;
   <имя в aHeads>;
   }
   если aIn[i] одномерный, то индекс_2 равен 0
   <предыдущее значение> - обновляется после выполнения bGetBlock
   присвоением aIn[i]
   Массив спец. информации :
   {
   ,;
   ,;
   ,;
   ,;
   - ссылка на массив информ.для восстан  >,;
   ,;
   - флаг повторного запуска ReadModal()            >,;
   без выполнения bPostGet,bPostRead, если .T.
   - номер позиционирования в GetList             >;
   }
   При выполнении aValid[i] или aGetBlock[i] (если указанный элемент блок кода !)
   для соответсвующего элемента предварительно восстанавливается
   оригинальная ссылка на aIn и другая информация, если указан bRestSave, а
   по выходу восстановливается текущая.
   Дополнительно для aIn[i] типа дата или число проводится проверка на
   максимальное значение перед выполнением оригинальной проверки.
   ДОПОЛНИТЕЛЬНО см. описание доп.параметров qInput
   Дополнительные функции :
   GetUpdateIn(a1,a2) возвращает .T. если массивы
   отличаются
   SaveSeekPos() возвращает массив координат
   окна запроса поиска
   GetSortSeek() возвращает текущий актуальный
   номер в aSortSeek
   #INCLUDE "
INKEY.ch"
   #INCLUDE "
s_refer.ch"
   #INCLUDE "
s_public.ch"
   #INCLUDE "
getexit.ch"
   #INCLUDE "
my.ch"
   #DEFINE MAX_NUMBER 999999999999999
   //#TRANSLATE NTOC(<x>) => ALLTRIM(STR(<x>,10,0))
   #DEFINE TOP_TAG(x) IF(;
   VALTYPE(x) = "
C",;
   x,;
   IF(;
   ORDNAME(1) == "
MY_INDEX" .OR.;
   ORDNAME(1) == "
MY_FILTER",;
   IF(VALTYPE(x) = "
N",x,1)+1,;
   IF(VALTYPE(x) = "
N",x,IF(EMPTY(ORDNAME(1)),0,1));
   );
   )
   #translate SELF() => qself()
   #DEFINE SYM15 '????????????????'
   #translate _ALT_HOT(   <x>, <y> ) => ;
   IF( aHotLine\[4\],( IF( aHotLine\[3\], ( AADD(aHotKey\[3\], {'',555,,100} ),aHotLine\[3\]:=.F.),),;
   AADD(aHotKey\[3\], {<x>,0,,<y>} )), )
   #translate _CTRL_HOT( <x>, <y> ) =>;
   IF( aHotLine\[4\],( IF( aHotLine\[1\], ( AADD(aHotKey\[1\], {'',555,,100} ),aHotLine\[1\]:=.F.),),;
   AADD(aHotKey\[1\], {<x>,0,,<y>} )), )
   #translate _SHIFT_HOT( <x>, <y> ) =>;
   IF( aHotLine\[4\],( IF( aHotLine\[2\], ( AADD(aHotKey\[2\], {'',555,,100} ),aHotLine\[2\]:=.F.),),;
   AADD(aHotKey\[2\], {<x>,0,,<y>} )), )
   #translate LEN_HEADS( <aHeads>) => (nLenHeads := 0,AEVAL(<aHeads>,{|x| nLenHeads += IF(LEN(x) \< 8 .OR. x\[8\] = NIL,1,x\[8\]) }),nLenHeads )
   STATIC aSaveInit := {},nLenHeads
   STATIC nTopi,nLefti,nBottomi,nRighti,sResti,sRest23
   STATIC statCod,aArea,lWasApp:=.F.
   STATIC bFindBlock, nPozSortSeek
   STATIC sPre:={}, nStOrder
   STATIC lMySort := .F.,bMySort, lMyRecurs := .F.
   STATIC aNameArray := {}, lDisplay := .F.
   STATIC lPlugGetBlock := .F.,lPlugValid := .F.
   STATIC OnRefer := .T.
   MEMVAR cFind
*/
 FUNCTION INITLIST(;
   _nTop,_nBottom,cColHead,aBlockCol,cCurProc,aHeads,aRef,aPict,aWhen,aValid,;
   nUniMode,bDelInit,bScrInit,aSortSeek,aPrintHeads,bPost,bDelPost,;
   aGetBlock,bColor,bColor1,_nLeftBrd,bScrPost,cFindMacro,cCol_Browse,;
   lYesClear,bPreGet,bPostGet,nTag,nDispRow, aHotKey,bRestSave, bPostRead,;
   lSubIndex,bSayHead,bKeyHead,lSet1Tag )
   PLOCAL _Buff := qInitPush()
   PLOCAL _cLastColor:=SETCOLOR()
   PLOCAL _nLeft,_nRight
   PLOCAL _nTopF,_nBottomF,_nLeftF,_nRightF
   PLOCAL _nTopS,_nBottomS,_nLeftS,_nRightS
   PLOCAL _nLen:=IF(VALTYPE(cColHead)=='A',LEN(cColHead[1]),IF(VALTYPE(cColHead) = "
C",LEN(cColHead),cColHead))
   PLOCAL nCo:=0,_cType,cCol_Heads
   PLOCAL nMaxFiSize:=0,nMaxFiSizF:=0,nMaxFiSizS:=0,lenPict
   PLOCAL bEdit :=SETKEY(K_RETURN)
   PLOCAL bAdd  :=SETKEY(K_F4)
   PLOCAL bFltr :=SETKEY(K_F6)
   PLOCAL bCFltr :=SETKEY(K_CTRL_F6)
   PLOCAL bAFltr :=SETKEY(K_ALT_F6)
   PLOCAL bShFltr :=SETKEY(K_SH_F6)
   PLOCAL bSort :=SETKEY(K_F3)
   PLOCAL bSeek :=SETKEY(K_F7)
   PLOCAL bLocate:=SETKEY(K_ALT_F7)
   PLOCAL bDel  :=SETKEY(K_F8)
   PLOCAL bPrint:=SETKEY(K_F9)
   PLOCAL bA3Date:=SETKEY(297)
   PLOCAL cFltr0:=DBFILTER() //Глобальный фильтр (до входа в InitList)
   PLOCAL cScopeMacro:=ScopeMacro() //Глобальный Scope (до входа в InitList)
   PLOCAL aHeadsI:={},aHeadsF:={},aHeadsS:={}
   PLOCAL aRefI:={},aRefF:={}
   PLOCAL aPictI:={},aPictF:={}
   PLOCAL aWhenI:={},aWhenF:={}
   PLOCAL aValidI:={},aValidF:={}
   PLOCAL aGetBlockI:={},aGetBlockF:={}
   PLOCAL aBlockCols:=ACLONE(aBlockCol), lenPict1
   PLOCAL aRetKey := {},;
   aHotLine := { .T., .T., .T., .T. }
   PLOCAL __bStPrint
   PLOCAL bGetHead1Len:={|x|; //z0ne
   IF(VALTYPE(x)=="
B",x:=EVAL(x),) ,;
   LEN(x);
   }
   RunPlugIns("
РЕЕСТР","ВХОД",IF(GETSCOPE() != NIL,GETSCOPE()[2],NIL),aHeads,cColHead)
   IF EMPTY(cFltr0)
   cFltr0:='.T.'
   ENDIF
   // Сделаем массив горячих клавиш
   IF !( VALTYPE( aHotKey ) $ 'AB' )
   aHotLine[1] := aHotLine[2] := aHotLine[3] := .F.
   aHotKey := { {}, {}, {} }
   ELSEIF VALTYPE( aHotKey ) == 'B'
   aHotLine[4] := .F.
   ELSE
   AEVAL( aHotKey, {|x,xi|IF( VALTYPE(x)<>'A', aHotKey[xi]:={}, ),;
   IF( EMPTY(x), aHotLine[xi]:= .F., ) } )
   ENDIF
   _ALT_HOT( 'Z:Калькулятор', 120 )
   IF GlobalTask != 'KP'
   _ALT_HOT( 'K:Блокнот',     121 )
   _ALT_HOT( 'V:Курсы валют', 122 )
   ENDIF
   _CTRL_HOT( 'PageUp:На первую запись', 123 )
   _CTRL_HOT( 'PageDown:На последнюю запись',124 )
   //  __HARBOUR__
   _ALT_HOT( 'X:Экспорт в Excel', 125 )
   _nLeft:=INT(IF(_nLeftBrd==NIL, (80-_nLen)/2, _nLeftBrd))
   _nLeft:=IF(_nLeft<=1,1,_nLeft)
   _nRight:=_nLeft+_nLen-1
   IF cCol_Browse!=NIL
   SETCOLOR(cCol_Browse)
   cCol_Heads:=cCol_Browse
   ELSE
   SETCOLOR(COL_BROWSE)
   cCol_Heads:=COL_HEADS
   ENDIF
   IF (VALTYPE(cColHead)=='C')
   @ _nTop++,_nLeft SAY cColHead COLOR cCOL_HEADS
   ELSEIF VALTYPE(cColHead) = 'A'
   AEVAL(cColHead,{|x|DEVPOS(_nTop++,_nLeft),DEVOUT(x,cCOL_HEADS)})
   ENDIF
   AEVAL(aBlockCols,{|x|aBlockCols[++nCo,2]:=x[2]+_nLeft}) //Пересчет aBlockCols
   IF (aHeads != NIL)
   //Определение координат поля ввода
   FOR nCo=1 TO LEN(aHeads)
   lenPict := IF((lenPict := IF(aPict==NIL .OR. LEN(aPict)<nCo .OR. aPict[nCo]==NIL,0,LEN(TRANSFORM(SPACE(100),aPict[nCo])))) = 100,0,lenPict)
   _cType:=IF(EMPTY(aHeads[nCo,2]),'C',(FiAlias(aHeads[nCo,2]))->(FIELDTYPE(FiNum(aHeads[nCo,2]))))
   // справочное поле со скрытым кодом !!!!!!!!
   _cType := IF(_cType != "
N" .OR. aRef = NIL .OR. LEN(aRef) < nCo .OR. EMPTY(aRef[nCo]),_cType,"C")
   IF LEN(aHeads[nCo])<3.OR.aHeads[nCo,3]='1'.OR.aHeads[nCo,3]=NIL
   AADD(aHeadsI,{aHeads[nCo,1],aHeads[nCo,2],,,,,,IF(LEN(aHeads[nCo]) >= 8,aHeads[nCo,8],1)})
   IF aRef!=NIL.AND.LEN(aRef)>=nCo
   AADD(aRefI,aRef[nCo])
   ENDIF
   IF aPict!=NIL.AND.LEN(aPict)>=nCo
   AADD(aPictI,aPict[nCo])
   ENDIF
   IF aWhen!=NIL.AND.LEN(aWhen)>=nCo
   AADD(aWhenI,aWhen[nCo])
   ENDIF
   IF aValid!=NIL.AND.LEN(aValid)>=nCo
   AADD(aValidI,aValid[nCo])
   ENDIF
   IF aGetBlock!=NIL.AND.LEN(aGetBlock)>=nCo
   AADD(aGetBlockI,aGetBlock[nCo])
   ENDIF
   nMaxFiSize:=MAX(nMaxFiSize,IF(lenPict==0.AND.!EMPTY(aHeads[nCo,2]),;
   (FiAlias(aHeads[nCo,2]))->(FIELDSIZE(FiNum(aHeads[nCo,2]))),lenPict))
   ENDIF
   IF LEN(aHeads[nCo])<4.OR.aHeads[nCo,4]>='1'
   AADD(aHeadsF,aHeads[nCo])
   IF aRef!=NIL.AND.LEN(aRef)>=nCo
   AADD(aRefF,aRef[nCo])
   ENDIF
   IF aPict!=NIL.AND.LEN(aPict)>=nCo
   AADD(aPictF,aPict[nCo])
   ENDIF
   IF aWhen!=NIL.AND.LEN(aWhen)>=nCo
   AADD(aWhenF,aWhen[nCo])
   ENDIF
   IF aValid!=NIL.AND.LEN(aValid)>=nCo
   AADD(aValidF,aValid[nCo])
   ENDIF
   IF aGetBlock!=NIL.AND.LEN(aGetBlock)>=nCo
   AADD(aGetBlockF,aGetBlock[nCo])
   ENDIF
   nMaxFiSizF:=MAX(nMaxFiSizF,IF(_cType=='N'.OR._cType=='D',2,1)*;
   IF(lenPict==0.AND.!EMPTY(aHeads[nCo,2]),;
   (FiAlias(aHeads[nCo,2]))->(FIELDSIZE(FiNum(aHeads[nCo,2]))),lenPict)+;
   IF(_cType=='N'.OR._cType=='D',3,0))
   ENDIF
   IF _cType='N'.AND.(LEN(aHeads[nCo])<5.OR.aHeads[nCo,5]='1')
   AADD(aHeadsS,{aHeads[nCo,1],aHeads[nCo,2],IF(LEN(aHeads[nCo]) >= 7,aHeads[nCo,7],NIL),,,,,IF(LEN(aHeads[nCo]) >= 8,aHeads[nCo,8],1)})
   nMaxFiSizS:=20
   ENDIF
   NEXT
   // Изменение 3.110
   IF LEN(aHeadsI)>0
   nTopi:= IF(_nBottom-LEN_HEADS(aHeadsI)-2 < 0,0,_nBottom-LEN_HEADS(aHeadsI)-2)
   nLefti:=(MAXCOL()-EVAL(bGetHead1Len,aHeadsI[1,1])-nMaxFiSize-4)/2 //z0ne
   nBottomi:= nTopi+LEN_HEADS(aHeadsI)+1
   nRighti := nLefti+EVAL(bGetHead1Len,aHeadsI[1,1])+nMaxFiSize+3
   IF(nBottomi < MAXROW() .AND. nTopi = 0,(nTopi += 1,nBottomi += 1),NIL)
   IF(nBottomi < MAXROW() .AND. nTopi = 1,(nTopi += 1,nBottomi += 1),NIL)
   sResti:= BRSAVESCREEN(nTopi,0,nBottomi+1,MAXCOL(),sResti)
   ENDIF
   IF bEdit==NIL.AND.LEN(aHeadsI)>0
   SETKEY(K_RETURN,;
   {||QInput(nTopi,nLefti,nBottomi,nRighti,aHeadsI,;
   1,aRefI,aPictI,aWhenI,aValidI,nUniMode,bScrInit,;
   bPost,cFltr0,,aGetBlockI,bScrPost,,bPreGet,bPostGet,;
   nTag,,,,,bRestSave,bPostRead,,bSayHead,bKeyHead)})
   ENDIF
   IF bAdd==NIL.AND.LEN(aHeadsI)>0
   SETKEY(K_F4,;
   {||QInput(nTopi,nLefti,nBottomi,nRighti,aHeadsI,2,aRefI,aPictI,aWhenI,aValidI,;
   nUniMode,bScrInit,bPost,cFltr0,,aGetBlockI,bScrPost,,bPreGet,bPostGet,;
   nTag,,,,,bRestSave,bPostRead,,bSayHead,bKeyHead)})
   ENDIF
   IF bFltr==NIL.AND.LEN(aHeadsF)>0
   _nTopF:= IF(_nBottom-LEN_HEADS(aHeadsF)-2 < 0,0,_nBottom-LEN_HEADS(aHeadsF)-2)
   _nLeftF:=(MAXCOL()-EVAL(bGetHead1Len,aHeadsF[1,1])-nMaxFiSizF-4)/2
   _nBottomF:=_nTopF+LEN_HEADS(aHeadsF)+1
   _nRightF := _nLeftF+EVAL(bGetHead1Len,aHeadsF[1,1])+nMaxFiSizF+3
   sResti:= BRSAVESCREEN(_nTopF,0,_nBottomF+1,MAXCOL(),sResti)
   IF(_nBottomF < MAXROW() .AND. _nTopF = 0,(_nTopF += 1,_nBottomF += 1),NIL)
   IF(_nBottomF < MAXROW() .AND. _nTopF = 1,(_nTopF += 1,_nBottomF += 1),NIL)
   SETKEY(K_F6,;
   {||QInput(_nTopF,_nLeftF,_nBottomF,_nRightF,aHeadsF,0,aRefF,aPictF,aWhenF,aValidF,;
   nUniMode,bScrInit,bPost,cFltr0,,aGetBlockF,bScrPost,cScopeMacro,bPreGet,bPostGet,;
   nTag,,,,,bRestSave,bPostRead,lSubIndex,bSayHead,bKeyHead)})
   SETKEY(K_CTRL_F6,{||QSetFilter(aHeads,,"
Снять")})
   _CTRL_HOT( 'F6:Снять фильтр', 106 )
   ENDIF
   IF bShFltr==NIL.AND.LEN(aHeadsS)>0
   _nTopS:= IF(_nBottom-LEN_HEADS(aHeadsS)-2 < 0,0,_nBottom-LEN_HEADS(aHeadsS)-2)
   _nTopS:=_nBottom-LEN_HEADS(aHeadsS)-2
   _nLeftS:=(MAXCOL()-EVAL(bGetHead1Len,aHeadsS[1,1])-nMaxFiSizS-4)/2
   _nBottomS:=_nTopS+LEN_HEADS(aHeadsS)+1
   _nRightS := _nLeftS+EVAL(bGetHead1Len,aHeadsS[1,1])+nMaxFiSizS+3
   sResti:= BRSAVESCREEN(_nTopS,0,_nBottomS+1,MAXCOL(),sResti)
   IF(_nBottomS < MAXROW() .AND. _nTopS = 0,(_nTopS += 1,_nBottomS += 1),NIL)
   IF(_nBottomS < MAXROW() .AND. _nTopS = 1,(_nTopS += 1,_nBottomS += 1),NIL)
   SETKEY(K_SH_F6,;
   {||QInput(_nTopS,_nLeftS,_nBottomS,_nRightS,aHeadsS,-1,,,,,,bScrInit,,cFltr0)})
   _SHIFT_HOT('F6:Суммирование', 106)
   ENDIF
   ENDIF
   IF cFindMacro!=NIL
   PRIVATE cFind:=SPACE(30)
   IF bLocate=NIL
   IniString(cFindMacro,cFltr0)
   SETKEY(K_ALT_F7,{||FindName()})
   _ALT_HOT('F7:Контекстный поиск', 107 )
   ENDIF
   IF bAFltr=NIL
   SETKEY(K_ALT_F6,{||FiltName(cFindMacro,cFltr0,cScopeMacro,,,,lSubIndex)})
   _ALT_HOT(IF(IsMsNT(),'F6','F12')+':Контекстный фильтр', 106 )
   SETKEY(K_ALT_F12,{||FiltName(cFindMacro,cFltr0,cScopeMacro,,,,lSubIndex)})
   SETKEY(K_CTRL_F6,{||QSetFilter(aHeads,,"
Снять")})
   ENDIF
   ENDIF
   lSet1Tag := IF(lSet1Tag == NIL,.T.,lSet1Tag)
   ViewSortSeek(aSortSeek,lSet1Tag,{||QSeek(aSortSeek,,,,.T.)},{||QSort(aSortSeek,,,,.T.)})
   IF (bDel==NIL)
   bDel:=SETKEY(K_F8,{||QDel(bDelInit,bDelPost,nTag)})
   ENDIF
   IF (aPrintHeads!=NIL .AND. bPrint==NIL)
   SETKEY(K_F9,{||QPrint(aPrintHeads,,,bSayHead,bKeyHead)})
   ENDIF
   SETKEY(297,{||A3DateView()})
   //SETKEY(-41,{||QIni(,2)}) //F12 - теперь будет для печати исп-ся
   IF IsRunPlugIns("
РЕЕСТР","ПЕЧАТЬ")
   __bStPrint := SETKEY(K_F9,{|| RunPlugIns("
РЕЕСТР","ПЕЧАТЬ",__bStPrint) })
   ENDIF
   WHILE .T.
   QBrowse(_nTop,_nLeft,_nBottom,_nRight,aBlockCols,,cCurProc,bColor,lYesClear,bColor1,nDispRow,aHotKey,@aRetKey,bSayHead,bKeyHead)
   IF aRetKey != NIL
   aRetKey[1] := EVAL(aRetKey[3],ProcName(1), ProcLine(1), "
")
   ELSE
   EXIT
   ENDIF
   ENDDO
   COMMIT
   QSetFilter(aHeads,,"
Снять",,"End")
 RunPlugIns("
РЕЕСТР","ВЫХОД")
 SETKEY(K_RETURN,bEdit)
 SETKEY(K_F4,bAdd)
 SETKEY(K_F6,bFltr)
 SETKEY(K_CTRL_F6,bCFltr)
 SETKEY(K_ALT_F6,bAFltr)
 SETKEY(K_SH_F6,bShFltr)
 SETKEY(K_F8,bDel)
 SETKEY(K_F3,bSort)
 SETKEY(K_F7,bSeek)
 SETKEY(K_ALT_F7,bLocate)
 SETKEY(K_F9,bPrint)
 SETKEY(297,bA3Date)
 SETCOLOR(_cLastColor)
 qInitPop()
 RETURN (NIL)