 /*
 * Variables controlling Yak settings.
 * Routines for initialisation at startup.
 */

#include <exec/types.h>
#include <dos/dos.h>
#include <dos/dosextens.h>
#include <libraries/commodities.h>
#include <proto/dos.h>
#include <string.h>

#include "yak.h"
#include "hotkey_types.h"
#include "popup.h"
#ifndef YAK_LOCALE_STRINGS
#include "yak_locale_strings.h"
#endif

extern struct DosLibrary *DOSBase;


/* local prototypes */
static BOOL __regargs FWriteLong(BPTR fh, LONG n);
static BOOL __regargs FReadLong(BPTR fh, LONG *n);
static BOOL __regargs FWriteString(BPTR fh, char *buf);
static BOOL __regargs FReadString(BPTR fh, char *buf, LONG len);
static void LoadHotKeys(void);
static void SaveHotKeys(void);

#define DEF_VOLUME      48
LONG    click_volume = DEF_VOLUME;              /* used for keyclick */

#define DEF_BLANKSECS   300
LONG    blanksecs = DEF_BLANKSECS;
LONG    blanktimeout;
LONG    blankcount;                             /* countdown to blank-time */

#define DEF_MBLANKSECS  5
LONG    mouseblank = MB_SPRITES;
LONG    mblanksecs = DEF_MBLANKSECS;
LONG    mblanktimeout;
LONG    mblankcount;                    /* countdown to mouse-blank-time */

TOGGLEDATA toggles[] = {                /* -1 means UNUSED */
        TRUE,   GDX_CTFCheck,
        TRUE,   GDX_CTBCheck,
        TRUE,   GDX_AutoCheck,
        FALSE,  GDX_KeyActCheck,
        TRUE,   GDX_ScrCycleCheck,
        FALSE,  GDX_AutoPopCheck,
        FALSE,  GDX_RMBActCheck,
        FALSE,  -1,
        FALSE,  -1,
        FALSE,  GDX_WildStarCheck,
        TRUE,   GDX_ScrActCheck
};

PATTERNDATA patterns[NUM_PATTERNS] = {
        { "#?", NULL },                 /* autoactivation screens */
        { "#?", NULL },                 /* click screens */
        { "~(Workbench)", NULL },       /* autopop windows */
        { "~(Workbench)", NULL }        /* click windows */
};

/* 1.5 format
 * Routines to load/save config file for Yak.
 * Should handle config files in upward-compatible manner.
 * File format:
 *
 *      LONG ID
 *      LONG NUM_TOGGLES
 *      BOOL toggles
 *      LONG NUM_HOTKEYS                **REMOVED @ v1.5
 *      STR hotkey1 '\n'                        :
 *              :                               :
 *      STR hotkeyN '\n'                        :
 *      LONG NUM_PATTERNS
 *      STR pattern1 '\n'
 *              :
 *      STR patternN '\n'
 *      STR popcommand '\n'             **REMOVED @ v1.5
 *      STR datefmt '\n'                **REMOVED @ v1.5
 *      LONG click_volume, blanksecs
 *      LONG mblanksecs                 **ADDED @ v1.3b
 *      LONG mouseblank                 **ADDED @ v1.3e
 */

#define CONFIG_ID       0x594b3135      /* YK15 */

/* write a LONG to a file (in binary format) - returns success*/
static BOOL __regargs
FWriteLong(BPTR fh, LONG n)
{
        return (BOOL)(FWrite(fh, (UBYTE *)&n, sizeof(LONG), 1) == 1);
}

/* read a LONG to a file (in binary format) - returns success */
static BOOL __regargs
FReadLong(BPTR fh, LONG *n)
{
        return (BOOL)(FRead(fh, (UBYTE *)n, sizeof(LONG), 1) == 1);
}

/* write a string to a file (in binary format) - returns success*/
/* '\n' is appended */
static BOOL __regargs
FWriteString(BPTR fh, char *buf)
{
        FPuts(fh, buf);
        FPutC(fh, '\n');
        return (BOOL)(IoErr() == 0);
}

/* read a string to a file (in binary format) - returns success */
/* '\n' is stripped and buf null-terminated; assumes dest large enough */
static BOOL __regargs
FReadString(BPTR fh, char *buf, LONG len)
{
        FGets(fh, buf, len-1);
        buf[strlen(buf)-1] = '\0';      /* '\n' --> '\0' */
        return (BOOL)(IoErr() == 0);
}

/* save current settings to config file */
void
SaveSettings()
{
        BPTR    fh;
        UWORD   i;

        if (fh = Open(CONFIG_FILE, MODE_NEWFILE))
        {
                FWriteLong(fh, CONFIG_ID);

                /* toggles */
                FWriteLong(fh, NUM_TOGGLES);
                for (i = 0; i < NUM_TOGGLES; i++)
                        FWrite(fh, (UBYTE *)&toggles[i].pos, sizeof(BOOL), 1);

                /* patterns */
                FWriteLong(fh, NUM_PATTERNS);
                for (i = 0; i < NUM_PATTERNS; i++)
                        FWriteString(fh, patterns[i].patstr);

                /* miscellaneous */
                FWriteLong(fh, click_volume);
                FWriteLong(fh, blanksecs);
                FWriteLong(fh, mblanksecs);
                FWriteLong(fh, mouseblank);

                Close(fh);
        }

        SaveHotKeys();
}



/* load current settings from file */
void
LoadSettings()
{
        BPTR    fh;
        UWORD   i;
        LONG    n;

        if (fh = Open(CONFIG_FILE, MODE_OLDFILE))
        {
                FReadLong(fh, &n);
                if (n == CONFIG_ID)
                {
                        /* toggles */
                        FReadLong(fh, &n);
                        for (i = 0; i < n; i++)
                                FRead(fh, (UBYTE *)&toggles[i].pos, sizeof(BOOL), 1);

                        /* patterns */
                        FReadLong(fh, &n);
                        for (i = 0; i < n; i++)
                                FReadString(fh, patterns[i].patstr, PATLEN+1);

                        /* miscellaneous */
                        FReadLong(fh, &click_volume);
                        FReadLong(fh, &blanksecs);
                        if (!FReadLong(fh, &mblanksecs))        /* none there */
                                mblanksecs = DEF_MBLANKSECS;
                        if (!FReadLong(fh, &mouseblank))        /* none there */
                                mouseblank = MB_SPRITES;
                }
                else PostError(getString(Invalid_config_file_ERR));
                Close(fh);
        }

        DeleteYakHotKeyList();          /* delete old keys */
        LoadHotKeys();                  /* and load new ones */

        /* set-up patterns */
        for (i = 0; i < NUM_PATTERNS; i++)
                InitPattern(NULL, i);

        if (wildstar)
                WILDSTARON;
        else
                wildstar = ((struct RootNode *)(DOSBase->dl_Root))->rn_Flags & RNF_WILDSTAR;
        blankcount = blanktimeout = 10*blanksecs;
        mblankcount = mblanktimeout = 10*mblanksecs;
}

/*
 *      HOTKEY FILE FORMAT
 *
 *      LONG    ID      'YKK1'
 *      LONG NUM_HOTKEYS
 *      UWORD type1
 *      UWORD opts1
 *      STR hotkey1 '\n'
 *      STR argstr1 '\n'
 *              :
 *      STR hotkeyN '\n'
 */
#define HOTKEY_ID 0x594B4B31    /* 'YKK1' */

static void
SaveHotKeys()
{
        YakHotKey *yhk;
        BPTR    fh;
        UWORD   type, i;

        if (fh = Open(HOTKEY_FILE, MODE_NEWFILE))
        {
                FWriteLong(fh, HOTKEY_ID);

                FWriteLong(fh, num_hkeys);
                for (type = 0; type < NUM_HOTKEY_TYPES; type++)
                        for (yhk = (YakHotKey *)keylist(type)->lh_Head, i = 0;
                             i < numkeys(type);
                             i++, yhk = (YakHotKey *)yhk->yhk_Node.ln_Succ)
                        {
                                FWrite(fh, (UBYTE *)&yhk->yhk_Type, sizeof(UWORD), 1);
                                FWrite(fh, (UBYTE *)&yhk->yhk_Options, sizeof(UWORD), 1);
                                FWriteString(fh, yhk->yhk_KeyDef);
                                FWriteString(fh, yhk->yhk_ArgStr ? yhk->yhk_ArgStr : "");
                        }

                Close(fh);
        }
}

static void
LoadHotKeys()
{
        YakHotKey *yhk;
        char    *buf;
        UWORD   type, opts;
        BPTR    fh;
        LONG    n;
        UWORD   i;

        if (!(buf = AllocVec(512, 0L)))
        {
                PostError(getString(No_memory_ERR));
                return;
        }

        if (fh = Open(HOTKEY_FILE, MODE_OLDFILE))
        {
                FReadLong(fh, &n);

                if (n == HOTKEY_ID)
                {
                        FReadLong(fh, &n);
                        for (i = 0; i < n; i++)
                        {
                          FRead(fh, (UBYTE *)&type, sizeof(UWORD), 1);
                          FRead(fh, (UBYTE *)&opts, sizeof(UWORD), 1);

                          if (type >= NUM_HOTKEY_TYPES)
                          {
                            /* ignore key definition */
                            FReadString(fh, buf, 512);
                            FReadString(fh, buf, 512);
                            continue;
                          }

                          if (yhk = NewYakHotKey(type))
                          {
                            yhk->yhk_Options = opts;
                            FReadString(fh, buf, 512);
                            if (ModifyYHKKeyDef(yhk, buf))
                            {
                              FReadString(fh, buf, 512);
                              if (!buf[0] || ModifyYHKArgStr(yhk, buf))
                              {
                                continue;
                              }
                            }
                          }
                          PostError(getString(Error_reading_hotkey_file_ERR));
                          DeleteYakHotKeyList();
                          break;
                        }
                }
                Close(fh);
        }
        FreeVec(buf);
}
