/// Includes
#define INTUI_V36_NAMES_ONLY

#include <exec/types.h>                 // exec
#include <exec/lists.h>
#include <exec/nodes.h>
#include <dos/dos.h>                    // dos
#include <dos/dostags.h>
#include <libraries/reqtools.h>         // libraries
#include <clib/exec_protos.h>           // protos
#include <clib/dos_protos.h>
#include <clib/reqtools_protos.h>
#include <pragmas/exec_pragmas.h>       // pragmas
#include <pragmas/dos_pragmas.h>
#include <pragmas/reqtools_pragmas.h>

#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>

#include "DEV_IE:Generators/defs.h"
#include "DEV_IE:Include/IEditor.h"
#include "DEV_IE:Generators/C/Protos.h"
///
/// Prototypes
static BOOL     GetLine( STRPTR, UBYTE **, UBYTE * );
static void     WriteLocaleH( struct GenFiles *, struct MinList *, STRPTR );
static void     WriteCT( struct GenFiles *, struct MinList *, STRPTR );
///


/// AskFile
BOOL AskFile( UBYTE *File, struct IE_Data *IE )
{
    BOOL    ret = TRUE;
    BPTR    lock;

    if( lock = Lock( File, ACCESS_READ )) {

	UnLock( lock );

	ULONG   tags[] = { RT_ReqPos, REQPOS_CENTERSCR, RT_Underscore, '_',
			   RT_Screen, IE->ScreenData->Screen, TAG_DONE };

	ret = rtEZRequest( "%s alreay exists.\n"
			   "Overwrite?",
			   "_Yes|_No",
			   NULL, (struct TagItem *)tags,
			   FilePart( File )
			 );
    }

    return( ret );
}
///

/// WriteList
void WriteList( struct GenFiles *Files, struct MinList *List, UBYTE *Label, UWORD Num, struct IE_Data *IE )
{
    struct GadgetScelta *gs;
    UWORD                cnt;

    if( Num ) {

	FPrintf( Files->XDef, "extern struct MinList %sList;\n", Label );

	FPrintf( Files->Std, "\nstruct Node %sNodes[] = {\n\t", Label );

	gs = List->mlh_Head;

	if( Num == 1 ) {
	    FPrintf( Files->Std, "(struct Node *)&%sList.mlh_Tail, (struct Node *)&%sList.mlh_Head, 0, 0, ",
		     Label, Label );

	    if( IE->SrcFlags & LOCALIZE )
		FPuts( Files->Std, "(STRPTR)" );

	    if( Prefs.Flags & SMART_STR )
		FPrintf( Files->Std, "%s", (FindString( &Files->Strings, gs->gs_Testo ))->Label );
	    else
		FPrintf( Files->Std, "\"%s\"", gs->gs_Testo );

	    FPuts( Files->Std, " };\n" );
	} else {

	    FPrintf( Files->Std, "&%sNodes[1], (struct Node *)&%sList.mlh_Head, 0, 0, ",
		     Label, Label );

	    if( IE->SrcFlags & LOCALIZE )
		FPuts( Files->Std, "(STRPTR)" );

	    if( Prefs.Flags & SMART_STR )
		FPrintf( Files->Std, "%s", (FindString( &Files->Strings, gs->gs_Testo ))->Label );
	    else
		FPrintf( Files->Std, "\"%s\"", gs->gs_Testo );

	    FPuts( Files->Std, ",\n" );

	    for( cnt = 1; cnt < Num - 1; cnt++ ) {

		gs = gs->gs_Node.ln_Succ;

		FPrintf( Files->Std, "\t&%sNodes[%ld], &%sNodes[%ld], 0, 0, ",
			 Label, cnt + 1, Label, cnt - 1 );

		if( IE->SrcFlags & LOCALIZE )
		    FPuts( Files->Std, "(STRPTR)" );

		if( Prefs.Flags & SMART_STR )
		    FPrintf( Files->Std, "%s", (FindString( &Files->Strings, gs->gs_Testo ))->Label );
		else
		    FPrintf( Files->Std, "\"%s\"", gs->gs_Testo );

		FPuts( Files->Std, ",\n" );
	    }

	    gs = gs->gs_Node.ln_Succ;
	    FPrintf( Files->Std, "\t(struct Node *)&%sList.mlh_Tail, &%sNodes[%ld], 0, 0, ",
		     Label, Label, Num - 2 );

	    if( IE->SrcFlags & LOCALIZE )
		FPuts( Files->Std, "(STRPTR)" );

	    if( Prefs.Flags & SMART_STR )
		FPrintf( Files->Std, "%s", (FindString( &Files->Strings, gs->gs_Testo ))->Label );
	    else
		FPrintf( Files->Std, "\"%s\"", gs->gs_Testo );

	    FPuts( Files->Std, " };\n" );
	}

	FPrintf( Files->Std, "\nstruct MinList %sList = {\n"
			     "\t(struct MinNode *)&%sNodes[0], (struct MinNode *)NULL, (struct MinNode *)&%sNodes[%ld] };\n",
		 Label, Label, Label, Num - 1 );
    }
}
///

//      Locale stuff
/// WriteCD
void WriteCD( struct GenFiles *Files )
{
    struct StringNode  *str;
    UWORD               cnt = 0;

    for( str = Files->Strings.mlh_Head; str->Next; str = str->Next ) {

	FPrintf( (BPTR)Files->User1, "MSG_STRING_%ld (//)\n%s\n;\n",
		 cnt++, str->String );
    }
}
///
/// WriteLocale
void WriteLocaleStrings( struct GenFiles *Files, STRPTR Path, STRPTR FileName )
{
    struct MinList *l;
    TEXT            buffer[256];

    if( l = ReadOtherStrings( (struct IE_Data *)Files->User3 )) {

	strcpy( buffer, Path );
	AddPart( buffer, FileName, 256 );

	WriteLocaleH( Files, l, buffer );
	WriteCT( Files, l, Path );

	FreeOtherStrings( l );
    }
}
///
/// WriteLocaleH
void WriteLocaleH( struct GenFiles *Files, struct MinList *l, STRPTR FileName )
{
    BPTR    file;

    if( file = Open( FileName, MODE_NEWFILE )) {
	struct OtherStrNode    *otherstr;
	struct StringNode      *str;
	TEXT                    buffer[80];
	UBYTE                  *from, *to;
	ULONG                   num = 0, cnt;

	from = FilePart( FileName );
	to   = buffer;

	while( *from ) {
	    UBYTE   b;

	    b = *from++;

	    if( b == '.' )
		*to++ = '_';
	    else
		*to++ = toupper( b );
	}

	*to = '\0';


	FPrintf( file, "#ifndef %s\n#define %s\n\n"
		       "/* This file was generated automatically by IEditor!\n"
		       "   Do NOT edit by hand!\n"
		       " */\n\n"
		       "/*************************************************************************/\n\n"
		       "#ifndef EXEC_TYPES_H\n"
		       "#include <exec/types.h>\n"
		       "#endif\n\n"
		       "#ifdef CATCOMP_ARRAY\n"
		       "#undef CATCOMP_NUMBERS\n"
		       "#define CATCOMP_NUMBERS\n"
		       "#endif\n\n"
		       "/*************************************************************************/\n\n"
		       "#ifdef CATCOMP_NUMBERS\n\n",
		       buffer, buffer );


	for( otherstr = l->mlh_Head; otherstr->Next; otherstr = otherstr->Next )
	    FPrintf( file, "#define %s %ld\n", otherstr->Label, num++ );

	for( cnt = 0, str = Files->Strings.mlh_Head; str->Next; str = str->Next )
	    FPrintf( file, "#define MSG_STRING_%ld %ld\n", cnt++, num++ );

	FPuts( file, "\n"
		     "#endif /* CATCOMP_NUMBERS */\n"
		     "\n"
		     "/*************************************************************************/\n\n"
		     "#ifdef CATCOMP_ARRAY\n\n"
		     "struct CatCompArrayType\n"
		     "{\n"
		     "\tLONG\tcca_ID;\n"
		     "\tSTRPTR\tcca_Str;\n"
		     "};\n"
		     "\n"
		     "struct CatCompArrayType CatCompArray[] =\n"
		     "{\n" );

	for( otherstr = l->mlh_Head; otherstr->Next; otherstr = otherstr->Next )
	    FPrintf( file, "\t{%s,\"%s\"},\n", otherstr->Label, otherstr->String );

	for( cnt = 0, str = Files->Strings.mlh_Head; str->Next; str = str->Next )
	    FPrintf( file, "\t{MSG_STRING_%ld,\"%s\"},\n", cnt++, str->String );

	FPrintf( file, "};\n\n"
		       "#endif /* CATCOMP_ARRAY */\n"
		       "\n"
		       "#endif /* %s */\n",
		 buffer );

	Close( file );
    }
}
///
/// WriteCT
void WriteCT( struct GenFiles *Files, struct MinList *l, STRPTR Path )
{
    BPTR    file;
    TEXT    name[256];

    strcpy( name, Path );

    AddPart( name, ((struct IE_Data *)Files->User3 )->Locale->Catalog, 256 );

    strcat( name, ".ct" );

    if( file = Open( name, MODE_NEWFILE )) {
	struct OtherStrNode    *otherstr;
	struct StringNode      *str;
	ULONG                   cnt;

	FPrintf( file, "## version $VER: %s.catalog XX.XX (XX.XX.XX)\n"
		       "## codeset X\n"
		       "## language X\n"
		       ";\n",
		 ((struct IE_Data *)Files->User3 )->Locale->Catalog );

	for( otherstr = l->mlh_Head; otherstr->Next; otherstr = otherstr->Next )
	    FPrintf( file, "%s\n\n; %s\n;\n", otherstr->Label, otherstr->String );

	for( cnt = 0, str = Files->Strings.mlh_Head; str->Next; str = str->Next )
	    FPrintf( file, "MSG_STRING_%ld\n\n; %s\n;\n", cnt++, str->String );

	Close( file );
    }
}
///

/// ReadOtherStrings
struct MinList *ReadOtherStrings( struct IE_Data *IE )
{
    struct MinList *OtherStrings;
    BPTR            file;

    if( OtherStrings = AllocMem( sizeof( struct MinList ), MEMF_ANY )) {

	NewList( OtherStrings );

	if( file = Open( IE->Locale->JoinFile, MODE_OLDFILE )) {
	    LONG    size;
	    UBYTE  *buffer;

	    Seek( file, 0, OFFSET_END );
	    size = Seek( file, 0, OFFSET_BEGINNING );

	    if( buffer = AllocMem( size, MEMF_CLEAR )) {
		TEXT    str[512];
		UBYTE  *strings, *end;

		Read( file, buffer, size );

		strings = buffer;
		end     = buffer + size;

		while( GetLine( str, &strings, end )) {
		    TEXT    str2[512];
		    STRPTR  par;

		    if( par = strchr( str, '(' ))
			*par = '\0';

		    if( GetLine( str2, &strings, end )) {
			struct OtherStrNode    *s;

			if( s = AllocMem( sizeof( struct OtherStrNode ), MEMF_ANY | MEMF_CLEAR )) {

			    AddTail(( struct List * )OtherStrings, ( struct Node * )s );

			    strcpy( s->Label,  str  );
			    strcpy( s->String, str2 );

			} else
			    break;

		    } else
			break;
		}

		FreeMem( buffer, size );
	    }

	    Close( file );
	}

    }

    return( OtherStrings );
}
///
/// FreeOtherStrings
void FreeOtherStrings( struct MinList *OtherStrings )
{
    struct OtherStrNode    *str;

    while( str = (struct OtherStrNode *)RemTail(( struct List * )OtherStrings ))
	FreeMem( str, sizeof( struct OtherStrNode ));

    FreeMem( OtherStrings, sizeof( struct MinList ));
}
///

/// GetLine
BOOL GetLine( STRPTR string, UBYTE **buffer, UBYTE *end )
{
    BOOL    ret = FALSE, first = TRUE, ok = TRUE;
    UBYTE  *ptr;

    ptr = *buffer;

    while(( ptr < end ) && ( ok )) {
	UBYTE   c;

	switch( c = *ptr++ ) {

	    case ';':
		if( first ) {
		    /*  skip to EOL */
		    while( ptr < end ) {
			if( *ptr++ == '\n' )
			    break;
		    }
		} else {
		    *string++ = ';';
		}
		break;

	    case '\\':
		if( ptr < end ) {
		    UBYTE   b;

		    b = *ptr++;

		    if( b != '\n' ) {
			*string++ = '\\';
			*string++ = b;
		    }
		}
		break;

	    case '\n':
		if(!( first ))
		    ok = FALSE;
		break;

	    default:
		*string++ = c;
		ret       = TRUE;
		first     = FALSE;
		break;
	}
    }

    *string = '\0';
    *buffer = ptr;

    return( ret );
}
///
