+}
+
+static void handle_command(int c)
+{
+ int i;
+
+ /* first check user-defined key bindings */
+ for (i = 0; i < conf.key_map_given; ++i) {
+ char *tmp, *handler, *arg;
+
+ tmp = para_strdup(conf.key_map_arg[i]);
+ if (!split_key_map(tmp, &handler, &arg)) {
+ free(tmp);
+ return;
+ }
+ if (strcmp(tmp, km_keyname(c))) {
+ free(tmp);
+ continue;
+ }
+ if (*handler == 'd')
+ display_cmd(arg);
+ else if (*handler == 'x')
+ external_cmd(arg);
+ else if (*handler == 'p')
+ para_cmd(arg);
+ else if (*handler == 'i') {
+ int num = find_cmd_byname(arg);
+ if (num >= 0)
+ command_list[num].handler();
+ }
+ free(tmp);
+ return;
+ }
+ /* not found, check internal key bindings */
+ for (i = 0; command_list[i].handler; i++) {
+ if (!strcmp(km_keyname(c), command_list[i].key)) {
+ command_list[i].handler();
+ return;
+ }
+ }
+ print_in_bar(COLOR_ERRMSG, "key '%s' is not bound, press ? for help",
+ km_keyname(c));
+}
+
+static void input_post_select(void)
+{
+ int ret;
+ enum cmd_status cmds = cmd_status();
+
+ if (cmds == CMDS_XCMD)
+ return;
+ ret = wgetch(top.win);
+ if (ret == ERR || ret == KEY_RESIZE)
+ return;
+ if (cmds == CMDS_IDLE)
+ return handle_command(ret);
+ if (cmd_pid != 0)
+ kill(cmd_pid, SIGTERM);
+}
+
+static void signal_pre_select(fd_set *rfds, int *max_fileno)
+{
+ para_fd_set(signal_pipe, rfds, max_fileno);
+}
+
+/*
+ * This is the core select loop. It checks the following fds:
+ *
+ * - signal pipe
+ * - stdin
+ * - stdout/stderr of display or internal commands
+ */
+__noreturn static void do_select(void)
+{
+ fd_set rfds;
+ int ret, max_fileno;
+ struct timeval tv;
+
+repeat:
+ tv.tv_sec = conf.timeout_arg / 1000;
+ tv.tv_usec = (conf.timeout_arg % 1000) * 1000;
+ FD_ZERO(&rfds);
+ max_fileno = 0;
+ status_pre_select(&rfds, &max_fileno, &tv);
+ signal_pre_select(&rfds, &max_fileno);
+ command_pre_select(&rfds, &max_fileno);
+ input_pre_select(&rfds, &max_fileno);
+ ret = para_select(max_fileno + 1, &rfds, NULL, &tv);
+ if (ret <= 0)
+ goto repeat; /* skip fd checks */
+ signal_post_select(&rfds);
+ command_post_select(&rfds);
+ status_post_select(&rfds);
+ input_post_select();
+ goto repeat;