#ifndef CODE_FILEDIALOG_CXX
#define CODE_FILEDIALOG_CXX

/*-----------------------------------------------------------------------
 * Xclasses code file
 * ($Id: file_dialog.cxx,v 1.6 1999/04/18 18:16:56 schmitzj Exp $)
 * 
 * Copyright (C) 1998 Jürgen Schmitz
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA  02111-1307, USA.
 *-----------------------------------------------------------------------
 */

#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
#include "types.h"
#include <Xclasses/tools.h>
#include <Xclasses/Xwindows.h>
#include <Xclasses/Xcolors.h>
#include <Xclasses/file_dialog.h>
#include <Xclasses/easy_dialog.h>
#include "include/file_dialog_p.h"
#include "../include/defaults.h"

file_dialog::file_dialog(void) : Xcolors()
{
	while (!(p=new pfile_dialog))
	{
		outOfMemory("file_dialog");
	}
	p->o=this;
	p->aw.ParentClass(this);
	p->aw.Name("file_dialog_window");
	Name("file_dialog");
}
pfile_dialog::pfile_dialog() : aw(), maingp(), buts(), dirs(), pattern(), dirname(), filename(), rul(), ok(), cancel(), gohome(), parent()
{
	oktext="_Ok";
	canceltext="_Cancel";
	gohometext="_Home";
	parenttext="_Parent";
	patterntext="Pattern";
	dirnametext="Directory";
	filenametext="File";
	dirs.ApplyInput(dirname);

	dirname.MaxChars(400);
	filename.MaxChars(255);
	pattern.MaxChars(30);
	pattern.Default("*");

	save=0;
	append=0;
	dirmode=0;
	insertgroup=NULL;
}
pfile_dialog::~pfile_dialog()
{
}
file_dialog::~file_dialog()
{
	if (p) delete p;
}

void file_dialog::Text_Ok(char *t)
{
	p->oktext=t;
}
void file_dialog::Text_Cancel(char *t)
{
	p->canceltext=t;
}
void file_dialog::InsertGroup(group *g)
{
	p->insertgroup=g;
}
void file_dialog::LoadMode(void)
{
	p->save=0;
}
void file_dialog::SaveMode(void)
{
	p->save=1;
}

void file_dialog::ShowPeriod(void)
{
	p->dirs.ShowPeriod();
}
void file_dialog::NoPeriod(void)
{
	p->dirs.NoPeriod();
}
void file_dialog::MultiSelect(void)
{
	p->dirs.MultiSelect();
}
void file_dialog::SingleSelect(void)
{
	p->dirs.SingleSelect();
}

void file_dialog::DirSelector(void)
{
	p->dirmode=1;
	p->dirs.DirSelector();
}
void file_dialog::FileSelector(void)
{
	p->dirmode=0;
	p->dirs.FileSelector();
}

int file_dialog::SetDir(char *d)
{
	return p->dirs.SetDir(d);
}
void file_dialog::GetDir(char *d,int size)
{
	p->dirs.GetDir(d,size);
}
void file_dialog::SetFile(char *d)
{
	if (p->dirmode)
	{
		SetDir(d);
	}
	else
	{
		char *c1=d,*c2=d;
		while (*c1)
		{
			if (*c1=='/')
			{
				c2=c1+1;
			}
			c1++;
		}
		p->filename.Default(c2);
		if (c2!=d)
		{
			char b[c2-d+1];
			strncpy(b,d,c2-d);
			b[c2-d]=0;
			SetDir(b);
		}
	}
}
void file_dialog::GetFile(char *d,int size)
{
	char dir[400];
	p->filename.Input(dir);
	strncpy(d,dir,size);
}
void file_dialog::SetPattern(char *pt)
{
	p->dirs.SetPattern(pt);
	p->pattern.Default(pt);
}
int file_dialog::NextMarkedFile(int old,char *d,int size)
{
	return p->dirs.FindNextMarked(old,d,size);
}
int file_dialog::IsSelectedMarked(void)
{
	return p->dirs.IsSelectedMarked();
}
int pfile_dialog::fileok(Xwindows *w)
{
	int r=1;
	if (save)
	{
		char buf[600],f[260];
		struct stat st;
		o->GetDir(buf,sizeof(buf));
		filename.Input(f);
		strcat(buf,f);
		if (!stat(buf,&st))
		{
			easy_dialog saveok;
			saveok.Options("Save over|Select other|Leave");
			sprintf(buf,"File '%s' already\nexists!",f);
			saveok.Text(buf);
			switch (saveok.Start(w))
			{
				case 1:
					r=1;
					break;
				case 2:
					r=0;
					break;
				case 3:
					r=2;
					break;
			}
		}
	}
	else
	{
		char f[260];
		filename.Input(f);

		if (!f[0]) r=0;
	}
	return r;
}
int file_dialog::Start(Xwindows *w)
{
	int i,ende,x,y,wi,hi;

	p->maingp.Name("maingroup");
	p->maingp.Vert();
	p->maingp.YDistance(5);
	 p->dirs.Name("filelist");
	 p->dirs.Font(FONT_FIXED);
	 p->dirs.DirsFirst();
	 p->dirs.ID(1);
	p->maingp.Add(p->dirs);
	 p->pattern.Name("patterninput");
	 p->pattern.Text(p->patterntext);
	 p->pattern.ID(2);
	p->maingp.Add(p->pattern);
	 p->dirname.Name("dirnameinput");
	 p->dirname.Text(p->dirnametext);
	 p->dirname.ID(3);
	p->maingp.Add(p->dirname);
	 p->filename.Name("filenameinput");
	 p->filename.Text(p->filenametext);
	 p->filename.ID(4);
	if (!p->dirmode) p->maingp.Add(p->filename);
	if (p->insertgroup)
	{
	 p->maingp.Add(p->insertgroup,"");
	}
	 p->rul.Horiz();
	 p->rul.Space(4);
	p->maingp.Add(p->rul);
	 p->buts.Name("buttongroup");
	 p->buts.Horiz();
	 p->buts.XDistance(5);
	  p->ok.Text(p->oktext);
	  p->ok.ID(5);
	  p->ok.Name("okbutton");
	 p->buts.Add(p->ok);

	  p->parent.Text(p->parenttext);
	  p->parent.ID(8);
	  p->parent.Name("parentbutton");
	 p->buts.Add(p->parent);

	  p->gohome.Text(p->gohometext);
	  p->gohome.ID(7);
	  p->gohome.Name("homebutton");
	 p->buts.Add(p->gohome);
	  p->cancel.Text(p->canceltext);
	  p->cancel.ID(6);
	  p->cancel.Name("cancelbutton");
	  p->cancel.ApplyXKey(XK_Escape);
	 p->buts.Add(p->cancel);
	p->maingp.Add(p->buts);

	GetPositionOnRoot(display(),w->window(),x,y);
	w->Size(wi,hi);

	p->aw.InitSize(x,y,60);
	p->aw.Init();
	p->aw.TransientFor(w);
	p->aw.SetGroup(p->maingp);
	p->aw.Adjust(x,y,wi,hi,ADJUST_CENTER|ADJUST_MIDDLE);
	p->aw.Create();

	p->aw.BlockExcept();

	p->dirs.ActivateKey();
	p->cancel.ApplyXKey(XK_Escape);
	ende=0;
	do
	{
		i=p->aw.NextEvent();
		if (i==EV_WINDOWCLOSE)
		{
			if (p->aw.CloseMe()) ende=2;
		}
		else if (i==EV_GADGET)
		{
			switch (p->aw.ID())
			{
				case 1: // File
					{
						char fnme[400];
						p->dirs.GetFile(fnme,sizeof(fnme));
						p->filename.Default(fnme);
					}
					if (p->aw.DoubleClick() && !p->dirmode) ende=p->fileok(w);
					break;
				case 2: // pattern
					{
						char pat[40];
						p->pattern.Input(pat);
						if (!strlen(pat)) strcpy(pat,"*");
						p->dirs.SetPattern(pat);
					}
					break;
				case 3: // dirname
					{
						char pat[260],opat[260];
						GetDir(opat,sizeof(opat));
						p->dirname.Input(pat);
						if (p->dirs.SetDir(pat))
						{
							p->aw.Beep(30,120);
							p->dirs.SetDir(opat);
						}
					}
					break;
				case 4: // filename
					p->aw.MCursor(XC_watch);
					ende=p->fileok(w);
					p->aw.MCursor(-1);
					break;
				case 5: // ok
					p->aw.MCursor(XC_watch);
					ende=p->fileok(w);
					p->aw.MCursor(-1);
					if (!ende)
					{
						char pat[40];
						p->pattern.Input(pat);
						if (!strlen(pat)) strcpy(pat,"*");
						p->dirs.SetPattern(pat);
					}
					break;
				case 6: // cancel
					ende=2;
					break;
				case 7: // gohome
					{
						char *h=getenv("HOME");
						if (h)
						{
							p->dirs.SetDir(h);
						}
					}
					break;
				case 8: // parent
					{
						char pat[260];
						p->dirname.Input(pat);
						strcat(pat,"..");
						p->dirs.SetDir(pat);
					}
					break;
			}
		}
	}
	while (!ende);
	p->aw.UnblockExcept();
 	{
 		int x,y,w,h;
 		char buf[200];
 		p->aw.WMPosition(x,y);
 		p->aw.Size(w,h);
 		sprintf(buf,"%dx%d%+d%+d",w,h,x,y);
 		p->aw.SetResource("*file_dialog_window.geometry",buf);
 	}
	p->aw.Close();
	if (!p->dirmode)
	{
		char buf[200];
		GetFile(buf,sizeof(buf));
		if (!strlen(buf)) ende=3;
	}
	p->insertgroup=NULL;
	return (ende==1);
}

#endif
