'#define Win9x
#include "keys.bi"
#include "list.bi"
#include "misc.bi"
#include "declar.bi"
#include "undo.bi"
#include "encod.bi"
#include "mcons.bi"
#include "pos.bi"
#include "getkey.bi"
#include "cb.bi"
#include "cursor.bi"
#include "goto.bi"
#include "find.bi"
#include "paste.bi"
#include "files.bi"
#include "draw.bi"
#include "buffer.bi"
#include "help.bi"
#include "setting.bi"
#include "run.bi"

' инициализация начальных данных
sub InitNew()
	
	dim as string sFile = Command()
	
	pObj.pList.Add(0) ' просто добавим пустую строку
	
	pObj.iCurentCursorRowInWindow = 1 ' первая строка на экране
	
	pObj.iCurentPosInRow = 1 ' первая позиция в строке связного списка
	
	pObj.iStartRowInWindow = 1 ' первая видимая строка равна 1
	
	pObj.iScrollWidth = 1 ' нет прокрутки
	
	LoadSetting() ' загрузим настройки подсветки , если есть 
	
	GetWHConsole() ' получаем размеры консольного окна по высоте и ширине в символах
	
	pObj.iPrevWidthConsole = pObj.iWidthSimbols ' сохраняем ширину в символах (нужно при изменении размеров консоли)
	
	pObj.iPrevHeightConsole = pObj.iHeightRows ' сохраняем высоту в символах (нужно при изменении размеров консоли)
	
	SetLenghtNumbers() ' устанавливаем размер длины номеров строк
	
	pObj.iCurentCursorPosInWindow = pObj.iLenghtNumbers+2 ' позиция сразу после номеров строк (lenght+space+1)
	
	pObj.iInsertMode = 1 ' режим вставки
	
	pObjFB.iFlagSave = 1 ' файл пока не нуждается в сохранении
	
	#ifdef __UNIX_SYSTEM__
		
		shell "tabs 1"
		
		OpenTTY() ' откроем устройство терминала
		
		Init_Custom_Keys() ' инициализация терминала для установки отлова клавиш
		
		pObj.iParametersClipBoard = OpenClipBoard() ' проверяем в какой TTY находимся
		
		if pObj.iParametersClipBoard then ' если графический TTY
			
			CloseClipBoard() 'закрываем указатель на Display ptr
			
		EndIf
		
	#endif
	
	#ifdef __FB_win32__
		'shell "chcp 65001"
		
		pTConsole.hStdin = w32GetStdHandle(w32STD_INPUT_HANDLE) ' Получим хендл консоли для чтения
		pTConsole.hStdOutOld = w32GetStdHandle(w32STD_OUTPUT_HANDLE) ' Получим хендл консоли для чтения
		w32SetConsoleMode(pTConsole.hStdin , 8) ' включаем режим для перехватывания CTRL+C , CTRL+S
		#ifdef win9x
			pTConsole.hNewStdOut = pTConsole.hStdOutOld ' используем стандартную консоль
			w32SetThreadPriority(w32GetCurrentThread(),w32THREAD_PRIORITY_ABOVE_NORMAL) ' приоритет ставим повыше , чтобы не было торможений
		#else
			pTConsole.hNewStdOut = w32CreateConsoleScreenBuffer( w32GENERIC_READ OR w32GENERIC_WRITE, w32FILE_SHARE_READ OR w32FILE_SHARE_WRITE,_
			0, w32CONSOLE_TEXTMODE_BUFFER, 0) ' создадим новый буфер для консоли
			w32SetConsoleActiveScreenBuffer(pTConsole.hNewStdOut) ' установим новый буфер для консоли
			w32SetConsoleCP(65001) ' установим кодировку юникод
		#endif
		pObj.iParametersClipBoard = 1 ' буфер обмена стандартный для windows
		
		' проверяем поддержку рисования азиатских символов в консоли
		' не очень надежный способ , но другого я не нашел
		scope
			dim as Long iLocaleCount
			for i as Long = 0 to 7
				iLocaleCount+=w32IsDBCSLeadByte(iChineseBytes(i))
			Next
			if iLocaleCount > 3 then iLocaleWideSupport = 1
		end scope
		#ifndef Win9x
			dim as any ptr hWinConsole = w32GetConsoleWindow() ' получим окно консоли
			' поменяем стиль , запрещая изменять размер
			w32SetWindowLong(hWinConsole, w32GWL_STYLE, w32GetWindowLong(hWinConsole, w32GWL_STYLE) and not(w32WS_MAXIMIZEBOX or w32WS_SIZEBOX))
		#endif
		while len(INKEY) ' очистим буфер клавиш
		Wend
	#EndIf
	
	#ifdef __FB_DOS__
		__djgpp_set_ctrl_c(0)  ' включаем режим для перехватывания CTRL+C
		cls
	#EndIf
	
	if len(sFile) then
		
		sFile = CheckPath(sFile) ' проверим путь на относительность и если что заменим полным путем
		
		' если загрузка файла успешна
		If LoadFile(sFile) Then
			
			SetFileName(sFile) ' сохраним его имя
			
		endif
		
	EndIf
	
	ClearLine(pObj.iHeightRows+1) ' чистка последней строки для покраски
	
	SetDrawsRowsFlags(-1,0)
	
	DrawRowsEditor() ' первоначальная прорисовка
	
End Sub

' диалог подтверждения выхода из редактора
function ExitEditor() as LONG
	
	' очистим строку
	ClearLine(pObj.iHeightRows)
	
	' выводим подсказку
	DrawInPos(0 , "Quit? (ENTER - Yes \ ESC - No)" , pObj.iHeightRows , 1 , (pObj.iColorBackGround shl 4) or pObj.iColorWarning)
	
	do
		
		dim as Long iKey = GetOnlyAscKey() ' получим клавишу
		
		if iKey = CVK_ENTER then ' выходим
			
			if pObjFB.iFlagSave = 0 then ' если файл не сохранен
				
				FileDlgNotSave() ' выводим диалог запроса сохранения
				
			EndIf
			
			#ifdef __FB_DOS__
				__djgpp_set_ctrl_c(1)  ' отключаем режим для перехватывания CTRL+C
				color 15 ' сбрасываем цвет текста на белый
			#EndIf
			
			#ifdef __UNIX_SYSTEM__
				DeInit_Custom_Keys()
				printf !"\027[0m" ' сбрасываем цвета по умолчанию
			#EndIf
			
			#ifdef __FB_WIN32__
				#ifndef Win9x
					w32SetConsoleActiveScreenBuffer(pTConsole.hStdOutOld) ' вернем старый буфер
					w32CloseHandle(pTConsole.hNewStdOut) ' закроем работающий буфер
				#endif
			#EndIf
			
			cls
			
			return 1 ' возвратим успешный статус
			
		elseif iKey = CVK_ESC then ' продолжаем работу в редакторе
			
			' очистим последние линии
			ClearLine(pObj.iHeightRows-1)
			ClearLine(pObj.iHeightRows)
			
			bRepaintAnyway = 1 'перерисовать экран
			
			exit do ' выходим из цикла
			
		EndIf
		
	loop
	
End Function

InitNew() ' инициализируем различные значения

do
	
	dim as wstring ptr pwsSymbol ' буфер для получения юникод символа
	
	iInkey = GetKeyUni(pwsSymbol) ' получим обычный или юникод символ
	
	if iInkey = 0 andalso pwsSymbol = 0 then ' если нет нажатых клавиш
		
		#ifdef __UNIX_SYSTEM__
			CheckSizeConsole() ' проверим изменился ли размер консоли
			sleep(5) ' подождем и дадим передохнуть процессору
		#endif
		#ifdef __FB_WIN32__
			sleep(1) ' для windows небольшая
		#EndIf
		#ifdef __FB_Dos__
			usleep(1000) ' для dos пауза небольшая
		#endif
		
		continue do ' поехали на новый виток цикла
		
	EndIf
	
	if iInkey then ' если нажата обычная клавиша (не юникод)
		
		select case iInkey ' что это за клавиша?
				
			case CVK_CTRL_C
				
				' копируем текст
				CopyText()
				
			case CVK_CTRL_Z
				
				' откат назад
				tUD.Undo()
				
			case CVK_CTRL_Y
				
				' откат вперед
				tUD.Redo()
				
			case CVK_ESC
				
				if pObj.iMarkerSelectionStart then ' если включено выделение
					
					if iMode_F2_Selection then ' если включен режим выделения по клавише CTRL+6
						
						SetMarkerSelectionMode() ' отключим его
						
					EndIf
					
					SetMarkerSelection(1) ' удалим выделение
					
				else
					
					if ExitEditor() then ' если пользователь подтвердил выход
						
						exit do ' выходим из главного цикла
						
					EndIf
					
				endif
				
			case CVK_CTRL_Q
				
				if ExitEditor() then ' если пользователь подтвердил выход
					
					exit do ' выходим из главного цикла
					
				EndIf
				
			case CVK_CTRL_A
				
				' выделим весь текст
				SelectAll()
				
			case CVK_CTRL_F
				
				SetMarkerSelection(1) ' сбросим выделение
				
				' выводим все строки на экран
				DrawRowsEditor()
				
				' диалог поиска
				FindReplaceBox()
				
				bRepaintAnyway = 1 ' обновим экран
				
			case CVK_CTRL_R
				
				SetMarkerSelection(1) ' сбросим выделение
				
				' выводим все строки на экран
				DrawRowsEditor()
				
				' диалог замены
				FindReplaceBox(1)
				
				bRepaintAnyway = 1 ' обновим экран
				
			case CVK_CTRL_G
				
				SetMarkerSelection(1) ' сбросим выделение
				
				' выводим все строки на экран
				DrawRowsEditor()
				
				' переходим на нужную линию в редакторе
				GotoBox()
				
				bRepaintAnyway = 1 ' обновим экран
				
			case CVK_CTRL_S
				
				' сохраняем файл
				FileBoxSave()
				
				bRepaintAnyway = 1 ' обновим экран
				
			case CVK_CTRL_O
				
				' проверяем загружен ли уже файл и загружаем новый файл
				FileCheckLoad()
				
				bRepaintAnyway = 1 ' обновим экран
				
			Case CVK_BACKSPACE
				
				' удаляем символ
				BackSpace()
				
				' флаг сохранения сбрасываем (теперь файл не сохранен)
				pObjFB.iFlagSave = 0
				
			case CVK_TAB
				
				' добавление символа табуляции в текст
				AddSymBols(WCHR(9))
				
				' флаг сохранения сбрасываем (теперь файл не сохранен)
				pObjFB.iFlagSave = 0
				
			case CVK_HOME
				
				if iMode_F2_Selection = 0 then ' если режим выделения не включен
					
					SetMarkerSelection(1) ' сбросим выделение
					
				EndIf
				
				' курсор на начало строки
				SetPositionInStartLine()
				
				bRepaintAnyway = 1 ' обновим экран
				
			case CVK_END
				
				if iMode_F2_Selection = 0 then ' если режим выделения не включен
					
					SetMarkerSelection(1) ' сбросим выделение
					
				EndIf
				
				' курсор на конец строки
				SetPositionInEndLine()
				
				bRepaintAnyway = 1 ' обновим экран
				
			case CVK_CTRL_HOME
				
				if iMode_F2_Selection = 0 then ' если режим выделения не включен
					
					SetMarkerSelection(1) ' сбросим выделение
					
				EndIf
				
				' курсор на начало текста
				SetPosition(1) ' переход на начало текста
				
				bRepaintAnyway = 1 ' обновим экран
				
			case CVK_CTRL_END
				
				if iMode_F2_Selection = 0 then ' если режим выделения не включен
					
					SetMarkerSelection(1) ' сбросим выделение
					
				EndIf
				
				' курсор на конец текста
				SetPosition(100000000) ' переход на конец текста
				
				bRepaintAnyway = 1 ' обновим экран
				
			case CVK_PAGEUP
				
				if iMode_F2_Selection = 0 then ' если режим выделения не включен
					
					SetMarkerSelection(1) ' сбросим выделение
					
				EndIf
				
				' курсор вверх на одну страницу
				CursorPageUp()
				
			case CVK_PAGEDOWN
				
				if iMode_F2_Selection = 0 then ' если режим выделения не включен
					
					SetMarkerSelection(1) ' сбросим выделение
					
				EndIf
				
				' курсор вниз на одну страницу
				CursorPageDown()
				
			case CVK_DELETE
				
				' удаляем символ
				DeleteKey()
				
				' флаг сохранения сбрасываем (теперь файл не сохранен)
				pObjFB.iFlagSave = 0
				
			case CVK_LEFT
				
				if iMode_F2_Selection = 0 then ' если режим выделения не включен
					
					SetMarkerSelection(1) ' сбросим выделение
					
				EndIf
				
				' курсор влево
				CursorInLeft()
				
			case CVK_RIGHT
				
				if iMode_F2_Selection = 0 then ' если режим выделения не включен
					
					SetMarkerSelection(1) ' сбросим выделение
					
				EndIf
				
				' курсор вправо
				CursorInRight()
				
			case CVK_UP
				
				if iMode_F2_Selection = 0 then ' если режим выделения не включен
					
					SetMarkerSelection(1) ' сбросим выделение
					
				EndIf
				
				' курсор вверх
				CursorInUp()
				
			case CVK_DOWN
				
				if iMode_F2_Selection = 0 then ' если режим выделения не включен
					
					SetMarkerSelection(1) ' сбросим выделение
					
				endif
				
				' курсор вниз
				CursorInDown()
				
			case CVK_INSERT
				
				' переключаем флаг редактирования (замены\вставка) 
				pObj.iInsertMode xor= 1 
				
			case CVK_ENTER
				
				if pObj.iMarkerSelectionStart then ' если есть выделение
					
					' удалить выделенный текст
					DeleteSelection()
					
				EndIf
				
				' курсор на новую строку
				CursorInNewLine(1)
				
				' флаг сохранения сбрасываем (теперь файл не сохранен)
				pObjFB.iFlagSave = 0
				
				if pObj.iFlagHighlight then ' если подсветка включена
					
					' Подсчитаем многострочные комментарии
					CalcMultiComments()
					
				EndIf
				
			case CVK_CTRL_V
				
				' вставляем текст из буфера обмена
				PasteText()
				
				' флаг сохранения сбрасываем (теперь файл не сохранен)
				pObjFB.iFlagSave = 0
				
				bRepaintAnyway = 1 ' обновим экран
				
			case CVK_CTRL_X
				
				' вырезаем текст
				CopyText(1)
				
				bRepaintAnyway = 1 ' обновим экран
				
			case CVK_SHIFT_LEFT
				
				' устанавливаем маркер выделения , если не установлен
				SetMarkerSelection()
				
				' курсор влево
				CursorInLeft()
				
			case CVK_SHIFT_RIGHT
				
				' устанавливаем маркер выделения , если не установлен
				SetMarkerSelection()
				
				' курсор влево
				CursorInRight()
				
			case CVK_SHIFT_UP
				
				' устанавливаем маркер выделения , если не установлен
				SetMarkerSelection()
				
				' курсор влево
				CursorInUP()
				
			case CVK_SHIFT_DOWN
				
				' устанавливаем маркер выделения , если не установлен
				SetMarkerSelection()
				
				' курсор влево
				CursorInDown()
				
			case CVK_SHIFT_HOME
				
				' устанавливаем маркер выделения , если не установлен
				SetMarkerSelection()
				
				' курсор на начало текущей строки
				SetPositionInStartLine()
				
				bRepaintAnyway = 1 ' обновим экран
				
			case CVK_SHIFT_END
				
				' устанавливаем маркер выделения , если не установлен
				SetMarkerSelection()
				
				' курсор на конец текущей строки
				SetPositionInEndLine()
				
				bRepaintAnyway = 1 ' обновим экран
				
			case CVK_F8
				
				UnComment() ' раскомментирование
				
				bRepaintAnyway = 1 ' обновим экран
				
			case CVK_F9
				
				Comment() ' комментирование
				
				bRepaintAnyway = 1 ' обновим экран
				
			case CVK_F5,CVK_F6
				
				if pObjFB.pszFileName andalso len(*(pObjFB.pszFileName)) then ' если файл был сохранен
					
					SaveFile(*(pObjFB.pszFileName) , 1) ' быстрое сохранение
					
					RunScript(iInkey) ' запуск скрипта (компиляции или чего другого)
					
				else
				
					SaveNameForQuickRun() ' временно сохраним имя
					
					SaveFile(*(pObjFB.pszFileName) , 1) ' быстрое сохранение
					
					RunScript(iInkey) ' запуск скрипта (компиляции или чего другого)
					
					ClearTempName() ' очистим имя
					
				EndIf
				
			case CVK_F3,CVK_F4,CVK_F7,CVK_F12
				
				' ничего пока не делаем
				
			case CVK_F1
				
				help() ' помощь
				
				bRepaintAnyway = 1 ' обновим экран
				
			case CVK_F2
				
				SetMarkerSelectionMode() ' установим\удалим режим выделения
				
			case is > 31 ' если текстовый символ
				#ifdef Win9x
					' преобразуем символ из OEM в UNICODE
					dim as wstring ptr pwsTemp = ASCIITOUTF(chr(iInkey), w32CP_OEM)
					if pwsTemp then
						' добавим символ в текущую строку	
						AddSymBols(pwsTemp)
						deallocate(pwsTemp)
					endif
				#else
					' добавим символ в текущую строку	
					AddSymBols(Wchr(iInkey))				
				#endif
				' флаг сохранения сбрасываем (теперь файл не сохранен)
				pObjFB.iFlagSave = 0
				
		End Select
		
		' если не нажаты клавиши UP , DOWN , PAGE UP , PAGE DOWN
		if iInkey <> CVK_UP andalso iInkey <> CVK_DOWN _
		andalso iInkey <> CVK_PAGEUP andalso iInkey <> CVK_PAGEDOWN _
		andalso iInkey <> CVK_SHIFT_UP andalso iInkey <> CVK_SHIFT_DOWN then
			
			' сбрасываем позицию при нажатиях клавиш вверх\вниз
			pObj.iCursorSafePosForUpDown = 0
			
		EndIf
		
		' выводим все строки на экран
		DrawRowsEditor()
		
	elseif pwsSymbol then ' если символ юникода
		
		' добавим символ в текущую строку
		AddSymBols(pwsSymbol)
		
		' освободим память для буфера клавиши
		deallocate(pwsSymbol)
		
		' обнулим буфер клавиши
		pwsSymbol = 0
		
		' сбрасываем позицию при нажатиях клавиш вверх\вниз
		pObj.iCursorSafePosForUpDown = 0
		
		' флаг сохранения сбрасываем (теперь файл не сохранен)
		pObjFB.iFlagSave = 0
		
		' выводим все строки на экран
		DrawRowsEditor()
		
	endif
	
Loop