/*
** $VER: support.c 1.1 (05 May 1996)
**
** (C) Copyright 1996 Marius Gröger
**     All Rights Reserved
**
** $HISTORY:
**
** 05 May 1996 : 001.001 :  fixed bug in hex number conversion
** 25 Apr 1996 : 001.000 :  created
*/

/*F*/ /* includes */

#include <clib/alib_protos.h>
#include <clib/dos_protos.h>
#include <pragmas/dos_pragmas.h>
#include <clib/utility_protos.h>
#include <pragmas/utility_pragmas.h>
#include <clib/exec_protos.h>
#include <pragmas/exec_sysbase_pragmas.h>
#include <clib/intuition_protos.h>
#include <pragmas/intuition_pragmas.h>
#include <clib/gadtools_protos.h>
#include <pragmas/gadtools_pragmas.h>
#include <clib/icon_protos.h>
#include <pragmas/icon_pragmas.h>
#include <clib/locale_protos.h>
#include <pragmas/locale_pragmas.h>

#include <gtlayout/gtlayout.h>

#include <exec/libraries.h>
#include <exec/devices.h>
#include <exec/memory.h>
#include <exec/io.h>

#include <workbench/startup.h>

#include <utility/tagitem.h>

#include <netinclude:devices/sana2.h>

#define AsmPools
#include <pools/pool_lib.h>

#if (USE_EXTREADARGS != 0)
#include <extrdargs.h>
#endif

#include "compiler.h"
#include "debug.h"
#define CATCOMP_NUMBERS
#include "locale.h"
#include "sana2meter.h"
#include "constdata.h"

#include <strings.h>
/*E*/

/*F*/ /* private symbols */
PRIVATE int ToolMatch(char *s1, char *s2);
/*E*/
/*F*/ /* exported symbols */
PUBLIC VOID *allocpvec(GD gd, ULONG len);
PUBLIC VOID freepvec(GD gd, VOID *mem);
PUBLIC VOID *allocppvec(GD gd, ULONG len);
PUBLIC VOID freeppvec(GD gd, VOID *mem);
PUBLIC VOID message(GD gd, LONG, LONG, LONG, ...);
PUBLIC struct Library *openlib(GD gd, STRPTR name, LONG version);
PUBLIC char *AddToolType(GD gd, struct DiskObject *dobj, char *tool);
PUBLIC ULONG strntolong(GD gd, STRPTR s, LONG *number, LONG n);
/*E*/
/*F*/ /* imported symbols */
IMPORT ASM STRPTR GetString(REG(a0) struct LocaleInfo *li, REG(d0) LONG stringNum);
/*E*/

/*F*/ PUBLIC ULONG strntolong(GD gd, STRPTR s, LONG *number, LONG n)
{

#define IsDigit(c) ((c) >= '0' && (c) <= '9'))
#define IsXDigit(c) (((c) >= '0' && (c) <= '9') || ((c) >= 'A' && (c) <= 'F'))

   BOOL hex;
   UBYTE c;
   UWORD countdown;
   ULONG preconv, rc;

   if ((n > 2) && !Strnicmp(s, "0x", 2))
   {
      hex = TRUE;
      s += 2;
      n -= 2;
      preconv = 2;
   }
   else if ((n > 1) && !Strnicmp(s, "$", 1))
   {
      hex = TRUE;
      ++s;
      --n;
      preconv = 1;
   }
   else
   {
      hex = FALSE;
      preconv = 0;
   }

   if (countdown=n)
   {
      LONG num;

      for(num=0; countdown && (*s != '\0'); ++s, --countdown)
      {
         c = ToUpper((ULONG)*s);
         if (hex)
         {
            if (c >= '0' && c <= '9') num = num * 16 + c - '0';
            else if (c >= 'A' && c <= 'F') num = num * 16 + c - 'A' + 10;
            else break;
         }
         else
         {
            if (c >= '0' && c <= '9') num = num * 10 + c - '0';
            else break;
         }
      }

      if (n - countdown)
      {
         *number = num;
         rc = preconv + (n - countdown);
      }
      else rc = 0;
   }
   else rc = 0;

   return rc;
}
/*E*/

/*F*/ PUBLIC VOID message(GD gd, LONG title, LONG body, LONG button, ...)
{
   struct EasyStruct es;

   es.es_StructSize = sizeof(struct EasyStruct);
   es.es_Flags = 0;
   es.es_Title = GetString(&gd->gd_LocaleInfo, title);
   es.es_TextFormat = GetString(&gd->gd_LocaleInfo, body);
   es.es_GadgetFormat = GetString(&gd->gd_LocaleInfo, button);

   if (gd->gd_Handle)
   {
      LT_LockWindow(gd->gd_Handle->Window);
      EasyRequestArgs(gd->gd_Handle->Window, (struct EasyStruct *)&es, NULL, (APTR)(&button + 1));
      LT_UnlockWindow(gd->gd_Handle->Window);
   }
   else
   {
      if (gd->gd_CLI || !IntuitionBase)
      {
         if (gd->gd_DOSBase) VPrintf(es.es_TextFormat, (APTR)(&button + 1));
         VPrintf("\n", NULL);
      }
      else
         EasyRequestArgs(NULL, (struct EasyStruct *)&es, NULL, (APTR)(&button + 1));
   }
}
/*E*/

/*F*/ PUBLIC struct Library *openlib(GD gd, STRPTR name, LONG version)
{
   struct Library *lib;

   if (!(lib = OpenLibrary(name, version)))
      message(gd, REQ_ERROR_TITLE, REQ_ERROR_OPENLIB, REQ_ERROR_QUITBUTTON,
                                    name, version);
   return lib;
}
/*E*/

/*F*/ PUBLIC VOID *allocpvec(GD gd, ULONG len)
{
   ULONG *p;

   if (p = AsmAllocPooled(gd->gd_AnyPool, len+sizeof(ULONG), (struct ExecBase*)SysBase))
      *p++ = (ULONG)(len+sizeof(ULONG));

   return (VOID*)p;
}
/*E*/
/*F*/PUBLIC VOID freepvec(GD gd, VOID *mem)
{
   ULONG *p = (ULONG*)mem - 1;

   AsmFreePooled(gd->gd_AnyPool, p, *p, (struct ExecBase*)SysBase);

   return ;
}
/*E*/
/*F*/ PUBLIC VOID *allocppvec(GD gd, ULONG len)
{
   ULONG *p;

   if (p = AsmAllocPooled(gd->gd_PubPool, len+sizeof(ULONG), (struct ExecBase*)SysBase))
      *p++ = (ULONG)(len+sizeof(ULONG));

   return (VOID*)p;
}
/*E*/
/*F*/PUBLIC VOID freeppvec(GD gd, VOID *mem)
{
   ULONG *p = (ULONG*)mem - 1;

   AsmFreePooled(gd->gd_PubPool, p, *p, (struct ExecBase*)SysBase);

   return ;
}
/*E*/

/* ------------------------------------------------------------------------- */
/* This code has been grabbed by Jure Vrhovnik's supra.lib library.          */
/* I could not use the library since it assumes a global SysBase symbol      */
/* Except of the PUBLIC identifier the routines below are _exactly_  the    */
/* same as in supra.lib distribution 1.1, though.                            */
/* A word to the AddToolType() call: This routine uses some undocumented     */
/* information about the memory management of disk objects and might crash   */
/* under future releases of icon.library.                                    */
/*F*/ PRIVATE int ToolMatch(char *s1, char *s2)
{
int cmp = 2;
int offs = 0;

    if ((*s1 == '(' || *s2 == '(') && *s1 != *s2) offs = 3;
    if (*s1 == '(') s1++;
    if (*s2 == '(') s2++;
    if (*s1 == ')') {
            if (*(s1+1) == '\0') s1++;
    }

    if (*s2 == ')') {
        if (*(s2+1) == '\0') s2++;
    }


    while (*s1 && *s2) {
        if (*s1 == '\0' && *s2 == '\0') return(0+offs);
        if (*s1 != *s2) return(cmp+offs);
        if (*s1 == '=') cmp=1;
        s1++; s2++;
        if (*s1 == ')') {
            if (*(s1+1) == '\0') s1++;
        }

        if (*s2 == ')') {
            if (*(s2+1) == '\0') s2++;
        }

    }

    if (*s1 == '\0' && *s2 == '\0') return(0+offs);
    else return(cmp+offs);
}
/*E*/
/*F*/ PUBLIC char *AddToolType(GD gd, struct DiskObject *dobj, char *tool)
{
struct FreeList *flist = (struct FreeList *)dobj + sizeof(struct DiskObject);
char ***ttypes = &(dobj->do_ToolTypes);
char *item = (*ttypes)[0];
int change = -1;
int i=0;
char *newmem;
int len;

    while (item != NULL) {
      if (change == -1) { /* We haven't found any matching tooltype yet */
        switch(ToolMatch(item, tool)) {
            case 0: return(item);   /* This tooltype already defined */
            case 1:
            case 3:
            case 4: change = i;     /* Change this tooltype */
        }   /* 2,5 means different */
      }
      i++;
      item = (*ttypes)[i]; /* Get the next tooltype to be examined */
    }

    if (change != -1) {
        len = strlen(tool)+1;
        if ((newmem = AllocMem(len, 0L)) == NULL) return(NULL);
        else if (AddFreeList(flist, newmem, len) == FALSE) {
            FreeMem(newmem, len);
            return(NULL);
        }

        strcpy(newmem, tool);
        (*ttypes)[change] = newmem;
        return(newmem);
    } else {
        len = (i+2)*4;
        if ((newmem = AllocMem(len, 0L)) == NULL) return(NULL);
        else if (AddFreeList(flist, newmem, len) == FALSE) {
            FreeMem(newmem, len);
            return(NULL);
        }

        CopyMem(*ttypes, newmem+4, len);
        *ttypes = (char **)newmem;

        len = strlen(tool)+1;
        if ((newmem = AllocMem(len, 0L)) == NULL) return(NULL);
        else if (AddFreeList(flist, newmem, len) == FALSE) {
            FreeMem(newmem, len);
            return(NULL);
        }

        strcpy(newmem, tool);
        (*ttypes)[0] = newmem;
        (*ttypes)[i+1] = NULL;
        return(newmem);
    }
}
/*E*/
/* ------------------------------------------------------------------------- */

