+static void update_sizes(void)
+{
+ int hdr = COMPACT ? 1 : 2;
+ for (int i = 0; i < N_ELEMENTS(views); i++) {
+ wresize(views[i]->win, LINES-hdr, COLS);
+ mvwin(views[i]->win, hdr, 0);
+ views[i]->size(LINES-hdr, COLS);
+ }
+}
+
+static void draw_view(void)
+{
+ draw_header();
+ werase(view->win);
+ view->draw();
+ wrefresh(view->win);
+}
+
+static int set_view(view_t *_active, view_t *_popup)
+{
+ view = _popup ?: _active;
+ if (active != _active) {
+ active = _active;
+ set_string("view", 0, "active", active->name);
+ draw_view();
+ }
+ if (popup != _popup) {
+ popup = _popup;
+ draw_view();
+ }
+ return 1;
+}
+
+static int process(int key, mmask_t btn, int row, int col)
+{
+ /* Refresh timestamp */
+ draw_header();
+
+ /* Check for mouse events on the menu */
+ if (key == KEY_MOUSE && row == 0) {
+ int start = 1;
+ for (int i = 0; i < N_ELEMENTS(menu); i++) {
+ int end = start + strlen(menu[i]->name) - 1;
+ if (start <= col && col <= end && menu[i]->draw)
+ return set_view(menu[i], NULL);
+ start = end + 2;
+ }
+ }
+
+ /* Look though menu for hotkeys */
+ for (int i = 0; i < N_ELEMENTS(menu); i++) {
+ for (int j = 0; j < N_ELEMENTS(menu[i]->keys); j++)
+ if (menu[i]->keys[j] == key)
+ return set_view(menu[i], NULL);
+ }
+
+ /* Shift windows with left/right keys */
+ int shift = key == KEY_RIGHT ? +1 :
+ key == KEY_LEFT ? -1 : 0;
+ if (shift) {
+ int num = 0;
+ for (int i = 0; i < N_ELEMENTS(menu); i++)
+ if (menu[i] == active)
+ num = i;
+ do {
+ num += shift;
+ num += N_ELEMENTS(menu);
+ num %= N_ELEMENTS(menu);
+ } while (menu[num] == &spacer);
+ return set_view(menu[num], NULL);
+ }
+
+ /* Handle other keys */
+ switch (key) {
+ case KEY_RESIZE:
+ endwin();
+ refresh();
+ update_sizes();
+ draw_view();
+ return 1;
+ case '\14': // Ctrl-L
+ clear();
+ case '\7': // Ctrl-G
+ update_sizes();
+ draw_view();
+ return 1;
+ case '\033': // escape
+ return set_view(active, NULL);
+ case '?': // help
+ return set_view(active, &help_view);
+ }
+
+ /* Pass key to active view */
+ return view->run(key, btn, row, col);
+}
+
+/* Curses functions */
+void wmvresize(WINDOW *win, int top, int left, int rows, int cols)
+{
+ int y = getpary(win);
+ if (top < y)
+ mvderwin(win, top, left);
+ wresize(win, rows, cols);
+ if (top > y)
+ mvderwin(win, top, left);
+}
+
+void wshrink(WINDOW *win, int top)
+{
+ int x = getparx(win);
+ int y = getpary(win);
+ int r = getmaxy(win);
+ int c = getmaxx(win);
+ int rows = r + (y - top);
+ if (top < y) mvderwin(win, top, x);
+ if (rows != r) wresize(win, rows, c);
+ if (top > y) mvderwin(win, top, x);
+}
+