navigation: wtf I'm doing

This commit is contained in:
javalsai 2024-07-13 16:56:34 +02:00
parent 24b7db38a4
commit 6398d1b206
2 changed files with 190 additions and 26 deletions

View File

@ -11,11 +11,13 @@ struct editable_field field_new(char* content) {
} else { } else {
field_trim(&__efield, 0); field_trim(&__efield, 0);
} }
__efield.content[__efield.length] = '\0';
return __efield; return __efield;
} }
void field_trim(struct editable_field *field, u_char pos) { void field_trim(struct editable_field *field, u_char pos) {
field->length = field->pos = pos; field->length = field->pos = pos;
field->content[field->length] = '\0';
} }
void field_update(struct editable_field *field, char *update) { void field_update(struct editable_field *field, char *update) {
@ -28,12 +30,14 @@ void field_update(struct editable_field *field, char *update) {
if (insert_len == 1) { if (insert_len == 1) {
// backspace // backspace
if (*update == 127) { if (*update == 127) {
if (field->pos == 0) return;
if (field->pos < field->length) { if (field->pos < field->length) {
memcpy(&field->content[field->pos - 1], &field->content[field->pos], memcpy(&field->content[field->pos - 1], &field->content[field->pos],
field->length - field->pos); field->length - field->pos);
} }
(field->pos)--; (field->pos)--;
(field->length)--; (field->length)--;
field->content[field->length] = '\0';
return; return;
} }
} }
@ -51,6 +55,7 @@ void field_update(struct editable_field *field, char *update) {
field->pos += insert_len; field->pos += insert_len;
field->length += insert_len; field->length += insert_len;
field->content[field->length] = '\0';
} }
// returns bool depending if it was able to "use" the seek // returns bool depending if it was able to "use" the seek
@ -60,5 +65,8 @@ bool field_seek(struct editable_field *field, char seek) {
if(seek < 0 && -seek > field->pos) field->pos = 0; if(seek < 0 && -seek > field->pos) field->pos = 0;
else if(seek > 0 && 255 - field->pos < seek) field->pos = 255; else if(seek > 0 && 255 - field->pos < seek) field->pos = 255;
else field->pos += seek; else field->pos += seek;
if(field->pos > field->length) field->pos = field->length;
return true; return true;
} }

208
src/ui.c
View File

@ -1,4 +1,5 @@
// i'm sorry // i'm sorry
// really sorry
#include <errno.h> #include <errno.h>
#include <signal.h> #include <signal.h>
@ -35,6 +36,9 @@ static void print_session(struct uint_point, struct session, bool);
static void print_user(struct uint_point, struct user, bool); static void print_user(struct uint_point, struct user, bool);
static void print_passwd(struct uint_point, uint, bool); static void print_passwd(struct uint_point, uint, bool);
enum input { SESSION, USER, PASSWD };
static u_char inputs_n = 3;
// ansi resource: https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797 // ansi resource: https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797
static struct termios orig_term; static struct termios orig_term;
static struct termios term; static struct termios term;
@ -57,6 +61,7 @@ void setup(struct config __config) {
theme = __config.theme; theme = __config.theme;
functions = __config.functions; functions = __config.functions;
strings = __config.strings; strings = __config.strings;
behavior = __config.behavior;
tcgetattr(STDOUT_FILENO, &orig_term); tcgetattr(STDOUT_FILENO, &orig_term);
term = orig_term; // save term term = orig_term; // save term
@ -64,10 +69,9 @@ void setup(struct config __config) {
term.c_lflag &= ~(ICANON | ECHO); term.c_lflag &= ~(ICANON | ECHO);
tcsetattr(STDOUT_FILENO, TCSANOW, &term); tcsetattr(STDOUT_FILENO, TCSANOW, &term);
// save cursor pos, save screen, hide cursor, set color and reset screen // save cursor pos, save screen, set color and reset screen
// (applying color to all screen) // (applying color to all screen)
printf("\x1b[s\x1b[?47h\x1b[%s;%sm\x1b[2J", theme.colors.bg, printf("\x1b[s\x1b[?47h\x1b[%s;%sm\x1b[2J", theme.colors.bg, theme.colors.fg);
theme.colors.fg);
print_footer(); print_footer();
atexit(restore_all); atexit(restore_all);
@ -107,6 +111,8 @@ struct opt_field {
uint current_opt; // 0 is edit mode btw uint current_opt; // 0 is edit mode btw
struct editable_field efield; struct editable_field efield;
}; };
void print_ofield(struct opt_field *focused_input);
static struct opt_field ofield_new(uint opts) { static struct opt_field ofield_new(uint opts) {
struct opt_field __field; struct opt_field __field;
__field.opts = opts; __field.opts = opts;
@ -118,8 +124,26 @@ static struct opt_field ofield_new(uint opts) {
return __field; return __field;
} }
static void ofield_toedit(struct opt_field *ofield, char *init) { static void ofield_toedit(struct opt_field *ofield, char *init) {
ofield->current_opt = 0;
ofield->efield = field_new(init); ofield->efield = field_new(init);
} }
static void ofield_type(struct opt_field *ofield, char *new, char *startstr) {
if (ofield->current_opt != 0)
ofield_toedit(ofield, startstr);
field_update(&ofield->efield, new);
}
// true if it changed anything, single opt fields return false
static bool ofield_opt_seek(struct opt_field *ofield, char seek) {
// TODO: think this
if (ofield->opts == 0 || (ofield->opts == 1 && ofield->current_opt != 0))
return false;
ofield->current_opt =
1 + ((ofield->current_opt - 1 + seek + ofield->opts) % ofield->opts);
print_ofield(ofield);
return true;
}
// true in case it was able to "use" the seek (a empty only editable field // true in case it was able to "use" the seek (a empty only editable field
// wouldn't) // wouldn't)
static bool ofield_seek(struct opt_field *ofield, char seek) { static bool ofield_seek(struct opt_field *ofield, char seek) {
@ -132,54 +156,171 @@ static bool ofield_seek(struct opt_field *ofield, char seek) {
if (ofield->opts == 0) if (ofield->opts == 0)
return false; return false;
ofield->current_opt = (ofield->current_opt + seek + ofield->opts + 1) % ofield_opt_seek(ofield, seek);
(ofield->opts + 1); // not sure about this one
return true; return true;
} }
static u_char ofield_max_displ_pos(struct opt_field *ofield) { static u_char ofield_max_displ_pos(struct opt_field *ofield) {
// TODO: set max cursor pos too // TODO: set max cursor pos too
// keep in mind that also have to keep in mind scrolling and ughhh, mentally blocked, but this is complex // keep in mind that also have to keep in mind scrolling and ughhh, mentally
if(ofield->current_opt == 0) // blocked, but this is complex
if (ofield->current_opt == 0)
return ofield->efield.pos; return ofield->efield.pos;
else else
return 0; return 0;
} }
enum input { SESSION, USER, PASSWD };
static u_char inputs_n = 3;
enum input focused_input = PASSWD; enum input focused_input = PASSWD;
struct opt_field of_session; struct opt_field of_session;
struct opt_field of_user; struct opt_field of_user;
struct opt_field of_passwd; struct opt_field of_passwd;
void update_cursor_focus() { struct users_list *gusers;
struct sessions_list *gsessions;
// not *that* OF tho
struct opt_field *get_of(enum input from) {
if (from == SESSION)
return &of_session;
if (from == USER)
return &of_user;
if (from == PASSWD)
return &of_passwd;
return NULL;
}
void ffield_cursor_focus() {
struct uint_point bstart = box_start(); struct uint_point bstart = box_start();
u_char line = bstart.y; u_char line = bstart.y;
u_char row = bstart.x + 15; u_char row = bstart.x + 15;
// rows in here quite bodged
if (focused_input == SESSION) { if (focused_input == SESSION) {
line += 5; line += 5;
row += ofield_max_displ_pos(&of_session); row += (of_session.opts > 1) * 2;
} else if (focused_input == USER) { } else if (focused_input == USER) {
line += 7; line += 7;
row += ofield_max_displ_pos(&of_user); row += (of_user.opts > 1) * 2;
} else if (focused_input == PASSWD) { } else if (focused_input == PASSWD)
line += 9; line += 9;
row += ofield_max_displ_pos(&of_passwd);
} struct opt_field *ofield = get_of(focused_input);
row += ofield->current_opt == 0 ? ofield_max_displ_pos(ofield) : 0;
printf("\x1b[%d;%dH", line, row); printf("\x1b[%d;%dH", line, row);
fflush(stdout); fflush(stdout);
} }
struct user get_current_user() {
if (of_user.current_opt != 0)
return gusers->users[of_user.current_opt - 1];
else {
struct user custom_user;
custom_user.shell = "/usr/bin/bash";
custom_user.username = custom_user.display_name = of_user.efield.content;
return custom_user;
}
}
struct session get_current_session() {
if (of_session.current_opt != 0) {
// this is for the default user shell :P, not the greatest implementation
// but I want to get his done
if (behavior.include_defshell &&
of_session.current_opt == gsessions->length + 1) {
struct session shell_session;
shell_session.type = SHELL;
shell_session.path = shell_session.name = get_current_user().shell;
return shell_session;
} else
return gsessions->sessions[of_session.current_opt - 1];
} else {
struct session custom_session;
custom_session.type = SHELL;
custom_session.name = custom_session.path = of_session.efield.content;
return custom_session;
}
}
void print_field(enum input focused_input) {
struct uint_point origin = box_start();
if (focused_input == PASSWD) {
print_passwd(origin, of_passwd.efield.length, false);
} else if (focused_input == SESSION) {
print_session(origin, get_current_session(), of_session.opts > 1);
} else if (focused_input == USER) {
print_user(origin, get_current_user(), of_user.opts > 1);
print_field(SESSION);
}
ffield_cursor_focus();
}
void print_ffield() { print_field(focused_input); }
void print_ofield(struct opt_field *ofield) {
enum input input;
if (ofield == &of_session)
input = SESSION;
else if (ofield == &of_user)
input = USER;
else if (ofield == &of_passwd)
input = PASSWD;
else
return;
print_field(input);
}
// true = forward, false = backward // true = forward, false = backward
void change_field_focus(bool direction) { void ffield_move(bool direction) {
if (direction) if (direction)
focused_input = (focused_input + 1 + inputs_n) % inputs_n; focused_input = (focused_input + 1 + inputs_n) % inputs_n;
else else
focused_input = (focused_input - 1 + inputs_n) % inputs_n; focused_input = (focused_input - 1 + inputs_n) % inputs_n;
ffield_cursor_focus();
}
// tf I'm doing
void ffield_change_opt(bool direction) {
struct opt_field *ffield = get_of(focused_input);
if (focused_input == PASSWD)
ffield = &of_session;
if (!ofield_opt_seek(ffield, direction ? 1 : -1)) {
if (focused_input == PASSWD || focused_input == SESSION)
ofield_opt_seek(&of_user, direction ? 1 : -1);
else
ofield_opt_seek(&of_session, direction ? 1 : -1);
}
}
void ffield_change_pos(bool direction) {
struct opt_field *ffield = get_of(focused_input);
if (!ofield_seek(ffield, direction ? 1 : -1))
if (!ofield_opt_seek(&of_session, direction ? 1 : -1))
ofield_opt_seek(&of_user, direction ? 1 : -1);
ffield_cursor_focus();
}
void ffield_type(char *text) {
struct opt_field *field = get_of(focused_input);
char *start = "";
if (focused_input == USER && of_user.current_opt != 0)
start = get_current_user().username;
if (focused_input == SESSION && of_session.current_opt != 0 &&
get_current_session().type == SHELL)
start = get_current_session().path;
ofield_type(field, text, start);
print_ffield();
} }
int load(struct users_list *users, struct sessions_list *sessions) { int load(struct users_list *users, struct sessions_list *sessions) {
/// SETUP /// SETUP
gusers = users;
gsessions = sessions;
// hostnames larger won't render properly // hostnames larger won't render properly
char *hostname = malloc(16); char *hostname = malloc(16);
@ -211,36 +352,51 @@ int load(struct users_list *users, struct sessions_list *sessions) {
boxstart.x + boxw - 3 - (uint)strlen(fmtd_time), theme.colors.e_date, boxstart.x + boxw - 3 - (uint)strlen(fmtd_time), theme.colors.e_date,
fmtd_time, theme.colors.fg); fmtd_time, theme.colors.fg);
print_session(boxstart, sessions->sessions[0], false); print_field(SESSION);
print_user(boxstart, users->users[0], false); print_field(USER);
print_passwd(boxstart, 5, false); print_field(PASSWD);
fflush(stdout); ffield_cursor_focus();
update_cursor_focus();
/// INTERACTIVE /// INTERACTIVE
u_char len; u_char len;
char seq[256]; char seq[256];
uint esc = 0;
while (true) { while (true) {
read_press(&len, seq); read_press(&len, seq);
if (*seq == '\x1b') { if (*seq == '\x1b') {
enum keys ansi_code = find_ansi(seq); enum keys ansi_code = find_ansi(seq);
if (ansi_code != -1) { if (ansi_code != -1) {
if (ansi_code == functions.refresh) { if (ansi_code == ESC) {
esc = 2;
} else if (ansi_code == functions.refresh) {
restore_all(); restore_all();
return 0; return 0;
} else if (ansi_code == functions.reboot) { } else if (ansi_code == functions.reboot) {
restore_all();
system("reboot"); system("reboot");
exit(0); exit(0);
} else if (ansi_code == functions.poweroff) { } else if (ansi_code == functions.poweroff) {
restore_all();
system("poweroff"); system("poweroff");
exit(0); exit(0);
} else if (ansi_code == A_UP || ansi_code == A_DOWN) { } else if (ansi_code == A_UP || ansi_code == A_DOWN) {
change_field_focus(ansi_code == A_UP); ffield_move(ansi_code == A_DOWN);
} else if (ansi_code == A_RIGHT || ansi_code == A_LEFT) {
if (esc)
ffield_change_opt(ansi_code == A_RIGHT);
else
ffield_change_pos(ansi_code == A_RIGHT);
} }
} }
} else {} } else {
/*printf("norm(%d): %d\n", len, *seq);*/ if(len == 1 && *seq == '\n') {
printf("\x1b[HTODO: submit creds\n");
}
ffield_type(seq);
}
if (esc != 0)
esc--;
} }
} }