/*
	The FreeDOS Standart System Library.
	Copyright (C) 2002 Sandul Yura Valentinovich.
	This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your option) any
later version.
	This program is distributed in the hope that it will be useful,	but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
details.
	You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc., 675
Mass Ave, Cambridge, MA 02139, USA.
	Compiled using the Borland (R) Turbo-C v2.0.
*/

			/* Macros for getting offset value from far pointer. */
#define FP_OFF(fp)     ((unsigned)(fp))
		       /* Macror for getting segment value from far pointer. */
#define FP_SEG(fp)     ((unsigned)((unsigned long)(fp)>>16))
	  /* Macros for make far pointer from the segment and offset values. */
#define MKFP(seg,ofs) ((void far*)(((unsigned long)(seg)<<16)|(unsigned)(ofs)))
				/* Macros for put integer value into memory. */
#define poke(a,b,c)    (*((int far*)MKFP((a),(b)))=(int)(c))
				   /* Macros for put byte value into memory. */
#define pokeb(a,b,c)   (*((char far*)MKFP((a),(b)))=(char)(c))
			    /* Macros for get integer value from the memory. */
#define peek(a,b)      (*((int far*)MKFP((a),(b))))
			       /* Macros for get byte value from the memory. */
#define peekb(a,b)     (*((char far*)MKFP((a),(b))))
				   /* Enumerated standart required constans. */
enum {bw40=0,co40=1,bw80=2,co80=3,mono=7,true=1,false=0,black=0,blue=1,green=2,
cyan=3,red=4,magenta=5,brown=6,lightgray=7,darkgray=8,lightblue=9,
lightgreen=10,lightcyan=11,lightred=12,lightmagenta=13,yellow=14,white=15,
blink=128,EOF=-1};
						 /* Enumerated number bases. */
enum bases {binary,octal,decimal,hexadecimal};
struct REGPACK       /* Register structure for performs the interrupt calls. */
{
 unsigned int r_ax;                            /* Mirror of AX CPU register. */
 unsigned int r_bx;                            /* Mirror of BX CPU register. */
 unsigned int r_cx;                            /* Mirror of CX CPU register. */
 unsigned int r_dx;                            /* Mirror of DX CPU register. */
 unsigned int r_bp;                   /* Mirror of BasePointer CPU register. */
 unsigned int r_si;                   /* Mirror of SourceIndex CPU register. */
 unsigned int r_di;              /* Mirror of DestinationIndex CPU register. */
 unsigned int r_ds;                  /* Mirror of data segment CPU register. */
 unsigned int r_es;                 /* Mirror of extra segment CPU register. */
 unsigned int r_flags;                      /* Mirror of flags CPU register. */
};
struct screendata     /* Structure of display data in the text screen modes. */
{
 unsigned char symbol;                 /* Mirror of symbol value in display. */
 unsigned char attribute;           /* Mirror of attribute value in display. */
};
struct screentext                         /* Structure of display data area. */
{
 struct screendata textdata[2000];              /* Display data area mirror. */
};
char displaymode;                                   /* Current display mode. */
char screenwidth;                        /* Current screen width in columns. */
char screenheight;                         /* Current screen height in rows. */
char windowx;                                      /* Current window column. */
char windowy;                                         /* Current window row. */
char windowwidth;                        /* Current window width in columns. */
char windowheight;                         /* Current window height in rows. */
char textx;                        /* Current screen cursor column location. */
char texty;                           /* Current screen cursor row location. */
char params[8];                        /* Parameters for the ANSI sequences. */
char paramscount;                     /* Count of ANSI sequences parameters. */
char cursorx;                   /* Variable for save cursor column position. */
char cursory;                      /* Variable for save cursor row position. */
char cursorsave;                             /* Saved cursor positions flag. */
char outmode;                                        /* Symbol parsing mode. */
char numberline[2];             /* Variable for number parameters charsters. */
unsigned char attribute;                        /* Color attribute variable. */
struct screentext far *screenarea;           /* Pointer to screen data area. */
unsigned char scancode;      /* Current keyboard scan code for special keys. */
void far (*subroutine)();                            /* Far void subroutine. */
/* ************************************************************************* */
/*                               String functions.                           */
/* ************************************************************************* */
/* ========================================================================= */
/* Copies source to target. Return target.                                   */
char *strcpy(char *target,char *source)
{
 char *value;            /* Variable for temporary saves the target meaning. */
 value=source;                                  /* Saves the target meaning. */
 while(*source!=0)                   /* Repeat while source pointed to null. */
 {
  *target=*source;                                      /* Target <= source. */
  source++;                                /* Increments the source pointer. */
  target++;                                /* Increments the target pointer. */
 }
 return value;                                /* Returns the target meaning. */
}
/* ========================================================================= */
/* Copies count charsters from source to target. Return target.              */
char *strncpy(char *target,char *source,int count)
{
 while(count!=0)                        /* Repeat while count is not a zero. */
 {
  *target=*source;                                      /* Target <= source. */
  target++;                                /* Increments the target pointer. */
  source++;                                /* Increments the source pointer. */
  count--;                                        /* Decrements the counter. */
 }
 return target;                                       /* Returns the target. */
}
/* ========================================================================= */
/* Appending source to target. Return target.                                */
char *strcat(char *target,char *source)
{
 char *value;                /* Variable for temporary saves target meaning. */
 value=target;
 while(*target!=0)target++;             /* Repeat while target is not a end. */
 while(*source!=0)                     /* Repeat while source is not a zero. */
 {
  *target=*source;                                      /* Target <= source. */
  target++;                                /* Increments the target pointer. */
  source++;                                /* Increments the source pointer. */
 }
 return value;                                  /* Returns the target value. */
}
/* ========================================================================= */
/* Copies count charsters from source to target. Return target.              */
char *strncat(char *target,char *source,int count)
{
 char *value;              /* Variable for temporary saves the source value. */
 value=source;                                    /* Saves the source value. */
 while(*target!=0)target++;            /* Repeat while target is not a zero. */
 while(count!=0)                      /* Repeat while counter is not a zero. */
 {
  *target=*source;                                      /* Target <= source. */
  target++;                                /* Increments the target pointer. */
  source++;                                /* Increments the source pointer. */
  count--;                                        /* Decrements the counter. */
 }
 return value;                                   /* Return the target value. */
}
/* ========================================================================= */
/*
Compare two lines.
If first line is less than second line, return -1.
If lines is equalient, return 0.
If first line is greater than second line, return 1.
*/
int strcmp(char *oneline,char *twoline)
{
 while(*oneline!=0)           /* Repeat while oneline pointer is not a null. */
 {
  if(*twoline==0)return 1;           /* If second line is less than, return. */
  oneline++;                              /* Increments the oneline pointer. */
  twoline++;                              /* Increments the twoline pointer. */
 }
 if(*twoline!=0)return -1;         /* If second line is greter than, return. */
 if(*oneline==*twoline)return 0;         /* If lines is equaliented, return. */
}
/* ========================================================================= */
/*
Compare count charsters from lines.
If first line is less than second line, return -1.
If lines is equalient, return 0.
If first line is greater than second line, return 1.
*/
int strncmp(char *oneline,char *twoline,int count)
{
 while(count!=0)                      /* Repeat while counter is not a zero. */
 {
  if((*oneline==0)&&(*twoline!=0))return -1;  /* Check oneline is less than. */
  if((*twoline==0)&&(*oneline!=0))return 1;   /* Check twoline is less than. */
  oneline++;                              /* Increments the oneline pointer. */
  twoline++;                              /* Increments the twoline pointer. */
  count--;                                        /* Decrements the counter. */
 }
 if(*oneline==*twoline)return 0;         /* If lines is equalientes, return. */
}
/* ========================================================================= */
/* Return length of line.                                                    */
int strlen(char *line)
{
 int result=0;                                 /* Variable for result value. */
 while(*line!=0)                         /* Repeat while line is not a null. */
 {
  result++;                         /* Increments the length result counter. */
  line++;                                    /* Increments the line pointer. */
 }
 return result;                    /* Return the resultative length of line. */
}
/* ========================================================================= */
/* Return pointer to first occurence of charster in line, else return null.  */
char *strchr(char *line,char charster)
{
 while(*line!=0)                         /* Repeat while line is not a null. */
 {
  if(*line==charster)return line;                 /* If find, then retun it. */
  line++;                                    /* Increments the line pointer. */
 }
 return 0;                                                   /* Return null. */
}
/* ========================================================================= */
/* Return pointer to last occurence of charster in line, else return null.   */
char *strrchr(char *line,char charster)
{
 int index=0;                                 /* Indexing variable for loop. */
 while(*(line+index)!=0)index++;         /* Repeat while line is not a null. */
 while(index!=0)                /* Repeat while index counter is not a zero. */
 {
  if(*(line+index)==charster)return line+index;   /* Return pointer to find. */
  index--;                                        /* Decrements the counter. */
 }
 return 0;                                                   /* Return null. */
}
/* ========================================================================= */
/* Return lower line.                                                        */
char *lower(char *line)
{
 int index=0;                                 /* Indexing variable for loop. */
 while(*(line+index)!=0)
 {
  if((*(line+index)>('A'-1))&&(*(line+index)<('Z'+1)))   /* Check for chars. */
  *(line+index)=*(line+index)+' ';    /* If charster is up, add space to it. */
  index++;                                  /* Increments the index counter. */
 }
 return line;                                         /* Returns lower line. */
}
/* ========================================================================= */
/* Return upper line.                                                        */
char *upper(char *line)
{
 int index=0;                                 /* Indexing variable for loop. */
 while(*(line+index)!=0)                 /* Repeat while line is not a null. */
 {
  if((*(line+index)>('a'-1))&&(*(line+index)<('z'+1))) /* Check for lo char. */
  *(line+index)=*(line+index)-' ';   /* If char is lo, then add space to it. */
  index++;                                  /* Increments the index counter. */
 }
 return line;                                         /* Returns upper line. */
}
/* ------------------------------------------------------------------------- */
/* ************************************************************************* */
/*                                Music functions.                           */
/* ************************************************************************* */
/* ========================================================================= */
/* Play a sound.                                                             */
void music(unsigned int frequency)
{
 if(frequency==0)return;                 /* If sound is not played, returns. */
 frequency=frequency/0x1234dc;                         /* Divide a freqency. */
 if(inportb(0x61)&&0x3)                    /* Check for dynamic is turn off. */
 {
  outportb(0x61,inportb(0x61)|0x3);                 /* Turned dynamic to on. */
  outportb(0x43,0xb6);                                   /* Prepare a timer. */
 }
 outportb(0x42,frequency%0x100);          /* Out frequency meaning to timer. */
 outportb(0x42,frequency/0x100);          /* Out frequency meaning to timer. */
}
/* ========================================================================= */
/* Stop a playing music.                                                     */
void offmusic()
{
 outportb(0x61,inportb(0x61)&0xfc);                     /* Turn off dynamic. */
}
/* ========================================================================= */
/* Delay out.                                                                */
void wait(unsigned int miliseconds)
{
 unsigned long int far *timer;                  /* Pointer to timer meaning. */
 timer=MKFP(0x40,0x6c);                                /* Set timer pointer. */
}
/* ------------------------------------------------------------------------- */
/* ************************************************************************* */
/*                                Screen functions.                          */
/* ************************************************************************* */
/* ========================================================================= */
/* Get current screen column cursor location in text window.                 */
char inx()
{
 return textx;                   /* Return value from the internal variable. */
}
/* ========================================================================= */
/* Get current screen row cursor location in text window.                    */
char iny()
{
 return texty;                   /* Return value from the internal variable. */
}
/* ========================================================================= */
/* Change location of a screen cursor location.                              */
void movecursor(char newx,char newy)
{
 struct REGPACK registers;                     /* Registers mirror variable. */
					   /* Check for invalid coordinates. */
 if((newx<1)||(newy<1)||(newx>windowwidth)||(newy>windowheight))return;
 textx=newx;                            /* Assignment a new value of column. */
 texty=newy;                               /* Assignment a new value of row. */
 registers.r_ax=0x0200;       /* Video BIOS function 2: Set cursor location. */
 registers.r_bx=0x0000;                   /* Set current video page to zero. */
				/* Assignments the cursor location meanings. */
 registers.r_dx=(((windowy-1)+(texty-1))*0x100)+((windowx-1)+(textx-1));
 intr(0x10,&registers);                     /* Call to video BIOS interrupt. */
}
/* ========================================================================= */
/* Makes a text window.                                                      */
void screenwindow(char newx,char newy,char newwidth,char newheight)
{
					   /* Check for invalid coordinates. */
 if((newx<1)||(newy<1)||(newwidth<1)||(newheight<1)||
 (((newx-1)+newwidth)>screenwidth)||(((newy-1)+newheight)>screenheight))return;
 windowx=newx;           /* Assignments a new value of a text window column. */
 windowy=newy;              /* Assignments a new value of a text window row. */
 windowwidth=newwidth;    /* Assignments a new value of a text window width. */
 windowheight=newheight; /* Assignments a new value of a text window height. */
 movecursor(1,1);            /* Change cursor location to left upper corner. */
}
/* ========================================================================= */
/* Changing a current text color value.                                      */
void textcolor(unsigned char newcolor)
{
	/* If new text color is greater than white color, then set blinking. */
 if(newcolor>white)attribute=(((attribute/0x10)*0x10)+white)+0x80;else
 attribute=((attribute/0x10)*0x10)+newcolor;
}
/* ========================================================================= */
/* Changing a current background color value.                                */
void textbackground(unsigned char newcolor)
{
  /* If new background color is greater than lightgray color, set lightgray. */
 if(newcolor>lightgray)attribute=((lightgray*0x10)+(attribute%0x10))+0x80;else
 attribute=(newcolor*0x10)+(attribute%0x10);
}
/* ========================================================================= */
/* Internal function for get symbol from the screen.                         */
char insymbol(char x,char y)
{
 return screenarea->textdata[(((windowy-1)+(y-1))*screenwidth)+((windowx-1)+
 (x-1))].symbol;            /* Returns the symbol from screen area directly. */
}
/* ========================================================================= */
/* Internal function for get attribute from the screen.                      */
char inattribute(char x,char y)
{
 return screenarea->textdata[(((windowy-1)+(y-1))*screenwidth)+((windowx-1)+
 (x-1))].attribute; /* Return attribute value from the screen area directly. */
}
/* ========================================================================= */
/* Internal function for put symbol and attribute into the screen.           */
void outsymbol(char x,char y,char symbol,char attribute)
{
 screenarea->textdata[(((windowy-1)+(y-1))*screenwidth)+((windowx-1)+(x-1))].
 symbol=symbol;                   /* Put the symbol directly to screen area. */
 screenarea->textdata[(((windowy-1)+(y-1))*screenwidth)+((windowx-1)+(x-1))].
 attribute=attribute;   /* Put the symbol attribute directly to screen area. */
}
/* ========================================================================= */
/* Clearing current line in text window from cursor to end of a line.        */
void cleartoendofline()
{
 char x;                                        /* Column indexing variable. */
 for(x=textx;x<(windowwidth+1);x++)outsymbol(x,texty,0,attribute); /* Clear. */
}
/* ========================================================================= */
/* Clears the screen subroutine.                                             */
void clearscreen()
{
 char x;                                        /* Column indexing variable. */
 char y;                                           /* Row indexing variable. */
 for(y=0;y<(windowheight+1);y++)for(x=1;x<(windowwidth+1);x++)      /* Loop. */
 outsymbol(x,y,0,attribute);                                   /* The clear. */
 movecursor(1,1);    /* Change current cursor location to left upper corner. */
}
/* ========================================================================= */
/* Internal function for moving current text in screen window to up.         */
void scrollup()
{
 char x;                                        /* Column indexing variable. */
 char y;                                           /* Row indexing variable. */
 for(y=2;y<(windowheight+1);y++)for(x=1;x<(windowwidth+1);x++)      /* Loop. */
 outsymbol(x,y-1,insymbol(x,y),inattribute(x,y));             /* The moving. */
			      /* Clears the last line in screen text window. */
 for(x=1;x<(windowwidth+1);x++)outsymbol(x,windowheight,0,attribute);
}
/* ========================================================================= */
/* Internal function for moving current text in screen window to down.       */
void scrolldown()
{
 char x;                                        /* Column indexing variable. */
 char y;                                           /* Row indexing variable. */
 for(y=windowheight;y>1;y--)for(x=1;x<(windowwidth+1);x++)          /* Loop. */
 outsymbol(x,y,insymbol(x,y-1),inattribute(x,y-1));           /* The moving. */
			     /* Clears the first line in screen text window. */
 for(x=1;x<(windowwidth+1);x++)outsymbol(x,1,0,attribute);
}
/* ========================================================================= */
/* Deletes current row in the screen text window.                            */
void deleteline()
{
 char x;                                        /* Column indexing variable. */
 char y;                                           /* Row indexing variable. */
							    /* Deletes loop. */
 for(y=texty+1;y<(windowheight+1);y++)for(x=1;x<(windowwidth+1);x++)
 outsymbol(x,y-1,insymbol(x,y),inattribute(x,y));        /* Deleting a line. */
			      /* Clears the last line in screen text window. */
 for(x=1;x<(windowwidth+1);x++)outsymbol(x,windowheight,0,attribute);
}
/* ========================================================================= */
/* Insert new line to current row location.                                  */
void insertline()
{
 char x;                                        /* Column indexing variable. */
 char y;                                           /* Row indexing variable. */
							  /* Inserting loop. */
 for(y=windowheight;y>texty;y--)for(x=1;x<(windowwidth+1);x++)
 outsymbol(x,y,insymbol(x,y-1),inattribute(x,y-1));     /* Inserting a line. */
			   /* Clears the current line in screen text window. */
 for(x=1;x<(windowwidth+1);x++)outsymbol(x,texty,0,attribute);
}
/* ========================================================================= */
void clearparams()                /* Function for clear all ANSI parameters. */
{
 char index;                                           /* Indexing variable. */
 paramscount=0;                                   /* Clear parameters count. */
 for(index=0;index<8;index++)params[index]=0;       /* Clear the parameters. */
}
/* ========================================================================= */
/* Symbol parsing function.                                                  */
void writesymbol(unsigned char symbol)
{
 switch(outmode)                                   /* Select the parse mode. */
 {
  case 0:                                        /* Mode 0: Main parse mode. */
   switch(symbol)                                    /* Select the charster. */
   {
    case 27:        /* If the escape code, then switch to escape parse mode. */
     outmode=1;                                /* Set the escape parse mode. */
     break;                           /* Break out from the switch operator. */
    default:                                     /* Other printed charsters. */
     switch(symbol)                                  /* Select the charster. */
     {
      case 7:                                                       /* Beep. */
       music(500);                                            /* Play music. */
       wait(50);                                                   /* Delay. */
       offmusic();                                             /* Off music. */
       break;                         /* Break out from the switch operator. */
      case 10:                                                  /* New line. */
       if(texty==windowheight)             /* Check for last line in window. */
       {
	scrollup();                       /* If yes, scroll the text window. */
	movecursor(textx,windowheight);    /* Changing location of a cursor. */
       } else movecursor(textx,texty+1);   /* Changing location of a cursor. */
       break;                         /* Break out from the switch operator. */
      case 13:                                            /* Carrige return. */
       movecursor(1,texty);               /* Move cursor to start of a line. */
       break;                         /* Break out from the switch operator. */
      default:                                         /* All other symbols. */
       outsymbol(textx,texty,symbol,attribute);        /* Write this symbol. */
       if(textx==windowwidth)                  /* Check for moving a cursor. */
       {
	if(texty==windowheight)                /* Check for moving a cursor. */
        {
	 scrollup();               /* Scroll the current screen text window. */
	 movecursor(1,windowheight);       /* Changing location of a cursor. */
	} else movecursor(1,texty+1);      /* Changing location of a cursor. */
       } else movecursor(textx+1,texty);   /* Changing location of a cursor. */
     }
   }
   break;                             /* Break out from the switch operator. */
  case 1:                                                 /* Mode 1: Escape. */
   switch(symbol)                                    /* Select the charster. */
   {
    case '[':     /* If is the open parenthis charster, switch to next mode. */
     outmode=2;                      /* Switch to ANSI sequences parse mode. */
     break;                           /* Break out from the switch operator. */
    default:                    /* If other symbols, assert the escape mode. */
     outmode=0;                           /* Set mode to 0: Main parse mode. */
     writesymbol(symbol);           /* Recursive call to write the charster. */
   }
   break;                             /* Break out from the switch operator. */
  case 2:                               /* Mode 2: The ANSI sequences parse. */
   switch(symbol)                           /* Select the sequence charster. */
   {
    case '0':                                                     /* Digits. */
    case '1':
    case '2':
    case '3':
    case '4':
    case '5':
    case '6':
    case '7':
    case '8':
    case '9':
     clearparams();                           /* Clear all exist parameters. */
     paramscount=1;                          /* Set parameters count to one. */
     outmode=3;                             /* Set parse mode to 3: Digital. */
     numberline[0]=numberline[1]=0;                        /* Clear numbers. */
     writesymbol(symbol);              /* Recursive call to get fisrt digit. */
     break;                           /* Break out from the switch operator. */
    case 's':            /* ANSI sequence 's': Save current cursor position. */
     if(cursorsave==0)        /* Check to previously saving cursor position. */
     {
      cursorx=textx;                          /* Save current cursor column. */
      cursory=texty;                             /* Save current cursor row. */
      cursorsave=1;                         /* Set saved cursor flag to one. */
     }
     clearparams();                           /* Clear all exist parameters. */
     outmode=0;                     /* Set parse mode to 0: Main parse mode. */
     break;                           /* Break out from the switch operator. */
    case 'u':                 /* ANSI sequence 'u': Restore cursor position. */
     if(cursorsave==1)                       /* Check for saved cursor flag. */
     {
      movecursor(cursorx,cursory);  /* Restore the previous cursor position. */
      cursorx=cursory=cursorsave=0;           /* Clear the cursor variables. */
     }
     clearparams();                           /* Clear all exist parameters. */
     outmode=0;                     /* Set parse mode to 0: Main parse mode. */
     break;                           /* Break out from the switch operator. */
    case 'J':                        /* ANSI sequence 'J': Clear the screen. */
     clearscreen();                                     /* Clear the screen. */
     clearparams();                           /* Clear all exist parameters. */
     outmode=0;                     /* Set parse mode to 0: Main parse mode. */
     break;                           /* Break out from the switch operator. */
    case 'H':                    /* ANSI sequences 'H' and 'f': Move cursor. */
    case 'f':
		/* If one or two parameter(s) is not present, set it to one. */
     if(params[0]==0)params[0]=1;
     if(params[1]==0)params[1]=1;
     movecursor(params[1],params[0]);             /* Change cursor position. */
     clearparams();                           /* Clear all exist parameters. */
     outmode=0;                     /* Set parse mode to 0: Main parse mode. */
     break;                           /* Break out from the switch operator. */
    case 'K':                    /* Ansi sequence 'K': Clear to end of line. */
     clreol();                                      /* Clear to end of line. */
     clearparams();                           /* Clear all exist parameters. */
     outmode=0;                     /* Set parse mode to 0: Main parse mode. */
     break;                           /* Break out from the switch operator. */
    case 'A':                       /* ANSI sequence 'A': Move cursor to up. */
     if(params[0]==0)params[0]=1;         /* If parameter not exist, set it. */
                           /* If cursor is not change normal range, move it. */
     if((texty-params[0])>0)movecursor(textx,texty-params[0]);
     clearparams();                           /* Clear all exist parameters. */
     outmode=0;                     /* Set parse mode to 0: Main parse mode. */
     break;                           /* Break out from the switch operator. */
    case 'B':                     /* ANSI sequence 'B': Move cursor to down. */
     if(params[0]==0)params[0]=1;         /* If parameter not exist, set it. */
                           /* If cursor is not change normal range, move it. */
     if((texty+params[0])<26)movecursor(textx,texty+params[0]);
     clearparams();                           /* Clear all exist parameters. */
     outmode=0;                     /* Set parse mode to 0: Main parse mode. */
     break;                           /* Break out from the switch operator. */
    case 'C':                    /* ANSI sequence 'C': Move cursor to right. */
     if(params[0]==0)params[0]=1;         /* If parameter not exist, set it. */
                           /* If cursor is not change normal range, move it. */
     if((textx+params[0])<81)movecursor(textx+params[0],texty);
     clearparams();                           /* Clear all exist parameters. */
     outmode=0;                     /* Set parse mode to 0: Main parse mode. */
     break;                           /* Break out from the switch operator. */
    case 'D':                    /* ANSI sequence 'C': Move cursor to right. */
     if(params[0]==0)params[0]=1;         /* If parameter not exist, set it. */
                           /* If cursor is not change normal range, move it. */
     if((textx-params[0])>0)movecursor(textx-params[0],texty);
     clearparams();                           /* Clear all exist parameters. */
     outmode=0;                     /* Set parse mode to 0: Main parse mode. */
     break;                           /* Break out from the switch operator. */
    case 'm':                     /* ANSI sequence 'm': Set color attribute. */
     if(paramscount>0)                 /* Check for presents the parameters. */
     {
      char index;                                      /* Indexing variable. */
      for(index=0;index<paramscount;index++)      /* Parse exist parameters. */
      {
       switch(params[index])                 /* Parse concretelly parameter. */
       {
        case 0:                           /* Attribute 0: Set gray on black. */
         attribute=(attribute&0x00)|0x07;                  /* Set attribute. */
         break;                       /* Break out from the switch operator. */
        case 1:                          /* Attribute 1: Set high intensity. */
         attribute=(attribute&0xff)|0x08;                  /* Set attribute. */
         break;                       /* Break out from the switch operator. */
        case 4:                               /* Attribute 4: Set underline. */
         attribute=(attribute&0xf8)|0x01;                  /* Set attribute. */
         break;                       /* Break out from the switch operator. */
        case 5:                                /* Attribute 5: Set blinking. */
         attribute=(attribute&0xff)|0x80;                  /* Set attribute. */
         break;                       /* Break out from the switch operator. */
        case 7:                                  /* Attribute 7: Set invert. */
         attribute=(attribute&0xf8)|0x70;                  /* Set attribute. */
         break;                       /* Break out from the switch operator. */
        case 8:                          /* Attribute 8: Set black on black. */
         attribute=(attribute&0x88)|0x00;                  /* Set attribute. */
         break;                       /* Break out from the switch operator. */
        case 30:                            /* Attribute 30: Set black text. */
	 attribute=(attribute&0xf8)|black;                 /* Set attribute. */
         break;                       /* Break out from the switch operator. */
        case 31:                              /* Attribute 31: Set red text. */
	 attribute=(attribute&0xf8)|red;                   /* Set attribute. */
         break;                       /* Break out from the switch operator. */
        case 32:                            /* Attribute 32: Set green text. */
	 attribute=(attribute&0xf8)|green;                 /* Set attribute. */
         break;                       /* Break out from the switch operator. */
        case 33:                            /* Attribute 33: Set brown text. */
	 attribute=(attribute&0xf8)|brown;                 /* Set attribute. */
         break;                       /* Break out from the switch operator. */
        case 34:                             /* Attribute 34: Set blue text. */
	 attribute=(attribute&0xf8)|blue;                  /* Set attribute. */
         break;                       /* Break out from the switch operator. */
        case 35:                          /* Attribute 35: Set magenta text. */
	 attribute=(attribute&0xf8)|magenta;               /* Set attribute. */
         break;                       /* Break out from the switch operator. */
        case 36:                             /* Attribute 36: Set cyan text. */
	 attribute=(attribute&0xf8)|cyan;                  /* Set attribute. */
         break;                       /* Break out from the switch operator. */
        case 37:                             /* Attribute 37: Set gray text. */
	 attribute=(attribute&0xf8)|lightgray;             /* Set attribute. */
         break;                       /* Break out from the switch operator. */
        case 40:                      /* Attribute 40: Set black background. */
	 attribute=(attribute&0x8f)|(black*0x10);          /* Set attribute. */
         break;                       /* Break out from the switch operator. */
        case 41:                        /* Attribute 41: Set red background. */
	 attribute=(attribute&0x8f)|(red*0x10);            /* Set attribute. */
         break;                       /* Break out from the switch operator. */
        case 42:                      /* Attribute 42: Set green background. */
	 attribute=(attribute&0x8f)|(green*0x10);          /* Set attribute. */
         break;                       /* Break out from the switch operator. */
        case 43:                      /* Attribute 43: Set brown background. */
	 attribute=(attribute&0x8f)|(brown*0x10);          /* Set attribute. */
         break;                       /* Break out from the switch operator. */
        case 44:                       /* Attribute 44: Set blue background. */
	 attribute=(attribute&0x8f)|(blue*0x10);           /* Set attribute. */
         break;                       /* Break out from the switch operator. */
        case 45:                    /* Attribute 45: Set magenta background. */
	 attribute=(attribute&0x8f)|(magenta*0x10);        /* Set attribute. */
         break;                       /* Break out from the switch operator. */
        case 46:                       /* Attribute 46: Set cyan background. */
	 attribute=(attribute&0x8f)|(cyan*0x10);           /* Set attribute. */
         break;                       /* Break out from the switch operator. */
        case 47:                       /* Attribute 47: Set gray background. */
	 attribute=(attribute&0x8f)|(lightgray*0x10);      /* Set attribute. */
         break;                       /* Break out from the switch operator. */
       }
      }
     } else                 /* If parameters is not present, set to default. */
      attribute=(attribute&black)|lightgray;           /* Set gray on black. */
     clearparams();                           /* Clear all exist parameters. */
     outmode=0;                     /* Set parse mode to 0: Main parse mode. */
     break;                           /* Break out from the switch operator. */
    default:                                    /* Other charster: write it. */
     outmode=0;                     /* Set parse mode to 0: Main parse mode. */
     writesymbol(symbol);               /* Recursive call to write charster. */
     break;                           /* Break out from the switch operator. */
   }
   break;                             /* Break out from the switch operator. */
  case 3:                                           /* Mode 3: Digital mode. */
   switch(symbol)                                        /* Select charster. */
   {
    case '0':                                                     /* Digits. */
    case '1':
    case '2':
    case '3':
    case '4':
    case '5':
    case '6':
    case '7':
    case '8':
    case '9':
    /* If null charster in parameter line, set first charster to own,
    if one charster is present, set second charster to own, else
    if number line is full (two charsters), skipp adding the charster.       */
     if(numberline[0]==0)numberline[0]=symbol;
     else if(numberline[1]==0)numberline[1]=symbol;
     break;                           /* Break out from the switch operator. */
    case ';':                                         /* Parameters divider. */
                     /* If parameters table is not full, then add parameter. */
     if(paramscount<9)
     {
      if(numberline[1]!=0)              /* Evaluating the parameter meaning. */
      params[paramscount-1]=((numberline[0]-'0')*10)+(numberline[1]-'0');
      else params[paramscount-1]=numberline[0]-'0';
     }
                                                    /* Clear parameter line. */
     numberline[0]=numberline[1]=0;
     if(paramscount<9)paramscount++;          /* Change count of parameters. */
     break;                           /* Break out from the switch operator. */
    default:                                              /* Other charster. */
     if(paramscount<9)                    /* If parameter table is not full. */
     {
      if(numberline[1]!=0)              /* Evaluating the parameter meaning. */
      params[paramscount-1]=((numberline[0]-'0')*10)+(numberline[1]-'0');
      else params[paramscount-1]=numberline[0]-'0';
     }
                                                    /* Clear parameter line. */
     numberline[0]=numberline[1]=0;
              /* If parameters table is full, set the real parameters count. */
     if(paramscount==9)paramscount=8;
     outmode=2;            /* Set parse mode to 2: The ANSI sequences parse. */
     writesymbol(symbol);      /* Recursive call to parse the ANSI sequence. */
   }
 }
}
/* ========================================================================= */
/* Write a line.                                                             */
void writeline(unsigned char *line)
{
 while(*line!=0)                          /* Repeat while line is not empty. */
 {
  writesymbol(*line);                         /* Write a concretelly symbol. */
  line++;                                    /* Increments the line pointer. */
 }
 writesymbol(13);                            /* Write carrige return symbol. */
 writesymbol(10);                                 /* Write line feed symbol. */
}
/* ========================================================================= */
/* Changing the text screen mode.                                            */
void screenmode(char newmode)
{
 struct REGPACK registers;                     /* Registers variable mirror. */
 switch(newmode)                                  /* Select the screen mode. */
 {
  case bw40:                              /* Mode 0: Text, 40x25, monocrome. */
   displaymode=bw40;  /* Set screen mode to informational internal variable. */
   screenwidth=40;            /* Set screen width to internal work variable. */
   screenheight=25;          /* Set screen height to internal work variable. */
   screenarea=MKFP(0xb800,0x0000);     /* Set screen area text video memory. */
   registers.r_ax=0x0000;    /* Video BIOS function 0: Set new display mode. */
   break;                             /* Break out from the switch operator. */
  case co40:
   displaymode=co40;  /* Set screen mode to informational internal variable. */
   screenwidth=40;            /* Set screen width to internal work variable. */
   screenheight=25;          /* Set screen height to internal work variable. */
   screenarea=MKFP(0xb800,0x0000);     /* Set screen area text video memory. */
   registers.r_ax=0x0001;    /* Video BIOS function 0: Set new display mode. */
   break;                             /* Break out from the switch operator. */
  case bw80:
   displaymode=bw80;  /* Set screen mode to informational internal variable. */
   screenwidth=80;            /* Set screen width to internal work variable. */
   screenheight=25;          /* Set screen height to internal work variable. */
   screenarea=MKFP(0xb800,0x0000);     /* Set screen area text video memory. */
   registers.r_ax=0x0002;    /* Video BIOS function 0: Set new display mode. */
   break;                             /* Break out from the switch operator. */
  case co80:
   displaymode=co80;  /* Set screen mode to informational internal variable. */
   screenwidth=80;            /* Set screen width to internal work variable. */
   screenheight=25;          /* Set screen height to internal work variable. */
   screenarea=MKFP(0xb800,0x0000);     /* Set screen area text video memory. */
   registers.r_ax=0x0003;    /* Video BIOS function 0: Set new display mode. */
   break;                             /* Break out from the switch operator. */
  case mono:
   displaymode=mono;  /* Set screen mode to informational internal variable. */
   screenwidth=80;            /* Set screen width to internal work variable. */
   screenheight=25;          /* Set screen height to internal work variable. */
   screenarea=MKFP(0xb000,0x0000);     /* Set screen area text video memory. */
   registers.r_ax=0x0007;    /* Video BIOS function 0: Set new display mode. */
   break;                             /* Break out from the switch operator. */
  default:                                       /* If is not a screen mode. */
   return;                    /* If meaning is has been invalid, the return. */
 }
 intr(0x10,&registers);                    /* Call the video BIOS interrupt. */
 registers.r_ax=0x0500;    /* Video BIOS function 5: Set active screen page. */
 intr(0x10,&registers);                    /* Call the video BIOS interrupt. */
 registers.r_ax=0x0100;           /* Video BIOS function 1: Set cursor size. */
 registers.r_cx=0x0708;        /* Size of cursor: start line is 7, end is 8. */
 intr(0x10,&registers);                    /* Call the video BIOS interrupt. */
 screenwindow(1,1,screenwidth,screenheight); /* Set full screen text window. */
 textbackground(black);                    /* Set background color to black. */
 textcolor(lightgray);                            /* Set text color to gray. */
 clearscreen();                                         /* Clear the screen. */
}
/* ------------------------------------------------------------------------- */
/* ************************************************************************* */
/*                              Keyboard functions.                          */
/* ************************************************************************* */
/* ========================================================================= */
/* Return 1 if any key is pressed, else return 0.                            */
char keypressed()
{
 struct REGPACK registers;                     /* Registers mirror variable. */
 registers.r_ax=0x0100; /* BIOS function 1: Get keyboard keypressing status. */
 registers.r_flags=0x0000;                    /* Set flags register to zero. */
 intr(0x16,&registers);                          /* Call the BIOS interrupt. */
 return registers.r_flags&0x40?false:true;                       /* Cheking. */
}
/* ========================================================================= */
/* Returned pressed key.                                                     */
unsigned char readkey()
{
 struct REGPACK registers;                     /* Registers mirror variable. */
 if(scancode!=0)                               /* Check for previous status. */
 {
  unsigned char temp;                  /* Variable for save temporary value. */
  temp=scancode;                              /* Saving the temporary value. */
  scancode=0;                            /* Clear scan code status variable. */
  return temp;                              /* Return temporary saved value. */
 }
 registers.r_ax=0x0000;                 /* BIOS function 0: Get pressed key. */
 intr(0x16,&registers);                          /* Call the BIOS interrupt. */
 if((registers.r_ax%0x100)==0)             /* Check for pressed special key. */
 {
  scancode=registers.r_ax/0x100;         /* If yes, then save current value. */
  return 0;                                                  /* Return zero. */
 }
 scancode=0;                             /* Clear scan code status variable. */
 return registers.r_ax%0x100;                    /* Return pressed key code. */
}
/* ------------------------------------------------------------------------- */
/* ************************************************************************* */
/*                       Number conversion functions.                        */
/* ************************************************************************* */
/* ========================================================================= */
/* Convert line to number.                                                   */
unsigned long int linetonumber(char *line,enum bases base)
{
 unsigned long number;          /* Variable for save evaluated number value. */
 unsigned long mules;                   /* Variable for evaluating a number. */
 char numberline[12];                                 /* Number line digits. */
 char loopflag=1;
 for(number=0;number<12;number++)numberline[number]=0;
 while(loopflag==1)
 {
  if((*line==0)||(numberline[0]==10))break;
  switch(*line)
  {
   case '0':
   case '1':
   case '2':
   case '3':
   case '4':
   case '5':
   case '6':
   case '7':
   case '8':
   case '9':
   case 'A':
   case 'B':
   case 'C':
   case 'D':
   case 'E':
   case 'F':
   case 'a':
   case 'b':
   case 'c':
   case 'd':
   case 'e':
   case 'f':
    numberline[0]++;
    numberline[numberline[0]]=*line;
    break;                            /* Break out from the switch operator. */
   default:
    loopflag=0;
  }
  line++;
 }
 number=0;
 mules=1;
 while(numberline[0]!=0)
 {
  switch(base)
  {
   case binary:
    switch(numberline[numberline[0]])
    {
     case '0':
     case '1':
      number=number+((numberline[numberline[0]]-'0')*mules);
      break;                          /* Break out from the switch operator. */
     default:
      numberline[0]=0;
    }
    mules=mules*2;
    break;                            /* Break out from the switch operator. */
   case octal:
    switch(numberline[numberline[0]])
    {
     case '0':
     case '1':
     case '2':
     case '3':
     case '4':
     case '5':
     case '6':
     case '7':
      number=number+((numberline[numberline[0]]-'0')*mules);
      break;                          /* Break out from the switch operator. */
     default:
      numberline[0]=0;
    }
    mules=mules*8;
    break;                            /* Break out from the switch operator. */
   case decimal:
    switch(numberline[numberline[0]])
    {
     case '0':
     case '1':
     case '2':
     case '3':
     case '4':
     case '5':
     case '6':
     case '7':
     case '8':
     case '9':
      number=number+((numberline[numberline[0]]-'0')*mules);
      break;                          /* Break out from the switch operator. */
     default:
      numberline[0]=0;
    }
    mules=mules*10;
    break;                            /* Break out from the switch operator. */
   case hexadecimal:
    switch(numberline[numberline[0]])
    {
     case '0':
     case '1':
     case '2':
     case '3':
     case '4':
     case '5':
     case '6':
     case '7':
     case '8':
     case '9':
      number=number+((numberline[numberline[0]]-'0')*mules);
      break;                          /* Break out from the switch operator. */
     case 'A':
     case 'a':
      number=number+(10*mules);
      break;                          /* Break out from the switch operator. */
     case 'B':
     case 'b':
      number=number+(11*mules);
      break;                          /* Break out from the switch operator. */
     case 'C':
     case 'c':
      number=number+(12*mules);
      break;                          /* Break out from the switch operator. */
     case 'D':
     case 'd':
      number=number+(13*mules);
      break;                          /* Break out from the switch operator. */
     case 'E':
     case 'e':
      number=number+(14*mules);
      break;                          /* Break out from the switch operator. */
     case 'F':
     case 'f':
      number=number+(15*mules);
      break;                          /* Break out from the switch operator. */
     default:
      numberline[0]=0;
    }
    mules=mules*16;
  }
  if(numberline[0]==0)break;
  numberline[0]--;
 }
 return number;
}
/* ========================================================================= */
char *numbertoline(unsigned long meaning,enum basese base)
{
 unsigned long number;
 char *numberline;
 *numberline=0;
 numberline++;
 number=meaning;
 while(number!=0)
 {
  switch(base)
  {
   case binary:
    switch(number%2)
    {
     case 0:
     case 1:
      *numberline=(number%2)+'0';
      break;                          /* Break out from the switch operator. */
    }
    numberline++;
    number=number/2;
    break;                            /* Break out from the switch operator. */
   case octal:
    switch(number%8)
    {
     case 0:
     case 1:
     case 2:
     case 3:
     case 4:
     case 5:
     case 6:
     case 7:
      *numberline=(number%8)+'0';
      break;                          /* Break out from the switch operator. */
    }
    numberline++;
    number=number/8;
    break;                            /* Break out from the switch operator. */
   case decimal:
    switch(number%10)
    {
     case 0:
     case 1:
     case 2:
     case 3:
     case 4:
     case 5:
     case 6:
     case 7:
     case 8:
     case 9:
      *numberline=(number%10)+'0';
      break;                          /* Break out from the switch operator. */
    }
    numberline++;
    number=number/10;
    break;                            /* Break out from the switch operator. */
   case hexadecimal:
    switch(number%16)
    {
     case 0:
     case 1:
     case 2:
     case 3:
     case 4:
     case 5:
     case 6:
     case 7:
     case 8:
     case 9:
      *numberline=(number%16)+'0';
      break;                          /* Break out from the switch operator. */
     case 10:
      *numberline='A';
      break;                          /* Break out from the switch operator. */
     case 11:
      *numberline='B';
      break;                          /* Break out from the switch operator. */
     case 12:
      *numberline='C';
      break;                          /* Break out from the switch operator. */
     case 13:
      *numberline='D';
      break;                          /* Break out from the switch operator. */
     case 14:
      *numberline='E';
      break;                          /* Break out from the switch operator. */
     case 15:
      *numberline='F';
    }
    numberline++;
    number=number/16;
  }
 }
 numberline--;
 return *numberline;
}
/* ------------------------------------------------------------------------- */
/* ************************************************************************* */
/*                                Any functions.                             */
/* ************************************************************************* */
/* ========================================================================= */
/* Restarting the computer.                                                  */
void restartcomputer()
{
 (*subroutine)=MKFP(0xf000,0xfff0);                 /* Set restart address. */
 (*subroutine)();                                       /* Far call to BIOS. */
}
/* ========================================================================= */
void main()
{
 int key;
 screenmode(co80);
 writeline(numbertoline(256,hexadecimal));
 writeline("[0;33;44mHello, World!!![0m");
 readkey();
 for(key=0;key<2001;key++)writesymbol('X');
 screenwindow(5,5,10,10);
 while(1)
 {
  key=readkey();
  switch(key)
  {
   case 0:
    switch(readkey())
    {
     case 72:
      movecursor(inx(),iny()-1);
      break;                          /* Break out from the switch operator. */
     case 80:
      movecursor(inx(),iny()+1);
      break;                          /* Break out from the switch operator. */
     case 75:
      movecursor(inx()-1,iny());
      break;                          /* Break out from the switch operator. */
     case 77:
      movecursor(inx()+1,iny());
      break;                          /* Break out from the switch operator. */
     case 82:
      insertline();
      break;                          /* Break out from the switch operator. */
     case 83:
      deleteline();
    }
    break;                            /* Break out from the switch operator. */
   case 8:
    movecursor(inx()-1,iny());
    break;                            /* Break out from the switch operator. */
   case 13:
    movecursor(1,iny()+1);
    break;                            /* Break out from the switch operator. */
   case 27:
    return;
   default:
    if(key>31)writesymbol(key);
  }
 }
}
/* ========================================================================= */
