/*  MM2.C
 *	Looks for files on assigned device PROGDIR:
 *	    Files are MEMODATA.DAT and MMASTER.CONFIG
 */

#include <stdio.h>
#include <stdlib.h>
#include <intuition/intuition.h>
#include <dos/dos.h>
#include <time.h>
#include <ctype.h>
#include <exec/memory.h>
#include <string.h>
#include <exec/nodes.h>
#include <exec/lists.h>
#include <workbench/workbench.h>

#include "mm2.h"

/* Prototypes */
Prototype int CleanUp(void);
Prototype void Action(void);
Prototype BOOL MemoChk(BOOL);
Prototype int main(int, char **);
Prototype int wbmain(struct WBStartup *);
Prototype void Display_One(int,struct MI_Mem *);
Prototype void Display_Blank(int);
Prototype int Shrink(void);
Prototype struct Window *MainWindow(void);
Prototype struct Window *mm_w;
Prototype struct MinNode *DisplayFirst;
Prototype struct MinList *MemListPtr;
Prototype struct Gadget *mem_t_line[];
Prototype struct Gadget *m_gad_type[];
Prototype struct Gadget *m_gad_notice[];
Prototype struct Gadget *m_gad_date[];
Prototype struct Gadget *m_gad_checked[];

const char verstr[] = "\0$VER: MemoMaster 2.1 (12.9.94)";

struct IntuitionBase *IntuitionBase;
struct Library *WorkbenchBase;
struct Window *mm_w;
struct Remember *RK;
struct Gadget *mem_t_line[6];
struct Gadget *m_gad_type[6];
struct Gadget *m_gad_notice[6];
struct Gadget *m_gad_date[6];
struct Gadget *m_gad_checked[6];

int CPLine;
int Colour[4];
struct MinList *MemListPtr;
struct MinNode *DisplayFirst;

extern BOOL DataAmended;

struct Gadget gtgads[MEMOS_IN_BLOCK];
struct MM_Config mm_prefs;
struct MsgPort *port;
BOOL User_Config;
BOOL Check;
BOOL WBStart;

char date_today[10];
char MWTitle[60];

/*========================================================================
 *###======   wbmain() function   ========================================
 * DICE specific function. Program starts here if executed from WorkBench
 *========================================================================*/
int wbmain(struct WBStartup *wbs)
  {
  WBStart = TRUE;
  return main();
  }

/*==========================================================================*/
/*###======   main() function   ============================================*/
/*==========================================================================*/
main(int argc, char *argv[])
  {
  BOOL MFound;

  WorkbenchBase = OpenLibrary("workbench.library",37);
  if ((IntuitionBase=(struct IntuitionBase *)
	    OpenLibrary("intuition.library",37))==NULL)
    {
    printf("Failed to open intuition library\n");
    CleanUp();
    exit(0);
    }

/* Create a MsgPort for use when shrunk to an AppIcon */
  port = CreateMsgPort();

  MemListPtr = LoadData();
  if (!MemListPtr)
    {
    printf("Failed to create list of memos\n");
    CleanUp();
    exit(0);
    }
  Today(date_today);      /* Set up todays date string */
  sprintf(MWTitle, "MemoMaster V2.1  -  %s", date_today);
  MMWdt = MWTitle;

/* If started from WorkBench or if request on command line check for memos
 *  for today.
 */
  MFound=TRUE;
  if (stricmp(argv[1],"check")==0) Check = TRUE;
  if (stricmp(argv[1],"?")==0)
  {
    puts("MemoMaster v2.1 by Jeff Flynn, updated by Simon Dick\n"
         "    Use the CHECK argument to check for any memos for the day\n"
         "    Use no arguments to enter the memo editor.");
    CleanUp();
    exit(0);
  }
  if (((argc > 1) && (Check)) || (WBStart))
    MFound=MemoChk(FALSE);

  if (!Check)
    {
    mm_w=MainWindow();
    if(!mm_w)
      {
      printf("Failed to open MemoMaster window\n");
      CleanUp();
      exit(0);
      }
    Action();
    }
  CleanUp();
  }
/*=====================================================================*/
CleanUp()
  {
  CloseMMWindow();
  CloseDownScreen();
  FreeRemember(&RK,TRUE);
  if(port)DeleteMsgPort();
  if(IntuitionBase)CloseLibrary(IntuitionBase);
  if(WorkbenchBase)CloseLibrary(WorkbenchBase);
  return 1;
  }
/*=====================================================================*/
void Action()
{
  int x;
  BOOL finished = FALSE;
  ULONG SignalMask, Signal;

  if ((MemListPtr == NULL) || (MemListPtr->mlh_Head == NULL))
    DisplayFirst = NULL;
  else
    DisplayFirst = MemListPtr->mlh_Head;

  Display_Block(DisplayFirst);
  SignalMask = 1L << mm_w->UserPort->mp_SigBit;
  while(!finished)
  {
    Signal = Wait(SignalMask);
    if ((Signal & SignalMask) == SignalMask)
    {
      if (HandleMMIDCMP() == -1)
        finished = TRUE;
    }
  }
  if (DataAmended) x=SaveData();
}

/*========================================================================
 * BOOL MemoChk(BOOL loud)
 *   Checks through list of memos and displays those specified by date and
 *   notice values compared to todays date (supplied by caller).
 * Rather than display memos individually, which could be annoying if there
 *   several, display in blocks of 5
 * Optionally, if no memos displayed, display a message confirming that none
 *   found (parameter 'loud' is non-zero for confirmation, otherwise zero)
 * Return TRUE if one or more memos displayed, otherwise return FALSE
 */
BOOL MemoChk(BOOL loud)
  {
  char *cp_array[8]; /* One heading, up to 5 memos plus spacing */
  int cp_array_sub;
  char mtype;
  char dbuf[3];
  char ybuf[3];
  int today_days, memo_days, notice_days;
  struct MinNode *n;
  BOOL MFound = FALSE;
  char *empty = "";
  char *heading = "   Memos for today   ";
  char memobuf[5][80];

  if (LISTEMPTY)
    {
    if (loud)
      {
      cp_array[0] = "No memo for today";
      cp_array[1] = '\0';
      DisplayT(cp_array);
      }
    return FALSE;
    }

/*
 * Work out days from 1 Jan 1970 until today for comparison
 */
  dbuf[0] = *(date_today);
  dbuf[1] = *(date_today+1);
  dbuf[2] = '\0';
  ybuf[0] = *(date_today+7);
  ybuf[1] = *(date_today+8);
  ybuf[2] = '\0';
  today_days = date2days(atoi(dbuf),
			Month2Num((char *)date_today+3),
			atoi(ybuf));

  n=MemListPtr->mlh_Head;
  cp_array_sub = 2;
  while (n->mln_Succ)
    {
    dbuf[0] = ((struct MI_Mem *)n)->mim_MI.mi_Date[0];
    dbuf[1] = ((struct MI_Mem *)n)->mim_MI.mi_Date[1];
    dbuf[2] = '\0';
    mtype=((struct MI_Mem *)n)->mim_MI.mi_Type[0];
    if (( mtype == 'a') || (mtype == 'A'))
      {
      ybuf[0] = *(date_today+7);
      ybuf[1] = *(date_today+8);
      }
    else
      {
      ybuf[0] = ((struct MI_Mem *)n)->mim_MI.mi_Date[7];
      ybuf[1] = ((struct MI_Mem *)n)->mim_MI.mi_Date[8];
      }
    ybuf[2] = '\0';

    memo_days = date2days(atoi(dbuf),
		  Month2Num((char *)&(((struct MI_Mem *)n)->mim_MI.mi_Date[3])),
		  atoi(ybuf));
    if ( (memo_days < today_days) && ( (mtype == 'a') || (mtype == 'A') ))
      {
      sprintf(ybuf, "%d", atoi(ybuf)+1); /* Doesn't cater for going beyond 1999!!*/
      memo_days = date2days(atoi(dbuf),
		  Month2Num((char *)&(((struct MI_Mem *)n)->mim_MI.mi_Date[3])),
		  atoi(ybuf));
      }
    notice_days = memo_days -
		    atoi((char *)&(((struct MI_Mem *)n)->mim_MI.mi_Notice[0]));

    if ((today_days < notice_days) || (today_days > memo_days))
      {
      ; /* Do not display */
      }
    else
      {
      /* Add memo to list for display*/
      sprintf(memobuf[cp_array_sub-2], "  %s : %s  ",
		(char *)&(((struct MI_Mem *)n)->mim_MI.mi_Date[0]),
		(char *)&(((struct MI_Mem *)n)->mim_MI.mi_Text[0])   );
      cp_array[cp_array_sub] = (memobuf[cp_array_sub-2]);
      cp_array_sub++;
      if (cp_array_sub > 6)
	{
	cp_array[0] = heading;
	cp_array[1] = empty;
	cp_array[cp_array_sub] = empty;
	cp_array[cp_array_sub+1] = '\0';
	DisplayT(cp_array);
	cp_array_sub = 2;
	}
      MFound = TRUE;
      }
    n = n->mln_Succ;
    }
/* End of loop through memos */

  if (MFound)
    {
    /* Display remaining memos on display list */
    if (cp_array_sub > 2)
      {
      cp_array[0] = heading;
      cp_array[1] = empty;
      cp_array[cp_array_sub] = empty;
      cp_array[cp_array_sub+1] = '\0';
      DisplayT(cp_array);
      }
    }
  else
    {
    if (loud)
      {
      cp_array[0] = "No memo for today";
      cp_array[1] = '\0';
      DisplayT(cp_array);
      }
    }
  return MFound;

  }

/*------------------------------------------------------------------------*/
/*				 Display_One()                            */
/*		Move one memo into IntuiText structures and print	  */
/*------------------------------------------------------------------------*/
void Display_One(int gadg_no, struct MI_Mem *mim)
  {
  GT_SetGadgetAttrs(m_gad_date[gadg_no],mm_w,0,
                    GTTX_Text, mim->mim_MI.mi_Date,
                    TAG_DONE);
  GT_SetGadgetAttrs(m_gad_notice[gadg_no],mm_w,0,
                    GTTX_Text, mim->mim_MI.mi_Notice,
                    TAG_DONE);
  GT_SetGadgetAttrs(m_gad_type[gadg_no],mm_w,0,
                    GTTX_Text, mim->mim_MI.mi_Type,
                    TAG_DONE);
  GT_SetGadgetAttrs(mem_t_line[gadg_no],mm_w,0,
                    GTTX_Text, mim->mim_MI.mi_Text,
                    TAG_DONE);
  if (mim->mim_Select == 0)
    GT_SetGadgetAttrs(m_gad_checked[gadg_no],mm_w,0,
                      GA_Disabled, FALSE,
                      GTCB_Checked, FALSE,
                      TAG_DONE);
  else
    GT_SetGadgetAttrs(m_gad_checked[gadg_no],mm_w,0,
                      GA_Disabled, FALSE,
                      GTCB_Checked, TRUE,
                      TAG_DONE);
  }

/*------------------------------------------------------------------------*/
/*			       Display_Blank()                            */
/*	    Move blank 'memo' into IntuiText structures and print         */
/*------------------------------------------------------------------------*/
void Display_Blank(int gadg_no )
  {
    GT_SetGadgetAttrs(m_gad_date[gadg_no],mm_w,0,
                      GTTX_Text, "",
                      TAG_DONE);
    GT_SetGadgetAttrs(m_gad_notice[gadg_no],mm_w,0,
                      GTTX_Text, 0,
                      TAG_DONE);
    GT_SetGadgetAttrs(m_gad_type[gadg_no],mm_w,0,
                      GTTX_Text, "",
                      TAG_DONE);
    GT_SetGadgetAttrs(mem_t_line[gadg_no],mm_w,0,
                      GTTX_Text, "",
                      TAG_DONE);
    GT_SetGadgetAttrs(m_gad_checked[gadg_no],mm_w,0,
                      GTCB_Checked, FALSE,
                      GA_Disabled, TRUE,
                      TAG_DONE);
  }

/* ============================================================================
 * Function to display 'iconified' window to user and wait until user
 *   ready to continue with main window.
 *
 * Calling sequence should be something like :-
 *   CloseWindow(mm_w);
 *   Shrink();
 *   mm_w=OpenWindow(nw);
 *   if (!mm_w) panic!!!
 *   Display_Block(DisplayFirst);
 *
 */
Shrink()
  {
  struct DiskObject *dobj;
  struct AppIcon *appicon;
  struct Message *msg;

  if (!(dobj = GetDiskObject("PROGDIR:MM2")))
  {
    dobj = GetDefDiskObject(WBTOOL);
  }
 
  if (dobj)
  {
    if (port)
    {
      if (appicon = AddAppIconA(0,0,"MemoMaster",port,NULL,dobj,NULL))
      {
	CloseMMWindow();
	CloseDownScreen();
	WaitPort(port);
	Forbid();
	while (msg = GetMsg(port))
	  ReplyMsg(msg);
	RemoveAppIcon(appicon);
	Permit();
	mm_w = MainWindow();
	if (!mm_w)
	{
	  puts("Failed reopening main window");
	  FreeDiskObject(dobj);
	  CleanUp();
	  exit(0);
	}
	Display_Block(DisplayFirst);
      }
      else
	ZipWindow(MMWnd);
    }
    else
      ZipWindow(MMWnd);
  }
  else
    ZipWindow(MMWnd);

  if (dobj)
    FreeDiskObject(dobj); 
  }

/* ======================================================================
 * Function defining and opening main window
 */

struct Window *MainWindow()
{
  struct window *wnd = NULL;

  if (!SetupScreen())
    if (!OpenMMWindow())
    {
      wnd = MMWnd;
      mem_t_line[0] = MMGadgets[GDX_Message1Gad];
      mem_t_line[1] = MMGadgets[GDX_Message2Gad];
      mem_t_line[2] = MMGadgets[GDX_Message3Gad];
      mem_t_line[3] = MMGadgets[GDX_Message4Gad];
      mem_t_line[4] = MMGadgets[GDX_Message5Gad];
      mem_t_line[5] = MMGadgets[GDX_Message6Gad];
      m_gad_type[0] = MMGadgets[GDX_Type1Gad];
      m_gad_type[1] = MMGadgets[GDX_Type2Gad];
      m_gad_type[2] = MMGadgets[GDX_Type3Gad];
      m_gad_type[3] = MMGadgets[GDX_Type4Gad];
      m_gad_type[4] = MMGadgets[GDX_Type5Gad];
      m_gad_type[5] = MMGadgets[GDX_Type6Gad];
      m_gad_notice[0] = MMGadgets[GDX_Notice1Gad];
      m_gad_notice[1] = MMGadgets[GDX_Notice2Gad];
      m_gad_notice[2] = MMGadgets[GDX_Notice3Gad];
      m_gad_notice[3] = MMGadgets[GDX_Notice4Gad];
      m_gad_notice[4] = MMGadgets[GDX_Notice5Gad];
      m_gad_notice[5] = MMGadgets[GDX_Notice6Gad];
      m_gad_date[0] = MMGadgets[GDX_Date1Gad];
      m_gad_date[1] = MMGadgets[GDX_Date2Gad];
      m_gad_date[2] = MMGadgets[GDX_Date3Gad];
      m_gad_date[3] = MMGadgets[GDX_Date4Gad];
      m_gad_date[4] = MMGadgets[GDX_Date5Gad];
      m_gad_date[5] = MMGadgets[GDX_Date6Gad];
      m_gad_checked[0] = MMGadgets[GDX_Select1Gad];
      m_gad_checked[1] = MMGadgets[GDX_Select2Gad];
      m_gad_checked[2] = MMGadgets[GDX_Select3Gad];
      m_gad_checked[3] = MMGadgets[GDX_Select4Gad];
      m_gad_checked[4] = MMGadgets[GDX_Select5Gad];
      m_gad_checked[5] = MMGadgets[GDX_Select6Gad];
    }
    else
    {
      CloseMMWindow();
      CloseDownScreen();
    }
  else
    CloseDownScreen();
  return(wnd);
}
