⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gtkwin.c

📁 putty
💻 C
📖 第 1 页 / 共 5 页
字号:
    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);
    gtk_drawing_area_size(GTK_DRAWING_AREA(inst->area), area_x, area_y);
#endif

    gtk_container_dequeue_resize_handler(GTK_CONTAINER(inst->window));

#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_free_colors(inst->colmap, inst->cols + n, 1);
    gdk_colormap_alloc_colors(inst->colmap, inst->cols + n, 1,
			      FALSE, TRUE, success);
    if (!success[0])
	g_error("%s: couldn't allocate colour %d (#%02x%02x%02x)\n", appname,
		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[258]);
    if (inst->window && inst->window->window)
	gdk_window_set_background(inst->window->window, &inst->cols[258]);
}

void palette_set(void *frontend, int n, int r, int g, int b)
{
    struct gui_data *inst = (struct gui_data *)frontend;
    if (n >= 16)
	n += 256 - 16;
    if (n > NALLCOLOURS)
	return;
    real_palette_set(inst, n, r, g, b);
    if (n == 258) {
	/* Default Background changed. Ensure space between text area and
	 * window border is redrawn */
	set_window_background(inst);
	draw_backing_rect(inst);
	gtk_widget_queue_draw(inst->area);
    }
}

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[] = {
	256, 257, 258, 259, 260, 261,
	0, 8, 1, 9, 2, 10, 3, 11,
	4, 12, 5, 13, 6, 14, 7, 15
    };
    gboolean success[NALLCOLOURS];
    int i;

    assert(lenof(ww) == NCFGCOLOURS);

    if (!inst->colmap) {
	inst->colmap = gdk_colormap_get_system();
    } else {
	gdk_colormap_free_colors(inst->colmap, inst->cols, NALLCOLOURS);
    }

    for (i = 0; i < NCFGCOLOURS; i++) {
	inst->cols[ww[i]].red = inst->cfg.colours[i][0] * 0x0101;
	inst->cols[ww[i]].green = inst->cfg.colours[i][1] * 0x0101;
	inst->cols[ww[i]].blue = inst->cfg.colours[i][2] * 0x0101;
    }

    for (i = 0; i < NEXTCOLOURS; i++) {
	if (i < 216) {
	    int r = i / 36, g = (i / 6) % 6, b = i % 6;
	    inst->cols[i+16].red = r ? r * 0x2828 + 0x3737 : 0;
	    inst->cols[i+16].green = g ? g * 0x2828 + 0x3737 : 0;
	    inst->cols[i+16].blue = b ? b * 0x2828 + 0x3737 : 0;
	} else {
	    int shade = i - 216;
	    shade = shade * 0x0a0a + 0x0808;
	    inst->cols[i+16].red = inst->cols[i+16].green =
		inst->cols[i+16].blue = shade;
	}
    }

    gdk_colormap_alloc_colors(inst->colmap, inst->cols, NALLCOLOURS,
			      FALSE, TRUE, success);
    for (i = 0; i < NALLCOLOURS; i++) {
	if (!success[i])
	    g_error("%s: couldn't allocate colour %d (#%02x%02x%02x)\n",
                    appname, i, inst->cfg.colours[i][0],
                    inst->cfg.colours[i][1], inst->cfg.colours[i][2]);
    }

    /* Since Default Background may have changed, ensure that space
     * between text area and window border is refreshed. */
    set_window_background(inst);
    if (inst->area) {
	draw_backing_rect(inst);
	gtk_widget_queue_draw(inst->area);
    }
}

/* Ensure that all the cut buffers exist - according to the ICCCM, we must
 * do this before we start using cut buffers.
 */
void init_cutbuffers()
{
    unsigned char empty[] = "";
    XChangeProperty(GDK_DISPLAY(), GDK_ROOT_WINDOW(),
		    XA_CUT_BUFFER0, XA_STRING, 8, PropModeAppend, empty, 0);
    XChangeProperty(GDK_DISPLAY(), GDK_ROOT_WINDOW(),
		    XA_CUT_BUFFER1, XA_STRING, 8, PropModeAppend, empty, 0);
    XChangeProperty(GDK_DISPLAY(), GDK_ROOT_WINDOW(),
		    XA_CUT_BUFFER2, XA_STRING, 8, PropModeAppend, empty, 0);
    XChangeProperty(GDK_DISPLAY(), GDK_ROOT_WINDOW(),
		    XA_CUT_BUFFER3, XA_STRING, 8, PropModeAppend, empty, 0);
    XChangeProperty(GDK_DISPLAY(), GDK_ROOT_WINDOW(),
		    XA_CUT_BUFFER4, XA_STRING, 8, PropModeAppend, empty, 0);
    XChangeProperty(GDK_DISPLAY(), GDK_ROOT_WINDOW(),
		    XA_CUT_BUFFER5, XA_STRING, 8, PropModeAppend, empty, 0);
    XChangeProperty(GDK_DISPLAY(), GDK_ROOT_WINDOW(),
		    XA_CUT_BUFFER6, XA_STRING, 8, PropModeAppend, empty, 0);
    XChangeProperty(GDK_DISPLAY(), GDK_ROOT_WINDOW(),
		    XA_CUT_BUFFER7, XA_STRING, 8, PropModeAppend, empty, 0);
}

/* Store the data in a cut-buffer. */
void store_cutbuffer(char * ptr, int len)
{
    /* ICCCM says we must rotate the buffers before storing to buffer 0. */
    XRotateBuffers(GDK_DISPLAY(), 1);
    XStoreBytes(GDK_DISPLAY(), ptr, len);
}

/* Retrieve data from a cut-buffer.
 * Returned data needs to be freed with XFree().
 */
char * retrieve_cutbuffer(int * nbytes)
{
    char * ptr;
    ptr = XFetchBytes(GDK_DISPLAY(), nbytes);
    if (*nbytes <= 0 && ptr != 0) {
	XFree(ptr);
	ptr = 0;
    }
    return ptr;
}

void write_clip(void *frontend, wchar_t * data, int *attr, 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_ctext)
	sfree(inst->pasteout_data_ctext);
    if (inst->pasteout_data_utf8)
	sfree(inst->pasteout_data_utf8);

    /*
     * Set up UTF-8 and compound text 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;
	XTextProperty tp;
	char *list[1];

	inst->pasteout_data_utf8 = snewn(len*6, char);
	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 =
		sresize(inst->pasteout_data_utf8,
			inst->pasteout_data_utf8_len + 1, char);
	    inst->pasteout_data_utf8[inst->pasteout_data_utf8_len] = '\0';
	}

	/*
	 * Now let Xlib convert our UTF-8 data into compound text.
	 */
	list[0] = inst->pasteout_data_utf8;
	if (Xutf8TextListToTextProperty(GDK_DISPLAY(), list, 1,
					XCompoundTextStyle, &tp) == 0) {
	    inst->pasteout_data_ctext = snewn(tp.nitems+1, char);
	    memcpy(inst->pasteout_data_ctext, tp.value, tp.nitems);
	    inst->pasteout_data_ctext_len = tp.nitems;
	    XFree(tp.value);
	} else {
            inst->pasteout_data_ctext = NULL;
            inst->pasteout_data_ctext_len = 0;
        }
    } else {
	inst->pasteout_data_utf8 = NULL;
	inst->pasteout_data_utf8_len = 0;
	inst->pasteout_data_ctext = NULL;
	inst->pasteout_data_ctext_len = 0;
    }

    inst->pasteout_data = snewn(len*6, char);
    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 =
	    sresize(inst->pasteout_data, inst->pasteout_data_len, char);
    }

    store_cutbuffer(inst->pasteout_data, inst->pasteout_data_len);

    if (gtk_selection_owner_set(inst->area, GDK_SELECTION_PRIMARY,
				inst->input_event_time)) {
	gtk_selection_add_target(inst->area, GDK_SELECTION_PRIMARY,
				 GDK_SELECTION_TYPE_STRING, 1);
	if (inst->pasteout_data_ctext)
	    gtk_selection_add_target(inst->area, GDK_SELECTION_PRIMARY,
				     compound_text_atom, 1);
	if (inst->pasteout_data_utf8)
	    gtk_selection_add_target(inst->area, GDK_SELECTION_PRIMARY,
				     utf8_string_atom, 1);
    }

    if (must_deselect)
	term_deselect(inst->term);
}

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 == utf8_string_atom)
	gtk_selection_data_set(seldata, seldata->target, 8,
			       (unsigned char *)inst->pasteout_data_utf8,
			       inst->pasteout_data_utf8_len);
    else if (seldata->target == compound_text_atom)
	gtk_selection_data_set(seldata, seldata->target, 8,
			       (unsigned char *)inst->pasteout_data_ctext,
			       inst->pasteout_data_ctext_len);
    else
	gtk_selection_data_set(seldata, seldata->target, 8,
			       (unsigned char *)inst->pasteout_data,
			       inst->pasteout_data_len);
}

gint selection_clear(GtkWidget *widget, GdkEventSelection *seldata,
		     gpointer data)
{
    struct gui_data *inst = (struct gui_data *)data;

    term_deselect(inst->term);
    if (inst->pasteout_data)
	sfree(inst->pasteout_data);
    if (inst->pasteout_data_ctext)
	sfree(inst->pasteout_data_ctext);
    if (inst->pasteout_data_utf8)
	sfree(inst->pasteout_data_utf8);
    inst->pasteout_data = NULL;
    inst->pasteout_data_len = 0;
    inst->pasteout_data_ctext = NULL;
    inst->pasteout_data_ctext_len = 0;
    inst->pasteout_data_utf8 = NULL;
    inst->pasteout_data_utf8_len = 0;
    return TRUE;
}

void request_paste(void *frontend)
{
    struct gui_data *inst = (struct gui_data *)frontend;
    /*
     * In Unix, pasting is asynchronous: all we can do at the
     * moment is to call gtk_selection_convert(), and when the data
     * comes back _then_ we can call term_do_paste().
     */

    if (!inst->direct_to_font) {
	/*
	 * First we attempt to retrieve the selection as a UTF-8
	 * string (which we will convert to the correct code page
	 * before sending to the session, of course). If that
	 * fails, selection_received() will be informed and will
	 * fall back to an ordinary string.
	 */
	gtk_selection_convert(inst->area, GDK_SELECTION_PRIMARY,
			      utf8_string_atom,
			      inst->input_event_time);
    } else {
	/*
	 * If we're in direct-to-font mode, we disable UTF-8
	 * pasting, and go straight to ordinary string data.
	 */
	gtk_selection_convert(inst->area, GDK_SELECTION_PRIMARY,
			      GDK_SELECTION_TYPE_STRING,
			      inst->input_event_time);
    }
}

gint idle_paste_func(gpointer data);   /* forward ref */

void selection_received(GtkWidget *widget, GtkSelectionData *seldata,
			guint time, gpointer data)
{
    struct gui_data *inst = (struct gui_data *)data;
    XTextProperty tp;
    char **list;
    char *text;
    int length, count, ret;
    int free_list_required = 0;
    int free_required = 0;
    int charset;

    if (seldata->target == utf8_string_atom && seldata->length <= 0) {
	/*
	 * Failed to get a UTF-8 selection string. Try compound
	 * text next.
	 */
	gtk_selection_convert(inst->area, GDK_SELECTION_PRIMARY,
			      compound_text_atom,
			      inst->input_event_time);
	return;
    }

    if (seldata->target == compound_text_atom && seldata->length <= 0) {
	/*
	 * Failed to get UTF-8 or compound text. Try an ordinary
	 * string.
	 */
	gtk_selection_convert(inst->area, GDK_SELECTION_PRIMARY,
			      GDK_SELECTION_TYPE_STRING,
			      inst->input_event_time);
	return;
    }

    /*
     * If we have data, but it's not of a type we can deal with,
     * we have to ignore the data.
     */
    if (seldata->length > 0 &&
	seldata->type != GDK_SELECTION_TYPE_STRING &&
	seldata->type != compound_text_atom &&
	seldata->type != utf8_string_atom)
	return;

    /*
     * If we have no data, try looking in a cut buffer.
     */
    if (seldata->length <= 0) {
	text = retrieve_cutbuffer(&length);
	if (length == 0)
	    return;
	/* Xterm is rumoured to expect Latin-1, though I havn't checked the
	 * source, so use that as a de-facto standard. */
	charset = CS_ISO8859_1;
	free_required = 1;
    } else {
	/*
	 * Convert COMPOUND_TEXT into UTF-8.
	 */
	if (seldata->type == compound_text_atom) {
	    tp.value = seldata->data;
	    tp.encoding = (Atom) seldata->type;
	    tp.format = seldata->format;
	    tp.nitems = seldata->length;
	    ret = Xutf8TextPropertyToTextList(GDK_DISPLAY(), &tp,
					      &list, &count);
	    if (ret != 0 || count != 1) {
		/*
		 * Compound text failed; fall back to STRING.
		 */
		gtk_selection_convert(inst->area, GDK_SELECTION_PRIMARY,
				      GDK_SELECTION_TYPE_STRING,
				      inst->input_event_time);
		return;
	    }
	    text = list[0];
	    length = strlen(list[0]);
	    charset = CS_UTF8;
	    free_list_required = 1;
	} else {
	    text = (char *)seldata->data;
	    length = seldata->length;
	    charset = (seldata->type == utf8_string_atom ?
		       CS_UTF8 : inst->ucsdata.line_codepage);
	}
    }

    if (inst->pastein_data)
	sfree(inst->pastein_data);

    inst->pastein_data = snewn(length, wchar_t);
    inst->pastein_data_len = length;
    inst->pastein_data_len =
	mb_to_wc(charset, 0, text, length,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -