/*
 * widgetlib.c
 *
 * UI toolkit for C modelled after Tk
 *
 * Author: Dario Rodriguez antartica@whereismybit.com
 * Please see the file LICENSE.txt in the source's root directory.
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "widgetlib.h"

#define BLOCKWICLASS 16

wi_t *
wi_init(void)
{
        wi_t *wi;
        if((wi=malloc(sizeof(wi_t)))==NULL)
                return(NULL); /* insuf. mem. */
        memset(wi,0,sizeof(wi_t));
        return(wi);
}

void
wi_free(wi_t *wi)
{
        int i;
        if(wi==NULL)
                return; /* nothing to do */
        for(i=wi->usedclasses-1;i>=0 && i<wi->usedclasses;i--)
                wi_class_unregister(wi,wi->classes[i].classname);
        if(wi->classes!=NULL)
                free(wi->classes),wi->classes=NULL,wi->sizeclasses=wi->usedclasses=0;
        free(wi),wi=NULL;
        return;
}

int
wi_class_register(wi_t *wi, char *classname, int (*classcallback)(void *wi, wiclass_t *cl, widget_t *widget, wiclassop_t *op))
{
        wiclass_t *cl;
        wiclassop_t clop;
        if(wi==NULL || classname==NULL || classcallback==NULL)
                return(-1); /* sanity check error */
        wi_class_unregister(wi,classname);
        if(wi->sizeclasses==wi->usedclasses) {
                wiclass_t *newclasses;
                int newsize;
                newsize=wi->sizeclasses+BLOCKWICLASS;
                if((newclasses=realloc(wi->classes,newsize*sizeof(wiclass_t)))==NULL)
                        return(-1); /* insuf. mem. */
                wi->classes=newclasses;
                memset(newclasses+wi->sizeclasses,0,sizeof(wiclass_t)*(newsize-wi->sizeclasses));
                wi->sizeclasses=newsize;
        }
        cl=wi->classes+wi->usedclasses;
        memset(cl,0,sizeof(wiclass_t));
        memset(&clop,0,sizeof(clop));
        clop.op=classop_initclass;
        cl->classcallback=classcallback;
        if((cl->classname=strdup(classname))==NULL || classcallback(wi,cl,NULL,&clop)!=0) {
                if(cl->classname!=NULL)
                        free(cl->classname),cl->classname=NULL;
                if(cl->classglobaldata!=NULL)
                        free(cl->classglobaldata),cl->classglobaldata=NULL,cl->sizeclassglobaldata=0;
                cl->classcallback=NULL;
                return(-1); /* insuf. mem. */
        }
        wi->usedclasses++;
        return(0);
}

int
wi_class_unregister(wi_t *wi, char *classname)
{
        int i;
        wiclass_t *cl;
        wiclassop_t clop;
        if(wi==NULL || classname==NULL)
                return(-1); /* sanity check failed */
        /* search for class starting from last (as the usual user of this function is wi_free(), and it frees classes starting from the last one) */
        for(i=wi->usedclasses-1;i>=0;i--) {
                if(strcmp(wi->classes[i].classname,classname)==0)
                        break;
        }
        if(i<0)
                return(-1); /* unknown classname */
        cl=wi->classes+i;
        memset(&clop,0,sizeof(clop));
        clop.op=classop_freeclass;
        cl->classcallback(wi,cl,NULL,&clop);
        if(cl->classname!=NULL)
                free(cl->classname),cl->classname=NULL;
        if(cl->classglobaldata!=NULL)
                free(cl->classglobaldata),cl->classglobaldata=NULL,cl->sizeclassglobaldata=0;
        cl->classcallback=NULL;
        memmove(wi->classes+i,wi->classes+i+1,(wi->usedclasses-(i+1))*sizeof(wiclass_t));
        memset(wi->classes+(wi->usedclasses-1),0,sizeof(wiclass_t));
        wi->usedclasses--;
        return(0);
}

int
wi_toplevel_set(wi_t *wi, char *name)
{
#warning TODO
        return(-1);
}

int
wi_toplevel_destroy(wi_t *wi, char *name)
{
#warning TODO
        return(-1);
}

char *
wi_add(wi_t *wi, char *debugfile, int debugline, char *class, char *path, char *format,...)
{
#warning TODO
        return(NULL);
}

char *
wi_config(wi_t *wi, char *debugfile, int debugline, char *path, char *format,...)
{
#warning TODO
        return(NULL);
}

int
wi_pack(wi_t *wi, char *debugfile, int debugline, char *path, char *format,...)
{
#warning TODO
        return(-1);
}

int
wi_destroy(wi_t *wi, char *path)
{
#warning TODO
        return(-1);
}

int
wi_alias_set(wi_t *wi, char *alias, char *path)
{
#warning TODO
        return(-1);
}

int
wi_alias_unset(wi_t *wi, char *alias)
{
#warning TODO
        return(-1);
}

int
wi_tree_move(wi_t *wi, char *path, char *newparent)
{
#warning TODO
        return(-1);
}

int
wi_var_updated(wi_t *wi, char *vardata, int sizevardata)
{
#warning TODO
        return(-1);
}

int wi_var_destroy(wi_t *wi, char *vardata, int sizevardata)
{
#warning TODO
        return(-1);
}

int
wi_font_load(wi_t *wi, char *filename, char *fontname)
{
#warning TODO
        return(-1);
}

/* default widgets */
int
wi_classcallback_frame(void *wi, wiclass_t *cl, widget_t *widget, wiclassop_t *op)
{
#warning TODO
        return(-1);
}

int
wi_classcallback_label(void *wi, wiclass_t *cl, widget_t *widget, wiclassop_t *op)
{
#warning TODO
        return(-1);
}

int
wi_classcallback_image(void *wi, wiclass_t *cl, widget_t *widget, wiclassop_t *op)
{
#warning TODO
        return(-1);
}