//	ggcw.c		gg630504 hg9ieg linux.ubuntu.gcc
//	1999-10-13 - 2025-11-09

#include "ggstd.h"
#include "ggcw.h"

// kódtáblák

#include "ggcw_.h"
#include "ggcw_.c"


//$ CwcFromCu ----------------------------------------------------------
CWC		CwcFromCu( cu_ )
CU		cu_;	// be:	unikód
			// vissza:	cw kód
			//		0, ha nincs
{
IX		ixMin;
IX		ixMax;
IX		ixMid;
CU		cu;

// logaritmusos/bináris keresés
ixMin = 0;
ixMax = ixCwTxLim-1;
while( ixMin<=ixMax )
	{
	ixMid = (ixMin+ixMax)/2;
	cu = cwTxMp[ixMid].cu;
	if( (WU)cu_ < (WU)cu )
		ixMax = ixMid-1;
	else	if( (WU)cu_ > (WU)cu )
			ixMin = ixMid+1;
		else	return( cwTxMp[ixMid].cwc );
	}
return( 0 );
}


//$ RCwPraSzDD ---------------------------------------------------------
R		RCwPraSzDD( pra_, sz_, dCh_, dW_ )
PRA		pra_;	// eredmény
SZ		sz_;	// utf-8
D		dCh_;	// karakterek közötti szünet ( 3 )
D		dW_;	// szavak közötti szünet ( 7 )
{
SUA		sua;
R		r;

if( (r = RInitPraSs( pra_, sizeof( CWT ) )) != rSucceed )
	return( r );
if( (sua = SuaFromSz( sz_ )) == NULL )
	return( rFail );
r = RCwPraSzuDD( pra_, sua, dCh_, dW_ );
free( sua );
return( r );
}


//$ RCwPraSzuDD --------------------------------------------------------

#define VPushV() \
	{\
	cwt._tsCwt = wDotAct + dCh_*wChAct + dW_*wWAct;\
	cwt.cwsCwt = cwsPrev;\
	if( (r=RPushPraPv( pra_, &cwt )) != rSucceed )\
		goto retErr;\
	wDotAct	+= wDotAccu;	wDotAccu	= 0;\
	wChAct	+= wChAccu;	wChAccu		= 0;\
	wWAct	+= wWAccu;	wWAccu		= 0;\
	}


R		RCwPraSzuDD( pra_, szu_, dCh_, dW_ )
PRA		pra_;	// eredmény
SZU		szu_;	// unicode
D		dCh_;	// karakterek közötti szünet ( 3 )
D		dW_;	// szavak közötti szünet ( 7 )
{
CU		cuAct;
CWC		cwcAct;
CWC		cwcPrev;
CWC		cwcShift;
CWS		cwsPrev;
CWT		cwt;
F		fCwcFirst;
F		fEscAct;
R		r;



W		wChAccu;
W		wChAct;
W		wDotAccu;
W		wDotAct;
W		wWAccu;
W		wWAct;

W		wChEsc;
W		wDotEsc;
W		wWEsc;


r = rSucceed;
retnull( pra_ );

retparam( dCh_ < 3 || dW_ < 7 || dCh_ > dW_ );

if( (r = RInitPraSs( pra_, sizeof( CWT ) )) != rSucceed )
	return( r );


cwcPrev		= cwcUndefined;
cwsPrev		= cwsUndefined;
fEscAct		= fFalse;

wChAct		= 0;
wDotAct		= 0;
wWAct		= 0;

wChAccu		= 0;
wDotAccu	= 0;
wWAccu		= 0;

wChEsc		= 0;
wDotEsc		= 0;
wWEsc		= 0;



cuAct = *szu_++;
while( cuAct != cuEos )
	{
	if( fEscAct )
		{ // fEscAct
		switch( cuAct )
			{
		case ' ':
			break;
		case '0': case '1': case '2': case '3': case '4':
		case '5': case '6': case '7': case '8': case '9':
			wDotEsc = (10*wDotEsc + cuAct-'0') % 1000;
			break;
		case 'c':
			wChEsc++;
			break;
		case 'w':
			wWEsc++;
			break;
		case 's':	// space
			if( wDotEsc + wChEsc + wWEsc > 0 )
				{
				switch( cwsPrev )
					{
				case cwsUndefined: // első
					break;
				case cwsSpace: // folytatni kell
					break;
				case cwsMark: // le kell zárni az előző jelet és nyitni kell szünetet
					VPushV();
					break;
					}
				cwsPrev = cwsSpace;
				wDotAccu	+= wDotEsc;	wDotEsc	= 0;
				wChAccu		+= wChEsc;	wChEsc	= 0;
				wWAccu		+= wWEsc;	wWEsc	= 0;
				}
			break;
		case 'm':
			if( wDotEsc + wChEsc + wWEsc > 0 )
				{
				switch( cwsPrev )
					{
				case cwsUndefined: // első
					break;
				case cwsSpace: // le kell zárni az előző szünetet és nyitni kell jelet
					VPushV();
					break;
				case cwsMark: // folytatni kell
					break;
					}
				cwsPrev = cwsMark;
				wDotAccu	+= wDotEsc;	wDotEsc	= 0;
				wChAccu		+= wChEsc;	wChEsc	= 0;
				wWAccu		+= wWEsc;	wWEsc	= 0;
				}
			break;
		case ';':
			cwcPrev = cwcUndefined;
			fEscAct = fFalse;
			break;
			} // cuAct
		} // fEscAct
	else	{ // !fEscAct
		if( cuAct == cuCwEsc )
			{
			wDotEsc	= 0;
			wChEsc	= 0;
			wWEsc	= 0;
			fEscAct	= fTrue;
			}
		else	{
			if( (cwcAct=CwcFromCu( cuAct ))!=0 )
				{
				if( cwcAct == cwcSpace )
					{
					}
				else	{
					fCwcFirst = fTrue;
					cwcShift = cwcAct;
					while( !(cwcShift == cwcEnd) )
						{
// < < < < <
if( fCwcFirst )
	{
	switch( cwsPrev )
		{
	case cwsUndefined: // első
		break;
	case cwsSpace: // csak Esc lehetett előtte, utána esetleg szóközök
		switch( cwcPrev )
			{
		case cwcSpace: // szóköz volt előtte
			if( wDotAccu + dCh_*wChAccu + dW_*wWAccu < dW_ )
				{
				wDotAccu = 0;
				wChAccu	= 0;
				wWAccu	= 1;
				}
			VPushV();
			break;
		default:
			VPushV();
			break;
			}	
		break;
	case cwsMark: // le kell zárni az előző jelet és nyitni kell szünetet
		// közt kiírni, de mi volt előtte?
		switch( cwcPrev )
			{
		case cwcUndefined: // Esc volt, egybe kell a Mark-kal.
			break;
		case cwcSpace: // Space: Mark-ot lezárni, dW_ szünet.
			VPushV();
			wWAccu = 1;
			cwsPrev = cwsSpace;
			VPushV();
			break;
		default: // normál karakter: Mark-ot lezárni, dCh_ szünet
			VPushV();
			wChAccu = 1;
			cwsPrev = cwsSpace;
			VPushV();
			break;
			}
		break;
		}
	}
else	{ // !fCwcFirst, előtte Mark volt, 1 szünet
	VPushV(); // Mark-ot lezárni
	wDotAccu = 1;
	cwsPrev = cwsSpace;
	VPushV();
	}
// előjegyez 1 : 3 Mark-ot. lehet Esc Mark
wDotAccu += cwcShift & cwcBit ? 3 : 1;
cwsPrev = cwsMark;
fCwcFirst = fFalse;
ShiftCwc( cwcShift );
// > > > > >
						}
					}
				cwcPrev = cwcAct;
				} // cwcAct
			} // cuAct

		} // !fEscAct
	cuAct = *szu_++;
	}

switch( cwsPrev )
	{
case cwsUndefined: // első
	break;
case cwsSpace:
	VPushV();
	cwsPrev = cwsUndefined;
	VPushV();
	break;
case cwsMark:
	VPushV();
	cwsPrev = cwsUndefined;
	VPushV();
	break;
	}

ret:
return( r );

retErr:
RFreePra( pra_ );
return( r );
}


//$ SzFromCwc ----------------------------------------------------------
SZ		SzFromCwc( cwc_ )
CWC		cwc_;	// be:	cw kód
			// vissza:	UTF-8 szöveg
			//		NULL, ha nincs
{
IX		iMin;
IX		iMax;
IX		iMid;
CWC		cwc;

// logaritmusos/bináris keresés
iMin = 0;
iMax = ixCwRxLim-1;
while( iMin<=iMax )
	{
	iMid = (iMin+iMax)/2;
	cwc = cwRxMp[iMid].cwc;
	if( cwc_ < cwc )
		iMax = iMid-1;
	else	if( cwc_ > cwc )
			iMin = iMid+1;
		else	return( cwRxMp[iMid].sz0 );
	}
return( NULL );
}


//$ SzFrom1Cwc ----------------------------------------------------------
SZ		SzFrom1Cwc( cwc_ )
CWC		cwc_;	// be:	cw kód
			// vissza:	UTF-8 szöveg
			//		NULL, ha nincs
{
IX		iMin;
IX		iMax;
IX		iMid;
CWC		cwc;

// logaritmusos/bináris keresés
iMin = 0;
iMax = ixCwRxLim-1;
while( iMin<=iMax )
	{
	iMid = (iMin+iMax)/2;
	cwc = cwRxMp[iMid].cwc;
	if( cwc_ < cwc )
		iMax = iMid-1;
	else	if( cwc_ > cwc )
			iMin = iMid+1;
		else	return( cwRxMp[iMid].sz1 );
	}
return( NULL );
}


//$ CwcReverseCwc ------------------------------------------------------
CWC		CwcReverseCwc( cwc_ )
CWC		cwc_;	// be:	cw kód
			// vissza: fordított cw kód
{
CWC	cwcRev;
if( cwc_ == 0 )
	return( 0 );
cwcRev = cwcEnd;
while( cwc_ != cwcEnd )
	{
	cwcRev >>= 1;
	if( cwc_ & cwcBit )
		cwcRev |= cwcBit;
	cwc_ <<= 1;
	}
return( cwcRev );
}


//$ CtElemCwc --------------------------------------------------------
CT		CtElemCwc( cwc_ )
CWC		cwc_;	// be:	cw kód
			// vissza: rövid és hosszú jelek darabszáma
{
CT	ctLen;

if( cwc_ == 0 )
	return( 0 );
ctLen = 0;
while( cwc_ != cwcEnd )
	{
	ctLen++;
	cwc_ <<= 1;
	}
return( ctLen );
}

//$ SzFromSzCwcChChCh --------------------------------------------------
SZ		SzFromSzCwcChChCh( sz_, cwc_, chDi_, chDa_, chSp_ )
SZ		sz_;
CWC		cwc_;
CH		chDi_;
CH		chDa_;
CH		chSp_;
{
PCH		pch;
CT		ct;

ct = 0;
pch = sz_;
while( cwc_ != cwcEnd && ct < 16 )
	{
	*pch++ = cwc_ & cwcBit ? chDa_: chDi_;
	cwc_ <<= 1;
	ct++;
	}

if( chSp_ != chEos )
	*pch++ = chSp_;

*pch = chEos;
return( sz_ );
}

//@

