#include <textmenu.h>
#include <function.h>

#include <stdio.h>
#include <string.h>

FILE *TextFile;
MODE Buffer[4000],BufX1=0,BufY1=0,BufX2=10,BufY2=20;
MODE Text[25][81];
MODE Width=0,Growth=0;
MENU BoxMenu={ 1,1,10,12, 8, "jJоО1!1!2@2@3#3#4$4$5%5%6^6^7&7&",
 LIGHTBLUE, WHITE, LIGHTGRAY, NO_HELP, YES,0 }; //BoxMenu->Setup  - нужна
static MODE Selected;
MODE *Str[2]={"  ",""};
MODE X1=10,Y1=10,X2=15,Y2=25;

extern MODE far *vid_mem, far *V;
extern MODE CX,CY,IsEdit;
extern MODE Screen[],FullName[],Attr,Char;
extern void Error (unsigned);

char read_char (char x, char y, char *attr) {
 char ch;
 V = vid_mem + (x<<7) + (x<<5) + (y<<1);
 ch = *V++;  // символ
 *attr = *V; // атрибут
 return (ch);
}

void Get_Screen (void) {
 //Получить с экрана образ Screen
 MODE c,a; int i,j;
 for (i=0; i<25; i++)
 for (j=0; j<80; j++) {
  c=read_char (i,j,&a);
  Screen[(i*80+j)*2]=c;
  Screen[(i*80+j)*2+1]=a;
 }
 IsEdit=YES;
}

MODE Pull_Border (MODE *x,MODE *y,MODE rows, MODE cols) {
 MODE *Bar=" $ESC$ Отказ  $\033$ Влево  $\032$ Вправо  $\030$ Вверх  $\031$ Вниз  $ENTER$ Выбор";
// ESC Отказ  ! Влево  ! Вправо  ! Вверх  ! Вниз  ENTER Выбор
 KEY Sim;
 MODE x1,y1,x2,y2,Out=NO;
 x1=*x; y1=*y; x2=x1+rows-1; y2=y1+cols-1; ATTR=0x0F;
 Fun_Bar (Bar);
 while (1) {
  save (x1,y1,x2,y2);
  box (x1,y1,x2,y2,0x02);
  Sim=Get_Key();
  restore (x1,y1,x2,y2);
  switch (Sim) {
   case LEFT:  if (y1>0) { y1--; y2--; } break;
   case RIGHT: if (y2<79) { y1++; y2++; } break;
   case UP:    if (x1>0) { x1--; x2--; } break;
   case DOWN:  if (x2<24) { x1++; x2++; } break;
   case ESC:   Out=1; break;
   case ENTER: *x=x1; *y=y1; Out=2; break;
   default: continue;
  }
  if (Out) break;
 }
 return (Out-1);
}

void Read_Text (MODE *FullName) {
 MODE c,cx,cy; int i,j;
 TextFile=fopen (FullName,"rt");
 if (TextFile==NULL) return;
 Width=Growth=0;
 for (i=0; i<25; i++) {
  memset (Text[i],'\0',80);
  if (fgets (Text[i],81,TextFile)!=NULL) {
   Growth++;
   c=strlen (Text[i]);
   if (Text[i][c-1]=='\n') Text[i][c-1]='\0';
   if (c>Width) Width=c;
  }
  if (feof (TextFile)) break;
 }
 if (!(Growth>0 && Width>0)) return;
 cx=cy=0;
 save (24,0,24,79);
 c=Pull_Border (&cx,&cy,Growth,Width);
 restore (24,0,24,79);
 if (c) {
  ATTR=Attr;
  for (i=0; i<Growth; i++) {
   for (j=0; j<Width; j++) {
    if (Text[i][j]=='\0') break;
    write_char (cx+i, cy+j, Text[i][j]);
   }
  }
  Get_Screen();
 }
 return;
}

void Do_Open_Text (void) {
 MODE c;
 save (24,0,24,79);
 c=Filer ("*.TXT", FullName, 0x01);
 restore (24,0,24,79);
 if (c==0x00) { //Выбран файл
  Read_Text(FullName);
 }
 else if (c!=0xff) Error (c); //Ошибка!
}

void Open_Text(void) {
 Set_Key (3,ESC,ESC,START);
 Ext_Function=Do_Open_Text;
}

MODE Draw_Border (MODE *sx,MODE *sy,MODE *ex,MODE *ey) {
 MODE *Bar=" $ESC$ Отказ  $Home$ Влево  $End$ Вправо  $PgUp$ Вверх  $PgDn$ Вниз  $ENTER$ Выбор";
// ESC Отказ  Home Влево  End Вправо  PgUp Вверх  PgDn Вниз  ENTER Выбор
 KEY Sim;
 MODE x1,y1,x2,y2,Out=NO;
 x1=*sx; y1=*sy; x2=*ex; y2=*ey; ATTR=0x0F;
 Fun_Bar (Bar);
 while (1) {
  save (x1,y1,x2,y2);
  box (x1,y1,x2,y2,0x02);
  Sim=Get_Key();
  restore (x1,y1,x2,y2);
  switch (Sim) {
   case LEFT:  if (y1>0) { y1--; y2--; } break;
   case RIGHT: if (y2<79) { y1++; y2++; } break;
   case UP:    if (x1>0) { x1--; x2--; } break;
   case DOWN:  if (x2<24) { x1++; x2++; } break;
   case HOME:      if (y1>0)  y1--; break;
   case END:       if (y1<y2-1) y1++; break;
   case PAGE_UP:   if (x1>0)  x1--; break;
   case PAGE_DO:   if (x1<x2-1) x1++; break;
   case ESC:   Out=1; break;
   case ENTER: *sx=x1; *sy=y1; *ex=x2; *ey=y2; Out=2; break;
   default: continue;
  }
  if (Out) break;
 }
 return (Out-1);
}

void Fix_Type (void) {
 Selected=BoxMenu.Setup;
 Set_Key (1,ESC);
}

void Do_Draw_Box (void) {
 MODE c;
 MENUITEM Item[]={
  {"$О$пределить",YES,Fix_Type},
  {"$1$. ┌─┐",YES,Fix_Type},
  {"$2$. ╔═╗",YES,Fix_Type},
  {"$3$. ┌─╖",YES,Fix_Type},
  {"$4$. ╒═╕",YES,Fix_Type},
  {"$5$. ╓─╖",YES,Fix_Type},
  {"$6$. ▌ ▐",YES,Fix_Type},
  {"$7$. █ █",YES,Fix_Type},
 };
 MENU Menu={9,30,16,50, 1, " Введите 1 символ: ",
  WHITE,LIGHTRED,BLUE,  NO_HELP, YES,YES};
 MODE **Ptr=&Str[0];
 STRLIST List[]={
  {10,32, 12,32,   "", 1, LIGHTGRAY, MAGENTA, 1, Ptr, 0}
 };
 Selected=NO_SIM;
 save (24,0,24,79);
 Popup (&BoxMenu, Item);
 restore (24,0,24,79);
 if (Selected!=NO_SIM) {
  if (Selected==0) {
   save (24,0,24,79);
   c=GetText (&Menu,List);
   restore (24,0,24,79);
  }
  save (24,0,24,79);
  c=Draw_Border (&X1,&Y1,&X2,&Y2);
  restore (24,0,24,79);
  if (c) {
   FILLER=Str[0][0]; ATTR=Attr;
   box (X1,Y1,X2,Y2,Selected);
   Get_Screen();
  }
 }
}

void Draw_Box (void) {
 Set_Key (3,ESC,ESC,START);
 Ext_Function=Do_Draw_Box;
}

void Do_Fill_Box (void) {
 MODE c;
 save (24,0,24,79);
 c=Draw_Border (&X1,&Y1,&X2,&Y2);
 restore (24,0,24,79);
 if (c) {
  ATTR=Attr;
  clear (X1,Y1,X2,Y2);
  Get_Screen();
 }
}

void Fill_Box (void) {
 Set_Key (3,ESC,ESC,START);
 Ext_Function=Do_Fill_Box;
}

void Do_Show_Curs (void) {
 MODE *Str="  ";
 WINDOW Win={ 5, 28, 11, 52, " Координаты курсора: ",
 "Строка:    \n"
 "Столбец:    ",  BLACK, YELLOW, CYAN, NO_HELP, YES, 0 };
 sprintf (Str,"%02d",CX);
 memcpy (&Win.str[8],Str,2);
 sprintf (Str,"%02d",CY);
 memcpy (&Win.str[21],Str,2);
 save (24,0,24,79);
 MessageText (&Win);
 restore (24,0,24,79);
}

void Show_Curs (void) {
 Set_Key (3,ESC,ESC,START);
 Ext_Function=Do_Show_Curs;
}

void Cut_Box (MODE x1, MODE y1, MODE x2,MODE y2) {
 int i;
 BufX1=x1; BufY1=y1; BufX2=x2; BufY2=y2;
 for (i=(x1*80+y1)*2; i<=(x2*80+y2)*2+1; i++) {
  Buffer[i]=Screen[i];
 }
}

void Do_Cut_To_Buffer (void) {
 MODE c;
 save (24,0,24,79);
 c=Draw_Border (&BufX1,&BufY1,&BufX2,&BufY2);
 restore (24,0,24,79);
 if (c) Cut_Box (BufX1,BufY1,BufX2,BufY2);
}

void Cut_To_Buffer (void) {
 Set_Key (3,ESC,ESC,START);
 Ext_Function=Do_Cut_To_Buffer;
}

void Get_Box (MODE x1, MODE y1) {
 int i,j; MODE c;
 for (i=BufX1; i<=BufX2; i++)
 for (j=BufY1; j<=BufY2; j++) {
  c=Buffer[(i*80+j)*2];
  ATTR=Buffer[(i*80+j)*2+1];
  write_char (x1+i-BufX1,y1+j-BufY1,c);
 }
}

void Do_Pop_From_Buffer (void) {
 MODE c,x1,y1,sx,sy;
 save (24,0,24,79);
 x1=BufX1; y1=BufY1; sx=BufX2-BufX1; sy=BufY2-BufY1;
 c=Pull_Border (&x1,&y1,sx+1,sy+1);
 restore (24,0,24,79);
 if (c) {
  Get_Box (x1,y1);
  Get_Screen();
 }
}

void Pop_From_Buffer (void) {
 Set_Key (3,ESC,ESC,START);
 Ext_Function=Do_Pop_From_Buffer;
}
