 /* Copyright © 1996 Kai Hofmann. All rights reserved. */

 #define __MakeLib


 #include "system.h"
 #include "muiutils.h"
 #include "MonthNavigator_mcc.h"
 #include <clib/alib_protos.h>
 #include <proto/muimaster.h>
 #include <libraries/mui.h>
 #include "date.h"
 #include "date_pragmas.h"
 #include <exec/libraries.h>
 #include <proto/utility.h>
 #include <utility/tagitem.h>
 #include <proto/exec.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>


 struct MUI_CustomClass *App_CC,*Win_CC,*Str_CC;


 struct Library *MUIMasterBase;
 struct Library *DateBase;
 static Object *App,*Win;


 #define MUIA_Win_Type			((TAG_USER | 494 << 16) | 0x8001)
 #define MUIV_Win_Type_ReadOnly		0
 #define MUIV_Win_Type_RelVerify	1
 #define MUIV_Win_Type_Immediate	2

 #define MUIM_Win_Update		((TAG_USER | 494 << 16) | 0x8002)
 #define MUIM_Win_UpdateDay		((TAG_USER | 494 << 16) | 0x8003)


 struct Str_Data {
                  Object *dummy;
                 };


 struct Win_Data {
                  Object *monthnavigator;
                  Object *month,*year,*day;
                 };


 struct App_Data {
                  Object *win1,*win2,*win3;
                 };


 static char *months[13];


 /* --- String ------------------------------------------------------------- */

 static ULONG Str_New(struct IClass *cl, Object *obj, struct opSet *msg)
  {
   obj = (Object *)DoSuperNew(cl,obj,
                              MUIA_String_Format,	MUIV_String_Format_Left,
                              MUIA_String_MaxLen,	30,
                              MUIA_Frame,		MUIV_Frame_String,
                              MUIA_Background,		MUII_TextBack,
                              TAG_MORE, msg->ops_AttrList
                             );
   if (obj != NULL)
    {
     struct Str_Data *data = (struct Str_Data *)INST_DATA(cl,obj);
     /*ULONG result;*/

     data->dummy = NULL;
    }
   return((ULONG)obj);
  }


 static ULONG Str_DragQuery(struct IClass *cl, Object *obj, struct MUIP_DragQuery *msg)
  {
   /*struct Str_Data *data = (struct Str_Data *)INST_DATA(cl,obj);*/
   /*ULONG result;*/
   ULONG Year,Month,Day;

   if (get(msg->obj,MUIA_MonthNavigator_Year,&Year) && get(msg->obj,MUIA_MonthNavigator_Month,&Month) && get(msg->obj,MUIA_MonthNavigator_Day,&Day))
    {
     return(MUIV_DragQuery_Accept);
    }
   return(MUIV_DragQuery_Refuse);
  }


 static ULONG Str_DragDrop(struct IClass *cl, Object *obj, struct MUIP_DragDrop *msg)
  {
   /*struct Str_Data *data = (struct Str_Data *)INST_DATA(cl,obj);*/
   /*ULONG result;*/
   char str[30];
   ULONG Day,Month,Year;

   /*result =*/ get(msg->obj,MUIA_MonthNavigator_Year,&Year);
   /*result =*/ get(msg->obj,MUIA_MonthNavigator_Month,&Month);
   /*result =*/ get(msg->obj,MUIA_MonthNavigator_Day,&Day);
   sprintf(str,"%lu.%lu.%lu",Day,Month,Year);
   /*result =*/ set(obj,MUIA_String_Contents,(ULONG)str);
   return(0);
  }


 static ULONG SAVEDS_ASM Str_Dispatcher(REG(A0) struct IClass *cl, REG(A2) Object *obj, REG(A1) Msg msg)
  {
   switch (msg->MethodID)
    {
     case OM_NEW			: return(Str_New(cl,obj,(struct opSet *)msg));
     case MUIM_DragQuery		: return(Str_DragQuery(cl,obj,(struct MUIP_DragQuery *)msg));
     case MUIM_DragDrop			: return(Str_DragDrop(cl,obj,(struct MUIP_DragDrop *)msg));
     default				: return(DoSuperMethodA(cl,obj,msg));
    }
  }

 /* --- Window ------------------------------------------------------------- */

 static ULONG Win_Update(struct IClass *cl, Object *obj, Msg msg)
  {
   struct Win_Data *data = (struct Win_Data *)INST_DATA(cl,obj);
   ULONG year,month;

   get(data->month,MUIA_Cycle_Active,&month);
   month++;
   get(data->year,MUIA_Numeric_Value,&year);
   set(data->monthnavigator,MUIA_MonthNavigator_Month,month);
   set(data->monthnavigator,MUIA_MonthNavigator_Year,year);
   if (data->day != NULL)
    {
     set(data->day,MUIA_Text_Contents,"0");
    }
   return(0);
  }


 static ULONG Win_UpdateDay(struct IClass *cl, Object *obj, Msg msg)
  {
   struct Win_Data *data = (struct Win_Data *)INST_DATA(cl,obj);
   ULONG day;
   char daystr[3];

   get(data->monthnavigator,MUIA_MonthNavigator_Day,&day);
   sprintf(daystr,"%lu",day);
   set(data->day,MUIA_Text_Contents,daystr);
   return(0);
  }


 static ULONG Win_New(struct IClass *cl, Object *obj, struct opSet *msg)
  {
   struct TagItem *tags,*tag;
   ULONG type = MUIV_Win_Type_ReadOnly;
   Object *monthnavigator,*monthobj,*yearobj,*pyearobj,*myearobj,*dayobj = NULL;

   tags = msg->ops_AttrList;
   while (tag = NextTagItem(&tags))
    {
     switch (tag->ti_Tag)
      {
       case MUIA_Win_Type	: type = (ULONG)tag->ti_Data;
                                  break;
      }
    }
   obj = (Object *)DoSuperNew(cl,obj,
                              MUIA_Window_ID,			MAKE_ID('D','E','M','0'+type),
                              MUIA_Window_Title,		(type == MUIV_Win_Type_ReadOnly) ? "ReadOnly" : ((type == MUIV_Win_Type_RelVerify) ? "RelVerify" : "Immediate"),
                              MUIA_Window_ScreenTitle,		"MonthNavigator-Demo V2.1",
                              MUIA_Window_RootObject,		VGroup,
                                MUIA_Group_SameWidth,		TRUE,
                                MUIA_Group_Child,		HGroup,
                                  MUIA_Frame,			MUIV_Frame_Group,
                                  MUIA_Background,		MUII_GroupBack,
                                  MUIA_Group_SameHeight,	TRUE,
                                  MUIA_Group_Child,		RectangleObject,
                                    MUIA_HorizWeight,		(type == MUIV_Win_Type_RelVerify) ? 100 : 50,
                                  End,
                                  MUIA_Group_Child,		(type == MUIV_Win_Type_RelVerify) ? dayobj = TextObject,
                                    MUIA_Text_PreParse,		"\33r",
                                    MUIA_Frame,			MUIV_Frame_Text,
                                    MUIA_Background,		MUII_TextBack,
                                    MUIA_FixWidthTxt,		"MM",
                                  End :
                                  RectangleObject,
                                    MUIA_HorizWeight,		50,
                                  End,
                                  MUIA_Group_Child,		monthobj = CycleObject,
                                    MUIA_Cycle_Entries,		months,
                                  End,
                                  MUIA_Group_Child,		yearobj = NumericbuttonObject,
                                    MUIA_Numeric_Format,	"%lu",
                                    MUIA_Numeric_Min,		8,
                                    MUIA_Numeric_Max,		8000,
                                  End,
                                  MUIA_Group_Child,		myearobj = ImageObject,
                                    MUIA_Frame,           	MUIV_Frame_Button,
                                    MUIA_InputMode,       	MUIV_InputMode_RelVerify,
                                    MUIA_Image_Spec,      	MUII_ArrowLeft,
                                    MUIA_Image_FreeVert,  	TRUE,
                                    MUIA_Background,      	MUII_ButtonBack,
                                    MUIA_ShowSelState,    	FALSE,
                                  End,
                                  MUIA_Group_Child,		pyearobj = ImageObject,
                                    MUIA_Frame,           	MUIV_Frame_Button,
                                    MUIA_InputMode,       	MUIV_InputMode_RelVerify,
                                    MUIA_Image_Spec,      	MUII_ArrowRight,
                                    MUIA_Image_FreeVert,  	TRUE,
                                    MUIA_Background,      	MUII_ButtonBack,
                                    MUIA_ShowSelState,    	FALSE,
                                  End,
                                  MUIA_Group_Child,		RectangleObject,
                                  End,
                                End,
                                MUIA_Group_Child,		monthnavigator = MonthNavigatorObject,
                                  MUIA_Frame,				MUIV_Frame_Group,
                                  MUIA_FrameTitle,			"MonthNavigator.mcc",
                                  MUIA_Background,			MUII_GroupBack,
                                  MUIA_MonthNavigator_InputMode,	type,
                                  MUIA_Draggable,			TRUE,
                                End,
                                MUIA_Group_Child,		RectangleObject,
                                End,
                                MUIA_Group_Child,		HGroup,
                                  MUIA_Frame,			MUIV_Frame_Group,
                                  MUIA_Background,		MUII_GroupBack,
                                  MUIA_Group_SameHeight,	TRUE,
                                  MUIA_Group_Child,		Label2("Drop here:"),
                                  MUIA_Group_Child,		NewObject(Str_CC->mcc_Class,NULL,MUIA_Dropable,TRUE,TAG_DONE),
                                End,
                              End,
                              TAG_MORE, msg->ops_AttrList
                             );
   if (obj != NULL)
    {
     struct Win_Data *data = (struct Win_Data *)INST_DATA(cl,obj);
     ULONG month,year,day;
     char daystr[3];
     /*ULONG result;*/

     data->monthnavigator = monthnavigator;
     data->month = monthobj;
     data->year = yearobj;
     data->day = dayobj;

     get(monthnavigator,MUIA_MonthNavigator_Month,&month);
     set(monthobj,MUIA_Cycle_Active,month-1);
     get(monthnavigator,MUIA_MonthNavigator_Year,&year);
     set(yearobj,MUIA_Numeric_Default,year);
     set(yearobj,MUIA_Numeric_Value,year);
     if (dayobj != NULL)
      {
       get(monthnavigator,MUIA_MonthNavigator_Day,&day);
       sprintf(daystr,"%lu",day);
       set(dayobj,MUIA_Text_Contents,daystr);
       /*result =*/ DoMethod(monthnavigator,MUIM_Notify,MUIA_MonthNavigator_Day,MUIV_EveryTime,MUIV_Notify_Window,1,MUIM_Win_UpdateDay);
      }
     /*result =*/ DoMethod(monthobj,MUIM_Notify,MUIA_Cycle_Active,MUIV_EveryTime,MUIV_Notify_Window,1,MUIM_Win_Update);
     /*result =*/ DoMethod(yearobj,MUIM_Notify,MUIA_Numeric_Value,MUIV_EveryTime,MUIV_Notify_Window,1,MUIM_Win_Update);
     /*result =*/ DoMethod(myearobj,MUIM_Notify,MUIA_Pressed,FALSE,yearobj,2,MUIM_Numeric_Decrease,1);
     /*result =*/ DoMethod(pyearobj,MUIM_Notify,MUIA_Pressed,FALSE,yearobj,2,MUIM_Numeric_Increase,1);
    }
   return((ULONG)obj);
  }


 static ULONG SAVEDS_ASM Win_Dispatcher(REG(A0) struct IClass *cl, REG(A2) Object *obj, REG(A1) Msg msg)
  {
   switch (msg->MethodID)
    {
     case OM_NEW			: return(Win_New(cl,obj,(struct opSet *)msg));
     case MUIM_Win_Update		: return(Win_Update(cl,obj,msg));
     case MUIM_Win_UpdateDay		: return(Win_UpdateDay(cl,obj,msg));
     default				: return(DoSuperMethodA(cl,obj,msg));
    }
  }

 /* --- Application -------------------------------------------------------- */

 static ULONG App_New(struct IClass *cl, Object *obj, struct opSet *msg)
  {
   Object *win1,*win2,*win3;

   obj = (Object *)DoSuperNew(cl,obj,
                              MUIA_Application_Title,           "MonthNavigator-Demo",
                              MUIA_Application_Author,          "Kai Hofmann",
                              MUIA_Application_Copyright,       "© 1996 Kai Hofmann",
                              MUIA_Application_Version,         "$VER: MonthNavigator-Demo 2.1 " __AMIGADATE__,
                              MUIA_Application_Description,     "MonthNavigator demonstration program",
                              MUIA_Application_Base,            "MNDEMO",
                              MUIA_Application_SingleTask,      TRUE,
                              MUIA_Application_Active,          TRUE,
                              MUIA_Application_Window,		win1 = NewObject(Win_CC->mcc_Class,NULL,MUIA_Win_Type,MUIV_Win_Type_ReadOnly,TAG_DONE),
                              MUIA_Application_Window,		win2 = NewObject(Win_CC->mcc_Class,NULL,MUIA_Win_Type,MUIV_Win_Type_RelVerify,TAG_DONE),
                              MUIA_Application_Window,		win3 = NewObject(Win_CC->mcc_Class,NULL,MUIA_Win_Type,MUIV_Win_Type_Immediate,TAG_DONE),
                              TAG_MORE, msg->ops_AttrList
                             );
   if (obj != NULL)
    {
     struct App_Data *data = (struct App_Data *)INST_DATA(cl,obj);
     /*ULONG result;*/

     data->win1 = win1;
     data->win2 = win2;
     data->win3 = win3;

     /*result =*/ DoMethod(win1,MUIM_Notify,MUIA_Window_CloseRequest,TRUE,MUIV_Notify_Application,2,MUIM_Application_ReturnID,MUIV_Application_ReturnID_Quit);
     set(win1,MUIA_Window_Open,TRUE);
     /*result =*/ DoMethod(win2,MUIM_Notify,MUIA_Window_CloseRequest,TRUE,MUIV_Notify_Application,2,MUIM_Application_ReturnID,MUIV_Application_ReturnID_Quit);
     set(win2,MUIA_Window_Open,TRUE);
     /*result =*/ DoMethod(win3,MUIM_Notify,MUIA_Window_CloseRequest,TRUE,MUIV_Notify_Application,2,MUIM_Application_ReturnID,MUIV_Application_ReturnID_Quit);
     set(win3,MUIA_Window_Open,TRUE);
    }
   return((ULONG)obj);
  }


 static ULONG SAVEDS_ASM App_Dispatcher(REG(A0) struct IClass *cl, REG(A2) Object *obj, REG(A1) Msg msg)
  {
   switch (msg->MethodID)
    {
     case OM_NEW			: return(App_New(cl,obj,(struct opSet *)msg));
     default				: return(DoSuperMethodA(cl,obj,msg));
    }
  }

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

 int muiclasses_Init(void)
  {
   int retstat = RETURN_OK;

   App_CC = MUI_CreateCustomClass(NULL,MUIC_Application,NULL,sizeof(struct App_Data),App_Dispatcher);
   if (App_CC == NULL)
    {
     retstat = RETURN_ERROR;
    }
   Win_CC = MUI_CreateCustomClass(NULL,MUIC_Window,NULL,sizeof(struct Win_Data),Win_Dispatcher);
   if (Win_CC == NULL)
    {
     retstat = RETURN_ERROR;
    }
   Str_CC = MUI_CreateCustomClass(NULL,MUIC_String,NULL,sizeof(struct Str_Data),Str_Dispatcher);
   if (Str_CC == NULL)
    {
     retstat = RETURN_ERROR;
    }

   return(retstat);
  }


 int muiclasses_Cleanup(void)
  {
   int retstat = RETURN_OK;

   if (Str_CC != NULL)
    {
     if (!MUI_DeleteCustomClass(Str_CC))
      {
       retstat = RETURN_ERROR;
      }
    }
   if (Win_CC != NULL)
    {
     if (!MUI_DeleteCustomClass(Win_CC))
      {
       retstat = RETURN_ERROR;
      }
    }
   if (App_CC != NULL)
    {
     if (!MUI_DeleteCustomClass(App_CC))
      {
       retstat = RETURN_ERROR;
      }
    }

   return(retstat);
  }

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

 int gui_Init(void)
  {
   int retstat;

   MUIMasterBase = OpenLibrary((UBYTE *)MUIMASTER_NAME,(unsigned long)MUIMASTER_VMIN);
   if (MUIMasterBase != NULL)
    {
     retstat = muiclasses_Init();
     if (retstat == RETURN_OK)
      {
       App = NewObject(App_CC->mcc_Class,NULL,TAG_DONE);
       if (App == NULL)
        {
         retstat = RETURN_FAIL;
        }
      }
    }
   else
    {
     retstat = RETURN_FAIL;
    }
   return(retstat);
  }


 int gui_Cleanup(void)
  {
   int retstat = RETURN_OK;

   if (MUIMasterBase != NULL)
    {
     if (App != NULL)
      {
       MUI_DisposeObject(App);
      }
     retstat = muiclasses_Cleanup();
     if (retstat == RETURN_OK)
      {
       CloseLibrary(MUIMasterBase);
      }
    }
   return(retstat);
  }


 void gui_MainLoop(void)
  {
   if (App != NULL)
    {
     ULONG signals=0;

     while (DoMethod(App,(unsigned long)MUIM_Application_NewInput,&signals) != MUIV_Application_ReturnID_Quit)
      {
       if (signals)
        {
         signals = Wait(signals | SIGBREAKF_CTRL_C);
         if (signals & SIGBREAKF_CTRL_C)
          {
           /*ULONG result;*/

           /*result =*/ DoMethod(App,MUIM_Application_ReturnID,MUIV_Application_ReturnID_Quit);
          }
        }
      }
    }
  }

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

 void main(void)
  {
   DateBase = OpenLibrary(DATE_NAME,33);
   if (DateBase != NULL)
    {
     if (DateBase->lib_Revision >= 190)
      {
       unsigned short i;
       char mn[15];

       for (i=0;i<12;i++)
        {
         date_MonthText(i+1,mn,plocal_Locale);
         months[i] = (char *)malloc(strlen(mn)+1);
         if (months[i] != NULL)
          {
           strcpy(months[i],mn);
          }
         else
          {
           /* out of memory */
          }
        }
       months[12] = NULL;
       if (gui_Init() == RETURN_OK)
        {
         gui_MainLoop();
         if (gui_Cleanup() != RETURN_OK)
          {
 /*
           printf("gui_Cleanup error!\n");
 */
          }
        }
 /*
       else
        {
         printf("gui_Init error!\n");
        }
 */
       for (i=0;i<12;i++)
        {
         free(months[i]);
        }
      }
     CloseLibrary(DateBase);
    }
  }
