/* misc.c 
 *      Misc. subroutines that like to live together...
 *
 * Phillip Lindsay (c) 1987 Commodore-Amiga - This code may be freely used 
 * as long as the copyright notice is left intact.
 */

                                                            /* V17.08.87 */
/* Some small changes and a bug fix were made by Olaf Seibert, KosmoSoft */

#include <exec/types.h>
#include <exec/nodes.h>
/* #include <exec/lists.h> */
#include <exec/memory.h>
#include <exec/ports.h>
#include <exec/libraries.h>
/* #include <exec/devices.h> */
/* #include <exec/io.h> */
/* #include <devices/console.h> */
/* #include <intuition/intuition.h> */
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <libraries/filehandler.h>

#ifdef AZTEC_C
#include <functions.h>
#endif

#define MKBPTR(x)       ((BPTR)((long)x >> 2))
 
/* btoc() takes a pointer to a BSTR and converts it to a
 * C string.
 */
char *btoc(bstring)
CPTR bstring;
{
 register UBYTE len,count,*cstring=NULL;
 
 if (bstring) {
    cstring = (UBYTE *) bstring;
    len = cstring[0];              
    for(count=0;count < len;count++)
        cstring[count] = cstring[count+1];
        
    cstring[count] = '\0';
 }
 

 return((char *)cstring);
}

/* ctob() takes a pointer to a C string and converts 
 * it to a BSTR.
 */
BSTR ctob(cstring)
UBYTE *cstring;
{
 extern   UBYTE strlen();
 register UBYTE len,count; 

 if (cstring) {
    len = strlen(cstring);              
    for(count=len;count > (UBYTE)0;count--)
        cstring[count] = cstring[count-1];
    cstring[count] = len;
 }
 
 return((BSTR)MKBPTR(cstring));
}

/*
 * memcpy() - fast "C" byte memory copy.
 */
VOID memcpy(source,dest,size)
UBYTE *source,*dest;
ULONG size;
{
    register UBYTE  *msource=source,
                    *mdest=dest;
    register ULONG  msize=size;

    if (msize) {
        do { *mdest++ = *msource++; } while(--msize);
    }
        
}

/*
 * memfill() - fill memory with supplied byte value for "size" bytes
 */
VOID memfill(source,size,value)
UBYTE *source;
ULONG size;
UBYTE value;    
{
    register UBYTE  *msource=source,
                    mvalue=value,
                    *mend;

 for(mend = &source[size]; msource < mend ;msource++)
    *msource = mvalue;
}


/*
 * strupper() - return given string in upper case;
 *
 */ 

char *strupper(astring)
char *astring; 
{
    register char *astr = astring;
    
    if (astr) {
        do {
            *astr = toupper(*astr);
        } while(*astr++);
    }

    return(astring);    
}

/*
 * trunc() - truncate string at specified character
 *
 */
 VOID trunc(astring,acharacter)
 char *astring,acharacter;
 {
    register char *astr=astring,achar=acharacter;
    
    do {
        if ( *astr == achar ) {
            *astr = '\0';
            break;
        }
    } while(*astr++);       
 }
 

/*
 * allocstr() - copies a string into a newly allocated memory space.
 *
 */
char *allocstr(astring,length) 
char    *astring;
ULONG   length;
{
    register    char    *astr=astring,
                        *newstr=NULL;
    register    ULONG   slength=length;
    
    if ( (astr) && (slength) ) {
        if ( ( newstr = ( char * ) AllocMem( slength, MEMF_PUBLIC) ) )
            memcpy(astr,newstr,slength);
    }
    
    
    return(newstr);
}

/* OIS V09.08.87 */
#define KEYWORD ( ((ULONG)'C' << 24) | ((ULONG)'O' << 16) | ('P' << 8) | ('Y') )

/*
 * check to see if device node was created by dupdev().
 */
 BOOL ourdevnode(dnode)
 struct DeviceNode *dnode;
 {
    register    UBYTE   length;
    char                *bname;
    ULONG               key;

    
    bname   = (char *)  BADDR(dnode->dn_Name);
    length  = (UBYTE)   bname[0] + 1;
    key     =           KEYWORD;
        
    /* OIS V09.08.87 */
    return ( (BOOL) ( !strncmp(&key,&bname[length],(int)sizeof(ULONG)) ?
        TRUE : FALSE ) );
 }
    

/* 
 * free memory we allocated for duplicate device node. 
 */  
VOID freedev(dnode)
struct DeviceNode *dnode;
{
    register    char    *devname;
    register    UBYTE   length;
    
    if (dnode->dn_Name) {
        devname =   btoc( BADDR(dnode->dn_Name) );
        length  =   (UBYTE) strlen(devname);
        length +=   5;                  
        FreeMem(devname,(ULONG) length);
    }
        
    FreeMem( dnode, (ULONG) sizeof(*dnode) );   
}


/*
 *  Add a dos node to the system device list
 *
 */
VOID adddosnode(newdnode)
struct DeviceNode *newdnode;
{
    extern   struct DosLibrary *DOSBase;
    register struct RootNode   *rnode;
    register struct DosInfo    *dinfo;
    register struct DeviceNode *dnode;  
    register BPTR              *dnodelink;
     
    rnode   = (struct RootNode *)  DOSBase->dl_Root;        /* find root node */
    dinfo   = (struct DosInfo  *)  BADDR(rnode->rn_Info);   /* now dos info   */
	dnodelink = &dinfo->di_DevInfo;     /* Address of BPTR to next DeviceNode */
    
    Forbid();

    /* OIS V16.08.87 */
    /* Traverse the list until the first real DeviceNode shows up */
    while (dnode = (struct DeviceNode *) BADDR(*dnodelink)) {
        if (dnode->dn_Type == DLT_DEVICE) break;
        dnodelink = &dnode->dn_Next;
    }
                
    /* Insert it just before the first device, so we can override */
    /* existing device names, notably ASSIGNDEV RAM: VD0: */
    /* but don't collide with Volume and Directory names too much. */
	/* In the unlikely case there is no DeviceNode, append it at the end */

    newdnode->dn_Next = MKBPTR(dnode);
	*dnodelink        = MKBPTR(newdnode);

    Permit();        
}


/*
 *  find a dos node in the system device list
 *
 */
struct DeviceNode *finddosnode(lookfor)
char    *lookfor;
{
    extern   struct DosLibrary *DOSBase;
             struct RootNode   *rnode;
             struct DosInfo    *dinfo;
    register struct DeviceNode *dnode;
    register char              *bname;  
    char                        name1[81];
    char                        name2[81];
    BOOL                        found = FALSE;
     
    rnode   = (struct RootNode *)  DOSBase->dl_Root;        /* find root node */
    dinfo   = (struct DosInfo  *)  BADDR(rnode->rn_Info);   /* now dos info   */
    
    strcpy(name1,lookfor);
    strupper(name1);

    Forbid();

    for(dnode = (struct DeviceNode *) BADDR(dinfo->di_DevInfo); ( dnode ) ;
      dnode = (struct DeviceNode *) BADDR(dnode->dn_Next))
    {
        bname = (char *) BADDR(dnode->dn_Name);
        memcpy(bname, name2, (ULONG)( bname[0] + 1 ) );
        
        if ( !( strcmp( name1, strupper(btoc(name2)) ) ) ) {
            found   =   TRUE;
            break; 
        } 

    }
 
    Permit(); 
    
    return dnode;       /* NULL if not found */
}


/* 
 *  Duplicate the given device node and add it the system device list.
 */
VOID dupdev(dnode,newname)
struct DeviceNode   *dnode;
char                *newname;
{
    register struct DeviceNode  *newdnode;
    register BSTR               newbname;
    register UBYTE              length;
    char                        tmpname[81];
    ULONG                       tmplong;
        
    newdnode = (struct DeviceNode *)
        AllocMem( (ULONG) sizeof(*newdnode), MEMF_PUBLIC | MEMF_CLEAR );
    
    memcpy(dnode,newdnode,(ULONG)sizeof(*newdnode));
    
    newdnode->dn_Name   = NULL; 
  
    strcpy(tmpname,newname);
    
    length              = (UBYTE) strlen(tmpname);
     
    tmplong             = KEYWORD;
    
    memcpy(&tmplong,&tmpname[length+1], (ULONG) sizeof(ULONG) );
  
    length             += 5;    /* include NULL and LONG WORD */
    
    newbname            = ctob( allocstr(tmpname, (ULONG) length) );
    
    newdnode->dn_Next   = NULL;
   
    if (!newbname)
        freedev(newdnode);
    else {    
        newdnode->dn_Name = newbname;
        adddosnode(newdnode);
    }
}


/* end of misc.c */
