dictlookup took a Lang for two reasons that were not its business: to know whether to walk below the key (the emoji dictionary) and to drop a candidate equal to the key except there. No dictionary lists its key among its candidates — the rule was left from a first version that put the reading first itself — so it goes, and the walk is dictprefix(), called by the emoji search alone.
91 lines
1.7 KiB
C
91 lines
1.7 KiB
C
#include "dat.h"
|
|
#include "fn.h"
|
|
|
|
/* Appends the space-separated words of a node's entry to out[], up to max. */
|
|
static int
|
|
words(Tnode *nd, Str *out, int n, int max)
|
|
{
|
|
char *p, *e, *sp;
|
|
Str tmp;
|
|
|
|
if(nd->val == nil)
|
|
return n;
|
|
p = nd->val;
|
|
e = p + nd->vlen;
|
|
while(n < max && p < e){
|
|
while(p < e && *p == ' ')
|
|
p++;
|
|
sp = p;
|
|
while(p < e && *p != ' ')
|
|
p++;
|
|
if(sinit(&tmp, sp, p - sp) && tmp.n > 0)
|
|
out[n++] = tmp;
|
|
}
|
|
return n;
|
|
}
|
|
|
|
/* The entries at and below a node, in the dictionary's order. */
|
|
static int
|
|
below(Trie *t, int ni, Str *out, int n, int max)
|
|
{
|
|
Tnode *nd;
|
|
int ci;
|
|
|
|
nd = &t->nodes[ni];
|
|
n = words(nd, out, n, max);
|
|
for(ci = nd->child; ci >= 0 && n < max; ci = t->nodes[ci].sibling)
|
|
n = below(t, ci, out, n, max);
|
|
return n;
|
|
}
|
|
|
|
/* Fills out[] with up to max candidates for key: the words of its entry. */
|
|
int
|
|
dictlookup(Trie *t, Str *key, Str *out, int max)
|
|
{
|
|
int ni;
|
|
|
|
ni = key->n == 0 ? -1 : trienode(t, key);
|
|
if(ni < 0)
|
|
return 0;
|
|
return words(&t->nodes[ni], out, 0, max);
|
|
}
|
|
|
|
/* As dictlookup, for every entry key is a prefix of, key's own first. */
|
|
int
|
|
dictprefix(Trie *t, Str *key, Str *out, int max)
|
|
{
|
|
int ni;
|
|
|
|
ni = key->n == 0 ? -1 : trienode(t, key);
|
|
if(ni < 0)
|
|
return 0;
|
|
return below(t, ni, out, 0, max);
|
|
}
|
|
|
|
static Trie*
|
|
langopen(char *dir, char *name, char *ext)
|
|
{
|
|
char *path;
|
|
Trie *t;
|
|
|
|
path = smprint("%s/%s.%s", dir, name, ext);
|
|
if(path == nil)
|
|
die("out of memory");
|
|
t = trieopen(path);
|
|
free(path);
|
|
return t;
|
|
}
|
|
|
|
void
|
|
langinit(char *dir)
|
|
{
|
|
Lang *l;
|
|
|
|
for(l = langs; l < langs + nlang; l++){
|
|
if(l->mapname != nil)
|
|
l->map = langopen(dir, l->mapname, "map");
|
|
if(l->dictname != nil)
|
|
l->dict = langopen(dir, l->dictname, "dict");
|
|
}
|
|
}
|