diff options
-rw-r--r-- | conf.c | 214 | ||||
-rw-r--r-- | conf.h | 2 |
2 files changed, 208 insertions, 8 deletions
@@ -1,3 +1,4 @@ +#include <ctype.h> #include <stdio.h> #include <errno.h> #include <stdlib.h> @@ -13,6 +14,7 @@ #include "config.h" #include "options.h" #include "support.h" +#include "command.h" #include "conf.h" #ifdef DEBUG @@ -38,7 +40,15 @@ #define CONF_COLOR_PROGRESS "progress_color" #define CONF_COLOR_STATUS "status_color" #define CONF_COLOR_ALERT "alert_color" +#define CONF_KEY_DEFINITION "key" +typedef enum { + KEY_PARSER_UNKNOWN, + KEY_PARSER_CHAR, + KEY_PARSER_DEC, + KEY_PARSER_HEX, + KEY_PARSER_DONE +} key_parser_state_t; static int str2bool(char *str) @@ -72,7 +82,134 @@ str2color(char *str) return -1; } -int +static int +parse_key_value(char *str, size_t len, char **end) +{ + int i, value; + key_parser_state_t state; + + i=0; + value=0; + state=KEY_PARSER_UNKNOWN; + *end = str; + + while( i<len && state!=KEY_PARSER_DONE ) + { + int next = 0; + int c = str[i]; + + if( i+1<len ) + next = str[i+1]; + + switch(state) + { + case KEY_PARSER_UNKNOWN: + if( c=='\'' ) + state = KEY_PARSER_CHAR; + else if( c=='0' && next=='x' ) + state = KEY_PARSER_HEX; + else if( isdigit(c) ) + state = KEY_PARSER_DEC; + else { + fprintf(stderr, "Error: Unsupported key definition - %s\n", str); + return -1; + } + break; + case KEY_PARSER_CHAR: + if( next!='\'' ) + { + fprintf(stderr, "Error: Unsupported key definition - %s\n", str); + return -1; + } + value = c; + *end = str+i+2; + state = KEY_PARSER_DONE; + break; + case KEY_PARSER_DEC: + value = (int) strtol(str+(i-1), end, 10); + state = KEY_PARSER_DONE; + break; + case KEY_PARSER_HEX: + if( !isdigit(next) ) + { + fprintf(stderr, "Error: Digit expexted after 0x - %s\n", str); + return -1; + } + value = (int) strtol(str+(i+1), end, 16); + state = KEY_PARSER_DONE; + break; + case KEY_PARSER_DONE: + break; + } + i++; + } + + if( *end> str+len ) + *end = str+len; + + return value; +} + +static int +parse_key_definition(char *str) +{ + char buf[MAX_LINE_LENGTH]; + char *p, *end; + size_t len = strlen(str); + int i,j,key; + int keys[MAX_COMMAND_KEYS]; + command_t cmd; + + /* get the command name */ + i=0; + j=0; + memset(buf, 0, MAX_LINE_LENGTH); + while( i<len && str[i]!='=' && !IS_WHITESPACE(str[i]) ) + buf[j++] = str[i++]; + if( (cmd=get_key_command_from_name(buf)) == CMD_NONE ) + { + fprintf(stderr, "Error: Unknown key command %s\n", buf); + return -1; + } + + /* skip whitespace */ + while( i<len && (str[i]=='=' || IS_WHITESPACE(str[i])) ) + i++; + + /* get the value part */ + memset(buf, 0, MAX_LINE_LENGTH); + strncpy(buf, str+i, len-i); + len = strlen(buf); + if( len==0 ) + { + fprintf(stderr,"Error: Incomplete key definition - %s\n", str); + return -1; + } + + /* parse key values */ + i = 0; + key = 0; + len = strlen(buf); + p = buf; + end = buf+len; + memset(keys, 0, sizeof(int)*MAX_COMMAND_KEYS); + while( i<MAX_COMMAND_KEYS && p<end && (key=parse_key_value(p,len+1,&p))>=0 ) + { + keys[i++] = key; + while( p<end && (*p==',' || *p==' ' || *p=='\t') ) + p++; + len = strlen(p); + } + if( key<0 ) + { + fprintf(stderr,"Error: Bad key definition - %s\n", str); + return -1; + } + + return assign_keys(cmd, keys); +} + +static int read_rc_file(char *filename, options_t *options) { int fd; @@ -81,12 +218,9 @@ read_rc_file(char *filename, options_t *options) int free_filename = 0; if( filename==NULL ) - { - filename = g_build_filename(g_get_home_dir(), RCFILE, NULL); - free_filename = 1; - } + return -1; - D(printf("\n--Reading configuration file %s\n", filename)); + D(printf("Reading configuration file %s\n", filename)); if( (fd=open(filename,O_RDONLY)) <0 ) { D(perror(filename)); @@ -160,8 +294,13 @@ read_rc_file(char *filename, options_t *options) match_found = 0; + if( !strcasecmp(CONF_KEY_DEFINITION, name) ) + { + parse_key_definition(value); + match_found = 1; + } /* enable colors */ - if( !strcasecmp(CONF_ENABLE_COLORS, name) ) + else if( !strcasecmp(CONF_ENABLE_COLORS, name) ) { options->enable_colors = str2bool(value); match_found = 1; @@ -247,7 +386,68 @@ read_rc_file(char *filename, options_t *options) } +int +read_configuration(options_t *options) +{ + char *filename = NULL; + + /* check for user configuration ~/.ncmpc/config */ + filename = g_build_filename(g_get_home_dir(), "." PACKAGE, "config", NULL); + if( !g_file_test(filename, G_FILE_TEST_IS_REGULAR) ) + { + g_free(filename); + filename = NULL; + } + /* check for global configuration SYSCONFDIR/ncmpc/config */ + if( filename == NULL ) + { + filename = g_build_filename(SYSCONFDIR, PACKAGE, "config", NULL); + if( !g_file_test(filename, G_FILE_TEST_IS_REGULAR) ) + { + g_free(filename); + filename = NULL; + } + } + + /* load configuration */ + if( filename ) + { + read_rc_file(filename, options); + g_free(filename); + filename = NULL; + } + + /* check for user key bindings ~/.ncmpc/keys */ + filename = g_build_filename(g_get_home_dir(), "." PACKAGE, "keys", NULL); + if( !g_file_test(filename, G_FILE_TEST_IS_REGULAR) ) + { + g_free(filename); + filename = NULL; + } + + /* check for global key bindings SYSCONFDIR/ncmpc/keys */ + if( filename == NULL ) + { + filename = g_build_filename(SYSCONFDIR, PACKAGE, "keys", NULL); + if( !g_file_test(filename, G_FILE_TEST_IS_REGULAR) ) + { + g_free(filename); + filename = NULL; + } + } + + /* load key bindings */ + if( filename ) + { + read_rc_file(filename, options); + g_free(filename); + filename = NULL; + //write_key_bindings(stderr); + } + + return 0; +} @@ -1,3 +1,3 @@ -int read_rc_file(char *filename, options_t *options); +int read_configuration(options_t *options); |