"Fossies" - the Fresh Open Source Software Archive

Member "tmux-3.2a/tty-keys.c" (10 Jun 2021, 36428 Bytes) of package /linux/misc/tmux-3.2a.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "tty-keys.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 3.2_vs_3.2a.

    1 /* $OpenBSD$ */
    2 
    3 /*
    4  * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
    5  *
    6  * Permission to use, copy, modify, and distribute this software for any
    7  * purpose with or without fee is hereby granted, provided that the above
    8  * copyright notice and this permission notice appear in all copies.
    9  *
   10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   14  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
   15  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
   16  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   17  */
   18 
   19 #include <sys/types.h>
   20 #include <sys/time.h>
   21 
   22 #include <netinet/in.h>
   23 
   24 #include <ctype.h>
   25 #include <limits.h>
   26 #include <resolv.h>
   27 #include <stdlib.h>
   28 #include <string.h>
   29 #include <termios.h>
   30 #include <unistd.h>
   31 
   32 #include "tmux.h"
   33 
   34 /*
   35  * Handle keys input from the outside terminal. tty_default_*_keys[] are a base
   36  * table of supported keys which are looked up in terminfo(5) and translated
   37  * into a ternary tree.
   38  */
   39 
   40 static void tty_keys_add1(struct tty_key **, const char *, key_code);
   41 static void tty_keys_add(struct tty *, const char *, key_code);
   42 static void tty_keys_free1(struct tty_key *);
   43 static struct tty_key *tty_keys_find1(struct tty_key *, const char *, size_t,
   44             size_t *);
   45 static struct tty_key *tty_keys_find(struct tty *, const char *, size_t,
   46             size_t *);
   47 static int  tty_keys_next1(struct tty *, const char *, size_t, key_code *,
   48             size_t *, int);
   49 static void tty_keys_callback(int, short, void *);
   50 static int  tty_keys_extended_key(struct tty *, const char *, size_t,
   51             size_t *, key_code *);
   52 static int  tty_keys_mouse(struct tty *, const char *, size_t, size_t *,
   53             struct mouse_event *);
   54 static int  tty_keys_clipboard(struct tty *, const char *, size_t,
   55             size_t *);
   56 static int  tty_keys_device_attributes(struct tty *, const char *, size_t,
   57             size_t *);
   58 static int  tty_keys_extended_device_attributes(struct tty *, const char *,
   59             size_t, size_t *);
   60 
   61 /* Default raw keys. */
   62 struct tty_default_key_raw {
   63     const char         *string;
   64     key_code        key;
   65 };
   66 static const struct tty_default_key_raw tty_default_raw_keys[] = {
   67     /* Application escape. */
   68     { "\033O[", '\033' },
   69 
   70     /*
   71      * Numeric keypad. Just use the vt100 escape sequences here and always
   72      * put the terminal into keypad_xmit mode. Translation of numbers
   73      * mode/applications mode is done in input-keys.c.
   74      */
   75     { "\033Oo", KEYC_KP_SLASH|KEYC_KEYPAD },
   76     { "\033Oj", KEYC_KP_STAR|KEYC_KEYPAD },
   77     { "\033Om", KEYC_KP_MINUS|KEYC_KEYPAD },
   78     { "\033Ow", KEYC_KP_SEVEN|KEYC_KEYPAD },
   79     { "\033Ox", KEYC_KP_EIGHT|KEYC_KEYPAD },
   80     { "\033Oy", KEYC_KP_NINE|KEYC_KEYPAD },
   81     { "\033Ok", KEYC_KP_PLUS|KEYC_KEYPAD },
   82     { "\033Ot", KEYC_KP_FOUR|KEYC_KEYPAD },
   83     { "\033Ou", KEYC_KP_FIVE|KEYC_KEYPAD },
   84     { "\033Ov", KEYC_KP_SIX|KEYC_KEYPAD },
   85     { "\033Oq", KEYC_KP_ONE|KEYC_KEYPAD },
   86     { "\033Or", KEYC_KP_TWO|KEYC_KEYPAD },
   87     { "\033Os", KEYC_KP_THREE|KEYC_KEYPAD },
   88     { "\033OM", KEYC_KP_ENTER|KEYC_KEYPAD },
   89     { "\033Op", KEYC_KP_ZERO|KEYC_KEYPAD },
   90     { "\033On", KEYC_KP_PERIOD|KEYC_KEYPAD },
   91 
   92     /* Arrow keys. */
   93     { "\033OA", KEYC_UP|KEYC_CURSOR },
   94     { "\033OB", KEYC_DOWN|KEYC_CURSOR },
   95     { "\033OC", KEYC_RIGHT|KEYC_CURSOR },
   96     { "\033OD", KEYC_LEFT|KEYC_CURSOR },
   97 
   98     { "\033[A", KEYC_UP|KEYC_CURSOR },
   99     { "\033[B", KEYC_DOWN|KEYC_CURSOR },
  100     { "\033[C", KEYC_RIGHT|KEYC_CURSOR },
  101     { "\033[D", KEYC_LEFT|KEYC_CURSOR },
  102 
  103     /*
  104      * Meta arrow keys. These do not get the IMPLIED_META flag so they
  105      * don't match the xterm-style meta keys in the output tree - Escape+Up
  106      * should stay as Escape+Up and not become M-Up.
  107      */
  108     { "\033\033OA", KEYC_UP|KEYC_CURSOR|KEYC_META },
  109     { "\033\033OB", KEYC_DOWN|KEYC_CURSOR|KEYC_META },
  110     { "\033\033OC", KEYC_RIGHT|KEYC_CURSOR|KEYC_META },
  111     { "\033\033OD", KEYC_LEFT|KEYC_CURSOR|KEYC_META },
  112 
  113     { "\033\033[A", KEYC_UP|KEYC_CURSOR|KEYC_META },
  114     { "\033\033[B", KEYC_DOWN|KEYC_CURSOR|KEYC_META },
  115     { "\033\033[C", KEYC_RIGHT|KEYC_CURSOR|KEYC_META },
  116     { "\033\033[D", KEYC_LEFT|KEYC_CURSOR|KEYC_META },
  117 
  118     /* Other (xterm) "cursor" keys. */
  119     { "\033OH", KEYC_HOME },
  120     { "\033OF", KEYC_END },
  121 
  122     { "\033\033OH", KEYC_HOME|KEYC_META|KEYC_IMPLIED_META },
  123     { "\033\033OF", KEYC_END|KEYC_META|KEYC_IMPLIED_META },
  124 
  125     { "\033[H", KEYC_HOME },
  126     { "\033[F", KEYC_END },
  127 
  128     { "\033\033[H", KEYC_HOME|KEYC_META|KEYC_IMPLIED_META },
  129     { "\033\033[F", KEYC_END|KEYC_META|KEYC_IMPLIED_META },
  130 
  131     /* rxvt-style arrow + modifier keys. */
  132     { "\033Oa", KEYC_UP|KEYC_CTRL },
  133     { "\033Ob", KEYC_DOWN|KEYC_CTRL },
  134     { "\033Oc", KEYC_RIGHT|KEYC_CTRL },
  135     { "\033Od", KEYC_LEFT|KEYC_CTRL },
  136 
  137     { "\033[a", KEYC_UP|KEYC_SHIFT },
  138     { "\033[b", KEYC_DOWN|KEYC_SHIFT },
  139     { "\033[c", KEYC_RIGHT|KEYC_SHIFT },
  140     { "\033[d", KEYC_LEFT|KEYC_SHIFT },
  141 
  142     /* rxvt-style function + modifier keys (C = ^, S = $, C-S = @). */
  143     { "\033[11^", KEYC_F1|KEYC_CTRL },
  144     { "\033[12^", KEYC_F2|KEYC_CTRL },
  145     { "\033[13^", KEYC_F3|KEYC_CTRL },
  146     { "\033[14^", KEYC_F4|KEYC_CTRL },
  147     { "\033[15^", KEYC_F5|KEYC_CTRL },
  148     { "\033[17^", KEYC_F6|KEYC_CTRL },
  149     { "\033[18^", KEYC_F7|KEYC_CTRL },
  150     { "\033[19^", KEYC_F8|KEYC_CTRL },
  151     { "\033[20^", KEYC_F9|KEYC_CTRL },
  152     { "\033[21^", KEYC_F10|KEYC_CTRL },
  153     { "\033[23^", KEYC_F11|KEYC_CTRL },
  154     { "\033[24^", KEYC_F12|KEYC_CTRL },
  155     { "\033[2^", KEYC_IC|KEYC_CTRL },
  156     { "\033[3^", KEYC_DC|KEYC_CTRL },
  157     { "\033[7^", KEYC_HOME|KEYC_CTRL },
  158     { "\033[8^", KEYC_END|KEYC_CTRL },
  159     { "\033[6^", KEYC_NPAGE|KEYC_CTRL },
  160     { "\033[5^", KEYC_PPAGE|KEYC_CTRL },
  161 
  162     { "\033[11$", KEYC_F1|KEYC_SHIFT },
  163     { "\033[12$", KEYC_F2|KEYC_SHIFT },
  164     { "\033[13$", KEYC_F3|KEYC_SHIFT },
  165     { "\033[14$", KEYC_F4|KEYC_SHIFT },
  166     { "\033[15$", KEYC_F5|KEYC_SHIFT },
  167     { "\033[17$", KEYC_F6|KEYC_SHIFT },
  168     { "\033[18$", KEYC_F7|KEYC_SHIFT },
  169     { "\033[19$", KEYC_F8|KEYC_SHIFT },
  170     { "\033[20$", KEYC_F9|KEYC_SHIFT },
  171     { "\033[21$", KEYC_F10|KEYC_SHIFT },
  172     { "\033[23$", KEYC_F11|KEYC_SHIFT },
  173     { "\033[24$", KEYC_F12|KEYC_SHIFT },
  174     { "\033[2$", KEYC_IC|KEYC_SHIFT },
  175     { "\033[3$", KEYC_DC|KEYC_SHIFT },
  176     { "\033[7$", KEYC_HOME|KEYC_SHIFT },
  177     { "\033[8$", KEYC_END|KEYC_SHIFT },
  178     { "\033[6$", KEYC_NPAGE|KEYC_SHIFT },
  179     { "\033[5$", KEYC_PPAGE|KEYC_SHIFT },
  180 
  181     { "\033[11@", KEYC_F1|KEYC_CTRL|KEYC_SHIFT },
  182     { "\033[12@", KEYC_F2|KEYC_CTRL|KEYC_SHIFT },
  183     { "\033[13@", KEYC_F3|KEYC_CTRL|KEYC_SHIFT },
  184     { "\033[14@", KEYC_F4|KEYC_CTRL|KEYC_SHIFT },
  185     { "\033[15@", KEYC_F5|KEYC_CTRL|KEYC_SHIFT },
  186     { "\033[17@", KEYC_F6|KEYC_CTRL|KEYC_SHIFT },
  187     { "\033[18@", KEYC_F7|KEYC_CTRL|KEYC_SHIFT },
  188     { "\033[19@", KEYC_F8|KEYC_CTRL|KEYC_SHIFT },
  189     { "\033[20@", KEYC_F9|KEYC_CTRL|KEYC_SHIFT },
  190     { "\033[21@", KEYC_F10|KEYC_CTRL|KEYC_SHIFT },
  191     { "\033[23@", KEYC_F11|KEYC_CTRL|KEYC_SHIFT },
  192     { "\033[24@", KEYC_F12|KEYC_CTRL|KEYC_SHIFT },
  193     { "\033[2@", KEYC_IC|KEYC_CTRL|KEYC_SHIFT },
  194     { "\033[3@", KEYC_DC|KEYC_CTRL|KEYC_SHIFT },
  195     { "\033[7@", KEYC_HOME|KEYC_CTRL|KEYC_SHIFT },
  196     { "\033[8@", KEYC_END|KEYC_CTRL|KEYC_SHIFT },
  197     { "\033[6@", KEYC_NPAGE|KEYC_CTRL|KEYC_SHIFT },
  198     { "\033[5@", KEYC_PPAGE|KEYC_CTRL|KEYC_SHIFT },
  199 
  200     /* Focus tracking. */
  201     { "\033[I", KEYC_FOCUS_IN },
  202     { "\033[O", KEYC_FOCUS_OUT },
  203 
  204     /* Paste keys. */
  205     { "\033[200~", KEYC_PASTE_START },
  206     { "\033[201~", KEYC_PASTE_END },
  207 };
  208 
  209 /* Default xterm keys. */
  210 struct tty_default_key_xterm {
  211     const char  *template;
  212     key_code     key;
  213 };
  214 static const struct tty_default_key_xterm tty_default_xterm_keys[] = {
  215     { "\033[1;_P", KEYC_F1 },
  216     { "\033O1;_P", KEYC_F1 },
  217     { "\033O_P", KEYC_F1 },
  218     { "\033[1;_Q", KEYC_F2 },
  219     { "\033O1;_Q", KEYC_F2 },
  220     { "\033O_Q", KEYC_F2 },
  221     { "\033[1;_R", KEYC_F3 },
  222     { "\033O1;_R", KEYC_F3 },
  223     { "\033O_R", KEYC_F3 },
  224     { "\033[1;_S", KEYC_F4 },
  225     { "\033O1;_S", KEYC_F4 },
  226     { "\033O_S", KEYC_F4 },
  227     { "\033[15;_~", KEYC_F5 },
  228     { "\033[17;_~", KEYC_F6 },
  229     { "\033[18;_~", KEYC_F7 },
  230     { "\033[19;_~", KEYC_F8 },
  231     { "\033[20;_~", KEYC_F9 },
  232     { "\033[21;_~", KEYC_F10 },
  233     { "\033[23;_~", KEYC_F11 },
  234     { "\033[24;_~", KEYC_F12 },
  235     { "\033[1;_A", KEYC_UP },
  236     { "\033[1;_B", KEYC_DOWN },
  237     { "\033[1;_C", KEYC_RIGHT },
  238     { "\033[1;_D", KEYC_LEFT },
  239     { "\033[1;_H", KEYC_HOME },
  240     { "\033[1;_F", KEYC_END },
  241     { "\033[5;_~", KEYC_PPAGE },
  242     { "\033[6;_~", KEYC_NPAGE },
  243     { "\033[2;_~", KEYC_IC },
  244     { "\033[3;_~", KEYC_DC },
  245 };
  246 static const key_code tty_default_xterm_modifiers[] = {
  247     0,
  248     0,
  249     KEYC_SHIFT,
  250     KEYC_META|KEYC_IMPLIED_META,
  251     KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META,
  252     KEYC_CTRL,
  253     KEYC_SHIFT|KEYC_CTRL,
  254     KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL,
  255     KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL,
  256     KEYC_META|KEYC_IMPLIED_META
  257 };
  258 
  259 /*
  260  * Default terminfo(5) keys. Any keys that have builtin modifiers (that is,
  261  * where the key itself contains the modifiers) has the KEYC_XTERM flag set so
  262  * a leading escape is not treated as meta (and probably removed).
  263  */
  264 struct tty_default_key_code {
  265     enum tty_code_code  code;
  266     key_code        key;
  267 };
  268 static const struct tty_default_key_code tty_default_code_keys[] = {
  269     /* Function keys. */
  270     { TTYC_KF1, KEYC_F1 },
  271     { TTYC_KF2, KEYC_F2 },
  272     { TTYC_KF3, KEYC_F3 },
  273     { TTYC_KF4, KEYC_F4 },
  274     { TTYC_KF5, KEYC_F5 },
  275     { TTYC_KF6, KEYC_F6 },
  276     { TTYC_KF7, KEYC_F7 },
  277     { TTYC_KF8, KEYC_F8 },
  278     { TTYC_KF9, KEYC_F9 },
  279     { TTYC_KF10, KEYC_F10 },
  280     { TTYC_KF11, KEYC_F11 },
  281     { TTYC_KF12, KEYC_F12 },
  282 
  283     { TTYC_KF13, KEYC_F1|KEYC_SHIFT },
  284     { TTYC_KF14, KEYC_F2|KEYC_SHIFT },
  285     { TTYC_KF15, KEYC_F3|KEYC_SHIFT },
  286     { TTYC_KF16, KEYC_F4|KEYC_SHIFT },
  287     { TTYC_KF17, KEYC_F5|KEYC_SHIFT },
  288     { TTYC_KF18, KEYC_F6|KEYC_SHIFT },
  289     { TTYC_KF19, KEYC_F7|KEYC_SHIFT },
  290     { TTYC_KF20, KEYC_F8|KEYC_SHIFT },
  291     { TTYC_KF21, KEYC_F9|KEYC_SHIFT },
  292     { TTYC_KF22, KEYC_F10|KEYC_SHIFT },
  293     { TTYC_KF23, KEYC_F11|KEYC_SHIFT },
  294     { TTYC_KF24, KEYC_F12|KEYC_SHIFT },
  295 
  296     { TTYC_KF25, KEYC_F1|KEYC_CTRL },
  297     { TTYC_KF26, KEYC_F2|KEYC_CTRL },
  298     { TTYC_KF27, KEYC_F3|KEYC_CTRL },
  299     { TTYC_KF28, KEYC_F4|KEYC_CTRL },
  300     { TTYC_KF29, KEYC_F5|KEYC_CTRL },
  301     { TTYC_KF30, KEYC_F6|KEYC_CTRL },
  302     { TTYC_KF31, KEYC_F7|KEYC_CTRL },
  303     { TTYC_KF32, KEYC_F8|KEYC_CTRL },
  304     { TTYC_KF33, KEYC_F9|KEYC_CTRL },
  305     { TTYC_KF34, KEYC_F10|KEYC_CTRL },
  306     { TTYC_KF35, KEYC_F11|KEYC_CTRL },
  307     { TTYC_KF36, KEYC_F12|KEYC_CTRL },
  308 
  309     { TTYC_KF37, KEYC_F1|KEYC_SHIFT|KEYC_CTRL },
  310     { TTYC_KF38, KEYC_F2|KEYC_SHIFT|KEYC_CTRL },
  311     { TTYC_KF39, KEYC_F3|KEYC_SHIFT|KEYC_CTRL },
  312     { TTYC_KF40, KEYC_F4|KEYC_SHIFT|KEYC_CTRL },
  313     { TTYC_KF41, KEYC_F5|KEYC_SHIFT|KEYC_CTRL },
  314     { TTYC_KF42, KEYC_F6|KEYC_SHIFT|KEYC_CTRL },
  315     { TTYC_KF43, KEYC_F7|KEYC_SHIFT|KEYC_CTRL },
  316     { TTYC_KF44, KEYC_F8|KEYC_SHIFT|KEYC_CTRL },
  317     { TTYC_KF45, KEYC_F9|KEYC_SHIFT|KEYC_CTRL },
  318     { TTYC_KF46, KEYC_F10|KEYC_SHIFT|KEYC_CTRL },
  319     { TTYC_KF47, KEYC_F11|KEYC_SHIFT|KEYC_CTRL },
  320     { TTYC_KF48, KEYC_F12|KEYC_SHIFT|KEYC_CTRL },
  321 
  322     { TTYC_KF49, KEYC_F1|KEYC_META|KEYC_IMPLIED_META },
  323     { TTYC_KF50, KEYC_F2|KEYC_META|KEYC_IMPLIED_META },
  324     { TTYC_KF51, KEYC_F3|KEYC_META|KEYC_IMPLIED_META },
  325     { TTYC_KF52, KEYC_F4|KEYC_META|KEYC_IMPLIED_META },
  326     { TTYC_KF53, KEYC_F5|KEYC_META|KEYC_IMPLIED_META },
  327     { TTYC_KF54, KEYC_F6|KEYC_META|KEYC_IMPLIED_META },
  328     { TTYC_KF55, KEYC_F7|KEYC_META|KEYC_IMPLIED_META },
  329     { TTYC_KF56, KEYC_F8|KEYC_META|KEYC_IMPLIED_META },
  330     { TTYC_KF57, KEYC_F9|KEYC_META|KEYC_IMPLIED_META },
  331     { TTYC_KF58, KEYC_F10|KEYC_META|KEYC_IMPLIED_META },
  332     { TTYC_KF59, KEYC_F11|KEYC_META|KEYC_IMPLIED_META },
  333     { TTYC_KF60, KEYC_F12|KEYC_META|KEYC_IMPLIED_META },
  334 
  335     { TTYC_KF61, KEYC_F1|KEYC_META|KEYC_IMPLIED_META|KEYC_SHIFT },
  336     { TTYC_KF62, KEYC_F2|KEYC_META|KEYC_IMPLIED_META|KEYC_SHIFT },
  337     { TTYC_KF63, KEYC_F3|KEYC_META|KEYC_IMPLIED_META|KEYC_SHIFT },
  338 
  339     { TTYC_KICH1, KEYC_IC },
  340     { TTYC_KDCH1, KEYC_DC },
  341     { TTYC_KHOME, KEYC_HOME },
  342     { TTYC_KEND, KEYC_END },
  343     { TTYC_KNP, KEYC_NPAGE },
  344     { TTYC_KPP, KEYC_PPAGE },
  345     { TTYC_KCBT, KEYC_BTAB },
  346 
  347     /* Arrow keys from terminfo. */
  348     { TTYC_KCUU1, KEYC_UP|KEYC_CURSOR },
  349     { TTYC_KCUD1, KEYC_DOWN|KEYC_CURSOR },
  350     { TTYC_KCUB1, KEYC_LEFT|KEYC_CURSOR },
  351     { TTYC_KCUF1, KEYC_RIGHT|KEYC_CURSOR },
  352 
  353     /* Key and modifier capabilities. */
  354     { TTYC_KDC2, KEYC_DC|KEYC_SHIFT },
  355     { TTYC_KDC3, KEYC_DC|KEYC_META|KEYC_IMPLIED_META },
  356     { TTYC_KDC4, KEYC_DC|KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META },
  357     { TTYC_KDC5, KEYC_DC|KEYC_CTRL },
  358     { TTYC_KDC6, KEYC_DC|KEYC_SHIFT|KEYC_CTRL },
  359     { TTYC_KDC7, KEYC_DC|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL },
  360     { TTYC_KIND, KEYC_DOWN|KEYC_SHIFT },
  361     { TTYC_KDN2, KEYC_DOWN|KEYC_SHIFT },
  362     { TTYC_KDN3, KEYC_DOWN|KEYC_META|KEYC_IMPLIED_META },
  363     { TTYC_KDN4, KEYC_DOWN|KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META },
  364     { TTYC_KDN5, KEYC_DOWN|KEYC_CTRL },
  365     { TTYC_KDN6, KEYC_DOWN|KEYC_SHIFT|KEYC_CTRL },
  366     { TTYC_KDN7, KEYC_DOWN|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL },
  367     { TTYC_KEND2, KEYC_END|KEYC_SHIFT },
  368     { TTYC_KEND3, KEYC_END|KEYC_META|KEYC_IMPLIED_META },
  369     { TTYC_KEND4, KEYC_END|KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META },
  370     { TTYC_KEND5, KEYC_END|KEYC_CTRL },
  371     { TTYC_KEND6, KEYC_END|KEYC_SHIFT|KEYC_CTRL },
  372     { TTYC_KEND7, KEYC_END|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL },
  373     { TTYC_KHOM2, KEYC_HOME|KEYC_SHIFT },
  374     { TTYC_KHOM3, KEYC_HOME|KEYC_META|KEYC_IMPLIED_META },
  375     { TTYC_KHOM4, KEYC_HOME|KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META },
  376     { TTYC_KHOM5, KEYC_HOME|KEYC_CTRL },
  377     { TTYC_KHOM6, KEYC_HOME|KEYC_SHIFT|KEYC_CTRL },
  378     { TTYC_KHOM7, KEYC_HOME|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL },
  379     { TTYC_KIC2, KEYC_IC|KEYC_SHIFT },
  380     { TTYC_KIC3, KEYC_IC|KEYC_META|KEYC_IMPLIED_META },
  381     { TTYC_KIC4, KEYC_IC|KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META },
  382     { TTYC_KIC5, KEYC_IC|KEYC_CTRL },
  383     { TTYC_KIC6, KEYC_IC|KEYC_SHIFT|KEYC_CTRL },
  384     { TTYC_KIC7, KEYC_IC|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL },
  385     { TTYC_KLFT2, KEYC_LEFT|KEYC_SHIFT },
  386     { TTYC_KLFT3, KEYC_LEFT|KEYC_META|KEYC_IMPLIED_META },
  387     { TTYC_KLFT4, KEYC_LEFT|KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META },
  388     { TTYC_KLFT5, KEYC_LEFT|KEYC_CTRL },
  389     { TTYC_KLFT6, KEYC_LEFT|KEYC_SHIFT|KEYC_CTRL },
  390     { TTYC_KLFT7, KEYC_LEFT|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL },
  391     { TTYC_KNXT2, KEYC_NPAGE|KEYC_SHIFT },
  392     { TTYC_KNXT3, KEYC_NPAGE|KEYC_META|KEYC_IMPLIED_META },
  393     { TTYC_KNXT4, KEYC_NPAGE|KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META },
  394     { TTYC_KNXT5, KEYC_NPAGE|KEYC_CTRL },
  395     { TTYC_KNXT6, KEYC_NPAGE|KEYC_SHIFT|KEYC_CTRL },
  396     { TTYC_KNXT7, KEYC_NPAGE|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL },
  397     { TTYC_KPRV2, KEYC_PPAGE|KEYC_SHIFT },
  398     { TTYC_KPRV3, KEYC_PPAGE|KEYC_META|KEYC_IMPLIED_META },
  399     { TTYC_KPRV4, KEYC_PPAGE|KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META },
  400     { TTYC_KPRV5, KEYC_PPAGE|KEYC_CTRL },
  401     { TTYC_KPRV6, KEYC_PPAGE|KEYC_SHIFT|KEYC_CTRL },
  402     { TTYC_KPRV7, KEYC_PPAGE|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL },
  403     { TTYC_KRIT2, KEYC_RIGHT|KEYC_SHIFT },
  404     { TTYC_KRIT3, KEYC_RIGHT|KEYC_META|KEYC_IMPLIED_META },
  405     { TTYC_KRIT4, KEYC_RIGHT|KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META },
  406     { TTYC_KRIT5, KEYC_RIGHT|KEYC_CTRL },
  407     { TTYC_KRIT6, KEYC_RIGHT|KEYC_SHIFT|KEYC_CTRL },
  408     { TTYC_KRIT7, KEYC_RIGHT|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL },
  409     { TTYC_KRI, KEYC_UP|KEYC_SHIFT },
  410     { TTYC_KUP2, KEYC_UP|KEYC_SHIFT },
  411     { TTYC_KUP3, KEYC_UP|KEYC_META|KEYC_IMPLIED_META },
  412     { TTYC_KUP4, KEYC_UP|KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META },
  413     { TTYC_KUP5, KEYC_UP|KEYC_CTRL },
  414     { TTYC_KUP6, KEYC_UP|KEYC_SHIFT|KEYC_CTRL },
  415     { TTYC_KUP7, KEYC_UP|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL },
  416 };
  417 
  418 /* Add key to tree. */
  419 static void
  420 tty_keys_add(struct tty *tty, const char *s, key_code key)
  421 {
  422     struct tty_key  *tk;
  423     size_t       size;
  424     const char  *keystr;
  425 
  426     keystr = key_string_lookup_key(key, 1);
  427     if ((tk = tty_keys_find(tty, s, strlen(s), &size)) == NULL) {
  428         log_debug("new key %s: 0x%llx (%s)", s, key, keystr);
  429         tty_keys_add1(&tty->key_tree, s, key);
  430     } else {
  431         log_debug("replacing key %s: 0x%llx (%s)", s, key, keystr);
  432         tk->key = key;
  433     }
  434 }
  435 
  436 /* Add next node to the tree. */
  437 static void
  438 tty_keys_add1(struct tty_key **tkp, const char *s, key_code key)
  439 {
  440     struct tty_key  *tk;
  441 
  442     /* Allocate a tree entry if there isn't one already. */
  443     tk = *tkp;
  444     if (tk == NULL) {
  445         tk = *tkp = xcalloc(1, sizeof *tk);
  446         tk->ch = *s;
  447         tk->key = KEYC_UNKNOWN;
  448     }
  449 
  450     /* Find the next entry. */
  451     if (*s == tk->ch) {
  452         /* Move forward in string. */
  453         s++;
  454 
  455         /* If this is the end of the string, no more is necessary. */
  456         if (*s == '\0') {
  457             tk->key = key;
  458             return;
  459         }
  460 
  461         /* Use the child tree for the next character. */
  462         tkp = &tk->next;
  463     } else {
  464         if (*s < tk->ch)
  465             tkp = &tk->left;
  466         else if (*s > tk->ch)
  467             tkp = &tk->right;
  468     }
  469 
  470     /* And recurse to add it. */
  471     tty_keys_add1(tkp, s, key);
  472 }
  473 
  474 /* Initialise a key tree from the table. */
  475 void
  476 tty_keys_build(struct tty *tty)
  477 {
  478     const struct tty_default_key_raw    *tdkr;
  479     const struct tty_default_key_xterm  *tdkx;
  480     const struct tty_default_key_code   *tdkc;
  481     u_int                    i, j;
  482     const char              *s;
  483     struct options_entry            *o;
  484     struct options_array_item       *a;
  485     union options_value         *ov;
  486     char                     copy[16];
  487     key_code                 key;
  488 
  489     if (tty->key_tree != NULL)
  490         tty_keys_free(tty);
  491     tty->key_tree = NULL;
  492 
  493     for (i = 0; i < nitems(tty_default_xterm_keys); i++) {
  494         tdkx = &tty_default_xterm_keys[i];
  495         for (j = 2; j < nitems(tty_default_xterm_modifiers); j++) {
  496             strlcpy(copy, tdkx->template, sizeof copy);
  497             copy[strcspn(copy, "_")] = '0' + j;
  498 
  499             key = tdkx->key|tty_default_xterm_modifiers[j];
  500             tty_keys_add(tty, copy, key);
  501         }
  502     }
  503     for (i = 0; i < nitems(tty_default_raw_keys); i++) {
  504         tdkr = &tty_default_raw_keys[i];
  505 
  506         s = tdkr->string;
  507         if (*s != '\0')
  508             tty_keys_add(tty, s, tdkr->key);
  509     }
  510     for (i = 0; i < nitems(tty_default_code_keys); i++) {
  511         tdkc = &tty_default_code_keys[i];
  512 
  513         s = tty_term_string(tty->term, tdkc->code);
  514         if (*s != '\0')
  515             tty_keys_add(tty, s, tdkc->key);
  516 
  517     }
  518 
  519     o = options_get(global_options, "user-keys");
  520     if (o != NULL) {
  521         a = options_array_first(o);
  522         while (a != NULL) {
  523             i = options_array_item_index(a);
  524             ov = options_array_item_value(a);
  525             tty_keys_add(tty, ov->string, KEYC_USER + i);
  526             a = options_array_next(a);
  527         }
  528     }
  529 }
  530 
  531 /* Free the entire key tree. */
  532 void
  533 tty_keys_free(struct tty *tty)
  534 {
  535     tty_keys_free1(tty->key_tree);
  536 }
  537 
  538 /* Free a single key. */
  539 static void
  540 tty_keys_free1(struct tty_key *tk)
  541 {
  542     if (tk->next != NULL)
  543         tty_keys_free1(tk->next);
  544     if (tk->left != NULL)
  545         tty_keys_free1(tk->left);
  546     if (tk->right != NULL)
  547         tty_keys_free1(tk->right);
  548     free(tk);
  549 }
  550 
  551 /* Lookup a key in the tree. */
  552 static struct tty_key *
  553 tty_keys_find(struct tty *tty, const char *buf, size_t len, size_t *size)
  554 {
  555     *size = 0;
  556     return (tty_keys_find1(tty->key_tree, buf, len, size));
  557 }
  558 
  559 /* Find the next node. */
  560 static struct tty_key *
  561 tty_keys_find1(struct tty_key *tk, const char *buf, size_t len, size_t *size)
  562 {
  563     /* If no data, no match. */
  564     if (len == 0)
  565         return (NULL);
  566 
  567     /* If the node is NULL, this is the end of the tree. No match. */
  568     if (tk == NULL)
  569         return (NULL);
  570 
  571     /* Pick the next in the sequence. */
  572     if (tk->ch == *buf) {
  573         /* Move forward in the string. */
  574         buf++; len--;
  575         (*size)++;
  576 
  577         /* At the end of the string, return the current node. */
  578         if (len == 0 || (tk->next == NULL && tk->key != KEYC_UNKNOWN))
  579             return (tk);
  580 
  581         /* Move into the next tree for the following character. */
  582         tk = tk->next;
  583     } else {
  584         if (*buf < tk->ch)
  585             tk = tk->left;
  586         else if (*buf > tk->ch)
  587             tk = tk->right;
  588     }
  589 
  590     /* Move to the next in the tree. */
  591     return (tty_keys_find1(tk, buf, len, size));
  592 }
  593 
  594 /* Look up part of the next key. */
  595 static int
  596 tty_keys_next1(struct tty *tty, const char *buf, size_t len, key_code *key,
  597     size_t *size, int expired)
  598 {
  599     struct client       *c = tty->client;
  600     struct tty_key      *tk, *tk1;
  601     struct utf8_data     ud;
  602     enum utf8_state      more;
  603     utf8_char        uc;
  604     u_int            i;
  605 
  606     log_debug("%s: next key is %zu (%.*s) (expired=%d)", c->name, len,
  607         (int)len, buf, expired);
  608 
  609     /* Is this a known key? */
  610     tk = tty_keys_find(tty, buf, len, size);
  611     if (tk != NULL && tk->key != KEYC_UNKNOWN) {
  612         tk1 = tk;
  613         do
  614             log_debug("%s: keys in list: %#llx", c->name, tk1->key);
  615         while ((tk1 = tk1->next) != NULL);
  616         if (tk->next != NULL && !expired)
  617             return (1);
  618         *key = tk->key;
  619         return (0);
  620     }
  621 
  622     /* Is this valid UTF-8? */
  623     more = utf8_open(&ud, (u_char)*buf);
  624     if (more == UTF8_MORE) {
  625         *size = ud.size;
  626         if (len < ud.size) {
  627             if (!expired)
  628                 return (1);
  629             return (-1);
  630         }
  631         for (i = 1; i < ud.size; i++)
  632             more = utf8_append(&ud, (u_char)buf[i]);
  633         if (more != UTF8_DONE)
  634             return (-1);
  635 
  636         if (utf8_from_data(&ud, &uc) != UTF8_DONE)
  637             return (-1);
  638         *key = uc;
  639 
  640         log_debug("%s: UTF-8 key %.*s %#llx", c->name, (int)ud.size,
  641             ud.data, *key);
  642         return (0);
  643     }
  644 
  645     return (-1);
  646 }
  647 
  648 /* Process at least one key in the buffer. Return 0 if no keys present. */
  649 int
  650 tty_keys_next(struct tty *tty)
  651 {
  652     struct client       *c = tty->client;
  653     struct timeval       tv;
  654     const char      *buf;
  655     size_t           len, size;
  656     cc_t             bspace;
  657     int          delay, expired = 0, n;
  658     key_code         key;
  659     struct mouse_event   m = { 0 };
  660     struct key_event    *event;
  661 
  662     /* Get key buffer. */
  663     buf = EVBUFFER_DATA(tty->in);
  664     len = EVBUFFER_LENGTH(tty->in);
  665     if (len == 0)
  666         return (0);
  667     log_debug("%s: keys are %zu (%.*s)", c->name, len, (int)len, buf);
  668 
  669     /* Is this a clipboard response? */
  670     switch (tty_keys_clipboard(tty, buf, len, &size)) {
  671     case 0:     /* yes */
  672         key = KEYC_UNKNOWN;
  673         goto complete_key;
  674     case -1:    /* no, or not valid */
  675         break;
  676     case 1:     /* partial */
  677         goto partial_key;
  678     }
  679 
  680     /* Is this a device attributes response? */
  681     switch (tty_keys_device_attributes(tty, buf, len, &size)) {
  682     case 0:     /* yes */
  683         key = KEYC_UNKNOWN;
  684         goto complete_key;
  685     case -1:    /* no, or not valid */
  686         break;
  687     case 1:     /* partial */
  688         goto partial_key;
  689     }
  690 
  691     /* Is this an extended device attributes response? */
  692     switch (tty_keys_extended_device_attributes(tty, buf, len, &size)) {
  693     case 0:     /* yes */
  694         key = KEYC_UNKNOWN;
  695         goto complete_key;
  696     case -1:    /* no, or not valid */
  697         break;
  698     case 1:     /* partial */
  699         goto partial_key;
  700     }
  701 
  702     /* Is this a mouse key press? */
  703     switch (tty_keys_mouse(tty, buf, len, &size, &m)) {
  704     case 0:     /* yes */
  705         key = KEYC_MOUSE;
  706         goto complete_key;
  707     case -1:    /* no, or not valid */
  708         break;
  709     case -2:    /* yes, but we don't care. */
  710         key = KEYC_MOUSE;
  711         goto discard_key;
  712     case 1:     /* partial */
  713         goto partial_key;
  714     }
  715 
  716     /* Is this an extended key press? */
  717     switch (tty_keys_extended_key(tty, buf, len, &size, &key)) {
  718     case 0:     /* yes */
  719         goto complete_key;
  720     case -1:    /* no, or not valid */
  721         break;
  722     case 1:     /* partial */
  723         goto partial_key;
  724     }
  725 
  726 first_key:
  727     /* Try to lookup complete key. */
  728     n = tty_keys_next1(tty, buf, len, &key, &size, expired);
  729     if (n == 0) /* found */
  730         goto complete_key;
  731     if (n == 1)
  732         goto partial_key;
  733 
  734     /*
  735      * If not a complete key, look for key with an escape prefix (meta
  736      * modifier).
  737      */
  738     if (*buf == '\033' && len > 1) {
  739         /* Look for a key without the escape. */
  740         n = tty_keys_next1(tty, buf + 1, len - 1, &key, &size, expired);
  741         if (n == 0) {   /* found */
  742             if (key & KEYC_IMPLIED_META) {
  743                 /*
  744                  * We want the escape key as well as the xterm
  745                  * key, because the xterm sequence implicitly
  746                  * includes the escape (so if we see
  747                  * \033\033[1;3D we know it is an Escape
  748                  * followed by M-Left, not just M-Left).
  749                  */
  750                 key = '\033';
  751                 size = 1;
  752                 goto complete_key;
  753             }
  754             key |= KEYC_META;
  755             size++;
  756             goto complete_key;
  757         }
  758         if (n == 1) /* partial */
  759             goto partial_key;
  760     }
  761 
  762     /*
  763      * At this point, we know the key is not partial (with or without
  764      * escape). So pass it through even if the timer has not expired.
  765      */
  766     if (*buf == '\033' && len >= 2) {
  767         key = (u_char)buf[1] | KEYC_META;
  768         size = 2;
  769     } else {
  770         key = (u_char)buf[0];
  771         size = 1;
  772     }
  773     goto complete_key;
  774 
  775 partial_key:
  776     log_debug("%s: partial key %.*s", c->name, (int)len, buf);
  777 
  778     /* If timer is going, check for expiration. */
  779     if (tty->flags & TTY_TIMER) {
  780         if (evtimer_initialized(&tty->key_timer) &&
  781             !evtimer_pending(&tty->key_timer, NULL)) {
  782             expired = 1;
  783             goto first_key;
  784         }
  785         return (0);
  786     }
  787 
  788     /* Get the time period. */
  789     delay = options_get_number(global_options, "escape-time");
  790     tv.tv_sec = delay / 1000;
  791     tv.tv_usec = (delay % 1000) * 1000L;
  792 
  793     /* Start the timer. */
  794     if (event_initialized(&tty->key_timer))
  795         evtimer_del(&tty->key_timer);
  796     evtimer_set(&tty->key_timer, tty_keys_callback, tty);
  797     evtimer_add(&tty->key_timer, &tv);
  798 
  799     tty->flags |= TTY_TIMER;
  800     return (0);
  801 
  802 complete_key:
  803     log_debug("%s: complete key %.*s %#llx", c->name, (int)size, buf, key);
  804 
  805     /*
  806      * Check for backspace key using termios VERASE - the terminfo
  807      * kbs entry is extremely unreliable, so cannot be safely
  808      * used. termios should have a better idea.
  809      */
  810     bspace = tty->tio.c_cc[VERASE];
  811     if (bspace != _POSIX_VDISABLE && (key & KEYC_MASK_KEY) == bspace)
  812         key = (key & KEYC_MASK_MODIFIERS)|KEYC_BSPACE;
  813 
  814     /* Remove data from buffer. */
  815     evbuffer_drain(tty->in, size);
  816 
  817     /* Remove key timer. */
  818     if (event_initialized(&tty->key_timer))
  819         evtimer_del(&tty->key_timer);
  820     tty->flags &= ~TTY_TIMER;
  821 
  822     /* Check for focus events. */
  823     if (key == KEYC_FOCUS_OUT)
  824         tty->client->flags &= ~CLIENT_FOCUSED;
  825     else if (key == KEYC_FOCUS_IN)
  826         tty->client->flags |= CLIENT_FOCUSED;
  827 
  828     /* Fire the key. */
  829     if (key != KEYC_UNKNOWN) {
  830         event = xmalloc(sizeof *event);
  831         event->key = key;
  832         memcpy(&event->m, &m, sizeof event->m);
  833         if (!server_client_handle_key(c, event))
  834             free(event);
  835     }
  836 
  837     return (1);
  838 
  839 discard_key:
  840     log_debug("%s: discard key %.*s %#llx", c->name, (int)size, buf, key);
  841 
  842     /* Remove data from buffer. */
  843     evbuffer_drain(tty->in, size);
  844 
  845     return (1);
  846 }
  847 
  848 /* Key timer callback. */
  849 static void
  850 tty_keys_callback(__unused int fd, __unused short events, void *data)
  851 {
  852     struct tty  *tty = data;
  853 
  854     if (tty->flags & TTY_TIMER) {
  855         while (tty_keys_next(tty))
  856             ;
  857     }
  858 }
  859 
  860 /*
  861  * Handle extended key input. This has two forms: \033[27;m;k~ and \033[k;mu,
  862  * where k is key as a number and m is a modifier. Returns 0 for success, -1
  863  * for failure, 1 for partial;
  864  */
  865 static int
  866 tty_keys_extended_key(struct tty *tty, const char *buf, size_t len,
  867     size_t *size, key_code *key)
  868 {
  869     struct client   *c = tty->client;
  870     size_t       end;
  871     u_int        number, modifiers;
  872     char         tmp[64];
  873     cc_t         bspace;
  874     key_code     nkey;
  875     key_code     onlykey;
  876 
  877     *size = 0;
  878 
  879     /* First two bytes are always \033[. */
  880     if (buf[0] != '\033')
  881         return (-1);
  882     if (len == 1)
  883         return (1);
  884     if (buf[1] != '[')
  885         return (-1);
  886     if (len == 2)
  887         return (1);
  888 
  889     /*
  890      * Look for a terminator. Stop at either '~' or anything that isn't a
  891      * number or ';'.
  892      */
  893     for (end = 2; end < len && end != sizeof tmp; end++) {
  894         if (buf[end] == '~')
  895             break;
  896         if (!isdigit((u_char)buf[end]) && buf[end] != ';')
  897             break;
  898     }
  899     if (end == len)
  900         return (1);
  901     if (end == sizeof tmp || (buf[end] != '~' && buf[end] != 'u'))
  902         return (-1);
  903 
  904     /* Copy to the buffer. */
  905     memcpy(tmp, buf + 2, end);
  906     tmp[end] = '\0';
  907 
  908     /* Try to parse either form of key. */
  909     if (buf[end] == '~') {
  910         if (sscanf(tmp, "27;%u;%u", &modifiers, &number) != 2)
  911             return (-1);
  912     } else {
  913         if (sscanf(tmp ,"%u;%u", &number, &modifiers) != 2)
  914             return (-1);
  915     }
  916     *size = end + 1;
  917 
  918     /* Store the key. */
  919     bspace = tty->tio.c_cc[VERASE];
  920     if (bspace != _POSIX_VDISABLE && number == bspace)
  921         nkey = KEYC_BSPACE;
  922     else
  923         nkey = number;
  924 
  925     /* Update the modifiers. */
  926     switch (modifiers) {
  927     case 2:
  928         nkey |= KEYC_SHIFT;
  929         break;
  930     case 3:
  931         nkey |= (KEYC_META|KEYC_IMPLIED_META);
  932         break;
  933     case 4:
  934         nkey |= (KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META);
  935         break;
  936     case 5:
  937         nkey |= KEYC_CTRL;
  938         break;
  939     case 6:
  940         nkey |= (KEYC_SHIFT|KEYC_CTRL);
  941         break;
  942     case 7:
  943         nkey |= (KEYC_META|KEYC_CTRL);
  944         break;
  945     case 8:
  946         nkey |= (KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL);
  947         break;
  948     case 9:
  949         nkey |= (KEYC_META|KEYC_IMPLIED_META);
  950         break;
  951     default:
  952         *key = KEYC_NONE;
  953         break;
  954     }
  955 
  956     /*
  957      * Don't allow both KEYC_CTRL and as an implied modifier. Also convert
  958      * C-X into C-x and so on.
  959      */
  960     if (nkey & KEYC_CTRL) {
  961         onlykey = (nkey & KEYC_MASK_KEY);
  962         if (onlykey < 32 &&
  963             onlykey != 9 &&
  964             onlykey != 13 &&
  965             onlykey != 27)
  966             /* nothing */;
  967         else if (onlykey >= 97 && onlykey <= 122)
  968             onlykey -= 96;
  969         else if (onlykey >= 64 && onlykey <= 95)
  970             onlykey -= 64;
  971         else if (onlykey == 32)
  972             onlykey = 0;
  973         else if (onlykey == 63)
  974             onlykey = 127;
  975         else
  976             onlykey |= KEYC_CTRL;
  977         nkey = onlykey|((nkey & KEYC_MASK_MODIFIERS) & ~KEYC_CTRL);
  978     }
  979 
  980     if (log_get_level() != 0) {
  981         log_debug("%s: extended key %.*s is %llx (%s)", c->name,
  982             (int)*size, buf, nkey, key_string_lookup_key(nkey, 1));
  983     }
  984     *key = nkey;
  985     return (0);
  986 }
  987 
  988 /*
  989  * Handle mouse key input. Returns 0 for success, -1 for failure, 1 for partial
  990  * (probably a mouse sequence but need more data).
  991  */
  992 static int
  993 tty_keys_mouse(struct tty *tty, const char *buf, size_t len, size_t *size,
  994     struct mouse_event *m)
  995 {
  996     struct client   *c = tty->client;
  997     u_int        i, x, y, b, sgr_b;
  998     u_char       sgr_type, ch;
  999 
 1000     /*
 1001      * Standard mouse sequences are \033[M followed by three characters
 1002      * indicating button, X and Y, all based at 32 with 1,1 top-left.
 1003      *
 1004      * UTF-8 mouse sequences are similar but the three are expressed as
 1005      * UTF-8 characters.
 1006      *
 1007      * SGR extended mouse sequences are \033[< followed by three numbers in
 1008      * decimal and separated by semicolons indicating button, X and Y. A
 1009      * trailing 'M' is click or scroll and trailing 'm' release. All are
 1010      * based at 0 with 1,1 top-left.
 1011      */
 1012 
 1013     *size = 0;
 1014     x = y = b = sgr_b = 0;
 1015     sgr_type = ' ';
 1016 
 1017     /* First two bytes are always \033[. */
 1018     if (buf[0] != '\033')
 1019         return (-1);
 1020     if (len == 1)
 1021         return (1);
 1022     if (buf[1] != '[')
 1023         return (-1);
 1024     if (len == 2)
 1025         return (1);
 1026 
 1027     /*
 1028      * Third byte is M in old standard (and UTF-8 extension which we do not
 1029      * support), < in SGR extension.
 1030      */
 1031     if (buf[2] == 'M') {
 1032         /* Read the three inputs. */
 1033         *size = 3;
 1034         for (i = 0; i < 3; i++) {
 1035             if (len <= *size)
 1036                 return (1);
 1037             ch = (u_char)buf[(*size)++];
 1038             if (i == 0)
 1039                 b = ch;
 1040             else if (i == 1)
 1041                 x = ch;
 1042             else
 1043                 y = ch;
 1044         }
 1045         log_debug("%s: mouse input: %.*s", c->name, (int)*size, buf);
 1046 
 1047         /* Check and return the mouse input. */
 1048         if (b < 32)
 1049             return (-1);
 1050         b -= 32;
 1051         if (x >= 33)
 1052             x -= 33;
 1053         else
 1054             x = 256 - x;
 1055         if (y >= 33)
 1056             y -= 33;
 1057         else
 1058             y = 256 - y;
 1059     } else if (buf[2] == '<') {
 1060         /* Read the three inputs. */
 1061         *size = 3;
 1062         while (1) {
 1063             if (len <= *size)
 1064                 return (1);
 1065             ch = (u_char)buf[(*size)++];
 1066             if (ch == ';')
 1067                 break;
 1068             if (ch < '0' || ch > '9')
 1069                 return (-1);
 1070             sgr_b = 10 * sgr_b + (ch - '0');
 1071         }
 1072         while (1) {
 1073             if (len <= *size)
 1074                 return (1);
 1075             ch = (u_char)buf[(*size)++];
 1076             if (ch == ';')
 1077                 break;
 1078             if (ch < '0' || ch > '9')
 1079                 return (-1);
 1080             x = 10 * x + (ch - '0');
 1081         }
 1082         while (1) {
 1083             if (len <= *size)
 1084                 return (1);
 1085             ch = (u_char)buf[(*size)++];
 1086             if (ch == 'M' || ch == 'm')
 1087                 break;
 1088             if (ch < '0' || ch > '9')
 1089                 return (-1);
 1090             y = 10 * y + (ch - '0');
 1091         }
 1092         log_debug("%s: mouse input (SGR): %.*s", c->name, (int)*size,
 1093             buf);
 1094 
 1095         /* Check and return the mouse input. */
 1096         if (x < 1 || y < 1)
 1097             return (-1);
 1098         x--;
 1099         y--;
 1100         b = sgr_b;
 1101 
 1102         /* Type is M for press, m for release. */
 1103         sgr_type = ch;
 1104         if (sgr_type == 'm')
 1105             b |= 3;
 1106 
 1107         /*
 1108          * Some terminals (like PuTTY 0.63) mistakenly send
 1109          * button-release events for scroll-wheel button-press event.
 1110          * Discard it before it reaches any program running inside
 1111          * tmux.
 1112          */
 1113         if (sgr_type == 'm' && (sgr_b & 64))
 1114             return (-2);
 1115     } else
 1116         return (-1);
 1117 
 1118     /* Fill mouse event. */
 1119     m->lx = tty->mouse_last_x;
 1120     m->x = x;
 1121     m->ly = tty->mouse_last_y;
 1122     m->y = y;
 1123     m->lb = tty->mouse_last_b;
 1124     m->b = b;
 1125     m->sgr_type = sgr_type;
 1126     m->sgr_b = sgr_b;
 1127 
 1128     /* Update last mouse state. */
 1129     tty->mouse_last_x = x;
 1130     tty->mouse_last_y = y;
 1131     tty->mouse_last_b = b;
 1132 
 1133     return (0);
 1134 }
 1135 
 1136 /*
 1137  * Handle OSC 52 clipboard input. Returns 0 for success, -1 for failure, 1 for
 1138  * partial.
 1139  */
 1140 static int
 1141 tty_keys_clipboard(__unused struct tty *tty, const char *buf, size_t len,
 1142     size_t *size)
 1143 {
 1144     size_t   end, terminator, needed;
 1145     char    *copy, *out;
 1146     int  outlen;
 1147 
 1148     *size = 0;
 1149 
 1150     /* First five bytes are always \033]52;. */
 1151     if (buf[0] != '\033')
 1152         return (-1);
 1153     if (len == 1)
 1154         return (1);
 1155     if (buf[1] != ']')
 1156         return (-1);
 1157     if (len == 2)
 1158         return (1);
 1159     if (buf[2] != '5')
 1160         return (-1);
 1161     if (len == 3)
 1162         return (1);
 1163     if (buf[3] != '2')
 1164         return (-1);
 1165     if (len == 4)
 1166         return (1);
 1167     if (buf[4] != ';')
 1168         return (-1);
 1169     if (len == 5)
 1170         return (1);
 1171 
 1172     /* Find the terminator if any. */
 1173     for (end = 5; end < len; end++) {
 1174         if (buf[end] == '\007') {
 1175             terminator = 1;
 1176             break;
 1177         }
 1178         if (end > 5 && buf[end - 1] == '\033' && buf[end] == '\\') {
 1179             terminator = 2;
 1180             break;
 1181         }
 1182     }
 1183     if (end == len)
 1184         return (1);
 1185     *size = end + terminator;
 1186 
 1187     /* Skip the initial part. */
 1188     buf += 5;
 1189     end -= 5;
 1190 
 1191     /* Get the second argument. */
 1192     while (end != 0 && *buf != ';') {
 1193         buf++;
 1194         end--;
 1195     }
 1196     if (end == 0 || end == 1)
 1197         return (0);
 1198     buf++;
 1199     end--;
 1200 
 1201     /* It has to be a string so copy it. */
 1202     copy = xmalloc(end + 1);
 1203     memcpy(copy, buf, end);
 1204     copy[end] = '\0';
 1205 
 1206     /* Convert from base64. */
 1207     needed = (end / 4) * 3;
 1208     out = xmalloc(needed);
 1209     if ((outlen = b64_pton(copy, out, len)) == -1) {
 1210         free(out);
 1211         free(copy);
 1212         return (0);
 1213     }
 1214     free(copy);
 1215 
 1216     /* Create a new paste buffer. */
 1217     log_debug("%s: %.*s", __func__, outlen, out);
 1218     paste_add(NULL, out, outlen);
 1219 
 1220     return (0);
 1221 }
 1222 
 1223 /*
 1224  * Handle secondary device attributes input. Returns 0 for success, -1 for
 1225  * failure, 1 for partial.
 1226  */
 1227 static int
 1228 tty_keys_device_attributes(struct tty *tty, const char *buf, size_t len,
 1229     size_t *size)
 1230 {
 1231     struct client   *c = tty->client;
 1232     u_int        i, n = 0;
 1233     char         tmp[64], *endptr, p[32] = { 0 }, *cp, *next;
 1234 
 1235     *size = 0;
 1236     if (tty->flags & TTY_HAVEDA)
 1237         return (-1);
 1238 
 1239     /*
 1240      * First three bytes are always \033[>. Some older Terminal.app
 1241      * versions respond as for DA (\033[?) so accept and ignore that.
 1242      */
 1243     if (buf[0] != '\033')
 1244         return (-1);
 1245     if (len == 1)
 1246         return (1);
 1247     if (buf[1] != '[')
 1248         return (-1);
 1249     if (len == 2)
 1250         return (1);
 1251     if (buf[2] != '>' && buf[2] != '?')
 1252         return (-1);
 1253     if (len == 3)
 1254         return (1);
 1255 
 1256     /* Copy the rest up to a 'c'. */
 1257     for (i = 0; i < (sizeof tmp) - 1; i++) {
 1258         if (3 + i == len)
 1259             return (1);
 1260         if (buf[3 + i] == 'c')
 1261             break;
 1262         tmp[i] = buf[3 + i];
 1263     }
 1264     if (i == (sizeof tmp) - 1)
 1265         return (-1);
 1266     tmp[i] = '\0';
 1267     *size = 4 + i;
 1268 
 1269     /* Ignore DA response. */
 1270     if (buf[2] == '?')
 1271         return (0);
 1272 
 1273     /* Convert all arguments to numbers. */
 1274     cp = tmp;
 1275     while ((next = strsep(&cp, ";")) != NULL) {
 1276         p[n] = strtoul(next, &endptr, 10);
 1277         if (*endptr != '\0')
 1278             p[n] = 0;
 1279         n++;
 1280     }
 1281 
 1282     /* Add terminal features. */
 1283     switch (p[0]) {
 1284     case 41: /* VT420 */
 1285         tty_add_features(&c->term_features, "margins,rectfill", ",");
 1286         break;
 1287     case 'M': /* mintty */
 1288         tty_default_features(&c->term_features, "mintty", 0);
 1289         break;
 1290     case 'T': /* tmux */
 1291         tty_default_features(&c->term_features, "tmux", 0);
 1292         break;
 1293     case 'U': /* rxvt-unicode */
 1294         tty_default_features(&c->term_features, "rxvt-unicode", 0);
 1295         break;
 1296     }
 1297     log_debug("%s: received secondary DA %.*s", c->name, (int)*size, buf);
 1298 
 1299     tty_update_features(tty);
 1300     tty->flags |= TTY_HAVEDA;
 1301 
 1302     return (0);
 1303 }
 1304 
 1305 /*
 1306  * Handle extended device attributes input. Returns 0 for success, -1 for
 1307  * failure, 1 for partial.
 1308  */
 1309 static int
 1310 tty_keys_extended_device_attributes(struct tty *tty, const char *buf,
 1311     size_t len, size_t *size)
 1312 {
 1313     struct client   *c = tty->client;
 1314     u_int        i;
 1315     char         tmp[128];
 1316 
 1317     *size = 0;
 1318     if (tty->flags & TTY_HAVEXDA)
 1319         return (-1);
 1320 
 1321     /* First four bytes are always \033P>|. */
 1322     if (buf[0] != '\033')
 1323         return (-1);
 1324     if (len == 1)
 1325         return (1);
 1326     if (buf[1] != 'P')
 1327         return (-1);
 1328     if (len == 2)
 1329         return (1);
 1330     if (buf[2] != '>')
 1331         return (-1);
 1332     if (len == 3)
 1333         return (1);
 1334     if (buf[3] != '|')
 1335         return (-1);
 1336     if (len == 4)
 1337         return (1);
 1338 
 1339     /* Copy the rest up to a '\033\\'. */
 1340     for (i = 0; i < (sizeof tmp) - 1; i++) {
 1341         if (4 + i == len)
 1342             return (1);
 1343         if (buf[4 + i - 1] == '\033' && buf[4 + i] == '\\')
 1344             break;
 1345         tmp[i] = buf[4 + i];
 1346     }
 1347     if (i == (sizeof tmp) - 1)
 1348         return (-1);
 1349     tmp[i - 1] = '\0';
 1350     *size = 5 + i;
 1351 
 1352     /* Add terminal features. */
 1353     if (strncmp(tmp, "iTerm2 ", 7) == 0)
 1354         tty_default_features(&c->term_features, "iTerm2", 0);
 1355     else if (strncmp(tmp, "tmux ", 5) == 0)
 1356         tty_default_features(&c->term_features, "tmux", 0);
 1357     else if (strncmp(tmp, "XTerm(", 6) == 0)
 1358         tty_default_features(&c->term_features, "XTerm", 0);
 1359     else if (strncmp(tmp, "mintty ", 7) == 0)
 1360         tty_default_features(&c->term_features, "mintty", 0);
 1361     log_debug("%s: received extended DA %.*s", c->name, (int)*size, buf);
 1362 
 1363     free(c->term_type);
 1364     c->term_type = xstrdup(tmp);
 1365 
 1366     tty_update_features(tty);
 1367     tty->flags |= TTY_HAVEXDA;
 1368 
 1369     return (0);
 1370 }