+ inst->currcursor = inst->rawcursor;
+ else
+ inst->currcursor = inst->textcursor;
+ show_mouseptr(inst, inst->mouseptr_visible);
+}
+
+void request_resize(void *frontend, int w, int h)
+{
+ struct gui_data *inst = (struct gui_data *)frontend;
+ int large_x, large_y;
+ int offset_x, offset_y;
+ int area_x, area_y;
+ GtkRequisition inner, outer;
+
+ /*
+ * This is a heinous hack dreamed up by the gnome-terminal
+ * people to get around a limitation in gtk. The problem is
+ * that in order to set the size correctly we really need to be
+ * calling gtk_window_resize - but that needs to know the size
+ * of the _whole window_, not the drawing area. So what we do
+ * is to set an artificially huge size request on the drawing
+ * area, recompute the resulting size request on the window,
+ * and look at the difference between the two. That gives us
+ * the x and y offsets we need to translate drawing area size
+ * into window size for real, and then we call
+ * gtk_window_resize.
+ */
+
+ /*
+ * We start by retrieving the current size of the whole window.
+ * Adding a bit to _that_ will give us a value we can use as a
+ * bogus size request which guarantees to be bigger than the
+ * current size of the drawing area.
+ */
+ get_window_pixels(inst, &large_x, &large_y);
+ large_x += 32;
+ large_y += 32;
+
+#if GTK_CHECK_VERSION(2,0,0)
+ gtk_widget_set_size_request(inst->area, large_x, large_y);
+#else
+ gtk_widget_set_usize(inst->area, large_x, large_y);
+#endif
+ gtk_widget_size_request(inst->area, &inner);
+ gtk_widget_size_request(inst->window, &outer);
+
+ offset_x = outer.width - inner.width;
+ offset_y = outer.height - inner.height;
+
+ area_x = inst->font_width * w + 2*inst->cfg.window_border;
+ area_y = inst->font_height * h + 2*inst->cfg.window_border;
+
+ /*
+ * Now we must set the size request on the drawing area back to
+ * something sensible before we commit the real resize. Best
+ * way to do this, I think, is to set it to what the size is
+ * really going to end up being.
+ */
+#if GTK_CHECK_VERSION(2,0,0)
+ gtk_widget_set_size_request(inst->area, area_x, area_y);
+#else
+ gtk_widget_set_usize(inst->area, area_x, area_y);
+#endif
+
+#if GTK_CHECK_VERSION(2,0,0)
+ gtk_window_resize(GTK_WINDOW(inst->window),
+ area_x + offset_x, area_y + offset_y);
+#else
+ gdk_window_resize(inst->window->window,
+ area_x + offset_x, area_y + offset_y);
+#endif
+}
+
+static void real_palette_set(struct gui_data *inst, int n, int r, int g, int b)
+{
+ gboolean success[1];
+
+ inst->cols[n].red = r * 0x0101;
+ inst->cols[n].green = g * 0x0101;
+ inst->cols[n].blue = b * 0x0101;
+
+ gdk_colormap_alloc_colors(inst->colmap, inst->cols + n, 1,
+ FALSE, FALSE, success);
+ if (!success[0])
+ g_error("pterm: couldn't allocate colour %d (#%02x%02x%02x)\n",
+ n, r, g, b);
+}
+
+void set_window_background(struct gui_data *inst)
+{
+ if (inst->area && inst->area->window)
+ gdk_window_set_background(inst->area->window, &inst->cols[18]);
+ if (inst->window && inst->window->window)
+ gdk_window_set_background(inst->window->window, &inst->cols[18]);
+}
+
+void palette_set(void *frontend, int n, int r, int g, int b)
+{
+ struct gui_data *inst = (struct gui_data *)frontend;
+ static const int first[21] = {
+ 0, 2, 4, 6, 8, 10, 12, 14,
+ 1, 3, 5, 7, 9, 11, 13, 15,
+ 16, 17, 18, 20, 22
+ };
+ real_palette_set(inst, first[n], r, g, b);
+ if (first[n] >= 18)
+ real_palette_set(inst, first[n] + 1, r, g, b);
+ if (first[n] == 18)
+ set_window_background(inst);
+}
+
+void palette_reset(void *frontend)
+{
+ struct gui_data *inst = (struct gui_data *)frontend;
+ /* This maps colour indices in inst->cfg to those used in inst->cols. */
+ static const int ww[] = {
+ 6, 7, 8, 9, 10, 11, 12, 13,
+ 14, 15, 16, 17, 18, 19, 20, 21,
+ 0, 1, 2, 3, 4, 5
+ };
+ gboolean success[NCOLOURS];
+ int i;
+
+ assert(lenof(ww) == NCOLOURS);
+
+ if (!inst->colmap) {
+ inst->colmap = gdk_colormap_get_system();
+ } else {
+ gdk_colormap_free_colors(inst->colmap, inst->cols, NCOLOURS);
+ }
+
+ for (i = 0; i < NCOLOURS; i++) {
+ inst->cols[i].red = inst->cfg.colours[ww[i]][0] * 0x0101;
+ inst->cols[i].green = inst->cfg.colours[ww[i]][1] * 0x0101;
+ inst->cols[i].blue = inst->cfg.colours[ww[i]][2] * 0x0101;
+ }
+
+ gdk_colormap_alloc_colors(inst->colmap, inst->cols, NCOLOURS,
+ FALSE, FALSE, success);
+ for (i = 0; i < NCOLOURS; i++) {
+ if (!success[i])
+ g_error("pterm: couldn't allocate colour %d (#%02x%02x%02x)\n",
+ i, inst->cfg.colours[i][0], inst->cfg.colours[i][1], inst->cfg.colours[i][2]);
+ }
+
+ set_window_background(inst);
+}
+
+void write_clip(void *frontend, wchar_t * data, int len, int must_deselect)
+{
+ struct gui_data *inst = (struct gui_data *)frontend;
+ if (inst->pasteout_data)
+ sfree(inst->pasteout_data);
+ if (inst->pasteout_data_utf8)
+ sfree(inst->pasteout_data_utf8);
+
+ /*
+ * Set up UTF-8 paste data. This only happens if we aren't in
+ * direct-to-font mode using the D800 hack.
+ */
+ if (!inst->direct_to_font) {
+ wchar_t *tmp = data;
+ int tmplen = len;
+
+ inst->pasteout_data_utf8 = smalloc(len*6);
+ inst->pasteout_data_utf8_len = len*6;
+ inst->pasteout_data_utf8_len =
+ charset_from_unicode(&tmp, &tmplen, inst->pasteout_data_utf8,
+ inst->pasteout_data_utf8_len,
+ CS_UTF8, NULL, NULL, 0);
+ if (inst->pasteout_data_utf8_len == 0) {
+ sfree(inst->pasteout_data_utf8);
+ inst->pasteout_data_utf8 = NULL;
+ } else {
+ inst->pasteout_data_utf8 =
+ srealloc(inst->pasteout_data_utf8,
+ inst->pasteout_data_utf8_len);
+ }
+ } else {
+ inst->pasteout_data_utf8 = NULL;
+ inst->pasteout_data_utf8_len = 0;
+ }
+
+ inst->pasteout_data = smalloc(len*6);
+ inst->pasteout_data_len = len*6;
+ inst->pasteout_data_len = wc_to_mb(inst->ucsdata.line_codepage, 0,
+ data, len, inst->pasteout_data,
+ inst->pasteout_data_len,
+ NULL, NULL, NULL);
+ if (inst->pasteout_data_len == 0) {
+ sfree(inst->pasteout_data);
+ inst->pasteout_data = NULL;
+ } else {
+ inst->pasteout_data =
+ srealloc(inst->pasteout_data, inst->pasteout_data_len);
+ }
+
+ if (gtk_selection_owner_set(inst->area, GDK_SELECTION_PRIMARY,
+ GDK_CURRENT_TIME)) {
+ gtk_selection_add_target(inst->area, GDK_SELECTION_PRIMARY,
+ GDK_SELECTION_TYPE_STRING, 1);
+ gtk_selection_add_target(inst->area, GDK_SELECTION_PRIMARY,
+ inst->compound_text_atom, 1);
+ if (inst->pasteout_data_utf8)
+ gtk_selection_add_target(inst->area, GDK_SELECTION_PRIMARY,
+ inst->utf8_string_atom, 1);
+ }
+}
+
+void selection_get(GtkWidget *widget, GtkSelectionData *seldata,
+ guint info, guint time_stamp, gpointer data)
+{
+ struct gui_data *inst = (struct gui_data *)data;
+ if (seldata->target == inst->utf8_string_atom)
+ gtk_selection_data_set(seldata, seldata->target, 8,
+ inst->pasteout_data_utf8,
+ inst->pasteout_data_utf8_len);