#include <alloc.h>
#include <graphics.h>
#include <dos.h>
#include <string.h>  /* for Init_Case_Wnd */
#include <wnd_asm.h>

//extern void Save_Scr(void);
extern unsigned char Thank;
//extern CASE far tabl12[];
extern void Set_Direction(void);
/***************************************************************************
 *   Данная подпрограмма работает с меню действий, которое задает основной *
 * режим работы программы                                                  *
 ***************************************************************************/
FUN  Ext_Function;  //Указатель на функцию для запуска независимых
		    //подпрограмм
MODE Flag_Help = 0;
MODE Kol_Help = 0;
extern char Mouse;
char buttons;     /* байт состояния/индикации кнопок   */
int hor_position; /* гоpизонтальная кооpдината куpсоpа */
int ver_position; /* веpтикальная кооpдината куpсоpа   */

// Верхняя строка меню: координаты по Y
#define MENU_LINE1 1
#define MENU_LINE2 10
// Цвета выделенного курсора и восстановления
#define CURSOR_ON_COLOR 8
#define CURSOR_OFF_COLOR 15

#define MAX_POINTS 3  // Макс.число пунктов гор.меню
static BLOCK  far   bar_menu[MAX_POINTS] = {
	 { 10,  MENU_LINE1, 72,  MENU_LINE2 },
	 { 82,  MENU_LINE1, 140, MENU_LINE2 },
	 { 150, MENU_LINE1, 204, MENU_LINE2 }
};
static char *MainHotKeys =  "xXчЧgGпПdDвВ" ;
static char Poits=MAX_POINTS;

void Menu_Deis( void ) {
   MODE poit = 0,   //Указатель на активный пункт меню
	klop;
   KEY sim;         //Символ принимаемый от пользователя
   // Размер блоков курсора
    // Подпрограммы обработки действий
    FUN  Pad_Menu[MAX_POINTS] = { Set_Direction, Help, Ret_In_Dos};
    // Тексты подсказок к действиям
    CASE Help_Bar [MAX_POINTS]= {
     { 140,100,500,165,0,0,0,"",
     "     Данный пункт запускает подпрограммы&"
     "$расчета$ регулировки стыковых зазоров&",Nop},
     { 140,100,500,165,0,0,0,"",
     "     Данный пункт предназначен для выдачи&"
     "помощи и информации о программе",Nop},
     { 140,100,500,165,0,0,0,"",
     "     Данный пункт предназначен для завер-&"
     "шения работы программы и выхода в DOS",Nop}
   };
   char *Menu_Deis_Bar=
 "$F1$ Справка  $ENTER$ Выбор  $HOME$ Начало  $END$ Конец  $LEFT$ Влево   $RIGHT$ Вправо";
   KEY Bar_Keys[6]={F1,ENTER,HOME,END,LEFT,RIGHT};
   int Pos_Keys[7]={15,111,215,319,397,501,613};
   char i,Num_Keys=6;

   Fun_Bar (Menu_Deis_Bar);
   while( 1 )  { // Цикл до тех пор пока пользователь не нажмет ESC
    Chan_Block_Xor( &bar_menu[ poit ], CURSOR_ON_COLOR, XORI );
    if (Mouse) while (!Hit_Key()) {
     ms_state ();
     if (buttons==0x01) { //Left
      if (Fun_Bar_Keys (Num_Keys,Bar_Keys,Pos_Keys)) goto KEYBOARD;
      if (ver_position>=MENU_LINE1 && ver_position<=MENU_LINE2) {
       buttons=0x00; while (ms_release()<1); // до отпускания кнопки мыши
       for (i=0; i<Poits; i++)
       if (hor_position>=bar_menu[i].X1 && hor_position<=bar_menu[i].X2) {
	Set_Key (1,(unsigned)MainHotKeys[i<<2]);
	goto KEYBOARD;
       }
      }
     }
    }
KEYBOARD:
    sim = Get_Key();
    Chan_Block_Xor( &bar_menu[ poit ], CURSOR_OFF_COLOR, XORI );
    switch( sim ) {
     case   ESC : Ret_In_Dos(); Fun_Bar(Menu_Deis_Bar); break;
     case    F1 :
      Chan_Block_Xor( &bar_menu[ poit ], CURSOR_ON_COLOR, XORI );
      Common_Menu( &Help_Bar[ poit ], &Help_Bar[ poit ], H_ELP );
      Chan_Block_Xor( &bar_menu[ poit ], CURSOR_OFF_COLOR, XORI );
      Fun_Bar(Menu_Deis_Bar);
     break;
     //case F2: Graph_Beg(); Clr_Scr(); Fun_Bar(Menu_Deis_Bar); break;
     case S_TAB :
     case LEFT  : if ( !poit-- ) poit = Poits-1;
     break;
     case   TAB :
     case RIGHT :
      poit++; if (poit==Poits) poit = 0;
     break;
     case  HOME : poit = 0; break;
     case   END : poit = Poits-1; break;
//     case  DOWN :
     case ENTER :
      Flag_Help = 1;
      Chan_Block_Xor( &bar_menu[ poit ], CURSOR_ON_COLOR, XORI );
      Pad_Menu[ poit ]();
      Chan_Block_Xor( &bar_menu[ poit ], CURSOR_ON_COLOR, XORI );
      Fun_Bar(Menu_Deis_Bar);
      Flag_Help = 0;
     break;
     case START : //Запуск внешней функции
      Flag_Help = 1;
      Chan_Block_Xor( &bar_menu[ poit ], CURSOR_ON_COLOR, XORI );
      Ext_Function();
      Chan_Block_Xor( &bar_menu[ poit ], CURSOR_ON_COLOR, XORI );
      Fun_Bar(Menu_Deis_Bar);
      Clr_Scr(); //!!!
      Flag_Help = 0;
     break;
//     case ALT_C: Clr_Scr ();break; //!!!
//     case ALT_S: Save_Scr ();break; //!!!
     default:
      klop = Find_Key( MainHotKeys, (char)sim );
      if ( klop == 100 ) break;
      else {  // Выбор действия по букве
       poit = klop;
       Set_Key (1,ENTER);
       // Flag_Help = 1; Chan_Block_Xor( &bar_menu[ poit ], CURSOR_ON_COLOR, XORI ); Pad_Menu[ poit ](); Chan_Block_Xor( &bar_menu[ poit ], CURSOR_ON_COLOR, XORI ); Fun_Bar(Menu_Deis_Bar); Flag_Help = 0;
      }
     break;
    } // switch
   }  // while
}  // Menu_Deis

/***************************************************************************
 *                                                                         *
 *   Данная подпрограмма организует панель_меню_выбора, используя при этом *
 * графический режим работы дисплея, и работая при этом с адаптерами не    *
 * ниже EGA.                                                               *
 *   Панель является полем многозначного  выбора, и  может  использоваться *
 * при организации диалога с пользователем в реальном режиме работы. Реко- *
 * мендуется использовать в выпадающих меню и в расширенном меню действий. *
 *                                                                         *
 *   Используемые переменные:                                              *
 * wnd - указатель на структуру, информирующую подпрограмму о создаваемом  *
 *       окне                                                              *
 * fn  - указатель на структуру, имеющую расширенную информацию о создавае-*
 *       мом окне                                                          *
 *                                                                         *
 *   Более подробную информацию смотрите в файле WND_ASM.H                 *
 ***************************************************************************/
void Case_Wnd( MENU *wnd, CASE *fn ) {
 // Резервируем память для сохранения изображения под окном
 void far  *bm; unsigned ii;
 //Количество строк заголовка окна
 int  text = (( wnd->kol >> 4 ) & 0xF)*12 +17;
 int  point = 0;                      //Указатель на текущ. строку
 int  hi = wnd->y1+text-1+point*11;   //Указатель на текущ. позицию курсора
 KEY  sim;                            //Текущий символ буфера клавиатуры
 CASE *vf = fn;                       //Сохранение текущего указателя fn
 int i,j;                               //Переменная цикла
 int X1=wnd->x1+8, X2=wnd->x2-7, YMAX=wnd->kol & 0xf;
 char *Case_Wnd_Bar=
  "$ESC$ Отказ  $F1$ Справка  $SPASEBAR$ Отметить  $ENTER$ Выбор  $DOWN$ Вниз  $UP$ Вверх";
 KEY Bar_Keys[]={ESC,F1,S_BAR,ENTER,DOWN,UP};
 int Pos_Keys[]={15,103,199,351,455,543,615};
 char Num_Keys=6;
 CURSOR_OFF();
 if (!(Thank&0x10)) {
  ii=imagesize( wnd->x1, wnd->y1, wnd->x2+8, wnd->y2+8 );
  bm=malloc (ii); //    bm=&bmForSpl[bmPos]; bmPos+=ii;
  if  ( bm == NULL ) //Если невозможно выделить память, то выход
    Close_System();  //из программы
  getimage( wnd->x1, wnd->y1, wnd->x2+8, wnd->y2+8, bm ); //Сохранение
 }                                                         //изображения
 setfillstyle( SOLID_FILL, LIGHTBLUE ); //Установка заполнителя и цвета
 bar( wnd->x1, wnd->y1, wnd->x2, wnd->y2 ); //Заполнение
 //Выделение защищенной области окна
 setfillstyle( SOLID_FILL, YELLOW );
 bar( wnd->x1+8, wnd->y1+8, wnd->x2 - 8, wnd->y1+text-8 );
 setcolor( YELLOW );   //Устанавливаем цвет рамки меню
 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 ); //рамку
 //Вывод всех пунктов меню
 for( i = 0; i <= YMAX; i++, fn++ ) {
  setcolor( fn->color1 );
  rectangle( wnd->x1+11, wnd->y1+text+i*11, wnd->x1+22, wnd->y1+7+text+ i*11 );
  if( fn->color2 ) {
   line( wnd->x1+11, wnd->y1+text+i*11, wnd->x1+22, wnd->y1+7+text + i*11 );
   line( wnd->x1+11, wnd->y1+7+text + i*11, wnd->x1+22, wnd->y1+text + i*11 );
  }
  Print( wnd->x1+30, wnd->y1+text + i*11, fn->color1, fn->color1, fn->name );
 }
 fn = vf;  //Востанавление указателя на начальную структуру
 //Повторный вывод первой строки меню для устранения ошибки работы
 Print( wnd->x1+30, wnd->y1+text, fn->color1, fn->color2, fn->name );
 fn = (vf + point); //Указатель на текущий выбор пользователя
 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(Case_Wnd_Bar);
 // Вывод заголовка окна
 Print( wnd->x1+11, wnd->y1+12, LIGHTBLUE, LIGHTBLUE, wnd->keys );
 Thank&=0xF7; // По умолч.-ESC
 //Цикл до отказа пользователя от работы с меню
 while ( 1 ) {
  hi = wnd->y1+text -1 + point*11;
  fn = (vf + point);
  Chand( X1, hi, X2, hi+9,( fn->color1 == YELLOW )? BLUE: DARKGRAY, XORI );
  if (Mouse) while (!Hit_Key()) {
   ms_state ();
   if (buttons==0x01) { //Left
    if (Fun_Bar_Keys (Num_Keys,Bar_Keys,Pos_Keys)) goto KEYBOARD;
    if (hor_position>=X1 && hor_position<=X2) {
     buttons=0x00; while (ms_release()<1); // до отпускания кнопки мыши
     for (i=0; i<=YMAX; i++) {
      j=wnd->y1+text+i*11;
      if (ver_position>=j && ver_position<=j+11) {
       if (i==point) Set_Key (1,S_BAR);
       else {  point=i; Set_Key (1,START); }
       goto KEYBOARD;
      }
     }
    }
   }
  }
KEYBOARD:
  sim = Get_Key();
  Chand( X1, hi, X2, hi+9, ( fn->color1 == YELLOW )? BLUE: DARKGRAY, XORI );
  switch( sim ) { //Анализ считаной клавиши
   case ESC: goto OUT;
   case START: break;
   case    F1 :
    Common_Menu( fn, fn, H_ELP ); //Вызов подсказки
    Fun_Bar(Case_Wnd_Bar);
   break;
   case  S_BAR:  //Нажатие пробела, выбор/невыбор пункта меню
    if ( fn->color1 == YELLOW ) {
     if( fn->zam ) setcolor( DARKGRAY );
     else setcolor( WHITE ); CURSOR_OFF();
     line( wnd->x1+11, hi+1, wnd->x1+22, hi+8 );
     line( wnd->x1+11, hi+1, wnd->x1+22, hi+8 );
     line( wnd->x1+11, hi+8, wnd->x1+22, hi+1 );
     fn->zam^= 1; CURSOR_ON();
     //Выполнить функцию, делающюю соответст. установки
     fn->sf();
     Fun_Bar(Case_Wnd_Bar);
    } break;
   case    UP :
    if ( !point-- ) point = YMAX;
   break;
   case  DOWN :
    point++;
    point %= (YMAX+1);
   break;
   case PAGE_UP:
    point = 0;
   break;
   case PAGE_DO:
    point = YMAX;
   break;
   case ENTER :  // Подтверждение выбора и выход
    Thank|=0x08; // ENTER есть
    Set_Key( 1, ESC );
    fn = vf; //Установка указателя в начало
    for( i = 0; i <= YMAX; i++, fn++ )  fn->color2 = fn->zam;
   break;
  } // switch
 } // while
OUT: fn = vf; //Установка указателя в начало
 //Совмещение произведенных установок
 for( i = 0; i <= YMAX; i++, fn++ ) {
  fn->zam = fn->color2;
  fn->sf();
 }
 fn = vf; //Установка указателя в начало
 if (!(Thank&0x10)) { CURSOR_OFF();
  putimage( wnd->x1, wnd->y1, bm, COPY_PUT ); //Востанавливаем изображение //    bmPos-=ii;
  farfree( bm );CURSOR_ON();  //При этом, освобождаем занятую память
 }
 else Thank&=0xef;
 return;
}

/***************************************************************************
 *                                                                         *
 *   Данная подпрограмма выводит тексты подсказок, которые находятся в ст- *
 * руктуре CASE. Тексты подсказок могут выводится в любое место экрана *
 * Cоздаваемые подпрограммой окна помогут выдавать конктекстно-независимые *
 * подсказки в реальном режиме работы.                                     *
 *                                                                         *
 * Описание переменных:                                                    *
 * fn - стуктура, содержащая текст подсказки и размер окна                 *
 ***************************************************************************/
void Common_Menu( CASE *fn, CASE *fn_help, MODE option ) {
 // Резервируем память для сохранения изображения под окном
 void far  *bm; unsigned ii;
 KEY  sim;        //Символ буфера клавиатуры
 int  hi;         //Переменная, которая будет содержать центр окна
 MODE swit = 0;   //Указатель положения курсора: 0 - СПАСИБО, 1 - СПРАВКА
 MODE fill_color,   //Цвет фона меню
      menu_color,   //Цвет текста и рамки меню
      cursor_color, //Цвет текста курсора меню
      light_color,  //Цвет выделения текста
      title_size;   //Размер текста заголовка
 int Y1=fn->y2 - 15, Y2=fn->y2 - 6;
 char *function_string,    //Текст функциональной строки
      *title_string;       //Текста заголовка
 KEY All_Bar_Keys[3][5]={
  {ESC,LEFT,RIGHT,TAB,S_TAB},
  {ESC,F1,LEFT,RIGHT,0xffff},
  {ESC,F1,LEFT,RIGHT,0xffff}
 };
 int All_Pos_Keys[3][6]={
  {15,103,199,311,431,599},
  {15,103,199,295,399,0xffff},
  {15,103,199,295,399,0xffff}
 };
 char All_Num_Keys[3]={5,4,4},Flag;
 KEY *Bar_Keys; int *Pos_Keys; char Num_Keys;
 Bar_Keys = All_Bar_Keys[option];
 Pos_Keys = All_Pos_Keys[option];
 Num_Keys= All_Num_Keys[option];
 switch( option ) {
  case  H_ELP:
   function_string ="$ESC$ Отказ  $LEFT$ Влево  $RIGHT$ Вправо  $TAB$ Следующее  $SHIFT-TAB$ Предыдущее";
   title_string    = "СПРАВКА";
   fill_color      = LIGHTBLUE;
   menu_color      = WHITE;
   title_size      = 70;
   light_color     = LIGHTRED;
   cursor_color    = YELLOW;
   break;
  case  E_RROR:
   function_string = "$ESC$ Отказ  $F1$ Справка  $LEFT$ Влево  $RIGHT$ Вправо";
   title_string    = "ОШИБКА";
   fill_color      = LIGHTRED;
   menu_color      = WHITE;
   title_size      = 60;
   light_color     = BLACK;
   cursor_color    = BLACK;
  break;
  case  W_ARNING:
   function_string ="$ESC$ Отказ  $F1$ Справка  $LEFT$ Влево  $RIGHT$ Вправо";
   title_string    = "ПРЕДУПРЕЖДЕНИЕ";
   fill_color      = YELLOW;
   menu_color      = BLACK;
   title_size      = 130;
   light_color     = LIGHTRED;
   cursor_color    = BLACK;
  break;
 } // switch
 CURSOR_OFF();
 ii=imagesize( fn->x1, fn->y1, fn->x2+8, fn->y2+8 ); //   bm=&bmForSpl[bmPos]; bmPos+=ii;
 bm = malloc( ii );
 if  ( bm == NULL ) Close_System();
 Kol_Help++;  //Показатель открытых окон справки
 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 );
 // Определение середины окна
 hi = int( ( fn->x1 + fn->x2 - title_size ) /2 );
 setfillstyle( SOLID_FILL, menu_color );
 bar( hi, fn->y1 + 2, hi + title_size, fn->y1 +12 );
 CURSOR_ON();
 Print( hi + 8, fn->y1 +3, 12, 12, title_string );
 // Создание тени окна
 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+18, menu_color, light_color, fn->help );
 Print( fn->x1+20, fn->y2 -14, cursor_color, LIGHTMAGENTA, "$С$пасибо" );
 Print( fn->x2 -90, fn->y2 -14, cursor_color, LIGHTMAGENTA, "$П$одсказка" );
 // Выводим курсор выбора
 Chand( fn->x1+18, Y1, fn->x1+75, Y2, BLUE, XORI );
 // Если это окно ошибки или предупреждения, то выдача звукового сигнала
 if( option ) Sound( 400, 40 );
 // Цикл до отказа пользователя от работы с меню
 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 && ver_position>=Y1 && ver_position<=Y2) {
      buttons=0x00; while (ms_release()<1); // до отпускания кнопки мыши
      if (hor_position>=fn->x1+18 && hor_position<=fn->x1+75)
       { ii=0; Set_Key (1,ESC); }
      else if (hor_position>=fn->x2-93 && hor_position<=fn->x2-15)
       { ii=0; Set_Key (1,F1); }
     }
    }
   }
  }
  sim = Get_Key();
  switch( sim ) {    //Анализ считаной клавиши
   case ESC: goto OUT;
   // Движение курсора между полями СПАСИБО и ПОДСКАЗКА
   case  LEFT :	 case RIGHT :
    Chand( fn->x1+18, Y1, fn->x1+75, Y2, BLUE, XORI );
    Chand( fn->x2-93, Y1, fn->x2-15, Y2, BLUE, XORI );
    swit ^= 1;  // Указатель позиции курсора сменить
   break;
   case  TAB:
    if ( option == H_ELP ) { //Если меню справки
     // Переход к следующей подсказке
     Set_Key( 3, ESC, ( Flag_Help )? DOWN: RIGHT, F1);
    }
    else  Set_Key( 1, RIGHT );
   break;
   case S_TAB :
    if ( option == H_ELP ) { //Если меню справки
     // Переход к предыдущей подсказке
     Set_Key( 3, ESC, ( Flag_Help )? UP: LEFT, F1 );
    }
    else  Set_Key( 1, LEFT );
   break;
   case ENTER :
    if ( swit ) { // Проверка на позицию курсора
     Help();
     Fun_Bar( function_string );
    }
    else Set_Key ( 1, ESC );
   break;
   case    F1 :
    if ( Kol_Help <= 2 ) {
     if ( !swit ) {
      Chand( fn->x1+18, Y1, fn->x1+75, Y2, BLUE, XORI );
      Chand( fn->x2-93, Y1, fn->x2-15, Y2, BLUE, XORI );
      swit ^= 1;
     }
     Flag=Flag_Help; Flag_Help=0x01;
     if ( option ) //Если это меню ошибки или предупреждения,
      //то выдача дополнительной справки
      Common_Menu( (fn_help+1), fn, H_ELP );
     else Help();
     Fun_Bar( function_string );
     Flag_Help=Flag;
    }
   break;
   case   'C' :	 case   'c' :	 case   'С' :	 case   'с' :
    Set_Key( 1, ESC ); break;
   case   'G' :	 case   'g' :	 case   'П' :	 case   'п' :
    Set_Key( 1, F1 ); break;
  } // switch
 }  // while
OUT: Kol_Help--;  //Счетчик открытых окон подсказки уменьшаем на 1
 CURSOR_OFF();
 putimage( fn->x1, fn->y1, bm, COPY_PUT ); //Востанавливаем изображение//   bmPos-=ii;
 farfree( bm );  //При этом, освобождаем занятую память
 CURSOR_ON(); return;
}

/***************************************************************************
 *                                                                         *
 *   Данная подпрограмма организует панель_меню_выбора, используя при этом *
 * графический режим работы дисплея, и работая при этом с адаптерами не    *
 * ниже EGA.                                                               *
 *   Панель является полем однозначного автовыбора, и может использоваться *
 * при организации диалога с пользователем в реальном режиме работы. Реко- *
 * мендуется использовать в выпадающих меню и в расширенном меню действий. *
 *                                                                         *
 *   Используемые переменные:                                              *
 * wnd - указатель на структуру, информирующую подпрограмму о создаваемом  *
 *       окне                                                              *
 * fn  - указатель на структуру, имеющую расширенную информацию о создавае-*
 *       мом окне                                                          *
 *                                                                         *
 *   Более подробную информацию смотрите в файле WND_ASM.H                 *
 ***************************************************************************/
/*
void Menu_Wnd( MENU *wnd, CASE *fn, MODE &point ) {
 // Резервируем память для сохранения изображения под окном
 void far  *bm; unsigned ii;
 int  hi = wnd->y1+6 + point*11; //Указатель на текущюю позицию курсора
 KEY  sim = 10,                  //Начальное значение буфера клавиатуры
      klop;                      //Сохранение текущего указателя fn
 CASE  *vf = fn;
 char *Menu_Wnd_Bar=
  "$ESC$ Отказ  $F1$ Справка  $DOWN$ Вниз  $UP$ Вверх  $LEFT$ Меню слева  $RIGHT$ Меню справа";
 KEY Bar_Keys[]={ESC,F1,DOWN,UP,LEFT,RIGHT};
 int Pos_Keys[]={15,103,199,287,367,503,653};
 char Num_Keys=6;
 int i,j,X1=wnd->x1+8, X2=wnd->x2-7;

 //   ii=FP_SEG(bmForSpl);   bm=MK_FP(ii,bmPos);
 CURSOR_OFF();
 ii=imagesize( wnd->x1, wnd->y1, wnd->x2+8, wnd->y2+8 );//   bmPos+=ii;
 bm = malloc(ii  );
 if  ( bm == NULL ) Close_System();
 getimage( wnd->x1, wnd->y1, wnd->x2+8, wnd->y2+8, bm ); //Сохранение изображения
 setfillstyle( SOLID_FILL, WHITE ); //Установка заполнителя и цвета
 bar( wnd->x1, wnd->y1, wnd->x2, wnd->y2 ); //Заполнение
 setcolor( BLACK );   //Устанавливаем цвет рамки меню
 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 ); //рамку
 //Вывод всех пунктов меню
 for( i = 0; i <= wnd->kol; i++, fn++ )
  Print( wnd->x1+11, wnd->y1+7 + i*11, fn->color1, fn->color2, fn->name );
 fn = vf;  //Востанавление указателя на начальную структуру
 //Повторный вывод первой строки меню для устранения ошибки работы
 Print( wnd->x1+11, wnd->y1+7, fn->color1, fn->color2, fn->name );
 fn = (vf + point); //Указатель на текущий выбор пользователя
 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 );
 Thank&=0xF7; // По умолч.-ESC
 //Вывод подсказки пользователю о возможных комбинациях клавиш для работы
 Fun_Bar(Menu_Wnd_Bar);
// Chand( wnd->x1+8, hi, wnd->x2-7, hi+9, (fn->color2)? YELLOW : WHITE, XORI );
 //Цикл до отказа пользователя от работы с меню
 while ( 1 ) {  //Считывание клавиши
  fn = (vf + point);
  hi = wnd->y1+6 + point*11;
  Chand( X1, hi, X2, hi+9, (fn->color2)? YELLOW : WHITE, XORI );
  if (Mouse) while (!Hit_Key()) {
   ms_state ();
   if (buttons==0x01) { //Left
    if (Fun_Bar_Keys (Num_Keys,Bar_Keys,Pos_Keys)) goto KEYBOARD;
    if (hor_position>=X1 && hor_position<=X2) {
     buttons=0x00; while (ms_release()<1); // до отпускания кнопки мыши
     for (i=0; i<= wnd->kol; i++) {
      j=wnd->y1+7+i*11;
      if (ver_position>=j && ver_position<=j+11) {
       point=i;
       Set_Key (1,ENTER);
       goto KEYBOARD;
      }
     }
    }
    if (ver_position>=MENU_LINE1 && ver_position<=MENU_LINE2) {
     buttons=0x00; while (ms_release()<1); // до отпускания кнопки мыши
     for (i=0; i<Poits; i++)
     if (hor_position>=bar_menu[i].X1 && hor_position<=bar_menu[i].X2) {
      Set_Key (2,ESC,(unsigned)MainHotKeys[i<<2]); // В другое меню
      goto KEYBOARD;
     }
    }
   }
  }
KEYBOARD:
  sim = Get_Key();
  Chand( X1, hi, X2, hi+9, (fn->color2)? YELLOW : WHITE, XORI );
  switch( sim ) {    //Анализ считаной клавиши
   case ESC: goto OUT;
   case  F1 :
    Common_Menu( fn, fn, H_ELP ); //Вызов подсказки
    Fun_Bar(Menu_Wnd_Bar);
   break;
   case  LEFT : Set_Key( 3, ESC, LEFT, ENTER ); //Переход в соседние меню
   break;
   case RIGHT : Set_Key( 3, ESC, RIGHT, ENTER ); break;
   case    UP :    if ( !point-- )  point = wnd->kol;   break;
   case  DOWN :    point++;  point %= (wnd->kol+1);   break;
   case PAGE_UP:   point = 0;   break;
   case PAGE_DO:    point = wnd->kol;   break;
   case PSEUDO: goto Ret_Wnd;
   case ENTER :
    Thank|=0x08; // ENTER есть
    if ( (vf+point)->color2 != LIGHTMAGENTA ) // Если исполнение возможно,
     (vf+point)->sf();   //то вызов соответств. функции
    Fun_Bar(Menu_Wnd_Bar);
   break;
   default   :
    klop = Find_Key( wnd->keys, (char)sim );
    if ( klop != NO_SIM ) {  //Если выбираемое поле доступно, то выполнение
     if ( (vf + klop)->color2 != LIGHTMAGENTA ) {
      point = klop;
      Set_Key( 1, ENTER );
     } // if
    } // else
   break; // default
  } // switch
 } // while
OUT:   fn = vf; CURSOR_OFF();
 putimage( wnd->x1, wnd->y1, bm, COPY_PUT ); CURSOR_ON();
Ret_Wnd:   farfree( bm );  //bmPos-=ii;
 return;
}
*/
/***************************************************************************
 *                                                                         *
 *   Данная подпрограмма организует панель_меню_выбора, используя при этом *
 * графический режим работы дисплея, и работая при этом с адаптерами не    *
 * ниже EGA.                                                               *
 *   Панель является полем однозначного автовыбора, и может использоваться *
 * при организации диалога с пользователем в реальном режиме работы. Реко- *
 * мендуется использовать в выпадающих меню и в расширенном меню действий. *
 *                                                                         *
 *   Используемые переменные:                                              *
 * wnd - указатель на структуру, информирующую подпрограмму о создаваемом  *
 *       окне                                                              *
 * fn  - указатель на структуру, имеющую расширенную информацию о создавае-*
 *       мом окне                                                          *
 *                                                                         *
 *   Более подробную информацию смотрите в файле WND_ASM.H                 *
 ***************************************************************************/
#define FILL_ICW LIGHTBLUE
#define PROTECT_ICW YELLOW
#define CURSOR_ICW BLUE

void Init_Case_Wnd( VID *wnd, CASE *fn, MODE *point ) {
 // Резервируем память для сохранения изображения под окном
 void far  *bm; unsigned ii;
// Количество строк заголовка окна
 int  text = (( wnd->kol >> 4 ) & 0xF)*12 +17;
 int  hi = wnd->y1+text-1+(*point)*11;   //Указатель на текущюю позицию курсора
 KEY  sim;                               //Текущий символ буфера клавиатуры
 CASE *vf = fn;                          //Сохранение текущего указателя fn
 int i,j,X1,X2,YMAX;
 int klop;                               //Значение текущей клавиши
 char *Init_Case_Wnd_Bar=
  "$ESC$ Отказ  $F1$ Справка  $ENTER$ Выбор  $DOWN$ Вниз  $UP$ Вверх";
 KEY Bar_Keys[]={ESC,F1,ENTER,DOWN,UP};
 int Pos_Keys[]={15,103,199,303,391,463};
 char Num_Keys=5;
 X1=wnd->x1+8; X2=wnd->x2-7; YMAX=(wnd->kol & 0xF);
 CURSOR_OFF();
 if (!(Thank&0x10)) {
  ii=imagesize( wnd->x1, wnd->y1, wnd->x2+8, wnd->y2+8 ); //    bm=&bmForSpl[bmPos]; bmPos+=ii;
  bm= malloc( ii );
  if  ( bm == NULL ) Close_System();//Если невозможно выделить память, то выход
  getimage( wnd->x1, wnd->y1, wnd->x2+8, wnd->y2+8, bm ); //Сохранение изображения
 }
 setfillstyle( SOLID_FILL, FILL_ICW ); //Установка заполнителя и цвета
 bar( wnd->x1, wnd->y1, wnd->x2, wnd->y2 ); //Заполнение
 //Выделение защищенной области окна
 setfillstyle( SOLID_FILL, PROTECT_ICW );
 bar( wnd->x1+8, wnd->y1+8, wnd->x2 - 8, wnd->y1+text-8 );
 setcolor( PROTECT_ICW );   //Устанавливаем цвет рамки меню
 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 ); //рамку
 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(Init_Case_Wnd_Bar);
 // Вывод заголовка окна
 Print( wnd->x1+11, wnd->y1+12, FILL_ICW, FILL_ICW, wnd->title );
 //Вывод всех пунктов меню
 for( i = 0; i <= YMAX; i++, fn++ ) {
  setcolor( fn->color1 ); CURSOR_OFF();
  ellipse( wnd->x1+16, wnd->y1+text+4+i*11, 0, 360, 6, 4 );
  if( fn->zam ) fillellipse( wnd->x1+16, wnd->y1+4+text+i*11, 4, 2 ); CURSOR_ON();
  Print( wnd->x1+30, wnd->y1+text + i*11, fn->color1, fn->color2, fn->name );
 }
 fn = vf;  //Востанавление указателя на начальную структуру
 //Повторный вывод первой строки меню для устранения ошибки работы
 Print( wnd->x1+30, wnd->y1+text, fn->color1, fn->color2, fn->name );
 fn = (vf + (*point)); //Указатель на текущий выбор пользователя

 Thank&=0xf7; // по умолчанию - ESC
 //Цикл до отказа пользователя от работы с меню
 while (1) {
  fn = (vf + (*point));
  hi = wnd->y1+text-1+ (*point)*11;
  Chand( X1, hi, X2, hi+9,( fn->color1 == PROTECT_ICW )? CURSOR_ICW: DARKGRAY, XORI );
  if (Mouse) while (!Hit_Key()) {
   ms_state ();
   if (buttons==0x01) { //Left
    if (Fun_Bar_Keys (Num_Keys,Bar_Keys,Pos_Keys)) goto KEYBOARD;
    if (hor_position>=X1 && hor_position<=X2) {
     buttons=0x00; while (ms_release()<1); // до отпускания кнопки мыши
     for (i=0; i<=YMAX; i++) {
      j=wnd->y1+text+i*11;
      if (ver_position>=j && ver_position<=j+11) {
       *point=i;
       Set_Key (1,ENTER);
       goto KEYBOARD;
      }
     }
    }
   }
  }
KEYBOARD:
  sim = Get_Key();
  Chand( X1, hi, X2, hi+9,( fn->color1 == PROTECT_ICW )? CURSOR_ICW: DARKGRAY, XORI );
  switch( sim ) {    //Анализ считаной клавиши
   case ESC: goto OUT;
   case    F1 :
    Common_Menu( fn, fn, H_ELP ); //Вызов подсказки
    Fun_Bar(Init_Case_Wnd_Bar);
   break;
   case    UP :   if ( !(*point)-- ) (*point) = YMAX; break;
   case  DOWN :   (*point)++; (*point) %= (YMAX+ 1); break;
   case PAGE_UP:  (*point) = 0;	 break;
   case PAGE_DO:  (*point) = YMAX; break;
   case ENTER :  //Если выбираемое поле доступно, то выполнение
    if ( (vf + (*point))->color2 != CURSOR_ICW ) {
     Thank|=0x08;
     fn = vf; //Установка указателя в начало
     i = 0;
     //Поиск активного пункта
     while( (fn + i)->zam != 1 ) i++;
     if ( i != (*point) ) { //Курсор стоит на актвном поле?
      (fn + i)->zam = 0;
      fn = ( vf + (*point));
      fn->zam = 1; CURSOR_OFF();
      setcolor( fn->color1 );
      setfillstyle( SOLID_FILL, fn->color1 );
      fillellipse( wnd->x1+16, wnd->y1+4+text+(*point)*11, 4, 2 );
      setcolor( FILL_ICW );
      setfillstyle( SOLID_FILL, FILL_ICW );
      fillellipse( wnd->x1+16, wnd->y1+4+text+i*11,  4, 2 ); CURSOR_ON();
     }
     (vf+(*point))->sf(); //Вызов соответствующей функции
    }
   break;
   default    :
    klop = Find_Key( wnd->keys, (char)sim );
    if ( klop == NO_SIM ) break;
    else {  //Если выбираемое поле доступно, то выполнение
     if ( (vf + klop)->color2 != CURSOR_ICW ) {
      *point = klop;
      Set_Key( 1, ENTER );
     } // if
    } // else
   break; // default
  } // switch
 } // while
OUT:
 fn = vf; //Установка указателя в начало
 if (!(Thank&0x10)) { CURSOR_OFF();
  putimage( wnd->x1, wnd->y1, bm, COPY_PUT ); //Востанавливаем изображение //    bmPos-=ii;
  farfree( bm ); CURSOR_ON(); //При этом, освобождаем занятую память
 }
 else Thank&=0xef;
 return;
}

/***************************************************************************
 *                                                                         *
 *   Данная подпрограмма организует панель_меню_выбора, используя при этом *
 * графический режим работы дисплея, и работая адаптерами не               *
 * ниже EGA.                                                               *
 *   Панель является полем многозадачного выбора, изменяя при выборе текс- *
 * товые сообщения меню. Может применяться в итерактивном режиме работы и  *
 * при организации диалога с пользователем в реальном режиме работы. Реко- *
 * мендуется использовать в выпадающих меню и в расширенном меню действий. *
 *                                                                         *
 *   Используемые переменные:                                              *
 * wnd - указатель на структуру, информирующую подпрограмму о создаваемом  *
 *       окне                                                              *
 * fn  - указатель на структуру, имеющую расширенную информацию о создавае-*
 *       мом окне                                                          *
 *                                                                         *
 *   Более подробную информацию смотрите в файле WND_ASM.H                 *
 ***************************************************************************/
/*
void Case_Wnd_Text( MENU *wnd, CASE *fn, CASE *alt ) {
 // Резервируем память для сохранения изображения под окном
 void far  *bm; unsigned ii;
 int  text = (( wnd->kol >> 4 ) & 0xF)*12 +17;
 int  point = 0;                      //Указатель на текущюю строку
 int  hi = wnd->y1+text-1+point*11;   //Указатель на текущюю позицию курсора
 KEY  sim;                            //Текущий символ буфера клавиатуры
 CASE *vf  = fn,                      //Сохранение текущего указателя fn
  *tal = alt;                     //Сохранение текущего указателя alt
 char *Case_Wnd_Text_Bar=
  "$ESC$ Отказ  $F1$ Справка  $SPASEBAR$ Отметить  $ENTER$ Выбор  $DOWN$ Вниз  $UP$ Вверх";
 KEY Bar_Keys[]={ESC,F1,S_BAR,ENTER,DOWN,UP};
 int Pos_Keys[]={15,103,199,351,455,543,615};
 char Num_Keys=6;
 int i,j,X1=wnd->x1+8, X2=wnd->x2-7, YMAX=(wnd->kol & 0xF);
 CURSOR_OFF();
 ii=imagesize( wnd->x1, wnd->y1, wnd->x2+8, wnd->y2+8 ); //   bm=&bmForSpl[bmPos]; bmPos+=ii;
 bm = malloc( ii );
 if  ( bm == NULL ) Close_System();
 getimage( wnd->x1, wnd->y1, wnd->x2+8, wnd->y2+8, bm ); //Сохранение
 Thank&=0xF7; // По умолч.-ESC
 setfillstyle( SOLID_FILL, LIGHTBLUE ); //Установка заполнителя и цвета
 bar( wnd->x1, wnd->y1, wnd->x2, wnd->y2 ); //Заполнение
 //Выделение защищенной области окна
 setfillstyle( SOLID_FILL, YELLOW );
 bar( wnd->x1+8, wnd->y1+8, wnd->x2 - 8, wnd->y1+text-8 );
 setcolor( YELLOW );   //Устанавливаем цвет рамки меню
 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 ); //рамку
 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(Case_Wnd_Text_Bar);
 // Вывод заголовка окна
 Print( wnd->x1+11, wnd->y1+12, LIGHTBLUE, LIGHTBLUE, wnd->keys );
 //Вывод всех пунктов меню
 for( i = 0; i <= YMAX; i++, fn++, alt++ ) {
  Print( wnd->x1+11, wnd->y1+text + i*11, fn->color1, fn->color1, fn->name );
  if ( fn->color1 == YELLOW ) {
   if( alt->zam ) Print( wnd->x1+20+strlen( fn->name )*8, wnd->y1+text + i*11, alt->color1, alt->color1, alt->name );
   else	Print( wnd->x1+20+strlen( fn->name )*8, wnd->y1+text + i*11, alt->color2, alt->color2, alt->help );
  }
 }
 fn = vf;  //Востанавление указателя на начальную структуру
 alt = tal;
 //Повторный вывод первой строки меню для устранения ошибки работы
 Print( wnd->x1+11, wnd->y1+text, fn->color1, fn->color2, fn->name );
 while (1) {
  Chand( X1, hi, X2, hi+9, ( fn->color1 == YELLOW )? BLUE: DARKGRAY, XORI );
  fn = (vf + point);
  alt = (tal + point);
  hi = wnd->y1+text-1+ point*11;
  if (Mouse) while (!Hit_Key()) {
   ms_state ();
   if (buttons==0x01) { //Left
    if (Fun_Bar_Keys (Num_Keys,Bar_Keys,Pos_Keys)) goto KEYBOARD;
    if (hor_position>=X1 && hor_position<=X2) {
     buttons=0x00; while (ms_release()<1); // до отпускания кнопки мыши
     for (i=0; i<=YMAX; i++) {
      j=wnd->y1+text+i*11;
      if (ver_position>=j && ver_position<=j+11) {
       if (i==point) Set_Key (1,S_BAR);
       else {  point=i; Set_Key (1,START); }
       goto KEYBOARD;
      }
     }
    }
   }
  }
KEYBOARD:
  sim = Get_Key();
  Chand( X1, hi, X2, hi+9, ( fn->color1 == YELLOW )? BLUE: DARKGRAY, XORI );
  switch( sim ) {    //Анализ считанной клавиши
   case ESC: goto OUT;
   case    F1 :
    Common_Menu( fn, fn, H_ELP ); //Вызов подсказки
    Fun_Bar(Case_Wnd_Text_Bar);
   break;
   case  S_BAR:  //Нажатие пробела, выбор/отмена пункта меню
    if ( fn->color1 == YELLOW ) { CURSOR_OFF();
     setfillstyle( SOLID_FILL, DARKGRAY );
     bar( wnd->x1+11+strlen( fn->name )*8, hi,wnd->x2-7, hi+9 );
     bar( wnd->x1+11+strlen( fn->name )*8, hi,wnd->x2-7, hi+9 ); CURSOR_ON();
     if ( fn->zam )
      Print( wnd->x1+20+strlen( fn->name )*8, wnd->y1+text + 11*point,
       alt->color2 ^ BLUE, alt->color2, alt->help );
     else  Print( wnd->x1+20+strlen( fn->name )*8, wnd->y1+text + 11*point,
       alt->color1 ^ BLUE, alt->color1, alt->name );
     fn->zam ^= 1;
    }
   break;
   case    UP : if ( !point-- )  point = YMAX; break;
   case  DOWN :	 point++; point %= (YMAX + 1); break;
   case PAGE_UP: point = 0; break;
   case PAGE_DO: point = YMAX; break;
   case ENTER : // Подтверждение выбора и выход
    Thank|=0x08;
    Set_Key( 1, ESC );
    alt = tal; fn = vf; //Установка указателей в начало
    for ( i = 0; i <= YMAX; i++, fn++, alt++ ) alt->zam = fn->zam;
   break;
  } // switch
 } // while
OUT:
 fn = vf; alt = tal; //Установка указателей в начало
 //Совмещение произведенных установок
 for( i = 0; i <= YMAX; i++, fn++, alt++ ) fn->zam = alt->zam;
 fn = vf;  alt = tal; //Повторная установка указателей в начало
 CURSOR_OFF();
 putimage( wnd->x1, wnd->y1, bm, COPY_PUT ); //Востанавливаем изображение //   bmPos-=ii;
 farfree( bm );  //При этом, освобождаем занятую память
 CURSOR_ON(); return;
}
*/
/***************************************************************************
 *                                                                         *
 *    Данная подпрограмма выводит список допустимых клавиш в функциональ-  *
 * ную строку приложения.                                                  *
 *                                                                         *
 * Описание переменых:                                                     *
 * str - строка для вывода                                                 *
 * MAXY - максимальное количество пикселов по вертикали                    *
 ***************************************************************************/
// Подсказка о назначении клавиш: координаты по Y
#define KEYS_LINE1 MAXY - 12
#define KEYS_LINE2 MAXY
#define FUN_BAR_COLOR 15

void Fun_Bar( char *str ) {
 setfillstyle( SOLID_FILL, FUN_BAR_COLOR ); //Задаем наполнитель и его цвет
 CURSOR_OFF();
 bar( 0, KEYS_LINE1, 639, KEYS_LINE2 ); //Очищаем строку функциональных
 bar( 0, KEYS_LINE1 , 639, KEYS_LINE2 ); //клавиш
 CURSOR_ON();
 Print( 15, KEYS_LINE1+2, LIGHTBLUE, LIGHTRED, str ); //Выводим строку
 return;
}

char Fun_Bar_Keys (char Num_Keys,KEY *Bar_Keys,int *Pos_Keys) {
 int i;
 if (ver_position>=KEYS_LINE1 && ver_position<=KEYS_LINE2) {
  for (i=0; i<Num_Keys; i++)
  if (hor_position>=Pos_Keys[i] && hor_position<=Pos_Keys[i+1]) {
   Set_Key (1,Bar_Keys[i]);
   Chand (Pos_Keys[i],KEYS_LINE1,Pos_Keys[i+1],KEYS_LINE2,FUN_BAR_COLOR,XORI);
   buttons=0x00; while (ms_release()<1); // до отпускания кнопки мыши
   Chand (Pos_Keys[i],KEYS_LINE1,Pos_Keys[i+1],KEYS_LINE2,FUN_BAR_COLOR,XORI);
   return (0x01);
  }
 } return (0x00);
}

//////////////////////////////////////////////////////////////
//                    Часть для мыши
//////////////////////////////////////////////////////////////
static unsigned ms_mask[32] =  { // AND-маска (маска экpана)
 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
 // XOR-маска (маска куpсоpа)
 0x0000, 0x0000, 0x0000, 0x0800, 0x0C00, 0x0E00, 0x0F00, 0x0F80,
 0x0FC0, 0x0FE0, 0x0F00, 0x0D80, 0x0980, 0x00C0, 0x00C0, 0x0000
};

int Init_Mouse (void) {
 _AX=0;
 geninterrupt(0x33);
 if(_AX==0) return 0;
 else {
  set_graph_cursor(4, 3 , ms_mask);
  /* Установка куpсоpа в начальную позицию */
  hor_position= 397; ver_position= 127; buttons=0x00;
  ms_move(hor_position,ver_position);
  _AX=1; geninterrupt(0x33);
  return 1;
 }
}

/* Опpеделяет состояние кнопок и текущие кооpдинаты куpсоpа. */
void ms_state(void) {
 struct REGPACK r;
 r.r_ax = 3;
 intr(0x33, &r);
 buttons = r.r_bx;
 hor_position = r.r_cx;
 ver_position = r.r_dx;
}

int ms_release(void) {
 struct REGPACK r;
 r.r_ax = 6;
 r.r_bx = buttons;
 intr(0x33, &r);
 hor_position = r.r_cx; ver_position = r.r_dx;
 return r.r_bx;
}

/*  Пеpемещает куpсоp "мыши" в заданную позицию экpана. */
void ms_move(int hor_position, int ver_position) {
 if (Mouse) {
  _AX = 4;
  _CX = hor_position;
  _DX = ver_position;
  geninterrupt(0x33);
 } return;
}

void set_graph_cursor(int hot_spot_column, int hot_spot_row,
 unsigned int far * screen_and_cursor_masks) {
  struct REGPACK r;
  r.r_ax = 9;
  r.r_bx = hot_spot_column;
  r.r_cx = hot_spot_row;
  r.r_es = FP_SEG(screen_and_cursor_masks);
  r.r_dx = FP_OFF(screen_and_cursor_masks);
  intr(0x33, &r);
}

void CURSOR_ON(void) {
 if (Mouse) { _AX=1; geninterrupt(0x33); }
 return;
}

void CURSOR_OFF(void) {
 if (Mouse) {_AX=2; geninterrupt(0x33); }
 return;
}

char Mouse_In_Field (int X1, int Y1, int Xsize, int Ysize,
 int Xnum, int Ynum, int Xdop, int Ydop, int Color, int *I, int *J) {
 // X1,Y1 - пиксельные координаты левого верхнего угла
 // Xsize,Ysize - размеры выделяемого блока
 // Xnum,Ynum - количество блоков по горизонтали и вертикали
 // Xdop,Ydop - пустое место между блоками по горизонтали и вертикали
 // Color - цвет выделения
 // *I,*J - клеточные координаты выбранного блока
 // Возвращает 1, если присвоены X,Y, иначе они максимальны
 int X2,Y2,XX,YY,cx,cy;
 X2=X1+Xsize*Xnum+Xdop*(Xnum-1);
 Y2=Y1+Ysize*Ynum+Ydop*(Ynum-1);
 XX=Xsize+Xdop; YY=Ysize+Ydop;
 *I=Xnum; *J=Ynum;
 if (hor_position>=X1 && hor_position<=X2 &&
     ver_position>=Y1 && ver_position<=Y2) {
  cx=(hor_position-X1)/XX;
  if (hor_position<=X1+XX*cx+Xsize) *I=cx;
  cy=(ver_position-Y1)/YY;
  if (ver_position<=Y1+YY*cy+Ysize) *J=cy;
  if (*I<Xnum && *J<Ynum) {
   Chand (X1+cx*XX,Y1+cy*YY,X1+cx*XX+Xsize,Y1+cy*YY+Ysize,Color,XORI);
   buttons=0x00; while (ms_release()<1); // до отпускания кнопки мыши
   Chand (X1+cx*XX,Y1+cy*YY,X1+cx*XX+Xsize,Y1+cy*YY+Ysize,Color,XORI);
   return 0x01;
  }
 }
 return 0x00;
}

char AnyClick (void) { // Любой щелчок мышью
 ms_state();
 if (buttons) { buttons--; while (!ms_release()); return 0x01; }
 return 0x00;
}

/////////////////////////////////////////////////////////////////
void Good_Sound (void) { Sound (30000,20); return; }
void Bad_Sound (void) { Sound (100,20); Sound (90,20); return; }
