---
name: "termkey_waitkey"
section: "3"
platform: "linux"
package: "libtermkey-dev"
version: "0.22-2+b1"
release: "Debian 13 (Trixie)"
platforms: ["linux"]
url: "https://new.carta.tech/termkey_waitkey"
---

# termkey\_waitkey(3)

wait for and retrieve the next key event

## NAME

termkey\_waitkey - wait for and retrieve the next key event

## SYNOPSIS

```
#include <termkey.h>

TermKeyResult termkey_waitkey(TermKey *tk, TermKeyKey *key);
```

Link with *-ltermkey*.

## DESCRIPTION

**termkey\_waitkey**() attempts to retrieve a single keypress event from the [**termkey**(7)](/termkey/7.md) instance buffer, and put it in the structure referred to by *key*. If successful it will return **TERMKEY\_RES\_KEY** to indicate that the structure now contains a new keypress event. If nothing is in the buffer it will block until one is available. If no events are ready and the input stream is now closed, will return **TERMKEY\_RES\_EOF**. If no filehandle is associated with this instance, **TERMKEY\_RES\_ERROR** is returned with *errno* set to **EBADF**.

Before returning, this function canonicalises the *key* structure according to the rules given for [**termkey\_canonicalise**(3)](/termkey_canonicalise/3.md).

Some keypresses generate multiple bytes from the terminal. Because there may be network or other delays between the terminal and an application using **termkey**, **termkey\_waitkey**() will attempt to wait for the remaining bytes to arrive if it detects the start of a multibyte sequence. If no more bytes arrive within a certain time, then the bytes will be reported as they stand, even if this results in interpreting a partially-complete Escape sequence as a literal Escape key followed by some normal letters or other symbols. The amount of time to wait can be set by [**termkey\_set\_waittime**(3)](/termkey_set_waittime/3.md).

## RETURN VALUE

**termkey\_waitkey**() returns one of the following constants:

- **TERMKEY\_RES\_KEY**

  A key event as been provided.

- **TERMKEY\_RES\_EOF**

  No key events are ready and the terminal has been closed, so no more will arrive.

- **TERMKEY\_RES\_ERROR**

  An IO error occurred. *errno* will be preserved. If the error is **EINTR** then this will only be returned if **TERMKEY\_FLAG\_EINTR** flag is not set; if it is then the IO operation will be retried instead. If this is called with terminal IO stopped, due to **termkey\_stop**(3) then *errno* will be set to **EINVAL**.

## EXAMPLE

The following example program prints details of every keypress until the user presses *Ctrl-C*.

```
// we want optarg
#define _XOPEN_SOURCE 600
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include "termkey.h"
int main(int argc, char *argv[])
{
  TERMKEY_CHECK_VERSION;
  int mouse = 0;
  int mouse_proto = 0;
  TermKeyFormat format = TERMKEY_FORMAT_VIM;
  char buffer[50];
  TermKey *tk;
  int opt;
  while((opt = getopt(argc, argv, "m::p:")) != -1) {
    switch(opt) {
    case 'm':
      if(optarg)
        mouse = atoi(optarg);
      else
        mouse = 1000;
      break;
    case 'p':
      mouse_proto = atoi(optarg);
      break;
    default:
      fprintf(stderr, "Usage: %s [-m]\n", argv[0]);
      return 1;
    }
  }
  tk = termkey_new(0, TERMKEY_FLAG_SPACESYMBOL|TERMKEY_FLAG_CTRLC);
  if(!tk) {
    fprintf(stderr, "Cannot allocate termkey instance\n");
    exit(1);
  }
  if(termkey_get_flags(tk) & TERMKEY_FLAG_UTF8)
    printf("Termkey in UTF-8 mode\n");
  else if(termkey_get_flags(tk) & TERMKEY_FLAG_RAW)
    printf("Termkey in RAW mode\n");
  TermKeyResult ret;
  TermKeyKey key;
  if(mouse) {
    printf("\033[?%dhMouse mode active\n", mouse);
    if(mouse_proto)
      printf("\033[?%dh", mouse_proto);
  }
  while((ret = termkey_waitkey(tk, &key)) != TERMKEY_RES_EOF) {
    if(ret == TERMKEY_RES_KEY) {
      termkey_strfkey(tk, buffer, sizeof buffer, &key, format);
      if(key.type == TERMKEY_TYPE_MOUSE) {
        int line, col;
        termkey_interpret_mouse(tk, &key, NULL, NULL, &line, &col);
        printf("%s at line=%d, col=%d\n", buffer, line, col);
      }
      else if(key.type == TERMKEY_TYPE_POSITION) {
        int line, col;
        termkey_interpret_position(tk, &key, &line, &col);
        printf("Cursor position report at line=%d, col=%d\n", line, col);
      }
      else if(key.type == TERMKEY_TYPE_MODEREPORT) {
        int initial, mode, value;
        termkey_interpret_modereport(tk, &key, &initial, &mode, &value);
        printf("Mode report %s mode %d = %d\n", initial ? "DEC" : "ANSI", mode, value);
      }
      else if(key.type == TERMKEY_TYPE_UNKNOWN_CSI) {
        long args[16];
        size_t nargs = 16;
        unsigned long command;
        termkey_interpret_csi(tk, &key, args, &nargs, &command);
        printf("Unrecognised CSI %c %ld;%ld %c%c\n", (char)(command >> 8), args[0], args[1], (char)(command >> 16), (char)command);
      }
      else {
        printf("Key %s\n", buffer);
      }
      if(key.type == TERMKEY_TYPE_UNICODE &&
         key.modifiers & TERMKEY_KEYMOD_CTRL &&
         (key.code.codepoint == 'C' || key.code.codepoint == 'c'))
        break;
      if(key.type == TERMKEY_TYPE_UNICODE &&
         key.modifiers == 0 &&
         key.code.codepoint == '?') {
        // printf("\033[?6n"); // DECDSR 6 == request cursor position
        printf("\033[?1$p"); // DECRQM == request mode, DEC origin mode
        fflush(stdout);
      }
    }
    else if(ret == TERMKEY_RES_ERROR) {
      if(errno != EINTR) {
        perror("termkey_waitkey");
        break;
      }
      printf("Interrupted by signal\n");
    }
  }
  if(mouse)
    printf("\033[?%dlMouse mode deactivated\n", mouse);
  termkey_destroy(tk);
}
```

## COMPATIBILITY

This function is not available on Windows.

## SEE ALSO

[**termkey\_getkey**(3)](/termkey_getkey/3.md), [**termkey\_set\_waittime**(3)](/termkey_set_waittime/3.md), [**termkey**(7)](/termkey/7.md)
