#include <alloc.h>
#include <graphics.h>
#include <string.h>
#include <wnd_asm.h>
extern char Mouse,buttons;
extern int hor_position,ver_position;
//extern unsigned bmPos; extern char far  *bmForSpl;
DOPINPUTFUN DOP_INPUT; // Дополнительный контроль ввода для Geting_Text

unsigned char Thank;
// xxxx xxx1 - Нет ввода
// xxxx xx1x - Автовыполнение
// xxxx x1xx - Спасибо/Отказ
// xxxx 1xxx - Выход через ENTER(в.т.ч.по Esc_Key); иначе ESC
// xxx1 xxxx - Не сохранять экран
// xx1x xxxx - Продолжить/Закончить
// x1xx xxxx -
// 1xxx xxxx -
static MODE Serv=0x00; //for Get_Many_Text
// xxxx xxx1 UP/DOWN
// xxxx xx1x Обойти/Выполнить

/***************************************************************************
 *   Данная подпрограмма выводит текст сообшения пользователю и ждет ввода *
 * ( ESC, ENTER ) для продолжения работы. Текст сообщения находится в ст-  *
 * руктуре CASE. Тексты подсказок могут выводится в любое место экрана     *
 * Cоздаваемые подпрограммой окна помогут выдавать конктекстно-независимые *
 * подсказки в реальном режиме работы.                                     *
 *                                                                         *
 * Описание переменных:                                                    *
 * fn - стуктура, содержащая текст подсказки и размер окна                 *
 ***************************************************************************/
#define  FILL_COLOR   WHITE       //Цвет фона меню
#define  MENU_COLOR   BLACK       //Цвет текста и рамки меню
#define  LEN_TEXT     28	  //Длина текста сообщения
#define  LIGHT_COLOR  LIGHTRED    //Цвет выделения текста
#define  CURSOR_COLOR BLUE        //Цвет текста курсора меню

void Message_Text( CASE *fn ) {
 void far  *bm; unsigned ii;
 KEY  sim;        //Символ буфера клавиатуры
 char *function_string="$ESC$ Отказ  $ENTER$ Переход к дальнейшим действиям";
 KEY Bar_Keys[]={ESC,ENTER};
 int Pos_Keys[]={15,103,399};
 char Num_Keys=2;

 Thank&=0xf7; CURSOR_OFF();
 if (!(Thank&0x10)) {
  ii=imagesize( fn->x1, fn->y1, fn->x2+8, fn->y2+8 );
  bm= malloc( ii );
  if (bm == NULL)  Close_System(); //  bm=&bmForSpl[bmPos]; bmPos+=ii;
  getimage( fn->x1, fn->y1, fn->x2+8, fn->y2+8, bm ); //Сохранение изображ.
 }
 setfillstyle( SOLID_FILL, FILL_COLOR ); //Установка заполнителя и цвета
 bar( fn->x1, fn->y1, fn->x2, fn->y2 ); //Заполнение
 setcolor( MENU_COLOR );   //Устанавливаем цвет рамки меню
 rectangle( fn->x1+2, fn->y1+2, fn->x2 -2, fn->y2 -2 ); //Создаем
 rectangle( fn->x1+4, fn->y1+4, fn->x2 -4, fn->y2 -19 ); //рамку
 rectangle( fn->x1+4, fn->y2 -17, fn->x2 -4, fn->y2 -4 );
 CURSOR_ON();
 // Создание тени окна
 Chand( fn->x1+8, fn->y2+1, fn->x2+8, fn->y2+8, DARKGRAY, ANDI );
 Chand( fn->x2+1, fn->y1+5, fn->x2+8, fn->y2, DARKGRAY, ANDI );
 Fun_Bar( function_string );
 Print( fn->x1+12, fn->y1+12, MENU_COLOR, LIGHT_COLOR, fn->help );
 Print( ((fn->x2+fn->x1)>>1) - LEN_TEXT, fn->y2 -14, CURSOR_COLOR, LIGHTMAGENTA, "$С$пасибо" );
 // Выводим курсор выбора
 Chand( ((fn->x2+fn->x1)>>1) - LEN_TEXT - 3, fn->y2 - 15,
	((fn->x2+fn->x1)>>1) + LEN_TEXT + 3, fn->y2 - 6, CURSOR_COLOR, XORI );
 if (Thank&0x02) { //AUTO ON
  Thank&=0xfd; goto RET_MES;
 }
 Sound( 2000, 10 ); //Выдача звукового сигнала, для предупреждения пользователя
 //Цикл до отказа пользователя от работы с меню
 while (1) {
  if (Mouse) {
   ii=1;
   while (ii) {
    if (Hit_Key()) ii=0;
    ms_state ();
    if (buttons==0x01) { //Left
     if (Fun_Bar_Keys (Num_Keys,Bar_Keys,Pos_Keys)) ii=0;
     if (ii) {
      buttons=0x00; while (ms_release()<1); // до отпускания кнопки мыши
      if (ver_position>=fn->y2 - 15 && ver_position<=fn->y2 - 6 &&
	  hor_position>=((fn->x2+fn->x1)>>1) - LEN_TEXT - 3 &&
	  hor_position<=((fn->x2+fn->x1)>>1) + LEN_TEXT + 3)
       ii=ENTER;
      else ii=ESC;
      Set_Key (1,ii);
      ii=0;
     }
    }
   }
  }
  sim = Get_Key();
  if (sim!=ESC) Thank|=0x08;
  if ( (sim == ESC) || (sim == ENTER) || (Find_Key("cCсС",sim)!=NO_SIM) )
   break;
 }
RET_MES:
 if (!(Thank&0x10)) { CURSOR_OFF();
  putimage( fn->x1, fn->y1, bm, COPY_PUT ); farfree( bm ); CURSOR_ON();//bmPos-=ii;
 }
 else Thank&=0xEF; return;
}

void Help_Text( HELP *fn ) {
 int i,j;
 Chand( fn->x1+8, fn->y2+1, fn->x2+8, fn->y2+8, DARKGRAY, ANDI );
 Chand( fn->x2+1, fn->y1+5, fn->x2+8, fn->y2, DARKGRAY, ANDI );
 CURSOR_OFF();
 setfillstyle( SOLID_FILL, FILL_COLOR ); //Установка заполнителя и цвета
 for (j=0;j<2;j++) bar( fn->x1, fn->y1, fn->x2, fn->y2 );  //Заполнение
 setcolor( MENU_COLOR );   //Устанавливаем цвет рамки меню
 rectangle( fn->x1+2, fn->y1+2, fn->x2 -2, fn->y2 -2 ); //Создаем
 rectangle( fn->x1+4, fn->y1+4, fn->x2 -4, fn->y2 -4 ); //рамку
 i=(fn->x1+fn->x2)/2; j=strlen(fn->title)*8;
 bar (i-j/2, fn->y1, i+j/2, fn->y1+10);  // Поле заголовка
 CURSOR_ON();
 Print( i-j/2+2, fn->y1+2, CURSOR_COLOR, LIGHT_COLOR, fn->title);
 Print( fn->x1+12, fn->y1+12, MENU_COLOR, LIGHT_COLOR, fn->text);
 return;
}



/***************************************************************************
 *   Данная подпрограмма выводит тексты подсказок, которые находятся в ст- *
 * руктуре CASE. Тексты подсказок могут выводится в любое место экрана *
 * Cоздаваемые подпрограммой окна помогут выдавать конктекстно-независимые *
 * подсказки в реальном режиме работы.                                     *
 *                                                                         *
 * Описание переменных:                                                    *
 * fn - стуктура, содержащая текст подсказки и размер окна                 *
 ***************************************************************************/
CASE *Answer; // Дополнительная помощь; Thank&0x20 is ON
#define  FILL_COLOR1   GREEN        //Цвет фона меню
#define  MENU_COLOR1   WHITE        //Цвет текста и рамки меню
#define  LIGHT_COLOR1  LIGHTRED     //Цвет выделения текста
#define  CURSOR_COLOR1 BLACK        //Цвет текста курсора меню

char Answ_Menu( CASE *fn ) {
 void far  *bm; unsigned ii;
 KEY  sim;      //Символ буфера клавиатуры
 char swit = 0; //Указатель положения курсора : 0 - ДА, 1 - НЕТ
 CASE help = {  10, 10,32+8*40,70, 0,12,0, "",
  "$Да$  - подтверждение указанного действия,&"
  "$Нет$ - отмена"
 };
 //Текст функциональной строки
 char *function_string = "$ESC$ Отказ  $F1$ Подсказка  $ENTER$ Подтверждение";
 KEY Bar_Keys[]={ESC,F1,ENTER};
 int Pos_Keys[]={15,103,215,375};
 char Num_Keys=3;
 Thank&=0xf7;
 CURSOR_OFF();
 ii=imagesize( fn->x1, fn->y1, fn->x2+8, fn->y2+8 );
 bm = malloc(ii  ); // bm=&bmForSpl[bmPos]; bmPos+=ii;
 if  ( bm == NULL )  Close_System();
 help.x1 += fn->x1;  //Позиционируем окно подсказки относительно
 help.x2 += fn->x1;  //текущего окна
 help.y1 += fn->y1;
 help.y2 += fn->y1;
 getimage( fn->x1, fn->y1, fn->x2+8, fn->y2+8, bm ); //Сохранение изображ.
 setfillstyle( SOLID_FILL, FILL_COLOR1 ); //Установка заполнителя и цвета
 bar( fn->x1, fn->y1, fn->x2, fn->y2 ); //Заполнение
 setcolor( MENU_COLOR1  );   //Устанавливаем цвет рамки меню
 rectangle( fn->x1+2, fn->y1+2, fn->x2 -2, fn->y2 -2 ); //Создаем
 rectangle( fn->x1+4, fn->y1+4, fn->x2 -4, fn->y2 -19 ); //рамку
 rectangle( fn->x1+4, fn->y2 -17, fn->x2 -4, fn->y2 -4 );
 CURSOR_ON();
 // Создание тени окна
 Chand( fn->x1+8, fn->y2+1, fn->x2+8, fn->y2+8, DARKGRAY, ANDI );
 Chand( fn->x2+1, fn->y1+5, fn->x2+8, fn->y2, DARKGRAY, ANDI );
 //Вывод подсказки пользователю о возможных комбинациях клавиш для работы
 Fun_Bar( function_string );
 Print( fn->x1+12, fn->y1+14, MENU_COLOR1 , LIGHT_COLOR1  , fn->help );
 Print( fn->x1+30, fn->y2 -14, CURSOR_COLOR1  , LIGHTRED, "$Д$а" );
 Print( fn->x2 -54, fn->y2 -14, CURSOR_COLOR1  , LIGHTRED, "$Н$ет" );
 // Выводим курсор выбора
 Chand( fn->x1+27, fn->y2 - 15, fn->x1+52, fn->y2 - 6, GREEN, XORI );
 //Цикл до отказа пользователя от работы с меню
 while (1) {
  if (Mouse) {
   ii=1;
   while (ii) {
    if (Hit_Key()) ii=0;
    ms_state ();
    if (buttons==0x01) { //Left
     if (Fun_Bar_Keys (Num_Keys,Bar_Keys,Pos_Keys)) ii=0;
     if (ii) {
      buttons=0x00; while (ms_release()<1); // до отпускания кнопки мыши
      if (ver_position>=fn->y2-15 && ver_position<=fn->y2-6) {
       if (hor_position>=fn->x1+27 && hor_position<=fn->x1+52)
	{ swit=0; Set_Key (1,ENTER); }
       else if (hor_position>=fn->x2-57 && hor_position<=fn->x2-27)
	{ swit=1; Set_Key (1,ESC); }
       ii=0;
      }
     }
    }
   }
  }
  sim = Get_Key();
  switch( sim ) {    //Анализ считаной клавиши
   case ESC: goto OUT;
   // Движение курсора между полями Да  и Нет
   case   TAB :   case  LEFT :   case S_TAB :   case RIGHT :
    Chand( fn->x1+27, fn->y2 - 15, fn->x1+52, fn->y2 - 6, GREEN, XORI );
    Chand( fn->x2-57, fn->y2 - 15, fn->x2-27, fn->y2 - 6, GREEN, XORI );
     //Курсор выбора
    swit ^= 1;  // Указатель позиции курсора сменить
   break;
   case ENTER :  Thank|=0x08;  swit += 10;   Set_Key( 1, ESC );  break;
   case    F1 :
    if (Thank&0x20) Message_Text (Answer);
    else Common_Menu( &help, &help, H_ELP );
    Fun_Bar( function_string );
   break;
   default : {
    if( Find_Key  ("lLдД",sim) != NO_SIM ) {
     swit = 0;  Set_Key( 1, ENTER ); }
    else if( Find_Key  ("yYнН",sim) != NO_SIM ) {
     swit = 1;  Set_Key( 1, ENTER );  }
   } // default
  } // switch
 }  // while
OUT: CURSOR_OFF(); putimage( fn->x1, fn->y1, bm, COPY_PUT ); //Востанавливаем изображение
 farfree( bm ); CURSOR_ON(); Thank&=0xdf;
 return( ((swit>2)? swit-10: 1) );
}

/***************************************************************************
 *   Данная подпрограмма выводит тексты подсказок, которые находятся в ст- *
 * руктуре CASE. Тексты подсказок могут выводится в любое место экрана     *
 * Cоздаваемые подпрограммой окна помогут выдавать конктекстно-зависимые   *
 * подсказки в реальном режиме работы.                                     *
 *                                                                         *
 * Описание переменных:                                                    *
 * fn - стуктура, содержащая текст подсказки и размер окна                 *
 ***************************************************************************/
#define  FILL_COLOR2   LIGHTBLUE   //Цвет фона меню
#define  MENU_COLOR2   YELLOW       //Цвет текста и рамки меню
#define  LIGHT_COLOR2  LIGHTMAGENTA //Цвет выделения текста
#define  CURSOR_COLOR2 YELLOW       //Цвет текста курсора меню
#define  COLOR_TEXT    LIGHTBLUE   //Цвет текста
#define  TEXT_CURSOR   GREEN
#define  BAR_CURSOR   BLUE

void Paint_Text( CASEI* );
void Out_Mess( CASEI* );
KEY *Alt_Keys;
char Kol_Punct;

char MultiMode=0x00; // 1, если в режиме ввода нескольких полей

void Get_Many_Text( VIDI *fn, CASEI *wn ) {
 void far  *bm; unsigned ii;
 KEY  sim;      //Символ буфера клавиатуры
 CASE help = {  9, -15,31+8*41,50, 0,12,0, "",
  "$Спасибо$ - подтверждение введенных данных,&"
  "$Отказ  $ - отменить все изменения"
 };
 int i,j=0; char kol_zagol;
 //Текст функциональной строки
 char *function_string =
  "$ESC$ Отказ  $TAB$ Вперед  $SHIFT-TAB$ Назад  $ENTER$ Подтверждение  $F1$ Подсказка";
 KEY Bar_Keys[]={ESC,TAB,S_TAB,ENTER,F1};
 int Pos_Keys[]={15,103,199,335,503,608};
 char Num_Keys=5,flag,Curs=0x02;
 int Y1,Y2,X11,X12,X21,X22,k;
 Y1=fn->y2-15; Y2=fn->y2-6;    // Y-координаты строки кнопок
 X11=fn->x1+27; X12=fn->x1+89; // "Спасибо"
 X21=fn->x2-73; X22=fn->x2-27; // "Отказ"
 MultiMode=0x01; CURSOR_OFF();
 if (!(Thank&0x10)) {
  ii=imagesize( fn->x1, fn->y1, fn->x2+8, fn->y2+8 );
  bm = malloc( ii );
  if  ( bm == NULL )  Close_System(); //  bm=&bmForSpl[bmPos]; bmPos+=ii;
  getimage( fn->x1, fn->y1, fn->x2+8, fn->y2+8, bm ); //Сохранение изображ.
 }
 kol_zagol = (fn->kol & 0xF0)>>4;
 Kol_Punct = (fn->kol & 0x0F);
 help.x1 += fn->x1;  //Позиционируем окно подсказки относительно
 help.x2 += fn->x1;  //текущего окна
 help.y1 += fn->y2;
 help.y2 += fn->y2;
 Alt_Keys = fn->keys;

 setfillstyle( SOLID_FILL, FILL_COLOR2 ); //Установка заполнителя и цвета
 bar( fn->x1, fn->y1, fn->x2, fn->y2 ); //Заполнение
 rectangle(fn->x1, fn->y1, fn->x2, fn->y2);
 setcolor( MENU_COLOR2  );   //Устанавливаем цвет рамки меню
 rectangle( fn->x1+2, fn->y1+2, fn->x2 -2, fn->y2 -2 ); //Создаем
 rectangle( fn->x1+4, fn->y1+4, fn->x2 -4, fn->y2 -19 ); //рамку
 rectangle( fn->x1+4, fn->y2 -17, fn->x2 -4, fn->y2 -4 );
 setfillstyle( SOLID_FILL, MENU_COLOR2 );
 bar( fn->x1+8, fn->y1+8, fn->x2 - 8, fn->y1+ kol_zagol*12 +9 );
 CURSOR_ON();
 Print( fn->x1+12, fn->y1+14, COLOR_TEXT, LIGHT_COLOR1, fn->title );
 Print( fn->x1+30, fn->y2 -14, CURSOR_COLOR2  , LIGHT_COLOR2, "$С$пасибо" );
 Print( fn->x2 -70, fn->y2 -14, CURSOR_COLOR2  , LIGHT_COLOR2, "$О$тказ" );
 Chand( fn->x1+8, fn->y2+1, fn->x2, fn->y2+8, DARKGRAY, ANDI );
 Chand( fn->x2+1, fn->y1+5, fn->x2+8, fn->y2, DARKGRAY, ANDI );
 Thank&=0xf7; // по умолчанию - ESC
 for( i = 0; i < Kol_Punct; i++ ) {
  (wn+i)->x1 += fn->x1;
  (wn+i)->x2 += fn->x1;
  (wn+i)->y1 += fn->y1+ kol_zagol*12 +15;
  (wn+i)->y2 += fn->y1+ kol_zagol*12 +15;
  (wn+i)->zam=0;
 }
start:
 for( i = 0; i < Kol_Punct; i++ ) {
  Paint_Text( (wn+i) );
  Set_Insert_Key( 1, ESC );
  Get_Ich_Text( (wn+i), i );
 }
 if (Serv&0x02) {   Serv&=0xfd;   goto end; }
 if (Thank&0x01) { // Переход на Спасибо если нет ввода
  Curs=0x00; i=Kol_Punct; Fun_Bar (function_string); goto CYCLE; }
next:
 do {
  i = j;
  j = Get_Ich_Text( (wn+i), i );
  if (j==0xff) { // Обработать щелчок мышью
   flag=0x00; // Нормальное вхождение, иначе из цикла ниже
PRESS_MOUSE:
   if (hor_position>=X11 && ver_position>=Y1 &&
       hor_position<=X12 && ver_position<=Y2) {//Спасибо
    j=Kol_Punct;
    if (flag && Curs==0x00) { Thank|=0x08; Set_Key (1,ENTER); }
   }
   else if (hor_position>=X21 && ver_position>=Y1 &&
       hor_position<=X22 && ver_position<= Y2) {//Отказ
    j=Kol_Punct+1;
    if (flag && Curs==0x01) { Set_Key (1,ESC); }
   }
   else {
    for (k=0; k<Kol_Punct; k++) {
     if (hor_position>=(wn+k)->x1 && ver_position>=(wn+k)->y1 &&
	 hor_position<=(wn+k)->x2 && ver_position<=(wn+k)->y2) {
      j=k;
      goto next; // Щелчок по другому полю
     }
    }
    if (flag) break;
    j=i; goto next; // Щелчок в "левом месте"
   }
  }
  Fun_Bar (function_string);
  if (Thank&0x02) { Serv|=0x02; goto start; }
 } while( j < Kol_Punct );
end:
 Curs=j-Kol_Punct;
 i = j;
 //Цикл до отказа пользователя от работы с меню
CYCLE:
 while( 1 ) { //Считывание клавиши
  Chand( (Curs?X21:X11), Y1, (Curs?X22:X12), Y2, BAR_CURSOR, XORI );
  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); // до отпускания кнопки мыши
    Chand( (Curs?X21:X11), Y1, (Curs?X22:X12), Y2, BAR_CURSOR, XORI );
    flag=0x01; goto PRESS_MOUSE;
   }
  }
KEYBOARD: sim = Get_Key();
  Chand( (Curs?X21:X11), Y1, (Curs?X22:X12), Y2, BAR_CURSOR, XORI );
  switch( sim )  {   //Анализ считаной клавиши
   case ESC: case ALT_J: goto OUT;
   case DOWN: case RIGHT : case   TAB :
    i++; Curs^=0x01;
    if (i==Kol_Punct+2) {  j=0; goto next;  }
   break;
   case UP:   case LEFT  :   case S_TAB :
    i--; Curs^=0x01;
    if (i<Kol_Punct) { j=i; goto next; }
   break;
   case ENTER : case ALT_C: Thank|=0x08; Set_Insert_Key( 1,ESC ); break;
   case F1 :
    Common_Menu( &help, &help, H_ELP );
    Fun_Bar( function_string );
    Clear_Buf(); //!!! Не переходим к подсказкам об отдельных полях
   break;
   default:
    ii=Find_Key ("cCсСjJоО",sim);
    if (ii!=NO_SIM) Set_Key( 1, (ii?ESC:ENTER) );
    for ( ii = 0; *(Alt_Keys+ii); ii++ ) if( *(Alt_Keys+ii) == sim ) {
     j=ii; goto next;
    }
   break;
  } // switch
 }  // while
OUT:
 if (i==Kol_Punct) Thank|=0x04;
 else (Thank&=0xFB);
 for( i = 0; i < Kol_Punct; i++ ) {
  (wn+i)->x1 -= fn->x1; (wn+i)->x2 -= fn->x1;
  (wn+i)->y1 -= fn->y1+ kol_zagol*12 +15;
  (wn+i)->y2 -= fn->y1+ kol_zagol*12 +15;
 }
 CURSOR_OFF();
 if (!(Thank&0x10)) {
  putimage( fn->x1, fn->y1, bm, COPY_PUT ); //Востанавливаем изображение
  farfree( bm );//  bmPos-=ii;
 }
 CURSOR_ON();
 Thank&=0xec; // Разрешаем редактирование и сохранение
	      // Запрещаем автовыполнение
 MultiMode=0x00; return;
}


static short
 Light_Curs  = 0,    Curs_Ins = 0,     Len = 0,     Sdvig = 0,
 Curs_Pos = 0,	     Fild_Len = 0,     Max_Len_St = 0,     Current = 0;
static KEY  Sim;
char *Strin,  *St_Pos;

#define TEXT  YELLOW
#define LIGHT LIGHTRED
void Paint_Text( CASEI *wnd ) {
 //strcpy( (text + fn->color2), text );
 Print( wnd->x1+11, wnd->y1+12, TEXT, LIGHT, wnd->name );
 Print( wnd->x1+11, wnd->y1+12, TEXT, LIGHT, wnd->name );
 //Установление поля вывода
 CURSOR_OFF();
 if (!(Thank&0x01)) {
  setfillstyle( SOLID_FILL, YELLOW );
  bar( wnd->x2 - 18, wnd->y2 - 18, wnd->x2 - 8, wnd->y2 - 8 );
  setcolor( LIGHTBLUE );
  line( wnd->x2 - 13, wnd->y2 - 17, wnd->x2 - 13, wnd->y2 - 9 );
  line( wnd->x2 - 13, wnd->y2 - 9, wnd->x2 - 10, wnd->y2 - 12 );
  line( wnd->x2 - 16, wnd->y2 - 12, wnd->x2 - 13, wnd->y2 - 9 );
  if( Fild_Len < wnd->color2 ) {
   bar( wnd->x2 - 32, wnd->y2 - 18, wnd->x2 - 20, wnd->y2 - 8 );
   line( wnd->x2 - 31, wnd->y2 - 13, wnd->x2 - 21, wnd->y2 - 13 );
   line( wnd->x2 - 24, wnd->y2 - 16, wnd->x2 - 21, wnd->y2 - 13 );
   line( wnd->x2 - 24, wnd->y2 - 10, wnd->x2 - 21, wnd->y2 - 13 );
  }
 }
 setfillstyle( SOLID_FILL, LIGHTMAGENTA );
 bar( wnd->x1+8, wnd->y2 - 18, wnd->x2 - 20 - Sdvig, wnd->y2 - 8 );
 CURSOR_ON();return;
}

char Get_Ich_Text( CASEI *fn, char position ) {
 char *Inp_Bar="$F1$ Справка  $TAB$ Вперед  $SHIFT-TAB$ Назад  $ENTER$ Ввод  $Scroll Lock$ Рус/Лат",
      *Out_Bar="$F1$ Справка  $TAB$ Вперед  $SHIFT-TAB$ Назад";
 KEY  All_Bar_Keys[2][4]={  {F1,TAB,S_TAB,ENTER},  {F1,TAB,S_TAB,0xffff} };
 int  All_Pos_Keys[2][5]={ {15,111,207,343,431}, {15,111,207,335,0xffff} };
 char  All_Num_Keys[2]={4,3};
 static KEY far *Bar_Keys=All_Bar_Keys[Thank&0x01];
 static int far *Pos_Keys=All_Pos_Keys[Thank&0x01];
 static char far Num_Keys=All_Num_Keys[Thank&0x01];
 int i;                         //Переменная цикла
 char flag = 0,F1_Press=0x00;
 char *text = fn->Data;
 Strin  = text;
 St_Pos = Strin;
 Fild_Len   = fn->color1; //- 2;
 Max_Len_St = fn->color2; //- 3;
 Current = Curs_Ins  = Sdvig = Curs_Pos = Light_Curs = 0;
 Len = strlen( text );
 // Fild_Len=Len-2; // (+)
 //   fn->color2=Len;  //(+)
 if ( Fild_Len < fn->color2 ) {
  Sdvig = 14; Fild_Len -= 2;
 }
 Fun_Bar(Thank&0x01?Out_Bar:Inp_Bar);
 //strcpy( (text + fn->color2), text );
 Chand( fn->x1+10+Light_Curs, fn->y2 - 11 - Curs_Ins, fn->x1+18+Light_Curs, fn->y2 - 9,
   TEXT_CURSOR, XORI ); //Текстовый Курсор
 Out_Mess( fn );
 Set_Insert_Key( 1, END );
 Thank&=0xf7; //ESC on
 //Цикл до отказа пользователя от работы с меню
 while( 1 )  {
  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); // до отпускания кнопки мыши
    position=0xff;
    goto OUT_WITHOUT_POS;
   }
  }
KEYBOARD:  Sim = Get_Key(); //Считывание клавиши
  switch( Sim )  {   //Анализ считаной клавиши
   case ALT_J:
    if (MultiMode) { position=Kol_Punct+1;  Set_Key (2,ESC,ESC); }
   break;
   case ALT_C:
    if (MultiMode) { position=Kol_Punct; Set_Key (2,ENTER,ALT_C); }
   break;
   case PSEUDO: if (MultiMode) {
    flag=1; goto OUT; } // Выход, не сбрасывающий флаг помощи
   case ESC:
    for( ; ( (Len>=1) && (Strin[ Len-1 ] == ' ') ); Len-- ) Strin[ Len-1 ] = '\0';
    F1_Press=0x00; goto OUT;
   case    F1 : {
    CASE Help;
    Help.help = fn->help;
    Help.x1 = fn->x1;
    Help.x2 = fn->x1+fn->help_x;
    Help.y1 = fn->y1+ fn->help_y1;
    Help.y2 = Help.y1+fn->help_y2;
    Common_Menu( &Help, &Help, H_ELP ); //Вызов подсказки
    Fun_Bar(Thank&0x01?Out_Bar:Inp_Bar);
    if (MultiMode) F1_Press=0x01;
   break; }
   case  DOWN:   case   TAB :
    position++;
    if ( position > Kol_Punct+1 ) position = 0;
    flag = 1;
    if (MultiMode && F1_Press) {
     if (position>=Kol_Punct) position=0;
     Set_Insert_Key (2,PSEUDO,ENTER);
     break;
    }
    if (Thank&0x02) Set_Key( 1, ENTER );// Выполнение
    else Set_Key( 1, ESC );          //или выход
    Serv&=0xfe; // !!!
   break;
   case UP:   case S_TAB :
    if( position )  position--;
    else  position = Kol_Punct+1;
    flag = 1;
    if (MultiMode && F1_Press) {
     if (position>=Kol_Punct) position=Kol_Punct-1;
     Set_Insert_Key (2,PSEUDO,ENTER);
     break;
    }
    if (Thank&0x02) Set_Key( 1, ENTER );// Выполнение
    else Set_Key( 1, ESC );             //или выход
    Serv|=0x01; // !!!
   break;
   case  LEFT :
    if (!(Thank&0x01)) {
     if ( Light_Curs >= 0 ) {
      if( Current && !Light_Curs ) Current--;
      else Light_Curs -= 8;
      St_Pos--;
      Curs_Pos--;
      if ( Curs_Pos < 0 ) {
       St_Pos = Strin;
       Curs_Pos = 0;
       Light_Curs = 0;
      }
      Out_Mess( fn );
     }
    }
    else Set_Key (1,S_TAB);
   break;
   case RIGHT :
    if (!(Thank&0x01)) {
     if ( Curs_Pos < Len ) {
      if ( Light_Curs == (Fild_Len << 3) ) Current++;
      else Light_Curs += 8;
      St_Pos++;
      Curs_Pos++;
      Out_Mess( fn );
     }
    }
    else Set_Key (1,TAB);
   break;
   case  HOME :
    Light_Curs = 0;
    Curs_Pos = 0;
    St_Pos = Strin;
    Current = 0;
    Out_Mess( fn );
   break;
   case   END :
    Curs_Pos = Len;
    St_Pos = (Strin + Len);
    Current = ((Len - Fild_Len > 0)? Len - Fild_Len: 0 );
    Light_Curs = ((Len - Current) << 3);
    Out_Mess( fn );
   break;
   case   INS :
    if (!(Thank&0x01)) {  Curs_Ins ^= 6; Out_Mess( fn ); }
   break;
   case   DEL :  case    BS :
    if (!(Thank&0x01)) {
     if ( Len > 0 ) {
      if ( (Sim == BS) ) {
       if ( Curs_Pos ) { St_Pos--; Curs_Pos--; }
       if ( (Light_Curs == 0) && Current ) {
	Current--;
	if( !Current ) Sim = DEL;
       }
       else {
	if( Light_Curs == 8 ) Sim = DEL;
	Light_Curs -= ((Light_Curs)? 8: 0);
       }
      }
      if ( Current || (Sim == DEL && Curs_Pos>=0 && Curs_Pos<Len) ||
       (Sim== BS && Light_Curs )) {
       Len--;
       for( i = (int)(St_Pos - Strin); i < Len; i++ )	Strin[i]=Strin[i+1];
       Out_Mess( fn );
      }
     }  // if
    }
   break;
// case START: position=Kol_Punct+4; Set_Key( 1, ESC );break; //!!!
   case ENTER :
    fn->zam=1;// Отметили этот пункт
    fn->sf(); // Выполнили внешнюю функцию
    fn->zam=0; // Сняли отметку
    Thank|=0x08;
    Set_Insert_Key (1,ESC);
//!!! position = Kol_Punct;
    flag = 1;
   break;
   default :
    for (i = 0; *(Alt_Keys+i); i++ )  if( *(Alt_Keys+i) == Sim ) {
     Chand( fn->x1+10+Light_Curs, fn->y2 - 11 - Curs_Ins,
      fn->x1+18+Light_Curs, fn->y2 - 9, TEXT_CURSOR, XORI );
     return( i );
    }
    if (!(Thank&0x01)) {
     if ( ((Len < fn->color2 - 1) || ((Len == fn->color2 - 1) && Curs_Ins))
      && (Curs_Pos < fn->color2-1) ) {
      if ( (Sim >= ' ') && (Sim < 255) ) {
       if ( !Curs_Ins ) {
	for (i=Len; i>St_Pos-Strin; i-- ) Strin[i]=Strin[i-1];
	Len++;
       }
       *(St_Pos++) = Sim;
       Curs_Pos++;
       if ( Curs_Pos > Len )  Len = Curs_Pos;
       if ( Light_Curs == (Fild_Len << 3) )  Current++;
       else  Light_Curs += 8;
       Out_Mess( fn );
      } // if
     }
     else {
      if ( fn->zam ) {
       //Вывод сообщения об ошибке
       //Common_Menu( (fn+1), (fn+1), E_RROR );
       //Fun_Bar("$ESC$ Отказ  $F1$ Справка  $ENTER$ Ввод  "
       //       "$BS$ Удаление  $ScrollLock$ Рус/Лат");
      } // if
     } // else
    } // if
   break;
  } // switch
 } // while
OUT: if (!flag) position = Kol_Punct+1;
OUT_WITHOUT_POS: Chand( fn->x1+10+Light_Curs, fn->y2 - 11 - Curs_Ins, fn->x1+18+Light_Curs, fn->y2 - 9,
  TEXT_CURSOR, XORI ); //Текстовый Курсор
 Strin[ Len ] = '\0';
 return( position );
}

void Out_Mess( CASEI *wnd ) {
 CURSOR_OFF();
 setfillstyle( SOLID_FILL, LIGHTCYAN); //LIGHTMAGENTA );
 bar( wnd->x1+8, wnd->y2 - 18, wnd->x2 - 20 - Sdvig, wnd->y2 - 8 );
 //!!! bar( wnd->x1+8, wnd->y2 - 18, wnd->x2 - 20 - Sdvig, wnd->y2 - 8 );
 if( Curs_Pos > Max_Len_St ) {
  setfillstyle( SOLID_FILL, LIGHTCYAN); //LIGHTMAGENTA );
  bar( wnd->x2 - 36, wnd->y2 - 18, wnd->x2 - 20, wnd->y2 - 8 );
 }
/* else if (!(Thank&0x01)) {
  setfillstyle( SOLID_FILL, LIGHTBLUE );
  bar( wnd->x2 - 33, wnd->y2 - 18, wnd->x2 - 19, wnd->y2 - 8 );
  setfillstyle( SOLID_FILL, YELLOW );
  bar( wnd->x2 - 32, wnd->y2 - 18, wnd->x2 - 20, wnd->y2 - 8 );
  setcolor( LIGHTBLUE );
  line( wnd->x2 - 31, wnd->y2 - 13, wnd->x2 - 21, wnd->y2 - 13 );
  line( wnd->x2 - 24, wnd->y2 - 16, wnd->x2 - 21, wnd->y2 - 13 );
  line( wnd->x2 - 24, wnd->y2 - 10, wnd->x2 - 21, wnd->y2 - 13 );
 } */
 setcolor( BLACK );
 Strin[ Len ] = '\0';
 Sim = Strin[ Current + Fild_Len ];
 Strin[ Current + Fild_Len ] = '\0';
 outtextxy( wnd->x1+10, wnd->y2 - 16, (Strin + Current) );
 CURSOR_ON();
 Strin[ Current + Fild_Len ] = Sim;
 Chand (wnd->x1+10+Light_Curs, wnd->y2 - 11 - Curs_Ins,
	wnd->x1+18+Light_Curs, wnd->y2 - 9, TEXT_CURSOR, XORI );
 return;
}

void Out( MENU *wnd ) {
 CURSOR_OFF();
 setfillstyle( SOLID_FILL, LIGHTMAGENTA );
 bar( wnd->x1+8, wnd->y2 - 18, wnd->x2 - 20 - Sdvig, wnd->y2 - 8 );
 bar( wnd->x1+8, wnd->y2 - 18, wnd->x2 - 20 - Sdvig, wnd->y2 - 8 );
 if( Curs_Pos > Max_Len_St ){
  setfillstyle( SOLID_FILL, LIGHTMAGENTA );
  bar( wnd->x2 - 36, wnd->y2 - 18, wnd->x2 - 20, wnd->y2 - 8 );
 }
 else {
  setfillstyle( SOLID_FILL, LIGHTBLUE );
  bar( wnd->x2 - 33, wnd->y2 - 18, wnd->x2 - 19, wnd->y2 - 8 );
  setfillstyle( SOLID_FILL, YELLOW );
  bar( wnd->x2 - 32, wnd->y2 - 18, wnd->x2 - 20, wnd->y2 - 8 );
  setcolor( LIGHTBLUE );
  line( wnd->x2 - 31, wnd->y2 - 13, wnd->x2 - 21, wnd->y2 - 13 );
  line( wnd->x2 - 24, wnd->y2 - 16, wnd->x2 - 21, wnd->y2 - 13 );
  line( wnd->x2 - 24, wnd->y2 - 10, wnd->x2 - 21, wnd->y2 - 13 );
 }
 setcolor( BLACK );
 Strin[ Len ] = '\0';
 Sim = Strin[ Current + Fild_Len ];
 Strin[ Current + Fild_Len ] = '\0';
 outtextxy( wnd->x1+10, wnd->y2 - 16, (Strin + Current) );
 Strin[ Current + Fild_Len ] = Sim;
 CURSOR_ON();
 Chand( wnd->x1+10+Light_Curs, wnd->y2 - 11 - Curs_Ins,
	wnd->x1+18+Light_Curs, wnd->y2 - 9, TEXT_CURSOR, XORI );
 return;
}

/***************************************************************************
 *                                                                         *
 *   Данная подпрограмма организует панель_меню_выбора, используя при этом *
 * графический режим работы дисплея, и работая при этом с адаптерами не    *
 * ниже EGA.                                                               *
 *   Панель является полем однозначного автовыбора, и может использоваться *
 * при организации диалога с пользователем в реальном режиме работы. Реко- *
 * мендуется использовать в выпадающих меню и в расширенном меню действий. *
 *                                                                         *
 *   Используемые переменные:                                              *
 * wnd - указатель на структуру, информирующую подпрограмму о создаваемом  *
 *       окне                                                              *
 * fn  - указатель на структуру, имеющую расширенную информацию о создавае-*
 *       мом окне                                                          *
 *                                                                         *
 *   Более подробную информацию смотрите в файле WND_ASM.H                 *
 ***************************************************************************/
void Geting_Text( MENU *wnd, CASE *fn, char *text ) {

 // Резервируем память для сохранения изображения под окном
 void far  *bm; unsigned ii;
 //Количество строк заголовка окна
 CASE *vf = fn;                          //Сохранение текущего указателя fn
 int i;                         //Переменная цикла
 char *Text_Bar=
 "$ESC$ Отказ  $F1$ Справка  $ENTER$ Ввод  $BS$ Удаление  $ScrollLock$ Рус/Лат";
 KEY Bar_Keys[]={ESC,F1,ENTER,BS};
 int Pos_Keys[]={15,103,199,295,391};
 char Num_Keys=4;
 Strin  = text;
 St_Pos = Strin;
 Fild_Len   = fn->color1; // - 2;
 Max_Len_St = fn->color2; // - 3;
 Len = strlen( text ); // !!!
 // Light_Curs = min(Fild_Len,Len)*8;// !!!
 // Curs_Pos= Current = Light_Curs/8; //!!!
 if (Thank&0x02) Curs_Ins  = 6; // Всегда замена для автовыполнения
 else Curs_Ins  = 0;
 Sdvig = Curs_Pos= Current = Light_Curs=0;
 CURSOR_OFF();
 if (!(Thank&0x10)) {
  ii=imagesize( wnd->x1, wnd->y1, wnd->x2+8, wnd->y2+8 );
  bm = malloc( ii );
  if  ( bm == NULL )Close_System();  //Если невозможно выделить память, то выход
  //  bm=&bmForSpl[bmPos]; bmPos+=ii;
  getimage( wnd->x1, wnd->y1, wnd->x2+8, wnd->y2+8, bm ); //Сохранение
 }
 // !!! strcpy( (text + fn->color2), text );
 //Установление окна
 setfillstyle( SOLID_FILL, LIGHTBLUE ); //Установка заполнителя и цвета
 setcolor( YELLOW );   //Устанавливаем цвет рамки меню
 bar( wnd->x1, wnd->y1, wnd->x2, wnd->y2 );
 rectangle( wnd->x1+2, wnd->y1+2, wnd->x2 -2, wnd->y2 -2 ); //Создаем
 rectangle( wnd->x1+4, wnd->y1+4, wnd->x2 -4, wnd->y2 -4 ); //рамку
 //Выделение защищенной области окна
 setfillstyle( SOLID_FILL, YELLOW );
 bar( wnd->x1+8, wnd->y1+8, wnd->x2 - 8, wnd->y1+ wnd->kol*12 +9 );

 setfillstyle( SOLID_FILL, YELLOW );
 bar( wnd->x2 - 18, wnd->y2 - 18, wnd->x2 - 8, wnd->y2 - 8 );
 setcolor( LIGHTBLUE );
 line( wnd->x2 - 13, wnd->y2 - 17, wnd->x2 - 13, wnd->y2 - 9 );
 line( wnd->x2 - 13, wnd->y2 - 9, wnd->x2 - 10, wnd->y2 - 12 );
 line( wnd->x2 - 16, wnd->y2 - 12, wnd->x2 - 13, wnd->y2 - 9 );
 if( Len>0 && Fild_Len < fn->color2 ) {
  bar( wnd->x2 - 32, wnd->y2 - 18, wnd->x2 - 20, wnd->y2 - 8 );
  line( wnd->x2 - 31, wnd->y2 - 13, wnd->x2 - 21, wnd->y2 - 13 );
  line( wnd->x2 - 24, wnd->y2 - 16, wnd->x2 - 21, wnd->y2 - 13 );
  line( wnd->x2 - 24, wnd->y2 - 10, wnd->x2 - 21, wnd->y2 - 13 );
  Sdvig = 14;
  Fild_Len -= 2;
 }
 setfillstyle( SOLID_FILL, LIGHTMAGENTA ); //LIGHTCYAN
 bar( wnd->x1+8, wnd->y2 - 18, wnd->x2 - 20 - Sdvig, wnd->y2 - 8 );
 CURSOR_ON();

 //Создание тени окна
 Chand( wnd->x1+8, wnd->y2+1, wnd->x2+8, wnd->y2+8, DARKGRAY, ANDI );
 Chand( wnd->x2+1, wnd->y1+5, wnd->x2+8, wnd->y2, DARKGRAY, ANDI );
 //Вывод подсказки пользователю о возможных комбинациях клавиш для работы
 Fun_Bar(Text_Bar);
 // Вывод заголовка окна
 Print( wnd->x1+11, wnd->y1+12, LIGHTBLUE, LIGHTBLUE, wnd->keys );
 fn = vf;  //Востанавление указателя на начальную структуру

 if (Len < Fild_Len) Out (wnd); // !!!
 else Chand( wnd->x1+10+Light_Curs, wnd->y2 - 11 - Curs_Ins,
      wnd->x1+18+Light_Curs, wnd->y2 - 9, TEXT_CURSOR, XORI ); //Текстовый Курсор
 Thank&=0xF7; // По умолч.-ESC

 //Цикл до отказа пользователя от работы с меню
 while( 1 )  {  //Считывание клавиши
  if (Mouse) while (!Hit_Key()) {
   ms_state ();
   if (buttons==0x01) { //Left
    if (Fun_Bar_Keys (Num_Keys,Bar_Keys,Pos_Keys)) goto KEYBOARD;
   }
  }
KEYBOARD: Sim = Get_Key();
  switch( Sim ) {    //Анализ считаной клавиши
   case ESC: goto OUT;
   case    F1 : {
    Common_Menu( fn, fn, H_ELP ); //Вызов подсказки
    Fun_Bar(Text_Bar);
   break;  }
   case  LEFT : {
    if( Light_Curs >= 0 )  {
     if( Current && !Light_Curs ) Current--;
     else Light_Curs -= 8;
     St_Pos--;  Curs_Pos--;
     if( Curs_Pos < 0 ) {
      St_Pos = Strin;
      Curs_Pos = 0; Light_Curs = 0;
     }
     Out( wnd );
    }   break;
   }
   case RIGHT : {
    if( Curs_Pos < Len ) {
     if( Light_Curs == (Fild_Len << 3) ) Current++;
     else Light_Curs += 8;
     St_Pos++; Curs_Pos++;
     Out( wnd );
    }
    break;
   }
   case  HOME : {
    Light_Curs = 0;  Curs_Pos = 0;
    St_Pos = Strin;  Current = 0;
    Out( wnd );      break;
   }
   case   END : {
    Curs_Pos = Len; St_Pos = (Strin + Len);
    Current = ((Len - Fild_Len > 0)? Len - Fild_Len: 0 );
    Light_Curs = ((Len - Current) << 3);
    Out( wnd );
    break;
   }
   case   INS :
    if (!(Thank&0x02)) { // Нет автовыполнения
     Curs_Ins ^= 6; Out( wnd );
    }
   break;
   case   DEL :
   case    BS :
    if (Thank&0x02) break; // Автовыполнение
    else if( Len > 0 ) {
     if( (Sim == BS) ) {
      if( Curs_Pos ) { St_Pos--;  Curs_Pos--; }
      if( (Light_Curs == 0) && Current ) {
       Current--;
       if( !Current ) Sim = DEL;
      }
      else {
       if( Light_Curs == 8 ) Sim = DEL;
       Light_Curs -= ((Light_Curs)? 8: 0);
      }
     }
     if ( Current || (Sim == DEL && Curs_Pos>=0 && Curs_Pos<Len) ||
       (Sim== BS && Light_Curs )) {
      Len--;
      for( i = (int)(St_Pos - Strin); i < Len; i++ ) Strin[i] = Strin[i+1];
      Out( wnd );
     }
    }  // if
   break;
   case ENTER : {
    Thank|=0x08; // Было подтверждение ввода
    fn->sf(); // Extern function;
    break;
   }
   default: {
    if( ((Len < fn->color2 - 1) || ((Len == fn->color2 - 1) && Curs_Ins)) &&
      (Curs_Pos < fn->color2-1) ) {
     if( (Sim >= ' ') && (Sim < 255) ) {
      if (Thank&0x02) { // Автовыполнение
       DOP_INPUT (Strin, &Curs_Pos, &Sim);
      }
      if( !Curs_Ins ) {
       for( i = Len; i > St_Pos - Strin; i-- ) Strin[ i ] = Strin[ i - 1 ];
       Len++;
      }
      *(St_Pos++) = Sim;
      Curs_Pos++;
      if( Curs_Pos > Len ) Len = Curs_Pos;
      if( Light_Curs == (Fild_Len << 3) ) Current++;
      else Light_Curs += 8;
      Out( wnd );
     } // if
    }
    else {
     if( fn->zam ) { //Вывод сообщения об ошибке
      Common_Menu( (fn+1), (fn+1), E_RROR );
      Fun_Bar(Text_Bar);
     } // if
    } // else
   } // default
  } // switch
 } // while
OUT:
 for(; ((Len>=1) && (Strin[ Len-1 ] == ' ')); Len-- ) Strin[ Len-1 ] = '\0';
 Strin[ Len ] = '\0';
 fn = vf; //Установка указателя в начало
 CURSOR_OFF();
 if (!(Thank&0x10)) {
  putimage( wnd->x1, wnd->y1, bm, COPY_PUT ); //Востанавливаем изображение
  farfree( bm );//  bmPos-=ii;
 }
 else Thank&=0xef;
 Thank&=0xfd; //Запретить автовыполнение
 CURSOR_ON(); return;
}

//////////////////////////
void Esc_Key (void) { Thank|=0x08; Set_Key (1,ESC); return;}
