📄 pterm.c
字号:
XChangeProperty(GDK_DISPLAY(), GDK_ROOT_WINDOW(), XA_CUT_BUFFER5, XA_STRING, 8, PropModeAppend, "", 0); XChangeProperty(GDK_DISPLAY(), GDK_ROOT_WINDOW(), XA_CUT_BUFFER6, XA_STRING, 8, PropModeAppend, "", 0); XChangeProperty(GDK_DISPLAY(), GDK_ROOT_WINDOW(), XA_CUT_BUFFER7, XA_STRING, 8, PropModeAppend, "", 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 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, inst->pasteout_data_utf8, inst->pasteout_data_utf8_len); else if (seldata->target == compound_text_atom) gtk_selection_data_set(seldata, seldata->target, 8, inst->pasteout_data_ctext, inst->pasteout_data_ctext_len); else gtk_selection_data_set(seldata, seldata->target, 8, 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, 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 beep(void *frontend, int mode){ if (mode != BELL_VISUAL) 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; if (attr & TATTR_COMBINING) { ncombining = len; len = 1; } else ncombining = 1; 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; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -