/*

Name:
DISPLAY.C

Description:
Ncurses display section of mikmod - bare unix version.

Should deal with all the quiet options and refresh() after ncurses calls,
so just call these functions direct wherever needed. 

Steve McIntyre <stevem@chiark.greenend.org.uk>

HISTORY
=======

v1.00 (06/12/96) - first "versioned" version
v1.01 (06/12/96) - fixed update_name_display for Solaris - add "(null)" if necessary
v1.02 (16/12/96) - minor cosmetic change to display_error()
v1.03 (01/01/97) - cosmetic changes to update_status_display()
v1.04 (12/01/97) - minor changes for compilation with -Wall
v1.05 (08/02/97) - added display_instruments() (Peter Amstutz)
v1.06 (20/04/97) - deleted all the update_*() functions 'cause I thought
			they were redundant, also eliminated the whole cur_mod 
			kludge Steve cursed us with.
v1.07 (16/10/97) - fixed bug in display_instruments(), 
	added display_message()
*/

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

#ifdef NCURSES
#include <ncurses/ncurses.h>
#else
#ifdef __FreeBSD__
#include <ncurses.h>
#else
#include <curses.h>
#endif
#endif

extern int quiet, semiquiet;
extern UNIMOD *mf;
int firstinst, dispsamp=1;

void init_display(void)
{
	if(quiet) return;
	initscr(); 
	cbreak(); 
	noecho(); 
	nonl(); 
	nodelay(stdscr, TRUE);
	timeout(0);
	keypad(stdscr, TRUE); 
}

void display_version(void)
{
	if(quiet) return;

	/* always use display_verion first, so clear call is OK here... */
	clear(); 

	printw("%s",mikversion);
	refresh();
}	

void display_pausebanner(void)
{
	if(quiet) return;
	addstr(pausebanner);
	refresh();
}	

void display_extractbanner(void)
{
	if(quiet) return;
	addstr(extractbanner);
	refresh();
}	

void display_loadbanner(void)
{
	if(quiet) return;
	addstr(loadbanner);
	refresh();
	firstinst=0;
}	

void display_error(char *myerr, char *myerr_file)
{
	if(quiet) return;
	printw("Non-fatal Error:\n %s: \"%s\".\n",myerr,myerr_file);
	refresh();
	sleep(3);
}	

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


void display_driver(void)
{
	if(quiet) return;
	printw("%s: %d bit %s %s, %u Hz, Reverb: %u\n",
		md_driver->Name,
		(md_mode&DMODE_16BITS) ? 16:8,
		(md_mode&DMODE_INTERP) ? "interpolated":"normal",
		(md_mode&DMODE_STEREO) ? "stereo":"mono",
		md_mixfreq, md_reverb);
	refresh();
}

void display_file(void)
{
	char filename[255];
	char arc[255];

	if(quiet) return;
	PL_GetCurrent(&playlist,filename,arc);
	printw("File: %s\n",filename); 
	refresh();
}

void display_name()
{
	if(quiet) return;
	printw("Name: %s\n"
		"Type: %s, "
		"Periods: %s,%s\n",
		mf->songname,
		mf->modtype,
		(mf->flags&UF_XMPERIODS) ? "XM type" : "mod type",
		(mf->flags&UF_LINEAR) ? "Linear" : "Log");
	refresh();
}

void display_status()
{
	if(quiet) return;
	printw("\rpat:%3d/%3d pos:%3d spd:%2d bpm:%3d vol:%d%% ",
		mf->sngpos,mf->numpos,mf->patpos,mf->sngspd,mf->bpm,
		mf->volume*100/128);
	refresh();
}

void exit_display()
{
	if(quiet) return;
	endwin();
}

void display_instruments()
{
	int t;
	int i, n;
	char str[99], *foo;

	if(quiet || semiquiet) return;
	if(dispsamp==2 && mf->comment==NULL) dispsamp=1;
	if(dispsamp==1 && mf->instruments==NULL) dispsamp=0;
	if(dispsamp==0 && mf->samples==NULL) dispsamp=1;
	switch(dispsamp)
	{
		case 0:
			if(firstinst>=mf->numsmp-38) firstinst=mf->numsmp-38;
			if(firstinst<0) firstinst=0;
			for(t=firstinst;t<mf->numsmp && t<(38+firstinst);t++)
			{
				move((t-firstinst)%19+6,((t-firstinst)<19) ? 0 : 38);
				printw("%2i %-34s",t,(mf->samples[t].samplename==NULL) ?
					"" : mf->samples[t].samplename);
			}
			if(t < (37+firstinst)) 
			{
				move((t-firstinst)%19+6,((t-firstinst)<19) ? 0 : 38);
				printw("%-34s","");
			}
			break;
		case 1:
			if(firstinst>=mf->numins-38) firstinst=mf->numins-38;
			if(firstinst<0) firstinst=0;
			for(t=firstinst;t<mf->numins && t<(38+firstinst);t++)
			{
				move((t-firstinst)%19+6,((t-firstinst)<19) ? 0 : 38);
				printw("%2i %-34s",t,(mf->instruments[t].insname==NULL) ?
					"" : mf->instruments[t].insname);
			}
			if(t < (37+firstinst)) 
			{
				move((t-firstinst)%19+6,((t-firstinst)<19) ? 0 : 38);
				printw("%-34s","");
			}
			break;
		case 2:
			if((foo=mf->comment)==NULL) break;
			for(t=0; *foo!=0; t++) while(*(foo++)!='\r' && *foo!=0);
			foo=mf->comment;
			if(firstinst+20>=t) firstinst=t-20;
			if(firstinst<0) firstinst=0;
			for(i=0; i<firstinst; i++) while(*(foo++)!='\r');
			for(i=firstinst; i<(19+firstinst<t ? 19+firstinst : t); i++)
			{
				move(i-firstinst+6, 0);
				for(n=0; *foo!='\r' && *foo!=0; n++, foo++)
				{
					str[n]=*foo;
				}
				foo++;
				str[n]=0;
				printw("%-80.80s", str);
			}
			break;
	}
	move(5,0);
	refresh();
}

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