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

📄 gtkwin.c

📁 putty
💻 C
📖 第 1 页 / 共 5 页
字号:
{
    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;

    /* By default, nothing is generated. */
    end = start = 0;
    special = use_ucsoutput = FALSE;

    /*
     * If Alt is being released after typing an Alt+numberpad
     * sequence, we should generate the code that was typed.
     * 
     * Note that we only do this if more than one key was actually
     * pressed - I don't think Alt+NumPad4 should be ^D or that
     * Alt+NumPad3 should be ^C, for example. There's no serious
     * inconvenience in having to type a zero before a single-digit
     * character code.
     */
    if (event->type == GDK_KEY_RELEASE &&
	(event->keyval == GDK_Meta_L || event->keyval == GDK_Alt_L ||
	 event->keyval == GDK_Meta_R || event->keyval == GDK_Alt_R) &&
	inst->alt_keycode >= 0 && inst->alt_digits > 1) {
#ifdef KEY_DEBUGGING
	printf("Alt key up, keycode = %d\n", inst->alt_keycode);
#endif
	output[0] = inst->alt_keycode;
	end = 1;
	goto done;
    }

    if (event->type == GDK_KEY_PRESS) {
#ifdef KEY_DEBUGGING
	{
	    int i;
	    printf("keypress: keyval = %04x, state = %08x; string =",
		   event->keyval, event->state);
	    for (i = 0; event->string[i]; i++)
		printf(" %02x", (unsigned char) event->string[i]);
	    printf("\n");
	}
#endif

	/*
	 * NYI: Compose key (!!! requires Unicode faff before even trying)
	 */

	/*
	 * If Alt has just been pressed, we start potentially
	 * accumulating an Alt+numberpad code. We do this by
	 * setting alt_keycode to -1 (nothing yet but plausible).
	 */
	if ((event->keyval == GDK_Meta_L || event->keyval == GDK_Alt_L ||
	     event->keyval == GDK_Meta_R || event->keyval == GDK_Alt_R)) {
	    inst->alt_keycode = -1;
            inst->alt_digits = 0;
	    goto done;		       /* this generates nothing else */
	}

	/*
	 * If we're seeing a numberpad key press with Mod1 down,
	 * consider adding it to alt_keycode if that's sensible.
	 * Anything _else_ with Mod1 down cancels any possibility
	 * of an ALT keycode: we set alt_keycode to -2.
	 */
	if ((event->state & GDK_MOD1_MASK) && inst->alt_keycode != -2) {
	    int digit = -1;
	    switch (event->keyval) {
	      case GDK_KP_0: case GDK_KP_Insert: digit = 0; break;
	      case GDK_KP_1: case GDK_KP_End: digit = 1; break;
	      case GDK_KP_2: case GDK_KP_Down: digit = 2; break;
	      case GDK_KP_3: case GDK_KP_Page_Down: digit = 3; break;
	      case GDK_KP_4: case GDK_KP_Left: digit = 4; break;
	      case GDK_KP_5: case GDK_KP_Begin: digit = 5; break;
	      case GDK_KP_6: case GDK_KP_Right: digit = 6; break;
	      case GDK_KP_7: case GDK_KP_Home: digit = 7; break;
	      case GDK_KP_8: case GDK_KP_Up: digit = 8; break;
	      case GDK_KP_9: case GDK_KP_Page_Up: digit = 9; break;
	    }
	    if (digit < 0)
		inst->alt_keycode = -2;   /* it's invalid */
	    else {
#ifdef KEY_DEBUGGING
		printf("Adding digit %d to keycode %d", digit,
		       inst->alt_keycode);
#endif
		if (inst->alt_keycode == -1)
		    inst->alt_keycode = digit;   /* one-digit code */
		else
		    inst->alt_keycode = inst->alt_keycode * 10 + digit;
                inst->alt_digits++;
#ifdef KEY_DEBUGGING
		printf(" gives new code %d\n", inst->alt_keycode);
#endif
		/* Having used this digit, we now do nothing more with it. */
		goto done;
	    }
	}

	/*
	 * Shift-PgUp and Shift-PgDn don't even generate keystrokes
	 * at all.
	 */
	if (event->keyval == GDK_Page_Up && (event->state & GDK_SHIFT_MASK)) {
	    term_scroll(inst->term, 0, -inst->cfg.height/2);
	    return TRUE;
	}
	if (event->keyval == GDK_Page_Up && (event->state & GDK_CONTROL_MASK)) {
	    term_scroll(inst->term, 0, -1);
	    return TRUE;
	}
	if (event->keyval == GDK_Page_Down && (event->state & GDK_SHIFT_MASK)) {
	    term_scroll(inst->term, 0, +inst->cfg.height/2);
	    return TRUE;
	}
	if (event->keyval == GDK_Page_Down && (event->state & GDK_CONTROL_MASK)) {
	    term_scroll(inst->term, 0, +1);
	    return TRUE;
	}

	/*
	 * Neither does Shift-Ins.
	 */
	if (event->keyval == GDK_Insert && (event->state & GDK_SHIFT_MASK)) {
	    request_paste(inst);
	    return TRUE;
	}

	special = FALSE;
	use_ucsoutput = FALSE;

	/* ALT+things gives leading Escape. */
	output[0] = '\033';
	strncpy(output+1, event->string, 31);
	if (!*event->string &&
	    (ucsval = keysym_to_unicode(event->keyval)) >= 0) {
	    ucsoutput[0] = '\033';
	    ucsoutput[1] = ucsval;
	    use_ucsoutput = TRUE;
	    end = 2;
	} else {
	    output[31] = '\0';
	    end = strlen(output);
	}
	if (event->state & GDK_MOD1_MASK) {
	    start = 0;
	    if (end == 1) end = 0;
	} else
	    start = 1;

	/* Control-` is the same as Control-\ (unless gtk has a better idea) */
	if (!event->string[0] && event->keyval == '`' &&
	    (event->state & GDK_CONTROL_MASK)) {
	    output[1] = '\x1C';
	    use_ucsoutput = FALSE;
	    end = 2;
	}

	/* Control-Break sends a Break special to the backend */
	if (event->keyval == GDK_Break &&
	    (event->state & GDK_CONTROL_MASK)) {
	    if (inst->back)
		inst->back->special(inst->backhandle, TS_BRK);
	    return TRUE;
	}

	/* We handle Return ourselves, because it needs to be flagged as
	 * special to ldisc. */
	if (event->keyval == GDK_Return) {
	    output[1] = '\015';
	    use_ucsoutput = FALSE;
	    end = 2;
	    special = TRUE;
	}

	/* Control-2, Control-Space and Control-@ are NUL */
	if (!event->string[0] &&
	    (event->keyval == ' ' || event->keyval == '2' ||
	     event->keyval == '@') &&
	    (event->state & (GDK_SHIFT_MASK |
			     GDK_CONTROL_MASK)) == GDK_CONTROL_MASK) {
	    output[1] = '\0';
	    use_ucsoutput = FALSE;
	    end = 2;
	}

	/* Control-Shift-Space is 160 (ISO8859 nonbreaking space) */
	if (!event->string[0] && event->keyval == ' ' &&
	    (event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK)) ==
	    (GDK_SHIFT_MASK | GDK_CONTROL_MASK)) {
	    output[1] = '\240';
	    use_ucsoutput = FALSE;
	    end = 2;
	}

	/* We don't let GTK tell us what Backspace is! We know better. */
	if (event->keyval == GDK_BackSpace &&
	    !(event->state & GDK_SHIFT_MASK)) {
	    output[1] = inst->cfg.bksp_is_delete ? '\x7F' : '\x08';
	    use_ucsoutput = FALSE;
	    end = 2;
	    special = TRUE;
	}
	/* For Shift Backspace, do opposite of what is configured. */
	if (event->keyval == GDK_BackSpace &&
	    (event->state & GDK_SHIFT_MASK)) {
	    output[1] = inst->cfg.bksp_is_delete ? '\x08' : '\x7F';
	    use_ucsoutput = FALSE;
	    end = 2;
	    special = TRUE;
	}

	/* Shift-Tab is ESC [ Z */
	if (event->keyval == GDK_ISO_Left_Tab ||
	    (event->keyval == GDK_Tab && (event->state & GDK_SHIFT_MASK))) {
	    end = 1 + sprintf(output+1, "\033[Z");
	    use_ucsoutput = FALSE;
	}

	/*
	 * NetHack keypad mode.
	 */
	if (inst->cfg.nethack_keypad) {
	    char *keys = NULL;
	    switch (event->keyval) {
	      case GDK_KP_1: case GDK_KP_End: keys = "bB\002"; break;
	      case GDK_KP_2: case GDK_KP_Down: keys = "jJ\012"; break;
	      case GDK_KP_3: case GDK_KP_Page_Down: keys = "nN\016"; break;
	      case GDK_KP_4: case GDK_KP_Left: keys = "hH\010"; break;
	      case GDK_KP_5: case GDK_KP_Begin: keys = "..."; break;
	      case GDK_KP_6: case GDK_KP_Right: keys = "lL\014"; break;
	      case GDK_KP_7: case GDK_KP_Home: keys = "yY\031"; break;
	      case GDK_KP_8: case GDK_KP_Up: keys = "kK\013"; break;
	      case GDK_KP_9: case GDK_KP_Page_Up: keys = "uU\025"; break;
	    }
	    if (keys) {
		end = 2;
		if (event->state & GDK_CONTROL_MASK)
		    output[1] = keys[2];
		else if (event->state & GDK_SHIFT_MASK)
		    output[1] = keys[1];
		else
		    output[1] = keys[0];
		use_ucsoutput = FALSE;
		goto done;
	    }
	}

	/*
	 * Application keypad mode.
	 */
	if (inst->term->app_keypad_keys && !inst->cfg.no_applic_k) {
	    int xkey = 0;
	    switch (event->keyval) {
	      case GDK_Num_Lock: xkey = 'P'; break;
	      case GDK_KP_Divide: xkey = 'Q'; break;
	      case GDK_KP_Multiply: xkey = 'R'; break;
	      case GDK_KP_Subtract: xkey = 'S'; break;
		/*
		 * Keypad + is tricky. It covers a space that would
		 * be taken up on the VT100 by _two_ keys; so we
		 * let Shift select between the two. Worse still,
		 * in xterm function key mode we change which two...
		 */
	      case GDK_KP_Add:
		if (inst->cfg.funky_type == FUNKY_XTERM) {
		    if (event->state & GDK_SHIFT_MASK)
			xkey = 'l';
		    else
			xkey = 'k';
		} else if (event->state & GDK_SHIFT_MASK)
			xkey = 'm';
		else
		    xkey = 'l';
		break;
	      case GDK_KP_Enter: xkey = 'M'; break;
	      case GDK_KP_0: case GDK_KP_Insert: xkey = 'p'; break;
	      case GDK_KP_1: case GDK_KP_End: xkey = 'q'; break;
	      case GDK_KP_2: case GDK_KP_Down: xkey = 'r'; break;
	      case GDK_KP_3: case GDK_KP_Page_Down: xkey = 's'; break;
	      case GDK_KP_4: case GDK_KP_Left: xkey = 't'; break;
	      case GDK_KP_5: case GDK_KP_Begin: xkey = 'u'; break;
	      case GDK_KP_6: case GDK_KP_Right: xkey = 'v'; break;
	      case GDK_KP_7: case GDK_KP_Home: xkey = 'w'; break;
	      case GDK_KP_8: case GDK_KP_Up: xkey = 'x'; break;
	      case GDK_KP_9: case GDK_KP_Page_Up: xkey = 'y'; break;
	      case GDK_KP_Decimal: case GDK_KP_Delete: xkey = 'n'; break;
	    }
	    if (xkey) {
		if (inst->term->vt52_mode) {
		    if (xkey >= 'P' && xkey <= 'S')
			end = 1 + sprintf(output+1, "\033%c", xkey);
		    else
			end = 1 + sprintf(output+1, "\033?%c", xkey);
		} else
		    end = 1 + sprintf(output+1, "\033O%c", xkey);
		use_ucsoutput = FALSE;
		goto done;
	    }
	}

	/*
	 * Next, all the keys that do tilde codes. (ESC '[' nn '~',
	 * for integer decimal nn.)
	 *
	 * We also deal with the weird ones here. Linux VCs replace F1
	 * to F5 by ESC [ [ A to ESC [ [ E. rxvt doesn't do _that_, but
	 * does replace Home and End (1~ and 4~) by ESC [ H and ESC O w
	 * respectively.
	 */
	{
	    int code = 0;
	    switch (event->keyval) {
	      case GDK_F1:
		code = (event->state & GDK_SHIFT_MASK ? 23 : 11);
		break;
	      case GDK_F2:
		code = (event->state & GDK_SHIFT_MASK ? 24 : 12);
		break;
	      case GDK_F3:
		code = (event->state & GDK_SHIFT_MASK ? 25 : 13);
		break;
	      case GDK_F4:
		code = (event->state & GDK_SHIFT_MASK ? 26 : 14);
		break;
	      case GDK_F5:
		code = (event->state & GDK_SHIFT_MASK ? 28 : 15);
		break;
	      case GDK_F6:
		code = (event->state & GDK_SHIFT_MASK ? 29 : 17);
		break;
	      case GDK_F7:
		code = (event->state & GDK_SHIFT_MASK ? 31 : 18);
		break;
	      case GDK_F8:
		code = (event->state & GDK_SHIFT_MASK ? 32 : 19);
		break;
	      case GDK_F9:
		code = (event->state & GDK_SHIFT_MASK ? 33 : 20);
		break;
	      case GDK_F10:
		code = (event->state & GDK_SHIFT_MASK ? 34 : 21);
		break;
	      case GDK_F11:
		code = 23;
		break;
	      case GDK_F12:
		code = 24;
		break;
	      case GDK_F13:
		code = 25;
		break;
	      case GDK_F14:
		code = 26;
		break;
	      case GDK_F15:
		code = 28;
		break;
	      case GDK_F16:
		code = 29;
		break;
	      case GDK_F17:
		code = 31;
		break;
	      case GDK_F18:
		code = 32;
		break;
	      case GDK_F19:
		code = 33;
		break;
	      case GDK_F20:
		code = 34;
		break;
	    }
	    if (!(event->state & GDK_CONTROL_MASK)) switch (event->keyval) {

⌨️ 快捷键说明

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