xdebug

next generation of mdebug (work in progress)
git clone http://frotz.net/git/xdebug.git
Log | Files | Refs | README

input.inl.c (5405B)


      1 // if s1 starts with s2 returns true, else false
      2 // len is the length of s1
      3 // s2 should be null-terminated
      4 static bool starts_with(const void *_s1, int len, const void *_s2)
      5 {
      6 	const uint8_t *s1 = _s1;
      7 	const uint8_t *s2 = _s2;
      8 	int n = 0;
      9 
     10 	while (*s2 && n < len) {
     11 		if (*s1++ != *s2++)
     12 			return false;
     13 		n++;
     14 	}
     15 	return *s2 == 0;
     16 }
     17 
     18 static int parse_mouse_event(struct tb_event *event, uint8_t *buf, int len) {
     19 	if (len >= 6 && starts_with(buf, len, "\033[M")) {
     20 		// X10 mouse encoding, the simplest one
     21 		// \033 [ M Cb Cx Cy
     22 		int b = buf[3] - 32;
     23 		switch (b & 3) {
     24 		case 0:
     25 			if ((b & 64) != 0)
     26 				event->key = TB_KEY_MOUSE_WHEEL_UP;
     27 			else
     28 				event->key = TB_KEY_MOUSE_LEFT;
     29 			break;
     30 		case 1:
     31 			if ((b & 64) != 0)
     32 				event->key = TB_KEY_MOUSE_WHEEL_DOWN;
     33 			else
     34 				event->key = TB_KEY_MOUSE_MIDDLE;
     35 			break;
     36 		case 2:
     37 			event->key = TB_KEY_MOUSE_RIGHT;
     38 			break;
     39 		case 3:
     40 			event->key = TB_KEY_MOUSE_RELEASE;
     41 			break;
     42 		default:
     43 			return -6;
     44 		}
     45 		event->type = TB_EVENT_MOUSE; // TB_EVENT_KEY by default
     46 		if ((b & 32) != 0)
     47 			event->mod |= TB_MOD_MOTION;
     48 
     49 		// the coord is 1,1 for upper left
     50 		event->x = (uint8_t)buf[4] - 1 - 32;
     51 		event->y = (uint8_t)buf[5] - 1 - 32;
     52 
     53 		return 6;
     54 	} else if (starts_with(buf, len, "\033[<") || starts_with(buf, len, "\033[")) {
     55 		// xterm 1006 extended mode or urxvt 1015 extended mode
     56 		// xterm: \033 [ < Cb ; Cx ; Cy (M or m)
     57 		// urxvt: \033 [ Cb ; Cx ; Cy M
     58 		int i, mi = -1, starti = -1;
     59 		int isM, isU, s1 = -1, s2 = -1;
     60 		int n1 = 0, n2 = 0, n3 = 0;
     61 
     62 		for (i = 0; i < len; i++) {
     63 			// We search the first (s1) and the last (s2) ';'
     64 			if (buf[i] == ';') {
     65 				if (s1 == -1)
     66 					s1 = i;
     67 				s2 = i;
     68 			}
     69 
     70 			// We search for the first 'm' or 'M'
     71 			if ((buf[i] == 'm' || buf[i] == 'M') && mi == -1) {
     72 				mi = i;
     73 				break;
     74 			}
     75 		}
     76 		if (mi == -1)
     77 			return 0;
     78 
     79 		// whether it's a capital M or not
     80 		isM = (buf[mi] == 'M');
     81 
     82 		if (buf[2] == '<') {
     83 			isU = 0;
     84 			starti = 3;
     85 		} else {
     86 			isU = 1;
     87 			starti = 2;
     88 		}
     89 
     90 		if (s1 == -1 || s2 == -1 || s1 == s2)
     91 			return 0;
     92 
     93 		n1 = strtoul((void*) &buf[starti], NULL, 10);
     94 		n2 = strtoul((void*) &buf[s1 + 1], NULL, 10);
     95 		n3 = strtoul((void*) &buf[s2 + 1], NULL, 10);
     96 		
     97 		if (isU)
     98 			n1 -= 32;
     99 
    100 		switch (n1 & 3) {
    101 		case 0:
    102 			if ((n1&64) != 0) {
    103 				event->key = TB_KEY_MOUSE_WHEEL_UP;
    104 			} else {
    105 				event->key = TB_KEY_MOUSE_LEFT;
    106 			}
    107 			break;
    108 		case 1:
    109 			if ((n1&64) != 0) {
    110 				event->key = TB_KEY_MOUSE_WHEEL_DOWN;
    111 			} else {
    112 				event->key = TB_KEY_MOUSE_MIDDLE;
    113 			}
    114 			break;
    115 		case 2:
    116 			event->key = TB_KEY_MOUSE_RIGHT;
    117 			break;
    118 		case 3:
    119 			event->key = TB_KEY_MOUSE_RELEASE;
    120 			break;
    121 		default:
    122 			return mi + 1;
    123 		}
    124 
    125 		if (!isM) {
    126 			// on xterm mouse release is signaled by lowercase m
    127 			event->key = TB_KEY_MOUSE_RELEASE;
    128 		}
    129 
    130 		event->type = TB_EVENT_MOUSE; // TB_EVENT_KEY by default
    131 		if ((n1&32) != 0)
    132 			event->mod |= TB_MOD_MOTION;
    133 
    134 		event->x = (uint8_t)n2 - 1;
    135 		event->y = (uint8_t)n3 - 1;
    136 
    137 		return mi + 1;
    138 	}
    139 
    140 	return 0;
    141 }
    142 
    143 // convert escape sequence to event, and return consumed bytes on success (failure == 0)
    144 static int parse_escape_seq(struct tb_event *event, uint8_t *buf, int len)
    145 {
    146 	int mouse_parsed = parse_mouse_event(event, buf, len);
    147 
    148 	if (mouse_parsed != 0)
    149 		return mouse_parsed;
    150 
    151 	// it's pretty simple here, find 'starts_with' match and return
    152 	// success, else return failure
    153 	int i;
    154 	for (i = 0; keys[i]; i++) {
    155 		if (starts_with(buf, len, keys[i])) {
    156 			event->ch = 0;
    157 			event->key = 0xFFFF-i;
    158 			return strlen(keys[i]);
    159 		}
    160 	}
    161 	return 0;
    162 }
    163 
    164 static bool extract_event(struct tb_event *event, struct bytebuffer *inbuf, int inputmode)
    165 {
    166 	uint8_t *buf = inbuf->buf;
    167 	const int len = inbuf->len;
    168 	if (len == 0)
    169 		return false;
    170 
    171 	if (buf[0] == '\033') {
    172 		int n = parse_escape_seq(event, buf, len);
    173 		if (n != 0) {
    174 			bool success = true;
    175 			if (n < 0) {
    176 				success = false;
    177 				n = -n;
    178 			}
    179 			bytebuffer_truncate(inbuf, n);
    180 			return success;
    181 		} else {
    182 			// it's not escape sequence, then it's ALT or ESC,
    183 			// check inputmode
    184 			if (inputmode&TB_INPUT_ESC) {
    185 				// if we're in escape mode, fill ESC event, pop
    186 				// buffer, return success
    187 				event->ch = 0;
    188 				event->key = TB_KEY_ESC;
    189 				event->mod = 0;
    190 				bytebuffer_truncate(inbuf, 1);
    191 				return true;
    192 			} else if (inputmode&TB_INPUT_ALT) {
    193 				// if we're in alt mode, set ALT modifier to
    194 				// event and redo parsing
    195 				event->mod = TB_MOD_ALT;
    196 				bytebuffer_truncate(inbuf, 1);
    197 				return extract_event(event, inbuf, inputmode);
    198 			}
    199 			assert(!"never got here");
    200 		}
    201 	}
    202 
    203 	// if we're here, this is not an escape sequence and not an alt sequence
    204 	// so, it's a FUNCTIONAL KEY or a UNICODE character
    205 
    206 	uint8_t buf0 = buf[0];
    207 
    208 	// first of all check if it's a functional key
    209 	if (buf0 <= TB_KEY_SPACE ||
    210 	    buf0 == TB_KEY_BACKSPACE2)
    211 	{
    212 		if (buf0 != TB_KEY_SPACE ||
    213 		    !(inputmode&TB_INPUT_SPACE)) {
    214 			// fill event, pop buffer, return success */
    215 			event->ch = 0;
    216 			event->key = buf0;
    217 			bytebuffer_truncate(inbuf, 1);
    218 			return true;
    219 		}
    220 	}
    221 
    222 	// feh... we got utf8 here
    223 
    224 	// check if there is all bytes
    225 	if (len >= tb_utf8_char_length(buf0)) {
    226 		/* everything ok, fill event, pop buffer, return success */
    227 		tb_utf8_char_to_unicode(&event->ch, buf);
    228 		event->key = 0;
    229 		bytebuffer_truncate(inbuf, tb_utf8_char_length(buf0));
    230 		return true;
    231 	}
    232 
    233 	// event isn't recognized, perhaps there is not enough bytes in utf8
    234 	// sequence
    235 	return false;
    236 }