Beispiel #1
0
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;
}
Beispiel #2
0
static void emit_codepoint(TermKey *tk, long codepoint, TermKeyKey *key)
{
  if(codepoint == 0) {
    // ASCII NUL = Ctrl-Space
    key->type = TERMKEY_TYPE_KEYSYM;
    key->code.sym = TERMKEY_SYM_SPACE;
    key->modifiers = TERMKEY_KEYMOD_CTRL;
  }
  else if(codepoint < 0x20) {
    // C0 range
    key->code.codepoint = 0;
    key->modifiers = 0;

    if(!(tk->flags & TERMKEY_FLAG_NOINTERPRET) && tk->c0[codepoint].sym != TERMKEY_SYM_UNKNOWN) {
      key->code.sym = tk->c0[codepoint].sym;
      key->modifiers |= tk->c0[codepoint].modifier_set;
    }

    if(!key->code.sym) {
      key->type = TERMKEY_TYPE_UNICODE;
      /* Generically modified Unicode ought not report the SHIFT state, or else
       * we get into complicationg trying to report Shift-; vs : and so on...
       * In order to be able to represent Ctrl-Shift-A as CTRL modified
       * unicode A, we need to call Ctrl-A simply 'a', lowercase
       */
      if(codepoint+0x40 >= 'A' && codepoint+0x40 <= 'Z')
        // it's a letter - use lowecase instead
        key->code.codepoint = codepoint + 0x60;
      else
        key->code.codepoint = codepoint + 0x40;
      key->modifiers = TERMKEY_KEYMOD_CTRL;
    }
    else {
      key->type = TERMKEY_TYPE_KEYSYM;
    }
  }
  else if(codepoint == 0x7f && !(tk->flags & TERMKEY_FLAG_NOINTERPRET)) {
    // ASCII DEL
    key->type = TERMKEY_TYPE_KEYSYM;
    key->code.sym = TERMKEY_SYM_DEL;
    key->modifiers = 0;
  }
  else if(codepoint >= 0x20 && codepoint < 0x80) {
    // ASCII lowbyte range
    key->type = TERMKEY_TYPE_UNICODE;
    key->code.codepoint = codepoint;
    key->modifiers = 0;
  }
  else if(codepoint >= 0x80 && codepoint < 0xa0) {
    // UTF-8 never starts with a C1 byte. So we can be sure of these
    key->type = TERMKEY_TYPE_UNICODE;
    key->code.codepoint = codepoint - 0x40;
    key->modifiers = TERMKEY_KEYMOD_CTRL|TERMKEY_KEYMOD_ALT;
  }
  else {
    // UTF-8 codepoint
    key->type = TERMKEY_TYPE_UNICODE;
    key->code.codepoint = codepoint;
    key->modifiers = 0;
  }

  termkey_canonicalise(tk, key);

  if(key->type == TERMKEY_TYPE_UNICODE)
    fill_utf8(key);
}
Beispiel #3
0
const char *termkey_strpkey(TermKey *tk, const char *str, TermKeyKey *key, TermKeyFormat format)
{
  struct modnames *mods = &modnames[!!(format & TERMKEY_FORMAT_LONGMOD) +
                                    !!(format & TERMKEY_FORMAT_ALTISMETA) * 2 +
                                    !!(format & TERMKEY_FORMAT_LOWERMOD) * 4];

  key->modifiers = 0;

  if((format & TERMKEY_FORMAT_CARETCTRL) && str[0] == '^' && str[1]) {
    str = termkey_strpkey(tk, str+1, key, format & ~TERMKEY_FORMAT_CARETCTRL);

    if(!str ||
       key->type != TERMKEY_TYPE_UNICODE ||
       key->code.codepoint < '@' || key->code.codepoint > '_' ||
       key->modifiers != 0)
      return NULL;

    if(key->code.codepoint >= 'A' && key->code.codepoint <= 'Z')
      key->code.codepoint += 0x20;
    key->modifiers = TERMKEY_KEYMOD_CTRL;
    fill_utf8(key);
    return (char *)str;
  }

  const char *sep_at;

  while((sep_at = strchr(str, (format & TERMKEY_FORMAT_SPACEMOD) ? ' ' : '-'))) {
    size_t n = sep_at - str;

    if(n == strlen(mods->alt) && strncmp(mods->alt, str, n) == 0)
      key->modifiers |= TERMKEY_KEYMOD_ALT;
    else if(n == strlen(mods->ctrl) && strncmp(mods->ctrl, str, n) == 0)
      key->modifiers |= TERMKEY_KEYMOD_CTRL;
    else if(n == strlen(mods->shift) && strncmp(mods->shift, str, n) == 0)
      key->modifiers |= TERMKEY_KEYMOD_SHIFT;

    else
      break;

    str = sep_at + 1;
  }

  size_t nbytes;
  ssize_t snbytes;
  const char *endstr;

  if((endstr = termkey_lookup_keyname_format(tk, str, &key->code.sym, format))) {
    key->type = TERMKEY_TYPE_KEYSYM;
    str = endstr;
  }
  else if(sscanf(str, "F%d%zn", &key->code.number, &snbytes) == 1) {
    key->type = TERMKEY_TYPE_FUNCTION;
    str += snbytes;
  }
  // Unicode must be last
  else if(parse_utf8((unsigned const char *)str, strlen(str), &key->code.codepoint, &nbytes) == TERMKEY_RES_KEY) {
    key->type = TERMKEY_TYPE_UNICODE;
    fill_utf8(key);
    str += nbytes;
  }
  // TODO: Consider mouse events?
  else
    return NULL;

  termkey_canonicalise(tk, key);

  return (char *)str;
}