
 // ML307.cpp
 // (c) Сергей Гоцуляк, ВВТ-307
 // 20.10.1999 - 10.01.2000

 // Интегрировання среда разработки программ на МИЛАНЕ.
 // Без наворотов, не до конца выловлены глюки, и куча других
 // недостатков - если есть желание, доработайте, а я - пас.

 #include <conio.h>
 #include <stdio.h>
 #include <string.h>
 #include <process.h>
 #include <errno.h>
 #include "c:\work\ml307\sources\sets.h"
 #include "c:\work\ml307\sources\NewTI.h"
 #include "c:\work\ml307\sources\win.h"


 char ComFileName[80];

 void showprogramtext()
 {
	 textbackground(BLACK);
	 textcolor(CYAN);
	 for(i=0;i<MaxY;i++)
	 {
		 gotoxy(ZeroX,i+ZeroY);
		 for(j=0;j<MaxX;j++)
		 {
			 //gotoxy(ZeroX+j,i+ZeroY);
			 putch(ProgramText[i+NumberFirstLine][j]);
		 }
	 }
 }

 void showscreen()
 {
	 textbackground(BLACK);
	 clrscr();
	 fillwindow(1,1,80,3,BLACK);
	 showframe(1,1,80,3,DARKGRAY);
	 textcolor(RED);
	 center(1," Милан-307 ");
	 fillwindow(1,4,80,23,BLACK);
	 showframe(1,4,80,23,LIGHTGRAY);
	 textcolor(RED);
	 gotoxy(4,4);
	 cprintf(" %s ",ProgramFileName);
	 showbottomline("");
	 gotoxy(3,24);
	 textcolor(YELLOW);
	 showbottomline("TAB: вход в меню");
	 gotoxy(XPos+ZeroX,YPos+ZeroY);
	 textbackground(WHITE);
	 cprintf("%c",Cursor);
	 textbackground(BLACK);
	 textcolor(CYAN);
	 gotoxy(4,23);
	 cprintf(" %02d:%02d ",XPos,YPos);
	 showmenu(-1);
	 textbackground(BLACK);
	 textcolor(CYAN);
	 for(i=0;i<MaxY;i++)
		 for(j=0;j<MaxX;j++)
		 {
			 gotoxy(ZeroX+j,i+ZeroY);
			 cprintf("%c",ProgramText[i+NumberFirstLine][j]);
		 }
 }

 void ErrorManager(int ErrorCode)
 {
	 if(!CoMo)
	 {
		 textbackground(BLACK);
		 textcolor(LIGHTBLUE);
		 clrscr();
	 }
	 textcolor(RED);
	 printf("\n\n");
	 cprintf(" Ошибка !!! ");
         printf("\n");
         if(ErrorCode==-1)
            cprintf(" ErrorCode: %d. errno: %d.",ErrorCode,errno);
         else
            cprintf(" ErrorCode: %d.",ErrorCode);
         textcolor(LIGHTBLUE);
         printf("\n");
         printf(" Пояснение:");
	 switch(ErrorCode)
	 {

		 case(1):
			 {
				 printf("\n    - Невозможен запуск");
				 printf("\n    - скомпилированного файла.");
				 switch(errno)
				 {
					 case(ENOENT):
						 {
							 printf("\n    - Файл");
							 printf("\n    - %s",WorkFileName);
							 printf("\n    - не найден ...");
							 printf("\n    - Нажмите любую клавишу ...");
							 getch();
							 break;
						 }
					 case(ENOMEM):
						 {
							 printf("\n    - Hе хватает памяти ...");
							 printf("\n    - Нажмите любую клавишу ...");
							 getch();
							 break;
						 }
				 }
				 key=getch();
				 break;
			 }
		 case(201):
			 {
				 printf("\n    - Не открывается файл");
				 printf("\n    - %s",WorkFileName);
				 printf("\n    - для чтения.");
				 printf("\n    - Нажмите любую клавишу ...");
				 key=getch();
				 break;
			 }
		 case(202):
			 {
				 printf("\n    - Открываемый файл");
				 printf("\n    - %s",WorkFileName);
				 printf("\n    - не помещается в буфер.");
				 printf("\n    - Нажмите любую клавишу ...");
				 key=getch();
				 break;
			 }
		 case(203):
			 {
				 printf("\n    - Не открывается файл");
				 printf("\n    - %s",WorkFileName);
				 printf("\n    - для записи.");
				 printf("\n    - Нажмите любую клавишу ...");
				 key=getch();
				 break;
			 }
		 case(401-256):
			 {
				 printf("\n    - Число лексем более 500.");
				 key=getch();
				 break;
			 }
		 case(501-256):
			 {
				 printf("\n    - Отсутствует begin.");
				 key=getch();
				 break;
			 }
		 case(502-256):
			 {
				 printf("\n    - Отсутствует end.");
				 key=getch();
				 break;
			 }
		 case(503-256):
			 {
				 printf("\n    - Программа не заканчивается на end.");
				 key=getch();
				 break;
			 }
		 case(504-256):
			 {
				 printf("\n    - Невозможно открыть com.com");
				 key=getch();
				 break;
			 }
		 case(505-256):
			 {
				 printf("\n    - Отсутствует символ ;");
				 key=getch();
				 break;
			 }
		 case(506-256):
			 {
				 printf("\n    - Неверное присваивание.");
				 key=getch();
				 break;
			 }
		 case(507-256):
			 {
				 printf("\n    - Отсутствует символ ( в output.");
				 key=getch();
				 break;
			 }
		 case(508-256):
			 {
				 printf("\n    - Отсутствует символ ) в output.");
				 key=getch();
				 break;
			 }
		 case(509-256):
			 {
				 printf("\n    - Отсутствует do в цикле while.");
				 key=getch();
				 break;
			 }
		 case(510-256):
			 {
				 printf("\n    - Отсутствует od в цикле while.");
				 key=getch();
				 break;
			 }
		 case(511-256):
			 {
				 printf("\n    - Отсутствует символ ) в выражении.");
				 key=getch();
				 break;
			 }
		 case(512-256):
			 {
				 printf("\n    - Неверная операция сравнения.");
				 key=getch();
				 break;
			 }
		 case(513-256):
			 {
				 printf("\n    - Отсутствует then.");
				 key=getch();
				 break;
			 }
		 case(514-256):
			 {
				 printf("\n    - Отсутствует fi.");
				 key=getch();
				 break;
			 }
		 case(-1):
			 {
				 switch(errno)
				 {
					 case(ENOENT):
						 {
							 printf("\n    - Файл");
							 printf("\n    - %s",WorkFileName);
							 printf("\n    - не найден ...");
							 getch();
							 break;
						 }
					 case(ENOMEM):
						 {
							 printf("\n    - Hе хватает памяти ...");
							 getch();
							 break;
						 }
				 }
			 }
	 }
	 if(CoMo)
	 {
		 textcolor(RED);
		 printf("\n\n");
		 cprintf(" Компиляция невозможна.");
		 printf("\n");
		 cprintf(" Hажмите любую клавишу ...");
		 getch();
		 CoMo=0;
	 }
	 showscreen();
 }


 int zerostring(int x)
 {
	 char flag=1;
	 for(int i=0; i<MaxX; i++)
	 {
		 if(ProgramText[x][i]!=SPACE)
			 flag=0;
	 }
	 return flag;
 }

 void PointReadMe()
 {
	 open_window(70,13," ReadMe! ");
	 textcolor(RED);
	 center(8,"ML-307 v1.2");
	 textcolor(LIGHTBLUE);
	 center(10,"(c)1999-2000 Сергей Гоцуляк");
	 center(11,"Волжский Политехнический Институт");
	 textcolor(BLACK);
	 center(13,"ML-307 - это курсовая работа по дисципплине");
	 center(14,"'Основы трансляции'");
	 center(15,"NB: Разрешено использование исходных текстов");
	 center(16,"для некоммерческого использования !");
	 getch();
	 close_window(70,13);
 }

 void PointQuit()
 {
	 open_window(40,10," Выход ");
	 center(10,"Вы действительно");
	 center(11,"желаете покинуть прогорамму ?");
	 center(13,"Нажмите Enter - подтверждение");
	 center(14,"        Esc   - отмена       ");
	 key=getch();
	 close_window(40,10);
	 if(key==ENTER)
		 exit(0);
 }

 void PointNew()
 {
	 for(i=0;i<MAX;i++)            // очищаем текстовый буфер
		 for(j=0;j<MaxX;j++)
			 ProgramText[i][j]=SPACE;
	 showscreen();
	 XPos=YPos=NumberFirstLine=0;
	 strcpy(ProgramFileName,"Zero.mil");
 }

 void PointRead()
 {
	 FILE *file;
	 int XPos,YPos,NumberString=-1,sym;
	 open_window(54,10," Чтение ");
	 strcpy(WorkFileName,ProgramFileName);
	 center(10,"Введите имя файла:");
	 center(14,"Нажмите Enter - подтверждение");
	 center(15,"        Esc   - отмена       ");
	 textbackground(LIGHTBLUE);
	 center(12,"                                       ");
	 gotoxy(21,12);
	 textcolor(WHITE);
	 cprintf(" * ");
	 int X=24;
	 YPos=12;
	 _setcursortype(1);
	 XPos=strlen(ProgramFileName);
	 while(1)
	 {
		 gotoxy(X,YPos);
		 cprintf("%s ",WorkFileName);
		 gotoxy(X+XPos,YPos);
		 do
		 {
			 key=getch();
			 if(!key)
				 getch();
		 }
		 while(!key);
		 if(key==BACKSPACE&&XPos>=0)
		 {
			 XPos--;
			 WorkFileName[XPos]='\0';
			 if(XPos==-1)
				 XPos=0;
		 }
		 if(key>32&&XPos<36)
		 {
			 WorkFileName[XPos]=key;
			 XPos++;
		 }
		 if(key==ENTER||key==ESC)
			break;
	 }
	 _setcursortype(0);
	 close_window(54,10);
	 if(key==ESC)
		 return;
	 file=fopen(WorkFileName,"rb");
	 if(file==NULL)
	 {
		 ErrorManager(201);
		 return;
	 }
	 for(i=0;i<MAX;i++)            // очищаем текстовый буфер
		 for(j=0;j<MaxX;j++)
	  ProgramText[i][j]=SPACE;
	 NumberString=XPos=0;
	 while(1)
	 {
		 sym=fgetc(file);
		 if(sym==EOF)
			 break;
		 if(sym==TAB)
			 sym=SPACE;
		 if(sym==ENTER&&XPos!=0)
		 {

			 XPos=0;
			 NumberString++;
			 if(NumberString>MAX-1)
			 {
				 ErrorManager(202);
				 break;
			 }
		 }
		 if(sym>=SPACE)
		 {
			 ProgramText[NumberString][XPos]=sym;
			 XPos++;
			 if(XPos>=MaxX)
			 {
				 XPos=0;
				 NumberString++;
				 if(NumberString>MAX-1)
				 {
					 ErrorManager(202);
					 break;
				 }
			 }
		 }
	 }
	 fclose(file);
	 ::XPos=0;
	 ::YPos=0;
	 NumberFirstLine=0;
	 strcpy(ProgramFileName,WorkFileName);
	 showscreen();
	 return;
 }

 void PointSave()
 {
	 FILE *file;
	 int XPos,YPos;
	 open_window(54,10," Запись ");
	 strcpy(WorkFileName,ProgramFileName);
	 center(10,"Введите имя файла:");
	 center(14,"Нажмите Enter - подтверждение");
	 center(15,"        Esc   - отмена       ");
	 textbackground(LIGHTBLUE);
	 center(12,"                                       ");
	 gotoxy(21,12);
	 textcolor(WHITE);
	 cprintf(" * ");
	 int X=24;
	 YPos=12;
	 _setcursortype(1);
	 XPos=strlen(ProgramFileName);
	 while(1)
	 {
		 gotoxy(X,YPos);
		 cprintf("%s ",WorkFileName);
		 gotoxy(X+XPos,YPos);
		 do
		 {
			 key=getch();
			 if(!key)
				 getch();
		 }
		 while(!key);
		 if(key==BACKSPACE&&XPos>=0)
		 {
			 XPos--;
			 WorkFileName[XPos]='\0';
			 if(XPos==-1)
				 XPos=0;
		 }
		 if(key>32&&XPos<36)
		 {
			 WorkFileName[XPos]=key;
			 XPos++;
		 }
		 if(key==ENTER||key==ESC)
			break;
	 }
	 _setcursortype(0);
	 close_window(54,10);
	 if(key==ESC)
		 return;
	 file=fopen(WorkFileName,"wb");
	 if(file==NULL)
	 {
		 ErrorManager(203);
		 return;
	 }
	 for(i=(MaxX-1);i>=0;i--)
		 if(!zerostring(i))
			 break;

	 int temp=i;
	 for(i=0;i<=temp;i++)
	 {
		 for(j=0;j<MaxX;j++)
			 fputc(ProgramText[i][j],file);
		 fputc(10,file);
		 fputc(13,file);
	 }

	 fclose(file);
	 strcpy(ProgramFileName,WorkFileName);
	 showscreen();
	 return;
 }

 void PointCompile()
 {
	 textbackground(BLACK);
	 textcolor(LIGHTBLUE);
	 clrscr();
	 CoMo=1;
	 // пишем в файл
	 textcolor(RED);
	 center(2,"Компиляция");
	 FILE *file;

	 file=fopen("ProgText.tmp","wb");
	 if(file==NULL)
	 {
		 ErrorManager(203+256);
		 return;
	 }
	 for(i=(MaxX-1);i>=0;i--)
		 if(!zerostring(i))
			 break;

	 int temp=i;
	 for(i=0;i<=temp;i++)
	 {
		 for(j=0;j<MaxX;j++)
			 fputc(ProgramText[i][j],file);
		 fputc(10,file);
		 fputc(13,file);
	 }
	 fclose(file);
	 // вызываем пpепpоцессоp
	 int error=spawnl(P_WAIT,"preproc.exe","  ",NULL);
	 if(error)
	 {
		 if(error==-1)
			 strcpy(WorkFileName,"preproc.exe");
		 if(error==201-256)
			 strcpy(WorkFileName,"ProgText.tmp");
		 if(error==203-256)
			 strcpy(WorkFileName,"Phase01.tmp");
		 ErrorManager(error);
		 return;
	 }
	 error=spawnl(P_WAIT,"scaner.exe","  ",NULL);
	 if(error)
	 {
           	 if(error==-1)
			 strcpy(WorkFileName,"scaner.exe");
		 if(error==201-256)
			 strcpy(WorkFileName,"Phase01.tmp");
		 if(error==203-256)
			 strcpy(WorkFileName,"Phase02.tmp");
		 ErrorManager(error);
		 return;
	 }
         char strtmp[80];
         for(i=0;i<strlen(ProgramFileName);i++)
         {
             if(ProgramFileName[i]=='.')
                break;
             strtmp[i]=ProgramFileName[i];
         }
         strtmp[i]='.';
         strtmp[i+1]='c';
         strtmp[i+2]='o';
         strtmp[i+3]='m';
         strtmp[i+4]='\0';
         strcpy(ComFileName,strtmp);
         //***
         file=fopen("FileName.tmp","wb");
	 if(file==NULL)
	 {
            strcpy(WorkFileName,"FileName.tmp");
		 ErrorManager(203+256);
		 return;
	 }
	 fputs(strtmp,file);
	 fclose(file);

         //***
	 error=spawnl(P_WAIT,"compiler.exe",strtmp,"  ",NULL);
	 if(error)
	 {
                 if(error==-1)
			 strcpy(WorkFileName,"compiler.exe");
		 if(error==201-256)
			 strcpy(WorkFileName,"Phase02.tmp");
		 if(error==203-256)
			 strcpy(WorkFileName,strtmp);
		 ErrorManager(error);
		 return;
	 }
	 textcolor(YELLOW);
	 printf("\n\n");
	 cprintf(" Компиляция закончилась успешно.");
	 printf("\n");
	 cprintf(" Hажмите любую клавишу ...");
	 getch();
	 showscreen();
	 CoMo=0;
 }

 void PointRun()
 {
	 textbackground(BLACK);
	 textcolor(WHITE);
	 clrscr();
	 /*printf("\n");
	 cprintf("                             Выполнение программы");
	 textcolor(WHITE);
	 gotoxy(1,1);
	 cprintf(" aaa ");
	 gotoxy(1,1);
	 printf("     ");
	 gotoxy(1,5);*/
	 int error=spawnl(P_WAIT,ComFileName,"  ",NULL);
	 if(error==-1)
	 {
		 strcpy(WorkFileName,ComFileName);
		 ErrorManager(1);
		 return;
	 }
	 textcolor(YELLOW);
	 printf("\n\n");
	 cprintf("                       Программа завершила свою работу.");
	 printf("\n");
	 cprintf("                            Нажмите любую клавишу ...");
	 getch();
	 showscreen();
 }

 void KeyRight()
 {
  gotoxy(XPos+ZeroX,YPos+ZeroY);
		  cprintf("%c",ProgramText[YPos+NumberFirstLine][XPos]);
		  if(XPos<(MaxX-1))
		XPos++;
 }

 void KeyLeft()
 {
 gotoxy(XPos+ZeroX,YPos+ZeroY);
		  cprintf("%c",ProgramText[YPos+NumberFirstLine][XPos]);
		  if(XPos>0)
		XPos--;
 }

 void KeyUp()
 {
 gotoxy(XPos+ZeroX,YPos+ZeroY);
		  cprintf("%c",ProgramText[YPos+NumberFirstLine][XPos]);
		  if(YPos>0)
		YPos--;
		  else
		  {
		if(NumberFirstLine>0)
		{
			NumberFirstLine--;
			for(i=0;i<MaxY;i++)
				for(j=0;j<MaxX;j++)
				{
			 gotoxy(ZeroX+j,i+ZeroY);
			 cprintf("%c",ProgramText[i+NumberFirstLine][j]);
				}
		}
		  }
 }

 void KeyDown()
 {
		  gotoxy(XPos+ZeroX,YPos+ZeroY);
		  cprintf("%c",ProgramText[YPos+NumberFirstLine][XPos]);
		  if(YPos<(MaxY-1))
		YPos++;
		  else
		  {
		if(NumberFirstLine+YPos<(MAX-1))
		{
			NumberFirstLine++;
			for(i=0;i<MaxY;i++)
				for(j=0;j<MaxX;j++)
				{
			 gotoxy(ZeroX+j,i+ZeroY);
			 cprintf("%c",ProgramText[i+NumberFirstLine][j]);
				}
		}
		  }
 }

 void KeyEnter()
 {
	 int pt=0;

		 if(!zerostring(YPos+NumberFirstLine))
		 {
			 for(i=0;i<MaxX;i++)
				 if(ProgramText[YPos+NumberFirstLine][i]!=SPACE)
					 break;
			 pt=i;
		 }
	 //}
	 if(zerostring(MAX-1))
	 {
		 for(i=(MAX-2);i>YPos+NumberFirstLine;i--)
	  for(j=0;j<MaxX;j++)
		  ProgramText[i+1][j]=ProgramText[i][j];
		 for(j=0;j<MaxX;j++)
	  ProgramText[YPos+1+NumberFirstLine][j]=SPACE;
		 for(i=XPos;i<MaxX;i++)
		 {
	  ProgramText[YPos+1+NumberFirstLine][i-XPos]=
	  ProgramText[YPos+NumberFirstLine][i];
	  ProgramText[YPos+NumberFirstLine][i]=SPACE;
		 }
		 XPos=pt;
		 KeyDown();
		 showprogramtext();

	 }
	// else
	// {
	// }
 }

 void KeyDefault()
 {
	 if(key<32||predsym==0)
		 return;
	 textcolor(CYAN);
	 if(ProgramText[YPos+NumberFirstLine][MaxX-1]==SPACE)
	 {
		 for(i=MaxX-1;i>XPos;i--)
		 {
			 ProgramText[YPos+NumberFirstLine][i]=
			 ProgramText[YPos+NumberFirstLine][i-1];
			 gotoxy(i+ZeroX,YPos+ZeroY);
			 cprintf("%c",ProgramText[YPos+NumberFirstLine][i]);
		 }

		  ProgramText[YPos+NumberFirstLine][XPos]=key;
		  gotoxy(XPos+ZeroX,YPos+ZeroY);
		  cprintf("%c",key);
		  if(XPos<(MaxX-1))
		XPos++;
	}
 }

 void KeyBackSpace()
 {
	 if(XPos==0&&YPos==0&&NumberFirstLine==0)
		 return;
	 if(XPos>0)
	 {
		 for(i=XPos;i<MaxX;i++)
		 {
			 ProgramText[YPos+NumberFirstLine][i-1]=
			 ProgramText[YPos+NumberFirstLine][i];
		 }

		 ProgramText[YPos+NumberFirstLine][MaxX-1]=SPACE;
		 for(i=0;i<MaxX;i++)
		 {
			 gotoxy(i+ZeroX,YPos+ZeroY);
			 putch(ProgramText[YPos+NumberFirstLine][i]);
		 }
		 XPos--;
		 //putch(ProgramText[YPos+NumberFirstLine][XPos+1]);
		 return;
	 }
	 if(XPos==0&&zerostring(YPos+NumberFirstLine-1))
	 {
		 for(i=YPos+NumberFirstLine-1;i<MAX-1;i++)
			 for(j=0;j<MaxX;j++)
				 ProgramText[i][j]=ProgramText[i+1][j];
		 for(j=0;j<MaxX;j++)
			 ProgramText[MAX-1][j]=SPACE;
		 if(YPos==0)
			 NumberFirstLine--;
		 else
			 YPos--;
		 showprogramtext();

		 return;
	 }
	 else
	 {
		 int slen;
		 for(i=MaxX-1;i>=0;i--)
			 if(ProgramText[YPos+NumberFirstLine-1][i]!=SPACE)
				 break;
		 slen=MaxX-i-1;
		 if(slen!=0)
		 {
		 for(j=i+1;j<MaxX;j++)
		 {
			 ProgramText[YPos+NumberFirstLine-1][j]=
			 ProgramText[YPos+NumberFirstLine][j-i-1];
		 }
		 for(j=0;j<MaxX-slen;j++)
		 {
			 ProgramText[YPos+NumberFirstLine][j]=
			 ProgramText[YPos+NumberFirstLine][slen+j];
		 }
		 for(j=MaxX-slen;j<MaxX;j++)
			 ProgramText[YPos+NumberFirstLine][j]=SPACE;
		 showprogramtext();
		 KeyUp();
		 XPos=MaxX-slen;
		 }

	 }

 }

 void main()
 {
	 _setcursortype(0);
	 int NumberPoint;
	 for(i=0;i<MAX;i++)            // очищаем текстовый буфер
		 for(j=0;j<MaxX;j++)
	  ProgramText[i][j]=SPACE;
	 showscreen();
	 while(1)
	 {

		 gotoxy(XPos+ZeroX,YPos+ZeroY);
		 textbackground(WHITE);
		 cprintf("%c",Cursor);
		 textcolor(CYAN);
		 textbackground(BLACK);
		 gotoxy(4,23);
		 cprintf(" %03d:%03d ",XPos+1,YPos+NumberFirstLine+1);
		 do
		 {
			 predsym=1;
			 key=getch();
			 if(key==0)
			 {
				 key=getch();
				 predsym=0;
			 }
		 }
		 while(!key);

		 switch(key)
		 {
			 case TAB:
			 {
				  NumberPoint=workwithmenu();
				  switch(NumberPoint)
				  {
					 case  7: PointQuit();break; // Выход
					 case  1: PointNew();break;  // Новый
					 case  2: PointRead();break; // Чтение
					 case  3: PointSave();break; // Запись
					 case  4: PointCompile();break;
					 case  5: PointRun();break;
					 case  0: PointReadMe();break;
					 default:break;
				  }
				  break;
	  }
	  case ENTER: KeyEnter()  ;break;
	  case RIGHT: KeyRight()  ;break;
	  case LEFT : KeyLeft()   ;break;
	  case UP   : KeyUp()     ;break;
	  case DOWN : KeyDown()   ;break;
	  case BACKSPACE : KeyBackSpace();break;
	  default   : KeyDefault();

		 }
	 }
 }