void k_scroll(const keyarg_u *a, unsigned repeat, const int from_ch) { window *win = windows_cur(); if(a->pos.x){ /* y: 0=mid, -1=top, 1=bot */ int h = 0; switch(a->pos.y){ case 0: h = win->screen_coord.h / 2; break; case -1: break; case 1: h = win->screen_coord.h - 1; break; } win->ui_start.y = win->ui_pos->y - h; }else{ win->ui_start.y += a->pos.y; } if(win->ui_start.y < 0) win->ui_start.y = 0; if(win->ui_pos->y < win->ui_start.y) win->ui_pos->y = win->ui_start.y; else if(win->ui_pos->y >= win->ui_start.y + win->screen_coord.h) win->ui_pos->y = win->ui_start.y + win->screen_coord.h - 1; ui_redraw(); ui_cur_changed(); }
void k_redraw(const keyarg_u *a, unsigned repeat, const int from_ch) { (void)a; ui_clear(); ui_redraw(); ui_cur_changed(); }
void k_winmove(const keyarg_u *a, unsigned repeat, const int from_ch) { enum neighbour dir = pos2dir(&a->pos); int count = 0; window *w; ITER_WINDOWS(w){ count++; if(count == 2){ /* now have >1 */ break; } } if(count < 2) return; w = windows_cur(); window *target = window_next(w); window_evict(w); switch(dir){ case neighbour_up: for(; target->neighbours.above; target = target->neighbours.above); break; case neighbour_down: for(; target->neighbours.below; target = target->neighbours.below); break; case neighbour_right: for(; target->neighbours.above; target = target->neighbours.above); for(; target->neighbours.right; target = target->neighbours.right); break; case neighbour_left: for(; target->neighbours.above; target = target->neighbours.above); for(; target->neighbours.left; target = target->neighbours.left); break; } window_add_neighbour(target, dir, w); ui_redraw(); ui_cur_changed(); }
RETSIGTYPE signal_handler(int sig) { switch(sig){ case SIGINT: running = 0; break; case SIGALRM: //alarm(gs->delay); //pps_update_all(gs); /* fall through */ case SIGWINCH: case SIGCONT: ui_redraw(); break; } signal(sig, signal_handler); }
void k_winsel(const keyarg_u *a, unsigned repeat, const int from_ch) { enum neighbour dir = pos2dir(&a->pos); window *const curwin = windows_cur(); window *found = NULL; switch(dir){ case neighbour_up: found = curwin->neighbours.above; break; case neighbour_down: found = curwin->neighbours.below; break; case neighbour_left: case neighbour_right: for(found = curwin; found->neighbours.above; found = found->neighbours.above); found = (dir == neighbour_left ? found->neighbours.left : found->neighbours.right); if(!found) break; const int to_match = curwin->screen_coord.y + curwin->ui_pos->y - curwin->ui_start.y; while(found->neighbours.below) { if(found->screen_coord.y <= to_match && to_match <= found->screen_coord.y + found->screen_coord.h) { break; } found = found->neighbours.below; } } if(found && found != curwin){ windows_set_cur(found); ui_redraw(); ui_cur_changed(); }else{ ui_err("no buffers in that direction"); } }
int itop_run(void) { fd_set fds; struct timeval tmout; running = 1; ui_init(); ic = collect_new(); signal(SIGINT, signal_handler); while(running) { collect_update(ic); ui_redraw(); FD_ZERO(&fds); FD_SET(0, &fds); tmout.tv_sec = 1; tmout.tv_usec = 0; if(select(2, &fds, NULL, NULL, &tmout) < 0) { switch(errno) { case EINTR: continue; default: running = 0; break; } } if(FD_ISSET(0, &fds)) { ui_process_events(); continue; } } ui_finish(); collect_destroy(ic); return 0; }
void k_jumpscroll(const keyarg_u *a, unsigned repeat, const int from_ch) { window *w = windows_cur(); const int height = w->screen_coord.h + 1; int inc = 0; switch(abs(a->i)){ case 2: inc = height; break; case 1: inc = height / 2; break; } if(a->i < 0) inc = -inc; w->ui_pos->y += inc; w->ui_start.y += inc; start_of_line(NULL, w); ui_cur_changed(); ui_redraw(); }
static char * ui_get_input(ui_t *ui, list_t *choices, const char *prompt, char *input) { int key = 0, selection = 0, visible_choices_count = 0, update, word_position; size_t cursor_position, query_length, query_size = 64; choices_t *c; char *query; c = choices_new(choices); if (!c) { return NULL; } query = calloc(query_size, sizeof(size_t)); if (!query) { return NULL; } if (input) { strncpy(query, input, query_size); } cursor_position = query_length = strlen(query); choices_filter(c, query); toggle_terminal(false); for (;;) { update = ui_update(ui); if (update == -1) { break; } if (update || key != ERR) { ui_redraw(ui); visible_choices_count = choices_print(c, query, selection); mvprintw(0, 0, "%s%s", prompt ? prompt : "", query); clrtoeol(); refresh(); } if (signal_flag) { signal_flag = false; toggle_terminal(true); free(query); return NULL; } key = mvgetch(0, cursor_position + strlen(prompt)); switch(key) { case ESCAPE: toggle_terminal(true); free(query); return NULL; case ENTER: toggle_terminal(true); if (visible_choices_count > 0) { if (selection >= 0 && selection < choices_get_size(c)) { free(query); return strdup(choices_get_string(c, selection)); } } return query; case BACKSPACE: case DEL: if (cursor_position > 0) { delete_between(query, query_length, cursor_position - 1, cursor_position); --cursor_position; --query_length; choices_filter(c, query); selection = 0; } break; case CTRL('D'): if (cursor_position < query_length) { delete_between(query, query_length, cursor_position, cursor_position + 1); --query_length; choices_filter(c, query); selection = 0; } break; case CTRL('U'): delete_between(query, query_length, 0, cursor_position); query_length -= cursor_position; cursor_position = 0; choices_filter(c, query); selection = 0; break; case CTRL('K'): delete_between(query, query_length, cursor_position, query_length); query_length = cursor_position; choices_filter(c, query); selection = 0; break; case CTRL('W'): if (cursor_position > 0) { for (word_position = cursor_position - 1; word_position > 0; --word_position) { if (query[word_position] != ' ' && query[word_position - 1] == ' ') break; } delete_between(query, query_length, word_position, cursor_position); query_length -= cursor_position - word_position; cursor_position = word_position; choices_filter(c, query); selection = 0; } break; case CTRL('A'): cursor_position = 0; break; case CTRL('E'): cursor_position = query_length; break; case CTRL('N'): case DOWN: if (selection < visible_choices_count - 1) ++selection; break; case CTRL('P'): case UP: if (selection > 0) --selection; break; case CTRL('B'): case LEFT: if (cursor_position > 0) --cursor_position; break; case CTRL('F'): case RIGHT: if (cursor_position < query_length) ++cursor_position; break; default: if (key > 31 && key < 127) { /* Printable chars */ if (cursor_position < query_length) { memmove( query + cursor_position + 1, query + cursor_position, query_length - cursor_position); } query[cursor_position++] = key; query[++query_length] = '\0'; choices_filter(c, query); selection = 0; } break; } if (query_length == query_size - 1) { query_size += query_size; query = realloc(query, query_size * sizeof(*query)); if (!query) toggle_terminal(true); return NULL; } } return NULL; }
void ui_loop(ui_t *ui) { int i, key = 0, prev_key = 0, update = 1, note; char *input; help_flag_t help = HELP_FALSE; double real; clock_t tap[3] = { 0.0, 0.0, 0.0 }; display_t *d; if (ui->filename) { ui_load_state(ui, ui->filename); } d = ui->display; clear(); while (true) { update = ui_update(ui); if (update == -1) { break; } if (signal_flag && d->keyboard) { d->keyboard = false; signal_flag = false; ui_redraw(ui); } if (update || key != ERR) { if (key != ERR) { if (prev_key == key && key == KEY_HELP_TOGGLE) { help = HELP_FALSE; key = 0; } prev_key = key; if (!isdigit(prev_key) && prev_key != 'g') { count = 0; } } (help != HELP_FALSE) ? helpscr(help) : ui_redraw(ui); } key = getch(); if (help != HELP_FALSE && key != ERR) { help = HELP_FALSE; count = 0; clear(); } switch (key) { case KEY_KEYBORD_OFF: if (d->keyboard) { d->keyboard = false; } continue; case KEY_TRANSPORT_TOGGLE: ui_send_transport(ui); continue; case KEY_BPM_SET: if (count) { ui_send_bpm(ui, count); } else { tap[2] = times(NULL); real = (((tap[2] - tap[1]) + (tap[1] - tap[0])) / 2); real /= (double) sysconf(_SC_CLK_TCK); /* 30 to 200 bpm */ if (real >= 0.3 && real <= 2.0) { ui_send_bpm(ui, (int)(60.0 / real)); } tap[0] = tap[1]; tap[1] = tap[2]; } continue; case KEY_HELP_TOGGLE: help = HELP_KEYS; continue; case KEY_PITCH_DOWN: if (ui->oct > 0) { ui->oct--; } continue; case KEY_PITCH_UP: if (ui->oct < 9) { ui->oct++; } continue; case KEY_ACCOMPANY_TOGGLE: ui_send_acc(ui); continue; case KEY_NOSAVE_QUIT: if (prev_key == 'Z') { ui_send_quit(ui); } continue; case KEY_SAVE_QUIT: if (prev_key == 'Z') { if (ui_save_state(ui, NULL)) { ui_send_quit(ui); } key = 0; } continue; case KEY_RECORD_TOGGLE: ui_send_rec(ui); continue; case KEY_DISPLAY_TOGGLE: d->note = !d->note; continue; default: break; } if (d->keyboard) { note = key_to_midi(key, ui->oct); if (note >= 0) { ui_send_play(ui, note); } continue; } switch(key) { case '0': if (!count) { d->x = 0; } else { count *= 10; } break; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': count = (count == 0) ? key - 48 : count * 10 + (key - 48); break; case KEY_PLAY_TOGGLE: ui_send_play(ui, d->y); break; case KEY_NOTE_TOGGLE: /* TODO: save length of previous notes */ ui_send_toggle(ui, d->y, count ? count : d->x, MAX_LEN); break; case KEY_NOTE_DELETE: if (prev_key == 'd') { ui->yank.key = d->y; ui->yank.step = d->x; ui->yank.pattern = ui->pattern; ui_send_delete(ui, d->y, ui->pattern); } break; case KEY_NOTE_REMOVE: ui_send_remove(ui, d->y, d->x, ui->pattern); break; case KEY_NOTE_CLEAR: if (prev_key == 'D') { ui_send_clear(ui, ui->pattern); } break; case KEY_GOTO_TOP: if (prev_key == 'g') { if (count <= MIDI_MAX) { d->y = count; count = 0; } } break; case KEY_GOTO_BOTTOM: if (!count) { d->y = MIDI_MAX; } else if (count <= MIDI_MAX) { d->y = count; } break; case KEY_LENGTH_UP: ui_send_length(ui, d->y, d->x, 1); break; case KEY_LENGTH_DOWN: ui_send_length(ui, d->y, d->x, -1); break; case KEY_KEYBORD_ON: d->keyboard = true; break; case KEY_DOWN: case KEY_VIM_DOWN: for (i = 0; i < count || i == 0; i++) { d->y = (d->y == MIDI_MAX) ? 0 : d->y + 1; } break; /* case KEY_VIM_DOWN_RIGHT: */ /* d->y = (d->y == MIDI_MAX - 1) ? 0 : d->y + 1; */ /* d->x = (d->x == 0) ? ui->steps - 1 : d->x - 1; */ /* break; */ case KEY_LEFT: case KEY_VIM_LEFT: for (i = 0; i < count || i == 0; i++) { d->x = (d->x == 0) ? ui->steps - 1 : d->x - 1; } break; case KEY_UP: case KEY_VIM_UP: for (i = 0; i < count || i == 0; i++) { d->y = (d->y == 0) ? MIDI_MAX : d->y - 1; } break; case KEY_RIGHT: case KEY_VIM_RIGHT: if (count) { d->x = (d->x + count) % ui->steps; } else { d->x = (d->x + 1) % ui->steps; } break; /* case KEY_VIM_DOWN_LEFT: */ /* d->y = (d->y == MIDI_MAX - 1) ? 0 : d->y + 1; */ /* d->x = (d->x == ui->steps - 1) ? 0 : d->x + 1; */ /* break; */ /* case KEY_VIM_UP_RIGHT: */ /* d->y = (d->y == 0) ? MIDI_MAX : d->y - 1; */ /* d->x = (d->x == ui->steps - 1) ? 0 : d->x + 1; */ break; case KEY_SCREEN_REDRAW: clear(); break; case KEY_MUTE_TOGGLE: ui_send_mute(ui, d->y); break; /* TODO: Mute all */ /* case 'M': */ /* ui_send_mute_all(ui); */ /* break; */ case KEY_STATE_LOAD: ui_load_state(ui, NULL); break; case KEY_STATE_SAVE: ui_save_state(ui, NULL); break; case KEY_PASTE: if (prev_key == 'p') { ui_send_kcopy(ui, ui->yank.pattern, ui->pattern, ui->yank.key, d->y); } /* ui_send_pcopy(ui, ui->pattern, count); */ break; /* case KEY_QUIT: */ /* ui_send_quit(ui); */ /* break; */ case KEY_SWING_DOWN: ui_send_swing(ui, ui->swing - 1); break; case KEY_SWING_UP: ui_send_swing(ui, ui->swing + 1); break; case KEY_BPM_DOWN: if (prev_key == 'g') { if (!count) { ui_change_pattern(ui, ui->pattern + 1); } else if (count <= 8) { ui_change_pattern(ui, count - 1); count = 0; } } else { ui_send_bpm(ui, count ? ui->bpm - count : ui->bpm - 1); } break; case KEY_BPM_UP: if (prev_key == 'g') { if (count) { ui_change_pattern(ui, count - 1); count = 0; } else if (count <= 8) { ui_change_pattern(ui, ui->pattern - 1); } } else { ui_send_bpm(ui, count ? ui->bpm + count : ui->bpm + 1); } break; case KEY_VELOCITY_SET: if (count) { ui_send_velocity(ui, d->y, d->x, count); } break; case KEY_YANK: if (prev_key == 'y') { ui->yank.key = d->y; ui->yank.step = d->x; ui->yank.pattern = ui->pattern; } break; case KEY_CMDLINE: input = ui_get_input(ui, NULL, ":", NULL); help = ui_command_execute(ui, input); ui->history = list_append(ui->history, input); break; case KEY_TRACKER: d->tracker = !d->tracker; break; default: break; } } }