📄 gtkwin.c
字号:
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 + -