#parsecommandline TRUE
#resize TRUE

#include "prefer.h--"

#define minRows 10
#define minCols 50
#ifdef VariableWindowsSize
word realRows;
word realCols;
word rows;// = initalRows;
word cols;// = initalCols;
word editRows;// = initalRows - 1;
#ifdef FloatWindow
word bufferLength;// = initalCols - 20;
#endif
#define screenRows CSWORD[#rows];
#define usefullRows CSWORD[#editRows];
#define screenCols CSWORD[#cols];
#ifdef FloatWindow
#define inputBufferLength CSWORD[#bufferLength];
#else
#define inputBufferLength 60
#endif
#else
#define screenRows 25
#define usefullRows 24
#define screenCols 80
#define inputBufferLength 60
#endif
#define screenBufferSeg 0B800h

#ifdef VariableChineseMode
byte chineseMode = TRUE;
#endif
#ifdef EnableReadOnly 
byte readOnlyMode = FALSE;
#endif

#define normalCharColor normalCharBackgroundColor*16+normalCharForegroundColor
#define selectedCharColor selectedCharBackgroundColor*16+selectedCharForegroundColor
#define markedLineColor markedLineBackgroundColor*16+markedLineForegroundColor
#define markedSelectedCharColor markedSelectedCharBackgroundColor*16+markedSelectedCharForegroundColor
#define messageLineColor messageLineBackgroundColor*16+messageLineForegroundColor
#define unsaveFileColor messageLineBackgroundColor*16+unsaveFileForegroundColor
#define readOnlyFileColor messageLineBackgroundColor*16+readOnlyFileForegroundColor
#define inputLineColor inputLineBackgroundColor*16+messageLineForegroundColor
#define unusableColor messageLineBackgroundColor*16+unusableSelectionForegroundColor


#define normalLineEnd 0
#define markedLineEnd 1
#define specialFillingChar 7

#include "temark.h--"
#include "vwrite.h--"
#include "teerror.h--"
#include "tefile.h--"
#include "temem.h--"
#include "keyfunc.c--"
#include "teselect.h--"
#include "tesearch.h--"

enum {EDIT,VIET};
enum{NO,YES,CANCEL};
enum {UNSET,PC,UNIX,MAC};

byte newFileName="NEWFILE";
//byte mode=EDIT;

word pMessage = 0;

word tabSize = 4;

byte isInsert = !0;
byte isAutoIndent = !0;
byte isSave = TRUE;
byte isNoName = FALSE;

//#ifdef MouseFunction
:byte isMouse = FALSE;
//#endif

word fileName;
word fileSeg;
word fileSize;
byte fileSystem;
word fileLines;

byte fileNameBuffer[128];
byte inputBuffer[128];

#ifdef Undo
word undoSeg;
word undoSaveSize;
word undoLine = -1;
word undoSaveLines;
word undoSaveX,undoSaveY;
#endif

:word fastcall _GONEXTLINE()
{
//	WHILE(SI <= CSWORD[#fileSize])
	for(;;)
    {
		$lodsb
		//IF(AL == 0) || (AL == 1)
		IF(!$test AL,0FEh) BREAK;
//		return 0;
	}
//	return -1;
}

:word fastcall _GONEXTLINE2()
{
	$push bx
	SI += STRLEN(SI) + 1;
	$pop bx
}

:word fastcall _SKIPLINES(CX)
{
	LOOPNZ(CX)
	{
		$push cx
		_GONEXTLINE();
		$pop cx
	}
}

:void fastcall SETLINEDSSI(CX)
{
	DS = CS;
	DS = fileSeg;
	SI = 0;
	_SKIPLINES(CX);
}

:void fastcall writeLine(SI,DL,AX,CH,CL)
{
	byte X = 0,Y = DL;
	word saveStartX = AX;
	byte normalAttr = CH;
	byte selectionAttr = CL;

	DI = AX;
	VGOTOXY(0,DL);

	for(;;)
	{
		IF(X >= screenCols) return;
		BL = DSBYTE[SI];
		CX = CSWORD[#selectionFirstPoint];
		DX = CSWORD[#selectionSecondPoint];
		IF(CSBYTE[#INSELECTION]) && (SI >= CX) && (SI < DX) AH = selectionAttr;
		ELSE AH = normalAttr;
		IF(BL == 0) || (BL == 1) BREAK;
		SI++;
		IF(BL != '\t')
		{
			IF(DI > 0)
			{
				DI--;
			}
			ELSE
			{
				VWRITEXYA(BL,X,Y,AH);
				X++;
			}
		}
		ELSE
		{
			$push ax
			AX = saveStartX + X - DI;
			BX = CSWORD[#tabSize];
			DX = 0;
			$div bx
			CX = BX - DX;
			IF(DI >= CX)
			{
				$pop ax
				DI -= CX;
			}
			ELSE
			{
				CX -= DI;
				$pop ax
				$push cx
				VWRITEXYNA(' ',X,Y,CL,AH);
				$pop cx
				X += CL;
				DI = 0;
			}
		}
	}
	$push ax
	VWRITEXYNA(' ',X,Y,screenCols - X,normalAttr);
	$pop ax
	VWRITEXYA(' ',X,Y,AH);
}

:void showBufferOnScreen(word startX,startY)
{
	$push ds;
	SETLINEDSSI(startY);
	AX = usefullRows;
	CX = CSWORD[#fileLines] - startY;
	IF(AX > CX) AX = CX;
	//FOR(DX = 0;DX < AX;DX++)
	FOR($cwd;DX < AX;DX++)
	{
		$push dx,ax
		$push dx
		IF(getMarkFromSI())
		{
			CX = markedLineColor * 256 + markedSelectedCharColor;
		}
		ELSE
		{
			CX = normalCharColor * 256 + selectedCharColor;
		}
		$pop dx

		#ifdef ChineseSupport
		$push dx,si
		writeLine(SI,DL,startX,CH,CL);
		$pop si,dx
		#ifdef VariableChineseMode
		IF(CSBYTE[#chineseMode])
		{
		#endif
			chineseCheckFromSI(startX);
			IF(AL)
			{
				$push dx
				VWRITEXYA(' ',0,DL,normalCharColor);
				$pop dx
			}
			chineseCheckFromSI(startX + screenCols);
			IF(AL) VWRITEXYA(' ',screenCols - 1,DL,normalCharColor);
		#ifdef VariableChineseMode
		}
		#endif

		#else
		writeLine(SI,DL,startX,CH,CL);
		#endif
		
		_GONEXTLINE();
		$pop ax,dx
	}

	DX = usefullRows;
	FOR(;AL < DL;AL++)
	{
		$push dx,ax
		CleanLineA(AL,normalCharColor);
		$pop ax,dx
	}
	$pop ds;
}

:void fastcall loadNewFile()
{
	fileSize = 0;
	fileSystem = PC;
	fileLines = 1;
	$push ds
	DS = fileSeg;
	DSBYTE[0] = 0;
	$pop ds
}

:word fastcall checkLines()
{
	$push ds
	DS = fileSeg;
	SI = 0;
	DX = 1;

	WHILE(SI < CSWORD[#fileSize])
	{
		$lodsb
		//IF(AL == 0) || (AL == 1) 
		IF(!$test AL,0FEh) DX++;
	}
	$pop ds
	return DX;
}

:word fastcall getRealFileXY(DI)
{
	$push ds
	DS = fileSeg;
	DX = DI;
	CX = 0;
	BX = -1;
	WHILE(DI > 0)
	{
		DI--;
		AL = DSBYTE[DI];
		//IF(AL == 0) || (AL == 1)
		IF(!$test AL,0FEh)
		{
			IF(BX == -1) BX = DX - DI - 1;
			CX++;
		}
	}
	IF(BX == -1) BX = DX;
	$pop ds
	// Y = CX;
	// X = BX;
}

:word fastcall getRealPointDSSI(BX,CX)
{
	SETLINEDSSI(CX);
	SI += BX;
}

:word fastcall getRealPointDSSIByFile()
{
	getRealPointDSSI(realFileX,realFileY);
}

:word fastcall getRealPoint(BX,CX)
{
	$push ds
	getRealPointDSSI(BX,CX);
	$pop ds
}

:word fastcall getRealPointByFile()
{
	$push ds
	getRealPointDSSIByFile();
	$pop ds
	return SI;
}

:word fastcall loadFile(DX)
{
	IF(OPEN(DX,F_READ) == 0) return FileNotFound;
	BX = AX;
 	
	#ifdef BigFileProtection
	$push bx
	FILESIZE(BX);
	IF(DX > 0) || (CX > 65530)
	{
		ASK("File too big, cut it? (Yes/No)");
		IF(AL != YES) 
		{
			$pop bx
			return FileTooBig;
		}
	}
	CX = 0;
	DX = 0;
	$pop bx
	@LSEEK(BX);
	#endif
	$push ds,es
	DS = fileSeg;
	ES = DS;


	CX = CSWORD[#fileSize] = SI = READ(BX,0,65530);
	CLOSE(BX);

	DSBYTE[SI] = 0;
	SI = 0;
	BH = UNSET;

	$push cx
	WHILE(CX != 0)
	{
		$lodsb
		CX--;
		IF(AL == 0) || (AL == 1)
		{
			DSBYTE[SI-1] = ' ';
			CONTINUE;
		}
		IF(AL != 0Ah) && (AL != 0Dh) CONTINUE;
		IF(BH == UNSET)
		{
			IF(AL == 0Dh) || (DSBYTE[SI] == 0Dh) BH = PC;
			ELSE BH = UNIX;
		}
		DSBYTE[SI-1] = 0;
	}

	$pop dx
	IF(BH == PC)
	{
		SI = DI = 0;
		WHILE(SI <= DX)
		{
			CX = STRLEN(SI) + 1;
			@COPY();
			SI++;
		}
		DI--;
		CSWORD[#fileSize] = DI;
		BH = PC;
	}

	DS = CS;
 	IF(BH == UNSET) BH = PC;
	fileSystem = BH;
	fileLines = checkLines();
	AX = 0;
	$pop es,ds
}

:word fastcall saveFile(DX)
{
	word handle;

	IF(handle = CREATE(DX,FA_NORMAL) == 0) return FileCreateError;

	$push ds
	DS = CS;
	CX = fileLines - 1;
	SI = 0;
	DS = fileSeg;
	DSWORD[0FFFEh] = 0A0Dh;
	WHILE(CX > 0)
	{
		$push cx
		CX = STRLEN(SI);
		DX = SI;
		SI += CX;
		SI++;
		IF(CX > 0)
		{
			IF(WRITE(handle,DX,CX) == 0) GOTO ERROREXIT;
		}
		CX = 1;
		DX = 0FFFEh;
		IF(CSBYTE[#fileSystem] == PC) CX++;
		ELSE DX++;
		IF(WRITE(handle,DX,CX) == 0) GOTO ERROREXIT;
		$pop cx
		CX--;
	}

	CX = CSWORD[#fileSize] - SI;
	IF(CX > 0)
	IF(WRITE(handle,SI,CX) == 0)
	{
	ERROREXIT:
		AX = WriteFileError;
		GOTO EXIT;
	}

	CLOSE(handle);
	AX = 0;
EXIT:
	$pop ds
}

:word fastcall allocMemory(BX)
{
	AH = 48h;
	$int 21h
	IF(CARRYFLAG) AX = 0;
}

:word fastcall freeMemory(AX)
{
	$push es
	ES = AX;
	AH = 49h;
	$int 21h
	$pop es
}

:word fastcall allocSegsForEditor()
{
	IF	(fileSeg = allocMemory(1000h) == 0) 
		#ifdef SelectionFunction
		|| (clipboardSeg = allocMemory(1000h) == 0)
		#endif
		#ifdef Undo
		|| (undoSeg = allocMemory(1000h) == 0) 
		#endif
	{
 		VADJUSTXY();
		VWRITESTRA("Out of memory !",messageLineColor);
		EXIT();
	}
}

:void fastcall showMessage(DX)
{
	pMessage = DX;
}

:void fastcall BIOSBACK()
{
	AL = 08h;
	$int 29h
	AL = ' ';
	$int 29h
	AL = 08h;
	$int 29h
}

:byte fastcall getStringDefault(SI)
inline
{
	BX = SI;
	$push bx
	for(;;)
	{
		$lodsb
		IF(AL == 0) BREAK;
		$int 29h
	}
	CX = STRLEN(BX);
	SI--;
	GOTO startGetString;
}

:byte fastcall getString(SI)
{
	$push si
	CX = 0;

startGetString:

	for(;;)
	{
		BIOSREADKEY();
		IF(AL == 0Dh) BREAK;
		ELSE IF(AL == 8) && (CX != 0)
		{
			BIOSBACK();
			SI--;
			CX--;

			#ifdef VariableChineseMode
			IF(chineseMode)
			{
			#endif
				#ifdef ChineseSupport
				$push cx,si
				SI -= CX;
				chineseCheckFromSI(CX);
				$pop si,cx
				IF(AL) 
				{
					BIOSBACK();
					SI--;
					CX--;
				}
				#endif
			#ifdef VariableChineseMode
			}
			#endif

		}
		ELSE IF(AL == 1Bh)
		{
			IF(CX == 0)
			{
				$pop si
				$push si
				BREAK;
			}
			ELSE
			{
				loop(CX)
				{
					BIOSBACK();
					SI--;
				}
			}
		}
		ELSE
		{
			$call DSWORD[#handleOtherKey];
			IF(AL >= 20h)
			{
				IF(CX < inputBufferLength)
				{
					DSBYTE[SI] = AL;
					SI++;
					CX++;
				}
				ELSE  AL = 7;
				$int 29h
			}
		}
	}
	DSBYTE[SI] = 0;
	$pop si
	IF(AL == 0Dh) && (CX == 0) return 1;
	return DSBYTE[SI];
}

:void fastcall CleanLine(AL)
{
	CL = screenCols;
	CH = 0;
	VWRITEXYN(' ',0,AL,CL);
}

:void fastcall CleanLineA(AL,AH)
{
	CL = screenCols;
	CH = 0;
	VWRITEXYNA(' ',0,AL,CL,AH);
}

:void fastcall CLEANLASTLINE1(AH)
{
	CleanLineA(usefullRows,AH);
}

:void fastcall CLEANLASTLINEN(AH,CX)
{
	loop(CX)
	{
		$push cx
		AL = usefullRows - CL;
		AX++;
		CleanLineA(AL,AH);
		$pop cx
	}
}

:void fastcall showString(SI)
{
	CLEANLASTLINEN(messageLineColor,1);
	VWRITESTRXYA(SI,1,usefullRows,messageLineColor);
	GOTOXY(CX + 1,usefullRows);
}

:void fastcall VWRITEWORDAN(AX,CL,BL,BH)
{
	$push bx
	INT2ASC(AX,#asctmp,CL);
	$pop bx
	$push si,bx
	BH -= AL;
	VWRITESTRNA(#string_5Space,BH,BL);
	$pop bx,si
	VWRITESTRA(SI,BL);
}

:void fastcall showFileInfo()
{
	IF(pMessage != 0)
	{
		showString(pMessage);
//		AL = 7;
//		$int 29h
		pMessage = 0;
		RETURN;
	}
	
	VWRITESTRXYA(" ",0,usefullRows,messageLineColor);

	TRUENAME(fileName,#inputBuffer);
	BX = STRLEN(#inputBuffer);
	MEMCASE(#inputBuffer,BX,LOWCASE);
	SI = #inputBuffer;
	CX = screenCols - 42;
	IF(BX >= CX)
	{
		for(;;)
		{
			$lodsb
			IF(AL == 0) BREAK;
			IF(AL == '\\') DI = SI;
		}
		SI = DI;
	}

	AX = STRLEN(SI);
	CX = screenCols - 37 - AX;
	BX = SI + AX;
	WHILE(CX > 0)
	{
		DSBYTE[BX] = ' ';
		CX--;
		BX++;
	}
	DSBYTE[BX] = 0;
	BH = messageLineColor;
	IF(!isSave) BH = unsaveFileColor;
	#ifdef EnableReadOnly 
	IF(readOnlyMode) BH = readOnlyFileColor;
	#endif

	VWRITESTRA(SI,BH);
//	VGOTOXY(screenCols - 36,usefullRows);

	BX = 6 * 256 + messageLineColor;
	VWRITEWORDAN(screenY + 1,10,BL,BH);
	BX = 6 * 256 + messageLineColor;
	VWRITEWORDAN(screenX + 1,10,BL,BH);
	BX = 6 * 256 + messageLineColor;
	VWRITEWORDAN(fileLines,10,BL,BH);

	getRealPointDSSIByFile();
	AL = DSBYTE[SI];
	DS = CS;

	IF(AL == 1) AL = 0;
	BX = 3 * 256 + messageLineColor;
	VWRITEWORDAN(AL,16,BL,BH);

	SI = #string_OVR;
	IF(isInsert) SI = #string_INS;
	VWRITESTRA(SI,messageLineColor);
	
	SI = #string_5Space;
	IF(isAutoIndent) SI = #string_AUTO;
	VWRITESTRA(SI,messageLineColor);

	SI = #string_PC;
	IF(fileSystem == UNIX) SI = #string_UNIX;
	VWRITESTRA(SI,messageLineColor);
}

:byte string_INS = " INS ";
:byte string_OVR = " OVR ";
:byte string_UNIX = "UNIX ";
:byte string_PC = "PC   ";
:byte string_AUTO = "AUTO ";
:byte string_5Space = "     ";

:byte fastcall ASK(SI)
{
	showString(SI);
	BIOSREADKEY();
	IF(AH == 15h) return YES;
	IF(AH == 31h) return NO;
	return CANCEL;
}

byte fastcall ASKFILENAME()
{
	byte buffer[128];

	IF(getString(#inputBuffer) & 0FEh == 0) return -1;
	IF(TRUENAME(#inputBuffer,#buffer) == 0) 
	{
		showMessage("Invalid file name !");
		return -1;
	}
	return 0;
}


/*:byte fastcall ASKIFSAVE()
{
	showString("Save the file? (Yes/No)");
	BIOSREADKEY();
	IF(AH == 15h) return YES;
	IF(AH == 31h) return NO;
	return CANCEL;
}*/


:fastcall SETFILENAME()
{
	DI = #fileNameBuffer;
	memcpy(DI,#inputBuffer,128);
	fileName = DI;
}


:void fastcall moveCursor(AX)
{
	#ifdef SelectionFunction
	$push ax
	IF(ISSHIFT()) startSelection();
	ELSE IF(INSELECTION)
	{
		$pop ax
		INSELECTION = FALSE;
		IF(AX == LEFT)
		{
				GOTOLINEX(selectionFirstY,selectionFirstX);
				return;
		}
		IF(AX == RIGHT)
		{
				GOTOLINEX(selectionSecondY,selectionSecondX);
				return;
		}
		$push ax
	}
	$pop ax
	#else
	INSELECTION = FALSE;
	#endif

	SWITCH(AX)
	{
	CASE LineUp:
		MOVEUP();
		BREAK;
	CASE LineDown:
		MOVEDOWN();
		BREAK;
	CASE CharLeft:
		MOVELEFT();
		BREAK;
	CASE CharRight:
		MOVERIGHT();
		BREAK;
	CASE LineEnd:
		MOVELINEEND();
		BREAK;
	CASE LineHome:
		IF(realFileX == 0) MOVELINESTART();
		ELSE MOVELINEHOME();
		BREAK;
	CASE PageDown:
		SCROLLPAGEDOWN();
		BREAK;
	CASE PageUp:
		SCROLLPAGEUP();
		BREAK;
	CASE FileHome:
		MOVEFILEHOME();
		BREAK;
	CASE FileEnd:
		MOVEFILEEND();
		BREAK;
	}

	#ifdef VariableChineseMode
	IF(chineseMode)
	{
	#endif
		#ifdef ChineseSupport
		IF(chineseCheck(realFileY,realFileX))
		{
			realFileX--;
			screenX--;
		}	
		#endif
	#ifdef VariableChineseMode
	}
	#endif

	#ifdef SelectionFunction
	IF(ISSHIFT()) endSelection();
	#endif
}

void fastcall NOTHING(){}
:word handleOtherKey = #NOTHING;
:word waitKey = #NOTHING;
:word setKey = #NOTHING;

:void mountNothingOnWaitkey()
{
	waitKey = #NOTHING;
}

:void SETMOUSEXY(CX,DX)
{
	AX = 4;
	$int 33h
}


void main()
{
	allocSegsForEditor();

	#ifdef VariableWindowsSize
	AX = 1130h;
	BH = 0;
	$int 10h
	screenRows = realRows = DL + 1;

	AH = 0Fh;
	$int 10h
	screenCols = realCols = AH;
	usefullRows = screenRows - 1;
	
	#ifdef FloatWindow
	bufferLength = cols - 20;
	#endif
	#endif

	ES = DS;

	IF(@PARAMCOUNT()!=0)
	{
		fileName = PARAMSTR(0);

		IF(TRUENAME(fileName,#inputBuffer) == 0) 
		{
			showMessage("Invalid file name !");
			GOTO MAKENEWFILE;
		}

		IF(loadFile(fileName) !=0)
		{
			#ifdef BigFileProtection
			IF(AX == FileTooBig)
			fileName = #newFileName;	
			#endif
			loadNewFile();
			showMessage("New File !");
		}
		
	}
	ELSE
	{
	MAKENEWFILE:
		fileName = #newFileName;
		isNoName = TRUE;
		loadNewFile();
	}

	CLS();
	RESETXY();
	SETCURSORLINE();
	//CLEANLASTLINEN(messageLineColor,1);
	#ifdef FloatWindow
	CLEANSCROLLLOCK();	
	#endif
	#ifdef MouseFunction
	IF(@RESETMOUSE() == 0ffffh)
	{
		isMouse = TRUE;
		DX = screenRows << 3;
		AX = screenCols << 3;
		SETMOUSEXY(AX,DX);
	}
	#endif

	#ifdef FastRepeatRate
	AX = 305h;
	BX = 0h;
	$int 16h
	#endif

	for(;;)
	{
	mainLoopStart:

		countScroll();
		showBufferOnScreen(scrollX,scrollY);
		showFileInfo();
		GOTOXY(nowCurX,nowCurY);

		#ifdef Undo
		#ifdef EnableReadOnly
		IF(!readOnlyMode)
		#endif
		IF(realFileY != undoLine) 
		{
			$push ds,es
			CX = fileSize;
			undoSaveY = undoLine = realFileY;
			undoSaveX = realFileX;
			undoSaveSize = CX;
			CX++;
			undoSaveLines = fileLines;
			ES = undoSeg;
			DS = fileSeg;
			SI = 0;
			DI = 0;
			@COPY(DI,SI,CX);
			$pop es,ds
		}
		#endif

		#ifdef MarcoFunction
		$call DSWORD[#setKey];
		#endif

		#ifdef MouseFunction
		IF(isMouse) FOR(;;)
		{
			SHOWMOUSE();
			GETMOUSEXY();
			#ifdef MouseMoveCursor
			IF(BL & 1) 
			{
				AX = CX >> 3;
				$push ax
				AX = DX >> 3;
				IF(AX + scrollY >= fileLines) AX = fileLines - 1;
				GOTOLINE(AX);
				$pop ax
				possibleX = AX + scrollX;
				UNCHANGEX();
				GOTO mainLoopStart;
			}
			#endif
			BIOSKEYCHECK();
			IF(!ZEROFLAG) BREAK;			
		}
		#endif

		BIOSREADKEY();

		#ifdef FloatWindow
		$push ax
		//IF(ISSCROLLLOCK())
		WHILE(ISSCROLLLOCK())
		{	
			$pop ax
			handleKeyForScrollLock();
			//continue;			
			GOTO mainLoopStart;
		}
		$pop ax
		#endif

		$call DSWORD[#waitKey];

		IF(AX == 0) continue;
		switch(AX)
		{
		CASE LineUp:
		CASE LineDown:
		CASE CharLeft:
		CASE CharRight:
		CASE LineEnd:
		CASE LineHome:
		CASE PageDown:
		CASE PageUp:
		CASE FileHome:
		CASE FileEnd:
			moveCursor(AX);
			break;

		#ifdef GotoLine
		CASE GotoLine:
			showString("Go to line: ");
			IF	(getString(#inputBuffer) & 0FEh != 0) &&
				(ASC2INT(SI,10) - 1 < fileLines)
			GOTOLINE(AX);
			ADJUSTSCROLL();
			break;
		#endif

		#ifdef LineDelete
		CASE LineDelete:
			#ifdef EnableReadOnly
			IF(readOnlyMode) break;
			#endif
			DELETELINE();
			ADJUSTSCROLL();
			break;
		#endif

		#ifdef FileOpen
		CASE FileOpen:
			#ifdef EnableReadOnly
			IF(!readOnlyMode)
			#endif
			handleFileOpen();
			break;
		#endif

		#ifdef FileName
		case FileName:
			#ifdef EnableReadOnly
			IF(!readOnlyMode)
			#endif

			showString("Enter the new name: ");
			IF(ASKFILENAME() == 0)
			{
				IF(FILEEXIST(#inputBuffer))
				{
					ASK("File exists, overwrite? (Yes/No)");
					IF(AL != YES) break;
				}

				SETFILENAME();
				isSave = FALSE;
				isNoName = FALSE;
			}
			break;
		#endif

		#ifdef FileSave
		case FileSave:
			#ifdef EnableReadOnly
			IF(!readOnlyMode)
			#endif
			handleFileSave();
			break;
		#endif

		case QuickQuit:
			IF(!isSave)
			{
				ASK("Press Y to quit directly  ...");
				IF(AL == YES) break 1;
				break;
			}
			break 1;

		case Quit:
			IF(!isSave)
			{
				ASK("Save the file? (Yes/No)");
				IF(AL == CANCEL)break;
				IF(AL == YES)
				IF(saveFile(fileName) != 0)
				{
					showMessage("Can't save file !");
					break;
				}
			}
			break 1;

		case CharDelete:
			#ifdef EnableReadOnly
			IF(readOnlyMode) break;
			#endif

			#ifdef SelectionFunction
			IF(!INSELECTION) DELETECHAR();
			deleteSelection();
			#else
			DELETECHAR();
			#endif
			break;

		case CharDeleteBack:
			#ifdef EnableReadOnly
			IF(readOnlyMode) break;
			#endif

			#ifdef SelectionFunction
			IF(!INSELECTION)
			{
			#endif
				IF(realFileX | realFileY != 0) 
				{
					#ifdef ChineseSupport
					IF
					#ifdef VariableChineseMode
					(chineseMode) && 
					#endif
					(chineseCheck(realFileY,realFileX - 1))
					{
						realFileX -= 2;
						DELETECHAR();
					}
					ELSE
					{
						MOVELEFT();			
						DELETECHAR();
					}
					#else
					MOVELEFT();				
					DELETECHAR();
					#endif
				}
			#ifdef SelectionFunction
			}
			deleteSelection();
			#endif
			break;

	#ifdef SelectionFunction

		#ifdef SelectionCopy
		case SelectionCopy:
			copySelection();
			break;
		#endif

		#ifdef SelectionPaste
		case SelectionPaste:
			#ifdef EnableReadOnly
			IF(readOnlyMode) break;
			#endif

			deleteSelection();
			AX = fileSize;
			$add ax,clipboardSize;
			IF(CARRYFLAG) || (AX >= 65530)
			{
				showMessage("Size limit is 65530 bytes!");
			}
			ELSE pasteSelection();
			break;
		#endif

		#ifdef SelectionCut
		case SelectionCut:
			#ifdef EnableReadOnly
			IF(readOnlyMode) break;
			#endif

			copySelection();
			deleteSelection();
			break;
		#endif
		
		#ifdef SelectAll
		case SelectAll:
			setSelection(0,fileSize);
			break;
		#endif

	#endif
	
	#ifdef MarcoFunction

		#ifdef KeyRecord
		case KeyRecord:
			DSWORD[#waitKey] = #keyRec;
			keyRecCount = 0;
			showMessage("Recording ...  (Ctrl+R to stop)");
			break;
		#endif

		#ifdef KeyPlayback
		case KeyPlayback:
			playCount = 0;
			DSWORD[#setKey] = #keyPlay;
			isPlayback = TRUE;
			//keyPlay();
			break;
		#endif

	#endif

	#ifdef OtherFunction

		#ifdef DosShell
		case DosShell:
			dosShell();
			break;
		#endif

		#ifdef Help
		case Help:
			IF(!FILEEXIST("TE.TXT")) 
			{
				showMessage("TE.TXT doesn't exist !");
				break;
			}
			IF(allocMemory(200h) == 0)
			{
				showMessage("Out of memory !");
				break;
			}
			enterView(AX);
			fileName = "TE.TXT";
			IF(loadFile(fileName) !=0)
			{
				showMessage("Can't open TE.TXT !");
				exitView();
			}
			RESETXY();
			#ifdef EnableReadOnly 
			readOnlyMode = TRUE;
			#endif
			waitKey = #handleKeyForView;
			break;
		#endif

		#ifdef Undo
		case Undo:
			#ifdef EnableReadOnly
			IF(readOnlyMode) break;
			#endif

			$push ds,es
			CX = undoSaveSize;
			fileSize = CX;
			CX++;
			ES = fileSeg;
			DS = undoSeg;
			SI = 0;
			DI = 0;
			@COPY(DI,SI,CX);
			$pop es,ds
			fileLines = undoSaveLines;
			GOTOLINEX(undoSaveY,undoSaveX);
			ADJUSTSCROLL();
			INSELECTION = FALSE;

			break;
		#endif

	#endif


	#ifdef FormatFunction

		#ifdef SelectionFunction
		#ifdef UpperCase
		case UpperCase:
			#ifdef EnableReadOnly
			IF(readOnlyMode) break;
			#endif

			changeSelectionCase(UPCASE);
			break;
		#endif

		#ifdef LowerCase
		case LowerCase:
			#ifdef EnableReadOnly
			IF(readOnlyMode) break;
			#endif

			changeSelectionCase(LOWCASE);
			break;
		#endif
		#endif

		#ifdef TrimSpace
		case TrimSpace:
			#ifdef EnableReadOnly
			IF(readOnlyMode) break;
			#endif

			#ifdef SelectionFunction
			IF(!INSELECTION) trimTail(0,fileSize);
			trimSelectionTail();
			#else
			trimTail(0,fileSize);
			#endif
			break;
		#endif

		#ifdef IndentMore
		case IndentMore:
			#ifdef EnableReadOnly
			IF(readOnlyMode) break;
			#endif

			#ifdef Ctrl_Shift_I_IndentLess
			IF(ISSHIFT()) GOTO IndentLessLabel;
			#endif

			#ifdef SelectionFunction
			IF(INSELECTION)
			{
				IF(selectionSecondX == 0) selectionSecondY--;
				FOR(DX = 0,CX = selectionFirstY;CX <= selectionSecondY;CX++,DX++)
				{
					$push cx,dx
					incIndent(CX);
					$pop dx,cx
				}
				DI = selectionFirstPoint;
				DX += selectionSecondPoint - DI;
				setSelection(DI,DX);
			}
			ELSE incIndent(realFileY);
			#else
			incIndent(realFileY);
			#endif
			break;
		#endif

		#ifdef IndentLess
		case IndentLess: 
			#ifdef EnableReadOnly
			IF(readOnlyMode) break;
			#endif

			IndentLessLabel:
			#ifdef SelectionFunction
			IF(INSELECTION)
			{
				IF(selectionSecondX == 0) selectionSecondY--;
				FOR(BX = 0,CX = selectionFirstY;CX <= selectionSecondY;CX++)
				{
					$push cx,bx
					decIndent(CX);
					$pop bx
					BX += AX;
					$pop cx
				}
				DI = selectionFirstPoint;
				DX = selectionSecondPoint - DI - BX;
				setSelection(DI,DX);
			}
			ELSE decIndent(realFileY);
			#else
			decIndent(realFileY);
			#endif
			break;	
		#endif

	#endif


	#ifdef SearchFunction
		#ifdef SearchReplace
		case SearchReplace:
			#ifdef EnableReadOnly
			IF(readOnlyMode) break;
			#endif

			IF(showReplaceDialog() == 0) break;
			IF(replaceMethod == AllInSelection)
			{
				replaceAllInSelection();
				showOccurrences();
				GOTOLINEX(selectionFirstY,selectionFirstX);
				#ifdef Undo
				undoLine = realFileY;
				#endif
			}
			ELSE IF(replaceMethod == AllInFile)
			{
				replaceAll();
				showOccurrences();
			}
			ELSE
			{
				findNextFromNow();
				checkWarpAtEnd();
				IF(AX == -1)
				{
					INSELECTION = FALSE;
					showMessage("Not found");
				}
				ELSE
				{
					waitKey = #handleKeyForReplaceNext;
					showMessage("Replace this occurence? (Yes/No/All/Cancel)");
				}
			}
			break;
		#endif

		#ifdef SearchFind
		case SearchFind:
			IF(showFindDialog() == 0) break;
		#ifdef SearchFindNext
		case SearchFindNext:
		#endif
			findNextFromNow();
			checkWarpAtEnd();
			IF(CARRYFLAG) showMessage("Passed thd end of the file");
			IF(AX == -1) 
			{
				INSELECTION = FALSE;
				showMessage("Not found");
			}
			break;
		#endif

		#ifdef CasesensitiveToggle
		case CasesensitiveToggle:
			findCaseSensitive ^= NonCaseSensitive;
			IF(findCaseSensitive == CaseSensitive)
			{
				showMessage("Search case-sensitive enable");
			}
			ELSE
			{
				showMessage("Search case-sensitive disable");
			}
			break;
		#endif
	#endif

	#ifdef MarkerFunction
		
		#ifdef MarkerToggle
		case MarkerToggle:
			switchMark(realFileY);
			break;
		#endif

		#ifdef MarkerNext
		case MarkerNext:
			IF(searchNextMark(realFileY) != -1)
			{
				GOTOLINE(AX);
				ADJUSTSCROLL();
			}
			break;
		#endif

	#endif

	#ifdef OptionFunction
		
		#ifdef SwitchInsertMode
		case SwitchInsertMode:
			!isInsert;
			IF(isInsert) SETCURSORLINE();
			ELSE SETCURSORBLOCK();
			break;
		#endif

		#ifdef SetTabSize
		case SetTabSize:
			showString("Set tab size : ");
			IF	(getString(#inputBuffer) & 0FEh != 0) &&
				(ASC2INT(SI,10) < 256) &&
				(AX > 0)
				tabSize = AX;
			break;
		#endif

		#ifdef SwitchAutoIndent
		case SwitchAutoIndent:
			#ifdef EnableReadOnly
			IF(readOnlyMode) break;
			#endif

			!isAutoIndent;
			break;
		#endif
		
		#ifdef SetFileSystem
		case SetFileSystem:
			#ifdef EnableReadOnly
			IF(readOnlyMode) break;
			#endif

			IF(fileSystem == PC) fileSystem = UNIX;
			ELSE fileSystem = PC;
			isSave = FALSE;
			break;
		#endif

		#ifdef VariableChineseMode
		#ifdef SwitchChineseMode
		case SwitchChineseMode:
			chineseMode ^= TRUE;
			IF(chineseMode)
			{
				showMessage("Chinese mode turned on");
			}
			ELSE
			{
				showMessage("Chinese mode turned off");
			}
			BREAK;
		#endif
		#endif

		#ifdef DosShellSet
		case DosShellSet:
			showString("Command: ");
			getStringDefault(#childDTA + 4);
			IF(AL & 0FEh == 0)
			{
				childDTA[0] = 0;
			}
			ELSE
			{
				STRLEN(#childDTA + 4);
				childDTA[0] = AL + 3;
			}
			BREAK;
		#endif

	#endif

		default:
			#ifdef EnableReadOnly
			IF(readOnlyMode) BREAK;
			#endif

			SWITCH(AL)
			{
			CASE 20h...0FEh:
			CASE '\t':
			CASE 0Dh:

				#ifdef SelectionFunction
				$push ax
				deleteSelection();
				$pop ax
				#endif

				IF(fileSize >= 65530)
				{
					showMessage("Size limit is 65530 bytes!");
					BREAK;
				}				
				IF(AL == 0Dh)
				{
					NEWLINE();
					IF(isAutoIndent) AUTOINDENT();
				}
				ELSE
				{
					CX = realLength;
					IF(realFileX == CX) || (isInsert) INSERTCHAR(AL);
					ELSE MODIFYCHAR(AL);
				}
			}
		}

	}

	CLEANLASTLINEN(7,1);
	GOTOXY(0,usefullRows);
	#ifdef MouseFunction
	IF(isMouse) HIDEMOUSE();
	#endif
}


byte handleFileSave() // return TRUE = save succeed, FALSE = faild
{
	IF(isNoName) && (FILEEXIST(fileName))
	{
		ASK("File exists, overwrite? (Yes/No)");
		IF(AL != YES) return;
		isNoName = FALSE;
	}
	IF(saveFile(fileName) != 0)		
	{
		showMessage("Can't save file !");
		return FALSE;
	}
	ELSE AL = isSave = TRUE;
}

void handleFileOpen()
{
	IF(!isSave)
	{
		ASK("Save the file? (Yes/No)");
		IF(AL == CANCEL) RETURN;
		IF(AL == YES)
		{	
			handleFileSave();
			IF(!AL) RETURN;
		}
	}

	showString("Open file: ");
	IF(ASKFILENAME()) RETURN;
	SETFILENAME();

	isSave = TRUE;
	IF(loadFile(fileName) !=0)
	{
		#ifdef BigFileProtection	
		IF(AX == FileTooBig) return;
		#endif
		loadNewFile();
		showMessage("New File !");
		isNoName = FALSE;
		isSave = FALSE;
	}
	RESETXY();		
	#ifdef EnableReadOnly
	IF(readOnlyMode) {
	#endif

	#ifdef Undo
	undoLine = -1;
	#endif

	#ifdef EnableReadOnly
	}
	#endif
}