/*  textfrag.C   */
/*  Copyright 1991 Mountain Math Software  */
/*  All Rights Reserved                    */

#include <string.h>
#include <ctype.h>
#include <stream.h>
#include "textfrag.h"
#include "textrans.h"
#include "texspec.h"
#include "outtok.h"
#include "debug.h"
#include "cgidbg.h"

static int DoubleDollarLength(const char * text)
{
	int Count = 0 ;
	for (const char * pt = text ; *pt ; pt++)
	    if (*pt=='$') if (pt[1]=='$') if (pt[2]) if (isalpha(pt[2])) {
		pt += 1 ;
		Count++;
	}
	return Count ;
}

const char * ClearDoubleDollar(const char * text)
{
	if (!text) return text ;
	if (!*text) return text ;
	if (!DoubleDollarLength(text)) return text ;
	char * Return = new char[strlen(text)] ;
	int index = 0 ;
	for (const char * pt = text ; *pt; pt++)  {
	   	if (*pt=='$') if (pt[1]=='$') if (pt[2]) if (isalpha(pt[2])) {
			pt += 2 ;
			while(isalnum(*pt)) pt++;
		}
		if (*pt) Return[index++] = *pt ;
		else break ;
	}
	Return[index] = '\0' ;
	if (index) {
		if (index > strlen(text) - 2) DbgError("ClearDoubleDollar","bad index");
	} else {
		Return[0] = ' ' ;
		Return[1] = '\0' ;
	}
	return Return ;
}

const char * DoubleDollarTranslate(const char * text)
{
	const char * Prefix = "{\\tt " ;
	const char * Index = "}\\index{" ;
	const char * Suffix = "}" ;
	int Count = DoubleDollarLength(text);
	if (!Count) return text ;

	int NewSize = (strlen(text) - 2) * 2 +
		strlen(Prefix) + strlen(Index) + strlen(Suffix)  ;
	char * Return = new char[NewSize+1] ;
	strcpy(Return,Prefix);
	strcat(Return,text+2);
	strcat(Return,Index);
	strcat(Return,text+2);
	strcat(Return,Suffix);
	if (strlen(Return) != NewSize) {
		cerr << "strlen = " << strlen(Return) <<
			", new = " << NewSize << "\n" ;
		DbgError("DoubleDollarTranslate","internal error");
	}
	return Return ;
/*
 *	int NewSize = strlen(text) + Count * (strlen(Prefix)+strlen(Suffix)-2);
 *	
 *	int AddSuffix = 0 ;
 *	char * Return = new char[NewSize+1] ;
 *	int index = 0 ;
 *	for (const char * pt = text ; *pt ; pt++) {
 *	    if (*pt == '$') if (pt[1] == '$') if(pt[2]) if (isalpha(pt[2])) {
 *			pt += 1 ;
 *			AddSuffix = 1 ;
 *			strcpy(Return + index, Prefix);
 *			index += strlen(Prefix);
 *			continue ;
 *		}
 *		if(AddSuffix) if (!isalnum(*pt)) {
 *			strcpy(Return + index,Suffix);
 *			index += strlen(Suffix);
 *			AddSuffix = 0 ;
 *		}
 *		Return[index++] = * pt ;
 *	}
 *	if (AddSuffix) {
 *		strcpy(Return+index,Suffix);
 *		index+= strlen(Suffix);
 *	}
 *	Return[index] = '\0' ;
 *	if (index != NewSize)
 *		DbgError("DoubleDollarTranslate","internal error");
 *	// delete (char *) text ;
 *	LogOut << "DoubleDollarTranslate: `" << Return << "'.\n" ;
 *	return Return ;
 */
}

const char * ReplaceQuote(const char * text)
{
	char * Temp = new char[strlen(text)+1] ;
	int index = 0 ;
	int QuoteOut = 0 ;
	for (const char * pt = text ; *pt ; pt ++) {
		if (QuoteOut) if (!isalnum(*pt)) {
			QuoteOut = 0 ;
			Temp[index++] = '\'' ;
		}
	    	if (*pt=='$') if (pt[1]=='$') if (pt[2]) if (isalpha(pt[2])) {
			Temp[index++] = '`' ;
			pt += 1 ;
			QuoteOut = 1 ;
			continue ;
		}
		Temp[index++] = *pt ;
	}
	if (QuoteOut) Temp[index++] = '\'' ;
	if (index != strlen(text)) DbgError("ReplaceQuote", "bad conut");
	Temp[index] = '\0' ;
	// delete (char *) text ;
	return Temp ;
}
		

TextFragment::TextFragment(int line,const char * text):
	Line(line),
	Text(text),
	TeXText(0),
	SpellText(0)
{
	const char * Check = TheTeXWordTranslator.Translate(text);
	Text = text ;
	if (Check) {
		// LogOut << "Found macro in `" << text << "'\n" ;
		TeXText = text ;
		Text = Check ; // translation of TeX macro(s)
	}
	if (DoubleDollarLength(Text)) {
		if (Check) DbgError("TextFragment::ctor","IMPOSSIBLE");
		TeXText = text ;
		Text = ReplaceQuote(text);
		SpellText = ClearDoubleDollar(text);
	} else SpellText = Text ;
}

TextFragment::~TextFragment()
{
	// delete (void *) Text;
	// delete (void *) TeXText;
}

TextFragmentList::~TextFragmentList()
{
	TextFragment * Frag ;
	while (Frag = Get()) delete Frag;
}


TextFragment * TextFragmentList::GetNthEntry(int N)
{
	TextFragmentListIterator Next(*this);
	TextFragment * Return ;
	int count = 0 ;
	while (Return = Next()) {
		if (count == N) return Return ;
		count++;
	}
	return 0;
}

void TextFragmentList::OutTeXEndDot(OutTokens& Out)
{
	const char * Temp = OutTeX(Out);
	Out.NextConcatCond('.');
}

static int LastLine = 0 ;

const char * TextFragmentList::OutTeX(OutTokens& Out)
{
	TextFragmentListIterator Next(*this);
	TextFragment * Frag ;
	const char * Last = 0 ;
	TranslateToTeX.ClearCheckTail();
	LastLine = 0 ;
	while (Frag = Next()) {
		const char * ToWrite = Frag->TeXText ;
		int UsingTeXLine = ToWrite != 0  ;
		if (!UsingTeXLine) ToWrite = Frag->Text ;
		// LogOut << "Outputting TeXfrag: `" << ToWrite << "'.\n" ;
		ToWrite = TranslateToTeX.DoTeXTranslate(ToWrite) ;
		if (UsingTeXLine) {
			// LogOut<<"TeX trans TeXfrag: `" << ToWrite << "'.\n" ;
			ToWrite = DoubleDollarTranslate(ToWrite);
			// LogOut<<"$$ trans TeXfrag: `" << ToWrite << "'.\n" ;
		}
		int CheckLine = Frag->Line ;
		if (CheckLine != LastLine && !strcmp(" ",ToWrite)) continue;
			
		if (CheckLine < 0) {
			CheckLine = -CheckLine ;
			if (LastLine != CheckLine) Out.NextOut("{\\tt");
			else Out.NextFillOutConcat("{\\tt");
			Out.NextOut(ToWrite);
			Out.NextFillOutConcat("}\\index{");
			Out.NextFillOutConcat(ToWrite);
			Out.NextFillOutConcat("}");
		} else {
			if (CheckLine != LastLine) Out.NextFillOut(ToWrite);				else Out.NextFillOutConcat(ToWrite);
		}
 		LastLine = CheckLine ;
		Last = ToWrite ;
	}
	return Last ;
}


