/* gui.h - interface to the XFH GUI control panel by Nicola Salmoria.
   Adapted from example code by Nicola Salmoria.
   Copyright (C) 1991, 1992, 1993 Kristian Nielsen.

   This file is part of XFH, the compressing file system handler.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.            */

#include "CFS.h"

#include <exec/ports.h>
#include <exec/semaphores.h>
#include <exec/memory.h>
#include <exec/execbase.h>

#include <string.h>
#include <stdlib.h>

#include "dossupport.h"

#include "gui.h"

#define GUISIGMASK SIGBREAKF_CTRL_F
#define MAX_PACK_MODE 100

extern struct ExecBase *SysBase;


/* KS1.3 support hack to fix bug in AddSemaphore(). */
static void MyAddSemaphore(struct SignalSemaphore *sem){
  if(SysBase->LibNode.lib_Version >= 36){
    debug(("Calling KS2.0 AddSemaphore().\n"));
    AddSemaphore(sem);
  }else{
    debug(("Using KS1.3-style AddSemaphore().\n"));
    sem->ss_Link.ln_Type=NT_SIGNALSEM;
    InitSemaphore(sem);
    Forbid();
    Enqueue(&SysBase->SemaphoreList,&sem->ss_Link);
    Permit();
  }
}

/* Lock the semaphore and return a pointer to it, or NULL if it isn't there. */
/* If it can't find it, will try to create a new one; so this function will */
/* fail only due to severe low memory conditions */
/* When done with the list, the semaphore must be freed with ReleaseSemaphore() */

/* You shouldn't need to call this function directly, let UpdateXFHNode() do that for you */
static struct XFHSemaphore *GetSemaphore(glb glob){
  struct XFHSemaphore *sem;
  static UBYTE xfhsemaphorename[] = XFHSEMAPHORENAME;

  Forbid();
  if(!(sem = (struct XFHSemaphore *)FindSemaphore(xfhsemaphorename)) &&
    (sem = AllocMem(sizeof(struct XFHSemaphore) + sizeof(XFHSEMAPHORENAME)
          + 1,MEMF_CLEAR | MEMF_PUBLIC))){
    debug(("Creating new semaphore.\n"));
    sem->xfh_Length = sizeof(struct XFHSemaphore);
    sem->xfh_Semaphore.ss_Link.ln_Name = ((UBYTE *)(sem + 1));
    strcpy(sem->xfh_Semaphore.ss_Link.ln_Name,xfhsemaphorename);
    NewList(&sem->xfh_DeviceList);
    MyAddSemaphore((struct SignalSemaphore *)sem);
  }
  Permit();

  /* out of Forbid() because the semaphore is guaranteed not to be removed */
  if(sem){
    debug(("Locking semaphore...\n"));
    ObtainSemaphore((struct SignalSemaphore *)sem);
  }else{
    debug(("ERROR: No memory for new semaphore!\n"));
    OUTOFMEM;
  }
  return(sem);
}

#define bool2string(b) ( (b) ? "YES" : "NO" )

static BOOL ReadConfigSem(glb glob, struct XFHNode *node){
  char buf[256];
  
  SPrintF(buf,"STEPDOWN=%s",bool2string(node->xfh_LowMemory));
  set_option(glob, buf);
  
  if(node->xfh_AutoPack && node->xfh_PackerID){
    set_option(glob, "AUTOCOMPRESS=YES");
    if(node->xfh_PackMode > MAX_PACK_MODE){
      SPrintF(buf,"PACKMODE=%s",(char *)&node->xfh_PackerID);
    }else{
      SPrintF(buf,"PACKMODE=%s.%ld",(char *)&node->xfh_PackerID,node->xfh_PackMode);
    }
    set_option(glob, buf);
  }else{
    set_option(glob, "AUTOCOMPRESS=NO");
  }
  
  return TRUE;    /* Never fail. */
}
#undef bool2string

static BOOL SetConfigSem(glb glob, struct XFHNode *node){

  node->xfh_LowMemory = glob->stepdown;
  
  node->xfh_AutoPack  = glob->autocompress;

  if(glob->packmode){
    strncpy((char *)&node->xfh_PackerID, glob->packmode, sizeof(ULONG));
    if(glob->packmode[4] == '.'){   /* ToDo: This is rather unsafe... */
      node->xfh_PackMode = atoi(&glob->packmode[5]);
    }else{
      node->xfh_PackMode = MAX_PACK_MODE+1;
    }
  }else{
    node->xfh_PackerID = 0L;
    node->xfh_PackMode = MAX_PACK_MODE+1;
  }

  node->xfh_RootLock = c2b(glob->xrootlock);
  
  return TRUE;   /* Never fail. */
}


/* this prototype of function will either create a new node and add it to */
/* the semaphore, or, if it already exists, read the configuration from it. */
/* You will call this function:
/* a) after initialization, to read or create your node */
/* b) when you receive a CTRL_F, to read your node */
/**/
/* your main loop will look like this:
  portsignal = 1L << myport->mp_SigBit;

  recsignal = Wait(portsignal | SIGBREAKF_CTRL_F);

  if (recsignal & SIGBREAKF_CTRL_F) UpdateXFHNode();
  if (recsignal & portsignal)
  {
    while (msg = GetMsg(myport))
    {
      ...usual msg processing...
    }
  }
*/
BOOL UpdateXFHNode(glb glob){
  struct XFHSemaphore *sem;
  struct XFHNode *node;
  BOOL succ;
  
  if(sem = GetSemaphore(glob)){
    if(node=(struct XFHNode *)FindName(&sem->xfh_DeviceList,glob->devname)){
      debug(("Reading config from semaphore.\n"));
      succ = ReadConfigSem(glob, node);
    }
    else if(node = AllocMem(sizeof(struct XFHNode)
                   + strlen(glob->devname) + 1,MEMF_CLEAR|MEMF_PUBLIC)){
      debug(("Creating new entry in semaphore.\n"));
      node->xfh_Length = sizeof(struct XFHNode);
      node->xfh_Node.ln_Name = (UBYTE *)(node + 1);
      strcpy(node->xfh_Node.ln_Name,glob->devname);
      succ = SetConfigSem(glob, node);

      node->xfh_Handler = glob->dosport;
      AddTail(&sem->xfh_DeviceList,(struct Node *)node);
    }else{
      debug(("Unable to create XFHNode entry!!!.\n"));
      OUTOFMEM;
      succ = FALSE;
    }
    ReleaseSemaphore((struct SignalSemaphore *)sem);
  }else{
   debug(("Unable to obtain semaphore!!!\n"));
    succ = FALSE;
  }
  return succ;
}


ULONG guisigmask(glb glob){
   return GUISIGMASK;
}


/* End of gui.c */
