// str_engineering.cpp

#include "StdAfx.h"
#include "aplValue.h"
#include "StepData.h"
//#include "step_ql.h"
//#include "step_ql_ex.h"

//////////////////////////////////////////////////////////
bool IsRezSym(TCHAR c)
{
	switch(c)
	{
	//case '.':
	case _T(';'):
	case _T(','):
	case _T('\r'):
    case _T('\n'):
    case _T('\t'):
    case _T(' '):
    case _T('('):
	case _T(')'):
	case _T('='):
	case _T('>'):
	case _T('<'):
	case _T(':'):
	case _T('!'):
		//	case _T('+'):
	case _T('*'):
		//case _T('-'):
	case _T('^'):
		return true;
		break;
	default:
		return false;
		break;
	}
}

//////////////////////////////////////////////////////////
bool aplGetWord(LPCTSTR str, int &pos, CString &word, bool make_lower)
{
	word=_T("");
	if(str==0)return false;
	int i=pos;//,j;
    TCHAR c, *in=(TCHAR *)str;
    bool flag;

begin:
	
    // пропуск разделителей
    flag=true;
    while(flag)
    {
        c=in[i];
        switch(c)
        {
        case _T('\0'):
            return false;
        case _T(' '):
        case _T('\r'):
        case _T('\n'):
        case _T('\t'):
            i++; break;
        default:
            flag=false;
            break;
        }
    }

     // пропуск комментариев
    if(c==_T('/'))         
	{
		if(in[i+1]==_T('/')) 
	        { i+=2;
              while(in[i]!=_T('\0')){if(in[i]==_T('\r')) break; if(in[i]==_T('\n')) break; i++;}
              i++;
              goto begin;}
		else if(in[i+1]==_T('*'))
			{ i+=3;
              while(in[i]!=_T('\0')){if((in[i]==_T('/')) &&(in[i-1]==_T('*'))) break; i++;}
              i++;
              goto begin;}
	}

    // чтение служебного символа
	if(IsRezSym(c))
	{
		word=c; i++;
		if((c==_T('<'))||(c==_T('>'))||(c==_T('!')))
			{c=in[i]; if(c==_T('=')) {word+=c;i++;}}
		if(c==_T('!'))
			if(in[i]==_T('=')){word+=_T('=');i++;}
		pos=i;
		return true;
	}
    // чтение строки
	if(c==_T('"'))      
	{
		word=_T("\"");
		i++;
		while (in[i]!=_T('\0'))
		{
			c=in[i];
			if(c==_T('"'))
				if(in[i-1]!=_T('\\'))
				{ i++; word+=_T("\""); break;}
			word+=c;
			i++;
		}
		pos=i;
		return true;
	}
	if(c==_T('\''))      
	{
		word=_T("'");
		i++;
		while (in[i]!=_T('\0'))
		{
			c=in[i];
			if(c==_T('\0')) break;
			if(c==_T('\''))
			{
				if(in[i+1]==_T('\'')) i++;
				else { i++; word+=_T("'"); break;}
			}
			/*else if(c==_T('\\'))
			{
				if(in[i+1]==_T('\\')) i++;
			}*/

			word+=c;
			i++;
		}
		pos=i;
		return true;
	}
	// чтение слова

	while(true) 
	{
		c=in[i];
        if(in[i]==_T('\0')) break;
		else if(in[i]==_T(' ')) break;
        else if(IsRezSym(c)) break;
		word+=c;
		i++;
	}
	pos=i;
    if(make_lower)word.MakeLower();
	return true;
}

//
// Пропускает скобочную структуру. Исходная позиция - позиция открывающей скобки
// сдвигает pos на символ после закрывающей скобки
bool SkipBrackets(CString &input_string, int &pos)
{
	if (input_string==_T("")) return false;
	int i = pos;						// позиция в строке
    LPCTSTR in = input_string;			// указатель на текущий символ во входной строке
	
	int n_brackets = 1;
	bool is_str=false;
	while (n_brackets != 0)
	{
		if(is_str==false)
		{
			switch (in[i])
			{
			case _T('\0'): 
				pos = i;
				return false;	
				break;
			case _T('\''): is_str=true; break;
			case _T('('): n_brackets++; break;
			case _T(')'): n_brackets--; break;
			}
		}
		else
		{
			// Типа сейчас строка
			if(in[i]==_T('\''))
			{
				if(in[i+1]==_T('\''))
				{
					i++;
				}
				else is_str=false;
			}
		}
		i++;
	}
	pos = i;
	if (in[i] == _T('\0'))return false;
	return true;
}


//
// Конвертация строки с рускими буквами
void ConvertP21String(CString &string, aplRusSaveMode initmode, aplRusSaveMode resultmode)
{
	if(string==_T("")) return;
	switch (initmode)
	{
	case aplWIN7BIT: 
		{
			switch (resultmode)
			{
			case aplWIN:
				{	// aplWIN7BIT -> aplWIN
					
#ifdef _UNICODE
					CaplStringAdapter sa(string);
					const char *str=sa;
#else
					const char *str=(char*)LPCTSTR(string);
#endif	
					CStringA sStr,buf;
					bool bConverted=false;
					int i=0;
					int l=strlen(str);

					while (true)
					{
						char c0=str[i];

						if(i>l) break;

						if(c0=='\0')
						{
							break;
						}
						else if (c0!='\\') sStr+=c0;
						else
						{
							bConverted=true;

							char c1=str[i+1];
							
							if(c1=='x' || c1=='X')
							{
								char c2=str[i+2];

								if(c2=='0')
								{
									i+=4;
									continue;
								}
								else if(c2=='2')
								{
									i+=4;
									buf="";
									// читаем в buf unicode
									while(true)
									{
										char c0=str[i];

										if(c0=='\\' || c0=='\0') break;

										char c1=str[i+1];
										char c2=str[i+2];
										char c3=str[i+3];


										if	    (c0>=0x41 && c0<= 0x46) c0-=(0x31-0x0a);
										else if (c0>=0x61 && c0<= 0x66) c0-=(0x51-0x0a);
										else if (c0>=0x30 && c0<= 0x39) c0-=0x30;
																		
										if	    (c1>=0x41 && c1<= 0x46) c1-=(0x41-0x0a);
										else if (c1>=0x61 && c1<= 0x66) c1-=(0x61-0x0a);
										else if (c1>=0x30 && c1<= 0x39) c1-=0x30;

										char cl=c0;
										cl<<=4;
										cl=cl | c1;

										if	    (c2>=0x41 && c2<= 0x46) c2-=(0x31-0x0a);
										else if (c2>=0x61 && c2<= 0x66) c2-=(0x51-0x0a);
										else if (c2>=0x30 && c2<= 0x39) c2-=0x30;
																		
										if	    (c3>=0x41 && c3<= 0x46) c3-=(0x41-0x0a);
										else if (c3>=0x61 && c3<= 0x66) c3-=(0x61-0x0a);
										else if (c3>=0x30 && c3<= 0x39) c3-=0x30;

										char cr=c2;
										cr<<=4;
										cr=cr | c3;

						
										buf+=cr;
										buf+=cl;

										i+=4;
									}
									buf+='\0';buf+='\0';

									// Преобразуем из Unicode
									// ЯАИ: код не проверялся, т.к. не нашлось файла в такой кодировке
									LPCWSTR Ustr =(LPCWSTR)(buf.GetBuffer());
									sStr+=(LPCSTR)CaplStringAdapter(Ustr);
								}
								else if(c2=='\\') // старое кодирование по одному символу
								{
									char c2=str[i+3];
									char c3=str[i+4];
									
									if	    (c2>=0x41 && c2<= 0x46) c2-=(0x31-0x0a);
									else if (c2>=0x61 && c2<= 0x66) c2-=(0x51-0x0a);
									else if (c2>=0x30 && c2<= 0x39) c2-=0x30;
																	
									if	    (c3>=0x41 && c3<= 0x46) c3-=(0x41-0x0a);
									else if (c3>=0x61 && c3<= 0x66) c3-=(0x61-0x0a);
									else if (c3>=0x30 && c3<= 0x39) c3-=0x30;

									char cr=c2;
									cr<<=4;
									cr=cr | c3;

									sStr+=cr;
									i+=4;
								}
							}
							else if(c1=='\\')
							{
								sStr+='\\';
								i++;
							}

						}
						i++;
					}
#ifdef _UNICODE
					if(bConverted)	string=LPCTSTR(CaplStringAdapter(sStr));
#else
					if(bConverted)	string=sStr;
#endif

				}
				break;
			case aplISO:break;
			default:  break;  // Нафиг не нужен, но без этого gcc выдает warning
			}
		}
		break;
	case aplWIN:
		{
			switch (resultmode)
			{
			case aplWIN7BIT:
				{	// aplWIN -> aplWIN7BIT
#ifdef _UNICODE
					CaplStringAdapter sa(string);
					LPCSTR pstroka=sa;
#else
					LPCSTR pstroka=LPCSTR(string);
#endif					
					CStringA sStr,sTmp;
					bool bConverted=false;
					int pos= 0;
					while (true)
					{
						unsigned char c = pstroka[pos];	
						if (c == '\0')
							break;
						if  (c >= 128)
						{
							bConverted=true;
							sTmp.Format("\\X\\%X", c);
							sStr+=sTmp;	// вставка нового варианта
						}
						else sStr+=c;

						pos++;
					}
#ifdef _UNICODE
					if(bConverted)	string=LPCTSTR(CaplStringAdapter(sStr));
#else
					if(bConverted)	string=sStr;
#endif
				}
				break;
			case aplISO:break;
			default:  break;  // Нафиг не нужен, но без этого gcc выдает warning
			}
		}
		break;
	case aplISO:
		{
			switch (resultmode)
			{
			case aplWIN7BIT:break;
			case aplWIN:break;
			case aplISO:break;
			}
		}
		break;
	default:  break;  // Нафиг не нужен, но без этого gcc выдает warning
	}
}

//********************************************************************************

CString GetOnlyFileName(CString &full_path)
{
	int ind = full_path.ReverseFind(aplDirRazd);
	return full_path.Right(full_path.GetLength() - ind - 1);
}
//********************************************************************************
CString GetOnlyDirName(CString &full_path)
{
	int ind = full_path.ReverseFind(aplDirRazd);
	if(ind==-1){ind = full_path.GetLength();}
	else{ind ++;}// чтобы вернулась косая черта
	return full_path.Left(ind);
}
