add new option API and implementation
This commit is contained in:
parent
977452b2ba
commit
a2769ec68b
|
@ -0,0 +1,697 @@
|
|||
/*
|
||||
* Copyright 2012 Vincent Sanders <vince@netsurf-browser.org>
|
||||
*
|
||||
* This file is part of NetSurf, http://www.netsurf-browser.org/
|
||||
*
|
||||
* NetSurf 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; version 2 of the License.
|
||||
*
|
||||
* NetSurf 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* Option reading and saving (implementation).
|
||||
*
|
||||
* Options are stored in the format key:value, one per line.
|
||||
*
|
||||
* For bool options, value is "0" or "1".
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "utils/errors.h"
|
||||
#include "utils/log.h"
|
||||
#include "utils/utils.h"
|
||||
#include "utils/nsoption.h"
|
||||
|
||||
struct nsoption_s *nsoptions = NULL;
|
||||
struct nsoption_s *nsoptions_default = NULL;
|
||||
|
||||
#define NSOPTION_BOOL(NAME, DEFAULT) \
|
||||
{ #NAME, sizeof(#NAME) - 1, OPTION_BOOL, { .b = DEFAULT } },
|
||||
|
||||
#define NSOPTION_STRING(NAME, DEFAULT) \
|
||||
{ #NAME, sizeof(#NAME) - 1, OPTION_STRING, { .cs = DEFAULT } },
|
||||
|
||||
#define NSOPTION_INTEGER(NAME, DEFAULT) \
|
||||
{ #NAME, sizeof(#NAME) - 1, OPTION_INTEGER, { .i = DEFAULT } },
|
||||
|
||||
#define NSOPTION_UINT(NAME, DEFAULT) \
|
||||
{ #NAME, sizeof(#NAME) - 1, OPTION_UINT, { .u = DEFAULT } },
|
||||
|
||||
#define NSOPTION_COLOUR(NAME, DEFAULT) \
|
||||
{ #NAME, sizeof(#NAME) - 1, OPTION_COLOUR, { .c = DEFAULT } },
|
||||
|
||||
struct nsoption_s defaults[] = {
|
||||
#include "desktop/options.h"
|
||||
|
||||
#if defined(riscos)
|
||||
#include "riscos/options.h"
|
||||
#elif defined(nsgtk)
|
||||
#include "gtk/options.h"
|
||||
#elif defined(nsbeos)
|
||||
#include "beos/options.h"
|
||||
#elif defined(nsamiga)
|
||||
#include "amiga/options.h"
|
||||
#elif defined(nsframebuffer)
|
||||
#include "framebuffer/options.h"
|
||||
#elif defined(nsatari)
|
||||
#include "atari/options.h"
|
||||
#elif defined(nsmonkey)
|
||||
#include "monkey/options.h"
|
||||
#endif
|
||||
{ NULL, 0, OPTION_INTEGER, { 0 } }
|
||||
};
|
||||
|
||||
#undef NSOPTION_BOOL
|
||||
#undef NSOPTION_STRING
|
||||
#undef NSOPTION_INTEGER
|
||||
#undef NSOPTION_UINT
|
||||
#undef NSOPTION_COLOUR
|
||||
|
||||
/**
|
||||
* Set an option value based on a string
|
||||
*/
|
||||
static bool
|
||||
strtooption(const char *value, struct nsoption_s *option)
|
||||
{
|
||||
bool ret = true;
|
||||
colour rgbcolour; /* RRGGBB */
|
||||
|
||||
switch (option->type) {
|
||||
case OPTION_BOOL:
|
||||
option->value.b = (value[0] == '1');
|
||||
break;
|
||||
|
||||
case OPTION_INTEGER:
|
||||
option->value.i = atoi(value);
|
||||
break;
|
||||
|
||||
case OPTION_UINT:
|
||||
option->value.u = strtoul(value, NULL, 0);
|
||||
break;
|
||||
|
||||
case OPTION_COLOUR:
|
||||
sscanf(value, "%x", &rgbcolour);
|
||||
option->value.c = (((0x000000FF & rgbcolour) << 16) |
|
||||
((0x0000FF00 & rgbcolour) << 0) |
|
||||
((0x00FF0000 & rgbcolour) >> 16));
|
||||
break;
|
||||
|
||||
case OPTION_STRING:
|
||||
if (option->value.s != NULL) {
|
||||
free(option->value.s);
|
||||
}
|
||||
|
||||
if (*value == 0) {
|
||||
/* do not allow empty strings in text options */
|
||||
option->value.s = NULL;
|
||||
} else {
|
||||
option->value.s = strdup(value);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* validate options to sane values */
|
||||
static void nsoption_validate(struct nsoption_s *opts)
|
||||
{
|
||||
if (opts[NSOPTION_font_size].value.i < 50) {
|
||||
opts[NSOPTION_font_size].value.i = 50;
|
||||
}
|
||||
|
||||
if (opts[NSOPTION_font_size].value.i > 1000) {
|
||||
opts[NSOPTION_font_size].value.i = 1000;
|
||||
}
|
||||
|
||||
if (opts[NSOPTION_font_min_size].value.i < 10) {
|
||||
opts[NSOPTION_font_min_size].value.i = 10;
|
||||
}
|
||||
|
||||
if (opts[NSOPTION_font_min_size].value.i > 500) {
|
||||
opts[NSOPTION_font_min_size].value.i = 500;
|
||||
}
|
||||
|
||||
if (opts[NSOPTION_memory_cache_size].value.i < 0) {
|
||||
opts[NSOPTION_memory_cache_size].value.i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/** Output choices to file stream
|
||||
*
|
||||
* @param fp the file stream to write to
|
||||
* @param opts The options table to write
|
||||
* @param defs the default value table to compare with.
|
||||
* @param all Output all entries not just ones changed from defaults
|
||||
*/
|
||||
static nserror
|
||||
nsoption_output(FILE *fp,
|
||||
struct nsoption_s *opts,
|
||||
struct nsoption_s *defs,
|
||||
bool all)
|
||||
{
|
||||
unsigned int entry;
|
||||
for (entry = 0; entry < NSOPTION_LISTEND; entry++) {
|
||||
switch (opts[entry].type) {
|
||||
case OPTION_BOOL:
|
||||
if (all ||
|
||||
(opts[entry].value.b != defs[entry].value.b)) {
|
||||
fprintf(fp, "%s:%c\n",
|
||||
opts[entry].key,
|
||||
opts[entry].value.b ? '1' : '0');
|
||||
}
|
||||
break;
|
||||
|
||||
case OPTION_INTEGER:
|
||||
if (all ||
|
||||
(opts[entry].value.i != defs[entry].value.i)) {
|
||||
fprintf(fp, "%s:%i\n",
|
||||
opts[entry].key,
|
||||
opts[entry].value.i);
|
||||
}
|
||||
break;
|
||||
|
||||
case OPTION_UINT:
|
||||
if (all ||
|
||||
(opts[entry].value.u != defs[entry].value.u)) {
|
||||
fprintf(fp, "%s:%u\n",
|
||||
opts[entry].key,
|
||||
opts[entry].value.u);
|
||||
}
|
||||
break;
|
||||
|
||||
case OPTION_COLOUR:
|
||||
if (all ||
|
||||
(opts[entry].value.c != defs[entry].value.c)) {
|
||||
colour rgbcolour; /* RRGGBB */
|
||||
rgbcolour = (((0x000000FF & opts[entry].value.c) << 16) |
|
||||
((0x0000FF00 & opts[entry].value.c) << 0) |
|
||||
((0x00FF0000 & opts[entry].value.c) >> 16));
|
||||
fprintf(fp, "%s:%06x\n",
|
||||
opts[entry].key,
|
||||
rgbcolour);
|
||||
}
|
||||
break;
|
||||
|
||||
case OPTION_STRING:
|
||||
/* output the key if:
|
||||
* - defs is null.
|
||||
* - default is null but value is not.
|
||||
* - default and value pointers are different
|
||||
* (acts as a null check because of previous check)
|
||||
* and the strings content differ.
|
||||
*/
|
||||
if (all ||
|
||||
((defs[entry].value.s == NULL) &&
|
||||
(opts[entry].value.s != NULL)) ||
|
||||
((defs[entry].value.s != opts[entry].value.s) &&
|
||||
(strcmp(opts[entry].value.s, defs[entry].value.s) != 0))) {
|
||||
fprintf(fp, "%s:%s\n",
|
||||
opts[entry].key,
|
||||
((opts[entry].value.s == NULL) ||
|
||||
(*opts[entry].value.s == 0)) ? "" : opts[entry].value.s);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return NSERROR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Output an option value into a string, in HTML format.
|
||||
*
|
||||
* \param option The option to output the value of.
|
||||
* \param size The size of the string buffer.
|
||||
* \param pos The current position in string
|
||||
* \param string The string in which to output the value.
|
||||
* \return The number of bytes written to string or -1 on error
|
||||
*/
|
||||
static size_t
|
||||
nsoption_output_value_html(struct nsoption_s *option,
|
||||
size_t size,
|
||||
size_t pos,
|
||||
char *string)
|
||||
{
|
||||
size_t slen = 0; /* length added to string */
|
||||
colour rgbcolour; /* RRGGBB */
|
||||
|
||||
switch (option->type) {
|
||||
case OPTION_BOOL:
|
||||
slen = snprintf(string + pos,
|
||||
size - pos,
|
||||
"%s",
|
||||
option->value.b ? "true" : "false");
|
||||
break;
|
||||
|
||||
case OPTION_INTEGER:
|
||||
slen = snprintf(string + pos,
|
||||
size - pos,
|
||||
"%i",
|
||||
option->value.i);
|
||||
break;
|
||||
|
||||
case OPTION_UINT:
|
||||
slen = snprintf(string + pos,
|
||||
size - pos,
|
||||
"%u",
|
||||
option->value.u);
|
||||
break;
|
||||
|
||||
case OPTION_COLOUR:
|
||||
rgbcolour = (((0x000000FF & option->value.c) << 16) |
|
||||
((0x0000FF00 & option->value.c) << 0) |
|
||||
((0x00FF0000 & option->value.c) >> 16));
|
||||
slen = snprintf(string + pos,
|
||||
size - pos,
|
||||
"<span style=\"background-color: #%06x; "
|
||||
"color: #%06x;\">#%06x</span>",
|
||||
rgbcolour,
|
||||
(~rgbcolour) & 0xffffff,
|
||||
rgbcolour);
|
||||
break;
|
||||
|
||||
case OPTION_STRING:
|
||||
if (option->value.s != NULL) {
|
||||
slen = snprintf(string + pos, size - pos, "%s",
|
||||
option->value.s);
|
||||
} else {
|
||||
slen = snprintf(string + pos, size - pos,
|
||||
"<span class=\"null-content\">NULL"
|
||||
"</span>");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return slen;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Output an option value into a string, in plain text format.
|
||||
*
|
||||
* \param option The option to output the value of.
|
||||
* \param size The size of the string buffer.
|
||||
* \param pos The current position in string
|
||||
* \param string The string in which to output the value.
|
||||
* \return The number of bytes written to string or -1 on error
|
||||
*/
|
||||
static size_t
|
||||
nsoption_output_value_text(struct nsoption_s *option,
|
||||
size_t size,
|
||||
size_t pos,
|
||||
char *string)
|
||||
{
|
||||
size_t slen = 0; /* length added to string */
|
||||
colour rgbcolour; /* RRGGBB */
|
||||
|
||||
switch (option->type) {
|
||||
case OPTION_BOOL:
|
||||
slen = snprintf(string + pos,
|
||||
size - pos,
|
||||
"%c",
|
||||
option->value.b ? '1' : '0');
|
||||
break;
|
||||
|
||||
case OPTION_INTEGER:
|
||||
slen = snprintf(string + pos,
|
||||
size - pos,
|
||||
"%i",
|
||||
option->value.i);
|
||||
break;
|
||||
|
||||
case OPTION_UINT:
|
||||
slen = snprintf(string + pos,
|
||||
size - pos,
|
||||
"%u",
|
||||
option->value.u);
|
||||
break;
|
||||
|
||||
case OPTION_COLOUR:
|
||||
rgbcolour = (((0x000000FF & option->value.c) << 16) |
|
||||
((0x0000FF00 & option->value.c) << 0) |
|
||||
((0x00FF0000 & option->value.c) >> 16));
|
||||
slen = snprintf(string + pos, size - pos, "%06x", rgbcolour);
|
||||
break;
|
||||
|
||||
case OPTION_STRING:
|
||||
if (option->value.s != NULL) {
|
||||
slen = snprintf(string + pos,
|
||||
size - pos,
|
||||
"%s",
|
||||
option->value.s);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return slen;
|
||||
}
|
||||
|
||||
/* exported interface documented in utils/nsoption.h */
|
||||
nserror
|
||||
nsoption_init(nsoption_set_default_t *set_defaults,
|
||||
struct nsoption_s **popts,
|
||||
struct nsoption_s **pdefs)
|
||||
{
|
||||
nserror ret;
|
||||
struct nsoption_s *src;
|
||||
struct nsoption_s *dst;
|
||||
struct nsoption_s *opts;
|
||||
|
||||
/* update the default table */
|
||||
if (set_defaults != NULL) {
|
||||
nsoptions = &defaults[0];
|
||||
ret = set_defaults(&defaults[0]);
|
||||
|
||||
if (ret != NSERROR_OK) {
|
||||
nsoptions = NULL;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
opts = malloc(sizeof(defaults));
|
||||
if (opts == NULL) {
|
||||
return NSERROR_NOMEM;
|
||||
}
|
||||
|
||||
/* copy the default values into the working set */
|
||||
src = &defaults[0];
|
||||
dst = opts;
|
||||
|
||||
while (src->key != NULL) {
|
||||
dst->key = src->key;
|
||||
dst->key_len = src->key_len;
|
||||
dst->type = src->type;
|
||||
if ((src->type == OPTION_STRING) && (src->value.s != NULL)) {
|
||||
dst->value.s = strdup(src->value.s);
|
||||
} else {
|
||||
dst->value = src->value;
|
||||
}
|
||||
src++;
|
||||
dst++;
|
||||
}
|
||||
dst->key = src->key;
|
||||
|
||||
/* return values if wanted */
|
||||
if (popts != NULL) {
|
||||
*popts = opts;
|
||||
} else {
|
||||
nsoptions = opts;
|
||||
}
|
||||
|
||||
if (pdefs != NULL) {
|
||||
*pdefs = &defaults[0];
|
||||
}
|
||||
|
||||
return NSERROR_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* exported interface documented in utils/nsoption.h */
|
||||
nserror
|
||||
nsoption_read(const char *path, struct nsoption_s *opts)
|
||||
{
|
||||
char s[100];
|
||||
FILE *fp;
|
||||
|
||||
if (path == NULL) {
|
||||
return NSERROR_BAD_PARAMETER;
|
||||
}
|
||||
|
||||
/* check to see if global table selected */
|
||||
if (opts == NULL) {
|
||||
opts = nsoptions;
|
||||
}
|
||||
|
||||
fp = fopen(path, "r");
|
||||
if (!fp) {
|
||||
LOG(("Failed to open file '%s'", path));
|
||||
return NSERROR_NOT_FOUND;
|
||||
}
|
||||
|
||||
LOG(("Sucessfully opened '%s' for Options file", path));
|
||||
|
||||
while (fgets(s, 100, fp)) {
|
||||
char *colon, *value;
|
||||
unsigned int idx;
|
||||
|
||||
if ((s[0] == 0) || (s[0] == '#')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
colon = strchr(s, ':');
|
||||
if (colon == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
s[strlen(s) - 1] = 0; /* remove \n at end */
|
||||
*colon = 0; /* terminate key */
|
||||
value = colon + 1;
|
||||
|
||||
for (idx = 0; opts[idx].key != NULL; idx++) {
|
||||
if (strcasecmp(s, opts[idx].key) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
strtooption(value, &opts[idx]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
nsoption_validate(opts);
|
||||
|
||||
return NSERROR_OK;
|
||||
}
|
||||
|
||||
|
||||
/* exported interface documented in utils/nsoption.h */
|
||||
nserror
|
||||
nsoption_write(const char *path,
|
||||
struct nsoption_s *opts,
|
||||
struct nsoption_s *defs)
|
||||
{
|
||||
FILE *fp;
|
||||
nserror ret;
|
||||
|
||||
if (path == NULL) {
|
||||
return NSERROR_BAD_PARAMETER;
|
||||
}
|
||||
|
||||
/* check to see if global table selected */
|
||||
if (opts == NULL) {
|
||||
opts = nsoptions;
|
||||
}
|
||||
|
||||
/* check to see if global table selected */
|
||||
if (defs == NULL) {
|
||||
defs = &defaults[0];
|
||||
}
|
||||
|
||||
fp = fopen(path, "w");
|
||||
if (!fp) {
|
||||
LOG(("failed to open file '%s' for writing", path));
|
||||
return NSERROR_NOT_FOUND;
|
||||
}
|
||||
|
||||
ret = nsoption_output(fp, opts, defs, false);
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* exported interface documented in utils/nsoption.h */
|
||||
nserror
|
||||
nsoption_dump(FILE *outf, struct nsoption_s *opts)
|
||||
{
|
||||
if (outf == NULL) {
|
||||
return NSERROR_BAD_PARAMETER;
|
||||
}
|
||||
|
||||
/* check to see if global table selected */
|
||||
if (opts == NULL) {
|
||||
opts = nsoptions;
|
||||
}
|
||||
|
||||
return nsoption_output(outf, opts, NULL, true);
|
||||
}
|
||||
|
||||
|
||||
/* exported interface documented in utils/nsoption.h */
|
||||
nserror
|
||||
nsoption_commandline(int *pargc, char **argv, struct nsoption_s *opts)
|
||||
{
|
||||
char *arg;
|
||||
char *val;
|
||||
int arglen;
|
||||
int idx = 1;
|
||||
int mv_loop;
|
||||
unsigned int entry_loop;
|
||||
|
||||
/* check to see if global table selected */
|
||||
if (opts == NULL) {
|
||||
opts = nsoptions;
|
||||
}
|
||||
|
||||
while (idx < *pargc) {
|
||||
arg = argv[idx];
|
||||
arglen = strlen(arg);
|
||||
|
||||
/* check we have an option */
|
||||
/* option must start -- and be as long as the shortest option*/
|
||||
if ((arglen < (2+5) ) || (arg[0] != '-') || (arg[1] != '-'))
|
||||
break;
|
||||
|
||||
arg += 2; /* skip -- */
|
||||
|
||||
val = strchr(arg, '=');
|
||||
if (val == NULL) {
|
||||
/* no equals sign - next parameter is val */
|
||||
idx++;
|
||||
if (idx >= *pargc)
|
||||
break;
|
||||
val = argv[idx];
|
||||
} else {
|
||||
/* equals sign */
|
||||
arglen = val - arg ;
|
||||
val++;
|
||||
}
|
||||
|
||||
/* arg+arglen is the option to set, val is the value */
|
||||
|
||||
LOG(("%.*s = %s", arglen, arg, val));
|
||||
|
||||
for (entry_loop = 0;
|
||||
entry_loop < NSOPTION_LISTEND;
|
||||
entry_loop++) {
|
||||
if (strncmp(arg, opts[entry_loop].key, arglen) == 0) {
|
||||
strtooption(val, opts + entry_loop);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
idx++;
|
||||
}
|
||||
|
||||
/* remove processed options from argv */
|
||||
for (mv_loop=0; mv_loop < (*pargc - idx); mv_loop++) {
|
||||
argv[mv_loop + 1] = argv[mv_loop + idx];
|
||||
}
|
||||
*pargc -= (idx - 1);
|
||||
|
||||
return NSERROR_OK;
|
||||
}
|
||||
|
||||
/* exported interface documented in options.h */
|
||||
int
|
||||
nsoption_snoptionf(char *string,
|
||||
size_t size,
|
||||
enum nsoption_e option_idx,
|
||||
const char *fmt)
|
||||
{
|
||||
size_t slen = 0; /* current output string length */
|
||||
int fmtc = 0; /* current index into format string */
|
||||
struct nsoption_s *option;
|
||||
|
||||
if (option_idx >= NSOPTION_LISTEND) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
option = &nsoptions[option_idx]; /* assume the global table */
|
||||
if (option == NULL || option->key == NULL)
|
||||
return -1;
|
||||
|
||||
|
||||
while ((slen < size) && (fmt[fmtc] != 0)) {
|
||||
if (fmt[fmtc] == '%') {
|
||||
fmtc++;
|
||||
switch (fmt[fmtc]) {
|
||||
case 'k':
|
||||
slen += snprintf(string + slen,
|
||||
size - slen,
|
||||
"%s",
|
||||
option->key);
|
||||
break;
|
||||
|
||||
case 't':
|
||||
switch (option->type) {
|
||||
case OPTION_BOOL:
|
||||
slen += snprintf(string + slen,
|
||||
size - slen,
|
||||
"boolean");
|
||||
break;
|
||||
|
||||
case OPTION_INTEGER:
|
||||
slen += snprintf(string + slen,
|
||||
size - slen,
|
||||
"integer");
|
||||
break;
|
||||
|
||||
case OPTION_UINT:
|
||||
slen += snprintf(string + slen,
|
||||
size - slen,
|
||||
"unsigned integer");
|
||||
break;
|
||||
|
||||
case OPTION_COLOUR:
|
||||
slen += snprintf(string + slen,
|
||||
size - slen,
|
||||
"colour");
|
||||
break;
|
||||
|
||||
case OPTION_STRING:
|
||||
slen += snprintf(string + slen,
|
||||
size - slen,
|
||||
"string");
|
||||
break;
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case 'V':
|
||||
slen += nsoption_output_value_html(option,
|
||||
size,
|
||||
slen,
|
||||
string);
|
||||
break;
|
||||
case 'v':
|
||||
slen += nsoption_output_value_text(option,
|
||||
size,
|
||||
slen,
|
||||
string);
|
||||
break;
|
||||
}
|
||||
fmtc++;
|
||||
} else {
|
||||
string[slen] = fmt[fmtc];
|
||||
slen++;
|
||||
fmtc++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Ensure that we NUL-terminate the output */
|
||||
string[min(slen, size - 1)] = '\0';
|
||||
|
||||
return slen;
|
||||
}
|
|
@ -0,0 +1,274 @@
|
|||
/*
|
||||
* Copyright 2012 Vincent Sanders <vince@netsurf-browser.org>
|
||||
*
|
||||
* This file is part of NetSurf, http://www.netsurf-browser.org/
|
||||
*
|
||||
* NetSurf 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; version 2 of the License.
|
||||
*
|
||||
* NetSurf 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* Option reading and saving (interface).
|
||||
*
|
||||
* Global options are defined in desktop/options.h
|
||||
* Distinct target options are defined in <TARGET>/options.h
|
||||
*
|
||||
* The implementation API is slightly compromised because it still has
|
||||
* "global" tables for both the default and current option tables.
|
||||
*
|
||||
* The initialisation and read/write interfaces take pointers to an
|
||||
* option table which would let us to make the option structure
|
||||
* opaque.
|
||||
*
|
||||
* All the actual acessors assume direct access to a global option
|
||||
* table (nsoptions). To avoid this the acessors would have to take a
|
||||
* pointer to the active options table and be implemented as functions
|
||||
* within nsoptions.c
|
||||
*
|
||||
* Indirect acees would have an impact on performance of NetSurf as
|
||||
* the expected option lookup cost is currently that of a simple
|
||||
* dereference (which this current implementation keeps).
|
||||
*/
|
||||
|
||||
#ifndef _NETSURF_UTILS_NSOPTION_H_
|
||||
#define _NETSURF_UTILS_NSOPTION_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "utils/errors.h"
|
||||
typedef uint32_t colour;
|
||||
|
||||
/* allow targets to include any necessary headers of their own */
|
||||
#define NSOPTION_BOOL(NAME, DEFAULT)
|
||||
#define NSOPTION_STRING(NAME, DEFAULT)
|
||||
#define NSOPTION_INTEGER(NAME, DEFAULT)
|
||||
#define NSOPTION_UINT(NAME, DEFAULT)
|
||||
#define NSOPTION_COLOUR(NAME, DEFAULT)
|
||||
|
||||
#include "desktop/options.h"
|
||||
#if defined(riscos)
|
||||
#include "riscos/options.h"
|
||||
#elif defined(nsgtk)
|
||||
#include "gtk/options.h"
|
||||
#elif defined(nsbeos)
|
||||
#include "beos/options.h"
|
||||
#elif defined(nsamiga)
|
||||
#include "amiga/options.h"
|
||||
#elif defined(nsframebuffer)
|
||||
#include "framebuffer/options.h"
|
||||
#elif defined(nsatari)
|
||||
#include "atari/options.h"
|
||||
#elif defined(nsmonkey)
|
||||
#include "monkey/options.h"
|
||||
#endif
|
||||
|
||||
#undef NSOPTION_BOOL
|
||||
#undef NSOPTION_STRING
|
||||
#undef NSOPTION_INTEGER
|
||||
#undef NSOPTION_UINT
|
||||
#undef NSOPTION_COLOUR
|
||||
|
||||
|
||||
|
||||
enum { OPTION_HTTP_PROXY_AUTH_NONE = 0,
|
||||
OPTION_HTTP_PROXY_AUTH_BASIC = 1,
|
||||
OPTION_HTTP_PROXY_AUTH_NTLM = 2 };
|
||||
|
||||
#define DEFAULT_MARGIN_TOP_MM 10
|
||||
#define DEFAULT_MARGIN_BOTTOM_MM 10
|
||||
#define DEFAULT_MARGIN_LEFT_MM 10
|
||||
#define DEFAULT_MARGIN_RIGHT_MM 10
|
||||
#define DEFAULT_EXPORT_SCALE 0.7
|
||||
|
||||
#ifndef DEFAULT_REFLOW_PERIOD
|
||||
#define DEFAULT_REFLOW_PERIOD 25 /* time in cs */
|
||||
#endif
|
||||
|
||||
enum nsoption_type_e {
|
||||
OPTION_BOOL,
|
||||
OPTION_INTEGER,
|
||||
OPTION_UINT,
|
||||
OPTION_STRING,
|
||||
OPTION_COLOUR
|
||||
};
|
||||
|
||||
struct nsoption_s {
|
||||
const char *key;
|
||||
int key_len;
|
||||
enum nsoption_type_e type;
|
||||
union {
|
||||
bool b;
|
||||
int i;
|
||||
unsigned int u;
|
||||
char *s;
|
||||
const char *cs;
|
||||
colour c;
|
||||
} value;
|
||||
};
|
||||
|
||||
/* construct the option enumeration */
|
||||
#define NSOPTION_BOOL(NAME, DEFAULT) NSOPTION_##NAME,
|
||||
#define NSOPTION_STRING(NAME, DEFAULT) NSOPTION_##NAME,
|
||||
#define NSOPTION_INTEGER(NAME, DEFAULT) NSOPTION_##NAME,
|
||||
#define NSOPTION_UINT(NAME, DEFAULT) NSOPTION_##NAME,
|
||||
#define NSOPTION_COLOUR(NAME, DEFAULT) NSOPTION_##NAME,
|
||||
|
||||
enum nsoption_e {
|
||||
#include "desktop/options.h"
|
||||
#if defined(riscos)
|
||||
#include "riscos/options.h"
|
||||
#elif defined(nsgtk)
|
||||
#include "gtk/options.h"
|
||||
#elif defined(nsbeos)
|
||||
#include "beos/options.h"
|
||||
#elif defined(nsamiga)
|
||||
#include "amiga/options.h"
|
||||
#elif defined(nsframebuffer)
|
||||
#include "framebuffer/options.h"
|
||||
#elif defined(nsatari)
|
||||
#include "atari/options.h"
|
||||
#elif defined(nsmonkey)
|
||||
#include "monkey/options.h"
|
||||
#endif
|
||||
NSOPTION_LISTEND /* end of list */
|
||||
};
|
||||
|
||||
#undef NSOPTION_BOOL
|
||||
#undef NSOPTION_STRING
|
||||
#undef NSOPTION_INTEGER
|
||||
#undef NSOPTION_UINT
|
||||
#undef NSOPTION_COLOUR
|
||||
|
||||
/* global option table */
|
||||
extern struct nsoption_s *nsoptions;
|
||||
|
||||
/* global default option table */
|
||||
extern struct nsoption_s *nsoptions_default;
|
||||
|
||||
/* default setting callback */
|
||||
typedef nserror(nsoption_set_default_t)(struct nsoption_s *defaults);
|
||||
|
||||
|
||||
/** Initialise option system.
|
||||
*
|
||||
* @param set_default callback to allow the customisation of the default
|
||||
* options.
|
||||
* @param ppots pointer to update to get options table or NULL.
|
||||
* @param pdefs pointer to update to get default options table or NULL.
|
||||
* @return The error status
|
||||
*/
|
||||
nserror nsoption_init(nsoption_set_default_t *set_default, struct nsoption_s **popts, struct nsoption_s **pdefs);
|
||||
|
||||
|
||||
/** Read choices file and set them in the passed table
|
||||
*
|
||||
* @param path The path to read the file from
|
||||
* @param opts The options table to enerate values from or NULL to use global
|
||||
* @return The error status
|
||||
*/
|
||||
nserror nsoption_read(const char *path, struct nsoption_s *opts);
|
||||
|
||||
|
||||
/** Write options that have changed from the defaults to a file.
|
||||
*
|
||||
* The \a nsoption_dump can be used to output all entries not just
|
||||
* changed ones.
|
||||
*
|
||||
* @param path The path to read the file from
|
||||
* @param opts The options table to enerate values from or NULL to use global
|
||||
* @param defs The default table to use or NULL to use global
|
||||
* @return The error status
|
||||
*/
|
||||
nserror nsoption_write(const char *path, struct nsoption_s *opts, struct nsoption_s *defs);
|
||||
|
||||
|
||||
/**
|
||||
* Write all options to a stream.
|
||||
*
|
||||
* @param outf The stream to write to
|
||||
* @param opts The options table to enerate values from or NULL to use global
|
||||
* @return The error status
|
||||
*/
|
||||
nserror nsoption_dump(FILE *outf, struct nsoption_s *opts);
|
||||
|
||||
/**
|
||||
* Process commandline and set options approriately.
|
||||
*
|
||||
* @param pargc Pointer to the size of the argument vector.
|
||||
* @param argv The argument vector.
|
||||
* @param opts The options table to enerate values from or NULL to use global
|
||||
* @return The error status
|
||||
*/
|
||||
nserror nsoption_commandline(int *pargc, char **argv, struct nsoption_s *opts);
|
||||
|
||||
/**
|
||||
* Fill a buffer with an option using a format.
|
||||
*
|
||||
* The format string is copied into the output buffer with the
|
||||
* following replaced:
|
||||
* %k - The options key
|
||||
* %t - The options type
|
||||
* %V - value (HTML formatting)
|
||||
* %v - value (plain formatting)
|
||||
*
|
||||
* @param string The buffer in which to place the results.
|
||||
* @param size The size of the string buffer.
|
||||
* @param option The option .
|
||||
* @param fmt The format string.
|
||||
* @return The number of bytes written to \a string or -1 on error
|
||||
*/
|
||||
int nsoption_snoptionf(char *string, size_t size, enum nsoption_e option, const char *fmt);
|
||||
|
||||
|
||||
|
||||
|
||||
/* value acessors - caution should be taken with type as this is not verified */
|
||||
#define nsoption_bool(OPTION) (nsoptions[NSOPTION_##OPTION].value.b)
|
||||
#define nsoption_int(OPTION) (nsoptions[NSOPTION_##OPTION].value.i)
|
||||
#define nsoption_uint(OPTION) (nsoptions[NSOPTION_##OPTION].value.u)
|
||||
#define nsoption_charp(OPTION) (nsoptions[NSOPTION_##OPTION].value.s)
|
||||
#define nsoption_colour(OPTION) (nsoptions[NSOPTION_##OPTION].value.c)
|
||||
|
||||
#define nsoption_set_bool(OPTION, VALUE) nsoptions[NSOPTION_##OPTION].value.b = VALUE
|
||||
#define nsoption_set_int(OPTION, VALUE) nsoptions[NSOPTION_##OPTION].value.i = VALUE
|
||||
#define nsoption_set_colour(OPTION, VALUE) nsoptions[NSOPTION_##OPTION].value.c = VALUE
|
||||
#define nsoption_set_charp(OPTION, VALUE) \
|
||||
do { \
|
||||
if (nsoptions[NSOPTION_##OPTION].value.s != NULL) { \
|
||||
free(nsoptions[NSOPTION_##OPTION].value.s); \
|
||||
} \
|
||||
nsoptions[NSOPTION_##OPTION].value.s = VALUE; \
|
||||
if ((nsoptions[NSOPTION_##OPTION].value.s != NULL) && \
|
||||
(*nsoptions[NSOPTION_##OPTION].value.s == 0)) { \
|
||||
free(nsoptions[NSOPTION_##OPTION].value.s); \
|
||||
nsoptions[NSOPTION_##OPTION].value.s = NULL; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* if a string option is unset set it otherwise leave it set */
|
||||
#define nsoption_setnull_charp(OPTION, VALUE) \
|
||||
do { \
|
||||
if (nsoptions[NSOPTION_##OPTION].value.s == NULL) { \
|
||||
nsoptions[NSOPTION_##OPTION].value.s = VALUE; \
|
||||
if (*nsoptions[NSOPTION_##OPTION].value.s == 0) { \
|
||||
free(nsoptions[NSOPTION_##OPTION].value.s); \
|
||||
nsoptions[NSOPTION_##OPTION].value.s = NULL; \
|
||||
} \
|
||||
} else { \
|
||||
free(VALUE); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue