/*
** $VER: support.c 1.2 (04 Jun 1996)
**
** (C) Copyright 1996 Marius Gröger
**     All Rights Reserved
**
** $HISTORY:
**
** 04 Jun 1996 : 001.002 :  ToolType handling improved
** 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 STRPTR AddToolType(GD gd, struct DiskObject *dobj, char *tool);
PUBLIC STRPTR *DupToolTypes(GD gd, struct DiskObject *dobj);
PUBLIC void UnDupToolTypes(GD gd, struct DiskObject *dobj, STRPTR *oldtt);
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 != NULL) && (gd->gd_Handle->Window != NULL))
   {
      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 and was   */
/* modified that it doesn't use the Undocumented FreeList handling of        */
/* icon.library. This should make the code much more safe.                   */
/*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*/ PRIVATE void FreeToolTypes(GD gd, struct DiskObject *dobj, STRPTR *tooltypes)
{
   int i;

   if (tooltypes != NULL)
   {
      for(i=0; tooltypes[i] != NULL; ++i)
         freeppvec(gd, tooltypes[i]);

      freeppvec(gd, tooltypes);

      dobj->do_ToolTypes = tooltypes;
   }
   return;
}
/*E*/
/*F*/ PUBLIC void UnDupToolTypes(GD gd, struct DiskObject *dobj, STRPTR *oldtt)
{
   FreeToolTypes(gd, dobj, dobj->do_ToolTypes);
   dobj->do_ToolTypes = oldtt;
   return;
}
/*E*/
/*F*/ PUBLIC STRPTR *DupToolTypes(GD gd, struct DiskObject *dobj)
{
   STRPTR *orga = dobj->do_ToolTypes;
   STRPTR *newa, p;
   STRPTR *rv = orga;
   int i,n;

   for(n=0; orga[n] != NULL; ++n)
      ;

   if (newa = allocppvec(gd, (n+1) * sizeof(STRPTR)))
   {
      for(i=0; i<n; ++i)
      {
         if (p = allocppvec(gd, strlen(orga[i]) + 1))
         {
            strcpy((char*)p, (char*)orga[i]);
            newa[i] = p;
         }
         else
         {
            while(i--) freeppvec(gd, newa[i]);
            freeppvec(gd, newa);
            rv = NULL;
            break;
         }
      }
      if (rv)
      {
         orga[i] = NULL;
         dobj->do_ToolTypes = newa;
      }
   }

   return rv;
}
/*E*/
/*F*/ PUBLIC STRPTR AddToolType(GD gd, struct DiskObject *dobj, char *tool)
{
   STRPTR **ttypes = &(dobj->do_ToolTypes);
   STRPTR item = (*ttypes)[0];
   int change = -1;
   int i=0;
   STRPTR newmem;
   int len;
   STRPTR rv = NULL;

   while (item != NULL)
   {
      if (change == -1)  /* We haven't found any matching tooltype yet */
      {
         switch(ToolMatch(item, tool))
         {
            case 0:
               rv = item;     /* This tooltype already defined */
            goto leave;

            case 1:
            case 3:
            case 4:
               change = i;     /* Change this tooltype */
            break;

            default:
               /* 2,5 means different */
            break;
         }
      }

      i++;
      item = (*ttypes)[i]; /* Get the next tooltype to be examined */
   }

   if (change != -1)
   {
      len = strlen(tool)+1;
      if ((newmem = allocppvec(gd, len)) != NULL)
      {
         strcpy(newmem, tool);
         freeppvec(gd, (*ttypes)[change]);
         (*ttypes)[change] = newmem;
         rv = newmem;
      }
   }
   else
   {
      len = (i+2) * sizeof(STRPTR);
      if ((newmem = allocppvec(gd, len)) != NULL)
      {
         CopyMem(*ttypes, newmem + sizeof(STRPTR), len);

         freeppvec(gd, *ttypes);

         *ttypes = (STRPTR *)newmem;

         len = strlen(tool)+1;
         if ((newmem = allocppvec(gd, len)) != NULL)
         {
            strcpy(newmem, tool);
            (*ttypes)[0] = newmem;
            (*ttypes)[i+1] = NULL;
            rv = newmem;
         }
      }
   }

leave:
   return rv;
}
/*E*/
/* ------------------------------------------------------------------------- */

