home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ARM Club 3
/
TheARMClub_PDCD3.iso
/
programs
/
desktop
/
newbar
/
Source
/
NewBar
/
c
/
options
< prev
next >
Wrap
Text File
|
1998-08-08
|
11KB
|
411 lines
/* options.c */
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include "options.h"
#include "various.h"
#include "debug.h"
/* When adding options, there are 5 parts that must be added to:
* An entry in the `Choices' file.
* The structure in options.h.
* Default values in loader.
* Value reader in loader.
* Extra line in destructor.
*/
static int process_lines(thiniconbar_options *obj,
FILE *file, bool enabled);
static bool read_option(thiniconbar_options *obj,
const char *opt, const char *val);
char *file_readline(FILE *file);
/* Options are loaded to here, in main(). */
thiniconbar_options *options = 0;
/* Create an options object with default options filled in. Will return 0
if the structure could not be allocated. */
thiniconbar_options *thiniconbar_options_create(void)
{
thiniconbar_options *obj;
DEBUGF("Options: creating object\n");
/* Allocate structure. */
obj = malloc(sizeof(thiniconbar_options));
if(!obj) return 0;
/* Fill in default values. */
/* Gaps */
obj->end_gap = 8;
obj->between_gap = 0;
obj->central_gap = 40;
obj->top_gap = 0;
obj->sprite_margin = 14;
obj->text_margin = 8;
obj->sprite_text_gap = 10;
obj->icon_h_margins = 10;
/* Heights */
obj->icon_height = 100;
obj->window_height = 100;
/* Scrolling */
obj->scroll_type = scroll_type_LINEAR_S;
obj->scroll_margin = 12;
obj->scroll_step = 12;
obj->scroll_speed = 12;
/* Colours */
obj->text_colour = 7;
obj->icon_bg_colour = 1;
obj->window_bg_colour = 1;
/* Borders */
obj->icon_borders = border_type_SLAB_OUT;
obj->border_size = 4;
obj->window_border = 0;
/* Menus */
obj->menu_y_offset = 12;
/* Misc */
obj->small_icons = 0;
obj->use_task_name = 0;
obj->text_height = 32;
obj->font = 0;
obj->font_size = 0;
obj->font_width = 0;
obj->arrangement = arrangement_TEXT_BOTTOM;
/* Pinboard */
obj->patch_pinboard = 1;
obj->pinboard_bg_colour = -1;
return obj;
}
/* Reads the options from a file to fill out an options object. Returns
non-zero for failure (ie. file could not be opened). */
bool thiniconbar_options_from_file(thiniconbar_options *obj,
const char *filename)
{
FILE *file;
if(!obj) return 1; /* Fail */
DEBUGF1("Options: opening options file `%s'\n", filename);
/* Open the options file. */
file = fopen(filename, "r");
if(!file) {
DEBUGF("Options: could not open file\n");
return 1; /* Fail */
}
DEBUGF("Options: reading file\n");
if(!process_lines(obj, file, 1))
{ fclose(file); return 1; } /* Fail */
/* Close file and finish. */
fclose(file);
DEBUGF("Options: finished reading file\n");
return 0; /* Success */
}
/* Processes lines from an option file. Returns when a closing } is
found. Will return non-zero for success, 0 if malloc failed. */
static int process_lines(thiniconbar_options *obj, FILE *file, bool enabled)
{
/* Read options from the file. */
/* Each line is of the form: option (whitespace) value */
while(!feof(file)) {
char *line = file_readline(file), *c = line, *l = 0;
char *opt, *val;
if(!line) return 0; /* malloc failed, so whinge. */
/* Extract option and value from line. */
while(isspace(*c) && *c) ++c;
/* Skip line if empty or a comment. */
if(!*c || *c == '#') { free(line); continue; }
/* Return if this is the end of a group. */
if(*c == '}') { free(line); return 1; }
/* If not switched on, ignore the line now. */
if(!enabled) { free(line); continue; }
opt = c;
/* Option keyword. */
while(!isspace(*c) && *c) {
if(*c == '-') *c = '_';
++c;
}
if(*c) *c++ = 0;
while(isspace(*c) && *c) ++c;
val = c;
/* Snip any comments and their whitespace, after the value. */
while(*c) {
if(isspace(*c)) { l = c; }
else { if(*c == '#') { *(l ? l : c) = 0; break; } }
++c;
}
/* Is this an option group? */
if(!strcmp(opt, "group")) {
const char *name = val;
bool enable, content;
/* Split value into group name and its state (on or off). */
char *c = val;
const char *state = 0;
/* Look for second arg. */
while(*c && !isspace(*c)) ++c;
if(*c) {
*c++ = 0;
state = c;
}
/* Look for group's opening bracket. */
while(*c && !isspace(*c)) ++c;
if(*c) *c++ = 0;
while(*c && isspace(*c) && *c != '{') ++c;
content = (*c == '{');
/* Is this group enabled? */
if(!state) { enable = 0; }
else if(!strcmp(state, "on")) { enable = 1; }
else if(!strcmp(state, "off")) { enable = 0; }
else { enable = atoi(state); }
/* Process group according to whether it is enabled. */
if(content) {
DEBUGF2("Options: begin group `%s' (state `%s')\n", name, state);
if(!process_lines(obj, file, enable))
{ free(line); return 0; } /* Fail */
DEBUGF2("Options: end group `%s' (state `%s')\n", name, state);
}
else {
DEBUGF2("Options: group `%s' (state `%s') has no content\n",
name, state);
}
free(line);
continue;
}
/* Match options. */
if(read_option(obj, opt, val)) {
free(line);
return 0; /* Failure */
}
free(line);
}
DEBUGF("Options: reached end of file\n");
return 1; /* Success */
}
/* Reads options from a command line, filling out the given options object.
Might return non-zero for malloc failure. This looks at *all* the
command line parameters you give it (so don't pass the command's
filename). */
bool thiniconbar_options_from_cli(thiniconbar_options *obj,
int argc, char *argv[])
{
/* Command line should consist of pairs of the form `--option value'.
Any parameters not conforming are ignored without error. */
int i;
for(i=0; i<(argc-1); ++i) {
if(argv[i][0] == '-' && argv[i][1] == '-') {
/* Copy argument so that `-'s can become `_'s. */
char *opt = my_strdup(argv[i] + 2), *c;
if(!opt) return 1; /* Failure */
for(c=opt; *c; ++c) if(*c == '-') *c = '_';
if(read_option(obj, opt, argv[i+1])) return 1; /* Failure */
++i;
}
}
return 0; /* Success */
}
/* Reads an option. Returns non-zero for a malloc failure. */
static bool read_option(thiniconbar_options *obj,
const char *opt, const char *val)
{
/* A number of macros are defined here to read each data type for us. */
/* Read an integer. */
#define READ_INT(option) \
if(!strcmp(opt, #option)) { \
obj->option = atoi(val); \
DEBUGF2("Options: option `%s' (value `%s') read as int\n", opt, val); \
return 0; \
}
/* Read a floating point number. */
#define READ_FLOAT(option) \
if(!strcmp(opt, #option)) { \
obj->option = atof(val); \
DEBUGF2("Options: option `%s' (value `%s') read as " \
"double\n", opt, val); \
return 0; \
}
/* Read a string. */
/* A string of `-' here means use a null char pointer. */
#define READ_STRING(option) \
if(!strcmp(opt, #option)) { \
if(val[0] == '-' && !val[1]) \
obj->option = 0; \
else { \
obj->option = my_strdup(val); \
if(!obj->option) return 1; /* Fail */ \
} \
DEBUGF2("Options: option `%s' (value `%s') read as " \
"string\n", opt, val); \
return 0; \
}
/* Read an enumeration. */
/* This may be one string of a set, or the number to use directly. */
#define BEGIN_ENUM(option) \
if(!strcmp(opt, #option)) { int *w = &obj->option;
#define ENUM_VAL(symbol, num) \
if(!strcmp(val, symbol)) { \
*w = num; \
DEBUGF3("Options: option `%s' (value `%s') read as enum, symbol `" \
symbol "' value " #num " (%i)\n", opt, val, num); \
return 0; \
}
#define END_ENUM \
*w = atoi(val); \
DEBUGF2("Options: option `%s' (value `%s') " \
"unmatched enum, read as int\n", opt, val); \
return 0; }
/* Read a boolean variable (on, off, 1 or 0). */
/* Implemented as an enumeration. */
#define READ_BOOL(option) \
BEGIN_ENUM(option) \
ENUM_VAL("off", 0) \
ENUM_VAL("on", 1) \
END_ENUM;
/* Read a colour. Only does Wimp colours at the moment. */
/* You can use a colour name or a number. */
#define READ_COLOUR(option) \
BEGIN_ENUM(option) \
ENUM_VAL("white", 0) \
ENUM_VAL("grey-1", 1) \
ENUM_VAL("grey-2", 2) \
ENUM_VAL("grey-3", 3) \
ENUM_VAL("grey-4", 4) \
ENUM_VAL("grey-5", 5) \
ENUM_VAL("grey-6", 6) \
ENUM_VAL("black", 7) \
ENUM_VAL("dark-blue", 8) \
ENUM_VAL("yellow", 9) \
ENUM_VAL("light-green", 10) \
ENUM_VAL("red", 11) \
ENUM_VAL("cream", 12) \
ENUM_VAL("dark-green", 13) \
ENUM_VAL("orange", 14) \
ENUM_VAL("light-blue", 15) \
ENUM_VAL("none", -1) \
END_ENUM;
/* Gaps */
READ_INT(end_gap);
READ_INT(between_gap);
READ_INT(central_gap);
READ_INT(top_gap);
READ_INT(sprite_margin);
READ_INT(text_margin);
READ_INT(sprite_text_gap);
READ_INT(icon_h_margins);
/* Heights */
READ_INT(icon_height);
READ_INT(window_height);
/* Scrolling */
BEGIN_ENUM(scroll_type)
ENUM_VAL("none", scroll_type_NONE)
ENUM_VAL("linear", scroll_type_LINEAR)
ENUM_VAL("linear-s", scroll_type_LINEAR_S)
ENUM_VAL("prop", scroll_type_PROP)
ENUM_VAL("move", scroll_type_MOVE)
END_ENUM;
READ_INT(scroll_margin);
READ_INT(scroll_step);
READ_INT(scroll_speed);
/* Colours */
READ_COLOUR(text_colour);
READ_COLOUR(icon_bg_colour);
READ_COLOUR(window_bg_colour);
/* Borders */
BEGIN_ENUM(icon_borders)
ENUM_VAL("none", border_type_NONE)
ENUM_VAL("plain", border_type_PLAIN)
ENUM_VAL("slab-out", border_type_SLAB_OUT)
ENUM_VAL("slab-in", border_type_SLAB_IN)
END_ENUM;
READ_INT(border_size);
READ_BOOL(window_border);
/* Menus */
READ_INT(menu_y_offset);
/* Misc */
READ_BOOL(small_icons);
READ_BOOL(use_task_name);
READ_INT(text_height);
READ_STRING(font);
READ_FLOAT(font_size);
READ_FLOAT(font_width);
BEGIN_ENUM(arrangement)
ENUM_VAL("text-bottom", arrangement_TEXT_BOTTOM);
ENUM_VAL("text-right", arrangement_TEXT_RIGHT);
END_ENUM;
/* Pinboard */
READ_BOOL(patch_pinboard);
READ_COLOUR(pinboard_bg_colour);
/* Don't need the macros any more. */
#undef READ_INT
#undef READ_FLOAT
#undef READ_STRING
#undef BEGIN_ENUM
#undef ENUM_VAL
#undef END_ENUM
#undef READ_BOOL
/* If not matched, make a note on debug. */
DEBUGF2("Options: option `%s' not recognised (value `%s')\n", opt, val);
return 0; /* Success */
}
/* Reads a line from a file. May return 0 if malloc failed at some point.
Free the returned string yourself. */
char *file_readline(FILE *file)
{
int ch, len = 40;
char *line = malloc(len + 1), *c = line;
if(!line) return 0;
do {
ch = fgetc(file);
if(ch == EOF || ch == '\n') ch = 0;
/* Extend buffer if necessary. */
if((c - line) >= len) {
char *old_line = line;
len += 30;
line = realloc(line, len + 1);
if(!line) return 0;
c = c - old_line + line;
}
*c++ = ch;
} while(ch);
return line;
}
/* Destroys an options object, freeing data it owns. */
void thiniconbar_options_destroy(thiniconbar_options *obj)
{
if(!obj) return;
/* Free strings owned. */
free(obj->font);
free(obj);
}