#include <stdio.h>
#include <stdlib.h>
#include <alloc.h>
#include <string.h>
#include <mem.h>
#include <dos.h>
#include <io.h>
#include <dir.h>
#include <graphics.h>
#include <wnd_asm.h>

#define isdigit_(c) ( (c)>47 && (c)<58 ) ? (1) : (0)
#define _tolower(c) ( (c>64&&c<91 || c>127&&c<144) ? (c+32) : ((c>143&&c<160) ? c+80 : c) )
#define isletter_(c) ( (c>64 && c<91) || (c>96 && c<123) || (c>127 && c<176) || (c>223 && c<240) ? 1:0)
#define BASE_NAME "test.dbf"
#define DIRECTIONS_FILE "direct.dbf"
#define CATALOG_FILE "catalog.dbf"
DOPEDITFUN Dop_Edit,Field_Save; MODE DOP_EDIT=NO, DOP_PACK=NO,FIELD_SAVER=NO;
extern MENU opr6,opr6_;
extern CASE tabl6[],tabl6_[];
extern FUN Ext_Function;
extern char Mouse,buttons,EDITOR;
extern int hor_position,ver_position;
extern int NowX,SUMX,Year;
extern char Mon,Day;
extern MODE Rails_,Shpala_,Epura_,Radius_;
extern int far Radius0[];
LONGFUN Do_Filtering;
void DBFSort (long,long); void SortMess (long);
void ReFile (void); int Cat_Pack (long Num);
void CreateInfo (char far *FileName);
char DBF_Create (char *Name, char Fields, char **Names, char *Types, char *Lens, char *Decs);
COMPAREFUN DBFCompare; LONGFUN Dop_Pack;

extern FILE far *Open_File (char far *Name, FILE *fp);
extern int Go_Work(void);
extern void Tf_Td_count(void),Inp_Peregon(void),Board_Peregon(void);
extern int strlen__(char far*,int *);
extern FILE *con_ptr;
extern MODE Thank,What;

extern KEY Start,End;                  // Начало и конец буфера ввода
//extern int HowManyPrint;
extern unsigned long LastFile;
extern char RegType;
extern void Ved1(void);
void Push (char far *Ptr); void Pop (char far *Ptr);
int FieldPosition (int FieldNum);
void Sel_From_Catalog (void); void Cat_End (void); void DBFappend (void);
void Characteristics (void); void Catalog_Filter (void);
void WriteCurrent (void); int Do_Catalog_Filter (long Num);
char Correct_Input (char far *String, int metx); long FilePosition (long Zap);
void LeftSide (char far *String, int Field); void InfoFile (char far *Name);
void RightSide (char far *String, int Field); void FillWith0 (char far *String);
void Win_Reg (void);

//char far *_fstrdel (char far *s, char c);
// Формы ввода даты
#define DMYY 0x01
#define YYMD 0x02
#define DMYMINUS 0x03
char IsDate (char *Date, char Form);

extern unsigned Temp_Type; // 1,2,3 - Index in TEMPS
static char *TEMPS[3]={"temp_n.dbf","temp_r.dbf","temp.dbf"};
int Direct_Print (long Num, int *How);
int Catalog_Print (long Num, int *How);
int Tabl_Print (long Num, int *How);
int Tempr_Print (long Num, int *How);
static char *VEDS[]=
 {"ved0.dbf","ved1.dbf"};
// {"ved0_r.dbf","ved1_r.dbf","ved2_r.dbf","ved3_r.dbf"}
//};
//static char *IZMS[4]={"izmer_l.dbf","izmer_r.dbf"};
MODE Line=0x00; // LEFT_LINE=0x00,RIGHT_LINE=0x01


int DBF_Init (char far *); void Change_Date (FILE far *);
void DBF_Zap (int);
int DBF_End(void); void Do_Format (void);
void Set_DBF (void), Set_Count(void);
//void Show_Selection (int), What_Line (int,int);
void Sel_Peregon(void); void Stan_End (void);
//void NoPrint (char far *,int far *,int);
void DBFWrite (long,long,int,int,char);
int isnumber(char far *);
void DBFinsert(long),DBFPrint(long,long),PRNSet(void);long DBFPack(long,long);
void LeftMargin (char far *); void RightMargin (char far *);
char far *segcpy__ (char far *,char far*,int);
int my2asc__ (char far *);


//static char Write_Key[4]; // Key for search in configuration file
unsigned STK=24; // Число стыков при последнем расчете
STRFUN Write_Field; // to DBFWrite
PRINTFUN StartPrint;

///////////////////////////////////////////////////////////////////
// Функции для окна обработки DBF-файла
static char String[STRING_LEN],InString[200];
static char Str1[16],Str2[16],Str3[16],Str4[16];
//	    Str5[16],Str6[16],Str7[16],Str8[16];
char far *InfoName="             ";
char far *Segment="                                    "; //36
#define FSIZE 12
 /* Размер строки формата */
WINDOW DBW; /* Окно обработки БД ;*/
char far *WinName;
FIELD FB;   /* Описание полей БД ;*/
dbffile DB; /* Заголовочная информация о БД ;*/
long Sel_Ptr;    //  указатель на выбранную запись
FUN After_DBF_Function;
char far * far *Other_Hdr;  // Указатель на заголовок и
int Max_Hdr_Line;       // макс. число строк заголовка
			// Исп.,если DB.Cond&0x04
char far * far *Fmt;    // Форматы вывода полей

int POS_STR;
char Del_Char='*',End_Char=0x1A, Start_Char=0x0D;

int STRtoPAGE=56,COLtoPAGE;
FILE  far *printer;
MODE Prn=0x00;
// xxxx xxx1 Печать заголовков в начале страницы
// xxxx xx1x Нумерация страниц
// xxxx x1xx Номера записей
// xxxx 1xxx Печать имени файла
//unsigned Open_Prn(unsigned);
MODE Search=NO;
extern char far Path[];extern MODE PathLen;
int DBF_Init (char far *FileName) {
 // инициализировать DBF-файл
 // 0  - OK
 // 1 - нет файла
 // 3 - нет памяти
 unsigned char far *hptr=NULL;
 int far *iptr=NULL;
 char far * far *vv=NULL,
      far * far *vv_beg=NULL,
      far * far *Fmt_beg=NULL,
      far *vv_ptr=NULL,
      far *Fmt_ptr=NULL;   // Заголовки полей
 dbfheader DBFhead;       // Заголовок файла
 dbffield FIL;            // Заголовок поля
 int l,k,i;
 char far *Str="  ";
 // Получить имя DBF-файла
 DB.fp=NULL;
 DB.fp=Open_File (FileName, DB.fp);
 if (DB.fp==NULL) { DB.Cond&=0xf7; //!!!
  return 1; }
 fseek (DB.fp,0L,SEEK_SET);
 // Считать заголовок
 fread (&DBFhead,32,1,DB.fp);
 DB.Cond&=0xFC; // Сброс флагов "Файл изменен" и "Запись удалена"
 DB.Zap=DBFhead.Zap; // число записей в базе
 DB.HeadLen=DBFhead.HeadLen; //дл.загол.части == 32+32*(число полей)+1;
 DB.Beg=DB.HeadLen;
 DB.ZapLen=DBFhead.ZapLen; //длина записи в базе == сумма длин полей + 1
 DB.Field=DB.HeadLen/32-1; //число полей

 // Выделить память
 i=_fstrlen(FileName)+DB.Field*12+DB.Field+DB.ZapLen+5;
 if (hptr!=NULL) {
  farfree (hptr); farfree (iptr); hptr=NULL;
 }
 hptr=(unsigned char far *) farmalloc (i);
 iptr=(int far *) farmalloc (2*(DB.Field)*sizeof (int));
 if (iptr==NULL || hptr==NULL) {
  Mistake (1); return 3; }
 DB.Lens=&(iptr[0]);
 DB.Decs=&(iptr[DB.Field]);
 _fmemset ((void far *)hptr,'\0',i);
 k=0;
 DB.Name=&(hptr[k]);  k+=_fstrlen(FileName)+1;
 DB.Names=&(hptr[k]); k+=DB.Field*12+1;
 DB.Types=&(hptr[k]); k+=DB.Field+2;
 DB.buffer=&(hptr[k]);
 DB.Types[DB.Field]=DB.buffer[DB.ZapLen]='\0';
 _fmemset (DB.Names,'\0',DB.Field*12);

 _fstrcpy (DB.Name,FileName);
 DBW.Title=WinName;
 for (l=0; l<DB.Field; l++) { // Заголовки полей БД
  fread (&FIL,32,1,DB.fp);
  _fmemcpy (&DB.Names [l*12], FIL.Name, 11);
  DB.Types[l]=FIL.Type;
  DB.Lens[l]=FIL.Len;
  DB.Decs[l]=FIL.Dec;
 }
 if (DB.Cond&0x08) { // Только инициализация
  DB.Cond&=0xf7; return 0; }

 l=sizeof(char far *);
 vv_beg = (char far * far *) farcalloc(DB.Field+ 1, l);
 Fmt_beg =(char far * far *) farcalloc(DB.Field, l);
 vv_ptr= (char far *) farmalloc ( (DB.Field+1)*FSIZE+1 );
 Fmt_ptr = (char far *) farmalloc (DB.Field*FSIZE);
 DBW.Line=(int far *) farmalloc ((DB.Field)*2);//Длины полей таблицы
 if (vv_beg==NULL || Fmt_beg==NULL ||
     vv_ptr==NULL || Fmt_ptr==NULL || DBW.Line==NULL) {
  Mistake (1); return 3; }
 // Подготовить заголовки столбцов , строки формата и размеры полей
 vv=vv_beg; Fmt=Fmt_beg;
 _fmemset (vv_ptr,'\0',(DB.Field+1)*FSIZE+1);
 _fmemset (Fmt_ptr,'\0',DB.Field*FSIZE);

 // Заголовки колонок вывода и форматы
 _fstrcpy (&(vv_ptr[0])," "); vv[0]=&(vv_ptr[0]);
 vv[0]="";
 for ( l=0 ; l < DB.Field ; l++ ) {
  vv[l+1]=&(vv_ptr[(l+1)*11+l]);
  Fmt[l]=&(Fmt_ptr[l*11+l]);
  if (DB.Cond&0x04) { // Другой заголовок
   if (Other_Hdr[l+1][0]!='\xFF') i=strlen__(Other_Hdr[l+1],&k);
   else i=0; // Строка с символа 255 не учитывается
  }
  else {
   RightMargin (&(DB.Names[12*l]));
   i=_fstrlen (&(DB.Names[12*l])); // Длина без хвостовых пробелов
   _fmemcpy (&vv[l+1], &DB.Names[12*l], 11); // заголовок колонки
  }
  k=max (i,DB.Lens[l])+1;
  DBW.Line[l]= ( k + 1) <<3; // длина поля
  // Сформировать строки формата
  Fmt[l][0]='%';  Fmt[l][1]='-';
  itoa (k,Str,10);
  _fstrcat (Fmt[l],Str);
  _fstrcat (Fmt[l],"s");
 }

 // доинициализировать окно для вывода DBF-файла
 //неизменяемые элементы:
 DBW.itemsx=DB.Field; DBW.itemsy=DB.Zap; // Полей и записей
 DBW.Text_Func=Show_DB;
 DBW.Item_Func=Item_DB;
 DBW.DownStep = 4; //поле снизу
 DBW.LeftStep = 8;   //поле слева
 DBW.FieldY  = 12; //размер по Y
 if (DB.Cond&0x04) { // Другой заголовок
  DBW.Names_Tabl=Other_Hdr;
  DBW.titley=Max_Hdr_Line;
 }
 else {
  DBW.Names_Tabl=vv;
  DBW.titley=2;
 }
 DB.Cond&=0xFB; // по умолчанию - имена полей
 fsetpos (DB.fp,&(DB.Beg));

 // Обратиться к функции просмотра окна
 Sel_Ptr=0L;
 Window (&DBW,&FB);

 // Вызвать функцию завершения
 After_DBF_Function();
 FIELD_SAVER=NO; //!!!
 // Изменить заголовок и закрыть файл
 if (DB.Cond&0x01) {
  DB.Zap=DBW.itemsy;
  Change_Date (DB.fp);
 }
 fseek (DB.fp,0L,SEEK_END);
 fclose (DB.fp);

 // Освободить память окна
 farfree (DBW.Line); farfree (Fmt_ptr);  farfree (vv_ptr);
 farfree (Fmt_beg);  farfree (vv_beg);

 // Освободить структуру DBF-файла
 farfree (hptr); farfree (iptr);
// iptr=NULL; hptr=NULL; vv_beg=NULL; Fmt_beg=NULL;
// vv_ptr=NULL; Fmt_ptr=NULL; DBW.Line=NULL;
 What&=0xFD; // DBF-структура свободна
 return 0;
}

void Change_Date (FILE far *fp) {
 char Byte;
 fseek (fp,1L,SEEK_SET);
 fwrite (&Day,1,1,fp); // дата изменения
 fwrite (&Mon,1,1,fp);
 Byte=(unsigned char)(Year-1980);
 fwrite (&Byte,1,1,fp);
 fwrite (&(DB.Zap),4,1,fp); // число записей
 return;
}

///////////////////////////////////////////////////////////////////
char far *DateBuf="  -  -  ";
void Transform_Date (char far *From) {
 // Переводит дату из формата СУБД (ГГГГММДД) в формат ввода (ДД-ММ-ГГ)
 _fmemcpy (DateBuf,&From[6],2);
 _fmemcpy (&DateBuf[3],&From[4],2);
 _fmemcpy (&DateBuf[6],&From[2],2);
 return;
}

void Show_DB (int cx,int cy,int metx,long mety) { // Вывод элемента
 int i;
 if (metx==-1) {
  //Gprintf (cx, cy, "%5d",mety+1); // Номер записи
  DB.Beg=FilePosition (mety);
  fsetpos (DB.fp,&(DB.Beg));
  fread (DB.buffer,DB.ZapLen,1,DB.fp);
  DB.Beg+=DB.ZapLen;
  if (DB.buffer[0]==Del_Char) {  //Удалена!
   DB.Cond|=0x02; Gprintf (FB.sx-8,cy,"%c",Del_Char);
  }
  else  DB.Cond&=0xFD;
  POS_STR=FieldPosition(FB.metx);
 }
 else {
  if (DBW.EDIT[metx]) {
   // Имитируем конец строки и печатаем нужное поле
   i=POS_STR+DB.Lens[metx]; Push (&DB.buffer[i]);
   if (DB.Types[metx]==0x44) { // Дата обрабатывается отдельно
    Transform_Date (&(DB.buffer[POS_STR]));
    Gprintf (cx,cy,"%8s",DateBuf);
   }
   else Gprintf (cx,cy,(char far *)Fmt[metx],&(DB.buffer[POS_STR]));
   // Восстанавливеам байт в конце поля и увеличиваем счетчики
   Pop (&DB.buffer[i]);
  }
  POS_STR+=DB.Lens[metx];
 }
 return;
}


int isnumber(char far *str) {
 // Проверяет, является ли строка записью числа в одном из целых или
 // вещественных форматов. Возвращает 0 или 1
 char far *ptr=str;
 char Point=0x00,E=0x00;
 while (*ptr==' ' || *ptr=='\t') ptr++;
 if (*ptr=='\0') return 1; // Допускается строка из пробелов!
 if (*ptr=='-'||*ptr=='+') ptr++;
 for (;*ptr; ptr++) {
  if (!isdigit_(*ptr)) {
   switch (*ptr) {
    case '.':
     if (Point) return 0;
     else Point=0x01;
    break;
    case 'e':
    case 'E':
     if (E) return 0;
     else E=0x01;
    break;
    case '+':
    case '-':
     if (Point && E) break;
     else return 0;
    default: return 0;
   }
  }
 }
 return 1;
}

////// Часть для ввода строки
char Correct_Date (char* Str, KEY c, int pos) {
 // Проверка ввода даты ДД-ММ-ГГ
 switch (pos) {
  case 0: case 3:
   if (c==' ') *(Str+pos)='0';
   else if (!isdigit_(c)) return NO;
  break;
  case 6: case 7:
   if (!isdigit_(c)) return NO;
  break;
  case 1: case 4:
   if (!isdigit_(c)) return NO;
   Set_Key (1,RIGHT);
  break;
  case 2: case 5: if (c!='-') return NO;
  break;
  default: return NO;
 }
 return YES;
}

char Correct_Number (char *Str, KEY c, int pos) {
 if (isnumber(Str) && (isdigit_(c) ||  c=='-')) return 0x01;
 return 0x00;
}

char Correct_Ascii (char *Str, KEY c, int pos) {
 if (c>31 && c<255) return 0x01;
 return 0x00;
}

CORRECTFUN Correct_String;
MODE DELAFTER1=YES; // Уничтожать строку после 1 цифрового символа
char Get_String (int x1, int y1, char *Strin, int MaxLen,
 int LineColor, int BkColor) {
 int Curs_Pos=0,Len=0,i; char Cursor=0x00; KEY c;
 char *Cursors[2]={"_","▄"};
 KEY Bar_Keys[3]={ESC,ENTER,F2};
 int Pos_Keys[4]={15,103,205,309};
 char Num_Keys=3,Ret;
 Fun_Bar ("$ESC$ Отказ  $ENTER$ Ввести  $F2$ Записать");
 Len= strlen (Strin);
 if (Len>MaxLen) {
  Len=MaxLen;
  Strin[MaxLen]='\0';
 }
 if (DELAFTER1) Curs_Pos=0;
 else Curs_Pos=Len;
 setfillstyle (SOLID_FILL,BkColor);
 bar (x1,y1,x1+8*MaxLen+7,y1+9);
 do {
AGAIN:
  Strin[Len]='\0';
  setwritemode (COPY_PUT); setcolor (LineColor); outtextxy (x1,y1,Strin);
  setwritemode (XOR_PUT);  outtextxy (x1+Curs_Pos*8,y1,Cursors[Cursor]);
  setwritemode (COPY_PUT);
  if (Mouse) while (!Hit_Key()) {
   ms_state ();
   if (buttons==0x01) { //Left
    if (Fun_Bar_Keys (Num_Keys,Bar_Keys,Pos_Keys)) goto KEYBOARD;
    buttons=0x00; while (ms_release()<1); // до отпускания кнопки мыши
   }
  }
KEYBOARD:
  c=Get_Key ();
  setcolor (BkColor);  outtextxy (x1,y1,Strin);
  setwritemode (XOR_PUT);  outtextxy (x1+Curs_Pos*8,y1,Cursors[Cursor]);
  setwritemode (COPY_PUT);
  if (DELAFTER1) {
   DELAFTER1=NO;
   if (Correct_String (Strin,c,0)) {
    Strin[0]=c; Len=1; Curs_Pos=1;
   }
   else Set_Key (1,c);
   goto AGAIN;
  }
  switch (c) {
   case ESC:   Ret= 0x00; goto OUT;
   case F2:    Ret= 0x02; goto OUT;
   case ENTER: Ret= 0x01; goto OUT;
   case LEFT: if (Curs_Pos>0) Curs_Pos--; break;
   case RIGHT: if (Curs_Pos<Len) Curs_Pos++; break;
   case HOME: Curs_Pos=0; break;
   case END: Curs_Pos=Len; break;
   case INS: Cursor^=0x01; break;
   case DEL: if (Len > 0) {
    if (Curs_Pos>=0 && Curs_Pos<Len) {
     for( i = Curs_Pos; i < Len-1; i++ ) Strin[i] = Strin[i+1];
      Len--;
    }
   } break;
   case TAB: break;
   case BS: if (Len > 0) {
    if (Curs_Pos>0 && Curs_Pos<=Len) {
     for( i = Curs_Pos-1; i < Len-1; i++ ) Strin[i] = Strin[i+1];
      Len--; Curs_Pos--;
    }
   } break;
   default:
   if (Correct_String (Strin,c,Curs_Pos)) {
    if (Cursor) { //Замена
     if (Curs_Pos<=Len) {
      Strin[Curs_Pos]=c;
      if (Curs_Pos<MaxLen) Curs_Pos++;
      if (Curs_Pos>Len) if (Len<MaxLen) Len++;
     }
    }
    else if (Len<MaxLen) { // Вставка
     for (i=Len; i>Curs_Pos; i--) Strin[i]=Strin[i-1];
     Strin[Curs_Pos]=c;
     Len++;
     if (Curs_Pos<Len)Curs_Pos++;
    }
   }
   break;
  }
  Strin[Len]='\0';
 } while (1);
OUT:
 DELAFTER1=YES;
 return (Ret);
}

char STRING_RESULT,Last=NO; // Dop_Edit
//char DIRECT_FOUND=NO,FIELD_FOUND=NO;
void Item_DB(int cx,int cy,int metx,long mety) { // Обработка элемента
 char Byte; KEY Sim,c;
 static char COPIED;
 int Pos=1,k,j,bufpos; long K;
 CASE  text_1 = { 134,100,502,150, 0,12,0,"", "Вы хотите ФИЗИЧЕСКИ вставить запись?"};
 // прочитали текущую запись
 DB.Beg=(long)(DB.HeadLen+max(min(mety,DBW.itemsy-1),0)*DB.ZapLen);
 fsetpos (DB.fp,&(DB.Beg));
 fread (DB.buffer,DB.ZapLen,1,DB.fp);
 if (DB.buffer[0]=='*') DB.Cond|=0x02;
 else DB.Cond&=0xFD;
 fsetpos (DB.fp,&(DB.Beg));
 // если нажато ENTER - запомнить номер записи и выйти
 if (Start==End) {
  Sel_Ptr = DB.Beg;
  return;
 }
 Good_Sound ();
 do {
  Sim=Get_Key();
  switch (Sim) {
   case F3:
    Pos=FieldPosition (10); // Позиция в записи
    _fmemset (String,'\0',STRING_LEN);
    _fmemcpy (String,&DB.buffer[Pos], DB.Lens[10]); // Пишем из записи
    if (String[0]=='~') { //Уже есть имя
     bufpos=FieldPosition (1);
     _fmemset (Segment,'\0',DB.Lens[1]);
     _fmemcpy (Segment,&DB.buffer[bufpos], DB.Lens[1]); // Пишем название участка
     // Начало участка:
     _fmemset (Str1,'\0',16); _fmemset (Str2,'\0',16); _fmemset (Str3,'\0',16);
     bufpos=FieldPosition (3); _fmemcpy (Str1,&DB.buffer[bufpos], DB.Lens[3]);
     bufpos=FieldPosition (4); _fmemcpy (Str2,&DB.buffer[bufpos], DB.Lens[4]);
     bufpos=FieldPosition (5); _fmemcpy (Str3,&DB.buffer[bufpos], DB.Lens[5]);
     _fstrcat (Str1,"/"); _fstrcat (Str1,Str2);
     _fstrcat (Str1,"/"); _fstrcat (Str1,Str3);
     // Конец участка:
     _fmemset (Str2,'\0',16); _fmemset (Str3,'\0',16); _fmemset (Str4,'\0',16);
     bufpos=FieldPosition (6); _fmemcpy (Str2,&DB.buffer[bufpos], DB.Lens[6]);
     bufpos=FieldPosition (7); _fmemcpy (Str3,&DB.buffer[bufpos], DB.Lens[7]);
     bufpos=FieldPosition (8); _fmemcpy (Str4,&DB.buffer[bufpos], DB.Lens[8]);
     _fstrcat (Str2,"/"); _fstrcat (Str2,Str3);
     _fstrcat (Str2,"/"); _fstrcat (Str2,Str4);
     InfoFile (String);
     Thank|=0x02;
     _fmemcpy (&DB.buffer[Pos],InfoName,8);
     WriteCurrent();
    }
   return;
   case START: // Начать редактирование с 1 поля
    Thank|=0x02; // Перерисовать окно
    for (NowX=0; NowX<DBW.itemsx; NowX++) if (DBW.EDIT[NowX]) break;
    for (j=0; j<DBW.itemsx; j++) if (DBW.EDIT[j]==EDITS) {
     FB.metx=j;
     _fmemcpy (InString,DB.buffer,DB.ZapLen);
     COPIED=YES;
     Set_Insert_Key (2,PSEUDO,START);
     return;
    }
   break;
   case PSEUDO: // Начать редактирование с текущего поля
    if (!COPIED) {
     _fmemcpy (InString,DB.buffer,DB.ZapLen);
     COPIED=YES;
    }
AGAIN:
    k=FB.metx+FB.locx;
    if (k<DBW.itemsx) {
     if ((!DOP_EDIT) && DBW.EDIT[k]!=EDITS) goto NEXT;
     Pos=FieldPosition (k); // Позиция в записи
     _fmemset (String,'\0',STRING_LEN);
     if (Start!=End) { // Нажат символ на клавиатуре
      c=Get_Key();
      if (isdigit_(c) || isletter_(c) || c=='-') String[0]=c;
      else goto FIELD_COPY;
     }
     else {
FIELD_COPY:
      _fmemcpy (String,&DB.buffer[Pos], DB.Lens[k]); // Пишем из записи
      LeftMargin (String); RightMargin (String); // убрать пробелы
     }
     if (DB.Types[k]==0x43) //String
      Correct_String=Correct_Ascii;
     else if (DB.Types[k]==0x44) //Date
      Correct_String=Correct_Date;
     else Correct_String=Correct_Number;
     if (DOP_EDIT) Byte=Dop_Edit (String, k, FB.sy+FB.locy*FB.sizey);
     else Byte=YES;
     if (Byte) { // Нужен обычный ввод
      STRING_RESULT=Get_String (FB.sx+SUMX+4, FB.sy+FB.locy*FB.sizey+2, String,
		   DB.Lens[k], BLACK, LIGHTCYAN);
     }
     switch (STRING_RESULT) {
      case 0x00: //ESC
       Thank|=0x02; // Перерисовать окно
       Clear_Buf();
      goto ABORT;
      case 0x01: // ENTER
LAST_INPUT:
       Byte=Correct_Input (String,k); // проверка корректности ввода
       if (Byte==NO) { Mistake (10); goto AGAIN; } // Ошибка ввода
       else {
	if (DB.Types[k]==0x43) LeftSide (String,DB.Lens[k]);
	else if (DB.Types[k]!=0x44) RightSide (String,DB.Lens[k]);
	if (FIELD_SAVER) Field_Save (String,k,DB.Lens[k]);
	_fmemcpy (&DB.buffer[Pos],String,DB.Lens[k]); //Пишем обратно в буфер
	if (Last) goto FINISH;
	for (j=k+1; j<DBW.itemsx; j++) if (DOP_EDIT || DBW.EDIT[j]==EDITS) goto NEXT;
	goto FINISH;
NEXT:   WriteCurrent();
	Set_Key (3,RIGHT,START,PSEUDO);
	return;
       }
      case 0x02:
       Last=YES;
       goto LAST_INPUT;
FINISH:
       Last=NO; COPIED=NO;
       WriteCurrent();
      return; // Закончить
     }
    }
   break;
   case ESC:
ABORT:
    COPIED=NO;
    _fmemcpy (DB.buffer,InString,DB.ZapLen);
    WriteCurrent();
   return;
   case DEL:
    if (DB.Cond&0x02) DB.buffer[0]=' ';
    else DB.buffer[0]='*';
    WriteCurrent ();
   return;
   case INS:
    DBW.itemsy++; FB.locy=0; FB.YN++;
    if (DBW.FILTER) {
     DBFinsert (FB.YN-1);
     //if (FB.YN<
     //FB.mety=FB.YN-1;
    }
    else {
     DBFappend();
     //FB.mety=DBW.itemsy-1;
    }
    //if (FB.onpagey<maxpagey) (FB.onpagey)++;
    Set_Insert_Key (3,F4,F4,CTRL_DO);
   return;
   case F6:
    k=Answ_Menu( &text_1);
    if( !k ) {
     DBFinsert(mety);
     FB.YN++;  DBW.itemsy++;
     Set_Insert_Key (2,F4,F4);
    }
   return;
   case F7:
    if (EDITOR) {
     if (Search==NO) {
      _fmemset (String,'\0',STRING_LEN);
      Pos=FieldPosition (FB.metx+FB.locx); // Позиция в записи
      _fmemcpy (String,&(DB.buffer[Pos]),DB.Lens[FB.metx+FB.locx]);
      LeftMargin (String); RightMargin (String); // убрать пробелы
      Search=YES;
     }
     //_fmemcpy (&opr6.keys[40],&DB.Names[12*metx],12);
     Geting_Text (&opr6,tabl6,String);
    }
    else {
/*   if (DIRECT_FOUND) switch (DIRECT_FOUND) {
      case 0x02: //Вправо
       if (FIELD_FOUND>NowX) Set_Insert_Key (2,F7,RIGHT);
       else DIRECT_FOUND=0x00;
      return;
      case 0x01: //Влево
       if (FIELD_FOUND<NowX) Set_Insert_Key (2,F7,LEFT);
       else DIRECT_FOUND=0x00;
      return;
     } */
     if (Search==NO) {
      _fmemset (String,'\0',STRING_LEN);
      Search=YES;
     }
     Geting_Text (&opr6_,tabl6_,String);
/*   if (Search>0x01) { //В другом поле
      FIELD_FOUND=Search-0x02;
      Search=0x01;
      if (FIELD_FOUND>NowX) DIRECT_FOUND=0x02;
      else DIRECT_FOUND=0x01;
      Set_Insert_Key (1,F7);
     } */
    }
   return;
   case F8:
    K=DBFPack (FB.Y0,FB.YN);
    if (K!=-1) {
     DBW.itemsy-=K; FB.YN-=K;
     if (FB.onpagey > FB.YN-FB.Y0) FB.onpagey = FB.YN-FB.Y0;
     FB.mety=FB.Y0; FB.locy=0;
    }
   return;
   case F9:  DBFPrint (FB.Y0,FB.YN); return;
   case F10: PRNSet();    return;
   default:  Bad_Sound(); break;
  }
 } while (1);
}

long DBFPack (long Start, long End) {
 // Физически сжимает текущую БД
 CASE  text_ = { 134,100,502,150, 0,12,0,"","Вы хотите ФИЗИЧЕСКИ сжать файл?"},
       res_=   { 160,100,480,150, 0,12,0,"","Удалено записей:       "};
 fpos_t Read,Writ; long ii;
 FILE far *bk; char far *Tmpfile="             ";
 int k; long Ret=0;
 MODE Byte;
 k=Answ_Menu( &text_);
 if( !k ) {
  Good_Sound();
  Fun_Bar ("Идет сжатие файла базы данных...");
  tmpnam(Tmpfile);
  bk=fopen (Tmpfile,"wb");
  if (bk==NULL) {
   Mistake (6); return -1;
  }
  fseek (bk,0L,SEEK_SET);
  fseek (DB.fp,0L,SEEK_SET);
  for (ii=0; ii<DB.HeadLen; ii++) {
   fread (&Byte,1,1,DB.fp);
   fwrite (&Byte,1,1,bk);
  }
  for (ii=0; ii<Start; ii++) {
   fread (DB.buffer,DB.ZapLen,1,DB.fp);
   fwrite (DB.buffer,DB.ZapLen,1,bk);
  }
  Read=FilePosition (Start);
  Writ=FilePosition (Start);
  fsetpos (DB.fp,&Read);
  fsetpos (bk,&Writ);
  _fmemset (DB.buffer,' ',DB.ZapLen);
  DB.buffer[DB.ZapLen]='\0';
  Ret=0;
  for (ii=Start; ii<End; ii++) {
   fread (DB.buffer,DB.ZapLen,1,DB.fp);
   if (DB.buffer[0]!=Del_Char) {
    DB.buffer[0]=' ';
    fwrite (DB.buffer,DB.ZapLen,1,bk);
    Writ+=DB.ZapLen;   fsetpos (bk,&Writ);
   }
   else { // Удаляем запись - не пишем ее в новый файл
    Ret++;
    if (DOP_PACK) Dop_Pack (ii); // Доп. действия для фильтра
   }
   Read+=DB.ZapLen;  fsetpos (DB.fp,&Read);
  }
  for (ii=End; ii<DB.Zap; ii++) {
   fread (DB.buffer,DB.ZapLen,1,DB.fp);
   fwrite (DB.buffer,DB.ZapLen,1,bk);
  }
  fwrite (&End_Char,1,1,bk);  Writ++;  fsetpos (bk,&Writ); //EOF
  fclose (bk); fclose (DB.fp); unlink (DB.Name);
  rename (Tmpfile,DB.Name);
  DB.fp= Open_File (DB.Name,DB.fp);
  if (DB.fp==NULL) goto ENDS_;
  // Сообщение

  ltoa (Ret,Tmpfile,10);  _fmemcpy (&res_.help[16],Tmpfile, _fstrlen (Tmpfile));
  Message_Text (&res_);
  DB.Zap-=Ret;
 } ENDS_:
 DB.Cond|=0x01; return (Ret);
}

char Correct_Input (char far *String, int metx) {
// проверка корректности ввода
 char Byte=YES; int s;
 s=_fstrlen (String);
 if (s==0) return (YES);
 LeftMargin (String); RightMargin (String); // убрать пробелы
 switch (DB.Types[metx]) {
  case 0x43: //Строка
  break;
  case 0x44: //Дата
   if (s!=8) Byte=NO;
   if (!IsDate (String, DMYMINUS)) Byte=NO;
  break;
  case 0x4E: //Вещест.1
  case 0x46: // Вещест.2
   if (!isnumber(String)) Byte=NO;
  break;
  case 0x4C: //Бинарное
   if (s!=1 || Find_Key ("tTfFдДнН",String[0])==NO_SIM) Byte=NO;
  break;
  case 0x4D: if (atol(String)<=0) Byte=NO;
  break;
  default: Byte=NO;
 } return (Byte);
}

void LeftMargin (char far *String) { // убрать пробелы слева
 int i,k=0;
 while (String[k]==' ' || String[k]=='\t') k++;
 if (k) for (i=0; ; i++) {
  String[i]=String[i+k];
  if (String[i+k]=='\0') break;
 } return;
}

void RightMargin (char far *String) { // убрать пробелы справа
 int k=_fstrlen(String)-1;
 if (k>=0) while (String[k]==' ') {
  String[k]='\0'; k--; if (k<0) break;
 } return;
}

void LeftSide (char far *String, int Field) {
// Выровнять строку по левому краю в поле [Field]
 int i;
 LeftMargin(String);
 i=strlen (String);
 while (i<Field) { String[i]=' '; i++; } // ... дописать строку
 String[Field]='\0';
 return;
}

void RightSide (char far *String, int Field) {
// Выровнять строку по правому краю в поле [Field]
 int i,k,d;
 LeftMargin(String); RightMargin(String);
 i=strlen(String);
 if (i>Field) {
  d=i-Field;
  for (k=0; k<Field; k++) String[k]=String[d+k];
 }
 else if (i<Field) {
  d=Field-i;
  for (k=Field-1; k>=d; k--) String[k]=String[k-d];
  for (k=0; k<d; k++) String[k]=' ';
 }
 String[Field]='\0';
 return;
}

void WriteCurrent (void) {
 int k;
 k=fwrite (DB.buffer,DB.ZapLen,1,DB.fp);
 if (!k) Mistake (7);
 DB.Cond|=0x01;
 return;
}

void DBFappend (void) {
 long Pos;
/* DB.Zap++;
 fseek (DB.fp,-1L,SEEK_END);
 _fmemset (DB.buffer,' ',DB.ZapLen);
 DB.buffer[DB.ZapLen]='\0';
 WriteCurrent();
 fwrite (&End_Char,1,1,DB.fp);
 DB.Cond|=0x01;
 return; */
 Pos=FilePosition (DB.Zap);
 fseek (DB.fp,Pos,SEEK_SET);
 DB.Zap++;
 _fmemset (DB.buffer,' ',DB.ZapLen);
 WriteCurrent();
 fwrite (&End_Char,1,1,DB.fp);
 DB.Cond|=0x01;
 return;
}

long FilePosition (long Zap) {
 // Возвращает позицию в файле записи с номером Zap
 if (Zap>0) return ((long)(DB.HeadLen+Zap*DB.ZapLen));
 else return (DB.HeadLen);
}

void DBFinsert (long Start) {
 fpos_t Tmp,Pos0;
 Fun_Bar ("Идет модификация файла базы данных...");
 DBFappend();  // Добавить пустую
 Pos0=FilePosition (Start); // Запомнили начальную позицию записи
 Tmp=FilePosition (DB.Zap-2);
 fsetpos (DB.fp,&Tmp);
 do {
  if (Pos0 <= Tmp ) {
   fread (DB.buffer,DB.ZapLen,1,DB.fp);
   Tmp+=DB.ZapLen; fsetpos (DB.fp,&Tmp);
   WriteCurrent(); //пишем на запись вперед
   Tmp-=2*DB.ZapLen; fsetpos (DB.fp,&Tmp);
  }
  else {
   _fmemset (DB.buffer,' ',DB.ZapLen);
   fsetpos (DB.fp,&Pos0);
   WriteCurrent();
   fsetpos (DB.fp,&Pos0);
   break;
  }
 } while (1);
 return;
}

void PRNSet(void) {
 extern MENU opr9,opr10;
 extern CASE tabl9[],tabl10[];
 static char far *Ss="    ";
 int i,n;
IN:
 itoa (STRtoPAGE,Ss,10);
 Geting_Text (&opr9,tabl9,Ss);
 if (Thank&0x08) {
  n=atoi(Ss);
  if (n<20 || n>150) {
   Mistake (14); goto IN;
  }
  STRtoPAGE=n;
  for (i=0;i<4;i++) {
   if (Prn&(0x01<<i)) tabl10[i].zam=tabl10[i].color2=1;
   else tabl10[i].zam=tabl10[i].color2=0;
  }
  Case_Wnd (&opr10,tabl10);
  if (Thank&0x08) for (i=0; i<4; i++) {  // Был ввод-
   if (tabl10[i].zam) Prn|=(0x01<<i);    // меняем установки для принтера
   else Prn&=(~(0x01<<i));
  }
 }
 return;
}

void PrintMargin (void) {
 char *Margin="\xff\xff\xff\xff";
 if (Prn&0x04) fprintf (printer,"%4s",Margin);
 return;
}


void DBFPrint( long Start, long End ) {
 long ii,File_Pos;
 int  j,k,Str,Page=0;
 CASE Prn_Error={218,100,456,160,14,12,0,"","Принтер не найден!&Продолжить работу?"     },
  Prn_Stop={218,100,456,160,14,12,0,"","Вы действительно хотите&прервать печать?"},
  Load_Prn     ={194,100,461,170,14,12,0,"","Подготовьте принтер к работе и&нажмите клавишу $ENTER$&$ESC$ - отмена печати"},
  Sel_Pg       ={194,100,475,175,14,12,0,"","Когда принтер допечатает, смените&страницу и нажмите клавишу $ENTER$&или $ESC$ для отмены печати"},
  Prn_Ok       ={238,100,420,150,14,12,0,"","Печать завершена"};
  char far *Bar_="$ESC$ - Прервать печать";
AGAIN:
 Clear_Buf ();
 if ((printer = fopen( "prn", "wt" )) == NULL) {
  if( !Answ_Menu( &Prn_Error ) ) goto AGAIN;
  else return;
 }
 while (!Prn_Status()) {
  Message_Text( &Load_Prn );
  if (!(Thank&0x08)) return;
 }
 fprintf (printer,"\n");
 Str=1;
 COLtoPAGE=StartPrint (FIRST_PRINT, &k);      // Печать доп.информации
 Str+=k;
 Fun_Bar (Bar_);
 File_Pos=FilePosition (Start);
 for (ii=Start;ii<End;ii++) { // Печать записей
  k=Hit_Key();
  if (k) {
   k=Get_Key();
   if ( (k==ESC) && (!Answ_Menu(&Prn_Stop)) ) break;
   Fun_Bar (Bar_); k=0; Clear_Buf();
  }
  if (Str>=STRtoPAGE || Page==0) { // Новая страница
   Page++;
   if (Page>1) {
    fprintf (printer,"\n");
    StartPrint (END_PAGE, &Str);  // Обработка конца страницы
    // fprintf (printer,"\f");
    Str=0;
    Message_Text( &Sel_Pg ); //Предложение сменить лист
    Fun_Bar (Bar_);
    if (!(Thank&0x08)) goto PRN_OUT; // Отказ от печати
    if (Prn&0x02) {  // номер страницы?
     k=(COLtoPAGE>>1)-2;
     fprintf (printer,"\n"); PrintMargin();
     for (j=0;j<k;j++) fprintf (printer," ");
     fprintf (printer,"-%u-",Page);
     Str++;
    }
   }
   if (Prn&0x08) { // имя файла?
    k=(COLtoPAGE-strlen (DB.Name))>>1;
    fprintf (printer,"\n"); PrintMargin();
    for (j=0;j<k;j++) fprintf (printer," ");
    fprintf (printer,"%s",DB.Name);
    Str++;
   }
   if (Prn&0x01 || Page==1) { // Печать заголовка
    fprintf (printer,"\n");
    StartPrint (HEADER_PRINT, &k);      // Печать заголовка
    Str+=k;
   }
  }
  fsetpos (DB.fp,&File_Pos);
  fread (String,DB.ZapLen,1,DB.fp); // Прочитали запись в строку String
  fprintf (printer,"\n");
  if (Prn&0x04) {  // Номер записи
   fprintf(printer,"%4d",ii-Start+1);
  }
  j=StartPrint (ii, &k);
  if (j==0 && Answ_Menu(&Prn_Error)) goto PRN_OUT;
  Str+=k;
  fgetpos (DB.fp,&File_Pos);
 }
 fprintf (printer,"\n");
 StartPrint (END_PAGE, &Str);  // Обработка конца страницы
 Message_Text( &Prn_Ok );
PRN_OUT:
 fclose (printer); return;
}

//void NoPrint (char far *s,int far *l,int a) {}

int Prn_Status(void) { // Готовность принтера
 union REGS regs;
 regs.x.dx=0;   // Type of printer - 0,1,2
 regs.h.ah=0x02; // BIOS function for printer status
 int86 (0x17,&regs,&regs);
 if ( (regs.h.ah ==0x90) || (regs.h.ah ==0x10) ) return 1;
 return 0;
}

char far *segcpy__ (char far *seg,char far *s,int segnum) {
 // Копирует сегмент строки под номером segnum (разделитель '&')
 // Возвращает указатель на сегмент.Сегменты нумеруются с 0.
 char far *ptr=seg; int i=0,j=0;
 while (j<segnum) {
  if (*(s+i)=='\0') break;
  else if (*(s+i)=='&') j++;
  i++;
 }
 j=i;
 while (*(s+i)!='&' && *(s+i)!='\0') { *(seg+i-j)=*(s+i); i++; }
 *(seg+i-j)='\0';
 return (ptr);
}

int my2asc__ (char far *str) {
 // Строку со служебными '&','$' переводит в ascii-строку;
 // '&' заменяет на '\n', '$' игнорирует
 // Возвращает длину ascii-строки
 char far *ptr=str; int i=0,s=strlen (str),j;
 while (i<s) {
  if (*(ptr+i)=='\0') break;
  switch (*(ptr+i)) {
   case '&': *(ptr+i)='\n'; continue;
   case '$':
    for (j=i; ; j++) {
     *(ptr+j)=*(ptr+j+1);
     if (*(ptr+j)=='\0') break;
    }
   continue;
   default: break;
  }
  i++;
 };
 j=strlen (str);
 if (*(ptr+j-1)=='\n') { *(ptr+j-1)='\0'; j--; }
 return (j);
}

void All_Search (void) {
 int i,j,k,Pos=1,Cur,Count,Len; fpos_t Fpos,OldPos;
 LeftMargin (String); RightMargin (String);
 Len=strlen (String); // Длина искомой строки
 fgetpos (DB.fp, &OldPos);
 if (FB.mety+FB.locy < FB.YN-1) { // Не последняя запись
  Count=FB.mety+FB.locy+1; // Стартовая запись
  Fpos=FilePosition(Count); // ее позиция в файле
  fsetpos (DB.fp,&Fpos);
  for (i=Count; i<FB.YN; i++) {
   fread (DB.buffer,DB.ZapLen,1,DB.fp);
   DB.Beg+=DB.ZapLen;
   Count++;
   // Проверяем все поля записи
   for (k=0; k<DB.Field; k++) if (DBW.EDIT[k]) { // Ищем по видимым полям
    Pos=FieldPosition (k); //Позиция поля k в записи файла
    Cur=DB.Lens[k]; // Длина поля k
    Push (&DB.buffer[Pos+Cur]);
    LeftMargin (&(DB.buffer[Pos]));
    j=_fstrnicmp( &(DB.buffer[Pos]),&(String[0]),Len);
    Pop (&DB.buffer[Pos+Cur]);
    if (j==0) { //Found
     if ( DBW.itemsy <= FB.onpagey) { FB.mety=0; FB.locy = Count-1; }
     else { FB.mety=Count-1; FB.locy=0; }
     Pos=0; goto OUT;
    }
   }
  }
 }
OUT:
 if (DB.buffer[0]==End_Char) DB.buffer[0]=' '; // if EOF
 if (Pos) { // Not found
  Mistake (15); Search=NO;
  fsetpos (DB.fp, &OldPos);
  fread (DB.buffer, DB.ZapLen, 1, DB.fp);
  fsetpos (DB.fp, &OldPos);
 }
 else {
  Search=YES; Set_Key (1,ESC);
  // if (NowX!=i) Search=0x02+i;
 }
 return;
}

void Key_Search (void) {
 int i,j,Pos=1,Cur,Count,Len; fpos_t Fpos,OldPos;
 Pos=FieldPosition (NowX); //Позиция в записи файла
 Cur=DB.Lens[NowX]; // Длина поля
 LeftMargin (String); RightMargin (String);
 Len=strlen (String); // Длина искомой строки
 fgetpos (DB.fp, &OldPos);
 if (FB.mety+FB.locy < FB.YN-1) { // Не последняя запись
  Count=FB.mety+FB.locy+1; // Стартовая запись
  Fpos=FilePosition(Count); // ее позиция в файле
  fsetpos (DB.fp,&Fpos);
  for (i=Count; i<FB.YN; i++) {
   fread (DB.buffer,DB.ZapLen,1,DB.fp);
   DB.Beg+=DB.ZapLen; Count++;
   // Имитируем конец строки и проверяем нужное поле
   DB.buffer[Pos+Cur]='\0';
   LeftMargin (&(DB.buffer[Pos]));
   j=_fstrnicmp( &(DB.buffer[Pos]),&(String[0]),Len);
   if (j==0) { //Found
    if ( DBW.itemsy <= FB.onpagey) { FB.mety=0; FB.locy = Count-1; }
    else { FB.mety=Count-1; FB.locy=0; }
    Pos=0; break;
   }
  }
 }
 if (DB.buffer[0]==End_Char) DB.buffer[0]=' '; // if EOF
 if (Pos) { // Not found
  Mistake (13); Search=NO;
  fsetpos (DB.fp, &OldPos);
  fread (DB.buffer, DB.ZapLen, 1, DB.fp);
  fsetpos (DB.fp, &OldPos);
 }
 else { Search=YES; Set_Key (1,ESC); }
 return;
}

void DBFWrite (long Zap,long How,int Field,int Many,char Flag) {
 // Flag==0x01 - пишем
 //       0x00 - читаем
 // Zap,Field - номера стартовой записи и поля (с нуля)
 // How - число записей, Many - число полей, которые пишем|читаем
 // в|из откр. БД
 int i,Pos=1,Len=0,Izm=0,k;
 long ii,Beg,Tmp,jj;
 char Byte;

 for (i=0; i<Field; i++) Pos+=DB.Lens[i]; // Position in record
 // for (i=Field; i<Field+Many; i++) Len+=DB.Lens[i];
 Beg=FilePosition(Zap); // Start record position in the file
 ii=Zap;
 jj=ii+How;
 fgetpos (DB.fp,&Tmp);
 for (;ii<jj;ii++) {
  fsetpos (DB.fp,&Beg);
  if (ii<DB.Zap) {
   fread (DB.buffer,DB.ZapLen,1,DB.fp);
   for (i=0;i<DB.ZapLen;i++) if (DB.buffer[i]=='\0') DB.buffer[i]=' ';
   DB.buffer[DB.ZapLen]='\0';
  }
  else {
   DBW.itemsy++;   //!!!
   DB.Zap++; Izm=1;
   for (i=0;i<DB.ZapLen;i++) DB.buffer[i]=' ';
   DB.buffer[DB.ZapLen]='\0';
  } //прочитали запись; если добавляем новую - очистили буфер
  Len=0;
  for (i=Field; i<Field+Many; i++) {
   k=Pos+Len+DB.Lens[i];
   Byte=DB.buffer[k]; DB.buffer[k]='\0';
   Write_Field (&(DB.buffer[Pos+Len]),DB.Lens[i],i,ii);
    // обратились к функции записи|чтения полей в|из строки
   DB.buffer[k]=Byte;
   Len+=DB.Lens[i];
  }
  if (Flag&0x01) {
   fsetpos (DB.fp,&Beg);
   fwrite (DB.buffer,DB.ZapLen,1,DB.fp);
  }
  Beg+=DB.ZapLen;
 }
 if (Izm) fwrite (&End_Char,1,1,DB.fp);
 if (Flag) DB.Cond|=0x01;
 fsetpos (DB.fp,&Tmp);
 return;
}

void DBFSort (long Start, long End) {
 // Сортирует открытую БД. Ф-я сравнения записей - DBFCompare
 // Фильтруются записи с номерами Start, ..., End-1
 long ii,jj,All,Done,Beg,Fin;  //int duphandle;
 if (DB.Zap<2 || End-Start<2) return;
 // Сбрасываем буферы на диск
 // fflush(DB.fp);
 // duphandle = dup(fileno(DB.fp));
 // close(duphandle);

 All=((End-Start)*(End-Start))>>1; // Всего возможных перестановок
 Done=0; //Сделано в %
 Fun_Bar ("Идет сортировка базы данных: ");
 SortMess (0);
 for (ii=Start,Beg=FilePosition(Start); ii<End-1; ii++) {
  fsetpos (DB.fp,&Beg);
  fread (DB.buffer,DB.ZapLen,1,DB.fp);
  Fin=Beg+DB.ZapLen;
  for (jj=ii+1; jj<End; jj++) {
   fsetpos (DB.fp,&Fin);
   fread (String,DB.ZapLen,1,DB.fp);
   if (DBFCompare (DB.buffer,String)) { // Меняем местами записи
    fsetpos (DB.fp,&Beg);
    fwrite (String,DB.ZapLen,1,DB.fp);
    fsetpos (DB.fp,&Fin);
    fwrite (DB.buffer,DB.ZapLen,1,DB.fp);
    _fmemcpy (DB.buffer, String, DB.ZapLen); // Новая строка - в буфере
   }
   Fin+=DB.ZapLen; Done++;
  }
  SortMess (Done*100/All);
  Beg+=DB.ZapLen;
 }
 SortMess (100); return;
}

void SortMess (long Cent) {
 static char far *Buf="     ";
 CURSOR_OFF(); setcolor (WHITE);
 outtextxy (255,MAXY-10,Buf);
 sprintf (Buf,"%3d%%",(int)Cent);
 setcolor (LIGHTBLUE);
 outtextxy (255,MAXY-10,Buf);
 CURSOR_ON();  return;
}

static char StackByte;
void Push (char far *Ptr) { StackByte=*Ptr; *Ptr='\0'; return; }
void Pop (char far *Ptr) { *Ptr=StackByte; return; }

int FieldPosition (int FieldNum) {
 // Позиция поля FieldNum [0,1,...] в записи открытой БД
 int i,Ret=1;
 for (i=0; i<FieldNum; i++) Ret+=DB.Lens[i];
 return (Ret);
}

void DBF_Zap (int Zap) {
 // Размер открытой базы данных делает Zap записей,
 // при необходимости дописывая или урезая
 fpos_t Read; long ii; FILE far *bk; char Byte1;
 char far *Tmpfile="             ";
 if (Go_Work()) return;
 if (DB.Zap>Zap) {  // Урезаем файл
  tmpnam(Tmpfile);
  bk=fopen (Tmpfile,"wb");
  if (bk==NULL) { Mistake (6); return; }
  fseek (bk,0L,SEEK_SET);  fseek (DB.fp,0L,SEEK_SET);
  for (ii=0;ii<DB.HeadLen;ii++) {
   fread (&Byte1,1,1,DB.fp);  fwrite (&Byte1,1,1,bk); }
  Read=DB.HeadLen; fsetpos (DB.fp,&Read); fsetpos (bk,&Read);
  for (ii=0; ii<Zap; ii++) {
   fread (DB.buffer,DB.ZapLen,1,DB.fp);
   fwrite (DB.buffer,DB.ZapLen,1,bk);
   Read+=DB.ZapLen; fsetpos (bk,&Read);
  }
  fwrite (&End_Char,1,1,bk); Read++;
  DB.Zap=Zap;   Change_Date (bk);
  fsetpos (bk,&Read); //EOF
  fclose (bk); fclose (DB.fp); unlink (DB.Name);
  rename (Tmpfile,DB.Name);
  //DB.fp=fopen (DB.Name,"r+b");
  DB.fp=Open_File (DB.Name,DB.fp);
  if (DB.fp==NULL) return;
 }
 else if (DB.Zap<Zap) {  // Дописываем файл пустыми записями
  Read=FilePosition(DB.Zap);  fsetpos (DB.fp,&Read);
  _fmemset (DB.buffer,' ',DB.ZapLen);
  DB.buffer[DB.ZapLen]='\0';
  for (ii=DB.Zap; ii<Zap; ii++) {
   WriteCurrent ();
   Read+=DB.ZapLen; fsetpos (DB.fp,&Read);
  }
  fwrite (&End_Char,1,1,DB.fp);
  DB.Zap=Zap;   Change_Date (DB.fp);
 } return;
}

////////////////////////////////////////////////////////////
#define FORMAT_LEN 65
char far *Format= //65
 "                                                                  ";

int DBF_End (void) {
 // Готовит строку формата и считывает текущую запись перед закрытием
 if (Sel_Ptr) { // Запись выбрана
  fsetpos (DB.fp,&Sel_Ptr);
  _fmemset (String,'\0',STRING_LEN);
  fread (String,DB.ZapLen,1,DB.fp);
  Do_Format ();
  return 1;
 }
 return 0;
}

void Do_Format (void) {
 // Создает строку формата для чтения записи открытого файла DBF
 // Запись - в строке String, формат - в строку Format
 int Pos,s,k,StrPos=1,J,L; char Sym1,Sym2;
 char far *Number="       ",far *Ptr;
 _fmemset (Format,'\0',FORMAT_LEN);
 Format[0]='%'; Format[1]='c'; Pos=2;
 for (k=0; k<DB.Field; k++) { // Число полей
  Format[Pos++]='%';
  itoa (DB.Lens[k], Number, 10);
  s=strlen (Number);
  switch (DB.Types[k]) {
   case 0x43: // String
    _fmemcpy (&Format[Pos], Number, s);
    Pos+=s;
    Format[Pos++]='s';
   break;
   case 0x44: //Date
    _fmemcpy (&Format[Pos], "8s", 2);
    Pos+=2;
   break;
   case 0x4d: //Memo
    _fmemcpy (&Format[Pos], "10ul", 4);
    Pos+=4;
   break;
   case 0x4e: // Real 1
   case 0x46: // Real 2
    if (DB.Types[k]==0x4e) { Sym1='d'; Sym2='f'; }
    else { Sym1='l'; Sym2='g'; }
    _fmemcpy (&Format[Pos], Number, s);
    Pos+=s;
    if (DB.Decs[k]==0) {
     Format[Pos++]=Sym1;
    }
    else {
     Format[Pos++]='.';
     itoa (DB.Decs[k], Number, 10);
     s=strlen (Number);
     _fmemcpy (&Format[Pos], Number, s);
     Pos+=s;
     Format[Pos++]=Sym2;
    }
   break;
   case 0x4C: //Binary
    Format[Pos++]='c';
   break;
  }
  // Обработка строки для разбора ее ф-ей sscanf
  if (!(DB.Types[k]==0x43 || DB.Types[k]==0x44 || DB.Types[k]==0x4C)) {
   // Корректное число, выровненное по правому краю - в String
   Ptr=&(String[StrPos+DB.Lens[k]]);
   Sym1=*Ptr; *Ptr='\0';
   FillWith0 (&(String[StrPos]));
   *Ptr=Sym1;
  }
  else { // Замена пробелов "жесткими" пробелами
   J=FieldPosition(k); //!!!
   for (L=J; L<J+DB.Lens[k]; L++) if (String[L]==' ') String[L]=0xff;
  }
  StrPos+=DB.Lens[k];
 } Format[Pos]='\0'; return;
}

void FillWith0 (char far *String) {
 // Дополняет строковую запись числа слева незначащими нулями
 int j,i=0;
 RightSide (String,_fstrlen(String));
 while (*(String+i)==' ') i++;
 if (i) {
  if (*(String+i)=='-') { *String='-'; i++; }
  else *String='0';
  for (j=1; j<i; j++) *(String+j)='0';
 }
 return;
}

/////////////////////// База "Направления"
extern int Tmax,Tmin;
char far *Direction="                                    "; //36
char DirBase[4]={EDITS,EDITS,EDITS,EDITS};
extern int DirectPos;
char DOP_FILE=NO;
char DelMark=' ';
int DirCod=0;

void Test_1_Dir (void) {
 if (DBW.itemsy==0) {
  DBFappend();
  DBW.itemsy=1;
 }
}

void Set_Direction (void) {
 char far *Per0[]={" ","  Код на-&правления"," Название",
  "Мин.&темп.","Макс.&темп."};
 char *Names[4]={"COD","NAME","TMIN","TMAX"};
 char **NamesPtr=&Names[0];
 char Types[4]={'N','C','N','N'};
 char Lens[4]={2,36,3,2};
 char Decs[4]={0,0,0,0};
 // Окно вывода DBF-файла (изменяемые элементы)
 DBW.x1=12; DBW.x2= 627;
 DBW.y1=20; DBW.y2=294;
 DBW.SAVE=NO; DBW.COLORS=YES; DBW.MODIFY=YES;
 DBW.PRINT=YES; DBW.SEARCH=YES; DBW.FILTER=NO;
 DBW.EDIT=DirBase; DBW.UpStep=0; DOP_FILE=NO;
 DBW.Init_Func=Test_1_Dir;
 FB.Y1=DirectPos; //  последний выбор
 After_DBF_Function=Stan_End;
 DB.Cond|=0x04; Other_Hdr=Per0; Max_Hdr_Line=2;
 WinName=(char far *)"Направления";
 StartPrint=Direct_Print;
AGAIN:
 if (!DBF_Init(DIRECTIONS_FILE)) { // Вызвать функцию обработки
  if (Thank&0x08) { // Подтверждение
   Set_Key (1,START);
   Ext_Function=Sel_From_Catalog;
  }
 }
 else if (DBF_Create (DIRECTIONS_FILE, 0x04, NamesPtr,
  &Types[0], &Lens[0], &Decs[0])) goto AGAIN;
 Clr_Scr();
 return;
}

void Stan_End (void) {
 if (DBF_End()) {  // Record in 'String'
  sscanf (String,Format,&DelMark, &DirCod,&Direction[0],&Tmin,&Tmax);
  DirectPos=FB.mety+FB.locy;
 }
 return;
}

/////////////////////// База "Каталог"
int Catalog_Sort (char far *Str1, char far *Str2);
char Cat_Input (char far *String, int Field, int PosY);
//     Cat_Show (char far *String, int Field, int PosY);
//void Cat_Edit_Prepare (void); void Cat_Show_Prepare (void);
//void Get_Data (char far *Str, short *Curs, KEY *Sim);
// void Info_End (void);
char Info_Input (char far *String, int Field, int PosY),
     Info_Save (char far *String, int Field, int FieldLen);
extern int CatalogPos; extern unsigned Zapusk;



char far *IzmDate="        ", //8
     far *IzmName="        "; //8

int Way=0, StartKm=0, StartPk=0, StartSt=0;
int    EndKm, EndPk, EndSt,
    NodType,PchType,  RailType, ShpalaType, EpuraType, MinRad;

char CatBase[17]={NO, EDITS,EDITS, EDITS,EDITS,EDITS, EDITS,EDITS,EDITS,
 //EDITS,SHOWS, EDITS,EDITS, SHOWS,SHOWS,SHOWS,SHOWS };
 EDITS,EDITS, EDITS,EDITS, EDITS,EDITS,EDITS,EDITS };
MODE Global_Sort=NO; // Признак сортировки всего файла БД
MODE CatalogPoint=NO; // Показать/ Редактировать каталог
float Tmp_All; // Средняя темпрература
#define ZAPUSK_SORT 9999
 //!!!
 // Число запусков программы, через которое обновляются имена файлов


void Zazor_Result (int Tiz, int Tpr, int Ziz, int *Zpr) {
 *Zpr=Ziz-(int)(0.295*(Tpr-Tiz));
 if (*Zpr<0) *Zpr=0;
}

void Init_Zazor (char *Str, int Len, int Fil, long Num) {
 static int Tiz,Tpr,Left,Right;
 char *StrBuf="          ",*Fmt="%-      ";
 int i;
 switch (Fil) {
  case 3: Tiz=atoi(Str); return;   // Измеренная темп. рельса
  case 4: i=Tpr=(int)Tmp_All; break;  // Приведенная=Средняя
  case 5: Left=atoi(Str);  return; // Левый изм. зазор
  case 6: Zazor_Result (Tiz,Tpr,Left,&i); break; // Левый приведенный зазор
  case 7: Right=atoi(Str); return; // Правый изм. зазор
  case 8: Zazor_Result (Tiz,Tpr,Right,&i); break; // Правый приведенный зазор
  default: return;
 }
 itoa (i,StrBuf,10);
 sprintf (&Fmt[2],"%d",Len);
 strcat (Fmt,"s");
 if (strlen(StrBuf)>Len) StrBuf[Len]='\0';
 sprintf (Str,Fmt,StrBuf);
 return;
}

char Cat_Date_Save (char far *String, int Field, int FieldLen) {
 int d,m,y;
 if (Field==9) { // Дата
  sscanf (String,"%02d-%02d-%02d",&d,&m,&y);
  if (y>79 && y<=99) y+=1900;
  else y+=2000;
  sprintf (String,"%04d%02d%02d",y,m,d);
 }
 return YES;
}


float Temp_Result (void) {
 float S=0.,Tiz;
 long i, Pos, n;
 int Step,End;
 char far *Ptr;
 n=DB.Zap;
 for (i=0; i<n; i++) {
  Pos=FilePosition (i);
  Step=FieldPosition (3); //Поле измер. температуры
  End=FieldPosition (4);
  fsetpos (DB.fp, &Pos);
  fread (DB.buffer, DB.ZapLen, 1, DB.fp);
  Ptr=&DB.buffer[End];
  Push (Ptr);
  Tiz=atoi (&DB.buffer[Step]);
  Pop (Ptr);
  S+=Tiz;
 }
 return (S/n);
}



void Sel_From_Catalog (void) {
 char far *CatField[]={" ","Код"," Название",
 "Пу&ть", "\xFF$Начало$&Км", "&Пк", "&Стык", "\xFF$Конец$&Км",
 "&Пк", "&Стык", "Дата&промера", "Имя&файла",
 "НОД", "ПЧ", "Тип&рельса", "Вид&шпал", "Эпюра&шпал",
 "Мин.&радиус" };
 //static MODE poit;
 HELP ZazorMes={ 140,80,470,120,"Идет расчет:",
 "Приведенные температуры и зазоры в файл&              "};
 char *Names[17]={"COD","NAME","TRACK","START_KM","START_PK",
		  "START_ST","END_KM","END_PK","END_ST","DATE",
		  "FILENAME","NOD","PCH","RAIL","SHPALA",
		  "EPURA","MIN_RAD"};
 char **NamesPtr=&Names[0];
 char Types[17]={'N','C','N','N','N',
		 'N','N','N','N','D',
		 'C','N','N','N','N',
		 'N','N'};
 char Lens[17]={2,20,3, 4,2,2, 4,2,2, 8,8, 2,2,2,2,4,4};
 char Decs[17]={0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0};
 // Окно вывода DBF-файла
 DBW.x1=12; DBW.x2= 627;
 DBW.y1=20; DBW.y2=294;
 DBW.SAVE=NO; DBW.COLORS=YES;
 DB.Cond|=0x04; Other_Hdr=CatField; Max_Hdr_Line=2; // Заголовки
 DBW.FILTER=YES; DBW.SEARCH=YES;  DBW.PRINT=YES;
 DBW.Init_Func= Catalog_Filter; // Отфильтровать БД

 CatalogPoint=YES;  DBW.UpStep=0;
 DBW.EDIT=CatBase; DBW.MODIFY=YES;
 DOP_EDIT=YES;
 Dop_Edit=Cat_Input;
 DOP_PACK=YES; DOP_FILE=YES;
 Dop_Pack=Cat_Pack;
 After_DBF_Function=Cat_End;
 FIELD_SAVER=YES; Field_Save=Cat_Date_Save;
 WinName=(char far *)"Участки";
 StartPrint=Catalog_Print;
AGAIN:
 if (!DBF_Init(CATALOG_FILE)) { // Вызвать функцию обработки
  if (Thank&0x08 && (!(DOP_EDIT==NO && FB.Y0==FB.YN)) ) {
   // Подтверждение при наличии хотя бы 1 записи
   Write_Field=Init_Zazor; // Рассчитать приведенные зазоры и тем-ру
   _fstrcpy (InfoName,IzmName);
   _fstrcat (InfoName,".dbf");
   DB.Cond|=0x08; // Только инициализация!
   WinName=(char far *)"Измеренные зазоры";
   if (!DBF_Init (InfoName)) {
    _fstrcpy(&ZazorMes.text[40],InfoName);
    Help_Text(&ZazorMes);
    Tmp_All=Temp_Result(); // Рассчитать среднюю температуру
    DBFWrite (0,DB.Zap,3,6,0x01);
    Set_Key (1,START);
    Ext_Function=Tf_Td_count;
    // !!!
   }
  }
  else { // Возврат к выбору режима
   Set_Key (1,START);
   Ext_Function=Set_Direction;
  }
  DOP_EDIT=NO; DOP_PACK=NO;
 }
 else if (DBF_Create (CATALOG_FILE, 17, NamesPtr,
  &Types[0], &Lens[0], &Decs[0])) goto AGAIN;
 return;
}

int Cat_Pack (long Num) {
 long Pos; int Ret;
 Pos=FieldPosition (10);
 _fmemcpy (String,&DB.buffer[Pos],8);
 _fstrcat (String,".dbf");
 Ret=unlink (String);
 return (Ret);
}

void Cat_End (void) {
 long ii,Pos; int i,InPos; char far *Ptr;
 if (DBF_End()) {  // Record in 'String'
  sscanf (String,Format,&DelMark, &i,Segment, &Way, // DirCod уже есть из БД "Направления"
   &StartKm, &StartPk, &StartSt, &EndKm, &EndPk, &EndSt,
   IzmDate, IzmName, &NodType, &PchType, &RailType,
   &ShpalaType, &EpuraType, &MinRad);
  CatalogPos=FB.mety+FB.locy; // Запомнить позицию
  // Для Main продублировать некоторые данные:
  Rails_=RailType;
  Shpala_=ShpalaType;
  Epura_=EpuraType;
  for (i=0; i<8; i++) if (MinRad==Radius0[i]) break;
  Radius_=i;
 }
 DOP_EDIT=NO;
 if (DB.Cond&0x01) { // Был ввод
  Pos=FilePosition(FB.Y0);
  for (ii=FB.Y0; ii<FB.YN; ii++) {
   // Все записи участка сделать подходящими под фильтр
   fsetpos (DB.fp, &Pos);
   fread (DB.buffer, DB.ZapLen, 1, DB.fp);
   InPos=FieldPosition (1); // Конец 1 поля
   Ptr=&DB.buffer[InPos];
   Push (Ptr);  i=atoi (&DB.buffer[1]); Pop(Ptr);
   if (i!=DirCod) {
    sprintf (String,"%2d",DirCod);
    _fmemcpy (&DB.buffer[1],String,2);
    fsetpos (DB.fp, &Pos);
    WriteCurrent();
   }
   Pos+=DB.ZapLen;
  }
  DBFCompare=Catalog_Sort;
  if (Global_Sort) DBFSort(0,DB.Zap);  // Был новый участок - сортируем все
  else DBFSort(FB.Y0,FB.YN); // Упорядочить участок после ввода
  Zapusk++;
  if (Zapusk== ZAPUSK_SORT) {  // Обновить информацию о файлах
   Zapusk=0;
   ReFile();
  }
 }
 return;
}

void Catalog_Filter (void) {
 int i; char In=NO; long Num=0;
 fseek (DB.fp, DB.HeadLen, SEEK_SET);
 FB.Y0=0; FB.Y1=0;
 while (1) {
  fread (String, DB.ZapLen, 1, DB.fp);
  if (feof (DB.fp)) break;
  String[1+DB.Lens[0]]='\0';
  i=atoi (&String[1]);
  if (DirCod==i) {
   if (!In) { In=YES; FB.Y0=Num; }
  }
  else if (In) break;
  Num++;
 }
 if (In) {
  FB.Y1=CatalogPos; FB.YN=Num;
  Global_Sort=NO;
 }
 else if (DOP_EDIT) {
  DBFappend ();// Добавить запись, если нет ни одной для участка
  Global_Sort=YES; // В этом случае сортируем всю базу
  FB.Y1=FB.Y0=DB.Zap-1; FB.YN=FB.Y0+1; DBW.itemsy++;
  Set_Key (1,S_BAR); // Войти в редактор - для записи кода направления
 }
 else { FB.Y0=FB.Y1=FB.YN=DB.Zap; }
 return;
}

int Catalog_Sort (char far *Str1, char far *Str2) {
 char far *Ptr1, far *Ptr2;
 int Ret,Pos,Pos0,n1,n2;
 Pos=FieldPosition (1); // Позиция следующего поля
 Ptr1=&(Str1[Pos]); Push (Ptr1); n1=atoi (&Str1[1]); Pop (Ptr1);
 Ptr2=&(Str2[Pos]); Push (Ptr2); n2=atoi (&Str2[1]); Pop (Ptr2);
 if (n1<n2) Ret=0;      // Код направления
 else if (n1>n2) Ret=1;
 else {
  Pos0=FieldPosition (2); Pos=FieldPosition (3);
  Ptr1=&(Str1[Pos]); Push (Ptr1); n1=atoi (&Str1[Pos0]); Pop (Ptr1);
  Ptr2=&(Str2[Pos]); Push (Ptr2); n2=atoi (&Str2[Pos0]); Pop (Ptr2);
  if (n1<n2) Ret=0;     // Номер пути
  else if (n1>n2) Ret=1;
  else {
   Pos0=Pos; Pos=FieldPosition (4);
   Ptr1=&(Str1[Pos]); Push (Ptr1); n1=atoi (&Str1[Pos0]); Pop (Ptr1);
   Ptr2=&(Str2[Pos]); Push (Ptr2); n2=atoi (&Str2[Pos0]); Pop (Ptr2);
   if (n1<=n2) Ret=0;   // Километр начала
   else Ret=1;
  }
 } return (Ret);
}

/*char Cat_Show (char far *String, int Field, int PosY) {
 switch (Field) {
  case 10: //Имя файла
   if (String[0]=='~') { //Уже есть имя
    InfoFile (String);
    _fmemcpy (String,InfoName,8);
    Set_Key (1,ESC);
    Thank|=0x02; // Перерисовать окно вызывающей программы
   }
  break;
  default: break;
 }
 return NO;
} */

char Cat_Input (char far *String, int Field, int PosY) {
 // YES, если нужно редактировать поле станд. ф-ей, иначе NO
 extern  DOPINPUTFUN DOP_INPUT; // Дополнительный контроль ввода для Geting_Text

 extern char far *Rails0[], far *Shpala0[], far *Epura0[];

 MODE i,Ret=NO; int j,k,l;
 VID  opr1 = { 280, 11, 360, 55, 0x12, "Рельсы:",  "5:5%6,6^7.7&" };
 static char *Help1= "  Вы должны выбрать один из трех&типов рельсов и нажать $ENTER$&";
 CASE  tabl1[3] = {
  {181, 140,459,210, 14,12,  1, Rails0[0], Help1, Esc_Key},
  {181,140,459,210, 14, 12, 0, Rails0[1],Help1, Esc_Key},
  {181,140,459,210, 14, 12, 0, Rails0[2],Help1, Esc_Key}
 };
 VID  opr2 = { 240, 11, 400, 44, 0x11," Шпалы:", "lLдД;:жЖ" };
 static char *Help2=
  "  Вы должны выбрать один из двух&видов шпал  и нажать $ENTER$&";
 CASE  tabl2[2] = {
  {181,140,459,210, 14,12,1,  Shpala0[0], Help2, Esc_Key},
  {181,140,459,210, 14, 12, 0,Shpala0[1],Help2, Esc_Key}
 };
 VID  opr3 = { 275, 11, 355, 44, 0x11," Эпюра:", "1!1!2@2\"" };
 static char *Help3=
  "  Вы должны выбрать один из двух&типов эпюры  и нажать $ENTER$&";
 CASE  tabl3[2] = {
  {181,140,459,210, 14,12,1,Epura0[0],Help3, Esc_Key},
  {181,140,459,210, 14,12,0,Epura0[1],Help3, Esc_Key}
 };
 VID  opr4 = { 275, 11, 365, 110, 0x17,"Радиус:", "gGпП2@2\"1!1!0)0%8*8;6^6,5%5:3#3/" };
 static char far *Help4=
  "  Вы должны выбрать значение&"
  "радиуса и нажать $ENTER$&"
  " При отличии значения радиуса&"
  "на участке от заданных в таб-&"
  "лице выбирается ближайшее";
 CASE  tabl4[8] = {
  {178, 127,461,222, 14,12,1,  "$П$рямая", Help4, Esc_Key},
  {178, 127,461,222, 14,12,0,  "$2$000", Help4, Esc_Key},
  {178, 127,461,222, 14,12,0,  "$1$200", Help4, Esc_Key},
  {178, 127,461,222, 14,12,0,  "100$0$", Help4, Esc_Key},
  {178, 127,461,222, 14,12,0,  "$8$00", Help4, Esc_Key},
  {178, 127,461,222, 14,12,0,  "$6$00", Help4, Esc_Key},
  {178, 127,461,222, 14,12,0,  "$5$00", Help4, Esc_Key},
  {178, 127,461,222, 14,12,0,  "$3$00", Help4, Esc_Key}
 };
 switch (Field) {
  case 13: // Тип рельса
 M_13:
   i=Rails_;
   opr1.y1=PosY; opr1.y2=PosY+66;
   Init_Case_Wnd ( &opr1, tabl1, &i );
   if (Thank&0x08) {  Rails_=i; sprintf (String,"%2d",i); STRING_RESULT=0x01; }
   else STRING_RESULT=0x00;
  break;
  case 14: // Вид шпал
 M_14:
   i=Shpala_;
   opr2.y1=PosY; opr2.y2=PosY+55;
   Init_Case_Wnd ( &opr2, tabl2, &i );
   if (Thank&0x08) { Shpala_=i; sprintf (String,"%2d",i); STRING_RESULT=0x01; }
   else goto M_13; //STRING_RESULT=0x00;
  break;
  case 15: // Эпюра
 M_15:
   i=Epura_;
   opr3.y1=PosY; opr3.y2=PosY+55;
   Init_Case_Wnd ( &opr3, tabl3, &i );
   if (Thank&0x08) { Epura_=i; sprintf (String,"%4d",i); STRING_RESULT=0x01; }
   else goto M_14; //STRING_RESULT=0x00;
  break;
  case 16: // Радиус
   i=Radius_;
   opr4.y1=min(PosY,MAXY-141); opr4.y2=opr4.y1+119;
   Init_Case_Wnd( &opr4, tabl4, &i );
   if (Thank&0x08) { Radius_=i; sprintf (String,"%4d",Radius0[i]); STRING_RESULT=0x02; }
   else goto M_15; //STRING_RESULT=0x00;
  break;
  case 1: // Название участка
   sprintf ( Str1,"%2d", DirCod);  // Код направления
   _fmemcpy (&DB.buffer[1],Str1,2);
   Ret=YES;
  break;
  case 10: //Имя файла
   if (String[0]!='~') { //Уже есть имя
    sprintf (String,"~%07u",LastFile);
    LastFile+=1L;
    //DBW.EDIT[10]=EDITS; // Разрешаем ввод в поле
   }
  break;
  case 9: // Дата
   // See Transform_Date !!!
   sscanf (String,"%04d%02d%02d",&l,&k,&j);
   if (!IsDate (String,YYMD)) {
    l=Year; k=Mon; j=Day;
   }
   l%=100;
   sprintf (String,"%02d-%02d-%02d",j,k,l);
   Set_Key (1,INS); Ret=YES;
  break;
  default: Ret=YES; break;
 }
 return Ret;
}

char IsDate (char *Date, char Form) {
 // YES, если Date - допустимая дата
 int d,m,y;
 int days[12] = {31,28,31,30,31,30, 31,31,30,31,30,31};
 int up_day;
 switch (Form) {
  case DMYMINUS: sscanf (Date,"%2d-%2d-%2d",&d,&m,&y); break;
  case DMYY: sscanf (Date,"%2d%2d%4d",&d,&m,&y); break;
  case YYMD: sscanf (Date,"%4d%2d%2d",&y,&m,&d); break;
  default: return (NO);
 }
 if ( y<0 || y>9999 ) return NO;
 if (m<1 || m>12) return NO;
 up_day=days[m-1];
 if (m==2 &&  ( ((y%4==0) && (y%100!=0)) || (y%400==0) ) ) up_day++;
 if (d<1 || d>up_day) return NO;
 return YES;
}


int Km_In,Pk_In,St_In,Temp_In; // Вводимые поля

void InfoMess (void) {
 Print (DBW.x1+30,DBW.y1+20, WHITE, BLACK,
 "$Название участка$:    $Начало$(Км/Пк/Стык)  $Конец$(Км/Пк/Стык)");
 Print (DBW.x1+30,DBW.y1+30,  BLACK,WHITE, Segment);
 Print (DBW.x1+206,DBW.y1+30, BLACK,WHITE, Str1);
 Print (DBW.x1+366,DBW.y1+30, BLACK,WHITE, Str2);
 return;
}

void InfoFile (char far *Name) {
 extern char far *IsButtons; //
 // Создать/обновить файл информации об участке
 char far *InfoField[]={" ",
  "Км", "Пк", "Стык", " Измер.&тем-ра", "Привед.&тем-ра",
  "$Измер.$&левый",  "$Привед.$&левый", "$Измер.$&правый",
  "$Привед.$&правый" };
 char InfoBase[9]={  EDITS,EDITS,EDITS, EDITS, SHOWS,
  EDITS,SHOWS, EDITS, SHOWS};
//      ShowBase[9]={  SHOWS, SHOWS, SHOWS, SHOWS, SHOWS,
//  SHOWS, SHOWS,  SHOWS, SHOWS };
 char far *Ptr; static char far *Tmp_Name; int Pos0,Pos;
 char far * far *Tmp_Hdr;
 int Tmp_Lin,Tmp_Now; long Tmp_Sel; FUN Tmp_Fun;
 char Tmp_Byte,Tmp_Byte2,Tmp_Dop,Tmp_Saver;
 DOPEDITFUN Tmp_Edit; PRINTFUN Temp_Print;
 char far * far *Tmp_Fmt; char far *Tmp_But="         ";
 int Res,i; struct ffblk ffblk_;
 static WINDOW DBW2; static dbffile DB2; static FIELD FB2;
 Clr_Scr();
 if (Go_Work()) return;
 strcat (Name,".dbf");
 _fstrcpy (InfoName, Name);
 Res=findfirst (InfoName,&ffblk_,FA_ARCH); // 0 -OK
 if (Res) { // Нет файла
  CreateInfo (InfoName);
 }

 // Инициализируем вводимые поля
 Pos0=FieldPosition (3); Pos=FieldPosition (4); //Километр начала
 Ptr=&(DB.buffer[Pos]); Push (Ptr); Km_In=atoi (&DB.buffer[Pos0]); Pop (Ptr);
 Pos0=Pos; Pos=FieldPosition (5); //Пикет начала
 Ptr=&(DB.buffer[Pos]); Push (Ptr); Pk_In=atoi (&DB.buffer[Pos0]); Pop (Ptr);
 Pos0=Pos; Pos=FieldPosition (6); //Стык начала
 Ptr=&(DB.buffer[Pos]); Push (Ptr); St_In=atoi (&DB.buffer[Pos0]); Pop (Ptr);
 Temp_In=0;

 DBW2=DBW; DB2=DB; FB2=FB; // Сохранили рабочие структуры
 Tmp_Hdr=Other_Hdr; Tmp_Lin=Max_Hdr_Line;
 Tmp_Now=NowX; _fmemcpy (Tmp_But,IsButtons,9);
 Tmp_Sel=Sel_Ptr; Tmp_Fun=After_DBF_Function; Tmp_Fmt=Fmt;
 Tmp_Byte=DOP_EDIT; Tmp_Byte2=DOP_PACK; Tmp_Edit=Dop_Edit;
 Tmp_Dop=DOP_FILE; Tmp_Name=WinName; Tmp_Saver=FIELD_SAVER;
 DBW.x1=12; DBW.x2= 627;
 DBW.y1=20; DBW.y2=294;  DBW.UpStep=20; DOP_FILE=NO;
 DBW.SAVE=NO; DBW.COLORS=YES;
 DB.Cond|=0x04; Other_Hdr=InfoField; Max_Hdr_Line=2; // Заголовки
 DBW.FILTER=NO;  DBW.SEARCH=YES;  DBW.PRINT=YES; DBW.MODIFY=YES;
 DBW.Init_Func= InfoMess;
 FB.Y1=0; //  последний выбор
 After_DBF_Function=Nop;
// if (EDITOR) { // Редактировать поля ввода
 DBW.EDIT=InfoBase;
 DOP_EDIT=YES;
 Dop_Edit=Info_Input;
 FIELD_SAVER=YES; Field_Save=Info_Save;
 DOP_PACK=NO; Temp_Print=StartPrint;

 WinName=(char far *)"Измеренные зазоры";
 StartPrint= Tabl_Print;
 _fmemcpy (String,DB.buffer,DB.ZapLen);
 String[DB.ZapLen]='\0';
 Do_Format();
 sscanf (String,Format,&DelMark, &i,Segment, &Way,
   &StartKm, &StartPk, &StartSt, &EndKm, &EndPk, &EndSt,
   IzmDate, IzmName, &NodType, &PchType, &RailType,
   &ShpalaType, &EpuraType, &MinRad);
 DBF_Init (InfoName); // Вызвать функцию обработки

 DBW=DBW2; DB=DB2; FB=FB2; // Восстановили рабочие структуры
 Other_Hdr=Tmp_Hdr; Max_Hdr_Line=Tmp_Lin;
 NowX=Tmp_Now; _fmemcpy (IsButtons,Tmp_But,9);
 Sel_Ptr=Tmp_Sel; After_DBF_Function=Tmp_Fun; Fmt=Tmp_Fmt;
 DOP_EDIT=Tmp_Byte; DOP_PACK=Tmp_Byte2; Dop_Edit=Tmp_Edit; DOP_FILE=Tmp_Dop;
 WinName=Tmp_Name; FIELD_SAVER=Tmp_Saver; StartPrint=Temp_Print;
 return;
}

char Info_Input (char far *String, int Field, int PosY) {
 // YES, если нужно редактировать поле станд. ф-ей, иначе NO
 switch (Field) {
  case 0: //Номер километра
   sprintf (String,"%4d",Km_In);
  break;
  case 1: // Пикет
   sprintf (String,"%2d",Pk_In);
  break;
  case 2: // Стык
   sprintf (String,"%2d",St_In);
  break;
  case 3: // Температура измеренная
   sprintf (String,"%3d",Temp_In);
  break;
  case 5: case 7: break;
  default: return (NO);
 }
 return (YES);
}

char Info_Save (char far *String, int Field, int FieldLen) {
 int in;
 in=atoi (String);
 switch (Field) {
  case 0: if (in!=Km_In) { Km_In=in; Pk_In=1; St_In=1; }  break;
  case 1: if (in!=Pk_In) { Pk_In=in; St_In=1; }           break;
  case 2: St_In=in+1;  break;
  case 3: Temp_In=in;  break;
  case 7:
   if (STRING_RESULT==0x01) {
    if (FB.mety+FB.locy>= DBW.itemsy-1)
     Set_Key (1,INS);
    else
     Set_Key (4,HOME,DOWN,F4,F4);
    Last=YES;
   }
  break;
  default: break;
 }
 return (YES);
}

void ReFile (void) {
 // Обновляет имена рабочих файлов для открытой базы
 struct ffblk ffblk_;
 char far *Ptr, far *TmpName="             ", far *NewName= "             ";
 long Beg,ii,nn;
 int Res,Pos0,Pos;

 if (Go_Work()) return;
 Res=findfirst ("~*.dbf",&ffblk_,FA_ARCH); // 0 -OK
 if (Res) { Mistake (33); return; } // Нет исх. файлов
 while (!Res) {
  Ptr=_fstrchr (ffblk_.ff_name,'.');
  Push (Ptr); _fstrcpy (TmpName,ffblk_.ff_name); Pop (Ptr);
  _fstrcat (TmpName,".~~~");
  Res=rename (ffblk_.ff_name, TmpName);
  if (Res) {  Mistake (34); return; } // Не могу переименовать файл
  Res=findnext (&ffblk_);
 }
 Fun_Bar ("Идет коррекция имен файлов: ");
 SortMess (0);
 for (ii=0, Beg=FilePosition(0); ii<DB.Zap; ii++) {
  fsetpos (DB.fp,&Beg);
  fread (DB.buffer,DB.ZapLen,1,DB.fp);
  Pos0=FieldPosition (10); // Позиции начала и конца имени файла
  Pos=FieldPosition (11);
  Ptr=&(DB.buffer[Pos]); Push (Ptr);
  nn=atol (&DB.buffer[Pos0+1]);
  Pop (Ptr);
  sprintf (TmpName,"~%07u",nn); // nn - номер файла в записи
  _fstrcat (TmpName,".~~~");
  sprintf (NewName,"~%07u",ii);
  _fstrcat (NewName,".dbf"); // Получить новое имя, соотв. номеру записи
  Res=findfirst (TmpName,&ffblk_,FA_ARCH); // Ищем переименованный файл
  if (Res) {
   Mistake (35);  // Нет такого файла на диске
   Fun_Bar ("Идет коррекция имен файлов: ");
   CreateInfo (NewName); // Создать файл с номером ii
  }
  else {
   Res=rename (TmpName, NewName);
   if (Res) {  Mistake (34); return; } // Не могу переименовать файл
  }
  _fmemcpy (&DB.buffer[Pos0],NewName,8);
  fsetpos (DB.fp,&Beg);
  fwrite (DB.buffer,DB.ZapLen,1,DB.fp);
  Beg+=DB.ZapLen;
  SortMess (ii*100/DB.Zap);
 }
 LastFile = DB.Zap; // Можно нумеровать снова
 SortMess (100); return;
}

#define INFO_FIELDS 9
 // Число полей инф. файла
void CreateInfo (char far *FileName) {
// Создает новый рабочий файл Filename.dbf;
 FILE far *fp;
 dbfheader DBFhead;       // Заголовок файла
 static dbffield FIL;     // Заголовок поля
 int i,Pos; long Zap=1;
 char far *Names[9]={
 "KILOMETR   ", "PIKET      ", "STYK       ", "TEMP_IZMER ", "TEMP_RESULT",
 "LEFT_IZMER ", "LEFT_RES   ", "RIGHT_IZMER",  "RIGHT_RES  " };
 char Lens[9]={4,2,2,3,3,2,2,2,2};
 fp=fopen (FileName,"wb");
 if (fp==NULL) { Mistake (6); return; }
 _fmemset (&DBFhead,'\0',32);
 DBFhead.Ver=0x03; DBFhead.Zap=1L;
 DBFhead.HeadLen=32+32*INFO_FIELDS+1; //!!!
 DBFhead.ZapLen=23;
 fwrite ( &DBFhead, 32, 1, fp);
 // Заголовки полей
 for (i=0; i<9; i++) {
  _fmemcpy (&FIL.Name,Names[i],11);
  FIL.Type=0x4E; // Числовой 1!
  FIL.Len=Lens[i];
  fwrite ( &FIL, 32, 1, fp);
 }
 fwrite (&Start_Char,1,1,fp);
 // Первая запись
 _fmemset (String,' ',23); String[23]='\0';
 Pos=FieldPosition (3); // Километр
 _fmemcpy (&String[1],&DB.buffer[Pos],4);
 Pos=FieldPosition (4); // Пикет
 _fmemcpy (&String[5],&DB.buffer[Pos],2);
 Pos=FieldPosition (5); // Стык
 _fmemcpy (&String[7],&DB.buffer[Pos],2);
 fwrite ( String, 23, 1, fp);
 fwrite (&End_Char, 1, 1, fp);
 Zap=DB.Zap; DB.Zap=1; Change_Date (fp); DB.Zap=Zap;
 fclose (fp);
 return;
}


char DBF_Create (char *Name, char Fields, char **Names, char *Types,
 char *Lens, char *Decs) {
 FILE *fp;
 char i,j,c;
 int ZapLen;
 dbfheader DBFhead;       // Заголовок файла
 dbffield FIL;     // Заголовок поля
 if (Go_Work()) return NO;
 fp=fopen (Name,"wb");
 if (fp==NULL) { Mistake (6); return NO; }
 for (i=0,ZapLen=1; i<Fields; i++) ZapLen+=(int)(Lens[i]);
 _fmemset (&DBFhead,'\0',32);
 DBFhead.Ver=0x03;    DBFhead.Zap=0L;
 DBFhead.ZapLen=ZapLen;
 DBFhead.HeadLen=32+32*Fields+1;
 DBFhead.Date[0]=(unsigned char)(Year-1980);
 DBFhead.Date[1]=Mon; DBFhead.Date[2]=Day;
 i=fwrite ( &DBFhead, 32, 1, fp);
 if (!i) { Mistake (7); return NO; }
 // Заголовки полей
 for (i=0; i<Fields; i++) {
  _fmemset (&FIL,'\0',32);
  _fmemset (&FIL.Name,' ',11);
  if (_fstrlen (Names[i])>11) Names[11]='\0';
  for (j=0; j<11; j++) {
   c=Names[i][j];
   if (c=='\0') break;
   FIL.Name[j]=Names[i][j];
  }
  FIL.Type=Types[i];
  FIL.Len=Lens[i];
  FIL.Dec=Decs[i];
  fwrite ( &FIL, 32, 1, fp);
 }
 fwrite (&Start_Char,1,1,fp);
 fwrite (&End_Char,1,1,fp);
 fclose (fp);
 return YES;
}


////////////////////////////////////////////////////////////////////////
/*
void Characteristics (void) {
 static KEY Alt_1_[10] = { ALT_Y, ALT_G, ALT_X,
 ALT_R, ALT_L, ALT_V, ALT_N, ALT_D, ALT_K, 0 };
 static MODE *vtitle=
  "Характеристики выбранного участка направления&$"
  "                                    "; //2*36
 VIDI   opr = { 95, 52, 515, 297, 0x29, vtitle, Alt_1_ };
 CASEI  tabl[] = {
  { 0,-10,320,35, 42,39,0,"$Н$азвание участка",
    300,10,70,Segment, "", Nop },
  { 320,-10,400,35,12,10,0,"Номер&&&$п$ути",
    200,10,100,Str1, "", Nop },

  { 0,35,200,90, 19,16,0,"На$ч$ало участка&(км/пк/cтык)",
    300,10,70,Str2, "", Nop },
  { 200,35,400,90,  19,16,0,"$К$онец участка&(км/пк/cтык)",
    300,10,70, Str3, "", Nop },

  { 0,90, 200,135, 19, 16,0, "$Д$ата промера зазоров",
    300,10,70, Str4, "", Nop },
  { 200,90, 400, 135, 9, 7, 0, "$М$инимальный радиус",
    300,10,70, Str8, "", Nop },

  { 0,135,130, 180, 9, 7, 0, "$Т$ип рельсов",
    300,10,70, Str5, "", Nop },
  { 130,135,260,180, 9, 7, 0,"$В$ид шпал",
    300,10,70, Str6, "", Nop },
  { 260,135,400,180, 9, 7,0, "Эпюра шпа$л$",
    250,10,90, Str7, "", Nop }

 };

 RightMargin (Segment);
 _fmemcpy (&vtitle[47],Direction,36);
 sprintf(Str2,"%4d/%2d/%2d",StartKm, StartPk, StartSt);
 sprintf(Str3,"%4d/%2d/%2d",EndKm, EndPk, EndSt);
 _fmemcpy(Str4,&IzmDate[6],2); Str4[2]='/';
 _fmemcpy(&Str4[3],&IzmDate[4],2); Str4[5]='/';
 _fmemcpy(&Str4[6],IzmDate,4);
 itoa (RailType,Str5,10); itoa (Way,Str1,10);
 itoa (ShpalaType,Str6,10);
 itoa (EpuraType,Str7,10);
 itoa (MinRad,Str8,10);
 Thank|=0x11; // Запрещаем ввод и сохранение окна
 Get_Many_Text (&opr,tabl);
 if (Thank&0x08) {
  Write_Field=Init_Zazor; // Рассчитать приведенные зазоры и тем-ру
  _fstrcpy (InfoName,IzmName);
  _fstrcat (InfoName,".dbf");
  DB.Cond|=0x08; // Только инициализация!
  WinName=(char far *)"Измеренные зазоры";
  if (!DBF_Init (InfoName)) {
   _fstrcpy(&ZazorMes.text[40],InfoName);
   Help_Text(&ZazorMes);
   DBFWrite (0,DB.Zap,3,6,0x01);
   // !!!
  }
 }
 else { // Возврат к выбору режима работы с окном участков
  Set_Key (1,START);
  Ext_Function=Sel_From_Catalog;
 }
 return;
}

void What_Line (int x,int y) {
 HELP lnmes={ 270,85,370,105,"","ЛЕВАЯ  НИТЬ" };
 lnmes.x1=x; lnmes.x2=x+108;
 lnmes.y1=y; lnmes.y2=y+30;
 if (Line) strncpy (lnmes.text,"ПРАВАЯ",6);
 else strncpy (lnmes.text,"ЛЕВАЯ ",6);
 Help_Text (&lnmes);
 return;
}
*/
////////////////////////////////////////////////////////////
/////////////////////// Базы "Норм.зазоры - Температура"

extern void Write68 (char *,int ,int,long),Write9 (char *,int ,int, long);
extern MODE SHOWBUTTONS;
//void Start689 (void);
void Win_Temp(char);
void Redefine(void);

void Win_Temp (char Par) {
 static char far *Temp0[]={"", "Нормальный&зазор","Температура"};
 static char far *Temp1[]={"", "Нормальный&зазор","Получено&для зимы",
  "Получено&для лета"};
 char TempBase[3]={SHOWS,SHOWS,SHOWS};
 int Ind; // 0,1
 char Kol[2]={2,3};
 char *Names1[2]={"ZAZOR","TEMP"};
 char *Names2[3]={"NORM_ZAZOR","TMP_WINTER","TMP_SUMMER"};
 char **NamesPtr[2]={ &Names1[0], &Names2[0] };
 char Types[3]={'N','N','N'};
 char Lens[3]={4,6,6};
 char Decs[3]={0,1,1};
// if (!(What&0x02)) {
 DBW.x1=40; DBW.x2=610; DBW.y2=338;
 _fmemset (String,'\0',60);
 DBW.SAVE=NO; DBW.COLORS=YES; DBW.MODIFY=NO;
 DBW.PRINT=YES; DBW.SEARCH=YES; DBW.UpStep=20;
 DBW.EDIT=TempBase; DOP_FILE=NO; DOP_EDIT=NO;
 FB.Y0=FB.Y1=0;
//!!!  StartPrint=Start689;
 switch (Par) {
  case 0x06: Write_Field=Write68;DBW.y1=145;
      Other_Hdr=Temp0; Temp_Type=1;
  break;
  case 0x08: Write_Field=Write68;DBW.y1=195;
      Other_Hdr=Temp0; Temp_Type=2;
  break;
  case 0x09: Write_Field=Write9;DBW.y1=145;
      Other_Hdr=Temp1; Temp_Type=3;
  break;
 }
 DBW.Init_Func=Redefine;
 // Вызвать функцию обработки
 What|=0x02; // DBF инициализирован
 After_DBF_Function=Nop;
 Max_Hdr_Line=2; DB.Cond|=0x04; //For other headers!
// }
 WinName=(char far *)"Температуры";
 StartPrint=Tempr_Print;
 SHOWBUTTONS=NO;
AGAIN:
 if (DBF_Init(TEMPS[Temp_Type-1])) {
  Ind=(Temp_Type%3 ? 0 : 1);
  if (DBF_Create (TEMPS[Temp_Type-1] , Kol[Ind], NamesPtr[Ind],
   &Types[0], &Lens[0], &Decs[0])) goto AGAIN;
 }
 SHOWBUTTONS=YES; // Восстановить состояние по умолчанию
 Set_Key (1,START);
 Ext_Function=Ved1; //Вместо вызова   -> Inp_Peregon -> Vedomost
 Clr_Scr(); return;
}

void Redefine (void) {
 int j;
 //Print (FB.sx+12,FB.ey+25,FB.Col[2],FB.Col[6],PrnStr);
 if (Temp_Type==3) {
  Print (FB.sx+12,DBW.y1+20,FB.Col[3],FB.Col[6],
  "НОРМАЛЬНЫЕ ЗАЗОРЫ ДЛЯ ОСЕННЕ-ЗИМНЕГО И&"
  "     ВЕСЕННЕ-ЛЕТНЕГО ПЕРИОДА");
  j=3; // 9
 }
 else {
  Print (FB.sx+12,DBW.y1+20,FB.Col[3],FB.Col[6],
  "ТАБЛИЦА НОРМАЛЬНЫХ ЗАЗОРОВ");
  j=2; //6,8
 }
 if (Temp_Type==1) //Ris 6
  Print (FB.sx+12,DBW.y1+30,FB.Col[3],FB.Col[6],
  "ЗАПАС ТЕМПЕРАТУРНОЙ АМПЛИТУДЫ НЕ ИСПОЛЬЗОВАН");
 DBFWrite (0,24,0,j,0x01); //!!!
 DBW.itemsy=24; FB.YN=24;
 return;
}

////////////////////////////////////////////////////
/////////////////////// База "Измеренные зазоры"

//!!! extern int Regul_Menu(void);

extern int Norm_Zazor_;
void Init_Izmer(void),Shut_Izmer(void);

void ReadTemp (char *,int ,int, long),WriteNormal (char *,int ,int, long);


/*char far *Izm0[]={
 "Номер&стыка",
 "Величина&нормальных&зазоров,мм",
 "Величина&измеренных&зазоров,мм",
 "Расчетный&допуск&на 1 стык,мм",
 "Назначенный&допуск,мм"
};

void Vedomost(void) {
 extern MODE Shpala_; extern float Dop14[];
 static KEY Alt_[] = { ALT_Y, ALT_L, ALT_C, ALT_J, 0 };
 static char Str1[8],Str2[8];
 VIDI   opr = { 40, 15, 610, 125, 0x22,
  " Заполнение ведомости& измеренных зазоров",Alt_ };
 CASEI  tabl[] = {
  { 10,-10,180,35,12,10,0, "$Н$ормальный зазор",
    300,20,70,Str1, "", Nop },

  { 180,-10,350,35,12,10,0,"Расчетный $д$опуск на содержание         , мм",
    300,20,70,Str2, "", Nop }
 };
 char *Stik[]={ "4 стыков","1 стыка "}; // 1 - ж./б., 0 - дер.
 Init_Izmer(); // Ввод измеренной температуры

 itoa (Norm_Zazor_,Str1,10);
 Str2[0]='\xFB'; sprintf (&(Str2[1]),"%-5.1f",Dop14[Shpala_?0:1]);
 strncpy (&(tabl[1].name[33]),Stik[Shpala_],8);
 Thank|=0x11; // Запрещаем ввод и сохранение окна
 Set_Key (1,ALT_C);
 Get_Many_Text (&opr,tabl);
 if (!Line) {
  RegType =0x01; //!!!(char) Regul_Menu();     // Выбор способа регулировки
  if (RegType==255) { RegType=0x00; return; }  // при первом проходе
 }

 What_Line (470,75);

// if (!(What&0x02)) { // Обработка БД измеренных зазоров
  DBW.x1=opr.x1; DBW.x2=opr.x2; DBW.y1=opr.y2-20; DBW.y2=320;
  DBW.SAVE=NO; DBW.COLORS=YES; DBW.MODIFY=YES;
  DBW.PRINT=YES; DBW.SEARCH=YES; DBW.UpStep=0; DOP_FILE=NO;
  DBW.EDIT=DirBase;
  DBW.Init_Func=Nop;
  After_DBF_Function=Shut_Izmer;
  // Имя
//  strset0 (String,60);
//  strcpy (String,IZMS[Line]);
  What|=0x02; // DBF инициализирован
// }
// else return;
 Other_Hdr=Izm0; Max_Hdr_Line=3; DB.Cond|=0x04; //For other headers!
 WinName=(char far *)"Измеренные зазоры";
 DBF_Init(IZMS[Line]);        // Изменение числа расчетных узлов !!!

 Ext_Function=Ved1; Set_Key (1,START);
 return;
}
*/
float ffmin=1.e+9;

void ReadTemp (char *Str,int Len,int Fil,long Num) {
 float f,ff;
 f=atof (Str);
 ff=fabs_(f-Tmp_All);
 if (ff < ffmin) { ffmin= ff; Norm_Zazor_= Num; }
 return;
}

void Init_Izmer(void) {
 extern int KN;
 static char Temp_[8];
 // 1 - с распределением, Td<=Tf
 // 2 - без распределения, Td<=Tf
 // 3 - Td>Tf, для зимы и лета
 CASE  temp_ = { 158,100,478,180, 0,12,0,"",
  "Производить расчет нормального&"
  "зазора по $зимним$ температурам?&"
  "Ответьте $ДА$ или $НЕТ$ для расчета&"
   "по $летним$" };
 int BegField=1;

 // Прочитать нормальный зазор -- одна из баз temp*.dbf
 _fmemset (String,'\0',30);
 _fstrcpy (String,TEMPS[Temp_Type-1]);
// _fstrcat (String,".dbf"); // Выбор временной базы
 DB.Cond|=0x08; //For initialization only!
 After_DBF_Function=Shut_Izmer;
 DBF_Init(String);
 if (Temp_Type==3) {
  BegField=1;
  if (Answ_Menu(&temp_)) BegField++;
 }
 Write_Field=ReadTemp; //Получить Norm_Zazor_
 ffmin=1.e+9;
 DBFWrite (0,KN+1,BegField,1,0x00); //Read from base!
 fclose (DB.fp); What&=0xfd;
 return;
}

extern unsigned char StrBuf[];

void Shut_Izmer (void) {
 STK=DBW.itemsy; return;
}

int Reg_Dim[]={24,24}; // Число записей


////////////////////////////////////////////////////
/////////////////////// База "Ведомoсть регулировки зазоров"

extern void Write0 (char *,int ,int, long),Write1(char *,int ,int, long),
       Write2 (char *,int ,int, long),Write3 (char *,int ,int, long),
       Read0 (char *,int ,int, long);
int Start0123 (long,int *);
void Read_Reg (void); // Reading from dbf-file


void Redefine_Reg(void);

//int Reg_Len[4]= {6,9,8,9};    // и полей в базах измеренных зазоров
int Reg_Len[2]= {9,10};
/*char far *Ved0h[]={
 "Номер&записи",
 "Номер&кило-&метра",
 "Номер&стыка",
 "Величина&измеренных&зазоров,мм",
 "Накопление&измеренных&зазоров,мм",
 "Накопление&нормальных&зазоров,мм",
 "Требуемая&передвижка&рельсов,мм"
};
char far *Ved1h[]={
 "Номер&записи",
 "Номер&кило-&метра",
 "Номер&стыка",
 "Величина&измеренных&зазоров,мм",
 "Накопление&измеренных&зазоров,мм",
 "Требуемая передвижка&рельсов для создания&нормальных зазоров,мм",
 "Установленный&допуск на содержание&1 стыка,мм",
 "Требуемая передвижка для&приведения зазоров к&нормальным с уч.допуска",
 "Установленные&нормальные&зазоры",
 "Установленный допуск&после расчета и&регулировки"
};*/
char far *Ved2h[]={
 "",
 "Номер&кило-&метра",
 "Номер&пике-&та",
 "Номер&стыка",
 "Величина&измеренных&зазоров,мм",
 "Накопление 4&текущих измер.&зазоров,мм",
 "Накопление 4&текущих норм.&зазоров,мм",
 "Разность сумм 4&измер. и норм.&зазоров, мм",
 "Передвижка рельсов&для приведения к&нормальным, мм",
 "Установл.&зазоры,&мм"
};
char far *Ved3h[]={
 "",
 "Номер&кило-&метра",
 "Номер&пике-&та",
 "Номер&стыка",
 "Величина&измеренных&зазоров,мм",
 "Накопление 4&текущих измер.&зазоров,мм",
 "Накопление 4&текущих норм.&зазоров,мм",
 "Разность сумм 4&измер. и норм.&зазоров, мм",
 "Передвижка рельсов&для приведения к&нормальным, мм",
 "Установл. допуск&на содерж.1 стыка,&мм",
 "Установл.&зазоры,&мм"
};

void Win_Reg (void) {
 char Types[10]={'N','N','N','N','N','N','N','N','N','N'};
 char *Names[2][10]={
  {"KM        ",   "PK        ",   "ST        ",   "IZM_ZAZOR ",
   "SUM_IZMER ",   "SUM_NORM  ",   "RAZNOST   ",   "SDVIG     ",
   "UST_ZAZOR",    "          "},
  {"KM        ",   "PK        ",   "ST        ",   "IZM_ZAZOR ",
   "SUM_IZMER ",   "SUM_NORM  ",   "RAZNOST   ",   "SDVIG     ",
   "UST_DOPUSK",   "UST_ZAZOR "}
 };
 char Lens[10]={4,2,2,3,3,3,3,3,3,3},
      Decs[10]={0,0,0,0,0,0,0,0,0,0};
 char RegBase[10]={SHOWS,SHOWS,SHOWS,SHOWS,SHOWS,
		   SHOWS,SHOWS,SHOWS,SHOWS,SHOWS};
 // Скорректировать размер файла отчета
AGAIN:
 DB.Cond|=0x08; // Init only;
 if (DBF_Init(VEDS[RegType])) {
  DBF_Create (VEDS[RegType],Reg_Len[RegType],Names[RegType],Types,Lens,Decs);
  goto AGAIN;
 }
 DBF_Zap(Reg_Dim[RegType]); //!!! DBF_Zap(STK);
 fclose (DB.fp); What&=0xfd;
 // и открыть его для перезаписи
 DBW.x1=40; DBW.x2=610; DBW.y1=150; DBW.y2=338;
 _fmemset (String,'\0',60);
 DBW.SAVE=NO; DBW.COLORS=YES; DBW.MODIFY=NO;
 DBW.PRINT=YES; DBW.SEARCH=YES;
 DBW.EDIT=RegBase; SHOWBUTTONS=NO; DBW.UpStep=0;
 switch (RegType) {
  case 0x00:  Write_Field=Write2; Other_Hdr=Ved2h; break;
  case 0x01:  Write_Field=Write3; Other_Hdr=Ved3h; break;
 }
 StartPrint=Start0123;
 DBW.Init_Func=Redefine_Reg;
 // Вызвать функцию обработки
 What|=0x02; // DBF инициализирован
 After_DBF_Function=Nop;
 Max_Hdr_Line=3; DB.Cond|=0x04; //For other headers!
 DBF_Init(VEDS[RegType]);
 SHOWBUTTONS=YES; Clr_Scr(); return;
}

void Redefine_Reg (void) {
// Print (FB.sx+32,FB.ey+25,FB.Col[2],FB.Col[6],PrnStr[RegType]);
 DBFWrite (0,Reg_Dim[RegType],0,Reg_Len[RegType],0x01);
// What_Line (DBW.x1+4,FB.ey+2);
 return;
}

extern void Init_Dopusk(int,int);
char FirstZap;
void Read_Reg (void) {
 extern int EPS3,EPS4,I3,I4,K1,K4;
 int eps=0;

 DB.Cond=0x10;
 memset (String,'\0',30);
 strcpy (String,IzmName);
 strcat (String,".dbf");
 DB.Cond|=0x08; //For initialization only!
 if (DBF_Init(String)) {
  Mistake (6);
  return;
 }
 FirstZap=1;
 Write_Field=Read0; //Читает массивы HLA,SLA
 DBFWrite (0,DB.Zap,0,DB.Field,0x00);
 Init_Dopusk (DB.Zap,RegType);  // Расчетный и назначенный допуски из A14[0],Dop14[0]
   //записать в массивы DN , DR
   //Dop14 - расчетный{2,8}, A14- назначенный{1,4}
 eps=0.01; //Погрешность расчета всегда 0.01!
 switch (RegType) {
  case 0x00: I3=DB.Zap; EPS3=eps; K1=1; break;
  case 0x01: I4=DB.Zap; EPS4=eps; K4=4; break;
 }
 fclose (DB.fp); What&=0xFD;
 return;
}

extern char far *Rails0[3], far *Shpala0[2],far *Epura0[2];
extern int far Radius0[8];

int Direct_Print (long Num, int *How) {
 if (Num==FIRST_PRINT) {
  PrintMargin();
  fprintf (printer,"		       КАТАЛОГ НАПРАВЛЕНИЙ\n");
  (*How)=1; return 66;
 }
 else if (Num==HEADER_PRINT) {
  PrintMargin();
  fprintf (printer,"┌───┬────────────────────────────────────┬───────────┬───────────┐\n");
  PrintMargin();
  fprintf (printer,"│Код│       Название направления         │Мин.тем-ра │Макс.тем-ра│\n");
  PrintMargin();
  fprintf (printer,"├───┼────────────────────────────────────┼───────────┼───────────┤");
  (*How)=3;
 }
 else if (Num==END_PAGE) {
  PrintMargin();
  fprintf (printer,  "└───┴────────────────────────────────────┴───────────┴───────────┘");
  (*How)=1;
 }
 else { // Печать записи из строки String
  Do_Format(); // Получили строку Format
  sscanf (String,Format,&DelMark, &DirCod,&Direction[0],&Tmin,&Tmax);
  //PrintMargin();
  fprintf (printer, "│%3d│%-36s│%-11d│%-11d│",  DirCod, Direction, Tmin, Tmax);
  (*How)=1;
 }
 return 1;
}


int Catalog_Print (long Num, int *How) {
 int i;
 if (Num==FIRST_PRINT) {
  PrintMargin();
  fprintf (printer,   "			      КАТАЛОГ УЧАСТКОВ\n");
  PrintMargin();
  fprintf (printer, "┌────────────────────────────────────────────────────────────────────────┐\n");
  PrintMargin();
  fprintf (printer, "│Код    Название направления                    Мин.тем-ра    Макс.тем-ра│\n");
  PrintMargin();
  fprintf (printer, "│%3d    %-36s    %3d           %3d        │\n",
   DirCod,Direction,Tmin,Tmax);
  PrintMargin();
  fprintf (printer, "└────────────────────────────────────────────────────────────────────────┘");
  (*How)=5; return 74;
 }
 else if (Num==HEADER_PRINT) {
  PrintMargin();
  fprintf (printer,   "┌────────────────────┬───┬──────────┬────────┬────────┬───┬──┬──┬──┬─────┐\n");
  PrintMargin();
  fprintf (printer, "│  Название участка  │Пу-│ Участок  │  Дата  │  Имя   │НОД│ПЧ│Р.│Ш.│Эпюра│\n");
  PrintMargin();
  fprintf (printer, "│                    │ти │Км/Пк/Стык│ промера│ файла  │   │  │  │  │Рад. │\n");
  PrintMargin();
  fprintf (printer, "├────────────────────┼───┼──────────┼────────┼────────┼───┼──┼──┼──┼─────┤");
  (*How)=4;
 }
 else if (Num==END_PAGE) {
  PrintMargin();
  fprintf (printer,
   "└────────────────────┴───┴──────────┴────────┴────────┴───┴──┴──┴──┴─────┘");
  (*How)=1;
 }
 else { // Печать записи из строки String
  Do_Format(); // Получили строку Format
  sscanf (String,Format,&DelMark, &i,Segment, &Way, // DirCod уже есть из БД "Направления"
   &StartKm, &StartPk, &StartSt, &EndKm, &EndPk, &EndSt,
   IzmDate, IzmName, &NodType, & PchType, &RailType,
   & ShpalaType, &EpuraType, & MinRad);
  Transform_Date (IzmDate); // Пишет дату в DateBuf
  //PrintMargin();
  fprintf (printer,
   "│%-20s│%-3d│%4d/%2d/%2d│%8s│%8s│ %2d│  │%c%c│  │%4s │\n",
   Segment,Way,StartKm, StartPk, StartSt,  DateBuf,
   IzmName, NodType,Rails0[RailType][1], Rails0[RailType][2], Epura0[EpuraType]);
  PrintMargin();
  fprintf (printer,
   "│                    │   │%4d/%2d/%2d│        │        │   │%2d│  │%c.│ %4d│\n",
   EndKm, EndPk, EndSt,PchType, Shpala0[ShpalaType][0], MinRad);
  PrintMargin();
  fprintf (printer,
   "├────────────────────┼───┼──────────┼────────┼────────┼───┼──┼──┼──┼─────┤");
  (*How)=3;
 }
 return 1;
}

int i1,i2,i3,i4,i5,i6,i7,i8,i9,i10;

int Tabl_Print (long Num, int *How) {
 if (Num==FIRST_PRINT) {
  PrintMargin();
  fprintf (printer,   " 	     ТАБЛИЦА ИЗМЕРЕННЫХ И ПРИВЕДЕННЫХ ЗАЗОРОВ\n");
  PrintMargin();
  fprintf (printer, "┌────────────────────────────────────────────────────────┐\n");
  PrintMargin();
  fprintf (printer, "│Код  Название направления                    Температуры│\n");
  PrintMargin();
  fprintf (printer, "│%3d  %-36s    Мин.  Макс.│\n", DirCod,Direction);
  PrintMargin();
  fprintf (printer, "│Название участка      Границы (Км/Пк/Стык)   %3d   %3d  │\n",Tmin,Tmax);
  PrintMargin();
  fprintf (printer,   "│%-20s  %4d/%2d/%2d  %4d/%2d/%2d            │\n",
   Segment,StartKm, StartPk, StartSt, EndKm, EndPk, EndSt);
  PrintMargin();
  fprintf (printer,  "├────────────────────────────────────────────────────────┤\n");
  PrintMargin();
  fprintf (printer,   "│Рельсы: %3s    Эпюра: %4s    Шпалы: %c%c%c.   Радиус: %4d│\n",
   Rails0[RailType], Epura0[EpuraType], Shpala0[ShpalaType][0],
   Shpala0[ShpalaType][1], Shpala0[ShpalaType][2], MinRad);
  PrintMargin();
  fprintf (printer,  "└────────────────────────────────────────────────────────┘");
  (*How)=9; return 58;
 }
 else if (Num==HEADER_PRINT) {
  PrintMargin();
  fprintf (printer,   "┌────┬───┬───┬───────┬───────┬─────────────┬─────────────┐\n");
  PrintMargin();
  fprintf (printer,   "│Км. │Пк.│Ст.│Измер. │Привед.│ Левый зазор │Правый  зазор│\n");
  PrintMargin();
  fprintf (printer,   "│    │   │   │тем-ра │тем-ра │Измер. Привед│Измер. Привед│\n");
  PrintMargin();
  fprintf (printer,   "├────┼───┼───┼───────┼───────┼──────┬──────┼──────┬──────┤");
  (*How)=4;
 }
 else if (Num==END_PAGE) {
  PrintMargin();
  fprintf (printer,
   "└────┴───┴───┴───────┴───────┴──────┴──────┴──────┴──────┘");
  (*How)=1;
 }
 else { // Печать записи из строки String
  Do_Format(); // Получили строку Format
  sscanf (String,Format,&DelMark, &i1,&i2,&i3,&i4,&i5,&i6,&i7,&i8,&i9);
  //PrintMargin();
  fprintf (printer,
   "│%4d│%2d │%2d │  %3d  │  %3d  │  %2d  │  %2d  │  %2d  │  %2d  │",
   i1,i2,i3,i4,i5,i6,i7,i8,i9);
  (*How)=1;
 } return 1;
}

#include <stdarg.h>
int Tempr_Print (long Num, int *How) {
 extern float DN1,DN2,SGP,SGM;
 int Dop,i1,Pos; float i2,i3;
 char *Dop14[2]={"4 стыков","1  стыка"},*Ptr;
 if (Num==FIRST_PRINT) {
  if (Temp_Type==3) {
   PrintMargin();
   fprintf (printer,   "      ТАБЛИЦА НОРМАЛЬНЫХ ЗАЗОРОВ ДЛЯ ОСЕННЕ-ЗИМНЕГО\n");
   PrintMargin();
   fprintf (printer,"		    И ВЕСЕННЕ-ЛЕТНЕГО ПЕРИОДА\n");
   (*How)=2;
  }
  else {
   PrintMargin();
   fprintf (printer,   "		    ТАБЛИЦА НОРМАЛЬНЫХ ЗАЗОРОВ\n");
   (*How)=1;
   if (Temp_Type==1) {
    PrintMargin();
    fprintf (printer, "      (запас температурной амплитуды не использован)\n");
    (*How)=2;
   }
  }
  if (Temp_Type!=3) {
   if (ShpalaType) { //ж./б.
    Dop=(Temp_Type==2?3:2); //Ris 8, Ris 6
    Ptr=Dop14[1];
   }
   else {        //дер.
    Dop=(Temp_Type==2?12:8); //Ris 8, Ris 6
    Ptr=Dop14[0];
   }
  }
  else { // Для рис 9 не зависит от вида шпал
   Dop=8;
   Ptr=Dop14[0];
  }
  PrintMargin();
  fprintf (printer,   "┌────────────────────────────────────────────────────────┐\n");
  PrintMargin();
  fprintf (printer,   "│Код  Название направления                               │\n");
  PrintMargin();
  fprintf (printer,   "│%3d  %-36s               │\n",DirCod, Direction);
  PrintMargin();
  fprintf (printer,   "│     Название участка          Участок (Км/Пк/Стык)     │\n");
  PrintMargin();
  fprintf (printer,   "│     %-20s      %4d/%2d/%2d   %4d/%2d/%2d  │\n",Segment,StartKm, StartPk, StartSt, EndKm, EndPk, EndSt);
  PrintMargin();
  fprintf (printer,   "├────────────────────────────────────────────────────────┤\n");
  PrintMargin();
  fprintf (printer,   "│Рельсы: %3s    Эпюра: %4s    Шпалы: %c%c%c.   Радиус: %4d│\n",
   Rails0[RailType], Epura0[EpuraType], Shpala0[ShpalaType][0],
   Shpala0[ShpalaType][1], Shpala0[ShpalaType][2], MinRad);
  PrintMargin();
  fprintf (printer,   "├────────────────────────────────────────────────────────┤\n");
  PrintMargin();
  fprintf (printer,   "│Мин. температура: %3d        Макс. температура: %3d     │\n",
   Tmin, Tmax);

  PrintMargin();
  fprintf (printer,
   "│Допуск на содержание %8s:       %4d               │\n", Ptr,Dop);

  if (Temp_Type==2) {
   PrintMargin();
   fprintf (printer, "│Уменьшение макс. растяг. сил зимой: %7.1f на %5.0f кН.│\n",SGP,DN1);
   PrintMargin();
   fprintf (printer, "│Уменьшение макс. растяг. сил летом: %7.1f на %5.0f кН.│\n",SGM,DN2);
   (*How)+=2;
  }
  PrintMargin();
  fprintf (printer, "└────────────────────────────────────────────────────────┘");
  (*How)+=11; return 58;
 }
 else if (Num==HEADER_PRINT) {
  if (Temp_Type==3) {
   PrintMargin();
   fprintf (printer, "┌──────────┬───────────┬───────────┐\n");
   PrintMargin();
   fprintf (printer, "│Нормальный│  Зимняя   │  Летняя   │\n");
   PrintMargin();
   fprintf (printer, "│  зазор   │температура│температура│\n");
   PrintMargin();
   fprintf (printer, "├──────────┼───────────┼───────────┤");
  }
  else {
   PrintMargin();
   fprintf (printer, "┌──────────┬───────────┐\n");
   PrintMargin();
   fprintf (printer, "│Нормальный│Температура│\n");
   PrintMargin();
   fprintf (printer, "│  зазор   │           │\n");
   PrintMargin();
   fprintf (printer, "├──────────┼───────────┤");
  }
  (*How)=4;
 }
 else if (Num==END_PAGE) {
  if (Temp_Type==3) {
   PrintMargin();
   fprintf (printer, "└──────────┴───────────┴───────────┘");
  }
  else {
   PrintMargin();
   fprintf (printer, "└──────────┴───────────┘");
  }
  (*How)=1;
 }
 else { // Печать записи из строки String
  Do_Format(); // Получили строку Format
  // Из-за вещественных чисел вынуждены разбирать строку
  // вручную: !!!
  Ptr=&String[1+DB.Lens[0]]; Push (Ptr); i1=atoi (&String[1]); Pop (Ptr);
  Pos=FieldPosition (1);
  Ptr=&String[Pos+DB.Lens[1]]; Push (Ptr); i2=atof (&String[Pos]); Pop (Ptr);
  if (Temp_Type==3) {
   Pos=FieldPosition (2);
   Ptr=&String[Pos+DB.Lens[2]]; Push (Ptr); i3=atof (&String[Pos]); Pop (Ptr);
   //sscanf (String,Format,&DelMark, &i1,&i2,&i3);
   fprintf (printer,"│  %6d  │  %7.1f  │  %7.1f  │",i1,i2,i3);
  }
  else {
   //sscanf (String,Format,&DelMark, &i1,&i2);
   fprintf (printer,"│  %6d  │  %7.1f  │",i1,i2);
  }
  (*How)=1;
 } return 1;
}

int Start0123 (long Num, int *How) { // See Reg_Info
 char *vtitle1[]= {
  "Ведомость регулировки (разгонки) зазоров для приведения их\n",
  "Ведомость регулировки зазоров по условию превышения допуска\n"
 };
 char *vtitle2[]= {
  "к нормальным с учетом допуска на 1 стык",
  "на содержание 4 стыков"
 };
 if (Num==FIRST_PRINT) {
  PrintMargin();
  fprintf (printer, vtitle1[RegType]);
  PrintMargin();
  fprintf (printer, vtitle2[RegType]);
//  PrintMargin();
  *How=2;
  if (RegType==0) return 67;
  else return 74;
 }
 else if (Num==HEADER_PRINT) {

  if (RegType==0) {
   PrintMargin();fprintf (printer,"┌────┬──┬──┬────────┬──────────┬──────────┬─────┬──────────┬──────┐\n");
   PrintMargin();fprintf (printer,"│Кило│Пк│  │Величина│Накопление│Накопление│     │Передвижка│Уста- │\n");
   PrintMargin();fprintf (printer,"│метр│  │Ст│измер.  │4 измер.  │4 норм.   │(R-N)│рельсов   │новл. │\n");
   PrintMargin();fprintf (printer,"│    │  │  │зазоров │зазоров(R)│зазоров(N)│     │          │зазоры│\n");
   PrintMargin();fprintf (printer,"├────┼──┼──┼────────┼──────────┼──────────┼─────┼──────────┼──────┤");
  }
  else {
   PrintMargin();fprintf (printer,"┌────┬──┬──┬────────┬──────────┬──────────┬─────┬──────────┬──────┬──────┐\n");
   PrintMargin();fprintf (printer,"│Кило│Пк│  │Величина│Накопление│Накопление│     │Передвижка│Допуск│Уста- │\n");
   PrintMargin();fprintf (printer,"│метр│  │Ст│измер.  │4 измер.  │4 норм.   │(R-N)│рельсов   │на 1  │новл. │\n");
   PrintMargin();fprintf (printer,"│    │  │  │зазоров │зазоров(R)│зазоров(N)│     │          │стык  │зазоры│\n");
   PrintMargin();fprintf (printer,"├────┼──┼──┼────────┼──────────┼──────────┼─────┼──────────┼──────┼──────┤");
  }
  *How=5;
 }
 else if (Num==END_PAGE) {
  if (RegType==0) {
   PrintMargin();fprintf (printer,"└────┴──┴──┴────────┴──────────┴──────────┴─────┴──────────┴──────┘");
  }
  else {
   PrintMargin();fprintf (printer,"└────┴──┴──┴────────┴──────────┴──────────┴─────┴──────────┴──────┴──────┘");
  }
  *How=1;
 }
 else {
  Do_Format(); // Получили строку Format
  if (RegType==0) {
   sscanf (String,Format,&DelMark, &i1,&i2,&i3,&i4,&i5,&i6,&i7,&i8,&i9);
//   PrintMargin();
   fprintf (printer,"│%4d│%2d│%2d│%3d     │%3d       │%3d       │%3d  │%3d       │%3d   │",i1,i2,i3,i4,i5,i6,i7,i8,i9);
  }
  else {
   sscanf (String,Format,&DelMark, &i1,&i2,&i3,&i4,&i5,&i6,&i7,&i8,&i9,&i10);
//   PrintMargin();
   fprintf (printer,"│%4d│%2d│%2d│%3d     │%3d       │%3d       │%3d  │%3d       │%3d   │%3d   │",i1,i2,i3,i4,i5,i6,i7,i8,i9,i10);
  }
  *How=1;
 }
 return 1;
}
