int termkey_keycmp(TermKey *tk, const TermKeyKey *key1p, const TermKeyKey *key2p) { /* Copy the key structs since we'll be modifying them */ TermKeyKey key1 = *key1p, key2 = *key2p; termkey_canonicalise(tk, &key1); termkey_canonicalise(tk, &key2); if(key1.type != key2.type) return key1.type - key2.type; switch(key1.type) { case TERMKEY_TYPE_UNICODE: if(key1.code.codepoint != key2.code.codepoint) return key1.code.codepoint - key2.code.codepoint; break; case TERMKEY_TYPE_KEYSYM: if(key1.code.sym != key2.code.sym) return key1.code.sym - key2.code.sym; break; case TERMKEY_TYPE_FUNCTION: case TERMKEY_TYPE_UNKNOWN_CSI: if(key1.code.number != key2.code.number) return key1.code.number - key2.code.number; break; case TERMKEY_TYPE_MOUSE: { int cmp = strncmp(key1.code.mouse, key2.code.mouse, 4); if(cmp != 0) return cmp; } break; case TERMKEY_TYPE_POSITION: { int line1, col1, line2, col2; termkey_interpret_position(tk, &key1, &line1, &col1); termkey_interpret_position(tk, &key2, &line2, &col2); if(line1 != line2) return line1 - line2; return col1 - col2; } break; case TERMKEY_TYPE_DCS: case TERMKEY_TYPE_OSC: return key1p - key2p; case TERMKEY_TYPE_MODEREPORT: { int initial1, initial2, mode1, mode2, value1, value2; termkey_interpret_modereport(tk, &key1, &initial1, &mode1, &value1); termkey_interpret_modereport(tk, &key2, &initial2, &mode2, &value2); if(initial1 != initial2) return initial1 - initial2; if(mode1 != mode2) return mode1 - mode2; return value1 - value2; } } return key1.modifiers - key2.modifiers; }
static void print_key(TermKey *tk, TermKeyKey *key) { switch(key->type) { case TERMKEY_TYPE_UNICODE: fprintf(stderr, "Unicode codepoint=U+%04lx utf8='%s'", key->code.codepoint, key->utf8); break; case TERMKEY_TYPE_FUNCTION: fprintf(stderr, "Function F%d", key->code.number); break; case TERMKEY_TYPE_KEYSYM: fprintf(stderr, "Keysym sym=%d(%s)", key->code.sym, termkey_get_keyname(tk, key->code.sym)); break; case TERMKEY_TYPE_MOUSE: { TermKeyMouseEvent ev; int button, line, col; termkey_interpret_mouse(tk, key, &ev, &button, &line, &col); fprintf(stderr, "Mouse ev=%d button=%d pos=(%d,%d)\n", ev, button, line, col); } break; case TERMKEY_TYPE_POSITION: { int line, col; termkey_interpret_position(tk, key, &line, &col); fprintf(stderr, "Position report pos=(%d,%d)\n", line, col); } break; case TERMKEY_TYPE_MODEREPORT: { int initial, mode, value; termkey_interpret_modereport(tk, key, &initial, &mode, &value); fprintf(stderr, "Mode report mode=%s %d val=%d\n", initial == '?' ? "DEC" : "ANSI", mode, value); } break; case TERMKEY_TYPE_DCS: fprintf(stderr, "Device Control String"); break; case TERMKEY_TYPE_OSC: fprintf(stderr, "Operating System Control"); break; case TERMKEY_TYPE_UNKNOWN_CSI: fprintf(stderr, "unknown CSI\n"); break; } int m = key->modifiers; fprintf(stderr, " mod=%s%s%s+%02x", (m & TERMKEY_KEYMOD_CTRL ? "C" : ""), (m & TERMKEY_KEYMOD_ALT ? "A" : ""), (m & TERMKEY_KEYMOD_SHIFT ? "S" : ""), m & ~(TERMKEY_KEYMOD_CTRL|TERMKEY_KEYMOD_ALT|TERMKEY_KEYMOD_SHIFT)); }
size_t termkey_strfkey(TermKey *tk, char *buffer, size_t len, TermKeyKey *key, TermKeyFormat format) { size_t pos = 0; size_t l = 0; struct modnames *mods = &modnames[!!(format & TERMKEY_FORMAT_LONGMOD) + !!(format & TERMKEY_FORMAT_ALTISMETA) * 2 + !!(format & TERMKEY_FORMAT_LOWERMOD) * 4]; int wrapbracket = (format & TERMKEY_FORMAT_WRAPBRACKET) && (key->type != TERMKEY_TYPE_UNICODE || key->modifiers != 0); char sep = (format & TERMKEY_FORMAT_SPACEMOD) ? ' ' : '-'; if(format & TERMKEY_FORMAT_CARETCTRL && key->type == TERMKEY_TYPE_UNICODE && key->modifiers == TERMKEY_KEYMOD_CTRL) { long codepoint = key->code.codepoint; // Handle some of the special casesfirst if(codepoint >= 'a' && codepoint <= 'z') { l = snprintf(buffer + pos, len - pos, wrapbracket ? "<^%c>" : "^%c", (char)codepoint - 0x20); if(l <= 0) return pos; pos += l; return pos; } else if((codepoint >= '@' && codepoint < 'A') || (codepoint > 'Z' && codepoint <= '_')) { l = snprintf(buffer + pos, len - pos, wrapbracket ? "<^%c>" : "^%c", (char)codepoint); if(l <= 0) return pos; pos += l; return pos; } } if(wrapbracket) { l = snprintf(buffer + pos, len - pos, "<"); if(l <= 0) return pos; pos += l; } if(key->modifiers & TERMKEY_KEYMOD_ALT) { l = snprintf(buffer + pos, len - pos, "%s%c", mods->alt, sep); if(l <= 0) return pos; pos += l; } if(key->modifiers & TERMKEY_KEYMOD_CTRL) { l = snprintf(buffer + pos, len - pos, "%s%c", mods->ctrl, sep); if(l <= 0) return pos; pos += l; } if(key->modifiers & TERMKEY_KEYMOD_SHIFT) { l = snprintf(buffer + pos, len - pos, "%s%c", mods->shift, sep); if(l <= 0) return pos; pos += l; } switch(key->type) { case TERMKEY_TYPE_UNICODE: if(!key->utf8[0]) // In case of user-supplied key structures fill_utf8(key); l = snprintf(buffer + pos, len - pos, "%s", key->utf8); break; case TERMKEY_TYPE_KEYSYM: { const char *name = termkey_get_keyname(tk, key->code.sym); if(format & TERMKEY_FORMAT_LOWERSPACE) l = snprint_cameltospaces(buffer + pos, len - pos, name); else l = snprintf(buffer + pos, len - pos, "%s", name); } break; case TERMKEY_TYPE_FUNCTION: l = snprintf(buffer + pos, len - pos, "%c%d", (format & TERMKEY_FORMAT_LOWERSPACE ? 'f' : 'F'), key->code.number); break; case TERMKEY_TYPE_MOUSE: { TermKeyMouseEvent ev; int button; int line, col; termkey_interpret_mouse(tk, key, &ev, &button, &line, &col); static const char *evnames[] = { "Unknown", "Press", "Drag", "Release" }; l = snprintf(buffer + pos, len - pos, "Mouse%s(%d)", evnames[ev], button); if(format & TERMKEY_FORMAT_MOUSE_POS) { if(l <= 0) return pos; pos += l; l = snprintf(buffer + pos, len - pos, " @ (%u,%u)", col, line); } } break; case TERMKEY_TYPE_POSITION: l = snprintf(buffer + pos, len - pos, "Position"); break; case TERMKEY_TYPE_MODEREPORT: { int initial, mode, value; termkey_interpret_modereport(tk, key, &initial, &mode, &value); if(initial) l = snprintf(buffer + pos, len - pos, "Mode(%c%d=%d)", initial, mode, value); else l = snprintf(buffer + pos, len - pos, "Mode(%d=%d)", mode, value); } case TERMKEY_TYPE_UNKNOWN_CSI: l = snprintf(buffer + pos, len - pos, "CSI %c", key->code.number & 0xff); break; } if(l <= 0) return pos; pos += l; if(wrapbracket) { l = snprintf(buffer + pos, len - pos, ">"); if(l <= 0) return pos; pos += l; } return pos; }