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

📄 pterm.c

📁 大名鼎鼎的远程登录软件putty的Symbian版源码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * pterm - a fusion of the PuTTY terminal emulator with a Unix pty * back end, all running as a GTK application. Wish me luck. */#define _GNU_SOURCE#include <string.h>#include <assert.h>#include <stdlib.h>#include <string.h>#include <signal.h>#include <stdio.h>#include <time.h>#include <errno.h>#include <fcntl.h>#include <unistd.h>#include <sys/types.h>#include <sys/wait.h>#include <gtk/gtk.h>#include <gdk/gdkkeysyms.h>#include <gdk/gdkx.h>#include <X11/Xlib.h>#include <X11/Xutil.h>#include <X11/Xatom.h>#define PUTTY_DO_GLOBALS	       /* actually _define_ globals */#include "putty.h"#include "terminal.h"#define CAT2(x,y) x ## y#define CAT(x,y) CAT2(x,y)#define ASSERT(x) enum {CAT(assertion_,__LINE__) = 1 / (x)}#define NCOLOURS (lenof(((Config *)0)->colours))GdkAtom compound_text_atom, utf8_string_atom;extern char **pty_argv;	       /* declared in pty.c */extern int use_pty_argv;struct gui_data {    GtkWidget *window, *area, *sbar;    GtkBox *hbox;    GtkAdjustment *sbar_adjust;    GtkWidget *menu, *specialsmenu, *specialsitem1, *specialsitem2,	*restartitem;    GtkWidget *sessionsmenu;    GdkPixmap *pixmap;    GdkFont *fonts[4];                 /* normal, bold, wide, widebold */    struct {	int charset;	int is_wide;    } fontinfo[4];    int xpos, ypos, gotpos, gravity;    GdkCursor *rawcursor, *textcursor, *blankcursor, *currcursor;    GdkColor cols[NCOLOURS];    GdkColormap *colmap;    wchar_t *pastein_data;    int direct_to_font;    int pastein_data_len;    char *pasteout_data, *pasteout_data_ctext, *pasteout_data_utf8;    int pasteout_data_len, pasteout_data_ctext_len, pasteout_data_utf8_len;    int font_width, font_height;    int width, height;    int ignore_sbar;    int mouseptr_visible;    guint term_paste_idle_id;    int alt_keycode;    int alt_digits;    char wintitle[sizeof(((Config *)0)->wintitle)];    char icontitle[sizeof(((Config *)0)->wintitle)];    int master_fd, master_func_id;    void *ldisc;    Backend *back;    void *backhandle;    Terminal *term;    void *logctx;    int exited;    struct unicode_data ucsdata;    Config cfg;    void *eventlogstuff;    char *progname, **gtkargvstart;    int ngtkargs;    guint32 input_event_time; /* Timestamp of the most recent input event. */};struct draw_ctx {    GdkGC *gc;    struct gui_data *inst;};static int send_raw_mouse;static char *app_name = "pterm";static void start_backend(struct gui_data *inst);char *x_get_default(const char *key){    return XGetDefault(GDK_DISPLAY(), app_name, key);}void connection_fatal(void *frontend, char *p, ...){    struct gui_data *inst = (struct gui_data *)frontend;    va_list ap;    char *msg;    va_start(ap, p);    msg = dupvprintf(p, ap);    va_end(ap);    inst->exited = TRUE;    fatal_message_box(inst->window, msg);    sfree(msg);    if (inst->cfg.close_on_exit == FORCE_ON)        cleanup_exit(1);}/* * Default settings that are specific to pterm. */FontSpec platform_default_fontspec(const char *name){    FontSpec ret;    if (!strcmp(name, "Font"))	strcpy(ret.name, "fixed");    else	*ret.name = '\0';    return ret;}Filename platform_default_filename(const char *name){    Filename ret;    if (!strcmp(name, "LogFileName"))	strcpy(ret.path, "putty.log");    else	*ret.path = '\0';    return ret;}char *platform_default_s(const char *name){    return NULL;}int platform_default_i(const char *name, int def){    if (!strcmp(name, "CloseOnExit"))	return 2;  /* maps to FORCE_ON after painful rearrangement :-( */    if (!strcmp(name, "WinNameAlways"))	return 0;  /* X natively supports icon titles, so use 'em by default */    return def;}void ldisc_update(void *frontend, int echo, int edit){    /*     * This is a stub in pterm. If I ever produce a Unix     * command-line ssh/telnet/rlogin client (i.e. a port of plink)     * then it will require some termios manoeuvring analogous to     * that in the Windows plink.c, but here it's meaningless.     */}int from_backend(void *frontend, int is_stderr, const char *data, int len){    struct gui_data *inst = (struct gui_data *)frontend;    return term_data(inst->term, is_stderr, data, len);}void logevent(void *frontend, const char *string){    struct gui_data *inst = (struct gui_data *)frontend;    log_eventlog(inst->logctx, string);    logevent_dlg(inst->eventlogstuff, string);}int font_dimension(void *frontend, int which)/* 0 for width, 1 for height */{    struct gui_data *inst = (struct gui_data *)frontend;    if (which)	return inst->font_height;    else	return inst->font_width;}/* * Translate a raw mouse button designation (LEFT, MIDDLE, RIGHT) * into a cooked one (SELECT, EXTEND, PASTE). *  * In Unix, this is not configurable; the X button arrangement is * rock-solid across all applications, everyone has a three-button * mouse or a means of faking it, and there is no need to switch * buttons around at all. */static Mouse_Button translate_button(Mouse_Button button){    /* struct gui_data *inst = (struct gui_data *)frontend; */    if (button == MBT_LEFT)	return MBT_SELECT;    if (button == MBT_MIDDLE)	return MBT_PASTE;    if (button == MBT_RIGHT)	return MBT_EXTEND;    return 0;			       /* shouldn't happen */}/* * Return the top-level GtkWindow associated with a particular * front end instance. */void *get_window(void *frontend){    struct gui_data *inst = (struct gui_data *)frontend;    return inst->window;}/* * Minimise or restore the window in response to a server-side * request. */void set_iconic(void *frontend, int iconic){    /*     * GTK 1.2 doesn't know how to do this.     */#if GTK_CHECK_VERSION(2,0,0)    struct gui_data *inst = (struct gui_data *)frontend;    if (iconic)	gtk_window_iconify(GTK_WINDOW(inst->window));    else	gtk_window_deiconify(GTK_WINDOW(inst->window));#endif}/* * Move the window in response to a server-side request. */void move_window(void *frontend, int x, int y){    struct gui_data *inst = (struct gui_data *)frontend;    /*     * I assume that when the GTK version of this call is available     * we should use it. Not sure how it differs from the GDK one,     * though.     */#if GTK_CHECK_VERSION(2,0,0)    gtk_window_move(GTK_WINDOW(inst->window), x, y);#else    gdk_window_move(inst->window->window, x, y);#endif}/* * Move the window to the top or bottom of the z-order in response * to a server-side request. */void set_zorder(void *frontend, int top){    struct gui_data *inst = (struct gui_data *)frontend;    if (top)	gdk_window_raise(inst->window->window);    else	gdk_window_lower(inst->window->window);}/* * Refresh the window in response to a server-side request. */void refresh_window(void *frontend){    struct gui_data *inst = (struct gui_data *)frontend;    term_invalidate(inst->term);}/* * Maximise or restore the window in response to a server-side * request. */void set_zoomed(void *frontend, int zoomed){    /*     * GTK 1.2 doesn't know how to do this.     */#if GTK_CHECK_VERSION(2,0,0)    struct gui_data *inst = (struct gui_data *)frontend;    if (iconic)	gtk_window_maximize(GTK_WINDOW(inst->window));    else	gtk_window_unmaximize(GTK_WINDOW(inst->window));#endif}/* * Report whether the window is iconic, for terminal reports. */int is_iconic(void *frontend){    struct gui_data *inst = (struct gui_data *)frontend;    return !gdk_window_is_viewable(inst->window->window);}/* * Report the window's position, for terminal reports. */void get_window_pos(void *frontend, int *x, int *y){    struct gui_data *inst = (struct gui_data *)frontend;    /*     * I assume that when the GTK version of this call is available     * we should use it. Not sure how it differs from the GDK one,     * though.     */#if GTK_CHECK_VERSION(2,0,0)    gtk_window_get_position(GTK_WINDOW(inst->window), x, y);#else    gdk_window_get_position(inst->window->window, x, y);#endif}/* * Report the window's pixel size, for terminal reports. */void get_window_pixels(void *frontend, int *x, int *y){    struct gui_data *inst = (struct gui_data *)frontend;    /*     * I assume that when the GTK version of this call is available     * we should use it. Not sure how it differs from the GDK one,     * though.     */#if GTK_CHECK_VERSION(2,0,0)    gtk_window_get_size(GTK_WINDOW(inst->window), x, y);#else    gdk_window_get_size(inst->window->window, x, y);#endif}/* * Return the window or icon title. */char *get_window_title(void *frontend, int icon){    struct gui_data *inst = (struct gui_data *)frontend;    return icon ? inst->icontitle : inst->wintitle;}gint delete_window(GtkWidget *widget, GdkEvent *event, gpointer data){    struct gui_data *inst = (struct gui_data *)data;    if (!inst->exited && inst->cfg.warn_on_close) {	if (!reallyclose(inst))	    return TRUE;    }    return FALSE;}static void show_mouseptr(struct gui_data *inst, int show){    if (!inst->cfg.hide_mouseptr)	show = 1;    if (show)	gdk_window_set_cursor(inst->area->window, inst->currcursor);    else	gdk_window_set_cursor(inst->area->window, inst->blankcursor);    inst->mouseptr_visible = show;}void draw_backing_rect(struct gui_data *inst){    GdkGC *gc = gdk_gc_new(inst->area->window);    gdk_gc_set_foreground(gc, &inst->cols[18]);   /* default background */    gdk_draw_rectangle(inst->pixmap, gc, 1, 0, 0,		       inst->cfg.width * inst->font_width + 2*inst->cfg.window_border,		       inst->cfg.height * inst->font_height + 2*inst->cfg.window_border);    gdk_gc_unref(gc);}gint configure_area(GtkWidget *widget, GdkEventConfigure *event, gpointer data){    struct gui_data *inst = (struct gui_data *)data;    int w, h, need_size = 0;    /*     * See if the terminal size has changed, in which case we must     * let the terminal know.     */    w = (event->width - 2*inst->cfg.window_border) / inst->font_width;    h = (event->height - 2*inst->cfg.window_border) / inst->font_height;    if (w != inst->width || h != inst->height) {	inst->cfg.width = inst->width = w;	inst->cfg.height = inst->height = h;	need_size = 1;    }    if (inst->pixmap) {	gdk_pixmap_unref(inst->pixmap);	inst->pixmap = NULL;    }    inst->pixmap = gdk_pixmap_new(widget->window,				  (inst->cfg.width * inst->font_width +				   2*inst->cfg.window_border),				  (inst->cfg.height * inst->font_height +				   2*inst->cfg.window_border), -1);    draw_backing_rect(inst);    if (need_size && inst->term) {	term_size(inst->term, h, w, inst->cfg.savelines);    }    if (inst->term)	term_invalidate(inst->term);    return TRUE;}gint expose_area(GtkWidget *widget, GdkEventExpose *event, gpointer data){    struct gui_data *inst = (struct gui_data *)data;    /*     * Pass the exposed rectangle to terminal.c, which will call us     * back to do the actual painting.     */    if (inst->pixmap) {	gdk_draw_pixmap(widget->window,			widget->style->fg_gc[GTK_WIDGET_STATE(widget)],			inst->pixmap,			event->area.x, event->area.y,			event->area.x, event->area.y,			event->area.width, event->area.height);    }    return TRUE;}#define KEY_PRESSED(k) \    (inst->keystate[(k) / 32] & (1 << ((k) % 32)))gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data){    struct gui_data *inst = (struct gui_data *)data;    char output[32];    wchar_t ucsoutput[2];    int ucsval, start, end, special, use_ucsoutput;    /* Remember the timestamp. */    inst->input_event_time = event->time;

⌨️ 快捷键说明

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