tkd->mask, 1);
else {
n = conf_htable_lookup(token + 2);
+ if (n == NULL)
+ return -1;
if ((n->flags & tkd->mask) != tkd->flags)
return -1;
TAILQ_INSERT_TAIL(&l, n, user_next);
struct confnode_complete_callback {
struct confnode *start;
struct confnode *cur;
+ int xpath;
};
static struct confnode *get_next_node(struct confnode *start,
struct confnode *cur, unsigned flags,
- unsigned mask)
+ unsigned mask, int xpath)
{
struct confnode *prev;
struct confnode *parent = start;
+ int descend = 1;
while (1) {
prev = cur;
/* first iteration */
if (cur == NULL)
cur = TAILQ_FIRST(&parent->children);
+ /* directory in xpath mode */
+ else if (xpath && descend &&
+ (cur->flags & CONFNODE_F_IS_DIR) &&
+ (cur->flags & CONFNODE_F_INVISIBLE) == 0)
+ cur = TAILQ_FIRST(&cur->children);
+ /* other cases */
else
cur = TAILQ_NEXT(cur, next);
+ descend = 1;
/* no next, return to upper level */
if (cur == NULL) {
if (prev == NULL)
return NULL; /* no node */
cur = prev->parent;
+ descend = 0;
continue;
}
continue;
}
+ /* skip other nodes with no name */
+ if (cur->flags & CONFNODE_F_NO_NAME)
+ continue;
+
/* check that flags match what we want */
if ((cur->flags & mask) != flags)
continue;
struct token_conf_node *tk2 = (struct token_conf_node *)tk;
struct token_conf_node_data *tkd = &tk2->conf_node_data;
struct confnode_complete_callback *cb;
- struct confnode *n;
+ struct confnode *n, *start;
unsigned flags = tkd->flags;
unsigned mask = tkd->mask;
return -1;
*opaque = cb;
- n = get_next_node(*tkd->cur, NULL, flags, mask);
- if (n == NULL)
- return -1; /* no completion */
+ if (strlen(tokstr) >= 2 && tokstr[0] == '/' && tokstr[1] == '/') {
+ start = *tkd->root;
+ cb->xpath = 1;
+ }
+ else {
+ start = *tkd->cur;
+ cb->xpath = 0;
+ }
+
+ n = get_next_node(start, NULL, flags, mask, cb->xpath);
+ if (n == NULL) {
+ /* no completion.
+ * cb is freed in complete_conf_node_end()*/
+ return -1;
+ }
- cb->start = *tkd->cur;
+ cb->start = start;
cb->cur = n;
return 0;
}
struct token_conf_node_data *tkd = &tk2->conf_node_data;
struct confnode_complete_callback *cb;
struct confnode *n;
- unsigned len;
unsigned flags = tkd->flags;
unsigned mask = tkd->mask;
+ int len;
cb = *opaque;
n = cb->cur;
if (n == NULL)
return -1;
- cb->cur = get_next_node(cb->start, n, flags, mask);
+ cb->cur = get_next_node(cb->start, n, flags, mask, cb->xpath);
- len = strlen(n->name) + 1;
- if (len > size)
+ len = snprintf(dstbuf, size, "%s%s",
+ cb->xpath ? "//" : "",
+ n->name);
+ if (len < 0 || len >= size)
return -1;
- strcpy(dstbuf, n->name);
return 0;
}