
/*
 * MISC.C
 * (c) 1992-3 J.Harper
 */

#include "jed.h"
#include "jed_protos.h"

Prototype   STRPTR	stpblk		(STRPTR);
Prototype   LONG	spclen		(STRPTR);
Prototype   STRPTR	stpalnum	(STRPTR);
Prototype   STRPTR	nextdigit	(STRPTR);
Prototype   STRPTR	cpyalnum	(STRPTR, STRPTR);
Prototype   STRPTR	cpynotspc	(STRPTR, STRPTR);
Prototype   STRPTR	savestring	(STRPTR);
Prototype   STRPTR	savestringn	(STRPTR, LONG);
Prototype   STRPTR	squirrelfile	(STRPTR);
Prototype   UBYTE	escchar		(STRPTR *);
Prototype   VOID	NewList		(struct List *list);
Prototype   VALUE *	cmd_format	(LONG, VALUE *);
Prototype   VALUE *	cmd_system	(LONG, VALUE *);
Prototype   VALUE *	cmd_match	(LONG, VALUE *);
Prototype   VOID	killfilereq	(VOID);
Prototype   VALUE *	cmd_freq	(LONG, VALUE *);
Prototype   VALUE *	cmd_atol	(LONG, VALUE *);
Prototype   VALUE *	cmd_substr	(LONG, VALUE *);
Prototype   VALUE *	cmd_car		(LONG, VALUE *);
Prototype   VALUE *	cmd_cdr		(LONG, VALUE *);

STRPTR
stpblk(STRPTR str)
{
    while(*str && isspace(*str))
	str++;
    return(str);
}

LONG
spclen(STRPTR string)
{
    STRPTR str = string;
    while(*str && isspace(*str))
	str++;
    return((LONG)(str - string));
}

STRPTR
stpalnum(STRPTR str)
{
    while(*str && isalnum(*str))
	str++;
    return(str);
}

STRPTR
nextdigit(STRPTR str)
{
    while(*str && !isdigit(*str))
	str++;
    return(str);
}

STRPTR
cpyalnum(STRPTR dest, STRPTR src)
{
    while(*src && isalnum(*src))
	*dest++ = *src++;
    *dest++ = 0;
    return(dest);
}

/*
 * returns the char after the last one copied.
 */
STRPTR
cpynotspc(STRPTR dest, STRPTR src)
{
    while(*src && (!isspace(*src)))
	*dest++ = *src++;
    *dest++ = 0;
    return(src);
}

STRPTR
savestring(STRPTR str)
{
    LONG len = strlen(str);
    STRPTR saved = AllocVec(len + 1, 0L);
    if(saved)
    {
	memcpy(saved, str, len);
	saved[len] = 0;
    }
    return(saved);
}

/*
 * len doesn't include the zero terminator
 * use the freestring() macro to unalloc this.
 */
STRPTR
savestringn(STRPTR str, LONG len)
{
    STRPTR saved = AllocVec(len + 1, 0L);
    if(saved)
    {
	memcpy(saved, str, len);
	saved[len] = 0;
    }
    return(saved);
}

/*
 * use the freestring() macro to release the mem.
 */
STRPTR
squirrelfile(STRPTR fileName)
{
    BPTR fh = Open(fileName, MODE_OLDFILE);
    if(fh)
    {
	ULONG length;
	STRPTR mem;
	Seek(fh, 0, OFFSET_END);
	length = Seek(fh, 0, OFFSET_BEGINNING);

	if(mem = AllocVec(length + 1, 0L))
	{
	    Read(fh, mem, length);
	    mem[length] = 0;
	    Close(fh);
	    return(mem);
	}
	else
	    settitle(NoMemMsg);
	Close(fh);
    }
    return(FALSE);
}

/*
 * returns the byte to replace an escape sequence with,
 * str_p is advanced past the last used char
 *
 * supported,
 *  \n
 *  \r
 *  \f
 *  \t
 *  \0Octal
 *  \0xHex
 *  \Decimal
 *
 * anything else is just copied (ie, '\\' equals '\')
 */
UBYTE
escchar(STRPTR *str_p)
{
    STRPTR str = *str_p;
    UBYTE c = *str++;

    switch(c)
    {
	case 'n':
	    c = '\n';
	    break;
	case 'r':
	    c = '\r';
	    break;
	case 'f':
	    c = '\f';
	    break;
	case 't':
	    c = '\t';
	    break;
	default:
	    if(isdigit(c))
	    {
		c = (UBYTE)strtol(str - 1, str_p, 0);
		str = *str_p;
	    }
	    break;
    }
    *str_p = str;
    return(c);
}

VOID
NewList(struct List *list)
{
    list->lh_Head = (struct Node *)&list->lh_Tail;
    list->lh_Tail = NULL;
    list->lh_TailPred = (struct Node *)&list->lh_Head;
}

/*
 * (format `fmtString' args...)
 */
VALUE *
cmd_format(LONG argc, VALUE *argv)
{
    if(TPLATE1(VTF_STRING))
    {
	UBYTE fmtbuff[256];
	LONG i, args[20];
	STRPTR str;
	for(i = 0; (i < (argc - 1)) && (i < 20); i++)
	    args[i] = argv[i + 2].val_Value.Number;
	vsprintf(fmtbuff, ARG1.val_Value.String, args);
	if(str = savestring(fmtbuff))
	{
	    setstrres(str);
	}
    }
    return(&RES);
}

/*
 * (system `AmigaDOS command string')
 */
VALUE *
cmd_system(LONG argc, VALUE *argv)
{
    if(TPLATE1(VTF_STRING))
    {
	setnumres(SystemTags(ARG1.val_Value.String,
	    NP_ConsoleTask, NULL,   /* I hope a NULL pr_ConsoleTask is OK */
	    TAG_END));
    }
    return(&RES);
}

/*
 * (match `wildString' `matchString')
 */
VALUE *
cmd_match(LONG argc, VALUE *argv)
{
    if(TPLATE2(VTF_STRING, VTF_STRING))
    {
	STRPTR parsed;
	LONG bufflen = ((strlen(ARG1.val_Value.String)) << 1) + 2;
	if(parsed = AllocVec(bufflen, 0L))
	{
	    if(ParsePatternNoCase(ARG1.val_Value.String, parsed, bufflen) >= 0)
	    {
		setnumres(MatchPatternNoCase(parsed, ARG2.val_Value.String));
	    }
	    else
		settitle("error: pattern won't parse");
	    FreeVec(parsed);
	}
	else
	    settitle(NoMemMsg);
    }
    return(&RES);
}

/*
 * File req stuff.
 * I don't like the ASL requester but I couldn't be bothered to make the DICE
 * libraries for reqtools.library. Use the RTpatch prog to get nice (fast)
 * requesters.
 */
	APTR		      AslBase;
Local	struct FileRequester *FileReq;

VOID
killfilereq(VOID)
{
    if(FileReq)
    {
	FreeAslRequest(FileReq);
	FileReq = NULL;
    }
    if(AslBase)
    {
	CloseLibrary(AslBase);
	AslBase = NULL;
    }
}

/*
 * (freq `r|w' `title' `file')  r|w means read|write
 */
VALUE *
cmd_freq(LONG argc, VALUE *argv)
{
    if(TPLATE3(VTF_STRING, VTF_STRING, VTF_STRING))
    {
	if(AslBase || (AslBase = OpenLibrary("asl.library", 36)))
	{
	    if(FileReq || (FileReq = AllocAslRequestTags(ASL_FileRequest, TAG_DONE)))
	    {
		WORD flags = 0;
		STRPTR dircopy;

		if(toupper(*(ARG1.val_Value.String)) == 'W')
		     flags |= FILF_SAVE;

		if(dircopy = savestring(ARG3.val_Value.String))
		{
		    STRPTR actualfile = FilePart(ARG3.val_Value.String);
		    dircopy[actualfile - ARG3.val_Value.String] = 0;

		    if(AslRequestTags(FileReq,
			ASL_Hail, ARG2.val_Value.String,
			ASL_Window, CurrVW->vw_Window,
			ASL_File, actualfile,
			ASL_Dir, dircopy,
			ASL_FuncFlags, flags,
			TAG_END))
		    {
			STRPTR selected;
			LONG sellen = strlen(FileReq->rf_File) + strlen(FileReq->rf_Dir) + 2;
			if(selected = AllocVec(sellen, 0L))
			{
			    strcpy(selected, FileReq->rf_Dir);
			    AddPart(selected, FileReq->rf_File, sellen);
			    setstrres(selected);
			}
			else
			    settitle(NoMemMsg);
		    }
		    freestring(dircopy);
		}
		else
		    settitle(NoMemMsg);
	    }
	    else
		settitle("error: can't allocate requester");
	}
	else
	    settitle("need asl.library");
    }
    return(&RES);
}

/*
 * (atol `number-string')
 */
VALUE *
cmd_atol(LONG argc, VALUE *argv)
{
    if(TPLATE1(VTF_STRING))
    {
	APTR dummy;
	setnumres(strtol(ARG1.val_Value.String, &dummy, 0));
    }
    return(&RES);
}

/*
 * (substr `str' start length)
 */
VALUE *
cmd_substr(LONG argc, VALUE *argv)
{
    if(TPLATE3(VTF_STRING, VTF_NUMBER, VTF_NUMBER))
    {
	STRPTR ext;
	if(ext = savestringn(ARG1.val_Value.String + ARG2.val_Value.Number, ARG3.val_Value.Number))
	{
	    setstrres(ext);
	}
	else
	    settitle(NoMemMsg);
    }
    return(&RES);
}

/*
 * (car `str' ~sep-char)
 */
VALUE *
cmd_car(LONG argc, VALUE *argv)
{
    if(TPLATE2(VTF_STRING, VTF_NUMBER))
    {
	STRPTR str = ARG1.val_Value.String;
	UBYTE sep = (UBYTE)ARG2.val_Value.Number;
	STRPTR rc;
	while(*str && (*str != sep))
	    str++;
	if(rc = savestringn(ARG1.val_Value.String, str - ARG1.val_Value.String))
	{
	    setstrres(rc);
	}
	else
	    settitle(NoMemMsg);
    }
    return(&RES);
}

/*
 * (cdr `str' ~sep-char)
 */
VALUE *
cmd_cdr(LONG argc, VALUE *argv)
{
    if(TPLATE2(VTF_STRING, VTF_NUMBER))
    {
	STRPTR str = ARG1.val_Value.String;
	UBYTE sep = (UBYTE)ARG2.val_Value.Number;
	STRPTR rc;
	while(*str && (*str != sep))
	    str++;
	if(*str)
	    str++;
	if(rc = savestring(str))
	{
	    setstrres(rc);
	}
	else
	    settitle(NoMemMsg);
    }
    return(&RES);
}
