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

📄 pterm.c

📁 远程登陆工具软件源码 用于远程登陆unix
💻 C
📖 第 1 页 / 共 5 页
字号:
 * We are allowed to fiddle with the contents of `text'.
 */
void do_text_internal(Context ctx, int x, int y, char *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 nfg, nbg, t, fontid, shadow, rlen, widefactor;

    nfg = ((attr & ATTR_FGMASK) >> ATTR_FGSHIFT);
    nfg = 2 * (nfg & 0xF) + (nfg & 0x10 ? 1 : 0);
    nbg = ((attr & ATTR_BGMASK) >> ATTR_BGSHIFT);
    nbg = 2 * (nbg & 0xF) + (nbg & 0x10 ? 1 : 0);
    if (attr & ATTR_REVERSE) {
	t = nfg;
	nfg = nbg;
	nbg = t;
    }
    if (inst->cfg.bold_colour && (attr & ATTR_BOLD))
	nfg |= 1;
    if (inst->cfg.bold_colour && (attr & ATTR_BLINK))
	nbg |= 1;
    if (attr & TATTR_ACTCURS) {
	nfg = NCOLOURS-2;
	nbg = NCOLOURS-1;
    }

    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_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+1, wchar_t);
	for (i = 0; i < len; i++) {
	    wcs[i] = (wchar_t) ((attr & CSET_MASK) + (text[i] & CHAR_MASK));
	}

	if (inst->fonts[fontid] == NULL) {
	    /*
	     * The font for this contingency does not exist.
	     * Typically this means we've been given ATTR_WIDE
	     * character and have no wide font. 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 (i = 0; i <= len; i++)
		gwcs[i] = wcs[i];
	    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);
	    sfree(gwcs);
	} else {
	    gcs = snewn(len+1, gchar);
	    wc_to_mb(inst->fontinfo[fontid].charset, 0,
		     wcs, 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);
	    sfree(gcs);
	}
	sfree(wcs);
    }

    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,
		      text, len);
    }

    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_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 * inst->font_width - i, inst->font_height);
	}
	len *= 2;
	if (lattr != LATTR_WIDE) {
	    int dt, db;
	    /* Now stretch vertically, in the same way. */
	    if (lattr == 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*widefactor*inst->font_width+inst->cfg.window_border,
				y*inst->font_height+inst->cfg.window_border+dt*(i+1),
				len * inst->font_width, inst->font_height-i-1);
	    }
	}
    }
}

void do_text(Context ctx, int x, int y, char *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_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, char *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 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;
    }
    do_text_internal(ctx, x, y, text, len, attr, lattr);

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

    if (lattr != 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[NCOLOURS-1]);
	    gdk_draw_rectangle(inst->pixmap, gc, 0,
			       x*inst->font_width+inst->cfg.window_border,
			       y*inst->font_height+inst->cfg.window_border,
			       len*inst->font_width-1, inst->font_height-1);
	}
    } else {
	int uheight;
	int startx, starty, dx, dy, length, i;

	int char_width;

	if ((attr & ATTR_WIDE) || lattr != LATTR_NORM)
	    char_width = 2*inst->font_width;
	else
	    char_width = inst->font_width;

	if (inst->cfg.cursor_type == 1) {
	    uheight = inst->fonts[0]->ascent + 1;
	    if (uheight >= inst->font_height)
		uheight = inst->font_height - 1;

	    startx = x * inst->font_width + inst->cfg.window_border;
	    starty = y * inst->font_height + inst->cfg.window_border + uheight;
	    dx = 1;
	    dy = 0;
	    length = len * char_width;
	} else {
	    int xadjust = 0;
	    if (attr & TATTR_RIGHTCURS)
		xadjust = char_width - 1;
	    startx = x * inst->font_width + inst->cfg.window_border + xadjust;
	    starty = y * inst->font_height + inst->cfg.window_border;
	    dx = 0;
	    dy = 1;
	    length = inst->font_height;
	}

	gdk_gc_set_foreground(gc, &inst->cols[NCOLOURS-1]);
	if (passive) {
	    for (i = 0; i < length; i++) {
		if (i % 2 == 0) {
		    gdk_draw_point(inst->pixmap, gc, startx, starty);
		}
		startx += dx;
		starty += dy;
	    }
	} else {
	    gdk_draw_line(inst->pixmap, gc, startx, starty,
			  startx + (length-1) * dx, starty + (length-1) * dy);
	}
    }

    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);
}

GdkCursor *make_mouse_ptr(struct gui_data *inst, int cursor_val)
{
    /*
     * Truly hideous hack: GTK doesn't allow us to set the mouse
     * cursor foreground and background colours unless we've _also_
     * created our own cursor from bitmaps. Therefore, I need to
     * load the `cursor' font and draw glyphs from it on to
     * pixmaps, in order to construct my cursors with the fg and bg
     * I want. This is a gross hack, but it's more self-contained
     * than linking in Xlib to find the X window handle to
     * inst->area and calling XRecolorCursor, and it's more
     * futureproof than hard-coding the shapes as bitmap arrays.
     */
    static GdkFont *cursor_font = NULL;
    GdkPixmap *source, *mask;
    GdkGC *gc;
    GdkColor cfg = { 0, 65535, 65535, 65535 };
    GdkColor cbg = { 0, 0, 0, 0 };
    GdkColor dfg = { 1, 65535, 65535, 65535 };
    GdkColor dbg = { 0, 0, 0, 0 };
    GdkCursor *ret;
    gchar text[2];
    gint lb, rb, wid, asc, desc, w, h, x, y;

    if (cursor_val == -2) {
	gdk_font_unref(cursor_font);
	return NULL;
    }

    if (cursor_val >= 0 && !cursor_font)
	cursor_font = gdk_font_load("cursor");

    /*
     * Get the text extent of the cursor in question. We use the
     * mask character for this, because it's typically slightly
     * bigger than the main character.
     */
    if (cursor_val >= 0) {
	text[1] = '\0';
	text[0] = (char)cursor_val + 1;
	gdk_string_extents(cursor_font, text, &lb, &rb, &wid, &asc, &desc);
	w = rb-lb; h = asc+desc; x = -lb; y = asc;
    } else {
	w = h = 1;
	x = y = 0;
    }

    source = gdk_pixmap_new(NULL, w, h, 1);
    mask = gdk_pixmap_new(NULL, w, h, 1);

    /*
     * Draw the mask character on the mask pixmap.
     */
    gc = gdk_gc_new(mask);
    gdk_gc_set_foreground(gc, &dbg);
    gdk_draw_rectangle(mask, gc, 1, 0, 0, w, h);
    if (cursor_val >= 0) {
	text[1] = '\0';
	text[0] = (char)cursor_val + 1;
	gdk_gc_set_foreground(gc, &dfg);
	gdk_draw_text(mask, cursor_font, gc, x, y, text, 1);
    }
    gdk_gc_unref(gc);

    /*
     * Draw the main character on the source pixmap.
     */
    gc = gdk_gc_new(source);
    gdk_gc_set_foreground(gc, &dbg);
    gdk_draw_rectangle(source, gc, 1, 0, 0, w, h);
    if (cursor_val >= 0) {
	text[1] = '\0';
	text[0] = (char)cursor_val;
	gdk_gc_set_foreground(gc, &dfg);
	gdk_draw_text(source, cursor_font, gc, x, y, text, 1);
    }
    gdk_gc_unref(gc);

    /*
     * Create the cursor.
     */
    ret = gdk_cursor_new_from_pixmap(source, mask, &cfg, &cbg, x, y);

    /*
     * Clean up.
     */
    gdk_pixmap_unref(source);
    gdk_pixmap_unref(mask);

    return ret;
}

void modalfatalbox(char *p, ...)
{
    va_list ap;
    fprintf(stderr, "FATAL ERROR: ");
    va_start(ap, p);
    vfprintf(stderr, p, ap);
    va_end(ap);
    fputc('\n', stderr);
    exit(1);
}

void cmdline_error(char *p, ...)
{
    va_list ap;
    fprintf(stderr, "%s: ", appname);
    va_start(ap, p);
    vfprintf(stderr, p, ap);
    va_end(ap);
    fputc('\n', stderr);
    exit(1);
}

char *get_x_display(void *frontend)
{
    return gdk_get_display();
}

long get_windowid(void *frontend)
{
    struct gui_data *inst = (struct gui_data *)frontend;
    return (long)GDK_WINDOW_XWIND

⌨️ 快捷键说明

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