int key_pressed(KEYBOARD_REC *keyboard, const char *key) { KEY_REC *rec; char *combo; int first_key, consumed; g_return_val_if_fail(keyboard != NULL, FALSE); g_return_val_if_fail(key != NULL && *key != '\0', FALSE); if (keyboard->timer_tag > 0) { g_source_remove(keyboard->timer_tag); keyboard->timer_tag = 0; } if (keyboard->key_state == NULL && key[1] == '\0' && !used_keys[(int) (unsigned char) key[0]]) { /* fast check - key not used */ return -1; } first_key = keyboard->key_state == NULL; combo = keyboard->key_state == NULL ? g_strdup(key) : g_strconcat(keyboard->key_state, "-", key, NULL); g_free_and_null(keyboard->key_state); rec = g_tree_search(key_states, (GCompareFunc) key_states_search, combo); if (rec == NULL) { /* unknown key combo, eat the invalid key unless it was the first key pressed */ g_free(combo); return first_key ? -1 : 1; } if (g_tree_lookup(key_states, combo) != rec) { /* key combo continues.. */ keyboard->key_state = combo; /* respect the timeout if specified by the user */ if (key_timeout > 0) { keyboard->timer_tag = g_timeout_add(key_timeout, (GSourceFunc) key_timeout_expired, keyboard); } return 0; } /* finished key combo, execute */ g_free(combo); consumed = key_emit_signal(keyboard, rec); /* never consume non-control characters */ return consumed ? 1 : -1; }
/* Returns TRUE if key press was consumed. Control characters should be sent as "^@" .. "^_" instead of #0..#31 chars, #127 should be sent as ^? */ int key_pressed(KEYBOARD_REC *keyboard, const char *key) { KEY_REC *rec; char *combo; int first_key, consumed; g_return_val_if_fail(keyboard != NULL, FALSE); g_return_val_if_fail(key != NULL && *key != '\0', FALSE); if (keyboard->key_state == NULL && key[1] == '\0' && !used_keys[(int) (unsigned char) key[0]]) { /* fast check - key not used */ return FALSE; } first_key = keyboard->key_state == NULL; combo = keyboard->key_state == NULL ? g_strdup(key) : g_strconcat(keyboard->key_state, "-", key, NULL); g_free_and_null(keyboard->key_state); #if GLIB_MAJOR_VERSION == 2 # define GSearchFunc GCompareFunc #endif rec = g_tree_search(key_states, (GSearchFunc) key_states_search, combo); if (rec == NULL) { /* unknown key combo, eat the invalid key unless it was the first key pressed */ g_free(combo); return !first_key; } if (g_tree_lookup(key_states, combo) != rec) { /* key combo continues.. */ keyboard->key_state = combo; return TRUE; } /* finished key combo, execute */ g_free(combo); consumed = key_emit_signal(keyboard, rec); /* never consume non-control characters */ return consumed; }
static gboolean key_timeout_expired(KEYBOARD_REC *keyboard) { KEY_REC *rec; keyboard->timer_tag = 0; /* So, the timeout has expired with the input queue full, let's see if * what we've got is bound to some action. */ rec = g_tree_lookup(key_states, keyboard->key_state); /* Drain the queue anyway. */ g_free_and_null(keyboard->key_state); if (rec != NULL) { (void)key_emit_signal(keyboard, rec); } return FALSE; }