/*
**
** Copyright © 1996 Kai Hofmann. All rights reserved.
**
** $VER: MCCLib.c 12.1 (12.12.96)
**
** Released as Giftware for NON-COMMERCIAL use!
**
*/

 /* ------------------------------------------------------------------------ */
 /*
    Before:
    CLASS       MUIC_MonthNavigator
    SUPERCLASS  MUIC_Group ; DO NOT SPECIFY THIS FOR MCPs!
    ONLYGLOBAL	Must only be set to TRUE for a MCP when it should be global
		available only!
    COPYRIGHT   "1996"
    AUTHOR      "Kai Hofmann"
    VERSION     12
    REVISION    0
    VERSIONSTR  "12.0"

    PREFSIMAGE_COMPRESSION  0 ; MCPs ONLY!
    PREFSIMAGE_DEPTH        3 ; MCPs ONLY!
    PREFSIMAGE_MASKING      2 ; MCPs ONLY!
    PREFSIMAGE_WIDTH       23 ; MCPs ONLY!
    PREFSIMAGE_HEIGHT      14 ; MCPs ONLY!

    struct Data {};
    extern const UBYTE PrefsImage_body[];    ; MCPs ONLY!
    extern const ULONG PrefsImage_colors[];  ; MCPs ONLY!

    Somewhere:
    static BOOL ClassInitFunc(const struct Library *const base);
    static VOID ClassExitFunc(const struct Library *const base);
    static ULONG SAVEDS_ASM Dispatcher(register __a0 struct IClass *const cl, register __a2 Object *const obj, register __a1 const Msg msg);
 */
 /* ------------------------------------------------------------------------ */

 #ifndef EXEC_TYPES_H
   #include <exec/types.h>
 #endif
 #ifndef EXEC_RESIDENT_H
   #include <exec/resident.h>
 #endif
 #ifndef EXEC_MEMORY_H
   #include <exec/memory.h>
 #endif
 #ifndef EXEC_LIBRARIES_H
   #include <exec/libraries.h>
 #endif
 #ifndef EXEC_SEMAPHORES_H
   #include <exec/semaphores.h>
 #endif
 #ifndef EXEC_EXECBASE_H
   #include <exec/execbase.h>
 #endif
 #include <clib/exec_protos.h>
 #include <pragmas/exec_sysbase_pragmas.h>
 #ifndef LIBRARIES_MUI_H
   #include <libraries/mui.h>
 #endif
 #ifndef PROTO_MUIMASTER_H
   #include <proto/muimaster.h>
 #endif


 /* copied from system.h © 1995 Kai Hofmann */
 #ifndef STACKARGS
   #define STACKARGS	__stdargs
 #endif
 #ifndef SAVEDS_ASM
   #define SAVEDS_ASM	__saveds __asm
 #endif
 #ifndef REG
   #define REG(r)	register r
   #define D0		__d0
   #define D1		__d1
   #define D2		__d2
   #define D3		__d3
   #define D4		__d4
   #define D5		__d5
   #define D6		__d6
   #define D7		__d7
   #define A0		__a0
   #define A1		__a1
   #define A2		__a2
   #define A3		__a3
   #define A4		__a4
   #define A5		__a5
   #define A6		__a6
 #endif


 #ifndef SUPERCLASS
   #define SUPERCLASS	MUIC_Mccprefs
   #define PREFSCLASS   1
   #ifndef ONLYGLOBAL
     #define ONLYGLOBAL	FALSE
   #endif
 #endif

 /* ------------------------------------------------------------------------ */

 /****************************************************************************/
 /* External references                                                      */
 /****************************************************************************/

 static BOOL SAVEDS_ASM UserLibOpen   (REG(A6) const struct Library *const base);
 static BOOL SAVEDS_ASM UserLibClose  (REG(A6) const struct Library *const base);
 static BOOL ClassInitFunc(const struct Library *const base);
 static VOID ClassExitFunc(const struct Library *const base);
 static ULONG SAVEDS_ASM Dispatcher(REG(A0) struct IClass *const cl, REG(A2) Object *const obj, REG(A1) const Msg msg);

 struct LibraryHeader * SAVEDS_ASM _LibInit(REG(A0) const BPTR Segment);
 BPTR SAVEDS_ASM _LibExpunge(REG(A6) struct LibraryHeader *const base);
 struct LibraryHeader * SAVEDS_ASM _LibOpen(REG(A6) struct LibraryHeader *const base);
 BPTR SAVEDS_ASM _LibClose(REG(A6) struct LibraryHeader *const base);
 LONG SAVEDS_ASM _LibExtFunc(VOID);

 SAVEDS_ASM struct MUI_CustomClass *MCC_Query(REG(D0) const LONG which);

 /****************************************************************************/
 /* Dummy entry point and LibExtFunc() function all in one                   */
 /****************************************************************************/

 LONG SAVEDS_ASM _LibExtFunc(VOID)
  {
   return(NULL);
  }

 /****************************************************************************/
 /* Structures                                                               */
 /****************************************************************************/

 const char _LibName[] = CLASS;
 const char _LibID[] = "$VER: " CLASS " " VERSIONSTR " " __AMIGADATE__ " ©" COPYRIGHT " " AUTHOR ", "
                       #ifdef _M68060
                         "68060"
                       #else
                         #ifdef _M68040
                           "68040"
                         #else
                           #ifdef _M68030
                             "68030"
                           #else
                             #ifdef _M68020
                               "68020"
                             #else
                               #ifdef _M68010
                                 "68010"
                               #else
                                 "68000"
                               #endif
                             #endif
                           #endif
                         #endif
                       #endif
                       #ifdef _MFPU40
                         "+FPU40"
                       #else
                         #ifdef _M68882
                           "+68882"
                         #else
                           #ifdef _M68881
                             "+68881"
                           #endif
                         #endif
                       #endif
                       " version.\n";

 const APTR _LibFuncTab[] =
  {
   _LibOpen,
   _LibClose,
   _LibExpunge,
   _LibExtFunc,
   MCC_Query,
   (APTR)-1
  };

 const struct Resident _LibRomTag =
  {
   RTC_MATCHWORD,
   &_LibRomTag,
   &_LibRomTag + 1,
   0,
   VERSION,
   NT_LIBRARY,
   0,
   _LibName,
   _LibID,
   _LibInit
  };


 struct LibraryHeader
  {
   struct Library         lh_Library;
   BPTR                   lh_Segment;
   struct SignalSemaphore lh_Semaphore;
  };


 struct Library         *MUIClassBase;
 struct Library         *MUIMasterBase;
 struct MUI_CustomClass *ThisClass;
 struct ExecBase        *SysBase;
 struct IntuitionBase   *IntuitionBase;
 #ifndef PREFSCLASS
 struct Library         *UtilityBase;
 struct DosLibrary      *DOSBase;
 /* struct GfxBase      *GfxBase; */
 #endif

 /****************************************************************************/
 /* Standard Library Functions, all of them are called in Forbid() state.    */
 /****************************************************************************/

 /* REG(D0) struct LibraryHeader *base */
 struct LibraryHeader * SAVEDS_ASM _LibInit(REG(A0) const BPTR Segment)
  {
   struct LibraryHeader *base;

   SysBase = *((struct ExecBase **)4);

   #ifdef _M68060
   if (!(SysBase->AttnFlags & AFF_68060))
    {
     return(NULL);
    }
   #else
     #ifdef _M68040
     if (!(SysBase->AttnFlags & AFF_68040))
      {
       return(NULL);
      }
     #else
       #ifdef _M68030
       if (!(SysBase->AttnFlags & AFF_68030))
        {
         return(NULL);
        }
       #else
         #ifdef _M68020
         if (!(SysBase->AttnFlags & AFF_68020))
          {
           return(NULL);
          }
         #else
           #ifdef _M68010
           if (!(SysBase->AttnFlags & AFF_68010))
            {
             return(NULL);
            }
           #endif
         #endif
       #endif
     #endif
   #endif
   #ifdef _MFPU40
   if (!(SysBase->AttnFlags & AFF_FPU40))
    {
     return(NULL);
    }
   #else
     #ifdef _M68882
     if (!(SysBase->AttnFlags & AFF_68882))
      {
       return(NULL);
      }
     #else
       #ifdef _M68881
       if (!(SysBase->AttnFlags & AFF_68881))
        {
         return(NULL);
        }
       #endif
     #endif
   #endif

   base = (struct LibraryHeader *)MakeLibrary((APTR)_LibFuncTab,NULL,NULL,sizeof(struct LibraryHeader),NULL);
   if (base != NULL)
    {
     base->lh_Library.lib_Node.ln_Type = NT_LIBRARY;
     base->lh_Library.lib_Node.ln_Name = (char *)_LibName;
     base->lh_Library.lib_Flags        = LIBF_CHANGED | LIBF_SUMUSED;
     base->lh_Library.lib_Version      = VERSION;
     base->lh_Library.lib_Revision     = REVISION;
     base->lh_Library.lib_IdString     = (char *)_LibID;
     base->lh_Segment = Segment;
     InitSemaphore(&base->lh_Semaphore);
     AddLibrary((struct Library *)base);
    }
   return(base);
  }


 BPTR SAVEDS_ASM _LibExpunge(REG(A6) struct LibraryHeader *const base)
  {
   struct ExecBase *SysBase = *((struct ExecBase **)4);
   BPTR rc;

   if (base->lh_Library.lib_OpenCnt != 0)
    {
     base->lh_Library.lib_Flags |= LIBF_DELEXP;
     return(NULL);
    }
   Remove((struct Node *)base);
   rc = base->lh_Segment;
   FreeMem((BYTE *)base - base->lh_Library.lib_NegSize,(ULONG)(base->lh_Library.lib_NegSize + base->lh_Library.lib_PosSize));
   return(rc);
  }

 /****************************************************************************/

 /* REG(D0) ULONG Version */
 struct LibraryHeader * SAVEDS_ASM _LibOpen(REG(A6) struct LibraryHeader *const base)
  {
   struct ExecBase *SysBase = *((struct ExecBase **)4);
   struct LibraryHeader *rc;

   base->lh_Library.lib_OpenCnt++;
   base->lh_Library.lib_Flags &= ~LIBF_DELEXP;
   ObtainSemaphore(&base->lh_Semaphore);
   if (UserLibOpen((struct Library *)base))
    {
     rc = base;
    }
   else
    {
     rc = NULL;
     base->lh_Library.lib_OpenCnt--;
    }
   ReleaseSemaphore(&base->lh_Semaphore);
   return(rc);
  }


 BPTR SAVEDS_ASM _LibClose(REG(A6) struct LibraryHeader *const base)
  {
   struct ExecBase *SysBase = *((struct ExecBase **)4);
   BPTR rc = NULL;

   ObtainSemaphore(&base->lh_Semaphore);
   UserLibClose((struct Library *)base);
   ReleaseSemaphore(&base->lh_Semaphore);
   if (--base->lh_Library.lib_OpenCnt == 0)
    {
     if (base->lh_Library.lib_Flags & LIBF_DELEXP)
      {
       rc = _LibExpunge(base);
      }
    }
   return(rc);
  }

 /****************************************************************************/

 static BOOL SAVEDS_ASM UserLibOpen(REG(A6) const struct Library *const base)
  {
   if (base->lib_OpenCnt == 1)
    {
     MUIMasterBase = OpenLibrary(MUIMASTER_NAME,(ULONG)base->lib_Version);
     if (MUIMasterBase != NULL)
      {
       ThisClass = MUI_CreateCustomClass((struct Library *const)base,SUPERCLASS,NULL,sizeof(struct Data),Dispatcher);
       if (ThisClass != NULL)
        {
         BOOL res;

         #ifndef PREFSCLASS
         UtilityBase   = ThisClass->mcc_UtilityBase;
         DOSBase       = (struct DosLibrary *)ThisClass->mcc_DOSBase;
         /*GfxBase       = (struct GfxBase *)ThisClass->mcc_GfxBase;*/
         #endif
         IntuitionBase = (struct IntuitionBase *)ThisClass->mcc_IntuitionBase;
         res = ClassInitFunc(base);
         if (res)
          {
           return(TRUE);
          }
         if (!MUI_DeleteCustomClass(ThisClass))
          {
           /* can't delete public custom class */
          }
        }
       CloseLibrary(MUIMasterBase);
      }
     ThisClass     = NULL;
     MUIMasterBase = NULL;
     IntuitionBase = NULL;
     #ifndef PREFSCLASS
     UtilityBase   = NULL;
     DOSBase       = NULL;
     /*GfxBase       = NULL;*/
     #endif
     return(FALSE);
    }
   return(TRUE);
  }


 static BOOL SAVEDS_ASM UserLibClose(REG(A6) const struct Library *const base)
  {
   if (base->lib_OpenCnt == 1)
    {
     ClassExitFunc(base);
     if (ThisClass != NULL)
      {
       if (!MUI_DeleteCustomClass(ThisClass))
        {
         /* can't delete public custom class */
        }
      }
     if (MUIMasterBase != NULL)
      {
       CloseLibrary(MUIMasterBase);
      }
     ThisClass       = NULL;
     MUIMasterBase   = NULL;
     IntuitionBase   = NULL;
     #ifndef PREFSCLASS
     UtilityBase     = NULL;
     DOSBase         = NULL;
     /*GfxBase         = NULL;*/
     #endif
    }
   return(TRUE);
  }

 /****************************************************************************/

 SAVEDS_ASM struct MUI_CustomClass *MCC_Query(REG(D0) const LONG which)
  {
   switch (which)
    {
     #ifndef PREFSCLASS
     case 0 : return(ThisClass);	/* Pointer to Custom Class */
     #else
     case 1 : return(ThisClass);	/* Pointer to Preference Class */
     case 2 : return(
                     #ifndef PREFSIMAGE_DEPTH
                     NULL
                     #else
                     (struct MUI_CustomClass *)
                     MUI_NewObject(MUIC_Bodychunk,
                                     MUIA_Bodychunk_Body,        PrefsImage_body,
                                     MUIA_Bodychunk_Compression, PREFSIMAGE_COMPRESSION,
                                     MUIA_Bodychunk_Depth,       PREFSIMAGE_DEPTH,
                                     MUIA_Bodychunk_Masking,     PREFSIMAGE_MASKING,
                                     MUIA_Bitmap_Width,          PREFSIMAGE_WIDTH,
                                     MUIA_Bitmap_Height,         PREFSIMAGE_HEIGHT,
                                     MUIA_FixWidth,              PREFSIMAGE_WIDTH,
                                     MUIA_FixHeight,             PREFSIMAGE_HEIGHT,
                                     MUIA_Bitmap_SourceColors,   PrefsImage_colors,
                                     MUIA_Bitmap_Transparent,    0,
                                   TAG_DONE
                                  )
                     #endif
                    );			/* Pointer to Preference Image */
     case 3 : return(ONLYGLOBAL);	/* Only Global */
     #endif
    }
   return(NULL);
  }

 /* ------------------------------------------------------------------------ */

   void __regargs __chkabort(void)
    {}

   void __regargs _CXBRK(void)
    {}

 /* ------------------------------------------------------------------------ */
