/*

Name:
TCLDISPLAY.C

Description:
TCL display section of mikmod 

Peter Amstutz <amstpi@freenet.tlh.fl.us>

HISTORY
=======

v1.00 (19/01/97) - split off from display.c to utilize TCL/TK frontend
v1.01 (27/03/97) - added version verification, so the version of the
					tcl/tk script has to match up with the version
					that tclmikmod expects.  Also upper-ascii translation,
					so mods that have ibm upper-ascii characters are translated
					into something that vaguly resembles what it was supposed
					to look like, rather than the gobbledygook that you end
					up with otherwise...  translation table is stored in
					"asc8-to-7.txt" (that is, 8 bit to 7 bit ascii)
v1.02 (22/04/97) - modified to work with MikMod 3.0
*/

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>
#include "mikmod.h"

extern int quiet;
extern float speed_constant;   /* multiplier for tempo,initialised to 1 */
int readme;
int writeme;
pid_t pid;
extern UNIMOD *mf;
extern int dorandom;

void init_display(void)
{
	int pipe1[2];
	int pipe2[2];
	FILE *tclfile;
	char c;
	char verline[40];

	if(quiet) return;

	pipe(pipe1);
	pipe(pipe2);

	pid=fork();

	if(pid==0)
	{
		dup2(pipe1[0],STDIN_FILENO);
		close(pipe1[0]);
		dup2(pipe2[1],STDOUT_FILENO);
		close(pipe2[1]);
		execlp("wish","wish",NULL);
		perror("Error in fork() call to start wish!!!");
		exit(1);
	}
	readme=pipe2[0];
	writeme=pipe1[1];
	if((tclfile=fopen("start.tcl","r"))==NULL)
	{
		perror("Error reading start.tcl file!");
		exit(1);
	}
	fgets(verline,40,tclfile);
	if(strcmp(verline,"#V1.13\n")!=0) 
	{
		perror("start.tcl version mismatch!");
		exit(1);
	} 
	while(!feof(tclfile))
	{
		c=fgetc(tclfile);
		write(writeme,&c,1);
	}
	c='\n';
	write(writeme,&c,1);
	usleep(500000);
}

void display_driver_error(char *myerr)
{
	if(quiet) return;
	printf("Driver error: %s.\n",myerr);
}	

void display_driver(void)
{
	char string[512];
	if(quiet) return;
	sprintf(string,
".top1.fra2.fra62.fra98.che5 %s\n"
".top1.fra2.fra62.fra98.che6 %s\n"
".top1.fra2.fra62.fra98.che7 %s\n"
".top1.fra2.fra62.fra77.che1 %s\n"
".top1.fra2.fra62.fra16.lab18 configure -text {%u}\n",
		(md_mode&DMODE_16BITS) ? "deselect":"select",
		(md_mode&DMODE_INTERP) ? "deselect":"select",
		(md_mode&DMODE_STEREO) ? "deselect":"select",
		(dorandom) ? "select":"deselect",
		md_mixfreq);
	write(writeme,string,strlen(string));
}

void display_file(void)
{
	char filename[255];
	char arc[255];
	char string[512];
	if(quiet) return;
	PL_GetCurrent(&playlist,filename,arc);
	sprintf(string,"File: %s\n",filename); 
	write(writeme,string,strlen(string));
}

void display_name()
{
	char string[512];
	if(quiet) return;

	sprintf(string,
".top1.fra2.lab10 configure -text {\"%s\"}\n"
".top1.fra2.fra22.lab25 configure -text {Type: %s}\n"
".top1.fra2.fra22.lab30 configure -text {Periods: %s}\n",
		mf->songname==NULL?"":mf->songname,
		mf->modtype,
		(mf->flags&UF_XMPERIODS) ? "XM type" : "mod type");
	write(writeme,string,strlen(string));

}

void display_status()
{
	char string[512];
	if(quiet) return;

	sprintf(string,
".top1.fra2.fra22.lab27 configure -text {Pattern: %i/ %i}\n"
".top1.fra2.fra22.lab28 configure -text {Position: %i}\n"
".top1.fra2.fra22.lab29 configure -text {Tempo: %i}\n",
		mf->sngpos, mf->numpos,
		mf->patpos, mf->sngspd);
	write(writeme,string,strlen(string));
}

void exit_display()
{
	if(quiet) return;
	write(writeme,"destroy .\n",10);
	kill(pid,SIGKILL);
}

void display_instruments()
{
	int t, i, n;
	char string[255];
	unsigned char string2[255];
	unsigned char upasc2lowasc[128];
	FILE *table;

	table=fopen("asc8-to-7.txt","r");
	if(table!=NULL)
	{
		for(i=0;i<128;i++)
		{
			fgets(string,255,table);
			upasc2lowasc[i]=string[4];
		}
	}

	write(writeme,".inst.lb delete 0 end\n",31);

	for(t=0;t<mf->numins;t++)
	{
		if(mf->instruments[t].insname!=NULL)
		{
		/* get rid of {}[]$ chars... You won't belive what a pain in 
			the ass it was to find the bug that makes this code
			essential */
			for(i=0,n=0;i<strlen(mf->instruments[t].insname);i++,n++)
			{
			/* quote all possible characters that the tcl 
			interpreter might try to interpret 
			(yes, there are a lot) */
				if(mf->instruments[t].insname[i]=='{' ||
					mf->instruments[t].insname[i]=='}' ||
					mf->instruments[t].insname[i]=='[' ||
					mf->instruments[t].insname[i]==']' ||
					mf->instruments[t].insname[i]=='$' ||
					mf->instruments[t].insname[i]=='\"' ||
					mf->instruments[t].insname[i]=='\\' ||
					mf->instruments[t].insname[i]=='(' ||
					mf->instruments[t].insname[i]==')' ||
					mf->instruments[t].insname[i]=='@' ||
					mf->instruments[t].insname[i]=='%' ||
					mf->instruments[t].insname[i]=='#')
				{
					string2[n]='\\';
					n++;
				}
				string2[n]=mf->instruments[t].insname[i];
				if(string2[n]>127) 
				{
					string2[n]=upasc2lowasc[string2[n]-128];
				}
			}
			string2[n]=0;
			sprintf(string,".inst.lb insert end \"%s\"\n",string2);
		}
		else sprintf(string,".inst.lb insert end \"\"\n");
		write(writeme,string,strlen(string));
	}
	fclose(table);
}

void display_all(void)
{
	if(quiet) return;
	display_driver();
	display_file();
	display_name();
	display_status();
}
