#include "pch.h"
#include "bk2ibm.h"

void ITCPC::BK2IBM(std::unique_ptr<CBaseFile> pInFile, std::unique_ptr<CBaseFile> pOutFile, const bool bVortex)
{
	if (pInFile == nullptr || pOutFile == nullptr)
	{
		std::_tcout << _T("Недостаточно памяти.\n");
		return;
	}

	if (!pInFile->Open(false))
	{
		std::_tcout << _T("Ошибка! '") << pInFile->getFileName()._tstring() << _T("' не открывается.\n");
		return;
	}

	if (!pOutFile->Open(true))
	{
		std::_tcout << _T("Ошибка! '") << pOutFile->getFileName()._tstring() << _T("' не открывается.\n");
		return;
	}

	if (bVortex)
	{
		int counter = 0, nExp = 1;

		if (pInFile->ReadWord() == 0x0c40)
		{
			// это мы пропускаем всякие шрифты и доп.модули
			counter = pInFile->ReadWord();
		}

		pInFile->SetPos(counter);
		counter = 0; // счётчик символов в строке

		while (!pInFile->isEOF())
		{
			auto tch = pInFile->ReadChar();

			if (tch == 0 || tch == CHR_N) // конец строки
			{
				pOutFile->WriteChar(L'\n');
				counter = 0;
				nExp = 1;
				continue;
			}

			if (tch < CHR_TAB) // обычно это просто количество пробелов, но бывает и количество табуляторов.
			{
				// эти байты используются для упаковки пробелов по
				// следующей формуле: N=A1+10*А2+100*А3+... , где
				// N-число пробелов, А1,А2,А3... последовательные
				// байты от 1 до 10
				for (TCHAR i = 0; i < tch * nExp; ++i)
				{
					pOutFile->WriteChar(_T(' ')); counter++;
				}

				nExp *= 8; // следующее подряд число - количество пробелов второго порядка и т.д.
				continue;
			}

			if (tch == CHR_TAB) // табуляция, по 8 символов на табулятор
			{
				int nNextTabPos = (counter / pInFile->getTabWidth() + 1) * pInFile->getTabWidth();

				do
				{
					pOutFile->WriteChar(_T(' ')); counter++;
				}
				while (counter < nNextTabPos);

				nExp = 1;
				continue;
			}

			if (tch < CHR_SPACE)
			{
				nExp = 1;
				continue; // эти коды в vxt используются для визуального форматирования, типа жирный текст, курсив и т.п.
			}

			nExp = 1;
			pOutFile->WriteChar(tch); counter++;
		}
	}
	else // это разные вариации TED, Edasp, Micro и т.п.
	{
		int counter = 0; // начнём с начала строки

		while (!pInFile->isEOF())
		{
			auto tch = pInFile->ReadChar();
			int repeater = 0;

			if (tch == 0 || tch == CHR_N) // перевод строки
			{
				tch = L'\n';
				counter = -1;
			}
			else if (tch == CHR_TAB) // табуляция
			{
				int nNextTabPos = (counter / pInFile->getTabWidth() + 1) * pInFile->getTabWidth();

				do
				{
					pOutFile->WriteChar(_T(' ')); counter++;
				}
				while (counter < nNextTabPos);

				continue;
			}
			else if (tch < CHR_SPACE) // это количество пробелов, или табуляций
			{
				for (uint32_t i = 0; i < tch; ++i)
				{
					pOutFile->WriteChar(_T(' ')); counter++;
				}

				continue;
			}
			else if (tch == 0200 || tch == 0201)
			{
				// возможно, надо будет и следующий за этим символом сивол проигнорировать
				continue;
			}
			else
			{
				bool bEof = false;

				while (0202 <= tch && tch < 0240) // то это количество следующих за кодом повторяющихся символов
				{
					repeater += (tch & 037);

					if (pInFile->isEOF()) // тут може случиться конец файла
					{
						bEof = true;
						break; // и надо прервать этот цикл, и внешний сразу.
					}

					tch = pInFile->ReadChar();
				}

				if (bEof) // на какую только хрень не пойдёшь, чтоб goto не использвать
				{
					break;
				}

				// какая-то непонятная фигня. если после счётчика повторений коды 0..37, то они мапятся на 40..77
				if (tch < 040)
				{
					tch += 040;
				} // это редкий диалект. обычно эта штука может вносить артефакты в текст
			}

			if (repeater == 0)
			{
				pOutFile->WriteChar(tch); counter++;
			}
			else
			{
				for (int i = 0; i < repeater; ++i)
				{
					pOutFile->WriteChar(tch); counter++;
				}
			}
		}
	}
}

