//Апдейт от 21/11/99
#include <textmenu.h>
#include <function.h>

#include <stdio.h>
#include <dir.h>

extern void             //SEDIT2.CPP
 Open_Text(void),
 Draw_Box (void),
 Fill_Box (void),
 Show_Curs (void),
 Cut_To_Buffer (void),
 Pop_From_Buffer (void);

MODE CX=0,CY=0; //Координаты курсора
MODE Char=' ',Attr=0x07; //Символ и атрибут для рисования
MODE *FileName[2]={ //48
 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 "};
MODE FullName[129];
MODE IsFile=NO;
MODE Screen[4000];
FILE *File;
ffblk Find;

void DrawBar (MODE x1, MODE y1, MODE x2, MODE y2, MODE BackColor,
 MODE AreaColor, MODE LineColor, MODE TextColor, MODE *hdr, MODE *str) {
 MODE i;
 save (x1,y1,x2,y2);
 ATTR=set_attr (LineColor, BackColor);
 box (x1,y1,x2,y2,0x02);
 ATTR=set_attr (TextColor, BackColor);
 clear (x1+1,y1+1,x2-1,y2-1);
 if (*hdr) center_string (x1, y1, y2, hdr);
 if (*str) {
  strlen__ (str,&i);
  ATTR=set_attr (TextColor, AreaColor);
  clear (x1+1,y1+1,x1+i,y2-1);
  Print (x1+1, y1+1, TextColor, LineColor, str);
 }
}

void Error (unsigned Num) {
 MODE *MesErrors[]={ //По 46 символов в строке
 "",
 "Ошибка процедуры выбора файла:\n"
 "$Нет памяти$",  //1
 "Ошибка процедуры выбора файла:\n"
 "$Нет ни одного файла на диске$",  //2
 "Ошибка процедуры выбора файла:\n"
 "$Ошибка доступа к каталогу$",  //3
 "Ошибка процедуры выбора файла:\n"
 "$Ошибка доступа к диску$",  //4
 "$Не могу$ создать файл  с введенным Вами именем.\n"
 "Возможно,  что имя введено $неверно$, или файл с\n"
 "таким именем  $уже есть$ или исчерпано место  на\n"
 "$диске$. Проверьте список Ваших файлов  и попро-\n"
 "буйте $еще раз$.", //5
 "Не могу открыть выбранный файл $для чтения$. По-\n"
 "пробуйте еще раз.", //6
 "$Нет$ открытого файла для сохранения!" //7
 };
 static MODE *Ptr;
 WINDOW Win={ 5, 15, 13, 64, " Ошибка ", Ptr,
  BLACK, YELLOW, CYAN, NO_HELP, YES, 0 };
 Win.str=MesErrors[Num];
 save (24,0,24,79);
 MessageText (&Win);
 restore (24,0,24,79);
}

void Close_All (void) {
 Close_System();
}

void FatalError (unsigned Num) {
 Error (Num);
 Close_All();
}

void Close_File (void) {
 int i;
 if (IsFile) {
  fseek (File,0L,SEEK_SET);
  i=fwrite (Screen,4000,1,File);
  if (!i) FatalError (2);
  fclose (File);
  IsFile=NO;
 }
}

MODE New_File (MODE *Name) {
 int i;
 if (IsFile) fclose (File);
 i=findfirst (Name,&Find,0x20);
 if (!i) return NO;
 File=fopen (Name,"wb");
 if (File==NULL) return NO;
 fclose (File);
 File=fopen (Name,"r+b");
 if (File==NULL) return NO;
 return YES;
}

MODE Get_File (void) {
 int i;
 //if (!IsFile) {
  for (i=0; i<4000; i++) {
   if (i%2==0) Screen[i]=' ';//Символ
   else Screen[i]=0x07;
  }
  FILLER=' '; ATTR=0x07;
  clear (0,0,24,79);
  goto_xy (0,0);
  IsFile=YES;
 //}
 return YES;
}

MODE IsEdit=NO;

void Save_Current (void) {
 MODE c;
 MENU Quest= { 9,27,14,53, NO,
  "   $Сохранить$ изменения в\n"
  "   текущем файле?" , DARKGRAY, WHITE, GREEN, NO_HELP ,YES, 0 };
 if (IsEdit) {
  save (24,0,24,79);
  c=AnswMenu (&Quest);
  restore (24,0,24,79);
  if (c) {
   IsEdit=NO;
   Close_File();
  }
 }
 fclose (File); //!!!
}

void Do_Create_File(void) {
 MENU Menu={9,12,16,65, 1, " Окно ввода ",
   WHITE,LIGHTRED,BLUE,  NO_HELP, YES,YES};
 MODE **FileNamePtr=&FileName[0],c;
 STRLIST List[]={
  {10,14, 12,14,   "Введите имя нового файла:", 48,
  LIGHTGRAY,MAGENTA, 2, FileNamePtr, ALT_A}
 };
 save (24,0,24,79);
 c=GetText (&Menu,List);
 restore (24,0,24,79);
 if (c) {
  Save_Current();
  LeftMargin (FileName[0]);
  RightMargin (FileName[0]);
  if ((!FileName[0][0]) || (!New_File(FileName[0])) ) Error (5);
  else {
   Get_File();
  }
 }
 return;
}

void Create_File(void) {
 Set_Key (3,ESC,ESC,START);
 Ext_Function=Do_Create_File;
}

void Draw_Screen (void) {
 MODE r=0,c=0; int i;
 for (i=0; i<2000; i++) {
  ATTR=Screen[(i<<1)+1];
  write_char (r,c,Screen[(i<<1)]);
  c++;
  if (c==80) {
   c=0;
   r++;
   if (r==25) break;
  }
 }
}

MODE Read_File (MODE *FullName) {
 MODE c; int i,j;
 File=fopen (FullName,"r+b");
 if (File==NULL) return NO;
 for (i=0; i<4000; i++) {
  j=fread (&c,1,1,File);
  if (!j) return NO;
  Screen[i]=c;
 }
 IsFile=YES;
 Draw_Screen ();
 return YES;
}


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

void Open_File(void) {
 Set_Key (3,ESC,ESC,START);
 Ext_Function=Do_Open_File;
}

void Do_Save_File (void) {
 int i;
 if (IsFile) {
  fseek (File, 0, SEEK_SET);
  i=fwrite (Screen,4000,1,File);
  if (!i) FatalError (2);
  IsEdit=NO;
 }
 else Error (7);
}

void Save_File(void) {
 Set_Key (3,ESC,ESC,START);
 Ext_Function=Do_Save_File;
}

void Do_Select_Char (void) {
 static MODE cx,cy;
 MODE i,j,x1=3,y1=25;
 KEY Sim;
 DrawBar (x1,y1, x1+20, y1+30, BLACK, CYAN, YELLOW, WHITE,
" Выбор символа ","Клавишами со стрелками выбе-\nрите символ и нажмите ENTER");
 ATTR=0x1e;
 for (i=0; i<16; i++)
 for (j=0; j<16; j++) {
  write_char (x1+3+i, y1+2+j,(i<<4)+j);
 }
 while (1) {
  goto_xy (x1+3+cx, y1+2+cy);
  Sim=Get_Key();
  switch (Sim) {
   case LEFT:  if (cy>0) cy--; break;
   case RIGHT: if (cy<15) cy++; break;
   case UP:    if (cx>0) cx--; break;
   case DOWN:  if (cx<15) cx++; break;
   case ESC:   goto OUT;
   case ENTER: Char=(cx<<4)+cy; goto OUT;
   default: continue;
  }
 }
OUT:
 restore (x1,y1, x1+20, y1+30);
 return;
}

void Select_Char(void) {
 Set_Key (3,ESC,ESC,START);
 Ext_Function=Do_Select_Char;
}

void Do_Select_Attr (void) {
 static MODE cx,cy;
 MODE i,j,x1=3,y1=25;
 KEY Sim;
 DrawBar (x1,y1, x1+20, y1+30, BLACK, CYAN, YELLOW, WHITE,
" Выбор атрибута ","Клавишами со стрелками выбе-\nрите атрибут и нажмите ENTER");
 for (i=0; i<16; i++)
 for (j=0; j<16; j++) {
  ATTR=(i<<4)+j;
  write_char (x1+3+i, y1+2+j,'\t');
 }
 while (1) {
  goto_xy (x1+3+cx, y1+2+cy);
  Sim=Get_Key();
  switch (Sim) {
   case LEFT:  if (cy>0) cy--; break;
   case RIGHT: if (cy<15) cy++; break;
   case UP:    if (cx>0) cx--; break;
   case DOWN:  if (cx<15) cx++; break;
   case ESC:   goto OUT;
   case ENTER: Attr=(cx<<4)+cy; goto OUT;
   default: continue;
  }
 }
OUT:
 restore (x1,y1, x1+20, y1+30);
 return;
}

void Select_Attr (void) {
 Set_Key (3,ESC,ESC,START);
 Ext_Function=Do_Select_Attr;
}

void Work(void) {
 static MODE Select;
 MENU Menu={ 1,1,14,25, 12, "jJоОyYнНhHрР    cCсСfFаАnNтТ,<бБpPзЗrRкКgGпПdDвВ",
  LIGHTBLUE, WHITE, LIGHTGRAY, NO_HELP, YES,0 };
 MENUITEM Item[]={
  {"Создать $н$овый        $F4$",YES,Create_File},
  {"$О$ткрыть              $F3$",YES,Open_File},
  {"Сох$р$анить            $F2$",YES,Save_File},
  {"\0",NO,Nop},
  {"$С$имвол заполнения    $F5$",YES,Select_Char},
  {"$А$трибут заполнения   $F6$",YES,Select_Attr},
  {"Прочитать $т$екст",NO, Open_Text },
  {"Нарисовать $б$окс",NO, Draw_Box },
  {"$З$аполнить атрибутом",NO, Fill_Box },
  {"$К$оординаты курсора",NO, Show_Curs },
  {"$П$оместить в буфер",NO, Cut_To_Buffer },
  {"$В$ставить из буфера",NO, Pop_From_Buffer }
 };
 MODE i;
 for (i=6; i<12; i++) {
  if (IsFile) Item[i].zam=YES;
  else Item[i].zam=NO;
 }
 Menu.Setup=Select;
 save (24,0,24,79);
 PullDown (&Menu,Item);
 restore (24,0,24,79);
 Select=Menu.Setup;
}

void Do_Go_Out (void) {
 MENU Quit= { 9,27,15,53, NO,
  " Вы действительно хотите\n"
  "$закончить$ работу и выйти\n"
  "        в $DOS$ ?", DARKGRAY, WHITE, GREEN, NO_HELP ,YES, 0 };
 MODE c;
 save (24,0,24,79);
 c=AnswMenu (&Quit);
 restore (24,0,24,79);
 if (c) {
  Save_Current();
  Close_All ();
 }
}

void Go_Out (void) {
 Set_Key (3,ESC,ESC,START);
 Ext_Function=Do_Go_Out;
}

void Do_About_Program (void) {
 WINDOW WinAbout={ 5, 16, 21, 63, " Помощь ",
"      Программа предназначена для редактирова-\n"
"ния текстовых образов и сохранения их в форма-\n"
"те 'Символ-Атрибут'.\n"
"     Для входа в меню используйте клавишу $F10$.\n"
" $F3$ - загрузить образ (предполагается, что они\n"
"хранятся в файлах с расширением $SCR$).\n"
" $F4$ - создать новый образ (ввести имя файла).\n"
" $F2$ - сохранить текущий образ на диске\n"
" $F5$ - выбрать символ, $F6$ - атрибут заполнения\n"
"экрана, $стрелки$ - перемещение по экрану, кла-\n"
"виша $пробела$ -  рисование  в текущей  позиции\n"
"символа и атрибута, $ENTER$ - только атрибута.",
  BLACK, YELLOW, CYAN, NO_HELP, YES, 0 };
 save (24,0,24,79);
 MessageText (&WinAbout);
 restore (24,0,24,79);
}

void About_Program (void) {
 Set_Key (3,ESC,ESC,START);
 Ext_Function=Do_About_Program;
}

void Helps(void) {
 static MODE Select;
 MENU Menu={1,10,5,29, 3, "jJоО    dDвВ", LIGHTBLUE, WHITE,
 LIGHTGRAY, NO_HELP, YES,0};
 MENUITEM Item[]={
  {"$О$ программе     $F1$", YES, About_Program },
  {"\0",NO,Nop},//Разделитель
  {"$В$ыход в DOS    $ESC$", YES, Go_Out }
 };
 Menu.Setup=Select;
 save (24,0,24,79);
 PullDown (&Menu,Item);
 restore (24,0,24,79);
 Select=Menu.Setup;
}

void main (int argc,char *argv[]) {
 static MODE *HorKeys="hHрРgGпП",First=YES;
 MODE *DopKeys="nNтТ,<бБpPзЗrRкКgGпПdDвВ";
 MENU Hor= {0,0,0,79, 2, HorKeys, LIGHTBLUE, WHITE, LIGHTGRAY, NO_HELP, YES, 0};
 MENUITEM Hors[]={
  {" $Р$абота",YES, Work},
  {" $П$омощь",YES, Helps}
 };
 MODE *Bar=" $ESC$ Выход  $F1$ О программе  $F3$ Открыть  $F10$ Меню",
      Pos_Keys[]={0,11,27,39,48};
 KEY Bar_Keys[]={ESC,F1,F3,F10},Sim,i;
 //Инициализация
 if (!textmode()) return;
 //Mouse=Init_Mouse ();

 //Оформление экрана
 FILLER='░'; ATTR=0x07;
 clear (0,0,24,79);
 Fun_Bar (Bar);
 Init_Date();
 Clear_Buf();
 //Основной цикл
 while (1) {
  goto_xy (CX,CY);
  if (Mouse) while (!Hit_Key()) {
   ms_state ();
   if (buttons==0x01) { //Left
    if (Fun_Bar_Keys (4,Bar_Keys,Pos_Keys)) goto KEYBOARD;
   }
  }
KEYBOARD:
  Sim=Get_Key();
  switch (Sim) {
   case ESC: Set_Key (4,F10,END,ENTER,'в');  break;
   case F1:  Set_Key (4,F10,END,ENTER,'о');  break;
   case F2:  Set_Key (4,F10,HOME,ENTER,'р'); break;
   case F3:  Set_Key (4,F10,HOME,ENTER,'о'); break;
   case F4:  Set_Key (4,F10,HOME,ENTER,'н'); break;
   case F5:  Set_Key (4,F10,HOME,ENTER,'с'); break;
   case F6:  Set_Key (4,F10,HOME,ENTER,'а'); break;
   case F10:
    if (!First) save (24,0,24,79);
    HorMenu (&Hor,Hors);
    if (First) First=NO;
    else restore (24,0,24,79);
   break;
   case START:
    Ext_Function();
    if (!IsFile) Fun_Bar (Bar);
   break;
   case LEFT:  if (CY>0) CY--; break;
   case RIGHT: if (CY<79) CY++; break;
   case UP:    if (CX>0) CX--; break;
   case DOWN:  if (CX<24) CX++; break;
   case S_BAR:
    ATTR=Attr;
    write_char (CX,CY,Char);
    Screen[(CX*80+CY)*2]=Char;
    Screen[(CX*80+CY)*2+1]=Attr;
    IsEdit=YES;
   break;
   case ENTER:
    ATTR=(Attr&0xf0)>>4;
    change_attr (CX,CY,CX,CY,ATTR);
    Screen[(CX*80+CY)*2+1]=Attr;
    IsEdit=YES;
   break;
   default:
/*    i=Find_Key(HorKeys,Sim);
    if (i!=NO_SIM) Set_Key (3,F10,HorKeys[i<<2],ENTER);
    i=Find_Key(DopKeys,Sim);
    if (i!=NO_SIM) {
     Set_Key (4,F10,HOME,ENTER,DopKeys[i<<2]);
    }
   continue; */
    ATTR=Attr;
    write_char (CX,CY,Sim);
    Screen[(CX*80+CY)*2]=Sim;
    Screen[(CX*80+CY)*2+1]=Attr;
    IsEdit=YES;
    if (CY<79) CY++;
    else { CY=0; if (CX<24) CX++; else CX=0; }
  }
 }
}
