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

📄 gtkwin.c

📁 putty
💻 C
📖 第 1 页 / 共 5 页
字号:
		 inst->pastein_data, inst->pastein_data_len);

    term_do_paste(inst->term);

    if (term_paste_pending(inst->term))
	inst->term_paste_idle_id = gtk_idle_add(idle_paste_func, inst);

    if (free_list_required)
	XFreeStringList(list);
    if (free_required)
	XFree(text);
}

gint idle_paste_func(gpointer data)
{
    struct gui_data *inst = (struct gui_data *)data;

    if (term_paste_pending(inst->term))
	term_paste(inst->term);
    else
	gtk_idle_remove(inst->term_paste_idle_id);

    return TRUE;
}


void get_clip(void *frontend, wchar_t ** p, int *len)
{
    struct gui_data *inst = (struct gui_data *)frontend;

    if (p) {
	*p = inst->pastein_data;
	*len = inst->pastein_data_len;
    }
}

static void set_window_titles(struct gui_data *inst)
{
    /*
     * We must always call set_icon_name after calling set_title,
     * since set_title will write both names. Irritating, but such
     * is life.
     */
    gtk_window_set_title(GTK_WINDOW(inst->window), inst->wintitle);
    if (!inst->cfg.win_name_always)
	gdk_window_set_icon_name(inst->window->window, inst->icontitle);
}

void set_title(void *frontend, char *title)
{
    struct gui_data *inst = (struct gui_data *)frontend;
    strncpy(inst->wintitle, title, lenof(inst->wintitle));
    inst->wintitle[lenof(inst->wintitle)-1] = '\0';
    set_window_titles(inst);
}

void set_icon(void *frontend, char *title)
{
    struct gui_data *inst = (struct gui_data *)frontend;
    strncpy(inst->icontitle, title, lenof(inst->icontitle));
    inst->icontitle[lenof(inst->icontitle)-1] = '\0';
    set_window_titles(inst);
}

void set_sbar(void *frontend, int total, int start, int page)
{
    struct gui_data *inst = (struct gui_data *)frontend;
    if (!inst->cfg.scrollbar)
	return;
    inst->sbar_adjust->lower = 0;
    inst->sbar_adjust->upper = total;
    inst->sbar_adjust->value = start;
    inst->sbar_adjust->page_size = page;
    inst->sbar_adjust->step_increment = 1;
    inst->sbar_adjust->page_increment = page/2;
    inst->ignore_sbar = TRUE;
    gtk_adjustment_changed(inst->sbar_adjust);
    inst->ignore_sbar = FALSE;
}

void scrollbar_moved(GtkAdjustment *adj, gpointer data)
{
    struct gui_data *inst = (struct gui_data *)data;

    if (!inst->cfg.scrollbar)
	return;
    if (!inst->ignore_sbar)
	term_scroll(inst->term, 1, (int)adj->value);
}

void sys_cursor(void *frontend, int x, int y)
{
    /*
     * This is meaningless under X.
     */
}

/*
 * This is still called when mode==BELL_VISUAL, even though the
 * visual bell is handled entirely within terminal.c, because we
 * may want to perform additional actions on any kind of bell (for
 * example, taskbar flashing in Windows).
 */
void do_beep(void *frontend, int mode)
{
    if (mode == BELL_DEFAULT)
	gdk_beep();
}

int char_width(Context ctx, int uc)
{
    /*
     * Under X, any fixed-width font really _is_ fixed-width.
     * Double-width characters will be dealt with using a separate
     * font. For the moment we can simply return 1.
     */
    return 1;
}

Context get_ctx(void *frontend)
{
    struct gui_data *inst = (struct gui_data *)frontend;
    struct draw_ctx *dctx;

    if (!inst->area->window)
	return NULL;

    dctx = snew(struct draw_ctx);
    dctx->inst = inst;
    dctx->gc = gdk_gc_new(inst->area->window);
    return dctx;
}

void free_ctx(Context ctx)
{
    struct draw_ctx *dctx = (struct draw_ctx *)ctx;
    /* struct gui_data *inst = dctx->inst; */
    GdkGC *gc = dctx->gc;
    gdk_gc_unref(gc);
    sfree(dctx);
}

/*
 * Draw a line of text in the window, at given character
 * coordinates, in given attributes.
 *
 * We are allowed to fiddle with the contents of `text'.
 */
void do_text_internal(Context ctx, int x, int y, wchar_t *text, int len,
		      unsigned long attr, int lattr)
{
    struct draw_ctx *dctx = (struct draw_ctx *)ctx;
    struct gui_data *inst = dctx->inst;
    GdkGC *gc = dctx->gc;
    int ncombining, combining;
    int nfg, nbg, t, fontid, shadow, rlen, widefactor;
    int monochrome = gtk_widget_get_visual(inst->area)->depth == 1;

    if (attr & TATTR_COMBINING) {
	ncombining = len;
	len = 1;
    } else
	ncombining = 1;

    nfg = ((monochrome ? ATTR_DEFFG : (attr & ATTR_FGMASK)) >> ATTR_FGSHIFT);
    nbg = ((monochrome ? ATTR_DEFBG : (attr & ATTR_BGMASK)) >> ATTR_BGSHIFT);
    if (!!(attr & ATTR_REVERSE) ^ (monochrome && (attr & TATTR_ACTCURS))) {
	t = nfg;
	nfg = nbg;
	nbg = t;
    }
    if (inst->cfg.bold_colour && (attr & ATTR_BOLD)) {
	if (nfg < 16) nfg |= 8;
	else if (nfg >= 256) nfg |= 1;
    }
    if (inst->cfg.bold_colour && (attr & ATTR_BLINK)) {
	if (nbg < 16) nbg |= 8;
	else if (nbg >= 256) nbg |= 1;
    }
    if ((attr & TATTR_ACTCURS) && !monochrome) {
	nfg = 260;
	nbg = 261;
    }

    fontid = shadow = 0;

    if (attr & ATTR_WIDE) {
	widefactor = 2;
	fontid |= 2;
    } else {
	widefactor = 1;
    }

    if ((attr & ATTR_BOLD) && !inst->cfg.bold_colour) {
	if (inst->fonts[fontid | 1])
	    fontid |= 1;
	else
	    shadow = 1;
    }

    if ((lattr & LATTR_MODE) != LATTR_NORM) {
	x *= 2;
	if (x >= inst->term->cols)
	    return;
	if (x + len*2*widefactor > inst->term->cols)
	    len = (inst->term->cols-x)/2/widefactor;/* trim to LH half */
	rlen = len * 2;
    } else
	rlen = len;

    {
	GdkRectangle r;

	r.x = x*inst->font_width+inst->cfg.window_border;
	r.y = y*inst->font_height+inst->cfg.window_border;
	r.width = rlen*widefactor*inst->font_width;
	r.height = inst->font_height;
	gdk_gc_set_clip_rectangle(gc, &r);
    }

    gdk_gc_set_foreground(gc, &inst->cols[nbg]);
    gdk_draw_rectangle(inst->pixmap, gc, 1,
		       x*inst->font_width+inst->cfg.window_border,
		       y*inst->font_height+inst->cfg.window_border,
		       rlen*widefactor*inst->font_width, inst->font_height);

    gdk_gc_set_foreground(gc, &inst->cols[nfg]);
    {
	GdkWChar *gwcs;
	gchar *gcs;
	wchar_t *wcs;
	int i;

	wcs = snewn(len*ncombining+1, wchar_t);
	for (i = 0; i < len*ncombining; i++) {
	    wcs[i] = text[i];
	}

	if (inst->fonts[fontid] == NULL && (fontid & 2)) {
	    /*
	     * We've been given ATTR_WIDE, but have no wide font.
	     * Fall back to the non-wide font.
	     */
	    fontid &= ~2;
	}

	if (inst->fonts[fontid] == NULL) {
	    /*
	     * The font for this contingency does not exist. So we
	     * display nothing at all; such is life.
	     */
	} else if (inst->fontinfo[fontid].is_wide) {
	    /*
	     * At least one version of gdk_draw_text_wc() has a
	     * weird bug whereby it reads `len' elements of the
	     * input string, but only draws `len/2'. Hence I'm
	     * going to make its input array twice as long as it
	     * theoretically needs to be, and pass in twice the
	     * actual number of characters. If a fixed gdk actually
	     * takes the doubled length seriously, then (a) the
	     * array will stand scrutiny up to the full length, (b)
	     * the spare elements of the array are full of zeroes
	     * which will probably be an empty glyph in the font,
	     * and (c) the clip rectangle should prevent it causing
	     * trouble anyway.
	     */
	    gwcs = snewn(len*2+1, GdkWChar);
	    memset(gwcs, 0, sizeof(GdkWChar) * (len*2+1));
	    /*
	     * FIXME: when we have a wide-char equivalent of
	     * from_unicode, use it instead of this.
	     */
	    for (combining = 0; combining < ncombining; combining++) {
		for (i = 0; i <= len; i++)
		    gwcs[i] = wcs[i + combining];
		gdk_draw_text_wc(inst->pixmap, inst->fonts[fontid], gc,
				 x*inst->font_width+inst->cfg.window_border,
				 y*inst->font_height+inst->cfg.window_border+inst->fonts[0]->ascent,
				 gwcs, len*2);
		if (shadow)
		    gdk_draw_text_wc(inst->pixmap, inst->fonts[fontid], gc,
				     x*inst->font_width+inst->cfg.window_border+inst->cfg.shadowboldoffset,
				     y*inst->font_height+inst->cfg.window_border+inst->fonts[0]->ascent,
				     gwcs, len*2);
	    }
	    sfree(gwcs);
	} else {
	    gcs = snewn(len+1, gchar);
	    for (combining = 0; combining < ncombining; combining++) {
		wc_to_mb(inst->fontinfo[fontid].charset, 0,
			 wcs + combining, len, gcs, len, ".", NULL, NULL);
		gdk_draw_text(inst->pixmap, inst->fonts[fontid], gc,
			      x*inst->font_width+inst->cfg.window_border,
			      y*inst->font_height+inst->cfg.window_border+inst->fonts[0]->ascent,
			      gcs, len);
		if (shadow)
		    gdk_draw_text(inst->pixmap, inst->fonts[fontid], gc,
				  x*inst->font_width+inst->cfg.window_border+inst->cfg.shadowboldoffset,
				  y*inst->font_height+inst->cfg.window_border+inst->fonts[0]->ascent,
				  gcs, len);
	    }
	    sfree(gcs);
	}
	sfree(wcs);
    }

    if (attr & ATTR_UNDER) {
	int uheight = inst->fonts[0]->ascent + 1;
	if (uheight >= inst->font_height)
	    uheight = inst->font_height - 1;
	gdk_draw_line(inst->pixmap, gc, x*inst->font_width+inst->cfg.window_border,
		      y*inst->font_height + uheight + inst->cfg.window_border,
		      (x+len)*widefactor*inst->font_width-1+inst->cfg.window_border,
		      y*inst->font_height + uheight + inst->cfg.window_border);
    }

    if ((lattr & LATTR_MODE) != LATTR_NORM) {
	/*
	 * I can't find any plausible StretchBlt equivalent in the
	 * X server, so I'm going to do this the slow and painful
	 * way. This will involve repeated calls to
	 * gdk_draw_pixmap() to stretch the text horizontally. It's
	 * O(N^2) in time and O(N) in network bandwidth, but you
	 * try thinking of a better way. :-(
	 */
	int i;
	for (i = 0; i < len * widefactor * inst->font_width; i++) {
	    gdk_draw_pixmap(inst->pixmap, gc, inst->pixmap,
			    x*inst->font_width+inst->cfg.window_border + 2*i,
			    y*inst->font_height+inst->cfg.window_border,
			    x*inst->font_width+inst->cfg.window_border + 2*i+1,
			    y*inst->font_height+inst->cfg.window_border,
			    len * widefactor * inst->font_width - i, inst->font_height);
	}
	len *= 2;
	if ((lattr & LATTR_MODE) != LATTR_WIDE) {
	    int dt, db;
	    /* Now stretch vertically, in the same way. */
	    if ((lattr & LATTR_MODE) == LATTR_BOT)
		dt = 0, db = 1;
	    else
		dt = 1, db = 0;
	    for (i = 0; i < inst->font_height; i+=2) {
		gdk_draw_pixmap(inst->pixmap, gc, inst->pixmap,
				x*inst->font_width+inst->cfg.window_border,
				y*inst->font_height+inst->cfg.window_border+dt*i+db,
				x*inst->font_width+inst->cfg.window_border,
				y*inst->font_height+inst->cfg.window_border+dt*(i+1),
				len * widefactor * inst->font_width, inst->font_height-i-1);
	    }
	}
    }
}

void do_text(Context ctx, int x, int y, wchar_t *text, int len,
	     unsigned long attr, int lattr)
{
    struct draw_ctx *dctx = (struct draw_ctx *)ctx;
    struct gui_data *inst = dctx->inst;
    GdkGC *gc = dctx->gc;
    int widefactor;

    do_text_internal(ctx, x, y, text, len, attr, lattr);

    if (attr & ATTR_WIDE) {
	widefactor = 2;
    } else {
	widefactor = 1;
    }

    if ((lattr & LATTR_MODE) != LATTR_NORM) {
	x *= 2;
	if (x >= inst->term->cols)
	    return;
	if (x + len*2*widefactor > inst->term->cols)
	    len = (inst->term->cols-x)/2/widefactor;/* trim to LH half */
	len *= 2;
    }

    gdk_draw_pixmap(inst->area->window, gc, inst->pixmap,
		    x*inst->font_width+inst->cfg.window_border,
		    y*inst->font_height+inst->cfg.window_border,
		    x*inst->font_width+inst->cfg.window_border,
		    y*inst->font_height+inst->cfg.window_border,
		    len*widefactor*inst->font_width, inst->font_height);
}

void do_cursor(Context ctx, int x, int y, wchar_t *text, int len,
	       unsigned long attr, int lattr)
{
    struct draw_ctx *dctx = (struct draw_ctx *)ctx;
    struct gui_data *inst = dctx->inst;
    GdkGC *gc = dctx->gc;

    int active, passive, widefactor;

    if (attr & TATTR_PASCURS) {
	attr &= ~TATTR_PASCURS;
	passive = 1;
    } else
	passive = 0;
    if ((attr & TATTR_ACTCURS) && inst->cfg.cursor_type != 0) {
	attr &= ~TATTR_ACTCURS;
        active = 1;
    } else
        active = 0;
    do_text_internal(ctx, x, y, text, len, attr, lattr);

    if (attr & TATTR_COMBINING)
	len = 1;

    if (attr & ATTR_WIDE) {
	widefactor = 2;
    } else {
	widefactor = 1;
    }

    if ((lattr & LATTR_MODE) != LATTR_NORM) {
	x *= 2;
	if (x >= inst->term->cols)
	    return;
	if (x + len*2*widefactor > inst->term->cols)
	    len = (inst->term->cols-x)/2/widefactor;/* trim to LH half */
	len *= 2;
    }

    if (inst->cfg.cursor_type == 0) {
	/*
	 * An active block cursor will already have been done by
	 * the above do_text call, so we only need to do anything
	 * if it's passive.
	 */
	if (passive) {
	    gdk_gc_set_foreground(gc, &inst->cols[261]);
	    gdk_draw_rectangle(inst->pixmap, gc, 0,
			       x*inst->font_width+inst->cfg.window_border,
			       y*inst->font_height+inst->cfg.window_border,
			       len*widefactor*inst->font_width-1, inst->font_height-1);
	}
    } else {
	int uhei

⌨️ 快捷键说明

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