diff --git a/gtk/Makefile.am b/gtk/Makefile.am
index 864de86..e6f9557 100644
--- a/gtk/Makefile.am
+++ b/gtk/Makefile.am
@@ -2,6 +2,8 @@ bin_PROGRAMS = rtbuf-gtk
rtbuf_gtk_CFLAGS = ${GTK3_CFLAGS}
rtbuf_gtk_LDADD = ${GTK3_LIBS} ../librtbuf/librtbuf.la
rtbuf_gtk_SOURCES = \
+ list.c \
+ queue.c \
rtbuf_gtk.c \
rtbuf_gtk_connection.c \
rtbuf_gtk_input.c \
@@ -11,14 +13,19 @@ rtbuf_gtk_SOURCES = \
rtbuf_gtk_rtbuf.c \
rtbuf_input_widget.c \
rtbuf_output_widget.c \
- rtbuf_widget.c
+ rtbuf_widget.c \
+ stack.c
rtbuf_includedir = $(includedir)/rtbuf
rtbuf_include_HEADERS = \
+ list.h \
+ queue.h \
rtbuf_gtk.h \
+ rtbuf_gtk_library.h \
rtbuf_input_widget.h \
rtbuf_output_widget.h \
- rtbuf_widget.h
+ rtbuf_widget.h \
+ stack.h
rtbuf_gtk_UI = \
rtbuf_input_widget.ui \
diff --git a/gtk/list.c b/gtk/list.c
new file mode 100644
index 0000000..17e121c
--- /dev/null
+++ b/gtk/list.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2020 Thomas de Grivel <thoxdg@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <stdlib.h>
+#include "list.h"
+
+s_list * list_new (void *item, s_list *next)
+{
+ s_list *list = malloc(sizeof(s_list));
+ if (list) {
+ list->item = item;
+ list->next = next;
+ }
+ return list;
+}
+
+void list_delete (s_list *list)
+{
+ free(list);
+}
+
+void list_delete_all (s_list *list)
+{
+ while (list) {
+ s_list *l = list;
+ list = list->next;
+ list_delete(l);
+ }
+}
diff --git a/gtk/list.h b/gtk/list.h
new file mode 100644
index 0000000..564742e
--- /dev/null
+++ b/gtk/list.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2020 Thomas de Grivel <thoxdg@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef LIST_H
+#define LIST_H
+
+typedef struct list s_list;
+
+struct list {
+ void *item;
+ s_list *next;
+};
+
+s_list * list_new (void *item, s_list *next);
+void list_delete (s_list *list);
+void list_delete_all (s_list *list);
+
+#endif /* LIST_H */
diff --git a/gtk/queue.c b/gtk/queue.c
new file mode 100644
index 0000000..333ef6e
--- /dev/null
+++ b/gtk/queue.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2020 Thomas de Grivel <thoxdg@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+#include "queue.h"
+
+void queue_init (s_queue *q)
+{
+ assert(q);
+ q->head = NULL;
+ q->tail = NULL;
+ q->length = 0;
+}
+
+void queue_destroy (s_queue *q)
+{
+ assert(q);
+ list_delete_all(q->head);
+ q->head = NULL;
+ q->tail = NULL;
+ q->length = 0;
+}
+
+s_queue * queue_new ()
+{
+ s_queue *q = malloc(sizeof(s_queue));
+ if (q)
+ queue_init(q);
+ return q;
+}
+
+void queue_delete (s_queue *q)
+{
+ assert(q);
+ queue_destroy(q);
+ free(q);
+}
+
+void queue_enqueue (s_queue *q, void *item)
+{
+ s_list *l;
+ assert(q);
+ l = list_new(item, NULL);
+ assert(l);
+ if (q->length == 0) {
+ q->head = q->tail = l;
+ }
+ else {
+ assert(q->tail);
+ q->tail->next = l;
+ q->tail = l;
+ }
+ q->length++;
+}
+
+void * queue_dequeue (s_queue *q)
+{
+ s_list *head;
+ void *item;
+ assert(q);
+ assert(q->length > 0);
+ assert(q->head);
+ head = q->head;
+ item = head->item;
+ q->head = head->next;
+ if (q->head == NULL)
+ q->tail = NULL;
+ q->length--;
+ list_delete(head);
+ return item;
+}
diff --git a/gtk/queue.h b/gtk/queue.h
new file mode 100644
index 0000000..5028df9
--- /dev/null
+++ b/gtk/queue.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2020 Thomas de Grivel <thoxdg@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef QUEUE_H
+#define QUEUE_H
+
+#include "list.h"
+
+typedef struct queue s_queue;
+
+struct queue {
+ s_list *head;
+ s_list *tail;
+ unsigned long length;
+};
+
+void queue_init (s_queue *q);
+void queue_destroy (s_queue *q);
+s_queue * queue_new ();
+void queue_delete (s_queue *q);
+void queue_enqueue (s_queue *q, void *item);
+void * queue_dequeue (s_queue *q);
+
+#endif /* LIST_H */
diff --git a/gtk/rtbuf_gtk.c b/gtk/rtbuf_gtk.c
index 941959d..332b50f 100644
--- a/gtk/rtbuf_gtk.c
+++ b/gtk/rtbuf_gtk.c
@@ -18,11 +18,13 @@
#include <gtk/gtk.h>
#include <stdio.h>
#include <rtbuf/rtbuf.h>
-#include "rtbuf_gtk.h"
-#include "rtbuf_input_widget.h"
#include <rtbuf/lib.h>
#include <rtbuf/var.h>
+#include "rtbuf_gtk.h"
+#include "rtbuf_gtk_library.h"
+#include "rtbuf_input_widget.h"
#include "rtbuf_widget.h"
+#include "stack.h"
unsigned int g_next_id = 0;
@@ -160,33 +162,56 @@ void rtbuf_gtk_library_menu_activate (GtkMenuItem *menuitem,
g_free(proc);
}
-void rtbuf_gtk_library_menu_library_item (GtkWidget *menuitem, gpointer data)
+void rtbuf_gtk_library_menu_library_item (GtkWidget *menuitem,
+ gpointer data)
{
gchar *library = (gchar*) data;
- g_signal_connect(menuitem, "activate", G_CALLBACK(rtbuf_gtk_library_menu_activate), library);
+ g_signal_connect(menuitem, "activate",
+ G_CALLBACK(rtbuf_gtk_library_menu_activate),
+ library);
}
-void rtbuf_gtk_library_menu_library (GtkWidget *menuitem, gpointer data)
+void rtbuf_gtk_destroy (GtkWidget *widget, gpointer data)
{
- GtkContainer *submenu;
- gchar *library;
(void) data;
- g_object_get(menuitem,
- "label", &library,
- "submenu", &submenu,
- NULL);
- gtk_container_foreach(submenu,
- rtbuf_gtk_library_menu_library_item,
- library);
- g_object_unref(G_OBJECT(submenu));
+ gtk_widget_destroy(widget);
}
void rtbuf_gtk_library_menu ()
{
- library_menu = GTK_MENU(gtk_builder_get_object(builder, "library_menu"));
- gtk_container_foreach(GTK_CONTAINER(library_menu),
- rtbuf_gtk_library_menu_library,
+ if (!library_menu)
+ library_menu = GTK_MENU(gtk_builder_get_object(builder,
+ "library_menu"));
+ gtk_container_foreach(GTK_CONTAINER(library_menu), rtbuf_gtk_destroy,
NULL);
+ if (g_rtbuf_gtk_library_tree) {
+ s_stack s;
+ stack_init(&s);
+ g_rtbuf_gtk_library_tree->menu = library_menu;
+ stack_push(&s, g_rtbuf_gtk_library_tree);
+ while (s.length) {
+ s_rtbuf_gtk_library_tree *tree = stack_pop(&s);
+ GtkMenu *menu = tree->menu;
+ while (tree) {
+ GtkWidget *item = gtk_menu_item_new_with_label(tree->dir_name);
+ gtk_container_add(GTK_CONTAINER(menu), item);
+ gtk_widget_show(item);
+ if (tree->children) {
+ GtkWidget *m = gtk_menu_new();
+ tree->children->menu = GTK_MENU(m);
+ gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), m);
+ stack_push(&s, tree->children);
+ }
+ else {
+ g_signal_connect(item, "activate",
+ G_CALLBACK(rtbuf_gtk_library_menu_activate),
+ (gpointer) tree->leaf_name);
+ }
+ tree = tree->next;
+ }
+ }
+ stack_destroy(&s);
+ }
}
void rtbuf_gtk_modular_close (GtkWidget *widget,
diff --git a/gtk/rtbuf_gtk.h b/gtk/rtbuf_gtk.h
index 2c12179..564c3ba 100644
--- a/gtk/rtbuf_gtk.h
+++ b/gtk/rtbuf_gtk.h
@@ -58,6 +58,4 @@ gboolean rtbuf_gtk_output_check_button_press (RtbufOutputWidget *widget,
gboolean rtbuf_gtk_output_check_button_release (RtbufOutputWidget *widget,
GdkEvent *event);
-void rtbuf_gtk_library_load ();
-
#endif /* RTBUF_GTK_H */
diff --git a/gtk/rtbuf_gtk_library.c b/gtk/rtbuf_gtk_library.c
index 968587c..600004c 100644
--- a/gtk/rtbuf_gtk_library.c
+++ b/gtk/rtbuf_gtk_library.c
@@ -14,7 +14,187 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <assert.h>
+#include <stdio.h>
+#include <gio/gio.h>
+#include <rtbuf/rtbuf.h>
+#include <rtbuf/lib.h>
+#include "rtbuf_gtk_library.h"
+#include "queue.h"
+
+s_rtbuf_gtk_library_tree *g_rtbuf_gtk_library_tree = NULL;
+
+s_rtbuf_gtk_library_tree * rtbuf_gtk_library_tree_new
+(const char *dir_name, const char *leaf_name,
+ s_rtbuf_gtk_library_tree *children,
+ s_rtbuf_gtk_library_tree *next)
+{
+ s_rtbuf_gtk_library_tree *tree =
+ malloc(sizeof(s_rtbuf_gtk_library_tree));
+ if (tree) {
+ tree->dir_name = dir_name;
+ tree->leaf_name = leaf_name;
+ tree->children = children;
+ tree->next = next;
+ }
+ return tree;
+}
+
+void rtbuf_gtk_library_tree_delete (s_rtbuf_gtk_library_tree *tree)
+{
+ s_queue q;
+ assert(tree);
+ queue_init(&q);
+ queue_enqueue(&q, tree);
+ while (q.length > 0) {
+ tree = queue_dequeue(&q);
+ if (tree->children)
+ queue_enqueue(&q, tree->children);
+ if (tree->next)
+ queue_enqueue(&q, tree->next);
+ free((void*) tree->dir_name);
+ tree->dir_name = 0;
+ free((void*) tree->leaf_name);
+ tree->leaf_name = 0;
+ free(tree);
+ }
+ queue_destroy(&q);
+}
+
+s_rtbuf_gtk_library_tree *
+rtbuf_gtk_library_tree_find_dir_name
+(s_rtbuf_gtk_library_tree *tree,
+ const char *dir_name,
+ size_t len)
+{
+ while (tree) {
+ if (strncmp(tree->dir_name, dir_name, len) == 0)
+ return tree;
+ tree = tree->next;
+ }
+ return NULL;
+}
+
+s_rtbuf_gtk_library_tree *
+rtbuf_gtk_library_tree_insert (s_rtbuf_gtk_library_tree **tree,
+ const char *dir_name,
+ const char *leaf_name)
+{
+ s_rtbuf_gtk_library_tree *t;
+ assert(tree);
+ t = rtbuf_gtk_library_tree_new(dir_name, leaf_name, NULL, *tree);
+ *tree = t;
+ return t;
+}
+
+void rtbuf_gtk_library_load_file_1 (const char *path,
+ size_t len,
+ size_t prefix_len,
+ size_t suffix_len)
+{
+ const char *dir_name;
+ const char *sep;
+ int leaf = 0;
+ s_rtbuf_gtk_library_tree **tree = &g_rtbuf_gtk_library_tree;
+ s_rtbuf_gtk_library_tree *found;
+ printf("Found library %s\n", path);
+ dir_name = path + prefix_len;
+ while (!leaf) {
+ sep = strchr(dir_name, '/');
+ if (!sep) {
+ sep = path + len - suffix_len;
+ leaf = 1;
+ }
+ found = rtbuf_gtk_library_tree_find_dir_name(*tree,
+ dir_name,
+ sep - dir_name);
+ if (!found) {
+ char *m_leaf_name = 0;
+ size_t dir_len = sep - dir_name;
+ char *m_dir_name = malloc(dir_len + 1);
+ memcpy(m_dir_name, dir_name, dir_len);
+ m_dir_name[dir_len] = 0;
+ if (leaf) {
+ size_t leaf_len = len - prefix_len - suffix_len;
+ m_leaf_name = malloc(leaf_len + 1);
+ memcpy(m_leaf_name, path + prefix_len, leaf_len);
+ m_leaf_name[leaf_len] = 0;
+ }
+ found = rtbuf_gtk_library_tree_insert(tree, m_dir_name, m_leaf_name);
+ }
+ printf("dir_name %s\n", found->dir_name);
+ if (leaf)
+ printf("leaf_name %s\n", found->leaf_name);
+ tree = &found->children;
+ dir_name = sep + 1;
+ }
+}
+
+void rtbuf_gtk_library_load_file (const char *path, size_t prefix_len)
+{
+ size_t len = strlen(path);
+ printf("file %s\n", path);
+ if (strncmp(&path[len - 7], ".so.0.0", 7) == 0)
+ rtbuf_gtk_library_load_file_1(path, len, prefix_len, 7);
+ else if (strncmp(&path[len - 4], ".dll", 4) == 0)
+ rtbuf_gtk_library_load_file_1(path, len, prefix_len, 4);
+}
+
+void rtbuf_gtk_library_load_directory (const char *path, size_t prefix_len)
+{
+ GFile *gf = g_file_new_for_path(path);
+ GError *error = NULL;
+ GFileEnumerator *dir_enum =
+ g_file_enumerate_children(gf, G_FILE_ATTRIBUTE_STANDARD_NAME,
+ G_FILE_QUERY_INFO_NONE, NULL, &error);
+ char child_path[PATH_MAX];
+ char *out = child_path;
+ const char *in = path;
+ while (*in)
+ *out++ = *in++;
+ printf("dir %s\n", path);
+ if (dir_enum) {
+ while (1) {
+ GFileInfo *info;
+ GFileType type;
+ char *name;
+ char *filename = out;
+ if (!g_file_enumerator_iterate(dir_enum, &info, NULL, NULL, &error))
+ goto out;
+ if (!info)
+ break;
+ type = g_file_info_get_file_type(info);
+ name = g_file_info_get_attribute_as_string(info, G_FILE_ATTRIBUTE_STANDARD_NAME);
+ if (name[0] != '.') {
+ in = name;
+ while (*in)
+ *filename++ = *in++;
+ *filename = 0;
+ if (type == G_FILE_TYPE_DIRECTORY) {
+ *filename++ = '/';
+ *filename = 0;
+ rtbuf_gtk_library_load_directory(child_path, prefix_len);
+ }
+ else
+ rtbuf_gtk_library_load_file(child_path, prefix_len);
+ }
+ }
+ }
+ return;
+ out:
+ g_object_unref(dir_enum);
+}
+
void rtbuf_gtk_library_load ()
{
-
+ char **path = g_rtbuf_lib_path;
+ if (g_rtbuf_gtk_library_tree) {
+ rtbuf_gtk_library_tree_delete(g_rtbuf_gtk_library_tree);
+ g_rtbuf_gtk_library_tree = NULL;
+ }
+ while (*path) {
+ printf("Loading rtbuf library in %s\n", *path);
+ rtbuf_gtk_library_load_directory(*path, strlen(*path));
+ path++;
+ }
}
diff --git a/gtk/rtbuf_gtk_library.h b/gtk/rtbuf_gtk_library.h
new file mode 100644
index 0000000..5b80c4e
--- /dev/null
+++ b/gtk/rtbuf_gtk_library.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2020 Thomas de Grivel <thoxdg@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef RTBUF_GTK_LIBRARY_H
+#define RTBUF_GTK_LIBRARY_H
+
+#include <gtk/gtk.h>
+
+typedef struct rtbuf_gtk_library_tree s_rtbuf_gtk_library_tree;
+
+struct rtbuf_gtk_library_tree {
+ const char *dir_name;
+ const char *leaf_name;
+ GtkMenu *menu;
+ s_rtbuf_gtk_library_tree *children;
+ s_rtbuf_gtk_library_tree *next;
+};
+
+extern s_rtbuf_gtk_library_tree *g_rtbuf_gtk_library_tree;
+
+void rtbuf_gtk_library_load ();
+
+#endif /* RTBUF_GTK_LIBRARY_H */
diff --git a/gtk/stack.c b/gtk/stack.c
new file mode 100644
index 0000000..eea5d02
--- /dev/null
+++ b/gtk/stack.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2020 Thomas de Grivel <thoxdg@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <assert.h>
+#include "stack.h"
+
+void stack_init (s_stack *s)
+{
+ assert(s);
+ s->head = 0;
+ s->length = 0;
+}
+
+void stack_destroy (s_stack *s)
+{
+ assert(s);
+ list_delete_all(s->head);
+ s->head = 0;
+ s->length = 0;
+}
+
+void stack_push (s_stack *s, void *item)
+{
+ assert(s);
+ s->head = list_new(item, s->head);
+ assert(s->head);
+ s->length++;
+}
+
+void * stack_pop (s_stack *s)
+{
+ void *item;
+ assert(s);
+ assert(s->length > 0);
+ assert(s->head);
+ item = s->head->item;
+ s->head = s->head->next;
+ s->length--;
+ return item;
+}
diff --git a/gtk/stack.h b/gtk/stack.h
new file mode 100644
index 0000000..9b711c0
--- /dev/null
+++ b/gtk/stack.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2020 Thomas de Grivel <thoxdg@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef STACK_H
+#define STACK_H
+
+#include "list.h"
+
+typedef struct stack s_stack;
+
+struct stack {
+ s_list *head;
+ unsigned long length;
+};
+
+void stack_init (s_stack *s);
+void stack_destroy (s_stack *s);
+void stack_push (s_stack *s, void *item);
+void * stack_pop (s_stack *s);
+
+#endif /* STACK_H */
diff --git a/librtbuf/include/rtbuf/lib.h b/librtbuf/include/rtbuf/lib.h
index cdc5ff2..861db6f 100644
--- a/librtbuf/include/rtbuf/lib.h
+++ b/librtbuf/include/rtbuf/lib.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2018 Thomas de Grivel <thoxdg@gmail.com> +33614550127
+ * Copyright 2018,2020 Thomas de Grivel <thoxdg@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -50,6 +50,8 @@ struct rtbuf_lib {
const char *path;
};
+extern char *g_rtbuf_lib_path[];
+
extern s_data_alloc g_rtbuf_lib_alloc;
extern s_rtbuf_lib *g_rtbuf_lib;
diff --git a/librtbuf/rtbuf_lib.c b/librtbuf/rtbuf_lib.c
index 0fa9f86..c3d391a 100644
--- a/librtbuf/rtbuf_lib.c
+++ b/librtbuf/rtbuf_lib.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2018 Thomas de Grivel <thoxdg@gmail.com> +33614550127
+ * Copyright 2018,2020 Thomas de Grivel <thoxdg@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above