do not edit — generated by btf.
git.druid.rocksindexmilitantprogrammerastral_canvassrc/api/node.c

src/api/node.c


#include "api/node.h"
#include "lib/id.h"
 
#include <stdlib.h>
#include <string.h>
 
static Node *g_root;
static Node **g_byId;
static unsigned g_cap;
 
static char *copyString(const char *s)
{
    size_t n;
    char *d;
 
    if (!s)
        return NULL;
    n = strlen(s) + 1;
    d = malloc(n);
    if (!d)
        return NULL;
    memcpy(d, s, n);
    return d;
}
 
static int ensureId(unsigned short id)
{
    unsigned need = (unsigned)id + 1;
    unsigned cap = g_cap;
    Node **grown;
 
    if (need <= g_cap)
        return 0;
    if (cap < 16)
        cap = 16;
    while (cap < need)
        cap *= 2;
    grown = realloc(g_byId, cap * sizeof(*grown));
    if (!grown)
        return -1;
    memset(grown + g_cap, 0, (cap - g_cap) * sizeof(*grown));
    g_byId = grown;
    g_cap = cap;
    return 0;
}
 
static void registerNode(Node *node)
{
    if (!node)
        return;
    if (ensureId(node->widget.id) != 0)
        return;
    g_byId[node->widget.id] = node;
}
 
static void unregisterNode(Node *node)
{
    if (!node || node->widget.id >= g_cap)
        return;
    if (g_byId[node->widget.id] == node)
        g_byId[node->widget.id] = NULL;
}
 
int nodeGraphInit(void)
{
    nodeGraphDestroy();
    g_root = nodeCreate((Widget){ .id = 0, .widgetType = A_WIDGET_PAGE });
    if (!g_root)
        return -1;
    return 0;
}
 
void nodeGraphDestroy(void)
{
    if (g_root)
        nodeDestroy(g_root);
    g_root = NULL;
    free(g_byId);
    g_byId = NULL;
    g_cap = 0;
}
 
Node *nodeRoot(void)
{
    return g_root;
}
 
Node *nodeFind(unsigned short id)
{
    if (!g_byId || id >= g_cap)
        return NULL;
    return g_byId[id];
}
 
Node *nodeCreate(Widget widget)
{
    Node *node = calloc(1, sizeof(*node));
    if (!node)
        return NULL;
    node->widget = widget;
    registerNode(node);
    if (!g_root && widget.id == 0)
        g_root = node;
    return node;
}
 
void nodeDetach(Node *node)
{
    Node *parent;
 
    if (!node || !node->parent)
        return;
    parent = node->parent;
    if (node->prevSibling)
        node->prevSibling->nextSibling = node->nextSibling;
    else
        parent->firstChild = node->nextSibling;
    if (node->nextSibling)
        node->nextSibling->prevSibling = node->prevSibling;
    else
        parent->lastChild = node->prevSibling;
    node->parent = NULL;
    node->nextSibling = NULL;
    node->prevSibling = NULL;
}
 
int nodeAttach(Node *parent, Node *child)
{
    if (!parent || !child || parent == child)
        return -1;
    nodeDetach(child);
    child->parent = parent;
    child->prevSibling = parent->lastChild;
    child->nextSibling = NULL;
    if (parent->lastChild)
        parent->lastChild->nextSibling = child;
    else
        parent->firstChild = child;
    parent->lastChild = child;
    return 0;
}
 
void nodeDestroy(Node *node)
{
    if (!node)
        return;
    while (node->firstChild)
        nodeDestroy(node->firstChild);
    nodeDetach(node);
    unregisterNode(node);
    if (node->widget.id != 0)
        libFreeId(node->widget.id);
    if (g_root == node)
        g_root = NULL;
    free(node->text);
    free(node->shader);
    free(node);
}
 
void nodeApplyShader(Node *node, const char *shader)
{
    Node *child;
    char *copy;
 
    if (!node)
        return;
    copy = copyString(shader);
    free(node->shader);
    node->shader = copy;
    for (child = node->firstChild; child; child = child->nextSibling)
        nodeApplyShader(child, shader);
}
 
void nodeApplyStyle(Node *node, const Style *style)
{
    Node *child;
 
    if (!node || !style)
        return;
    node->style = *style;
    for (child = node->firstChild; child; child = child->nextSibling)
        nodeApplyStyle(child, style);
}
powered by btf.