started image suport

This commit is contained in:
Null 2025-02-08 19:54:18 -03:00
parent e125d8f1aa
commit 1c11580efd
9 changed files with 238 additions and 2 deletions

View File

@ -1,9 +1,13 @@
# Ly - a TUI display manager
# Ly with image support - a TUI display manager with image support
![Ly screenshot](.github/screenshot.png "Ly screenshot")
Ly is a lightweight TUI (ncurses-like) display manager for Linux and BSD.
## Create your Custom Image
Use [**LyArt**](https://augusto-p.github.io/ly-Image-maker/) To Create Your Image Here
## Dependencies
- Compile-time:
- zig >=0.12.0

View File

@ -33,8 +33,10 @@
# none -> Nothing
# doom -> PSX DOOM fire
# matrix -> CMatrix
animation = none
# image -> Image
animation = image
image_path = /etc/ly/Img.lyim
# Stop the animation after some time
# 0 -> Run forever
# 1..2e12 -> Stop the animation after this many seconds

1
res/default_img.lyim Normal file
View File

@ -0,0 +1 @@
WWWWWWWWWWW333333333333333NNNNNNNNNNNNNNNNNNNNNNNNNNNN333333333Y!!!!!!!'WWWWWWWW WWWWWWWWWWW333333333333333NNNNNNNNNNNNNNNNNNNNNNNNNNNN33333338`Y!!!!!!!(WWWWWWWW WWWWWWWWWWW333333333333333NNNNNNNNNNNNNNNNNNNNNNNNNNNN33333338!!!!!!!!!!!?WWWWWW WWWWWWWWWWW333333333333333NNNNNNNNNNNNNNNNNNNNNNNNNNNN333333`Y!!!$<<<9!!!(`_WWWW WWWWWWWWWWW333333333333333NNNNNNNNNNNNNNNNNNNNNNNNNNNN333338!!!!![37WX!!!!!_WWWW WWWWWWWWWWW333333333333333NNNNNNNNNNNNNNNNNNNNNNNNNNNN33333\!!!(`[37WX`Y!!!$_WWW WWWWWWWWWWW333333333333333NNNNNNNNNNNNNNNNNNNNNNNNNNNN33338!!!!(3337WWWY!!!!_WWW WWWWWWWWWWW333333333333333NNNNNNNNNNNNNNNNNNNNNNNNNNNN3333Y!!$`[3337WWWX`Y!!$WWW WWWW_WWWWWW333333433333333NNNNNNNNNNNNNNNNNNNNNNNNNNNN33339!!(333337WWWWWY!!!WWW WWWW?WWWWWW333333433333333NNNNNNNNNNNNNNNNNNNNNNNNNNNN333Y!!![333337WWWWWX9!!(WW WWWX@WWWWWW333333<;3333333NNNNNNNNNNNNNNNNNNNNNNNNNNNN333Y!!@3333337WWWWWW\!!(WW WWWT<WWWWWW333333<;3333333NNNNNNNNNNNNNNNNNNNNNNNNNNNN333Y!!33333337WWWWWWW!!(WW WWWT<WWWWWW333333<;3333333NNNNNNNNNNNNNNNNNNNNNNNNNNNN33`9!@38``3337WWWX`_W`!!`W WWW\<_WWWWW333334<<3333333NNNNNNNNNNNNNNNNNNNNNNNNNNNN33Y!![38!(3337WWWY!'WX!!(W WWW<<?WWWWW333334<<3333333NNNNNNNNNNNNNNNNNNNNNNNNNNNN33Y!@338!$<<<<<<<9!'WW`!(W WWW<<?WWWWW333334<<3333333NNNNNNNNNNNNNNNNNNNNNNNNNNNN33Y![338!!!!!!!!!!!'WWX!(W WWX<<@WWWWW33333<<<;333333NNNNNNNNNNNNNNNNNNNNNNNNNNNN3Y!![338!!!!!!!!!!!'WWX!!( WWT<<<WWWWW33333<<<;333333NNNNNNNNNNNNNNNNNNNNNNNNNNNN3Y!![338!!!!!!!!!!!'WWX!!( WWT<<<WWWWW33333<<<;333333NNNNNNNNNNNNNNNNNNNNNNNNNNNN3Y!;3338!!!!!!!!!!!'WWWX!( WW\<<<_WWWW33334<<<<333333NNNNNNNNNNNNNNNNNNNNNNNNNNNN3Y!;338\!!!!!!!!!!!(_WWX!( WW<<<<?WWWW33334<<<<333333NNNNNNNNNNNNNNNNNNNNNNNNNNNN3Y!;338!!!!!!!!!!!!!_WWX!( WW<<<<?WWWW33334<<<<333333NNNNNNNNNNNNNNNNNNNNNNNNNNNN39!;338!!!!!!!!!!!!!_WWX!$ WX<<<<@WWWW3333<<<<<;33333NNNNNNNNNNNNNNNNNNNNNNNNNNNN3!!;338!!!!!!!!!!!!!_WWX!! WT<<<<<<<<<<<<<<<<<<;33333NNNNNNNNNNNNNNNNNNNNNNNNNNNN3!!;338!!!!!!!!!!!!!_WWX!! W\<<<<<<<<<<<<<<<<<<;33333NNNNNNNNNNNNNNNNNNNNNNNNNNNN3!!;338!!!!!!!!!!!!!_WWX!! W\<<<<<<<<<<<<<<<<<<<33333NNNNNNNNNNNNNNNNNNNNNNNNNNNN3!!;338!!!!!!!!!!!!!_WWX!! W<<<<<<<<<<<<<<<<<<<<33333NNNNNNNNNNNNNNNNNNNNNNNNNNNN3!!;338!!!!!!!!!!!!!_WWX!! X<<<<<<<<<<<<<<<<<<<<;3333NNNNNNNNNNNNNNNNNNNNNNNNNNNN3!!;338!!!!!!!!!!!!!_WWX!! X<<<<<<<<<<<<<<<<<<<<;3333NNNNNNNNNNNNNNNNNNNNNNNNNNNN3!!;338!!!!!!!!!!!!!_WWX!! T<<<<<<<<<<<<<<<<<<<<;3333NNNNNNNNNNNNNNNNNNNNNNNNNNNN3!!;338!!!!!!!!!!!!!_WWX!! \<<<<<<<<<<<<<<<<<<<<<3333NNNNNNNNNNNNNNNNNNNNNNNNNNNN3Y!;338\!!!!!!!!!!!(_WWX!( \<<<<<<<<<<<<<<<<<<<<<3333NNNNNNNNNNNNNNNNNNNNNNNNNNNN3Y!;3338!!!!!!!!!!!'WWWX!( W\<<<<<<<<<<<<<<<<<<<33333NNNNNNNNNNNNNNNNNNNNNNNNNNNN3Y!![8$8`Y!!!!!!!(`_WWX!!( WX<<<<<<<<<<<<<<<<<<;33333NNNNNNNNNNNNNNNNNNNNNNNNNNNN3Y!![8!33Y!!!!!!!(WWWWX!!( WWT<<<<<<<<<<<<<<<<;333333NNNNNNNNNNNNNNNNNNNNNNNNNNNN3Y!![8!(333Y!!!$WWWWWWX!!( WWW\<<<<<<<<<<<<<<<3333333NNNNNNNNNNNNNNNNNNNNNNNNNNNN3\!!@39$`33Y!!!!`WWWWW`!!@ WWWX<<<<<<<<<<<<<<;3333333NNNNNNNNNNNNNNNNNNNNNNNNNNNN33Y!![8!(33Y!!!!(WWWWX!!(W WWWWX<<<<<<<<<<<<;33333333NNNNNNNNNNNNNNNNNNNNNNNNNNNN33Y!!@3Y$``!!!!!(WWWW`!!(W WWWWW\<<<<<<<<<<<333333333NNNNNNNNNNNNNNNNNNNNNNNNNNNN33Y!!!38!!!!!!!!(WWWW!!!(W WWWWWX\<<<<<<<<<3333333333NNNNNNNNNNNNNNNNNNNNNNNNNNNN33`9!!@8Y!!!!!!!(WWW\!!$`W WWWWWWX<<<<<<<<;3333333333NNNNNNNNNNNNNNNNNNNNNNNNNNNN333Y!!![1!!!!!!!(WWX9!!(WW WWWWWWW\<<<<<<<33333333333NNNNNNNNNNNNNNNNNNNNNNNNNNNN33339!!(333Y!!!!(WWY!!!WWW WWWWWWWW\<<<<<333333333333NNNNNNNNNNNNNNNNNNNNNNNNNNNN3333Y!!$`[3Y!!!!(WXY!!$WWW WWWWWWWWX<<<<;333333333333NNNNNNNNNNNNNNNNNNNNNNNNNNNN33338!!!!(3Y!!!!(WY!!!WWWW WWWWWWWWWX<<;3333333333333NNNNNNNNNNNNNNNNNNNNNNNNNNNN33333\!!!(`9!!!!(`Y!!$WWWW WWWWWWWWWW\<33333333333333NNNNNNNNNNNNNNNNNNNNNNNNNNNN333338!!!!!!!!!!!!!!!_WWWW WWWWWWWWWWX333333333333333NNNNNNNNNNNNNNNNNNNNNNNNNNNN333333`Y!!!!!!!!!!!!@_WWWW WWWWWWWWWWW333333333333333NNNNNNNNNNNNNNNNNNNNNNNNNNNN33333338!!!!!!!!!!!!_WWWWW WWWWWWWWWWW333333333333333NNNNNNNNNNNNNNNNNNNNNNNNNNNN33333338`Y!!!!!!!!!(_WWWWW WWWWWWWWWWW333333333333333NNNNNNNNNNNNNNNNNNNNNNNNNNNN333333333Y!!!!!!!!!'WWWWWW

View File

@ -33,6 +33,7 @@ case $SHELL in
[ -f "$zhome"/.zprofile ] && . "$zhome"/.zprofile
[ -f "$zdir"/zlogin ] && . "$zdir"/zlogin
[ -f "$zhome"/.zlogin ] && . "$zhome"/.zlogin
[ -f "$zhome"/.zshrc ] && . "$zhome"/.zshrc
emulate -R sh
;;
*/csh|*/tcsh)

215
src/animations/Image.zig Normal file
View File

@ -0,0 +1,215 @@
const std = @import("std");
const Allocator = std.mem.Allocator;
const TerminalBuffer = @import("../tui/TerminalBuffer.zig");
const interop = @import("../interop.zig");
const termbox = interop.termbox;
const Image = @This();
allocator: Allocator,
terminal_buffer: *TerminalBuffer,
Text: []const u8,
pub fn init(allocator: Allocator, terminal_buffer: *TerminalBuffer, path: []const u8) !Image {
var buffer: [100]u8 = undefined;
const text = try std.fmt.bufPrint(&buffer, "{}X{}", .{terminal_buffer.width, terminal_buffer.height - 1});
try writeTextToFile("/etc/ly/Dimensions.txt", text);
const Texto = try readFile(path);
return .{
.allocator = allocator,
.terminal_buffer = terminal_buffer,
.Text = Texto,
};
}
pub fn countNewLines(text: []const u8) usize {
var lines: usize = 0;
for (text) |c| {
if (c == '\n') {
lines += 1;
}
}
return lines;
}
pub fn draw(self: *Image) !void {
const buf_height = self.terminal_buffer.height - 1;
const buf_width = self.terminal_buffer.width;
const Text_size = self.Text.len;
const Lines_number = countNewLines(self.Text);
const widthImage = Text_size / Lines_number;
const widthImageRange = widthImage - 1;
const maxRow = min(buf_height, Lines_number);
const maxCol = min(buf_width, widthImageRange);
for (0..maxRow) |y| {
for (0..maxCol) |x| {
const colorText: []const u8 = &[_]u8{ self.Text[(y * widthImage) + x] };
const color = try std.fmt.parseInt(u16, colorText, 10);
setPixel(x, y, self.terminal_buffer, color);
}
}
}
pub fn setPixel(x: usize, y: usize, terminal_buffer: *TerminalBuffer, color: u16) void {
if (x >= terminal_buffer.width or y >= terminal_buffer.height) {
@panic("Coordinates out of bounds of the buffer");
}
_ = termbox.tb_set_cell(@intCast(x), @intCast(y + 1), ' ', color + 1, color + 1);
}
pub fn min(a: usize, b: usize) usize {
if (a < b) {
return a;
}
return b;
}
pub fn readFile(path: []const u8) ![]const u8 {
var file_path = path;
const allocator = std.heap.page_allocator;
const fs = std.fs;
const cwd = fs.cwd();
var flag = false;
var file = cwd.openFile(file_path, .{ .mode = .read_write}) catch |err| {
if (err == error.FileNotFound) {
file_path = "/etc/ly/default_img.lyim";
flag = true;
}
return err;
};
if (flag){
file = try cwd.openFile(file_path, .{ .mode = .read_write});
}
defer file.close();
const file_size = (try file.stat()).size;
const buffer = try allocator.alloc(u8, file_size);
_ = try file.readAll(buffer);
const Text_size = buffer.len * 2;
var Text = try allocator.alloc(u8, Text_size);
var Index:usize = 0;
for (buffer) |c| {
if (c != ' ') {
const Nchar: usize = getAsciiChar(c);
const NBinary: [6]u8 = getBinary(Nchar - 33);
const ColorABin: [3]u8 = getBinPart(NBinary, 1);
const ColorBBin: [3]u8 = getBinPart(NBinary, 2);
const ColorA: usize = binarytoUsize(ColorABin);
const ColorB: usize = binarytoUsize(ColorBBin);
Text[Index] = UsizeToU8(ColorA);
Index += 1;
Text[Index] = UsizeToU8(ColorB);
Index += 1;
}else{
Text[Index] = '\n';
Index += 1;
}
}
return Text[0..Index];
}
pub fn writeTextToFile(file_path: []const u8, text: []const u8) !void {
var file = try std.fs.cwd().createFile(file_path, .{ .truncate = true });
defer file.close();
try file.writeAll(text);
}
pub fn getAsciiChar(char: u8) usize {
const ascii_table = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
var index: usize = 0;
while (index < ascii_table.len) {
if (ascii_table[index] == char) {
return index + 32;
}
index += 1;
}
return 0;
}
pub fn getBinary(N: usize) [6]u8 {
var binary: [6]u8 = undefined;
var num: usize = N;
var index: usize = 6;
while (num > 1) {
if (num % 2 == 0) {
binary[index-1] = '0';
} else {
binary[index-1] = '1';
}
num = num / 2;
index -= 1;
}
if (num == 0) {
binary[index-1] = '0';
} else {
binary[index-1] = '1';
}
index -= 1;
while (index > 0) {
binary[index-1] = '0';
index -= 1;
}
return binary;
}
pub fn getBinPart(Bin: [6]u8, part:usize) [3]u8{
var binary: [3]u8 = undefined;
if (part == 1){
binary[0] = Bin[0];
binary[1] = Bin[1];
binary[2] = Bin[2];
}else{
binary[0] = Bin[3];
binary[1] = Bin[4];
binary[2] = Bin[5];
}
return binary;
}
pub fn UsizeToU8(dec: usize) u8{
if(dec == 0){
return '0';
}else if(dec == 1){
return '1';
}else if(dec == 2){
return '2';
}else if(dec == 3){
return '3';
}else if(dec == 4){
return '4';
}else if(dec == 5){
return '5';
}else if(dec == 6){
return '6';
}else if(dec == 7){
return '7';
}else if(dec == 8){
return '8';
}else if(dec == 9){
return '9';
}else{
return '0';
}
}
pub fn binarytoUsize(slice: [3]u8) usize {
var result: usize = 0;
for (slice) |bit| {
result = result * 2 + (bit-48);
}
return result;
}

View File

@ -9,6 +9,7 @@ const Bigclock = enums.Bigclock;
animation: Animation = .none,
animation_timeout_sec: u12 = 0,
asterisk: ?u8 = '*',
image_path: []const u8 = "",
auth_fails: u64 = 10,
bg: u16 = 0,
bigclock: Bigclock = .none,

View File

@ -30,6 +30,7 @@ pub fn configFieldHandler(_: std.mem.Allocator, field: ini.IniField) ?ini.IniFie
mapped_field.value = switch (animation) {
0 => "doom",
1 => "matrix",
2 => "image",
else => "none",
};

View File

@ -2,6 +2,7 @@ pub const Animation = enum {
none,
doom,
matrix,
image,
};
pub const DisplayServer = enum {

View File

@ -8,6 +8,7 @@ const bigclock = @import("bigclock.zig");
const interop = @import("interop.zig");
const Doom = @import("animations/Doom.zig");
const Matrix = @import("animations/Matrix.zig");
const Image = @import("animations/Image.zig");
const TerminalBuffer = @import("tui/TerminalBuffer.zig");
const Session = @import("tui/components/Session.zig");
const Text = @import("tui/components/Text.zig");
@ -303,17 +304,21 @@ pub fn main() !void {
// Initialize the animation, if any
var doom: Doom = undefined;
var matrix: Matrix = undefined;
var image: Image = undefined;
switch (config.animation) {
.none => {},
.doom => doom = try Doom.init(allocator, &buffer),
.matrix => matrix = try Matrix.init(allocator, &buffer, config.cmatrix_fg),
.image => image = try Image.init(allocator, &buffer, config.image_path),
}
defer {
switch (config.animation) {
.none => {},
.doom => doom.deinit(),
.matrix => matrix.deinit(),
.image => {},
}
}
@ -365,6 +370,7 @@ pub fn main() !void {
.matrix => matrix.realloc() catch {
try info_line.addMessage(lang.err_alloc, config.error_bg, config.error_fg);
},
.image => {},
}
update = true;
@ -378,11 +384,14 @@ pub fn main() !void {
_ = termbox.tb_clear();
if (!animation_timed_out) {
switch (config.animation) {
.none => {},
.doom => doom.draw(),
.matrix => matrix.draw(),
.image => try image.draw(),
}
}
if (config.bigclock != .none and buffer.box_height + (bigclock.HEIGHT + 2) * 2 < buffer.height) draw_big_clock: {
@ -542,6 +551,7 @@ pub fn main() !void {
.none => {},
.doom => doom.deinit(),
.matrix => matrix.deinit(),
.image => {},
}
}
} else if (config.bigclock != .none and config.clock == null) {