/*- EXTRAS.CC --------------------------------------------------------------*

 Code for generating things with windows (C++)

 Any inquiries to Dylan Cuthbert via
 DYL@CIX.COMPULINK.CO.UK
*---------------------------------------------------------------------------*/
#define _EXTRAS_

#include "sfc.h"


/*--------------------------------------------------------------------------*/
// Variables used by the file requester

char drivetext[MAXDRIVE];
char dirtext[MAXDIR];
char pathtext[MAXPATH];
char filetext[MAXFILE];
char exttext[MAXEXT];
char filename[MAXPATH];
char *flist,*dlist;
Window *fr;
/*--------------------------------------------------------------------------*/


/*--------------------------------------------------------------------------*/
char *readindir(char *dir,int flags)
	{
	struct ffblk b;
	char *p=NULL,*s;
	int total=0;
	int done,n;
	char temp[MAXFILE+MAXEXT+2];

	done = findfirst(dir,&b,flags);
	while (!done)
		{
		if (((b.ff_attrib&flags) || !(flags&FA_DIREC)) && strcmp(b.ff_name,"."))
			{
			p = (char *)realloc(p,total+strlen(b.ff_name)+1);
			strcpy(p+total,b.ff_name);
			*(p+total+strlen(b.ff_name)) = '\0';
			total += strlen(b.ff_name)+1;
			}

		done = findnext(&b);
		}

	p = (char *)realloc(p,total+1);
	p[total] = '\0';

// Now to sort the list:

	do	{
		done = 1;
		s = p;
		while (*s)
			{
			n = strlen(s);
			if (!*(s+n+1)) break;

			if (stricmp(s,s+n+1) > 0)
				{
				strcpy(temp,s);
				memcpy(s,s+n+1,strlen(s+n+1)+1);
				strcpy(s+strlen(s)+1,temp);
				done = 0;
				}
			s += strlen(s)+1;
			}
		} while (!done);
	

	return p;
	}

/*--------------------------------------------------------------------------*/
// Display the filename if one is selected

void UpdateName()
	{
	char temp1[MAXFILE],temp2[MAXEXT];

	fr->FGcolor(LIGHTGRAY);
	fr->filledbox(0,fr->textheight(),fr->MaxX(),fr->textheight()*3);

	fr->textxy(0,1);
	fr->textalign(GR_ALIGN_LEFT,GR_ALIGN_TOP);
	fr->FGcolor(BLACK);
	fr->printf("\n Search: %s%s%s%s\n",drivetext,dirtext,filetext,exttext);

	strcpy(filename,fr->GetString(5));
	fr->printf(" Filename:\n");
	fr->Find(5)->Draw();
	fnsplit(filename,NULL,NULL,temp1,temp2);	// Separate the name and extension
	fnmerge(filename,drivetext,dirtext,temp1,temp2);
	}

/*--------------------------------------------------------------------------*/
// Update the directory and file lists

void UpdatePath()
	{

	if (dlist) free(dlist);
	if (flist) free(flist);

// Form the path and wildcards to search for files

	fnmerge(pathtext,drivetext,dirtext,filetext,exttext);
	flist = readindir(pathtext,FA_RDONLY|FA_ARCH);

// Form the path and wildcards to search for directories

	fnmerge(pathtext,drivetext,dirtext,"*",NULL);
	dlist = readindir(pathtext,FA_DIREC|FA_LABEL);

// Set up the lists in the gadgets

	fr->SetList(3,flist);
	fr->SetList(1,dlist);

	UpdateName();
	fr->flush();
	}
/*--------------------------------------------------------------------------*/
// Get a filename from the file requester

#define FR_XS ((GrScreenX()+1)/2)
#define FR_YS ((GrScreenY()+1)/2)
#define FRR_XS (FR_XS/2-16)

char *getfilename(char *title,FRPath *dir,char *name,int flags)
	{
	int exitplease = 0,r;
	char *s,*d;
	char tempfile[MAXFILE],tempext[MAXEXT];
	char tempdrive[MAXDRIVE],tempdir[MAXDIR];

	fr = new Window(GrScreenX()/2-FR_XS/2,GrScreenY()/2-FR_YS/2,GrScreenX()/2+FR_XS/2,GrScreenY()/2+FR_YS/2,LIGHTGRAY,title,W_BACKINGSTORE|W_MOTIFBORDER);

	*fr << WT_BLACK;
	fr->setfont(nicefont);

	new Gadget(fr, fr->textwidth("Filename: "), fr->textheight()*2, fr->textwidth("W")*20, 0, name,5,G_STRING|G_TEXTHIGHLIGHT|G_OVERONLY,0);

	new Gadget(fr,fr->MaxX()-32-FRR_XS*2,GADGETSIZEY(fr)*2,fr->MaxX()-32-FRR_XS,fr->MaxY()-GADGETSIZEY(fr)-4,flist,3,G_BOXHIGHLIGHT|G_LIST,0);
	new Gadget(fr,fr->MaxX()-16-FRR_XS,GADGETSIZEY(fr)*2,fr->MaxX()-16,fr->MaxY()-GADGETSIZEY(fr)-4,dlist,1,G_LIST|G_BOXHIGHLIGHT,0);

	new Gadget(fr,fr->SizeX()/2-(GADGETSIZEX(fr,"OK")+GADGETSIZEX(fr,"CANCEL")+2)/2 ,fr->MaxY()-GADGETSIZEY(fr), 0,0,"OK",0,G_TEXTHIGHLIGHT|G_BOXTEXT|G_OVERONLY|G_BOXHIGHLIGHT|G_EXCLUSIVE,13);
	new Gadget(fr,fr->SizeX()/2-(GADGETSIZEX(fr,"OK")+GADGETSIZEX(fr,"CANCEL")+2)/2 + GADGETSIZEX(fr,"OK")+2 ,fr->MaxY()-GADGETSIZEY(fr), 0,0,"CANCEL",6,G_TEXTHIGHLIGHT|G_BOXTEXT|G_OVERONLY|G_BOXHIGHLIGHT|G_EXCLUSIVE,'');


	fr->Highlight(3);

	*drivetext = '\0';
	*dirtext = '\0';
	*filetext = '\0';
	*exttext = '\0';
	fnsplit(dir->path,drivetext,dirtext,filetext,exttext);
	UpdatePath();

	fr->flush();

	while (!exitplease)
		{
		Update_Mouse();
		if (fr->mouse())
			{
			if (fr->input.gflags&GF_HIGHLIGHT)
				{
				switch(fr->input.gadget)
					{
					case 5:
// Deselect any highlighted items in the file listing
						fr->SetSelectedItem(3,-1);
						break;
					case 3:
						if (fr->GetSelectedItem(3))
							fr->SetString(5,fr->GetSelectedItem(3));
						else fr->SetString(5,"");
						UpdateName();
						fr->flush();
						break;
					default:
						break;
					}
				}
			if (fr->input.gflags&GF_SELECTED)
				 switch(fr->input.gadget)
					{
// CANCEL
					case 6:
						exitplease = 2;
						break;
// Filename string gadget
					case 5:
						if (s = fr->GetString(5))
							{
							if (r = ((fnsplit(s,tempdrive,tempdir,tempfile,tempext))&(WILDCARDS|DRIVE|DIRECTORY)))
								{
								if (r & WILDCARDS)
									{
									strcpy(filetext,tempfile);
									strcpy(exttext,tempext);
									}

								if (r & DRIVE)
									{
									strcpy(drivetext,tempdrive);
									if (!(r & DIRECTORY)) strcpy(dirtext,"\\");
									}

								if (r & DIRECTORY)
									strcpy(dirtext,tempdir);

								fr->SetString(5,"");
								UpdatePath();
								}
							}
						break;
// File listing gadget
					case 3:
						exitplease = 1;
						break;

// Directory listing gadget
					case 1:
						if (s = fr->GetItem(fr->input.gadget,fr->input.slider))
							{
							if (strcmp(s,"..")==0)
								{
								d = dirtext+strlen(dirtext)-2;

// If parent then delete previous directory name if possible

								if (d>dirtext)
									{
									while (dirtext<=d)
										{
										if (*d == '\\')
											{
											if (strncmp(d,"\\..",3) != 0)
												{
												d[1] = '\0';
												s = NULL;
												}
											break;
											}
										d--;
										}
									}
								}

							if (s)
								{
								strcpy(dirtext+strlen(dirtext),s);
								strcpy(dirtext+strlen(dirtext),"\\");
								}
							UpdatePath();
							}
						break;
					case 0:
						exitplease = 1;
						break;
					default:
						break;
					}
			}
		}

	UpdateName();

	delete fr;

	if (flist) free(flist);
	if (dlist) free(dlist);
	flist = NULL; dlist = NULL;

	if (exitplease == 1 && strlen(filename))
		{
		if (flags&FR_SETPATH) fnmerge(dir->path,drivetext,dirtext,filetext,exttext);
		fnsplit(filename,NULL,NULL,tempfile,NULL);
		if (!(flags&FR_ALLOWDIRECTORY) && strlen(tempfile)==0)
			return NULL;
		else return filename;
		}
	else return NULL;
	}

/*--------------------------------------------------------------------------*/

#define WOK_XS ((GrScreenX()+1)/4+(GrScreenX()+1)/8)
#define WOK_YS ((GrScreenY()+1)/8+(GrScreenY()+1)/16)

void Wait_ok(int cx,int cy,char *temp,...)
{
	Window *ow;
	va_list args;
	int exitplease = 0;

	va_start(args,temp);

	ow = new Window(cx-WOK_XS/2,cy-WOK_YS/2,cx+WOK_XS/2,cy+WOK_YS/2,LIGHTGRAY,"Select OK to continue",W_BACKINGSTORE|W_MOTIFBORDER);

	ow->FGcolor(BLACK);
	ow->setfont(nicefont_bold);
	ow->textxy(ow->SizeX()/2,ow->textheight());
	*ow << WT_CENTRE;
	ow->vprintf(temp,&args);

	new Gadget(ow,ow->SizeX()/2-GADGETSIZEX(ow,"OK")/2 ,ow->MaxY()-GADGETSIZEY(ow),0,0,"OK",0,G_TEXTHIGHLIGHT|G_BOXTEXT|G_OVERONLY|G_BOXHIGHLIGHT|G_EXCLUSIVE,13);

	va_end(args);

	ow->Direct();

	while (!exitplease)
		{
		Update_Mouse();
		if (ow->mouse())
			{
			if ((ow->input.gflags&GF_SELECTED) && ow->input.gadget==0)
				exitplease = 1;
			if ((ow->input.flags&M_KEYPRESS) && ow->input.key == '')
				exitplease = 1;
			}
		}

	delete ow;
}

/*--------------------------------------------------------------------------*/

int Wait_yesno(int cx,int cy,char *temp,...)
{
	Window *ow;
	va_list args;
	int exitplease = 0;

	va_start(args,temp);

	ow = new Window(cx-WOK_XS/2,cy-WOK_YS/2,cx+WOK_XS/2,cy+WOK_YS/2,LIGHTGRAY,"Select OK to continue",W_BACKINGSTORE|W_MOTIFBORDER);

	ow->FGcolor(BLACK);
	ow->setfont(nicefont_bold);
	ow->textxy(ow->SizeX()/2,ow->textheight());
	*ow << WT_CENTRE;
	ow->vprintf(temp,&args);

	new Gadget(ow,ow->SizeX()/2-(GADGETSIZEX(ow,"YES")+GADGETSIZEX(ow,"NO"))/2 ,ow->MaxY()-GADGETSIZEY(ow),0,0, "YES",1,G_TEXTHIGHLIGHT|G_BOXTEXT|G_OVERONLY|G_BOXHIGHLIGHT|G_EXCLUSIVE,13);
	new Gadget(ow,ow->SizeX()/2-(GADGETSIZEX(ow,"YES")+GADGETSIZEX(ow,"NO"))/2+GADGETSIZEX(ow,"NO") ,ow->MaxY()-GADGETSIZEY(ow),0,0, "NO",0,G_TEXTHIGHLIGHT|G_BOXTEXT|G_OVERONLY|G_BOXHIGHLIGHT|G_EXCLUSIVE,'');

	va_end(args);

	ow->Direct();

	while (!exitplease)
		{
		Update_Mouse();
		if (ow->mouse())
			{
			if ((ow->input.gflags&GF_SELECTED) && ow->input.gadget==0)
				exitplease = 1;
			}
		}

	delete ow;

	return ow->input.gadget;
}

/*--------------------------------------------------------------------------*/

#define GN_XS ((GrScreenX()+1)/2)
#define GN_YS ((GrScreenY()+1)/4)

int GetNumber(char *title,int *val,int min,int max)
	{
	Window *gn;
	int exitplease=0;
	int newval;
	char buffer[10];

	gn = new Window(GrScreenX()/2-GN_XS/2,GrScreenY()/2-GN_YS/2,GrScreenX()/2+GN_XS/2,GrScreenY()/2+GN_YS/2,LIGHTGRAY,title,W_BACKINGSTORE|W_MOTIFBORDER);

	*gn << WT_BLACK;
	gn->setfont(nicefont);

	sprintf(buffer,"%d",*val);

	new Gadget(gn,gn->SizeX()/2-(GADGETSIZEX(gn,"OK")+GADGETSIZEX(gn,"CANCEL")+2)/2 ,gn->MaxY()-GADGETSIZEY(gn), 0,0,"OK",0,G_TEXTHIGHLIGHT|G_BOXTEXT|G_OVERONLY|G_BOXHIGHLIGHT|G_EXCLUSIVE,13);
	new Gadget(gn,gn->SizeX()/2-(GADGETSIZEX(gn,"OK")+GADGETSIZEX(gn,"CANCEL")+2)/2 + GADGETSIZEX(gn,"OK")+2 ,gn->MaxY()-GADGETSIZEY(gn), 0,0,"CANCEL",1,G_TEXTHIGHLIGHT|G_BOXTEXT|G_OVERONLY|G_BOXHIGHLIGHT|G_EXCLUSIVE,'');
	new Gadget(gn, gn->textwidth("Value: "), gn->textheight()*2, gn->textwidth("W")*20, 0, buffer,2,G_STRING|G_TEXTHIGHLIGHT|G_OVERONLY|G_NUMBER|G_BOXTEXT|G_BOXHIGHLIGHT,0);

	gn->textxy(0,gn->textheight()*2+1);
	*gn << "Value: \n";
	
	gn->flush();

	gn->Highlight(2);
	gn->Select(2);

	while (!exitplease)
		{
		Update_Mouse();
		if (gn->mouse())
			{
			if (gn->input.gflags&GF_SELECTED)
				{
				switch(gn->input.gadget)
					{
					case 0:
						exitplease = 1;
						break;
					case 1:
						exitplease = 2;
						break;
					default:
						break;
					}
				}
			}
		}

	newval = strtol(gn->GetString(2),NULL,0);

	delete gn;

	if (exitplease==2) return 0;

	*val = newval;
	return 1;
	}
/*--------------------------------------------------------------------------*/

