if (inst->cfg.funky_type == 1 && code >= 11 && code <= 15) {
if (inst->cfg.funky_type == FUNKY_LINUX && code >= 11 && code <= 15) {
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 is the same as Control-C */	if (event->keyval == GDK_Break &&	    (event->state & GDK_CONTROL_MASK)) {	    output[1] = '\003';	    use_ucsoutput = FALSE;	    end = 2;	    special = 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"; break;	      case GDK_KP_2: case GDK_KP_Down: keys = "jJ"; break;	      case GDK_KP_3: case GDK_KP_Page_Down: keys = "nN"; break;	      case GDK_KP_4: case GDK_KP_Left: keys = "hH"; break;	      case GDK_KP_5: case GDK_KP_Begin: keys = ".."; break;	      case GDK_KP_6: case GDK_KP_Right: keys = "lL"; break;	      case GDK_KP_7: case GDK_KP_Home: keys = "yY"; break;	      case GDK_KP_8: case GDK_KP_Up: keys = "kK"; break;	      case GDK_KP_9: case GDK_KP_Page_Up: keys = "uU"; break;	    }	    if (keys) {		end = 2;		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 == 2) {		    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) {	      case GDK_Home: case GDK_KP_Home:		code = 1;		break;	      case GDK_Insert: case GDK_KP_Insert:		code = 2;		break;	      case GDK_Delete: case GDK_KP_Delete:		code = 3;		break;	      case GDK_End: case GDK_KP_End:		code = 4;		break;	      case GDK_Page_Up: case GDK_KP_Page_Up:		code = 5;		break;	      case GDK_Page_Down: case GDK_KP_Page_Down:		code = 6;		break;	    }	    /* Reorder edit keys to physical order */	    if (inst->cfg.funky_type == 3 && code <= 6)		code = "\0\2\1\4\5\3\6"[code];	    if (inst->term->vt52_mode && code > 0 && code <= 6) {		end = 1 + sprintf(output+1, "\x1B%c", " HLMEIG"[code]);		use_ucsoutput = FALSE;		goto done;	    }	    if (inst->cfg.funky_type == 5 &&     /* SCO function keys */		code >= 11 && code <= 34) {		char codes[] = "MNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@[\\]^_`{";		int index = 0;		switch (event->keyval) {		  case GDK_F1: index = 0; break;		  case GDK_F2: index = 1; break;		  case GDK_F3: index = 2; break;		  case GDK_F4: index = 3; break;		  case GDK_F5: index = 4; break;		  case GDK_F6: index = 5; break;		  case GDK_F7: index = 6; break;		  case GDK_F8: index = 7; break;		  case GDK_F9: index = 8; break;		  case GDK_F10: index = 9; break;		  case GDK_F11: index = 10; break;		  case GDK_F12: index = 11; break;		}		if (event->state & GDK_SHIFT_MASK) index += 12;		if (event->state & GDK_CONTROL_MASK) index += 24;		end = 1 + sprintf(output+1, "\x1B[%c", codes[index]);		use_ucsoutput = FALSE;		goto done;	    }	    if (inst->cfg.funky_type == 5 &&     /* SCO small keypad */		code >= 1 && code <= 6) {		char codes[] = "HL.FIG";		if (code == 3) {		    output[1] = '\x7F';		    end = 2;		} else {		    end = 1 + sprintf(output+1, "\x1B[%c", codes[code-1]);		}		use_ucsoutput = FALSE;		goto done;	    }	    if ((inst->term->vt52_mode || inst->cfg.funky_type == 4) &&		code >= 11 && code <= 24) {		int offt = 0;		if (code > 15)		    offt++;		if (code > 21)		    offt++;		if (inst->term->vt52_mode)		    end = 1 + sprintf(output+1,				      "\x1B%c", code + 'P' - 11 - offt);		else		    end = 1 + sprintf(output+1,				      "\x1BO%c", code + 'P' - 11 - offt);		use_ucsoutput = FALSE;		goto done;	    }	    if (inst->cfg.funky_type == 1 && code >= 11 && code <= 15) {		end = 1 + sprintf(output+1, "\x1B[[%c", code + 'A' - 11);		use_ucsoutput = FALSE;		goto done;	    }	    if (inst->cfg.funky_type == 2 && code >= 11 && code <= 14) {		if (inst->term->vt52_mode)		    end = 1 + sprintf(output+1, "\x1B%c", code + 'P' - 11);		else		    end = 1 + sprintf(output+1, "\x1BO%c", code + 'P' - 11);		use_ucsoutput = FALSE;		goto done;	    }	    if (inst->cfg.rxvt_homeend && (code == 1 || code == 4)) {		end = 1 + sprintf(output+1, code == 1 ? "\x1B[H" : "\x1BOw");		use_ucsoutput = FALSE;		goto done;	    }	    if (code) {		end = 1 + sprintf(output+1, "\x1B[%d~", code);		use_ucsoutput = FALSE;		goto done;	    }	}	/*	 * Cursor keys. (This includes the numberpad cursor keys,	 * if we haven't already done them due to app keypad mode.)	 * 	 * Here we also process un-numlocked un-appkeypadded KP5,	 * which sends ESC [ G.	 */	{	    int xkey = 0;	    switch (event->keyval) {	      case GDK_Up: case GDK_KP_Up: xkey = 'A'; break;	      case GDK_Down: case GDK_KP_Down: xkey = 'B'; break;	      case GDK_Right: case GDK_KP_Right: xkey = 'C'; break;	      case GDK_Left: case GDK_KP_Left: xkey = 'D'; break;	      case GDK_Begin: case GDK_KP_Begin: xkey = 'G'; break;	    }	    if (xkey) {		/*		 * The arrow keys normally do ESC [ A and so on. In		 * app cursor keys mode they do ESC O A instead.		 * Ctrl toggles the two modes.		 */		if (inst->term->vt52_mode) {		    end = 1 + sprintf(output+1, "\033%c", xkey);		} else if (!inst->term->app_cursor_keys ^			   !(event->state & GDK_CONTROL_MASK)) {		    end = 1 + sprintf(output+1, "\033O%c", xkey);		} else {		    		    end = 1 + sprintf(output+1, "\033[%c", xkey);		}		use_ucsoutput = FALSE;		goto done;	    }	}	goto done;    }    done:    if (end-start > 0) {#ifdef KEY_DEBUGGING	int i;	printf("generating sequence:");	for (i = start; i < end; i++)	    printf(" %02x", (unsigned char) output[i]);	printf("\n");#endif	if (special) {	    /*	     * For special control characters, the character set	     * should never matter.	     */	    output[end] = '\0';	       /* NUL-terminate */	    if (inst->ldisc)		ldisc_send(inst->ldisc, output+start, -2, 1);	} else if (!inst->direct_to_font) {	    if (!use_ucsoutput) {		/*		 * The stuff we've just generated is assumed to be		 * ISO-8859-1! This sounds insane, but `man		 * XLookupString' agrees: strings of this type		 * returned from the X server are hardcoded to		 * 8859-1. Strictly speaking we should be doing		 * this using some sort of GtkIMContext, which (if		 * we're lucky) would give us our data directly in		 * Unicode; but that's not supported in GTK 1.2 as		 * far as I can tell, and it's poorly documented		 * even in 2.0, so it'll have to wait.		 */		if (inst->ldisc)		    lpage_send(inst->ldisc, CS_ISO8859_1, output+start,			       end-start, 1);	    } else {		/*		 * We generated our own Unicode key data from the		 * keysym, so use that instead.		 */		if (inst->ldisc)		    luni_send(inst->ldisc, ucsoutput+start, end-start, 1);	    }	} else {	    /*	     * In direct-to-font mode, we just send the string	     * exactly as we received it.	     */	    if (inst->ldisc)		ldisc_send(inst->ldisc, output+start, end-start, 1);	}	show_mouseptr(inst, 0);	term_seen_key_event(inst->term);	term_out(inst->term);    }    return TRUE;}