/*
 *  texutil.C from ObjectProDSP
 *  Copyright (C) 1994, Mountain Math Software. All rights reserved.
 *  
 *  This file is part of ObjectProDSP, a tool for Digital Signal
 *  Processing design, development and implementation. It is free
 *  software provided you use and distribute it under the terms of
 *  version 2 of the GNU General Public License as published
 *  by the Free Software Foundation. You may NOT distribute it or
 *  works derived from it or code that it generates under ANY
 *  OTHER terms.  In particular NONE of the ObjectProDSP system is
 *  licensed for use under the GNU General Public LIBRARY License.
 *  Mountain Math Software plans to offer a commercial version of
 *  ObjectProDSP for a fee. That version will allow redistribution
 *  of generated code under standard commercial terms.
 *  
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *  GNU General Public License for more details.
 *  
 *  You should have received a copy of version 2 of the GNU General
 *  Public License along with this program. See file COPYING. If not
 *  or if you wish information on commercial versions and licensing
 *  write Mountain Math Software, P. O. Box 2124, Saratoga, CA 95070,
 *  USA, or send us e-mail at: support@mtnmath.com.
 *  
 *  You may also obtain the GNU General Public License by writing the
 *  Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
 *  USA.  However if you received a copy of this program without the
 *  file COPYING or without a copyright notice attached to all text
 *  files, librarys and executables please inform Mountain Math Software.
 *  
 *  ObjectProDSP is a trademark of Mountain Math Software.
 */
#include <string.h>
#include <stdlib.h>
#include <fstream.h>
#include <ctype.h>
#include "texutil.h"
#include "outtok.h"
#include "cgidbg.h"

static const char * TeXSectionNames[] = {
	"chapter",
	"section",
	"subsection",
	"subsubsection",
	"paragraph",
	"subparagraph",
	0
};

int IsTeXEscapable(char Check) 
{
	static const char * TeXEsc = "#$%&_{}" ;
	for (const char * pt =TeXEsc; *pt; pt++) if (*pt == Check) return 1;
	return 0;
}

int IsTeXSpecial(char Check) 
{
	static const char * TeXSpec = "#$%&~_^\\{}<>|[]*" ;
	for (const char * pt =TeXSpec; *pt; pt++) if (*pt == Check) return 1;
	return 0;
}

	

int MaxTeXSectionDepth()
{
	for (int Size = 0 ; TeXSectionNames[Size]; Size++);
	return Size ;
}

const char * GetTeXSectionName(int index)
{
	if (index < 0) {
		cerr << "GetTeXSectionName bad index\n" ;
		exit(1) ;
	}
	int Size = MaxTeXSectionDepth() ;
	if (index >= Size) return TeXSectionNames[Size-1] ;
	return TeXSectionNames[index];
}

OutTokens& VSpace(OutTokens& Out)
{
	Out.NewLine();
	Out.NewLine();
	Out.NextOut("\\vspace{.05in}") ;
	Out.NewLine();
	return Out ;
}


const char * QuoteQuote(const char * String)
{
	const MaxStringSize = 1024;
	static char Buf[MaxStringSize+1];
	if (strlen(String) > MaxStringSize) {
		cerr << "QuoteQuote::too long.\n" ;
		exit(1);
	}
	strcpy(Buf,String);

	int QuoteEven = 1 ;
	for (char * Ptr = Buf; *Ptr; Ptr++) {
		if (*Ptr == '"') {
			if (QuoteEven) *Ptr = '`' ;
			else *Ptr = '\'' ;
			QuoteEven = ! QuoteEven ;
		}
	}
	return Buf ;
}
	
void LitQuoteOut(const char * String, ostream * Out)
{
	*Out << "\t\tOut.NextQuoteOut(\"" << QuoteQuote(String) << "\");\n" ;
}

void LitFillOut(const char * String, ostream *Out)
{
	*Out << "\t\tOut.NextFillOut(\"" << QuoteQuote(String) << "\");\n" ;
}

void LitFillConcat(const char * String, ostream *Out)
{
	*Out<<"\t\tOut.NextFillOutConcat(\"" << String << "\");\n" ;
}

void LitFillQuoteConcat(const char * String, ostream *Out)
{
	*Out<<"\t\tOut.NextFillOutConcat(\"" << QuoteQuote(String) << "\");\n" ;
}

void ConditionalTeXIndex(OutTokens& Out, const char * String) 
{
	if (strlen(String) < MaxTeXLengthToIndex) Out.TeXIndexEntry(String);
}

static void BadChar(char c)
{
	if (!c) return ;
	if (isascii(c)) return ;
	if (iscntrl(c)) if (c== '\n' || c == '\r' || c == '\t')
		return ;
	cerr << "Bad character is `" << c << "' integer: " << (int) c << "\n" ;
	DbgError("BadChar","bad");
}


int TeXchrcmp(char a, char b)
{
	BadChar(a); BadChar(b);
	int AlphaA, AlphaB ;
	if (AlphaA = isalpha(a)) a = tolower(a);
	if (AlphaB = isalpha(b)) b = tolower(b);
	if (AlphaA && AlphaB) return a-b ;
	if (!AlphaA && !AlphaB) return a-b ;
	if (AlphaA) return 1 ;
	return -1 ;
}

static void SkipTeX(const char *& a)
{
	int ScanningMacro = 0 ;
	for (;*a;a++) {
		if (ScanningMacro) ScanningMacro++ ;
		int A = *a ;
		if (A < 0 || A > 127) return ;
		if (A == '\\' ) {
			ScanningMacro = 1 ;
			continue ;
		}
		if (ScanningMacro) {
			if (isalnum(A)) continue ;
			if (A== ':') continue ;
			if (ScanningMacro == 2) if (IsTeXEscapable(A)) return ;
			if (IsTeXSpecial(A)) {
				ScanningMacro = 0 ;
				continue ;
			}
			return ;
		}
		if (IsTeXSpecial(A)) continue ;
		return ;
	}
}

const NeitherNull = 2 ;
static int CheckNull(const char *a, const char *b)
{
	int Return = NeitherNull ;
	if (!*a || !*b) {
		Return = *a - *b ;
		if (Return == NeitherNull) return 1 ;
	}
	return Return ;
}

int TeXstrcmp(const char * a, const char * b)
{
	const char * Aptr = a ;
	const char * Bptr = b ;
	int Return = 0 ;
	for(;;) {
		Return = CheckNull(Aptr,Bptr);
		if (Return != NeitherNull) return Return ;
		SkipTeX(Aptr);
		SkipTeX(Bptr);
		Return = CheckNull(Aptr,Bptr) ;
		if (Return != NeitherNull) return Return ;
		if (Return = TeXchrcmp(*Aptr++,*Bptr++)) return Return;
	}
}
