mirror of
https://github.com/fairyglade/ly.git
synced 2025-12-21 11:44:55 +00:00
205 lines
6.6 KiB
Zig
205 lines
6.6 KiB
Zig
// The migrator ensures compatibility with <=0.6.0 configuration files
|
|
|
|
const std = @import("std");
|
|
const ini = @import("zigini");
|
|
const Save = @import("Save.zig");
|
|
const enums = @import("../enums.zig");
|
|
|
|
const color_properties = [_][]const u8{
|
|
"bg",
|
|
"border_fg",
|
|
"cmatrix_fg",
|
|
"colormix_col1",
|
|
"colormix_col2",
|
|
"colormix_col3",
|
|
"error_bg",
|
|
"error_fg",
|
|
"fg",
|
|
};
|
|
const removed_properties = [_][]const u8{
|
|
"wayland_specifier",
|
|
"max_desktop_len",
|
|
"max_login_len",
|
|
"max_password_len",
|
|
"mcookie_cmd",
|
|
"term_reset_cmd",
|
|
"term_restore_cursor_cmd",
|
|
"x_cmd_setup",
|
|
"wayland_cmd",
|
|
"console_dev",
|
|
};
|
|
|
|
var temporary_allocator = std.heap.page_allocator;
|
|
var buffer = std.mem.zeroes([10 * color_properties.len]u8);
|
|
|
|
pub var maybe_animate: ?bool = null;
|
|
pub var maybe_save_file: ?[]const u8 = null;
|
|
|
|
pub var mapped_config_fields = false;
|
|
|
|
pub fn configFieldHandler(_: std.mem.Allocator, field: ini.IniField) ?ini.IniField {
|
|
if (std.mem.eql(u8, field.key, "animate")) {
|
|
// The option doesn't exist anymore, but we save its value for "animation"
|
|
maybe_animate = std.mem.eql(u8, field.value, "true");
|
|
|
|
mapped_config_fields = true;
|
|
return null;
|
|
}
|
|
|
|
if (std.mem.eql(u8, field.key, "animation")) {
|
|
// The option now uses a string (which then gets converted into an enum) instead of an integer
|
|
// It also combines the previous "animate" and "animation" options
|
|
const animation = std.fmt.parseInt(u8, field.value, 10) catch return field;
|
|
var mapped_field = field;
|
|
|
|
mapped_field.value = switch (animation) {
|
|
0 => "doom",
|
|
1 => "matrix",
|
|
else => "none",
|
|
};
|
|
|
|
mapped_config_fields = true;
|
|
return mapped_field;
|
|
}
|
|
|
|
inline for (color_properties) |property| {
|
|
if (std.mem.eql(u8, field.key, property)) {
|
|
// These options now uses a 32-bit RGB value instead of an arbitrary 16-bit integer
|
|
const color = std.fmt.parseInt(u16, field.value, 0) catch return field;
|
|
var mapped_field = field;
|
|
|
|
mapped_field.value = mapColor(color) catch return field;
|
|
mapped_config_fields = true;
|
|
return mapped_field;
|
|
}
|
|
}
|
|
|
|
if (std.mem.eql(u8, field.key, "blank_password")) {
|
|
// The option has simply been renamed
|
|
var mapped_field = field;
|
|
mapped_field.key = "clear_password";
|
|
|
|
mapped_config_fields = true;
|
|
return mapped_field;
|
|
}
|
|
|
|
if (std.mem.eql(u8, field.key, "default_input")) {
|
|
// The option now uses a string (which then gets converted into an enum) instead of an integer
|
|
const default_input = std.fmt.parseInt(u8, field.value, 10) catch return field;
|
|
var mapped_field = field;
|
|
|
|
mapped_field.value = switch (default_input) {
|
|
0 => "session",
|
|
1 => "login",
|
|
2 => "password",
|
|
else => "login",
|
|
};
|
|
|
|
mapped_config_fields = true;
|
|
return mapped_field;
|
|
}
|
|
|
|
if (std.mem.eql(u8, field.key, "save_file")) {
|
|
// The option doesn't exist anymore, but we save its value for migration later on
|
|
maybe_save_file = temporary_allocator.dupe(u8, field.value) catch return null;
|
|
|
|
mapped_config_fields = true;
|
|
return null;
|
|
}
|
|
|
|
inline for (removed_properties) |property| {
|
|
if (std.mem.eql(u8, field.key, property)) {
|
|
// The options don't exist anymore
|
|
mapped_config_fields = true;
|
|
return null;
|
|
}
|
|
}
|
|
|
|
if (std.mem.eql(u8, field.key, "bigclock")) {
|
|
// The option now uses a string (which then gets converted into an enum) instead of an boolean
|
|
// It also includes the ability to change active bigclock's language
|
|
var mapped_field = field;
|
|
|
|
if (std.mem.eql(u8, field.value, "true")) {
|
|
mapped_field.value = "en";
|
|
mapped_config_fields = true;
|
|
} else if (std.mem.eql(u8, field.value, "false")) {
|
|
mapped_field.value = "none";
|
|
mapped_config_fields = true;
|
|
}
|
|
|
|
return mapped_field;
|
|
}
|
|
|
|
return field;
|
|
}
|
|
|
|
// This is the stuff we only handle after reading the config.
|
|
// For example, the "animate" field could come after "animation"
|
|
pub fn lateConfigFieldHandler(animation: *enums.Animation) void {
|
|
if (maybe_animate) |animate| {
|
|
if (!animate) animation.* = .none;
|
|
}
|
|
}
|
|
|
|
pub fn tryMigrateSaveFile(user_buf: *[32]u8) Save {
|
|
var save = Save{};
|
|
|
|
if (maybe_save_file) |path| {
|
|
defer temporary_allocator.free(path);
|
|
|
|
var file = std.fs.openFileAbsolute(path, .{}) catch return save;
|
|
defer file.close();
|
|
|
|
const reader = file.reader();
|
|
|
|
var user_fbs = std.io.fixedBufferStream(user_buf);
|
|
reader.streamUntilDelimiter(user_fbs.writer(), '\n', user_buf.len) catch return save;
|
|
const user = user_fbs.getWritten();
|
|
if (user.len > 0) save.user = user;
|
|
|
|
var session_buf: [20]u8 = undefined;
|
|
var session_fbs = std.io.fixedBufferStream(&session_buf);
|
|
reader.streamUntilDelimiter(session_fbs.writer(), '\n', session_buf.len) catch return save;
|
|
|
|
const session_index_str = session_fbs.getWritten();
|
|
var session_index: ?usize = null;
|
|
if (session_index_str.len > 0) {
|
|
session_index = std.fmt.parseUnsigned(usize, session_index_str, 10) catch return save;
|
|
}
|
|
save.session_index = session_index;
|
|
}
|
|
|
|
return save;
|
|
}
|
|
|
|
fn mapColor(color: u16) ![]const u8 {
|
|
const color_no_styling = color & 0x00FF;
|
|
const styling_only = color & 0xFF00;
|
|
|
|
// If color is "greater" than TB_WHITE, or the styling is "greater" than TB_DIM,
|
|
// we have an invalid color, so return an error
|
|
if (color_no_styling > 0x0008 or styling_only > 0x8000) return error.InvalidColor;
|
|
|
|
var new_color: u32 = switch (color_no_styling) {
|
|
0x0000 => 0x00000000, // Default
|
|
0x0001 => 0x20000000, // "Hi-black" styling
|
|
0x0002 => 0x00FF0000, // Red
|
|
0x0003 => 0x0000FF00, // Green
|
|
0x0004 => 0x00FFFF00, // Yellow
|
|
0x0005 => 0x000000FF, // Blue
|
|
0x0006 => 0x00FF00FF, // Magenta
|
|
0x0007 => 0x0000FFFF, // Cyan
|
|
0x0008 => 0x00FFFFFF, // White
|
|
else => unreachable,
|
|
};
|
|
|
|
// Only applying styling if color isn't black and styling isn't also black
|
|
if (!(new_color == 0x20000000 and styling_only == 0x20000000)) {
|
|
// Shift styling by 16 to the left to apply it to the new 32-bit color
|
|
new_color |= @as(u32, @intCast(styling_only)) << 16;
|
|
}
|
|
|
|
return try std.fmt.bufPrint(&buffer, "0x{X}", .{new_color});
|
|
}
|