Commit 6d7c0bf2 authored by Mark Hills's avatar Mark Hills
Browse files

Honour the search locale

Keep a cache of any records which needed converting to the ASCII
locale used for searching.

These changes would have to be broadened if somebody wanted to
search in a more complex locale; currently the only characters
allowable are [a-z0-9]. It would need a greater understanding of
how SDL handles the user input.
parent de009a79
* Fix a bug that prevented dithering from being used
* Honour the system locale; allow the full character set in track names
* When searching, match characters in other locales
v1.6 (2016-08-13)
-----------------
......
......@@ -170,10 +170,19 @@ static int record_cmp_bpm(const struct record *a, const struct record *b)
static bool record_match_word(struct record *re, const char *match)
{
if (strcasestr(re->artist, match) != NULL)
return true;
if (strcasestr(re->title, match) != NULL)
return true;
/* Some records provide a dedicated string for matching against,
* in the same locale as "match" */
if (re->match) {
if (strcasestr(re->match, match) != NULL)
return true;
} else {
if (strcasestr(re->artist, match) != NULL)
return true;
if (strcasestr(re->title, match) != NULL)
return true;
}
return false;
}
......
......@@ -27,8 +27,16 @@
#define SORT_PLAYLIST 2
#define SORT_END 3
/* A single music track in our listings */
struct record {
char *pathname, *artist, *title;
char *pathname, *artist, *title; /* a single malloc */
/* An optional extra string may be used to match against search
* input; allows us to handle locale but still type in ASCII */
char *match; /* or NULL */
double bpm; /* or 0.0 if not known */
};
......
......@@ -20,6 +20,7 @@
#define _GNU_SOURCE /* strdupa() */
#include <assert.h>
#include <errno.h>
#include <iconv.h>
#include <libgen.h> /* basename() */
#include <math.h> /* isfinite() */
#include <stdbool.h>
......@@ -34,6 +35,31 @@
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*x))
/* The locale used for searches */
static iconv_t ascii = (iconv_t)-1;
int library_global_init(void)
{
assert(ascii == (iconv_t)-1);
ascii = iconv_open("ASCII//TRANSLIT", "");
if (ascii == (iconv_t)-1) {
perror("iconv_open");
return -1;
}
return 0;
}
void library_global_clear(void)
{
assert(ascii != (iconv_t)-1);
if (iconv_close(ascii) == -1)
abort();
}
void listing_init(struct listing *l)
{
index_init(&l->by_artist);
......@@ -359,6 +385,7 @@ int library_init(struct library *li)
static void record_clear(struct record *re)
{
free(re->pathname);
free(re->match); /* may be NULL */
}
/*
......@@ -444,6 +471,57 @@ static size_t split(char *s, char *x[], size_t len)
return n;
}
/*
* Construct a string for matching against
*
* Only construct the string if the given "artist" and "title" contain
* characters which require converting to the ASCII locale which is
* used for searches.
*
* Return: string with responsibility, or NULL if not required
*/
static char* matchable(const char *artist, const char *title)
{
char *buf, *in, *out;
size_t len, fill, nonrev;
/*
* Append all the strings of interest into a single buffer
*/
len = strlen(artist) + strlen(title) + 1;
buf = alloca(len + 1); /* include \0 terminator */
assert(buf);
sprintf(buf, "%s %s", artist, title);
/*
* Perform iconv
*
* We know ASCII is the shorter encoding, so we can use the input
* buffer as also the output buffer
*/
out = buf;
fill = len; /* does not include \0 */
assert(ascii != (iconv_t)-1);
if (iconv(ascii, NULL, NULL, &out, &fill) == -1)
abort();
in = buf;
nonrev = iconv(ascii, &in, &len, &out, &fill);
*out = '\0';
if (nonrev == 0)
return NULL;
return strdup(buf);
}
/*
* Convert a line from the scan script to a record structure in memory
*
......@@ -489,6 +567,11 @@ struct record* get_record(char *line)
goto bad;
}
/* Decide if this record needs a character-equivalent in the
* locale used for searching */
x->match = matchable(x->artist, x->title);
return x;
bad:
......
......@@ -56,6 +56,9 @@ struct library {
size_t crates;
};
int library_global_init(void);
void library_global_clear(void);
void listing_init(struct listing *l);
void listing_clear(struct listing *l);
struct record* listing_add(struct listing *l, struct record *r);
......
......@@ -211,6 +211,8 @@ int main(int argc, char *argv[])
if (thread_global_init() == -1)
return -1;
if (library_global_init() == -1)
return -1;
if (rig_init() == -1)
return -1;
......@@ -640,6 +642,7 @@ out_rt:
library_clear(&library);
rt_clear(&rt);
rig_clear();
library_global_clear();
thread_global_clear();
if (rc == EXIT_SUCCESS)
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment