mirror of https://github.com/fairyglade/ly
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
461 lines
8.3 KiB
C
461 lines
8.3 KiB
C
#define _XOPEN_SOURCE 700
|
|
#include "draw.h"
|
|
#include "cylgom.h"
|
|
#include "termbox.h"
|
|
#include "util.h"
|
|
#include "config.h"
|
|
#include "widgets.h"
|
|
#include <math.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
#include <stdlib.h>
|
|
#include <sys/time.h>
|
|
#include <sys/ioctl.h>
|
|
#include <linux/kd.h>
|
|
#include <linux/vt.h>
|
|
#include <stdio.h>
|
|
#include <unistd.h>
|
|
|
|
// border chars: ┌ └ ┐ ┘ ─ ─ │ │
|
|
struct box box_main = {0x250c, 0x2514, 0x2510, 0x2518, 0x2500, 0x2500 ,0x2502, 0x2502};
|
|
// alternative border chars:
|
|
// struct box box_main = {'+', '+', '+', '+', '-', '-', '|', '|'};
|
|
|
|
u16 width = 0;
|
|
u16 height = 0;
|
|
u16 box_main_x = 0;
|
|
u16 box_main_y = 0;
|
|
u16 labels_max_len = 0;
|
|
|
|
void draw_init()
|
|
{
|
|
if (config.custom_res)
|
|
{
|
|
width = config.res_width;
|
|
height = config.res_height;
|
|
}
|
|
else
|
|
{
|
|
width = tb_width();
|
|
height = tb_height();
|
|
}
|
|
|
|
if (info_line == NULL)
|
|
{
|
|
hostname(&info_line);
|
|
}
|
|
}
|
|
|
|
// box outline
|
|
void draw_box()
|
|
{
|
|
box_main_x = ((width - config.box_main_w) / 2);
|
|
box_main_y = ((height - config.box_main_h) / 2);
|
|
u16 box_main_x2 = ((width + config.box_main_w) / 2);
|
|
u16 box_main_y2 = ((height + config.box_main_h) / 2);
|
|
// corners
|
|
tb_change_cell(box_main_x - 1,
|
|
box_main_y - 1,
|
|
box_main.left_up,
|
|
config.fg,
|
|
config.bg);
|
|
tb_change_cell(box_main_x2 + 1,
|
|
box_main_y - 1,
|
|
box_main.right_up,
|
|
config.fg,
|
|
config.bg);
|
|
tb_change_cell(box_main_x - 1,
|
|
box_main_y2 + 1,
|
|
box_main.left_down,
|
|
config.fg,
|
|
config.bg);
|
|
tb_change_cell(box_main_x2 + 1,
|
|
box_main_y2 + 1,
|
|
box_main.right_down,
|
|
config.fg,
|
|
config.bg);
|
|
|
|
// top and bottom
|
|
struct tb_cell c1 = {box_main.top, config.fg, config.bg};
|
|
struct tb_cell c2 = {box_main.bot, config.fg, config.bg};
|
|
|
|
for(u8 i = 0; i <= config.box_main_w; ++i)
|
|
{
|
|
tb_put_cell(box_main_x + i,
|
|
box_main_y - 1,
|
|
&c1);
|
|
tb_put_cell(box_main_x + i,
|
|
box_main_y2 + 1,
|
|
&c2);
|
|
}
|
|
|
|
// left and right
|
|
c1.ch = box_main.left;
|
|
c2.ch = box_main.right;
|
|
// blank
|
|
struct tb_cell blank = {' ', config.fg, config.bg};
|
|
|
|
for(u8 i = 0; i <= config.box_main_h; ++i)
|
|
{
|
|
// testing in the height loop takes less cycles
|
|
// (I know this is placebo optimization :D)
|
|
if (config.blank_box)
|
|
{
|
|
for (u8 k = 0; k <= config.box_main_w; ++k)
|
|
{
|
|
tb_put_cell(box_main_x + k,
|
|
box_main_y + i,
|
|
&blank);
|
|
}
|
|
}
|
|
|
|
tb_put_cell(box_main_x - 1,
|
|
box_main_y + i,
|
|
&c1);
|
|
tb_put_cell(box_main_x2 + 1,
|
|
box_main_y + i,
|
|
&c2);
|
|
}
|
|
}
|
|
|
|
struct tb_cell* strn_cell(char* s, u16 len)
|
|
{
|
|
struct tb_cell* cells = malloc((sizeof (struct tb_cell)) * len);
|
|
char* s2 = s;
|
|
u32 c;
|
|
|
|
if (cells != NULL)
|
|
{
|
|
for (u16 i = 0; i < len; ++i)
|
|
{
|
|
if ((s2 - s) >= len)
|
|
{
|
|
break;
|
|
}
|
|
|
|
s2 += utf8_char_to_unicode(&c, s2);
|
|
|
|
cells[i].ch = c;
|
|
cells[i].bg = config.bg;
|
|
cells[i].fg = config.fg;
|
|
}
|
|
}
|
|
|
|
return cells;
|
|
}
|
|
|
|
struct tb_cell* str_cell(char* s)
|
|
{
|
|
return strn_cell(s, strlen(s));
|
|
}
|
|
|
|
// input labels
|
|
void draw_labels()
|
|
{
|
|
struct tb_cell* login = str_cell(lang.login);
|
|
|
|
tb_blit(box_main_x + config.margin_box_main_h,
|
|
box_main_y + config.margin_box_main_v + 5,
|
|
strlen(lang.login),
|
|
1,
|
|
login);
|
|
|
|
free(login);
|
|
|
|
struct tb_cell* password = str_cell(lang.password);
|
|
|
|
tb_blit(box_main_x + config.margin_box_main_h,
|
|
box_main_y + config.margin_box_main_v + 7,
|
|
strlen(lang.password),
|
|
1,
|
|
password);
|
|
|
|
free(password);
|
|
|
|
labels_max_len = strlen(lang.login);
|
|
|
|
if (labels_max_len < strlen(lang.password))
|
|
{
|
|
labels_max_len = strlen(lang.password);
|
|
}
|
|
|
|
if (info_line != NULL)
|
|
{
|
|
u16 hostname_len = strlen(info_line);
|
|
struct tb_cell* info_cell = str_cell(info_line);
|
|
|
|
tb_blit(box_main_x + ((config.box_main_w - hostname_len) / 2),
|
|
box_main_y + config.margin_box_main_v,
|
|
hostname_len,
|
|
1,
|
|
info_cell);
|
|
free(info_cell);
|
|
}
|
|
}
|
|
|
|
// F1 and F2 labels
|
|
void draw_f_commands()
|
|
{
|
|
struct tb_cell* f1 = str_cell(lang.f1);
|
|
tb_blit(0, 0, strlen(lang.f1), 1, f1);
|
|
free(f1);
|
|
|
|
struct tb_cell* f2 = str_cell(lang.f2);
|
|
tb_blit(strlen(lang.f1) + 1, 0, strlen(lang.f2), 1, f2);
|
|
free(f2);
|
|
}
|
|
|
|
// numlock and capslock info
|
|
void draw_lock_state()
|
|
{
|
|
FILE* console = fopen(config.console_dev, "w");
|
|
|
|
if (console == NULL)
|
|
{
|
|
info_line = lang.err_console_dev;
|
|
return;
|
|
}
|
|
|
|
int fd = fileno(console);
|
|
char ret;
|
|
|
|
ioctl(fd, KDGKBLED, &ret);
|
|
fclose(console);
|
|
|
|
u16 pos_x = width - strlen(lang.numlock);
|
|
|
|
if (((ret >> 1) & 0x01) == 1)
|
|
{
|
|
struct tb_cell* numlock = str_cell(lang.numlock);
|
|
tb_blit(pos_x, 0, strlen(lang.numlock), 1, numlock);
|
|
free(numlock);
|
|
}
|
|
|
|
pos_x -= strlen(lang.capslock) + 1;
|
|
|
|
if (((ret >> 2) & 0x01) == 1)
|
|
{
|
|
struct tb_cell* capslock = str_cell(lang.capslock);
|
|
tb_blit(pos_x, 0, strlen(lang.capslock), 1, capslock);
|
|
free(capslock);
|
|
}
|
|
}
|
|
|
|
// main box
|
|
void draw_desktop(struct desktop* target)
|
|
{
|
|
u16 len = strlen(target->list[target->cur]);
|
|
|
|
if (len > (target->visible_len - 3))
|
|
{
|
|
len = target->visible_len - 3;
|
|
}
|
|
|
|
tb_change_cell(target->x,
|
|
target->y,
|
|
'<',
|
|
config.fg,
|
|
config.bg);
|
|
|
|
tb_change_cell(target->x + target->visible_len - 1,
|
|
target->y,
|
|
'>',
|
|
config.fg,
|
|
config.bg);
|
|
|
|
for (u16 i = 0; i < len; ++i)
|
|
{
|
|
tb_change_cell(target->x + i + 2,
|
|
target->y,
|
|
target->list[target->cur][i],
|
|
config.fg,
|
|
config.bg);
|
|
}
|
|
}
|
|
|
|
// classic input
|
|
void draw_input(struct input* input)
|
|
{
|
|
u16 len = strlen(input->text);
|
|
u16 visible_len = input->visible_len;
|
|
struct tb_cell* cells;
|
|
|
|
if (len > visible_len)
|
|
{
|
|
len = visible_len;
|
|
}
|
|
|
|
cells = strn_cell(input->visible_start, len);
|
|
|
|
if (cells != NULL)
|
|
{
|
|
tb_blit(input->x, input->y, len, 1, cells);
|
|
free(cells);
|
|
|
|
for (u16 i = input->end - input->visible_start; i < visible_len; ++i)
|
|
{
|
|
tb_change_cell(input->x + i,
|
|
input->y,
|
|
' ',
|
|
config.fg,
|
|
config.bg);
|
|
}
|
|
}
|
|
}
|
|
|
|
// password input (hidden text)
|
|
void draw_input_mask(struct input* input)
|
|
{
|
|
u16 len = strlen(input->text);
|
|
u16 visible_len = input->visible_len;
|
|
|
|
if (len > visible_len)
|
|
{
|
|
len = visible_len;
|
|
}
|
|
|
|
for (u16 i = 0; i < visible_len; ++i)
|
|
{
|
|
if (input->visible_start + i < input->end)
|
|
{
|
|
tb_change_cell(input->x + i,
|
|
input->y,
|
|
'o',
|
|
config.fg,
|
|
config.bg);
|
|
}
|
|
else
|
|
{
|
|
tb_change_cell(input->x + i,
|
|
input->y,
|
|
' ',
|
|
config.fg,
|
|
config.bg);
|
|
}
|
|
}
|
|
}
|
|
|
|
// configures the inputs accroding to the size of the screen
|
|
void position_input(struct desktop* desktop, struct input* login, struct input* password)
|
|
{
|
|
i32 len;
|
|
u16 x;
|
|
|
|
x = box_main_x + config.margin_box_main_h + labels_max_len + 1;
|
|
len = box_main_x + config.box_main_w - config.margin_box_main_h - x;
|
|
|
|
if (len < 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
desktop->x = x;
|
|
desktop->y = box_main_y + config.margin_box_main_v + 3;
|
|
desktop->visible_len = len;
|
|
|
|
login->x = x;
|
|
login->y = box_main_y + config.margin_box_main_v + 5;
|
|
login->visible_len = len;
|
|
|
|
password->x = x;
|
|
password->y = box_main_y + config.margin_box_main_v + 7;
|
|
password->visible_len = len;
|
|
}
|
|
|
|
// background animations
|
|
// example implementation
|
|
void spiral()
|
|
{
|
|
static struct timeval time;
|
|
static uint64_t time_present = 0;
|
|
static uint64_t time_past = 0;
|
|
const struct tb_cell c1 = {'o', config.fg, config.bg};
|
|
static f64 ini = 0;
|
|
|
|
gettimeofday(&time, NULL);
|
|
time_present = time.tv_usec + ((uint64_t) 1000000) * time.tv_sec;
|
|
|
|
ini += 2 * M_PI * ((time_present - time_past) / 2000000.0);
|
|
|
|
if (ini > (5 * 2 * M_PI))
|
|
{
|
|
ini = 0;
|
|
}
|
|
|
|
for (f64 t = 0; t < (5 * 2 * M_PI); t += 0.01)
|
|
{
|
|
f64 y = sin(t + ini) * (height / 2) * 0.3 * (t / (2 * M_PI)) * 1.2;
|
|
f64 x = cos(t + ini) * (width / 2) * 0.2 * (t / (2 * M_PI)) * 1.2;
|
|
|
|
tb_put_cell((width / 2) + x, (height / 2) + y, &c1);
|
|
}
|
|
|
|
time_past = time_present;
|
|
}
|
|
|
|
void animate()
|
|
{
|
|
switch(config.animate)
|
|
{
|
|
case 1:
|
|
spiral();
|
|
break;
|
|
case 0:
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
// very important ;)
|
|
void cascade(u8* fails)
|
|
{
|
|
u16 width = tb_width();
|
|
u16 height = tb_height();
|
|
struct tb_cell* buf = tb_cell_buffer();
|
|
char c;
|
|
char c_under;
|
|
bool changes = false;
|
|
|
|
for (int i = height - 2; i >= 0; --i)
|
|
{
|
|
for (int k = 0; k < width; ++k)
|
|
{
|
|
c = buf[i * width + k].ch;
|
|
|
|
if (isspace(c))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
c_under = buf[(i + 1) * width + k].ch;
|
|
|
|
if (!isspace(c_under))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (!changes)
|
|
{
|
|
changes = true;
|
|
}
|
|
|
|
// omg this is not cryptographically secure
|
|
if (((rand() % 10)) > 7)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
buf[(i + 1) * width + k] = buf[i * width + k];
|
|
buf[i * width + k].ch = ' ';
|
|
}
|
|
}
|
|
|
|
if (!changes)
|
|
{
|
|
sleep(7);
|
|
config.auth_fails = 0;
|
|
config.min_refresh_delta = config.old_min_refresh_delta;
|
|
config.force_update = config.old_force_update;
|
|
}
|
|
}
|