#include <ctype.h>
#include "includes.h"
#include <dos/dostags.h>

#include "vars.h"

/* This file contains empty template routines that
 * the IDCMP handler will call uppon. Fill out these
 * routines with your code or use them as a reference
 * to create your program.
 */

void DoAbout( void )
{
  rtEZRequestTags("Associate, A nice WB Util By Dominic Clifton - Hydra/LSD\n"
                  "1995 Deluxe Software Ltd.\n\n"
                  "This program is FreeWare! so spread and use it\n"
                  "but do NOT modify it in ANY way at all.\n"
                  "\n"
                  "Permission is GRANTED to use this in\n"
                  "any commercial package, it can also be\n"
                  "included on coverdisks and such like\n",
                  "Cool!",
                  NULL,NULL,RTGS_Flags, GSREQF_CENTERTEXT,
                  RT_Window,AssociateWnd,TAG_END);
}

BOOL SelectFile(char *Filename,char *title,char *wildcards)
{
  char *dirname;
  short chars;
  BOOL retval=FALSE;
  strcpy(tmpstr,FilePart(Filename));

  chars=(short)((int)PathPart(Filename)-(int)Filename);
  if (dirname=AllocMem(chars+1,MEMF_PUBLIC|MEMF_CLEAR))
  {
    strncpy(dirname,Filename,chars);
    rtChangeReqAttr(filereq,RTFI_MatchPat,wildcards,
                            RTFI_Dir, dirname,
                            TAG_DONE);

    if (rtFileRequest (filereq, tmpstr, title,RTFI_Flags,FREQF_PATGAD,TAG_END))
    {
      strcpy(Filename,filereq->Dir);
      AddPart(Filename,tmpstr,MAX_TEMP_STR_LEN);
      retval=TRUE;
    }
    FreeMem(dirname,chars+1);
  }
  return(retval);
}

struct TypeNode *FindTypeNode( void )
{
  struct TypeNode *node=NULL;
  LONG num;

#ifdef KS30
  if (1==GT_GetGadgetAttrs(AssociateGadgets[GD_TypeList],AssociateWnd,NULL,
                    GTLV_Selected,&num,
                    TAG_DONE))
  {
#endif

#ifdef KS20
  num=LastTypeClicked;
#endif
    if (num>=0)
    {
      node=(struct TypeNode *) GetNode(typelist,num);
    }
#ifdef KS30
  }
#endif
  return(node);
}

void UpdateLists( void )
{
  GT_SetGadgetAttrs(AssociateGadgets[GD_TypeList], AssociateWnd, NULL,
                    GTLV_Labels, (ULONG)typelist,
                    TAG_END);

  if (temptnode=FindTypeNode())
  {
#ifdef KS20
    LastNamePClicked=-1;
    LastFilePClicked=-1;
#endif
    GT_SetGadgetAttrs(AssociateGadgets[GD_NamePList], AssociateWnd, NULL,
                      GTLV_Labels, (ULONG)temptnode->nameplist,
                      TAG_END);
    GT_SetGadgetAttrs(AssociateGadgets[GD_FilePList], AssociateWnd, NULL,
                      GTLV_Labels, (ULONG)temptnode->fileplist,
                      TAG_END);
    GT_SetGadgetAttrs(AssociateGadgets[GD_IconStr], AssociateWnd, NULL,
                      GA_Disabled, FALSE,
                      GTST_String, temptnode->IconName,
                      TAG_END);
    GT_SetGadgetAttrs(AssociateGadgets[GD_IconRun],AssociateWnd,NULL,
                      GA_Disabled, FALSE,
                      GTCB_Checked,temptnode->RunInfo,
                      TAG_DONE);
    GT_SetGadgetAttrs(AssociateGadgets[GD_IconInfo],AssociateWnd,NULL,
                      GA_Disabled, FALSE,
                      TAG_DONE);
  }
  else // blank the lists..
  {
    GT_SetGadgetAttrs(AssociateGadgets[GD_NamePList], AssociateWnd, NULL,
                      GTLV_Labels, NULL,
                      TAG_END);
    GT_SetGadgetAttrs(AssociateGadgets[GD_FilePList], AssociateWnd, NULL,
                      GTLV_Labels, NULL,
                      TAG_END);
    GT_SetGadgetAttrs(AssociateGadgets[GD_IconStr], AssociateWnd, NULL,
                      GA_Disabled, TRUE,
                      GTST_String, NULL,
                      TAG_END);
    GT_SetGadgetAttrs(AssociateGadgets[GD_IconRun],AssociateWnd,NULL,
                      GA_Disabled, TRUE,
                      GTCB_Checked,FALSE,
                      TAG_DONE);
    GT_SetGadgetAttrs(AssociateGadgets[GD_IconInfo],AssociateWnd,NULL,
                      GA_Disabled, TRUE,
                      TAG_DONE);
  }
}

int TypeListClicked( void )
{
  /* routine when gadget "File Type" is clicked. */

#ifdef KS20
  LastTypeClicked=AssociateMsg.Code;
#endif
  UpdateLists();
  return(1);
}

int NamePListClicked( void )
{
  /* routine when gadget "Name Patterns" is clicked. */
#ifdef KS20
  LastNamePClicked=AssociateMsg.Code;
#endif
  return(1);
}

int FilePListClicked( void )
{
  /* routine when gadget "File Patterns" is clicked. */
#ifdef KS20
  LastFilePClicked=AssociateMsg.Code;
#endif
  return(1);
}

int IconPickClicked( void )
{
  /* routine when gadget "" is clicked. */

  if (temptnode=FindTypeNode())
  {
    if (SelectFile(temptnode->IconName,"Select an Icon!","#?.info"))
    {
      GT_SetGadgetAttrs(AssociateGadgets[GD_IconStr], AssociateWnd, NULL,
                        GTST_String, temptnode->IconName,
                        TAG_END);
    }
  }
  return(1);
}

int IconStrClicked( void )
{
  /* routine when gadget "Icon Filename" is clicked. */

  if (temptnode=FindTypeNode())
  {
    strcpy(temptnode->IconName,GetString(AssociateGadgets[GD_IconStr]));
  }
  return(1);
}

void addterm(char *s)
{
  if (s[strlen(s)-1]!=':' && s[strlen(s)-1]!='/') strcat(s,"/");
}

char *getparent(char *s)
{
  int l;
  char *outname;

  if (outname=strdup(s))
  {
    addterm(outname);
    l=strlen(outname);

    if (outname[l-1]=='/')
    {
      l--;
      while (outname[l-1]!='/' && outname[l-1]!=':') l--;
      outname[l]='\0';
    }
  }
  return(outname);
}

char *upcase(char *str)
{
  // converts str into uppercase and returns a pointer to a new
  // string.
  // returns NULL if it fails.

  char *outstr;
  short loop;

  if (outstr=strdup(str))
  {
    for (loop=0;str[loop];loop++) outstr[loop]=toupper(str[loop]);
  }
  return(outstr);
}

short position(char *substr,char *str)
{
  // returns an character offset of a substring in a string
  // this version is CASE SENSITIVE
  // returns -1 if substring not found in the string

  char *whstr;
  return((short)((whstr=strstr(str,substr)) ? (short)((LONG)whstr-(LONG)str) : -1));
}

short iposition(char *substr,char *str)
{
  // returns an character offset of a substring in a string
  // this version is CASE INSENSITIVE
  // returns -1 if substring not found in the string
  //      or -2 if memory allocation error

  short where=-2;
  char *isubstr,*istr;

  if (isubstr=upcase(substr))
  {
    if (istr=upcase(str))
    {
      where=position(isubstr,istr);
      free(isubstr);
    }
    free(istr);
  }
  return(where);
}

void removeinfo( char *str)
{
  short slen;

  // i know this looks tacky but it's fast and small... :-)

  slen=strlen(str)-1;
  if (toupper(str[slen])=='O' &&
      toupper(str[slen-1])=='F' &&
      toupper(str[slen-2])=='N' &&
      toupper(str[slen-3])=='I' &&
      toupper(str[slen-4])=='.')
  {
    str[slen-4]=0;
  }


  if (stricmp(str+(strlen(str)-5),".info")==0) puts("moocow!");
}

void DoInfo( char *fname)
{
  BPTR FL;
  char *drawername;
  char *filename;
  char *wholestr;

  if (WorkbenchBase->lib_Version>=39)
  {
    if (wholestr=strdup(fname))
    {
      if (wholestr[0])
      {
        removeinfo(wholestr);
        drawername=getparent(wholestr);
        filename=FilePart(wholestr);
        if (FL=Lock(drawername,ACCESS_READ))
        {
          WBInfo(FL,filename,Scr);
          UnLock(FL);
        }
        free(drawername);
      }
      free(wholestr);
    }
  }
  else rtEZRequest("Sorry, You Need WB 3.0+ to access Icon Info","Damn!",NULL,NULL);
}

int IconInfoClicked( void )
{
  /* routine when gadget "Icon Info" is clicked. */
  if (temptnode=FindTypeNode())
  {
    if (temptnode->IconName)
    {
      DoInfo(temptnode->IconName);
    }
  }
  return(1);
}
int IconRunClicked( void )
{
  /* routine when gadget "Run Info When activated" is clicked. */

  if (temptnode=FindTypeNode())
  {
    GT_GetGadgetAttrs(AssociateGadgets[GD_IconRun],AssociateWnd,NULL,
                      GTCB_Checked,&temptnode->RunInfo,
                      TAG_DONE);
  }
  return(1);
}

int TypeAddClicked( void )
{
  /* routine when gadget "Add" is clicked. */

  char *tmpstr;

  if (tmpstr=AllocMem(256,MEMF_PUBLIC|MEMF_CLEAR)) //MEMF_CLEAR to nullify string..
  {
    if (rtGetString(tmpstr,255, "Enter File Type Name", NULL,RT_Window,AssociateWnd, TAG_END))
    {
      NewTypeNode(typelist,tmpstr);
      UpdateLists();
    }
    FreeMem(tmpstr,256);
  }
  return(1);
}

int TypeDeleteClicked( void )
{
  /* routine when gadget "Delete" is clicked. */
  if (temptnode=FindTypeNode())
  {
    if (rtEZRequest("Sure ?","Yeah!|No Way!",NULL,NULL))
    {
      FreeTypeNode(temptnode);
      Remove((struct Node*)temptnode);
      FreeMem(temptnode,sizeof(struct TypeNode));
      UpdateLists();
    }
  }
  return(1);
}

int NamePAddClicked( void )
{
  /* routine when gadget "Add" is clicked. */
  char *tmpstr;
  if (temptnode=FindTypeNode())
  {
    if (tmpstr=AllocMem(256,MEMF_PUBLIC|MEMF_CLEAR)) //MEMF_CLEAR to nullify string..
    {
      if (rtGetString(tmpstr,255, "Enter Name Match String", NULL,RT_Window,AssociateWnd, TAG_END))
      {
        NewNameNode(temptnode->nameplist,tmpstr);
        GT_SetGadgetAttrs(AssociateGadgets[GD_NamePList], AssociateWnd, NULL,
                          GTLV_Labels, (ULONG)temptnode->nameplist,
                          TAG_END);
      }
    }
    FreeMem(tmpstr,256);
  }
  return(1);
}

int NamePDeleteClicked( void )
{
  /* routine when gadget "Delete" is clicked. */

  LONG num;
  struct Node *node;

  if (temptnode=FindTypeNode())
  {
#ifdef KS30
    if (1==GT_GetGadgetAttrs(AssociateGadgets[GD_NamePList],AssociateWnd,NULL,
                    GTLV_Selected,&num,
                    TAG_DONE))
    {
#endif

#ifdef KS20
    num=LastNamePClicked;
#endif

      if (num>=0)
      {
        node=GetNode(temptnode->nameplist,num);
        FreeNameNode(node);
        Remove(node);
        FreeMem(node,sizeof(struct Node));
        UpdateLists();
      }
#ifdef KS30
    }
#endif
  }

  return(1);
}

int FilePAddClicked( void )
{
  /* routine when gadget "Add" is clicked. */

  char *tmpstr;

  if (temptnode=FindTypeNode())
  {
    if (tmpstr=AllocMem(256,MEMF_PUBLIC|MEMF_CLEAR)) //MEMF_CLEAR to nullify string..
    {
      if (rtGetString(tmpstr,255, "Enter File Match String", NULL,RT_Window,AssociateWnd, TAG_END))
      {
        NewNameNode(temptnode->fileplist,tmpstr);
        GT_SetGadgetAttrs(AssociateGadgets[GD_FilePList], AssociateWnd, NULL,
                          GTLV_Labels, (ULONG)temptnode->fileplist,
                          TAG_END);
      }
    }
    FreeMem(tmpstr,256);
  }
  return(1);
}

int FilePDeleteClicked( void )
{
  /* routine when gadget "Delete" is clicked. */
  LONG num;
  struct Node *node;

  if (temptnode=FindTypeNode())
  {
#ifdef KS30

    if (1==GT_GetGadgetAttrs(AssociateGadgets[GD_FilePList],AssociateWnd,NULL,
                    GTLV_Selected,&num,
                    TAG_DONE))
    {
#endif
#ifdef KS20
    num=LastFilePClicked;
#endif
      if (num>=0)
      {
        node=GetNode(temptnode->fileplist,num);
        FreeNameNode(node);
        Remove(node);
        FreeMem(node,sizeof(struct Node));
        UpdateLists();
      }
#ifdef KS30
    }
#endif
  }
  return(1);
}

int SaveClicked( void )
{
  /* routine when gadget "Save" is clicked. */
  SavePrefs();
  return(0);
}

int HelpClicked( void )
{
  /* routine when gadget "Help" is clicked. */
  static ULONG sysargs[] =
  {
    SYS_Input,NULL,
    SYS_Output,NULL,
    SYS_Asynch,FALSE,
    SYS_UserShell,TRUE,
    NP_Priority,0L,
    TAG_DONE
  };

  if (SystemTagList("AmigaGuide Associate.Guide",(struct TagItem *)sysargs)!=0)
  {
    if (SystemTagList("AmigaGuide progdir:Associate.Guide",(struct TagItem *)sysargs)!=0)
    {
      rtEZRequest("Sorry, I Can't find AmigaGuide\n"
                  "and/or the Assoiciate.Guide file",okstr,NULL,(struct TagItem *)&reqtags,NULL);
    }
  }
  return(1);
}

int OKClicked( void )
{
  /* routine when gadget "OK" is clicked. */
  return(0);
}

int TypeEditClicked( void )
{
  /* routine when gadget "Edit" is clicked. */
  LONG num;
  struct Node *node;
#ifdef KS30

  if (1==GT_GetGadgetAttrs(AssociateGadgets[GD_TypeList],AssociateWnd,NULL,
                  GTLV_Selected,&num,
                  TAG_DONE))
  {
#endif
#ifdef KS20
  num=LastTypeClicked;
#endif
    if (num>=0)
    {
      node=GetNode(typelist,num);
      if (rtGetString(node->ln_Name,255, "Edit Filetype Name", NULL,RT_Window,AssociateWnd, TAG_END))
      {
        GT_SetGadgetAttrs(AssociateGadgets[GD_TypeList], AssociateWnd, NULL,
                          GTLV_Labels, (ULONG)typelist,
                          TAG_END);
      }
#ifdef KS30
    }
#endif
  }
  return(1);
}

int NamePEditClicked( void )
{
  /* routine when gadget "Edit" is clicked. */
  LONG num;
  struct Node *node;

  if (temptnode=FindTypeNode())
  {
#ifdef KS30
    if (1==GT_GetGadgetAttrs(AssociateGadgets[GD_NamePList],AssociateWnd,NULL,
                    GTLV_Selected,&num,
                    TAG_DONE))
    {
#endif
#ifdef KS20
    num=LastNamePClicked;
#endif
      if (num>=0)
      {
        node=GetNode(temptnode->nameplist,num);
        if (rtGetString(node->ln_Name,255, "Edit Match String", NULL,RT_Window,AssociateWnd, TAG_END))
        {
          GT_SetGadgetAttrs(AssociateGadgets[GD_NamePList], AssociateWnd, NULL,
                            GTLV_Labels, (ULONG)temptnode->nameplist,
                            TAG_END);
        }
      }
#ifdef KS30
    }
#endif
  }
  return(1);
}

int FilePEditClicked( void )
{
  /* routine when gadget "Edit" is clicked. */
  LONG num;
  struct Node *node;

  if (temptnode=FindTypeNode())
  {
#ifdef KS30
    if (1==GT_GetGadgetAttrs(AssociateGadgets[GD_FilePList],AssociateWnd,NULL,
                    GTLV_Selected,&num,
                    TAG_DONE))
    {
#endif
#ifdef KS20
      num=LastFilePClicked;
#endif
      if (num>=0)
      {
        node=GetNode(temptnode->fileplist,num);
        if (rtGetString(node->ln_Name,255, "Edit Match String", NULL,RT_Window,AssociateWnd, TAG_END))
        {
          GT_SetGadgetAttrs(AssociateGadgets[GD_FilePList], AssociateWnd, NULL,
                            GTLV_Labels, (ULONG)temptnode->fileplist,
                            TAG_END);
        }
      }
#ifdef KS30
    }
#endif
  }
  return(1);
}

int AssociateItem0( void )
{
  /* routine when (sub)item "About" is selected. */
  DoAbout();
  return(1);
}

int AssociateItem1( void )
{
  /* routine when (sub)item "Quit!" is selected. */
  done=TRUE;
  return(0);
}

int AssociateCloseWindow( void )
{
  /* routine for "IDCMP_CLOSEWINDOW". */
  return(0);
}


int PickTypeClicked( void )
{
  /* routine when gadget "" is clicked. */
#ifdef KS20
  LastPickClicked=PickMsg.Code;
#endif
  if (DoubleClick(LastSec,LastMic,PickMsg.Seconds,PickMsg.Micros))
  {
    return(PickOkClicked());
  }
  else
  {
    LastSec=PickMsg.Seconds;
    LastMic=PickMsg.Micros;
    return(1);
  }
}

int PickOkClicked( void )
{
  /* routine when gadget "Ok!" is clicked. */

  LONG num;
  int retval=1;
#ifdef KS30
  if (1==GT_GetGadgetAttrs(PickGadgets[GD_PickType],PickWnd,NULL,
                           GTLV_Selected,&num,
                           TAG_DONE))
  {
#endif
#ifdef KS20
      num=LastPickClicked;
#endif
    if (num>=0)
    {
      temptnode=(struct TypeNode *) GetNode(typelist,num);
      retval=0;
    }
#ifdef KS30
  }
#endif
  return(retval);
}

int PickCancelClicked( void )
{
  /* routine when gadget "Cancel" is clicked. */
  temptnode=NULL;
  return(0);
}

int PickCloseWindow( void )
{
  /* routine for "IDCMP_CLOSEWINDOW". */
  // hmm.  does this funtion get called when there is no close gadget ?
  return(0);
}

int PickVanillaKey( void )
{
  /* routine for "IDCMP_VANILLAKEY". */
  switch (PickMsg.Code)
  {
    case 13:
      return(PickOkClicked());
      break;
    case 27:
      temptnode=NULL;
      return(0);
      break;
  }
  return(1);
}
