Render selection
diff --git a/clients/terminal.c b/clients/terminal.c
index 2097400..9729268 100644
--- a/clients/terminal.c
+++ b/clients/terminal.c
@@ -395,6 +395,9 @@
 	struct wl_selection *selection;
 	struct wl_selection_offer *selection_offer;
 	uint32_t selection_offer_has_text;
+	int32_t dragging, selection_active;
+	int selection_start_x, selection_start_y;
+	int selection_end_x, selection_end_y;
 };
 
 /* Create default tab stops, every 8 characters */
@@ -492,16 +495,62 @@
 	uint32_t key;
 };
 
+static int
+terminal_compare_position(struct terminal *terminal,
+			  int x, int y, int32_t ref_row, int32_t ref_col)
+{
+	struct rectangle allocation;
+	int top_margin, side_margin, col, row, ref_x;
+
+	window_get_child_allocation(terminal->window, &allocation);
+	side_margin = allocation.x + (allocation.width - terminal->width * terminal->extents.max_x_advance) / 2;
+	top_margin = allocation.y + (allocation.height - terminal->height * terminal->extents.height) / 2;
+
+	col = (x - side_margin) / terminal->extents.max_x_advance;
+	row = (y - top_margin) / terminal->extents.height;
+
+	ref_x = side_margin + ref_col * terminal->extents.max_x_advance +
+		terminal->extents.max_x_advance / 2;
+
+	if (row < ref_row)
+		return -1;
+	if (row == ref_row) {
+		if (col < ref_col)
+			return -1;
+		if (col == ref_col && x < ref_x)
+			return -1;
+	}
+
+	return 1;
+}
+
 static void
 terminal_decode_attr(struct terminal *terminal, int row, int col,
 		     union decoded_attr *decoded)
 {
 	struct attr attr;
 	int foreground, background, tmp;
+	int inverse = 0, start_cmp, end_cmp;
+
+	start_cmp =
+		terminal_compare_position(terminal,
+					  terminal->selection_start_x,
+					  terminal->selection_start_y,
+					  row, col);
+	end_cmp =
+		terminal_compare_position(terminal,
+					  terminal->selection_end_x,
+					  terminal->selection_end_y,
+					  row, col);
+	if (start_cmp < 0 && end_cmp > 0)
+		inverse = 1;
+	else if (end_cmp < 0 && start_cmp > 0)
+		inverse = 1;
 
 	/* get the attributes for this character cell */
 	attr = terminal_get_attr_row(terminal, row)[col];
 	if ((attr.a & ATTRMASK_INVERSE) ||
+	    inverse ||
 	    ((terminal->mode & MODE_SHOW_CURSOR) &&
 	     terminal->focused && terminal->row == row &&
 	     terminal->column == col)) {
@@ -835,7 +884,6 @@
 {
 	struct rectangle allocation;
 	cairo_t *cr;
-	cairo_font_extents_t extents;
 	int top_margin, side_margin;
 	int row, col;
 	union utf8_char *p_row;
@@ -844,6 +892,7 @@
 	cairo_surface_t *surface;
 	double d;
 	struct glyph_run run;
+	cairo_font_extents_t extents;
 
 	window_get_child_allocation(terminal->window, &allocation);
 
@@ -855,7 +904,7 @@
 
 	cairo_set_scaled_font(cr, terminal->font_normal);
 
-	cairo_font_extents(cr, &extents);
+	extents = terminal->extents;
 	side_margin = (allocation.width - terminal->width * extents.max_x_advance) / 2;
 	top_margin = (allocation.height - terminal->height * extents.height) / 2;
 
@@ -1880,19 +1929,16 @@
 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);
+	write(fd, msg, sizeof msg - 1);
 	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);
 }
@@ -1914,6 +1960,8 @@
 	len = read(fd, buffer, sizeof buffer);
 	fprintf(stderr, "read %d bytes: %.*s\n", len, len, buffer);
 
+	write(terminal->master, buffer, len);
+
 	close(fd);
 	g_source_remove(terminal->tag);
 
@@ -2102,6 +2150,50 @@
 	window_schedule_redraw(terminal->window);
 }
 
+static void
+button_handler(struct window *window,
+	       struct input *input, uint32_t time,
+	       int button, int state, void *data)
+{
+	struct terminal *terminal = data;
+
+	switch (button) {
+	case 272:
+		if (state) {
+			terminal->dragging = 1;
+			terminal->selection_active = 0;
+			input_get_position(input,
+					   &terminal->selection_start_x,
+					   &terminal->selection_start_y);
+			terminal->selection_end_x = terminal->selection_start_x;
+			terminal->selection_end_y = terminal->selection_start_y;
+			window_schedule_redraw(window);
+		} else {
+			terminal->dragging = 0;
+		}
+		break;
+	}
+}
+
+static int
+motion_handler(struct window *window,
+	       struct input *input, uint32_t time,
+	       int32_t x, int32_t y,
+	       int32_t sx, int32_t sy, void *data)
+{
+	struct terminal *terminal = data;
+
+	if (terminal->dragging) {
+		terminal->selection_active = 1;
+		input_get_position(input,
+				   &terminal->selection_end_x,
+				   &terminal->selection_end_y);
+		window_schedule_redraw(window);
+	}
+
+	return POINTER_IBEAM;
+}
+
 static struct terminal *
 terminal_create(struct display *display, int fullscreen)
 {
@@ -2136,6 +2228,8 @@
 	window_set_key_handler(terminal->window, key_handler);
 	window_set_keyboard_focus_handler(terminal->window,
 					  keyboard_focus_handler);
+	window_set_button_handler(terminal->window, button_handler);
+	window_set_motion_handler(terminal->window, motion_handler);
 
 	surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 0, 0);
 	cr = cairo_create(surface);