/*
 *  FraZoom.c	(c) Arto V. Viitanen 1992
 *
 *	Based on the idea of the Fractfly program by Josh Lannin.
 *	Version 1.0. 3/22/92.
 */

#ifdef __MSDOS__
#include <stdlib.h>
#include <alloc.h>
#include <conio.h>
#include <io.h>
#endif					       /* __MSDOS__ */
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <fcntl.h>
#include <assert.h>
#include <math.h>
#include "gif_lib.h"
#include "getarg.h"
#include "fractinf.h"

#define PROGRAM_NAME	"FracZoom"
#ifdef __MSDOS__
extern unsigned int
	_stklen = 16384;		       /* Increase default stack
						* size. */
#endif					       /* __MSDOS__ */
#ifdef SYSV
static char
    *VersionStr = "FracZoom,\t\tArto V. Viitanen\n\
	(C) Copyright 1992 Arto V. Viitanen, Non commercial use only.\n";

static char
       *CtrlStr = "FracZoom GifFile%*s";
#else
static char
    *VersionStr =
	PROGRAM_NAME
	GIF_LIB_VERSION
	"	Arto V. Viitanen, "
	__DATE__ ",   " __TIME__ "\n"
	"(C) Copyright 1992, Arto V. Viitanen Non commercial use only.\n";
static char
       *CtrlStr =
PROGRAM_NAME
" GifFile!*s";
#endif					       /* SYSV */



static void ReadInfo(char* FileName, struct fractal_info* info);
static void GenerateFly(struct fractal_info* start, struct fractal_info* end,
			char* start_file, char* end_file);
static int  CheckFract(int ExtCode, GifByteType * Extension);
static void GetFileName(char *FileType, char** FileName);



int main(int argc, char **argv) {

    int    Error, NumFiles;
    char  *StartGifFileName, *EndGifFileName, **FileName = NULL;
    struct fractal_info start_info, end_info;

    if ((Error = GAGetArgs(argc, argv, CtrlStr,
			   &NumFiles, &FileName)) != FALSE ||
	    (NumFiles > 2)) {
	fprintf(stderr,"%s\n", VersionStr);
	if (Error)
	    GAPrintErrMsg(Error);
	else if (NumFiles > 2)
	    GIF_MESSAGE("Error in command line parsing - two GIF files please.");
	GAPrintHowTo(CtrlStr);
	return 1;
    }

    switch (NumFiles) {
	case 0:
	    GetFileName("Start", &StartGifFileName);
	    GetFileName("End", &EndGifFileName);
	    break;
	case 1:
	    StartGifFileName = FileName[0];
	    GetFileName("End", &EndGifFileName);
	    break;
	default:
	    StartGifFileName = FileName[0];
	    EndGifFileName = FileName[1];
    }

    ReadInfo(StartGifFileName, &start_info);
    ReadInfo(EndGifFileName, &end_info);

    GenerateFly(&start_info, &end_info, StartGifFileName, EndGifFileName);
    free(StartGifFileName);
    free(EndGifFileName);
    return 0;

}

static void GetFileName(char *FileType, char** FileName) {

    char buffer[120];

    printf("Give name of %s GIF file ", FileType);
    fflush(stdout);
    gets(buffer);

    *FileName = malloc(strlen(buffer)+1);
    strcpy(*FileName, buffer);

}

static void ReadInfo(char* FileName, struct fractal_info* info) {

    GifRecordType RecordType;
    GifByteType *CodeBlock, *Extension;
    GifFileType *GifFile;
    char   *p;
    int CodeSize, ExtCode, Len;


    if ((GifFile = DGifOpenFileName(FileName)) == NULL) {
	    PrintGifError();
	    exit(-1);
    }


    printf("\n%s:\n\tScreen Size - Width = %d, Height = %d.\n",
	   FileName, GifFile->SWidth, GifFile->SHeight);

    do {
	if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR) {
	    PrintGifError();
	    exit(-1);
	}
	switch (RecordType) {
	    case IMAGE_DESC_RECORD_TYPE:
		if (DGifGetImageDesc(GifFile) == GIF_ERROR) {
		    PrintGifError();
		    exit(-1);
		}
		/* Skip the image: */
		if (DGifGetCode(GifFile, &CodeSize, &CodeBlock) == GIF_ERROR) {
		    PrintGifError();
		    exit(-1);
		}
		while (CodeBlock != NULL) {
		    if (DGifGetCodeNext(GifFile, &CodeBlock) == GIF_ERROR) {
			PrintGifError();
			exit(-1);
		    }
		}
		break;
	    case EXTENSION_RECORD_TYPE:
		if (DGifGetExtension(GifFile, &ExtCode, &Extension) == GIF_ERROR) {
		    PrintGifError();
		    exit(-1);
		}
		p = (char*) info; /* Collect the extension data */

		if (CheckFract(ExtCode, Extension)) {
		    while (Extension != NULL) {
			if (DGifGetExtensionNext(GifFile, &Extension) == GIF_ERROR) {
			    PrintGifError();
			    exit(1);
			}
			Len = Extension[0];
			if (Len == 0 || Extension == NULL)
			    break;
			memcpy(p, &Extension[1], Len);
			p += Len;
		    }
		}
		else {
		    fprintf(stderr,"\007%s is not fractint picture\n",
			    FileName);
		    exit(2);
		}
		break;
	    default:
		break;
	}
    } while (RecordType != TERMINATE_RECORD_TYPE);


    if (DGifCloseFile(GifFile) == GIF_ERROR) {
	PrintGifError();
	exit(-1);
    }
}

static int CheckFract(int ExtCode, GifByteType * Extension) {

    int     Len;

    if (ExtCode != 255)
	return 0;
    Len = Extension[0];
    if (Len != 11)
	return 0;			       /* not fractint gif */
    if (strncmp(&Extension[1], "fractint001", 11) != 0)
	return 0;

    printf("This is fractint file\n");
    return 1;
}

static void GenerateFly(struct fractal_info *start, struct fractal_info *end,
			char* start_file, char* end_file) {

    char buffer[80];
    int steps, i;
    double decx1, decx2, decy1, decy2;
    double x1, x2, y1, y2;
    FILE* out;

    if (start->fractal_type != end->fractal_type) {
	fprintf(stderr,"\007Files have different kind of fractals.\n");
	fprintf(stderr,"%s has %s but %s has %s\n",
		start_file, name_of[start->fractal_type],
		end_file, name_of[end->fractal_type]);
	exit(1);
    }
    else
	printf("Both are %s\n", name_of[end->fractal_type]);

    do {
	printf("How many steps ");fflush(stdout);
	gets(buffer);
	steps=atoi(buffer);
	if (!steps)
	    fprintf(stderr,"%s is not positive number\n",buffer);
    } while (!steps);

    do {
	printf("Give batchfile name ");fflush(stdout);
	gets(buffer);

	if ((out = fopen(buffer, "wt")) == NULL)
	    fprintf(stderr,"Cannot create %s\n", buffer);
    } while (!out);


    x1 = start->xmin;
    x2 = start->xmax;
    y1 = start->ymin;
    y2 = start->ymax;
    decx1 = ( (x1 - end->xmin) / steps);
    decx2 = ( (x2 - end->xmax) / steps);
    decy1 = ( (y1 - end->ymin) / steps);
    decy2 = ( (y2 - end->ymax) / steps);

    for (i=steps; i>0; i--) {
	fprintf(out,"Fractint batch=yes type=%s corners=",
		name_of[start->fractal_type]);
	fprintf(out, "%10.10f/%10.10f/%10.10f/%10.10f\n",
		x1, x2, y1, y2);

	x1 -= decx1;
	x2 -= decx2;
	y1 -= decy1;
	y2 -= decy2;
    }
    fclose(out);
}
