/*
//
// option.c
//
// Program options and setting
//
// Copyright (c) 1995-96 Jim Nelson.  Permission to distribute
// granted by the author.  No warranties are made on the fitness of this
// source code.
//
*/

#include "option.h"
#include "msg.h"

static uint globalOptions[OPT_I_COUNT];
static uint localOptions[OPT_I_COUNT];
uint *currentOptions;

/*
//
*/
const char *option_msg_index[] = {
    "image pre-processing",
    NULL,
    "dependency checking",
    "precious output",
    "condensed output",
    NULL,
    "markup delimiter",
    "use XML-style generator tag",
};

const char *option_msg_value[] = {
    "turned OFF",
    "turned ON",
    "turned to SEMI",
    "set to \"<\"",
    "set to \"[\"",
    "set to \"{\""
};

BOOL SetOption(TASK *task, uint index, uint value)
{
    if(task != NULL && option_msg_index[index] != NULL) {
	HtpMsg(MSG_INFO, task->infile, 
	       "%s %s", option_msg_index[index], option_msg_value[value]);
    }
    
    currentOptions[index] = value;

    if (index == OPT_I_DELIM)
    {
	switch (value)
	{
	case OPT_V_DELIM_HTML:
	    htpOpenMarkup = '<';
	    htpCloseMarkup = '>';
	    break;
	case OPT_V_DELIM_CURLY:
	    htpOpenMarkup = '{';
	    htpCloseMarkup = '}';
	    break;
	case OPT_V_DELIM_SQUARE:
	    htpOpenMarkup = '[';
	    htpCloseMarkup = ']';
	    break;
	}
    }
    return TRUE;
}


BOOL InitializeGlobalOption()
{
    /* set defaults for all options */
    globalOptions[OPT_I_IMGXY]     = OPT_V_TRUE;
    globalOptions[OPT_I_MESSAGE]   = MSG_INFO;
    globalOptions[OPT_I_DEPEND]    = OPT_V_TRUE;
    globalOptions[OPT_I_PRECIOUS]  = OPT_V_FALSE;
    globalOptions[OPT_I_CONDENSE]  = OPT_V_SEMI;
    globalOptions[OPT_I_USAGE]     = OPT_V_FALSE;
    globalOptions[OPT_I_DELIM]     = OPT_V_DELIM_HTML;
    globalOptions[OPT_I_XML]       = OPT_V_FALSE;
    currentOptions = globalOptions;

    return TRUE;
}

void DestroyGlobalOption(void)
{
}

BOOL InitializeLocalOption(void)
{
    memcpy(localOptions, globalOptions, sizeof(globalOptions));
    currentOptions = localOptions;
    return TRUE;
}

void DestroyLocalOption(void)
{
}

BOOL ParseToken(TASK *task, const char *string)
{
    static const struct {
	char *name;
	uint index, value;
    } opt[] = {
	{"IMGXY",        OPT_I_IMGXY,    OPT_V_TRUE},
	{"NOIMGXY",      OPT_I_IMGXY,    OPT_V_FALSE},
	{"VERBOSE",      OPT_I_MESSAGE,  MSG_INFO},
	{"QUIET",        OPT_I_MESSAGE,  MSG_WARNING},
	{"DEPEND",       OPT_I_DEPEND,   OPT_V_TRUE},
	{"NODEPEND",     OPT_I_DEPEND,   OPT_V_FALSE},
	{"PRECIOUS",     OPT_I_PRECIOUS, OPT_V_TRUE},
	{"NOPRECIOUS",   OPT_I_PRECIOUS, OPT_V_FALSE},
	{"CONDENSE",     OPT_I_CONDENSE, OPT_V_TRUE},
	{"SEMICONDENSE", OPT_I_CONDENSE, OPT_V_SEMI},
	{"NOCONDENSE",   OPT_I_CONDENSE, OPT_V_FALSE},
	{"DELIM=HTML",   OPT_I_DELIM,    OPT_V_DELIM_HTML},
	{"DELIM=SQUARE", OPT_I_DELIM,    OPT_V_DELIM_SQUARE},
	{"DELIM=CURLY",  OPT_I_DELIM,    OPT_V_DELIM_CURLY},
	{"XML",          OPT_I_XML,      OPT_V_TRUE},
	{"XML=FALSE",    OPT_I_XML,      OPT_V_FALSE},
	{"?",            OPT_I_USAGE,    OPT_V_TRUE},
	{"H",            OPT_I_USAGE,    OPT_V_TRUE},
	{"-HELP",        OPT_I_USAGE,    OPT_V_TRUE}
    };
    int i;
    
    for (i = 0; i < sizeof(opt) / sizeof(opt[0]); i++) {
	if (stricmp(opt[i].name, string) == 0)
	    return SetOption(task, opt[i].index, opt[i].value);
    }

    /* dont like it, but dont stop processing either */
    HtpMsg(MSG_WARNING, task != NULL ? task->infile : NULL,
	   "unknown option \"%s\" specified", string);
    return TRUE;
}

uint OptionProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext)
{
    char buff[MAX_OPTION_LENGTH];
    char *token;
    HTML_ATTRIBUTE *attrib;

    UNREF_PARAM(newPlaintext);

    /* technically, would like to avoid iterating through the HTML_MARKUP */
    /* structure for certain (future design) reasons, but really have to */
    /* for this to work */
    attrib = htmlMarkup->attrib;
    while (attrib != NULL)
    {
	token = attrib->name;
        if(attrib->value != NULL)
        {
	    StringCopy(buff, token, sizeof(buff));
            strncat(buff, "=", sizeof(buff) - 1);
            strncat(buff, attrib->value, sizeof(buff) - 1);
	    token = buff;
        }

        if(ParseToken(task, token) == FALSE)
        {
	    return MARKUP_ERROR;
        }
	attrib = attrib->next;
    }

    return DISCARD_MARKUP;
}
