aboutsummaryrefslogtreecommitdiff
path: root/scripts/permute/menudata.c
blob: c941552b0c0a9a2f2ce6a4a8b83e05a34aac8080 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include "menudata.h"

struct menudata *menudata_new(void) {
    struct menudata *rtn;
    rtn = calloc(1, sizeof(struct menudata));
    return rtn;
}

void menudata_set_permute(struct menu *m, bool perm) {
    ((struct menudata *) m->data)->permute = perm;
    ((struct menudata *) m->data)->subpermute = perm;
    struct menu *prnt;
    for (prnt = m->parent; prnt != NULL; prnt = prnt->parent) {
        menudata_cal(prnt);
    }

    struct menu **stack;
    size_t stack_size = 2, stack_pos = 0;
    stack = malloc(stack_size * sizeof(struct menu *));

    m = m->list;
    while (m != NULL) {
        if (m->data == NULL)
            m->data = menudata_new();
        ((struct menudata *) m->data)->permute = perm;
        ((struct menudata *) m->data)->subpermute = perm;

        if (m->list != NULL) {
            if (stack_pos >= stack_size) {
                stack_size *= 2;
                stack = realloc(stack, stack_size * sizeof(struct menu *));
            }
            stack[stack_pos++] = m->list;
        }

        m = m->next;
        if (m == NULL && stack_pos > 0)
            m = stack[--stack_pos];
    }
}

void menudata_cal(struct menu *m) {
    bool perm = true;
    bool subperm = false;
    struct menu *w;
    for (w = m->list; w != NULL; w = w->next) {
        if (w->data != NULL && (((struct menudata *) w->data)->permute
                                || ((struct menudata *) w->data)->
                                subpermute)) {
            subperm = true;
        } else {
            perm = false;
        }
    }
    if (m->data == NULL)
        m->data = menudata_new();
    ((struct menudata *) m->data)->permute = perm && subperm;
    ((struct menudata *) m->data)->subpermute = subperm;
}