+ mvwaddstr(wgetparent(win->curses), win->starty - 1, win->startx + title_offset, title); } }
+
+static void draw_windows_borders (struct Win * win, struct Win * win_active, struct Corners * corners, uint16_t ccount) {
+// Craw draw_window_borders() for all windows in chain from win on. Save current window's border corners.
+ char active = 0;
+ if (win == win_active)
+ active = 1;
+ draw_window_borders(win, active);
+ corners[ccount].tl.y = win->starty - 1;
+ corners[ccount].tl.x = win->startx - 1;
+ corners[ccount].tr.y = win->starty - 1;
+ corners[ccount].tr.x = win->startx + win->width;
+ corners[ccount].bl.y = win->starty + win->height;
+ corners[ccount].bl.x = win->startx - 1;
+ corners[ccount].br.y = win->starty + win->height;
+ corners[ccount].br.x = win->startx + win->width;
+ if (0 != win->next) {
+ draw_windows_borders (win->next, win_active, corners, ccount + 1); } }
+
+static void draw_windows (struct Win * win) {
+// Draw contents of all windows in window chain from win on.
+ win->draw(win);
+ if (0 != win->next) {
+ draw_windows (win->next); } }
+
+static void draw_vertical_scroll_hint (struct WinMeta * win_meta, uint16_t x, uint32_t more_cols, char dir) {
+// Draw scroll hint line in win at col x of pad display, announce more_cols more columns in direction dir.
+ uint16_t y, offset;
+ char phrase[] = "more columns";
+ char * scrolldesc = malloc((3 * sizeof(char)) + strlen(phrase) + 10); // 10 = max chars for uint32_t string
+ sprintf(scrolldesc, " %d %s ", more_cols, phrase);
+ offset = 1;
+ if (win_meta->height > (strlen(scrolldesc) + 1))
+ offset = (win_meta->height - strlen(scrolldesc)) / 2;
+ for (y = 0; y < win_meta->height; y++)
+ if (y >= offset && y < strlen(scrolldesc) + offset)
+ mvwaddch(win_meta->pad, y, x, scrolldesc[y - offset] | A_REVERSE);
+ else
+ mvwaddch(win_meta->pad, y, x, dir | A_REVERSE);
+ free(scrolldesc); }
+
+extern void draw_all_windows (struct WinMeta * win_meta) {
+// Draw pad with all windows and their borders, plus scrolling hints.
+ erase();
+ wnoutrefresh(win_meta->screen);
+ werase(win_meta->pad);
+ if (win_meta->chain_start) {
+ uint16_t n_wins = 1;
+ struct Win * win_p = win_meta->chain_start;
+ while (0 != win_p->next) {
+ win_p = win_p->next;
+ n_wins++; }
+ struct Corners * all_corners = malloc(sizeof(struct Corners) * n_wins);
+ draw_windows (win_meta->chain_start);
+ draw_windows_borders (win_meta->chain_start, win_meta->active, all_corners, 0);
+ uint16_t i;
+ for (i = 0; i < n_wins; i++) {
+ mvwaddch(win_meta->pad, all_corners[i].tl.y, all_corners[i].tl.x, '+');
+ mvwaddch(win_meta->pad, all_corners[i].tr.y, all_corners[i].tr.x, '+');
+ mvwaddch(win_meta->pad, all_corners[i].bl.y, all_corners[i].bl.x, '+');
+ mvwaddch(win_meta->pad, all_corners[i].br.y, all_corners[i].br.x, '+'); }
+ free(all_corners);
+ uint16_t y;
+ if (win_meta->pad_offset > 0)
+ draw_vertical_scroll_hint(win_meta, win_meta->pad_offset, win_meta->pad_offset + 1, '<');
+ if (win_meta->pad_offset + win_meta->width < getmaxx(win_meta->pad) - 1)
+ for (y = 0; y < win_meta->height; y++)
+ draw_vertical_scroll_hint(win_meta, win_meta->pad_offset + win_meta->width - 1,
+ getmaxx(win_meta->pad) - (win_meta->pad_offset + win_meta->width), '>');
+ pnoutrefresh(win_meta->pad, 0, win_meta->pad_offset, 0, 0, win_meta->height, win_meta->width - 1); }
+ doupdate(); }
+
+extern void resize_active_window (struct WinMeta * win_meta, uint16_t height, uint16_t width) {