/*
/* let the user test and pick video modes */
/*                                        */
/* text screen is: a title on the top line
						 a video card list (columns 1 to 24)
						 a video mode list in the upper right corner (rows 2 to 12)
						 a selected mode list in the lower right (rows 13 to 24)
		--> if the lists ever exceed the ranges scroll bars will have to be added

  problems
  - plotting border has problems on the last char because it causes a CR/LF !!
  - loading the mask string needs a \n termination but this will be added the next time its
		saved (ie you have 2 then 3 then 4 ...  -> so search the string and clip them out - done during loadin
*/

#include "jvsetup.h"
#include "conio.h"
#include "stdio.h"


extern unsigned _stklen = 8192;


int get_key(void);
void borders(int hi_light);
void test_video(int sel_card, int sel_mode);


/* get a key and strip that pesky 0 if its a usefull {arrow, page, insert, delete ..} key */

int get_key(void)
{
int cmd;
if ( (cmd = getch()) == 0) cmd = getch();
return cmd;
}


/* draw the dividers on the screen for the text mode video selection
	 hi_light is the flag to draw a bright border around (active area)
  */

void test_video(int sel_card, int sel_mode)
{
static int i,
			x, y,
			x_size,
			y_size;

x_size = video_cards[sel_card].vid_mode[sel_mode].x_size;
y_size = video_cards[sel_card].vid_mode[sel_mode].y_size;

forcevga(sel_card);
svgamode(video_cards[sel_card].vid_mode[sel_mode].mode_number, x_size);

if (hi_color == 0){
	for (i=0; i<256; i++){
		palbuf[i][0] = 64 - i / 4;
		palbuf[i][1] = (i / 2) % 64;
		palbuf[i][2] = i % 64;
		}
	setmany(palbuf,0,256);
	}
for (x=0; x < x_size; x++)
	for(y=0; y < y_size; y++)
		if (hi_color)
			if (sel_card == 16){		/* ATI hi_color card */
				point(2*x,y, palbuf[x%256][2] + (palbuf[x%256][1]<<5));
				point(2*x+1,y, (palbuf[x%256][1] << 5) + (palbuf[x%256][0] << 10));
				}
			else
				point_hi(x,y, palbuf[x%256][2]+(palbuf[x%256][1]<<5) + (palbuf[x%256][0] << 10));
		else
			point(x,y,x%256);
getch();
textmode(C80);
}


void borders(int hi_light)
{
int i;
char char_is;
struct text_info ti;

gettextinfo(&ti);

if (hi_light){
	textcolor(WHITE);
	char_is = 219;			/* solid block */
	}
else{
	textcolor(LIGHTGRAY);
	char_is = 177;			/* 1/2 dense block */
	}

for (i=1; i <= (ti.winright-ti.winleft); i++){		/* should go 1 count more */
	gotoxy(i, 1);
	putch(char_is);
	gotoxy(i, ti.winbottom - ti.wintop + 1);
	putch(char_is);
	}
for (i=2; i <= (ti.winbottom-ti.wintop); i++){
	gotoxy(1, i);
	putch(char_is);
	gotoxy(ti.winright - ti.winleft, i);		/* had to sub +1 */
	putch(char_is);
	}
}


int main(void)
{
static int i,
			exit_now,			/* exit flag for main loop */
			sel_card,			/* pointer into array for selected video card */
			sel_mode,			/* pointer into array for selected mode */
			sel_mode_list,		/* currently item in selected mode list pointed to */
			ins_loc,				/* location to insert a new item into the users list of working modes */
			some,					/* a check to make sure that the user mode list is not empty - otherwise the prog locs! */
			update_file,		/* flag that cfg info has change */
			text_width,			/* text screen width - currently 80 char - not yet used*/
			text_mode,			/* mode for the text screen - not yet used */
			sort_mode,			/* method to sort file list by - not yet used*/
			card_mode_oklist;		/* flag for oklist (0) or card (2) or mode (1) in selection*/
static char cmd;
static struct text_info ti;
static char file_mask[20] = "*.*";
			FILE *config_file;

for (i = 0; i <= number_modes_in_list; i++)
	ok_mode[i].card_ID = -1;					/* set to not filled */


/* does the dvpeg.cfg file exist? */
config_file = fopen("dvpeg.cfg", "rb");
if (config_file != NULL){						/* load the file mode descriptions */
	text_width = getw(config_file);
	text_mode = getw(config_file);
	sort_mode = getw(config_file);
	fgets(file_mask, 15, config_file);
	for (i=0; i < 15; i++)
		if (file_mask[i] == '\n') file_mask[i] = 0;		/* remove that \n since it is only needed for loading string in */
	i = 0;
	while((sel_card = getw(config_file)) != -1){
		if (i >= number_modes_in_list){
			printf("Configuration file is in error.  Please delete it.\r\n");
			exit(-1);
			}
		ok_mode[i].card_ID = sel_card;
		ok_mode[i++].which_mode = getw(config_file);
		card_id = sel_card;		/* let the menu default to last card in the list */
		}
	fclose(config_file);
	}
else{					/* no? then autodetect */
	svga=whichvga();
	if (svga){
		if (aheada == 1 || aheadb == 1) card_id = 0;
		if (ativga == 1) card_id = 1;
		if (chipstech == 1) card_id = 2;
		if (everex == 1) card_id = 3;
		if (oaktech == 1) card_id = 4;
		if (genoa == 1) card_id = 5;
		if (ncr == 1) card_id = 6;
		if (paradise == 1) card_id = 7;
		if (trident == 1)
		if (t8900 == 1) card_id = 9;
			else card_id = 8;
		if (tseng == 1)
			if (tseng4 == 1) card_id = 11;
			else card_id = 10;
		if (video7 == 1) card_id = 12;
		if (cirrus == 1) card_id = 13;
		if (compaq == 1) card_id = 14;
		if (vesa == 1) card_id = 15;

		/* assume all modes are there and copy them over */
		for (i=0; i < number_modes_supported; i++)
			if (video_cards[card_id].vid_mode[i].mode_number != 0){
				ok_mode[i].card_ID = card_id;
				ok_mode[i].which_mode = i;
				}
		update_file = 1;
		}
	else
		{
		card_id = 0;				/* let the user guess what it is but assume 320 * 200 mode (first in all of them) */
		ok_mode[0].card_ID = 0;		/* make sure that there is one item in the selected list */
		ok_mode[0].which_mode = 0;      	/*  this will always be 320 * 200 */
		}
	}


sel_card = card_id;
sel_mode = sel_mode_list = 0;			/* default to lowest resolution, card detected*/

textmode(C80);
_setcursortype(_NOCURSOR);			/* hide the cursor*/

gettextinfo(&ti);

card_mode_oklist = 2;		/* start with card menu*/

/* select a video card and mode */
clrscr();
textcolor(YELLOW);
gotoxy(1,1);
cprintf("             Video Setup                                          Dvpeg");

/* note right side has to be wider to prevent CR/LF on plotting char 1! */

do{
	window(1, 2, 24, 25);
/* setup the borders on the screen with video card hi_light */
	borders(card_mode_oklist == 2);
	window(2, 3, 23, 24);
	gotoxy(1,1);
	textcolor(YELLOW);
	cprintf("  Video cards\n\r");
	textcolor(WHITE);
	for (i=0; i < number_VGA_cards; i++){
		if (i == sel_card)
			if (card_mode_oklist == 2)	textcolor(LIGHTMAGENTA);
			else	textcolor(MAGENTA);
			cprintf("  %2i - %s\r\n", i, video_cards[i].name);
		textcolor(WHITE);
		}

	window(25, 2, 80, 11);		/* plot video mode available */
	borders(card_mode_oklist == 1);
	window(26, 3, 78, 10);
	clrscr();
	gotoxy(1,1);
	textcolor(YELLOW);
	cprintf("   Video Modes\r\n");
	textcolor(WHITE);
	cprintf(" X size, Y size, mode #\n\r");
	for (i=0; i < number_modes_supported; i++)
		if (video_cards[sel_card].vid_mode[i].mode_number != 0){
			if (i == sel_mode)
				if (card_mode_oklist == 1)	textcolor(LIGHTMAGENTA);
				else	textcolor(MAGENTA);
			cprintf(" %4i   %5i   %4hu\r\n",video_cards[sel_card].vid_mode[i].x_size,video_cards[sel_card].vid_mode[i].y_size, video_cards[sel_card].vid_mode[i].mode_number);
			textcolor(WHITE);
			}

	window(25, 12, 80, 25);		/* plot video mode list as selected */
	borders(card_mode_oklist == 0);
	window(26, 13, 78, 24);
	clrscr();
	gotoxy(1,1);
	textcolor(YELLOW);
	cprintf("         Selected Video Modes\n\r");
	textcolor(WHITE);
	cprintf(" Video Card,        X size, Y size, mode #\n\r");
	for (i=0; i < number_modes_in_list; i++)
		if (ok_mode[i].card_ID >= 0){
			if (i == sel_mode_list)
				if (card_mode_oklist == 0)	textcolor(LIGHTMAGENTA);
				else	textcolor(MAGENTA);
			cprintf(" %15s    %4i   %5i   %4hu\r\n",video_cards[ok_mode[i].card_ID].name,
				video_cards[ok_mode[i].card_ID].vid_mode[ok_mode[i].which_mode].x_size,video_cards[ok_mode[i].card_ID].vid_mode[ok_mode[i].which_mode].y_size, video_cards[ok_mode[i].card_ID].vid_mode[ok_mode[i].which_mode].mode_number);
			textcolor(WHITE);
			}

	cmd = get_key();
	if (cmd == escape){
		if (card_mode_oklist == 2) exit_now = 1;
		else card_mode_oklist++;					/* RTN selects mode and/or exit */
		cmd = 0;
		}
	if (cmd == RTN){
		card_mode_oklist--;		/* ESC hops to card select */
		cmd = 0;						/* only change menu, don't act on cmd */
		}
	if (card_mode_oklist < 0) card_mode_oklist = 0;
	switch (card_mode_oklist){
		case 0:			/* ok mode list ie select for delete */
			for (some = 0, i=0; i< number_modes_in_list; i++)		/* check for an empty list which would hang the S/W */
				if (ok_mode[i].card_ID >= 0)
					some = 1;

			switch (cmd){
				case arrow_up:
					do{
						if (sel_mode_list > 0) sel_mode_list -=1;
						else sel_mode_list = number_modes_in_list - 1;
						} while (ok_mode[sel_mode_list].card_ID < 0 && some);
					break;
				case arrow_down:
					do{
						if (sel_mode_list < number_modes_in_list-1) sel_mode_list += 1;
						else sel_mode_list = 0;
						} while (ok_mode[sel_mode_list].card_ID < 0 && some);
					break;
				case delete:
					for (i=sel_mode_list; i < number_modes_in_list; i++){
						ok_mode[i].card_ID = ok_mode[i+1].card_ID;
						ok_mode[i].which_mode = ok_mode[i+1].which_mode;
						}
					update_file = 1;
					sel_mode = sel_mode_list = 0;		/* reset so point points to something */
					break;
				}
				break;
		case 2:			/* select a video card move up/down */
			switch (cmd){
				case arrow_up:
					if (sel_card > 0) sel_card -=1;
					else sel_card = number_VGA_cards - 1;
					sel_mode = 0;		/* old mode number may be high so reset */
					break;
				case arrow_down:
					if (sel_card < number_VGA_cards - 1) sel_card += 1;
					else sel_card = 0;
					sel_mode = 0;
				}
				break;
		case 1:			/* select a video mode -> test/add to list */
			switch (cmd){
				case arrow_up:
					do{				/* make sure that we get an existing mode */
						if (sel_mode > 0) sel_mode -=1;
						else sel_mode = number_modes_supported - 1;
						} while (video_cards[sel_card].vid_mode[sel_mode].mode_number == 0);
					break;
				case arrow_down:
					do{
						if (sel_mode < number_modes_supported - 1) sel_mode += 1;
						else sel_mode = 0;
						} while (video_cards[sel_card].vid_mode[sel_mode].mode_number == 0);
					break;
				case insert:
					ins_loc = 0;
					/* first find the position of a mode that is non 0 and lower resolution than the selected */
					for (i = 0; i < number_modes_in_list; i++)
						if (ok_mode[i].card_ID >= 0)
							if ((video_cards[ok_mode[i].card_ID].vid_mode[ok_mode[i].which_mode].y_size <
									video_cards[sel_card].vid_mode[sel_mode].y_size) &&
									( video_cards[sel_card].vid_mode[sel_mode].y_size != 0))
								ins_loc = i + 1;

						/* inserting to a full list does nothing */
						i = number_modes_in_list;
						while( --i > ins_loc){
							ok_mode[i].card_ID = ok_mode[i-1].card_ID;
							ok_mode[i].which_mode = ok_mode[i-1].which_mode;
							}

						/* now insert it - watchout for inserting at top + 1*/
						if (ins_loc < number_modes_in_list){
							ok_mode[ins_loc].card_ID = sel_card;
							ok_mode[ins_loc].which_mode = sel_mode;
							}
					update_file = 1;
					break;
				case 0:
					break;		/* make sure return, esc does nothing */
				default:			/* default to testing the mode */
					test_video(sel_card, sel_mode);
			}
			break;
		}
	} while (exit_now == 0);

textmode(C80);
clrscr();
_setcursortype(_NORMALCURSOR);

if (update_file){			/* file was changed - does the user want to save it? */
	printf("The video information has changed.\n\r");
	printf("Do you want to save it (Y or N)?\n\r");
	cmd = toupper(getch());
	if (cmd == 'Y'){
		config_file = fopen("dvpeg.cfg","wb");
		if (config_file != NULL){						/* load the file mode descriptions */
			putw(text_width, config_file);
			putw(text_mode, config_file);
			putw(sort_mode, config_file);
			fputs(file_mask, config_file);
			fputs("\n", config_file);
			i = 0;
			do{
				putw(ok_mode[i].card_ID, config_file);
				putw(ok_mode[i].which_mode, config_file);
				} while(ok_mode[i++].card_ID != -1);

			fclose(config_file);
			}
		else
			printf("Error saving the file.\r\n");
		}
	}
return(0);
}	/* main */
