commit 87d191828a7c0dd4eec3f61dc07fd40768a45f8c
parent 700df2e2739b914fa2738404f949f791814cf7d4
Author: lumidify <nobody@lumidify.org>
Date:   Thu,  7 Jan 2021 20:41:23 +0100
Add 'destroy' command; make grid sticky format more readable
Diffstat:
| M | grid.c |  |  | 29 | +++++++++++++++++++++++------ | 
| M | ltk.h |  |  | 16 | +++++++++------- | 
| M | ltkd.c |  |  | 45 | +++++++++++++++++++++++++++++++++++++++++++++ | 
| M | test.gui |  |  | 4 | ++-- | 
| M | test.sh |  |  | 8 | ++++++-- | 
5 files changed, 85 insertions(+), 17 deletions(-)
diff --git a/grid.c b/grid.c
@@ -111,6 +111,7 @@ ltk_grid_create(ltk_window *window, const char *id, int rows, int columns) {
 	grid->widget.mouse_release = <k_grid_mouse_release;
 	grid->widget.motion_notify = <k_grid_motion_notify;
 	grid->widget.resize = <k_recalculate_grid;
+	grid->widget.remove_child = <k_grid_ungrid;
 
 	grid->rows = rows;
 	grid->columns = columns;
@@ -258,6 +259,7 @@ ltk_recalculate_grid(ltk_grid *grid) {
 	}
 }
 
+/* FIXME: Check if widget already exists at position */
 static int
 ltk_grid_add(ltk_window *window, ltk_widget *widget, ltk_grid *grid,
     int row, int column, int row_span, int column_span, unsigned short sticky, char **errstr) {
@@ -376,18 +378,22 @@ ltk_grid_cmd_add(
     char **tokens,
     size_t num_tokens,
     char **errstr) {
+	const char *c;
 	ltk_grid *grid;
 	ltk_widget *widget;
 	const char *errstr_num;
 
-	int row, column, row_span, column_span, sticky;
+	int row, column, row_span, column_span, sticky = 0;
 	if (num_tokens != 9) {
 		*errstr = "Invalid number of arguments.\n";
 		return 1;
 	}
 	grid = ltk_get_widget(tokens[1], LTK_GRID, errstr);
 	widget = ltk_get_widget(tokens[3], LTK_WIDGET, errstr);
-	if (!grid || !widget) return 1;
+	if (!grid || !widget) {
+		*errstr = "Invalid widget ID.\n";
+		return 1;
+	}
 	row         = strtonum(tokens[4], 0, grid->rows - 1, &errstr_num);
 	if (errstr_num) {
 		*errstr = "Invalid row number.\n";
@@ -408,11 +414,22 @@ ltk_grid_cmd_add(
 		*errstr = "Invalid column span.\n";
 		return 1;
 	}
-	sticky      = strtonum(tokens[8], 0, 15, &errstr_num);
-	if (errstr_num) {
-		*errstr = "Invalid sticky setting.\n";
-		return 1;
+
+	for (c = tokens[8]; *c != '\0'; c++) {
+		if (*c == 'n') {
+			sticky |= LTK_STICKY_TOP;
+		} else if (*c == 's') {
+			sticky |= LTK_STICKY_BOTTOM;
+		} else if (*c == 'e') {
+			sticky |= LTK_STICKY_RIGHT;
+		} else if (*c == 'w') {
+			sticky |= LTK_STICKY_LEFT;
+		} else if (*c != 'u') {
+			*errstr = "Invalid sticky specification.\n";
+			return 1;
+		}
 	}
+
 	return ltk_grid_add(window, widget, grid, row, column, row_span, column_span, sticky, errstr);
 }
 
diff --git a/ltk.h b/ltk.h
@@ -70,19 +70,21 @@ typedef struct ltk_widget {
 	struct ltk_widget *parent;
 	char *id;
 
-	void (*key_press) (void *, XEvent event);
-	void (*key_release) (void *, XEvent event);
-	void (*mouse_press) (void *, XEvent event);
-	void (*mouse_release) (void *, XEvent event);
-	void (*motion_notify) (void *, XEvent event);
-	void (*mouse_leave) (void *, XEvent event);
-	void (*mouse_enter) (void *, XEvent event);
+	void (*key_press) (void *, XEvent);
+	void (*key_release) (void *, XEvent);
+	void (*mouse_press) (void *, XEvent);
+	void (*mouse_release) (void *, XEvent);
+	void (*motion_notify) (void *, XEvent);
+	void (*mouse_leave) (void *, XEvent);
+	void (*mouse_enter) (void *, XEvent);
 
 	void (*resize) (void *, int, int);
 	void (*draw) (void *);
 	void (*change_state) (void *);
 	void (*destroy) (void *, int);
 
+	int (*remove_child) (ltk_window *, void *, void *, char **);
+
 	ltk_widget_type type;
 	ltk_widget_state state;
 	unsigned int sticky;
diff --git a/ltkd.c b/ltkd.c
@@ -1,5 +1,6 @@
 /* FIXME: error checking in tokenizer (is this necessary?) */
 /* FIXME: parsing doesn't work properly with bs? */
+/* FIXME: strip whitespace at end of lines in socket format */
 /*
  * This file is part of the Lumidify ToolKit (LTK)
  * Copyright (c) 2016, 2017, 2018, 2020, 2021 lumidify <nobody@lumidify.org>
@@ -111,6 +112,7 @@ static ltk_rect ltk_rect_union(ltk_rect r1, ltk_rect r2);
 static int add_client(int fd);
 static int listen_sock(const char *sock_path);
 static int accept_sock(int listenfd);
+static int ltk_widget_destroy(ltk_window *window, char **tokens, size_t num_tokens, char **errstr);
 
 static short maxsocket = -1;
 static short running = 1;
@@ -753,6 +755,7 @@ ltk_fill_widget_defaults(ltk_widget *widget, const char *id, ltk_window *window,
 	widget->draw = draw;
 	widget->change_state = change_state;
 	widget->destroy = destroy;
+	widget->remove_child = NULL;
 
 	widget->needs_redraw = needs_redraw;
 	widget->state = LTK_NORMAL;
@@ -1151,6 +1154,8 @@ process_commands(ltk_window *window, struct ltk_sock_info *sock) {
 			err = ltk_draw_cmd(window, tokens, num_tokens, &errstr);
 		} else if (strcmp(tokens[0], "quit") == 0) {
 			ltk_quit(window);
+		} else if (strcmp(tokens[0], "destroy") == 0) {
+			err = ltk_widget_destroy(window, tokens, num_tokens, &errstr);
 		} else {
 			errstr = "Invalid command.\n";
 			err = 1;
@@ -1175,3 +1180,43 @@ process_commands(ltk_window *window, struct ltk_sock_info *sock) {
 		sock->read_cur = 0;
 	}
 }
+
+static int
+ltk_widget_destroy(
+    ltk_window *window,
+    char **tokens,
+    size_t num_tokens,
+    char **errstr) {
+	int err = 0, shallow = 1;
+	khint_t k;
+	if (num_tokens != 2 && num_tokens != 3) {
+		*errstr = "Invalid number of arguments.\n";
+		return 1;
+	}
+	if (num_tokens == 3) {
+		if (strcmp(tokens[2], "deep") == 0) {
+			shallow = 0;
+		} else if (strcmp(tokens[2], "shallow") == 0) {
+			shallow = 1;
+		} else {
+			*errstr = "Invalid argument: must be 'shallow' or 'deep'.\n";
+			return 1;
+		}
+	}
+	ltk_widget *widget = ltk_get_widget(tokens[1], LTK_WIDGET, errstr);
+	if (!widget) {
+		*errstr = "Invalid widget ID.\n";
+		return 1;
+	}
+	ltk_remove_widget(tokens[1]);
+	/* widget->parent->remove_child should never be NULl because of the fact that
+	   the widget is set as parent, but let's just check anyways... */
+	if (widget->parent && widget->parent->remove_child) {
+		err = widget->parent->remove_child(
+		    window, widget, widget->parent, errstr
+		);
+	}
+	widget->destroy(widget, shallow);
+
+	return err;
+}
diff --git a/test.gui b/test.gui
@@ -5,6 +5,6 @@ grid grd1 set-column-weight 0 1
 grid grd1 set-column-weight 1 1
 set-root-widget grd1
 button btn1 create "I'm a button!"
-grid grd1 add btn1 0 0 1 1 0
+grid grd1 add btn1 0 0 1 1 u
 button btn2 create "I'm also a button!"
-grid grd1 add btn2 1 0 1 2 3
+grid grd1 add btn2 1 0 1 2 ew
diff --git a/test.sh b/test.sh
@@ -16,7 +16,11 @@ fi
 cat test.gui | ./ltkc $ltk_id | while read cmd
 do
 	case "$cmd" in
-	"btn1 button_click") echo "quit"
-	;;
+	"btn1 button_click")
+		echo "quit"
+		;;
+	*)
+		printf "%s\n" "$cmd" >&2
+		;;
 	esac
 done | ./ltkc $ltk_id