/**	Filreq.c
  *
  *	Implement the File Requester functions for rexxarplib.library.
  *
  *   AUTHOR/DATE:  W.G.J. Langeveld, November 1987.
  *   ============
  *
  *	CURRENT VERSION:
  *
  *	This version has been converted to SAS C 6.5 format. It has been modified
  *	for modern definition sequences for ANSI compilation. This no longer works
  *	with OS versions prior to 2.04.
  *
  *	This module supports a major modification. All the large objects formerly
  * allocated on the stack are not allocated as a member of a local group of
  *	variables using mymalloc and myfree. This stops a stack crash which
  *	occured on machines running Picasso 96, and probably other RTG tools.
  *
  * Latest change is to fix so it compiles with 3.9 NDK.
  *
  *   AUTHOR/DATE:  Joanne Dow, jdow@bix.com, June 1998.
  *   AUTHOR/DATE:  Joanne Dow, jdow@bix.com, 23 Apr 2002.
  *   ============
  *
  **/

#include <functions.h>
#include "ralprotos.h"
#include <intuition/intuitionbase.h>
#include <graphics/gfx.h>
#include <workbench/workbench.h>
#include <workbench/startup.h>
#include <workbench/icon.h>
#include <libraries/MyARP.h>
#include <proto/rexxsyslib.h>
#include <clib/alib_protos.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "rexxarplib.h"

extern struct ArpBase       *ArpBase;
	
/**
 *
 *   This function is called by the file requester before opening the
 *   requester window. It is currently used to allow opening up on a
 *   custom screen and to move the x, y position.
 *
 **/
static int curx, cury;
	
void frfunction( ULONG flag, struct NewWindow *nw )
{
	if (flag & FRF_NewWindFunc) 
	{
		nw->LeftEdge = curx;
		nw->TopEdge  = cury;
	}
	return;
}

/**
 *
 *   File requester.
 *
**/
char *rxf_getfile( long *err, int n, char *s[] )
{
	struct Rxfg1
	{
		char			buffer[LONG_FSIZE + LONG_DSIZE + 2],
						hail[80],
						fil[LONG_FSIZE + 1],
						dir[LONG_DSIZE + 1],
						patt[LONG_DSIZE + 1],
						stembuff[256];
		struct TagItem	tags[12];
	} *rxfg = NULL;

	char *resval;
	struct ARPFileRequester freq;
	struct FileRequester *afreq = NULL;
	BYTE *result;
	struct Window *pixelw = NULL;
	int x = 0, y = 0, width = -1, height = -1;
	long filfs = 0L, fil1fs = 0L;
	int tagend, nfiles, i, aslflag = 1;
	char *stemname = NULL;
	struct RexxMsg *rmptr = (struct RexxMsg *) s;
	char **args = &rmptr->rm_Args[1];
	BPTR lock, oldlock;
	struct ViewPort *vp;
	struct Screen *ps;
	struct NewWindow pixelnw;
	

	rxfg = mymalloc( sizeof ( struct Rxfg1 ) );
	if (rxfg == NULL)
		return( NULL );

	setmem(&pixelnw, sizeof(struct NewWindow), 0);
	pixelnw.Width = pixelnw.Height = pixelnw.MaxWidth = pixelnw.MaxHeight = 1;
	pixelnw.Type = CUSTOMSCREEN;
	pixelnw.Flags = BORDERLESS;
	
	
	*err = 0L;
	
	if (n >= 1 && args[0])
		x = atoi(args[0]);
	if (n >= 2 && args[1])
		y = atoi(args[1]);
	if (n >= 3 && args[2])
		strncpy( rxfg->dir,  args[2], LONG_DSIZE + 1);
	if (n >= 4 && args[3])
		strncpy( rxfg->fil,  args[3], LONG_FSIZE + 1);
	if (n >= 5 && args[4])
		strncpy( rxfg->hail, args[4], 80);
	
	ps = NULL;
	if (n >= 6 && args[5]) 
	{
		ps = LockScreen(args[5]);
		if (ps) 
		{
			pixelnw.Screen = ps;
			pixelw = OpenWindow(&pixelnw);
			if (pixelw) 
			{
				if (vp = ViewPortAddress(pixelw)) 
				{
					x -= vp->DxOffset;
					y -= vp->DyOffset;
				}
			}
		}
	}
	filfs = FILF_NEWIDCMP;
	if (n >= 7 && args[6]) 
	{
		if (strstr(args[6], "NOFILES"))
			fil1fs |= FIL1F_NOFILES;
		if (strstr(args[6], "MATCHDIRS"))
			fil1fs |= FIL1F_MATCHDIRS;
		if (strstr(args[6], "PATGAD"))
			filfs  |= FILF_PATGAD;
		if (strstr(args[6], "SAVE"))
			filfs  |= FILF_SAVE;
		if (strstr(args[6], "MULTISELECT"))
			filfs  |= FILF_MULTISELECT;
		if (strstr(args[6], "DOARP"))
			aslflag = 0;
	}
	if (n >= 8 && args[7]) 
	{
		stemname = args[7];
	}
	else
	{
		filfs &= ~FILF_MULTISELECT;
	}
	if (n >= 9 && args[8]) 
	{
		width  = atoi(args[8]);
		if ((width < 300) || (width > 1024))
			width = -1;
	}
	if (n >= 10 && args[9]) 
	{
		height = atoi(args[9]);
		if ((height < 100) || (height > 1024))
			height = -1;
	}
	if (n >= 11 && args[10]) 
	{
		if (filfs & FILF_PATGAD)
			strncpy( rxfg->patt, args[10], LONG_DSIZE + 1);
	}
	
	if (aslflag) 
	{
		rxfg->tags[0].ti_Tag = ASL_Hail;      rxfg->tags[0].ti_Data = (ULONG) rxfg->hail;
		rxfg->tags[1].ti_Tag = ASL_Window;    rxfg->tags[1].ti_Data = (ULONG) pixelw;
		rxfg->tags[2].ti_Tag = ASL_LeftEdge;  rxfg->tags[2].ti_Data = (ULONG) x;
		rxfg->tags[3].ti_Tag = ASL_TopEdge;   rxfg->tags[3].ti_Data = (ULONG) y;
		rxfg->tags[4].ti_Tag = ASL_File;      rxfg->tags[4].ti_Data = (ULONG) rxfg->fil;
		rxfg->tags[5].ti_Tag = ASL_Dir;       rxfg->tags[5].ti_Data = (ULONG) rxfg->dir;
		rxfg->tags[6].ti_Tag = ASL_FuncFlags; rxfg->tags[6].ti_Data = (ULONG) filfs;
		rxfg->tags[7].ti_Tag = ASL_ExtFlags1; rxfg->tags[7].ti_Data = (ULONG) fil1fs;
		tagend = 8;
		if (width != -1) 
		{
			rxfg->tags[tagend].ti_Tag  = ASL_Width;
			rxfg->tags[tagend].ti_Data = (ULONG) width;
			tagend++;
		}
		if (height != -1) 
		{
			rxfg->tags[tagend].ti_Tag  = ASL_Height;
			rxfg->tags[tagend].ti_Data = (ULONG) height;
			tagend++;
		}
		if (filfs & FILF_PATGAD) 
		{
			rxfg->tags[tagend].ti_Tag  = ASL_Pattern;
			rxfg->tags[tagend].ti_Data = (ULONG) rxfg->patt;
			tagend++;
		}
		rxfg->tags[tagend].ti_Tag = TAG_END;  rxfg->tags[tagend].ti_Data = (ULONG) 0L;
		
		afreq = (struct FileRequester *) AllocAslRequest(ASL_FileRequest, rxfg->tags);
		
		if (afreq) 
		{
			result = (char *) AslRequest(afreq, TAG_END);
			
			if (result) 
			{
				if (stemname) 
				{
					MakeStemS( rxfg->stembuff, stemname, "WIDTH");
					ltoa( rxfg->buffer, (LONG) afreq->rf_Width);
					SetRexxVar( rmptr, rxfg->stembuff, rxfg->buffer, (long) strlen( rxfg->buffer));
					MakeStemS( rxfg->stembuff, stemname, "HEIGHT");
					ltoa( rxfg->buffer, (LONG) afreq->rf_Height);
					SetRexxVar( rmptr, rxfg->stembuff, rxfg->buffer, (long) strlen( rxfg->buffer));
					MakeStemS( rxfg->stembuff, stemname, "TOPEDGE");
					ltoa( rxfg->buffer, (LONG) afreq->rf_TopEdge);
					SetRexxVar( rmptr, rxfg->stembuff, rxfg->buffer, (long) strlen( rxfg->buffer));
					MakeStemS( rxfg->stembuff, stemname, "LEFTEDGE");
					ltoa( rxfg->buffer, (LONG) afreq->rf_LeftEdge);
					SetRexxVar( rmptr, rxfg->stembuff, rxfg->buffer, (long) strlen( rxfg->buffer));
					if ( rxfg->patt[0]) 
					{
						MakeStemS( rxfg->stembuff, stemname, "PATTERN");
						strncpy( rxfg->buffer, afreq->rf_Pat, LONG_DSIZE + 1);
						SetRexxVar( rmptr, rxfg->stembuff,  rxfg->buffer, (long) strlen( rxfg->buffer));
					}
				}
				
				if (stemname && (filfs & FILF_MULTISELECT)) 
				{
					nfiles = afreq->rf_NumArgs;
					for (i = 0; i < nfiles; i++) 
					{
						oldlock = CurrentDir(afreq->rf_ArgList[i].wa_Lock);
						if (oldlock) 
						{
							lock = Lock(afreq->rf_ArgList[i].wa_Name, ACCESS_READ);
							if (lock) 
							{
								NameFromLock(lock, rxfg->buffer, 256L);
								UnLock(lock);
							}
							CurrentDir(oldlock);
						}
						
						MakeStem( rxfg->stembuff, stemname, i + 1);
						SetRexxVar( rmptr, rxfg->stembuff, rxfg->buffer, (long) strlen( rxfg->buffer));
					}
					ltoa( rxfg->buffer, (LONG) nfiles);
					MakeStem( rxfg->stembuff, stemname, 0);
					SetRexxVar( rmptr, rxfg->stembuff, rxfg->buffer, (long) strlen( rxfg->buffer));
				}
				else
				{
					strncpy( rxfg->dir, afreq->rf_Dir, LONG_DSIZE + 1);
					strncpy( rxfg->fil, afreq->rf_File, LONG_FSIZE + 1);
					MakFilNam( rxfg->buffer, rxfg->dir, rxfg->fil);
					
					if (stemname) 
					{
						MakeStem( rxfg->stembuff, stemname, 1L);
						SetRexxVar( rmptr, rxfg->stembuff, rxfg->buffer, (long) strlen( rxfg->buffer));
						ltoa( rxfg->buffer, 1L);
						MakeStem( rxfg->stembuff, stemname, 0);
						SetRexxVar( rmptr, rxfg->stembuff, rxfg->buffer, (long) strlen( rxfg->buffer));
					}
				}
			}
			else
			if (stemname) 
			{
				ltoa( rxfg->buffer, 0L);
				MakeStem( rxfg->stembuff, stemname, 0L);
				SetRexxVar( rmptr, rxfg->stembuff, rxfg->buffer, (long) strlen( rxfg->buffer));
				rxfg->buffer[0] = '\0';
			}
			FreeAslRequest(afreq);
		}
	}
	else
	{
		curx = x;
		cury = y;
		
		freq.fr_Hail      = rxfg->hail;
		freq.fr_File      = rxfg->fil;
		freq.fr_Dir       = rxfg->dir;
		freq.fr_Window    = pixelw;
		freq.fr_FuncFlags = FRF_NewWindFunc;
		freq.fr_Flags2    = FR2F_LongPath;
		freq.fr_Function  = frfunction;
		freq.fr_TopEdge   = 0;
		freq.fr_LeftEdge  = 0;
		
		result = ARPFileRequest(&freq);
		if (result)
			MakFilNam( rxfg->buffer, rxfg->dir, rxfg->fil);
	}
	
	resval = CAS( rxfg->buffer);
	
	if (pixelw)
		CloseWindow(pixelw);
	if (ps)
		UnlockScreen(args[5], ps);

	myfree ( rxfg );
	
	return(resval);
}

/**
 *
 *   Routine to combine directory and file name into one.
 *
**/
void MakFilNam(str, dir, fil)
	char *str, *dir, *fil;
{
	int dirlen;
	
	dirlen = strlen(dir);
	
	if (dirlen == 0) 
	{
		strcpy(str, fil);
	}
	else
	{
		strcpy(str, dir);
		if (dir[dirlen-1] != ':')
			strcat(str,"/");
		strcat(str, fil);
	}
	return;
}


/**
 *
 *   Get a file name given some defaults.
 *
**/
char *rxf_getfont( long *err, int n, char *s[] )
{
	struct Rxfg2
	{
		char	buffer[256],
				hail[80],
				font[LONG_FSIZE + 10],
				stembuff[256];
		struct TagItem tags[16];
	} *rxfg = NULL;

	struct FontRequester *afreq = NULL;
	char *result;
	struct ViewPort *vp;
	struct Window *pixelw = NULL;
	int x = 0, y = 0;
	int minpts = -1, maxpts = -1;
	int style = -1, flags = -1, frontpen = -1, backpen = -1;
	int fontsize = -1, tagend;
	long fonfs = 0L;
	struct RexxMsg *rmptr = (struct RexxMsg *) s;
	char **args = &rmptr->rm_Args[1];
	char *stemname = NULL;
	struct Screen *ps = NULL;
	struct NewWindow pixelnw;
	
	rxfg = mymalloc( sizeof ( struct Rxfg2 ) );
	if (rxfg == NULL)
		return( NULL );

	setmem(&pixelnw, sizeof(struct NewWindow), 0);
	pixelnw.Width = pixelnw.Height = pixelnw.MaxWidth = pixelnw.MaxHeight = 1;
	pixelnw.Type = CUSTOMSCREEN;
	pixelnw.Flags = BORDERLESS;
	
	*err = 0L;
	
	if (n >= 1 && args[0])
		x = atoi(args[0]);
	if (n >= 2 && args[1])
		y = atoi(args[1]);
	if (n >= 3 && args[2])
		strncpy( rxfg->font, args[2], LONG_FSIZE + 1);
	if (n >= 4 && args[3])
		fontsize = atoi(args[3]);
	if (n >= 5 && args[4])
		strncpy( rxfg->hail, args[4], 80);
	
	if (n >= 6 && args[5]) 
	{
		ps = LockScreen(args[5]);
		if (ps) 
		{
			pixelnw.Screen = ps;
			pixelw = OpenWindow(&pixelnw);
			if (pixelw) 
			{
				if (vp = ViewPortAddress(pixelw)) 
				{
					x -= vp->DxOffset;
					y -= vp->DyOffset;
				}
			}
		}
	}
	fonfs = FONF_NEWIDCMP;
	if (n >= 7 && args[6]) 
	{
		if (strstr(args[6], "FIXEDWIDTH"))
			fonfs |= FONF_FIXEDWIDTH;
		if (strstr(args[6], "FRONTPEN"))
			fonfs |= FONF_FRONTCOLOR;
		if (strstr(args[6], "BACKPEN"))
			fonfs |= FONF_BACKCOLOR;
		if (strstr(args[6], "STYLE"))
			fonfs |= FONF_STYLES;
		if (strstr(args[6], "DRAWMODE"))
			fonfs |= FONF_DRAWMODE;
	}
	if (n >= 8  && args[7])
		stemname = args[7];
	if (n >= 9  && args[8])
		minpts   = atoi(args[8]);
	if (n >= 10 && args[9])
		maxpts   = atoi(args[9]);
	if (n >= 11 && args[10])
		style    = atoi(args[10]);
	if (n >= 12 && args[11])
		flags    = atoi(args[11]);
	if (n >= 13 && args[12])
		frontpen = atoi(args[12]);
	if (n >= 14 && args[13])
		backpen  = atoi(args[13]);
	
	rxfg->tags[0].ti_Tag = ASL_Hail;       rxfg->tags[0].ti_Data = (ULONG) rxfg->hail;
	rxfg->tags[1].ti_Tag = ASL_Window;     rxfg->tags[1].ti_Data = (ULONG) pixelw;
	rxfg->tags[2].ti_Tag = ASL_LeftEdge;   rxfg->tags[2].ti_Data = (ULONG) x;
	rxfg->tags[3].ti_Tag = ASL_TopEdge;    rxfg->tags[3].ti_Data = (ULONG) y;
	rxfg->tags[4].ti_Tag = ASL_FuncFlags;  rxfg->tags[4].ti_Data = (ULONG) fonfs;
	rxfg->tags[5].ti_Tag = ASL_FontName;   rxfg->tags[5].ti_Data = (ULONG) rxfg->font;
	tagend = 6;
	if (fontsize != -1) 
	{
		rxfg->tags[tagend].ti_Tag = ASL_FontHeight;
		rxfg->tags[tagend].ti_Data = (ULONG) fontsize;
		tagend++;
	}
	if (minpts != -1) 
	{
		rxfg->tags[tagend].ti_Tag = ASL_MinHeight;
		rxfg->tags[tagend].ti_Data = (ULONG) minpts;
		tagend++;
	}
	if (maxpts != -1) 
	{
		rxfg->tags[tagend].ti_Tag = ASL_MaxHeight;
		rxfg->tags[tagend].ti_Data = (ULONG) maxpts;
		tagend++;
	}
	if (style != -1) 
	{
		rxfg->tags[tagend].ti_Tag = ASL_FontStyles;
		rxfg->tags[tagend].ti_Data = (ULONG) style;
		tagend++;
	}
	if (flags != -1) 
	{
		rxfg->tags[tagend].ti_Tag = ASL_FontFlags;
		rxfg->tags[tagend].ti_Data = (ULONG) flags;
		tagend++;
	}
	if (frontpen != -1) 
	{
		rxfg->tags[tagend].ti_Tag = ASL_FrontPen;
		rxfg->tags[tagend].ti_Data = (ULONG) frontpen;
		tagend++;
	}
	if (backpen != -1) 
	{
		rxfg->tags[tagend].ti_Tag = ASL_BackPen;
		rxfg->tags[tagend].ti_Data = (ULONG) backpen;
		tagend++;
	}
	rxfg->tags[tagend].ti_Tag = TAG_END;  rxfg->tags[tagend].ti_Data = (ULONG) 0L;
	
	afreq = (struct FontRequester *) AllocAslRequest(ASL_FontRequest, rxfg->tags);
	
	if (afreq) 
	{
		result = (char *) AslRequest(afreq, TAG_END);
		if (result) 
		{
			strncpy( rxfg->font, afreq->fo_Attr.ta_Name, LONG_FSIZE + 1);
			fontsize = afreq->fo_Attr.ta_YSize;
			if (stemname) 
			{
				MakeStemS( rxfg->stembuff, stemname, "NAME");
				SetRexxVar( rmptr, rxfg->stembuff, rxfg->font, (long) strlen( rxfg->font));
				
				MakeStemS( rxfg->stembuff, stemname, "YSIZE");
				ltoa( rxfg->buffer, (LONG) fontsize);
				SetRexxVar( rmptr, rxfg->stembuff, rxfg->buffer, (long) strlen( rxfg->buffer));
				
				MakeStemS( rxfg->stembuff, stemname, "STYLE");
				ltoa( rxfg->buffer, (LONG) afreq->fo_Attr.ta_Style);
				SetRexxVar( rmptr, rxfg->stembuff, rxfg->buffer, (long) strlen( rxfg->buffer));
				
				MakeStemS( rxfg->stembuff, stemname, "FLAGS");
				ltoa( rxfg->buffer, (LONG) afreq->fo_Attr.ta_Flags);
				SetRexxVar( rmptr, rxfg->stembuff, rxfg->buffer, (long) strlen( rxfg->buffer));
				
				MakeStemS( rxfg->stembuff, stemname, "FRONTPEN");
				ltoa( rxfg->buffer, (LONG) afreq->fo_FrontPen);
				SetRexxVar( rmptr, rxfg->stembuff, rxfg->buffer, (long) strlen( rxfg->buffer));
				
				MakeStemS( rxfg->stembuff, stemname, "BACKPEN");
				ltoa( rxfg->buffer, (LONG) afreq->fo_BackPen);
				SetRexxVar( rmptr, rxfg->stembuff, rxfg->buffer, (long) strlen( rxfg->buffer));
				
				MakeStemS( rxfg->stembuff, stemname, "DRAWMODE");
				switch (afreq->fo_DrawMode) 
				{
				case 0 :
					strcpy( rxfg->buffer, "JAM1");
					break;
				case 1 :
					strcpy( rxfg->buffer, "JAM2");
					break;
				case 2 :
					strcpy( rxfg->buffer, "COMPLEMENT");
					break;
				default:
					strcpy( rxfg->buffer, "JAM1");
					break;
				}
				SetRexxVar( rmptr, rxfg->stembuff, rxfg->buffer, (long) strlen( rxfg->buffer));
			}
			else
			{
				strcat( rxfg->font, "/");
				ltoa( rxfg->buffer, (long) fontsize);
				strcat( rxfg->font, rxfg->buffer);
			}
		}
		else
		{
			rxfg->font[0] = '\0';
		}
		FreeAslRequest(afreq);
	}
	else
	{
		rxfg->font[0] = '\0';
	}
	
	if (pixelw)
		CloseWindow(pixelw);
	if (ps)
		UnlockScreen(args[5], ps);
	
	myfree ( rxfg );

	return(CAS( rxfg->font));
}

