Add proof-of-concept selection support to terminal

Next will be to support mouse selections so we can copy and paste
something more interesting than just 'selection data'.
diff --git a/clients/terminal.c b/clients/terminal.c
index a89a5bf..ab9bdb3 100644
--- a/clients/terminal.c
+++ b/clients/terminal.c
@@ -390,6 +390,11 @@
 	struct terminal_color color_table[256];
 	cairo_font_extents_t extents;
 	cairo_scaled_font_t *font_normal, *font_bold;
+
+	uint32_t tag;
+	struct wl_selection *selection;
+	struct wl_selection_offer *selection_offer;
+	uint32_t selection_offer_has_text;
 };
 
 /* Create default tab stops, every 8 characters */
@@ -1872,6 +1877,88 @@
 }
 
 static void
+selection_listener_send(void *data, struct wl_selection *selection,
+			const char *mime_type, int fd)
+{
+	struct terminal *terminal = data;
+	static const char msg[] = "selection data";
+
+	fprintf(stderr, "selection send, fd is %d\n", fd);
+	write(fd, msg, sizeof msg);
+	close(fd);
+}
+
+static void
+selection_listener_cancelled(void *data, struct wl_selection *selection)
+{
+	struct terminal *terminal = data;
+
+	fprintf(stderr, "selection cancelled\n");
+	wl_selection_destroy(selection);
+}
+
+static const struct wl_selection_listener selection_listener = {
+	selection_listener_send,
+	selection_listener_cancelled
+};
+
+static gboolean
+selection_io_func(GIOChannel *source, GIOCondition condition, gpointer data)
+{
+	struct terminal *terminal = data;
+	char buffer[256];
+	unsigned int len;
+	int fd;
+
+	fd = g_io_channel_unix_get_fd(source);
+	len = read(fd, buffer, sizeof buffer);
+	fprintf(stderr, "read %d bytes: %.*s\n", len, len, buffer);
+
+	close(fd);
+	g_source_remove(terminal->tag);
+
+	g_io_channel_unref(source);
+
+	return TRUE;
+}
+
+static int
+handle_bound_key(struct terminal *terminal,
+		 struct input *input, uint32_t sym, uint32_t time)
+{
+	struct wl_shell *shell;
+	GIOChannel *channel;
+	int fd;
+
+	switch (sym) {
+	case XK_C:
+		shell = display_get_shell(terminal->display);
+		terminal->selection = wl_shell_create_selection(shell);
+		wl_selection_add_listener(terminal->selection,
+					  &selection_listener, terminal);
+		wl_selection_offer(terminal->selection, "text/plain");
+		wl_selection_activate(terminal->selection,
+				      input_get_input_device(input), time);
+
+		return 1;
+	case XK_V:
+		if (input_offers_mime_type(input, "text/plain")) {
+			fd = input_receive_mime_type(input, "text/plain");
+			channel = g_io_channel_unix_new(fd);
+			terminal->tag = g_io_add_watch(channel, G_IO_IN,
+						       selection_io_func,
+						       terminal);
+		}
+
+		return 1;
+	case XK_X:
+		/* cut selection; terminal doesn't do cut */
+		return 0;
+	default:
+		return 0;
+	}
+}
+
 static void
 key_handler(struct window *window, struct input *input, uint32_t time,
 	    uint32_t key, uint32_t sym, uint32_t state, void *data)