commits
tags
#include "ui.h"
#include <curses.h>
#include <string.h>
#include <time.h>
#define GLYPH_H 5
#define GLYPH_W 5
#define LETTER_GAP 1
typedef const char *Glyph[GLYPH_H];
/* Blocky 5x5 "16-bit" pixel font, just enough letters to spell TRANSTUI. */
static const Glyph GLYPH_T = {"\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88", " \xe2\x96\x88 ", " \xe2\x96\x88 ",
" \xe2\x96\x88 ", " \xe2\x96\x88 "};
static const Glyph GLYPH_R = {"\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88 ", "\xe2\x96\x88 \xe2\x96\x88",
"\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88 ", "\xe2\x96\x88 \xe2\x96\x88 ", "\xe2\x96\x88 \xe2\x96\x88"};
static const Glyph GLYPH_A = {" \xe2\x96\x88\xe2\x96\x88\xe2\x96\x88 ", "\xe2\x96\x88 \xe2\x96\x88",
"\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88", "\xe2\x96\x88 \xe2\x96\x88", "\xe2\x96\x88 \xe2\x96\x88"};
static const Glyph GLYPH_N = {"\xe2\x96\x88 \xe2\x96\x88", "\xe2\x96\x88\xe2\x96\x88 \xe2\x96\x88", "\xe2\x96\x88 \xe2\x96\x88 \xe2\x96\x88",
"\xe2\x96\x88 \xe2\x96\x88\xe2\x96\x88", "\xe2\x96\x88 \xe2\x96\x88"};
static const Glyph GLYPH_S = {" \xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88", "\xe2\x96\x88 ", " \xe2\x96\x88\xe2\x96\x88\xe2\x96\x88 ",
" \xe2\x96\x88", "\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88 "};
static const Glyph GLYPH_U = {"\xe2\x96\x88 \xe2\x96\x88", "\xe2\x96\x88 \xe2\x96\x88", "\xe2\x96\x88 \xe2\x96\x88",
"\xe2\x96\x88 \xe2\x96\x88", " \xe2\x96\x88\xe2\x96\x88\xe2\x96\x88 "};
static const Glyph GLYPH_I = {"\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88", " \xe2\x96\x88 ", " \xe2\x96\x88 ",
" \xe2\x96\x88 ", "\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88"};
/* T R A N S T U I */
static const Glyph *const WORD[] = {&GLYPH_T, &GLYPH_R, &GLYPH_A, &GLYPH_N,
&GLYPH_S, &GLYPH_T, &GLYPH_U, &GLYPH_I};
#define WORD_LEN (int)(sizeof(WORD) / sizeof(WORD[0]))
#define SPLASH_MS 3000
/* Returns the key that dismissed the splash, or ERR if it timed out on its
* own - the caller feeds a real key straight into the normal key handler
* instead of silently swallowing it, so e.g. pressing 'g' to skip the
* splash also opens settings immediately rather than just landing on the
* plain list view. */
int ui_splash_show(void)
{
int rows, cols;
getmaxyx(stdscr, rows, cols);
int banner_w = WORD_LEN * GLYPH_W + (WORD_LEN - 1) * LETTER_GAP;
const char *subtitle = "Transmission TUI Client";
const char *hint = "Press any key to continue\xe2\x80\xa6";
int content_w = banner_w;
if ((int)strlen(subtitle) > content_w)
content_w = (int)strlen(subtitle);
int box_w = content_w + 8;
if (box_w > cols - 2)
box_w = cols - 2;
int box_h = GLYPH_H + 6;
if (box_h > rows - 2)
box_h = rows - 2;
if (box_w < 10 || box_h < 8)
return ERR; /* terminal too small to bother */
int box_y = (rows - box_h) / 2;
int box_x = (cols - box_w) / 2;
erase();
WINDOW *win = derwin(stdscr, box_h, box_w, box_y, box_x);
ui_box(win, box_h, box_w);
ui_box_title(win, box_w, "TransTUI");
int have_color = has_colors();
int banner_y = 2;
int banner_x = (box_w - banner_w) / 2;
if (banner_x < 1)
banner_x = 1;
int white = have_color ? (COLOR_PAIR(CP_SPLASH_WHITE) | A_BOLD) : A_BOLD;
wattron(win, white);
for (int li = 0; li < WORD_LEN; li++)
for (int r = 0; r < GLYPH_H; r++)
mvwaddstr(win, banner_y + r, banner_x + li * (GLYPH_W + LETTER_GAP), (*WORD[li])[r]);
wattroff(win, white);
int sub_y = banner_y + GLYPH_H + 1;
wattron(win, white);
mvwprintw(win, sub_y, (box_w - (int)strlen(subtitle)) / 2, "%s", subtitle);
wattroff(win, white);
int hint_w = (int)strlen(hint) - 2; /* the ellipsis is one 3-byte UTF-8 char, not 3 cells */
wattron(win, have_color ? COLOR_PAIR(CP_SPLASH_WHITE) : 0);
mvwprintw(win, box_h - 2, (box_w - hint_w) / 2, "%s", hint);
wattroff(win, have_color ? COLOR_PAIR(CP_SPLASH_WHITE) : 0);
wnoutrefresh(win);
doupdate();
delwin(win);
struct timespec t0;
clock_gettime(CLOCK_MONOTONIC, &t0);
timeout(50);
int ch = ERR;
for (;;) {
ch = getch();
if (ch != ERR)
break;
struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
long elapsed = (now.tv_sec - t0.tv_sec) * 1000 + (now.tv_nsec - t0.tv_nsec) / 1000000;
if (elapsed >= SPLASH_MS)
break;
}
return ch;
}