/*

Directory Opus 4
Original GPL release version 4.12
Copyright 1993-2000 Jonathan Potter

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program 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 General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

All users of Directory Opus 4 (including versions distributed
under the GPL) are entitled to upgrade to the latest version of
Directory Opus version 5 at a reduced price. Please see
http://www.gpsoft.com.au for more information.

The release of Directory Opus 4 under the GPL in NO WAY affects
the existing commercial status of Directory Opus 5.

*/

#include "DOpus.h"
#include "ppdata.h"

void makedir(rexx)
int rexx;
{
	int len,a,success,win,err;
	char dirname[32],new_directory[256];
	struct FileInfoBlock __aligned fileinfo;
	BPTR lock;

	win=data_active_window;
	dirname[0]=new_directory[0]=0;
	if (config->iconflags&ICONFLAG_MAKEDIRICON) len=25;
	else len=30;

	FOREVER {
		if (rexx) {
			for (a=0;a<256;a++) {
				if (!rexx_args[0][a] || rexx_args[0][a]=='/' || rexx_args[0][a]==':') break;
			}
			if (!rexx_args[0][a]) {
				if (!(isvalidwindow(data_active_window))) return;
				strcpy(new_directory,str_pathbuffer[data_active_window]);
				TackOn(new_directory,rexx_args[0],256);
			}
			else {
				strcpy(new_directory,rexx_args[0]);
				win=-1;
			}
		}
		else if (status_iconified) {
			if (!(status_flags&STATUS_ISINBUTTONS) ||
				(!(getdummypath(new_directory,STR_ENTER_DIRECTORY_NAME)))) return;
			win=-1;
		}
		else {
			if (!(isvalidwindow(data_active_window))) return;
			strcpy(new_directory,str_pathbuffer[data_active_window]);

			if (!(whatsit(globstring[STR_ENTER_DIRECTORY_NAME],len,dirname,NULL)) ||
				!dirname[0]) {
				myabort();
				return;
			}
			for (a=0;dirname[a];a++) {
				if (dirname[a]=='/' || dirname[a]==':') {
					dirname[a]=0;
					break;
				}
			}
			if (!dirname[0]) {
				myabort();
				return;
			}
			TackOn(new_directory,dirname,256);
		}

		if (!(lock=CreateDir(new_directory))) {
			doerror((err=IoErr()));
			if (rexx || (a=checkerror(globstring[STR_CREATING_DIRECTORY],
				BaseName(new_directory),-err))==3) {
				myabort();
				return;
			}
			continue;
		}

		Examine(lock,&fileinfo);
		UnLock(lock);

		if (win>-1) {
			addfile(dopus_curwin[win],win,fileinfo.fib_FileName,-1,
				fileinfo.fib_DirEntryType,&fileinfo.fib_Date,
				NULL,fileinfo.fib_Protection,0,TRUE,NULL,NULL,
				fileinfo.fib_OwnerUID,fileinfo.fib_OwnerGID);
			seename(win);
			update_buffer_stamp(win,1);
		}

		success=1;
		if (config->iconflags&ICONFLAG_MAKEDIRICON) {
			strcat(new_directory,".info");
			if ((iconwrite(ICONTYPE_DRAWER,new_directory))==1 &&
				(lockandexamine(new_directory,&fileinfo))) {
				if (win>-1) {
					addfile(dopus_curwin[win],win,fileinfo.fib_FileName,
						fileinfo.fib_Size,fileinfo.fib_DirEntryType,&fileinfo.fib_Date,
						fileinfo.fib_Comment,fileinfo.fib_Protection,0,TRUE,NULL,NULL,
						fileinfo.fib_OwnerUID,fileinfo.fib_OwnerGID);
					seename(win);
					update_buffer_stamp(win,1);
				}
			}
			else success=0;
		}
		break;
	}
	if (success) dostatustext(globstring[STR_DIRECTORY_CREATED]);
}

void blackout(screen,backupmap)
struct Screen *screen;
ULONG *backupmap;
{
	get_palette(screen,backupmap);
	LoadRGB4(&screen->ViewPort,nullpalette,1<<screen->RastPort.BitMap->Depth);
}

iconwrite(type,name)
int type;
char *name;
{
	int suc,err;
	struct DiskObject *diskobj;
	char namebuf[256],*ptr,*originalicon,sourcebuf[256];
	struct dopusfiletype *ftype;

	if (!IconBase) return(0);

	strcpy(namebuf,name);
	if ((ptr=strstri(namebuf,".info"))) *ptr=0;

	if (type==ICONTYPE_DRAWER) originalicon=config->drawericon;
	else if (type==ICONTYPE_TRASH) originalicon=NULL;
	else {
		ftype=checkfiletype(namebuf,-2,0);
		if (ftype && ftype->iconpath) originalicon=ftype->iconpath;
		else if (type==ICONTYPE_TOOL) originalicon=config->toolicon;
		else originalicon=config->projecticon;
	}

	if (originalicon) {
		strcpy(sourcebuf,originalicon);
		if (!(strstri(sourcebuf,".info"))) strcat(sourcebuf,".info");
	}

	FOREVER {
		if (originalicon && originalicon[0] && (CheckExist(sourcebuf,NULL)<0)) {
			if ((copyicon(originalicon,namebuf,&err))>0) return(1);
		}
		else {
			if (system_version2 && (diskobj=GetDefDiskObject(type+2))) {
				if (diskobj->do_Type==WBPROJECT && config->defaulttool[0]) {
					ptr=diskobj->do_DefaultTool;
					diskobj->do_DefaultTool=config->defaulttool;
				}
				else ptr=NULL;
				suc=PutDiskObject(namebuf,diskobj);
				if (ptr) diskobj->do_DefaultTool=ptr;
				FreeDiskObject(diskobj);
				if (suc) return(1);
				err=IoErr();
			}
			else {
				if (type==ICONTYPE_PROJECT)
					icontable[ICONTYPE_PROJECT]->do_DefaultTool=config->defaulttool;
				if (PutDiskObject(namebuf,icontable[type])) return(1);
				err=IoErr();
			}
		}
		if ((suc=checkerror(globstring[STR_ADDING_ICON],BaseName(namebuf),err))==3)
			return(-1);
		if (suc==0 || suc==2) return(0);
	}
}

copyicon(srce,dest,err)
char *srce,*dest;
int *err;
{
	int suc;
	struct DiskObject *diskobj;
	char buf[256],buf1[256],*ptr;

	strcpy(buf1,srce);
	if ((ptr=strstri(buf1,".info"))) *ptr=0;

	if (diskobj=GetDiskObject(buf1)) {
		suc=PutDiskObject(dest,diskobj);
		FreeDiskObject(diskobj);
		if (!suc || CheckExist(dest,NULL)>=0) *err=IoErr();
	}
	else {
		StrCombine(buf,dest,".info",256);
		suc=copyfile(srce,buf,err,-1,NULL,0);
	}
	return(suc);
}

char *isicon(name)
char *name;
{
	int a;

	if ((a=strlen(name))<6) return(NULL);
	if (LStrCmpI(&name[a-5],".info")==0) return(&name[a-5]);
	return(NULL);
}

char *getarexxpath(rexx,win,num,argnum)
int rexx,win,num,argnum;
{
	int a,b;
	char *ptr;
	struct FileInfoBlock __aligned fblock;
	APTR save;

	if (!rexx || !rexx_argcount) return(str_pathbuffer[win]);
	if ((strchr(rexx_args[argnum],':') || strchr(rexx_args[argnum],'/')) &&
		(a=CheckExist(rexx_args[argnum],&b))) {
		if (!num) {
			save=main_proc->pr_WindowPtr;
			main_proc->pr_WindowPtr=(APTR)-1;
			dos_global_entry.subtype=0;
			if (lockandexamine(rexx_args[argnum],&fblock)) {
				dos_global_entry.protection=fblock.fib_Protection;
				dos_global_entry.comment=dos_copy_comment;
				strcpy(dos_copy_comment,fblock.fib_Comment);
				dos_global_entry.dispstr=NULL;
				getprot(dos_global_entry.protection,dos_global_entry.protbuf);
				CopyMem(&fblock.fib_Date,&dos_global_entry.date,sizeof(struct DateStamp));
				seedate(&dos_global_entry.date,dos_global_entry.datebuf,1);
				dos_global_entry.selected=0;
			}
			main_proc->pr_WindowPtr=save;
			ptr=BaseName(rexx_args[argnum]);
			strcpy(dos_global_entry.name,ptr);
			if (ptr>rexx_args[argnum]) {
				*ptr=0;
				strcpy(rexx_pathbuffer[win],rexx_args[argnum]);
				TackOn(rexx_pathbuffer[win],NULL,256);
			}
			else rexx_pathbuffer[win][argnum]=0;
			dos_global_entry.last=dos_global_entry.next=NULL;
			dos_global_entry.type=a;
			dos_global_entry.size=b;
			func_single_entry=&dos_global_entry;
			removeargstring(argnum);
			return(rexx_pathbuffer[win]);
		}
		else {
			strcpy(rexx_pathbuffer[win],rexx_args[argnum]);
			TackOn(rexx_pathbuffer[win],NULL,256);
			removeargstring(argnum);
			return(rexx_pathbuffer[win]);
		}
	}
	return(str_pathbuffer[win]);
}

readfile(name,buf,size)
char *name,**buf;
int *size;
{
	int in,loadpp=0;

	if (PPBase) {
		if ((in=ppLoadData(name,DECR_POINTER,MEMF_CLEAR,buf,size,NULL))) {
			if (in==-1 || in==-2) return(-1);
			if (in==-3) return(-2);
		}
		else loadpp=1;
	}
	if (!loadpp) {
		if (CheckExist(name,size)>=0 || !(in=Open(name,MODE_OLDFILE))) return(-1);
		if (!(*buf=AllocMem(*size,MEMF_CLEAR))) {
			Close(in);
			return(-2);
		}
		Read(in,*buf,*size);
		Close(in);
	}
	return(0);
}

getnewprot(old,new,mask)
int old,new,mask;
{
	int val,a;

	if (!mask) return(new);
	val=old&(~255);
	for (a=0;a<8;a++) {
		if (mask&(1<<a)) {
			if (old&(1<<a)) val|=(1<<a);
		}
		else if (new&(1<<a)) val|=(1<<a);
	}
	return(val);
}

dateformat(flag)
int flag;
{
	int a;

	for (a=0;a<4;a++) {
		if (flag&(1<<a)) return(a);
	}
	return(a);
}

void dosound(type)
int type;
{
	struct IOAudio audio;
	static UBYTE achannels[8]={3,5,10,12,1,2,4,8};
	int a;

	if (type==0 && system_version2>=OSVER_38) DisplayBeep(NULL);
	else {
		audio.ioa_Request.io_Message.mn_ReplyPort=general_port;
		audio.ioa_Request.io_Message.mn_Node.ln_Pri=90;
		audio.ioa_Data=achannels;
		audio.ioa_Length=sizeof(achannels);
		if (!(a=OpenDevice("audio.device",0,(struct IORequest *)&audio,0))) {
			audio.ioa_Request.io_Command=CMD_WRITE;
			audio.ioa_Request.io_Flags=ADIOF_PERVOL;
			audio.ioa_Volume=64;
			audio.ioa_Data=(UBYTE *)beepwave;
			audio.ioa_Length=8;
			switch (type) {
				case 0:
					audio.ioa_Period=500;
					audio.ioa_Cycles=100;
					BeginIO((struct IORequest *)&audio);
					WaitIO((struct IORequest *)&audio);
					break;
				case 1:
					audio.ioa_Cycles=60;
					for (a=0;a<5;a++) {
						audio.ioa_Period=800;
						BeginIO((struct IORequest *)&audio);
						WaitIO((struct IORequest *)&audio);
						audio.ioa_Period=1200;
						BeginIO((struct IORequest *)&audio);
						WaitIO((struct IORequest *)&audio);
					}
					audio.ioa_Period=800;
					BeginIO((struct IORequest *)&audio);
					WaitIO((struct IORequest *)&audio);
					break;
			}
			CloseDevice((struct IORequest *)&audio);
		}
	}
}

checkscreenmode(mode)
int mode;
{
	DisplayInfoHandle *handle;
	struct DimensionInfo *dimension;
	char buf[256];
	int flags,minw,defw;

	if (mode==MODE_WORKBENCHUSE || mode==MODE_WORKBENCHCLONE || mode==MODE_PUBLICSCREEN)
		return(mode);
	if (!system_version2) {
		if (mode==HIRES_KEY || mode==HIRESLACE_KEY) return(mode);
		return(MODE_WORKBENCHCLONE);
	}
	if (!(handle=FindDisplayInfo(mode)) ||
		!(GetDisplayInfoData(handle,buf,256,DTAG_DISP,0)) ||
		((struct DisplayInfo *)buf)->NotAvailable)
		return(MODE_WORKBENCHCLONE);
	flags=((struct DisplayInfo *)buf)->PropertyFlags;
	if (flags&DIPF_IS_DUALPF || flags&DIPF_IS_PF2PRI || flags&DIPF_IS_HAM ||
		!(GetDisplayInfoData(handle,buf,256,DTAG_DIMS,0)))
		return(MODE_WORKBENCHCLONE);
	dimension=(struct DimensionInfo *)buf;
	if (mode&HIRES_KEY || mode&HIRESLACE_KEY) minw=640;
	else {
		minw=dimension->MinRasterWidth;
		if (minw<160) minw*=10;
	}
	defw=(dimension->TxtOScan.MaxX-dimension->TxtOScan.MinX)+1;
	if (minw<640 || defw<640 && dimension->MaxDepth>=5)
		return(MODE_WORKBENCHCLONE);
	return(mode);
}

void doarrowgadgets(gad,dir)
struct Gadget *gad;
int dir;
{
	int a;

	for (a=0;a<2;a++) {
		if (!gad) break;
		do3dbox(main_rp,
			gad->LeftEdge+2,
			gad->TopEdge+1,
			gad->Width-4,
			gad->Height-2);
		DoArrow(main_rp,
			gad->LeftEdge+2,
			gad->TopEdge+1,
			gad->Width-4,
			gad->Height-2,
			screen_pens[config->arrowfg].pen,
			screen_pens[config->arrowbg].pen,dir);
		gad=gad->NextGadget;
	}
}

void makermbgad(rmbgad,gad,high)
struct RMBGadget *rmbgad;
struct Gadget *gad;
int high;
{
	rmbgad->x=gad->LeftEdge;
	rmbgad->y=gad->TopEdge;
	rmbgad->w=gad->Width;
	rmbgad->h=gad->Height;
	if (high && gad->GadgetRender) {
		rmbgad->flags|=RGF_ALTBORD;
		rmbgad->high_bord[0]=gad->GadgetRender;
		rmbgad->high_bord[1]=gad->SelectRender;
	}
	else rmbgad->flags&=~RGF_ALTBORD;
}

void dolittlegads(gad,txt,num)
struct Gadget *gad;
char *txt;
int num;
{
	int a,y;
	struct TextFont *font;

	if (status_iconified || !Window) return;

	font=main_rp->Font;
	SetFont(main_rp,scr_font[FONT_GENERAL]);
	for (a=0;a<num;a++) {
		do3dbox(main_rp,gad->LeftEdge+2,gad->TopEdge+1,gad->Width-4,gad->Height-2);
		SetAPen(main_rp,screen_pens[config->littlegadbg].pen);
		rectfill(main_rp,gad->LeftEdge+2,gad->TopEdge+1,gad->Width-4,gad->Height-2);
		SetAPen(main_rp,screen_pens[config->littlegadfg].pen);
		SetBPen(main_rp,screen_pens[config->littlegadbg].pen);
		y=gad->TopEdge+1+(((gad->Height-2)-scr_font[FONT_GENERAL]->tf_YSize)/2);
		if (y<gad->TopEdge+1) y=gad->TopEdge+1;
		y+=scr_font[FONT_GENERAL]->tf_Baseline;
		Move(main_rp,gad->LeftEdge+((gad->Width-scr_font[FONT_GENERAL]->tf_XSize)/2),y);
		Text(main_rp,&txt[a],1);
		RefreshGList(gad,Window,NULL,1);
		if (!(gad=gad->NextGadget)) break;
	}
	SetFont(main_rp,font);
}

void rectfill(r,x,y,w,h)
struct RastPort *r;
int x,y,w,h;
{
	if (w<0 || h<0) return;
	RectFill(r,x,y,x+w-1,y+h-1);
}

isinwindow(x,y)
int x,y;
{
	int win;

	for (win=0;win<2;win++) {
		if (x>=scrdata_dirwin_xpos[win] && x<scrdata_dirwin_xpos[win]+scrdata_dirwin_width[win] &&
			y>=scrdata_dirwin_ypos[win] && y<scrdata_dirwin_height+scrdata_dirwin_ypos[win]) return(win);
	}
	return(-1);
}

isvalidwindow(win)
int win;
{
	if (!str_pathbuffer[win]) return(0);
	if (dopus_curwin[win]->total>0 && dopus_curwin[win]->firstentry->type==ENTRY_CUSTOM)
		return(0);
	return(1);
}
