Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
10daa9982b |
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "ming-wm"
|
||||
version = "1.2.0"
|
||||
version = "1.2.1"
|
||||
repository = "https://github.com/stjet/ming-wm"
|
||||
license = "GPL-3.0-or-later"
|
||||
edition = "2021"
|
||||
|
||||
BIN
bmps/arhants1440x842.bmp
Normal file
BIN
bmps/arhants1440x842.bmp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.6 MiB |
@@ -14,22 +14,28 @@ It is probably best to read a Vim tutorial for the basics. All supportd keystrok
|
||||
- `w[rite]`
|
||||
- `/<query>`
|
||||
|
||||
Tab completion is supported for the `<file>` argument.
|
||||
Tab completion is supported for the `<file>` argument. Down arrow will clear the current command, and up arrow will fill in the last ran command.
|
||||
|
||||
### Supported in Normal Mode
|
||||
|
||||
- `:`
|
||||
- `i`
|
||||
- `o`, `O`
|
||||
- `A`
|
||||
- `r`
|
||||
- `dd`
|
||||
- `dw`
|
||||
- `<number>dd`
|
||||
- `dw` (`dw` is not identical to vim's behaviour), `dW`
|
||||
- `d$`
|
||||
- `G`
|
||||
- `gg`
|
||||
- `<number>gg`
|
||||
- `f<char>`
|
||||
- `F<char>`
|
||||
- `f<char>`, `F<char>`
|
||||
- `<number>f<char>`, `<number>F<char>`
|
||||
- `;` (same as `f<char>` but with the char the cursor is on, so not the same as vim)
|
||||
- `<num>;`
|
||||
- `,` (same as `F<char>` but with the char the cursor is on, so not the same as vim)
|
||||
- `<num>,`
|
||||
- `x`
|
||||
- `h` (or left arrow), `j` (or down arrow), `k` (or up arrow), `l` (or right arrow)
|
||||
- `<num>h`, `<num>j` (or down arrow), `<num>k` (or up arrow), `<num>l`
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "ming-wm-lib"
|
||||
version = "0.2.1"
|
||||
version = "0.2.2"
|
||||
repository = "https://github.com/stjet/ming-wm"
|
||||
description = "library for building windows for ming-wm in rust"
|
||||
readme = "README.md"
|
||||
|
||||
107
ming-wm-lib/src/fonts.rs
Normal file
107
ming-wm-lib/src/fonts.rs
Normal file
@@ -0,0 +1,107 @@
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::dirs;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct FontCharInfo {
|
||||
pub c: char,
|
||||
pub data: Vec<Vec<u8>>,
|
||||
pub top_offset: u8,
|
||||
pub height: usize,
|
||||
pub width: usize,
|
||||
}
|
||||
|
||||
fn get_font_char(dir: &str, c: char) -> Option<FontCharInfo> {
|
||||
let c = if c == '/' { '𐘋' } else if c == '\\' { '𐚆' } else if c == '.' { '𐘅' } else { c };
|
||||
if let Ok(mut file) = File::open(dir.to_string() + "/" + &c.to_string() + ".alpha") {
|
||||
let mut ch: Vec<Vec<u8>> = Vec::new();
|
||||
let mut contents = String::new();
|
||||
file.read_to_string(&mut contents).unwrap();
|
||||
let lines: Vec<&str> = contents.split("\n").collect();
|
||||
for ln in 1..lines.len() {
|
||||
//.unwrap_or(0) is important because zeroes are just empty
|
||||
ch.push(lines[ln].replace(":", ",,,,").replace(";", ",,,").replace(".", ",,").split(",").map(|n| n.parse().unwrap_or(0)).collect());
|
||||
}
|
||||
return Some(FontCharInfo {
|
||||
c,
|
||||
top_offset: lines[0].parse().unwrap(),
|
||||
height: lines.len() - 1,
|
||||
width: ch[0].len(),
|
||||
data: ch,
|
||||
});
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn get_font_char_from_fonts(fonts: &[String], c: char) -> FontCharInfo {
|
||||
for font in fonts {
|
||||
let p = dirs::exe_dir(Some(&("ming_bmps/".to_string() + &font))).to_string_lossy().to_string();
|
||||
if let Some(font_char) = get_font_char(&p, c) {
|
||||
return font_char;
|
||||
}
|
||||
}
|
||||
let p = dirs::exe_dir(Some(&("ming_bmps/".to_string() + &fonts[0]))).to_string_lossy().to_string();
|
||||
//so a ? char should be in every font. otherwise will just return blank
|
||||
get_font_char(&p, '?').unwrap_or(FontCharInfo {
|
||||
c: '?',
|
||||
data: vec![vec![0]],
|
||||
top_offset: 0,
|
||||
height: 1,
|
||||
width: 1,
|
||||
})
|
||||
}
|
||||
|
||||
pub struct MeasureInfo {
|
||||
pub height: usize,
|
||||
pub width: usize,
|
||||
}
|
||||
|
||||
/// Doesn't take into account `horiz_spacing`, which defaults to 1 per character
|
||||
pub fn measure_text(fonts: &[String], text: String) -> MeasureInfo {
|
||||
let mut height = 0;
|
||||
let mut width = 0;
|
||||
for c in text.chars() {
|
||||
let i = get_font_char_from_fonts(fonts, c);
|
||||
let c_height = i.top_offset as usize + i.height;
|
||||
if c_height > height {
|
||||
height = c_height;
|
||||
}
|
||||
width += i.width;
|
||||
}
|
||||
MeasureInfo {
|
||||
height,
|
||||
width,
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct CachedFontCharGetter {
|
||||
cache: HashMap<char, FontCharInfo>,
|
||||
cache_size: usize, //# of items cached
|
||||
pub max_cache_size: usize,
|
||||
}
|
||||
|
||||
impl CachedFontCharGetter {
|
||||
pub fn new(max_cache_size: usize) -> Self {
|
||||
let mut s: Self = Default::default();
|
||||
s.max_cache_size = max_cache_size;
|
||||
s
|
||||
}
|
||||
|
||||
pub fn get(&mut self, fonts: &[String], c: char) -> FontCharInfo {
|
||||
if let Some(cached) = self.cache.get(&c) {
|
||||
cached.clone()
|
||||
} else {
|
||||
let got = get_font_char_from_fonts(fonts, c);
|
||||
if self.cache_size == self.max_cache_size {
|
||||
self.cache_size = 0;
|
||||
self.cache = HashMap::new();
|
||||
}
|
||||
self.cache.insert(c, got.clone());
|
||||
self.cache_size += 1;
|
||||
got
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ pub mod serialize;
|
||||
pub mod messages;
|
||||
pub mod ipc;
|
||||
pub mod components;
|
||||
pub mod fonts;
|
||||
pub mod dirs;
|
||||
pub mod utils;
|
||||
pub mod logging;
|
||||
|
||||
@@ -223,3 +223,4 @@ pub fn get_all_files(dir: PathBuf) -> Vec<PathBuf> {
|
||||
}
|
||||
files
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ use ming_wm_lib::window_manager_types::{ DrawInstructions, WindowLike, WindowLik
|
||||
use ming_wm_lib::messages::{ WindowMessage, WindowMessageResponse, WindowManagerRequest, ShortcutType };
|
||||
use ming_wm_lib::framebuffer_types::Dimensions;
|
||||
use ming_wm_lib::themes::ThemeInfo;
|
||||
use ming_wm_lib::fonts::measure_text;
|
||||
use ming_wm_lib::utils::{ concat_paths, random_u32, get_all_files, path_autocomplete, format_seconds, Substring };
|
||||
use ming_wm_lib::dirs::home;
|
||||
use ming_wm_lib::ipc::listen;
|
||||
@@ -150,11 +151,15 @@ impl WindowLike for AudioPlayer {
|
||||
let queue = &internal_locked.queue;
|
||||
let current = &queue[queue.len() - sink_len];
|
||||
let current_name = current.0.file_name().unwrap().to_string_lossy().into_owned();
|
||||
instructions.push(DrawInstructions::Text([self.dimensions[0] / 2 - current_name.len() * MONO_WIDTH as usize / 2, 2], vec!["nimbus-romono".to_string(), "shippori-mincho".to_string()], current_name.clone(), theme_info.text, theme_info.background, Some(0), Some(MONO_WIDTH)));
|
||||
let fonts = ["nimbus-roman".to_string(), "shippori-mincho".to_string()];
|
||||
let cn_width = measure_text(&fonts, current_name.clone()).width;
|
||||
instructions.push(DrawInstructions::Text([self.dimensions[0] / 2 - cn_width / 2, 2], fonts.to_vec(), current_name.clone(), theme_info.text, theme_info.background, Some(0), None));
|
||||
if let Some(artist) = ¤t.2 {
|
||||
let artist_string = "by ".to_string() + &artist;
|
||||
instructions.push(DrawInstructions::Text([self.dimensions[0] / 2 - artist_string.len() * MONO_WIDTH as usize / 2, LINE_HEIGHT + 2], vec!["nimbus-romono".to_string()], artist_string, theme_info.text, theme_info.background, Some(0), Some(MONO_WIDTH)));
|
||||
let as_width = measure_text(&fonts, artist_string.clone()).width;
|
||||
instructions.push(DrawInstructions::Text([self.dimensions[0] / 2 - as_width / 2, LINE_HEIGHT + 2], fonts.to_vec(), artist_string, theme_info.text, theme_info.background, Some(0), None));
|
||||
}
|
||||
//in this case no chance of mincho so MONO_WIDTH method of calculating width is ok
|
||||
let time_string = format!("{}/{}", format_seconds(internal_locked.sink.get_pos().as_secs()), format_seconds(current.1));
|
||||
instructions.push(DrawInstructions::Text([self.dimensions[0] / 2 - time_string.len() * MONO_WIDTH as usize / 2, LINE_HEIGHT * 2 + 2], vec!["nimbus-romono".to_string()], time_string, theme_info.text, theme_info.background, Some(0), Some(MONO_WIDTH)));
|
||||
} else {
|
||||
|
||||
@@ -19,6 +19,8 @@ const LINE_HEIGHT: usize = 18;
|
||||
const PADDING: usize = 2;
|
||||
const BAND_HEIGHT: usize = 19;
|
||||
|
||||
const WORD_END: [char; 8] = ['.', ',', ':', '[', ']', '{', '}', ' '];
|
||||
|
||||
struct FileInfo {
|
||||
pub name: String,
|
||||
pub path: String,
|
||||
@@ -43,6 +45,12 @@ enum State {
|
||||
//
|
||||
}
|
||||
|
||||
impl State {
|
||||
fn is_numberable(&self) -> bool {
|
||||
*self == State::Maybeg || *self == State::Find || *self == State::BackFind
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, PartialEq)]
|
||||
enum Mode {
|
||||
#[default]
|
||||
@@ -77,6 +85,7 @@ struct Malvim {
|
||||
state: State,
|
||||
mode: Mode,
|
||||
command: Option<String>,
|
||||
prev_command: Option<String>,
|
||||
bottom_message: Option<String>,
|
||||
maybe_num: Option<usize>,
|
||||
files: Vec<FileInfo>,
|
||||
@@ -178,7 +187,7 @@ impl WindowLike for Malvim {
|
||||
}
|
||||
let new_length = current_file.content[current_file.line_pos].chars().count();
|
||||
current_file.cursor_pos = Malvim::calc_new_cursor_pos(current_file.cursor_pos, new_length);
|
||||
} else if key_press.key == 'w' || key_press.key == '$' {
|
||||
} else if key_press.key == 'w' || key_press.key == 'W' || key_press.key == '$' {
|
||||
let line = ¤t_file.content[current_file.line_pos];
|
||||
let line_len = line.chars().count();
|
||||
if line_len > 0 && current_file.cursor_pos < line_len {
|
||||
@@ -186,11 +195,19 @@ impl WindowLike for Malvim {
|
||||
let mut line_chars = line.chars().skip(current_file.cursor_pos).peekable();
|
||||
//deref is Copy
|
||||
let current_char = *line_chars.peek().unwrap();
|
||||
let offset = if key_press.key == 'w' {
|
||||
line_chars.position(|c| if current_char == ' ' {
|
||||
c != ' '
|
||||
let offset = if key_press.key == 'W' || key_press.key == 'w' {
|
||||
line_chars.position(|c| if key_press.key == 'w' {
|
||||
if WORD_END.contains(¤t_char) {
|
||||
c != current_char
|
||||
} else {
|
||||
WORD_END.contains(&c)
|
||||
}
|
||||
} else {
|
||||
c == ' '
|
||||
if current_char == ' ' {
|
||||
c != ' '
|
||||
} else {
|
||||
c == ' '
|
||||
}
|
||||
}).unwrap_or(line_len - current_file.cursor_pos)
|
||||
} else {
|
||||
line_chars.count()
|
||||
@@ -212,33 +229,41 @@ impl WindowLike for Malvim {
|
||||
}
|
||||
changed = false;
|
||||
self.state = State::None;
|
||||
} else if self.state == State::Find || self.state == State::BackFind {
|
||||
let old_pos = current_file.cursor_pos;
|
||||
let find_pos = if self.state == State::Find {
|
||||
if old_pos < current_file.content[current_file.line_pos].chars().count() {
|
||||
let found_index = current_file.content[current_file.line_pos].chars().skip(old_pos + 1).position(|c| c == key_press.key);
|
||||
if let Some(found_index) = found_index {
|
||||
old_pos + found_index + 1
|
||||
} else {
|
||||
old_pos
|
||||
}
|
||||
} else {
|
||||
old_pos
|
||||
}
|
||||
} else if self.state == State::Find || self.state == State::BackFind || key_press.key == ';' || key_press.key == ',' {
|
||||
let mut old_pos = current_file.cursor_pos;
|
||||
let find_char = if self.state == State::Find || self.state == State::BackFind {
|
||||
key_press.key
|
||||
} else {
|
||||
//how does this work again? no idea
|
||||
if old_pos != 0 {
|
||||
let found_index = current_file.content[current_file.line_pos].chars().rev().skip(current_length - old_pos).position(|c| c == key_press.key);
|
||||
if let Some(found_index) = found_index {
|
||||
old_pos - found_index - 1
|
||||
current_file.content[current_file.line_pos].chars().nth(old_pos).unwrap()
|
||||
};
|
||||
for _ in 0..self.maybe_num.unwrap_or(1) {
|
||||
let find_pos = if self.state == State::Find || key_press.key == ';' {
|
||||
if old_pos < current_file.content[current_file.line_pos].chars().count() {
|
||||
let found_index = current_file.content[current_file.line_pos].chars().skip(old_pos + 1).position(|c| c == find_char);
|
||||
if let Some(found_index) = found_index {
|
||||
old_pos + found_index + 1
|
||||
} else {
|
||||
old_pos
|
||||
}
|
||||
} else {
|
||||
old_pos
|
||||
}
|
||||
} else {
|
||||
old_pos //0
|
||||
}
|
||||
};
|
||||
current_file.cursor_pos = find_pos;
|
||||
//how does this work again? no idea
|
||||
if old_pos != 0 {
|
||||
let found_index = current_file.content[current_file.line_pos].chars().rev().skip(current_length - old_pos).position(|c| c == find_char);
|
||||
if let Some(found_index) = found_index {
|
||||
old_pos - found_index - 1
|
||||
} else {
|
||||
old_pos
|
||||
}
|
||||
} else {
|
||||
old_pos //0
|
||||
}
|
||||
};
|
||||
current_file.cursor_pos = find_pos;
|
||||
old_pos = current_file.cursor_pos;
|
||||
}
|
||||
changed = false;
|
||||
self.state = State::None;
|
||||
} else if key_press.key == 'x' {
|
||||
@@ -394,7 +419,7 @@ impl WindowLike for Malvim {
|
||||
changed = false;
|
||||
}
|
||||
//reset maybe_num if not num
|
||||
if !numbered && self.state != State::Maybeg && self.state != State::MaybeDelete {
|
||||
if !numbered && !self.state.is_numberable() {
|
||||
self.maybe_num = None;
|
||||
}
|
||||
} else if self.mode == Mode::Command {
|
||||
@@ -402,7 +427,8 @@ impl WindowLike for Malvim {
|
||||
let command = self.command.clone().unwrap_or("".to_string());
|
||||
if key_press.is_enter() {
|
||||
new = self.process_command();
|
||||
self.command = None;
|
||||
self.prev_command = self.command.take();
|
||||
//line above does same as `self.command = None`
|
||||
self.mode = Mode::Normal;
|
||||
} else if key_press.key == '\t' { //tab
|
||||
let mut parts = command.split(" ").skip(1);
|
||||
@@ -425,6 +451,12 @@ impl WindowLike for Malvim {
|
||||
if command.len() > 0 {
|
||||
self.command = Some(command.remove_last());
|
||||
}
|
||||
} else if key_press.is_arrow() {
|
||||
if key_press.is_up_arrow() {
|
||||
self.command = self.prev_command.clone();
|
||||
} else if key_press.is_down_arrow() {
|
||||
self.command = Some(String::new());
|
||||
}
|
||||
} else {
|
||||
self.command = Some(command.to_string() + &key_press.key.to_string());
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ use ming_wm_lib::window_manager_types::{ DrawInstructions, WindowLike, WindowLik
|
||||
use ming_wm_lib::messages::{ WindowMessage, WindowMessageResponse, WindowManagerRequest, ShortcutType, InfoType, WindowsVec };
|
||||
use ming_wm_lib::framebuffer_types::Dimensions;
|
||||
use ming_wm_lib::themes::ThemeInfo;
|
||||
use ming_wm_lib::fonts::measure_text;
|
||||
use ming_wm_lib::components::Component;
|
||||
use ming_wm_lib::components::toggle_button::ToggleButton;
|
||||
|
||||
@@ -78,7 +79,25 @@ impl WindowLike for Taskbar {
|
||||
break;
|
||||
}
|
||||
let info = &self.windows_in_workspace[wi];
|
||||
let name = &info.1;
|
||||
let max_text_width = META_WIDTH - PADDING * 2;
|
||||
//horiz_spacing is by default 1 per char, which measure_text doesn't take into account
|
||||
let to_measure = info.1.clone();
|
||||
let to_measure_len = to_measure.chars().count();
|
||||
let name = if measure_text(&["nimbus-roman".to_string()], to_measure).width + to_measure_len > max_text_width {
|
||||
let mut current = String::new();
|
||||
for c in info.1.chars() {
|
||||
//horiz_spacing is 1 by default
|
||||
let to_measure = current.clone() + &c.to_string() + "...";
|
||||
let to_measure_len = to_measure.chars().count();
|
||||
if measure_text(&["nimbus-roman".to_string()], to_measure).width + to_measure_len > max_text_width {
|
||||
break;
|
||||
}
|
||||
current += &c.to_string();
|
||||
}
|
||||
current + "..."
|
||||
} else {
|
||||
info.1.clone()
|
||||
};
|
||||
let mut b = ToggleButton::new(name.to_string() + "-window", [PADDING * 2 + 44 + (META_WIDTH + PADDING) * wi, PADDING], [META_WIDTH, self.dimensions[1] - (PADDING * 2)], name.to_string(), TaskbarMessage::Nothing, TaskbarMessage::Nothing);
|
||||
b.inverted = info.0 == self.focused_id;
|
||||
instructions.extend(b.draw(theme_info));
|
||||
@@ -123,5 +142,3 @@ impl Taskbar {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -4,9 +4,7 @@ use std::vec::Vec;
|
||||
use bmp_rust::bmp::BMP;
|
||||
|
||||
use ming_wm_lib::framebuffer_types::*;
|
||||
use crate::fs::get_font_char_from_fonts;
|
||||
|
||||
type FontChar = (char, Vec<Vec<u8>>, u8);
|
||||
use ming_wm_lib::fonts::{ CachedFontCharGetter, FontCharInfo };
|
||||
|
||||
fn color_with_alpha(color: RGBColor, bg_color: RGBColor, alpha: u8) -> RGBColor {
|
||||
/*let factor: f32 = alpha as f32 / 255.0;
|
||||
@@ -47,6 +45,7 @@ pub struct FramebufferInfo {
|
||||
//currently doesn't check if writing onto next line accidentally
|
||||
pub struct FramebufferWriter {
|
||||
info: FramebufferInfo,
|
||||
fc_getter: CachedFontCharGetter,
|
||||
buffer: Vec<u8>,
|
||||
saved_buffer: Option<Vec<u8>>,
|
||||
rotate_buffer: Option<Vec<u8>>,
|
||||
@@ -57,6 +56,7 @@ impl FramebufferWriter {
|
||||
pub fn new(grayscale: bool) -> Self {
|
||||
Self {
|
||||
info: Default::default(),
|
||||
fc_getter: CachedFontCharGetter::new(128), //an arbitrary high-ish number for max cache size
|
||||
buffer: Vec::new(),
|
||||
saved_buffer: None,
|
||||
rotate_buffer: None,
|
||||
@@ -128,12 +128,11 @@ impl FramebufferWriter {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw_char(&mut self, top_left: Point, char_info: &FontChar, color: RGBColor, bg_color: RGBColor) {
|
||||
pub fn draw_char(&mut self, top_left: Point, char_info: &FontCharInfo, color: RGBColor, bg_color: RGBColor) {
|
||||
let mut start_pos;
|
||||
for row in 0..char_info.1.len() {
|
||||
//char_info.2 is vertical offset
|
||||
start_pos = ((top_left[1] + row + char_info.2 as usize) * self.info.stride + top_left[0]) * self.info.bytes_per_pixel;
|
||||
for col in &char_info.1[row] {
|
||||
for row in 0..char_info.height {
|
||||
start_pos = ((top_left[1] + row + char_info.top_offset as usize) * self.info.stride + top_left[0]) * self.info.bytes_per_pixel;
|
||||
for col in &char_info.data[row] {
|
||||
if col > &0 {
|
||||
if start_pos + 3 < self.info.byte_len {
|
||||
self._draw_pixel(start_pos, color_with_alpha(color, bg_color, *col));
|
||||
@@ -226,8 +225,8 @@ impl FramebufferWriter {
|
||||
if c == ' ' {
|
||||
top_left[0] += mono_width.unwrap_or(5) as usize;
|
||||
} else {
|
||||
let char_info = get_font_char_from_fonts(&fonts, c);
|
||||
let char_width = char_info.1[0].len();
|
||||
let char_info = self.fc_getter.get(&fonts, c);
|
||||
let char_width = char_info.width;
|
||||
let add_after: usize;
|
||||
if let Some(mono_width) = mono_width {
|
||||
let mono_width = mono_width as usize;
|
||||
|
||||
31
wm/src/fs.rs
31
wm/src/fs.rs
@@ -1,38 +1,9 @@
|
||||
use std::fs::{ read_dir, File };
|
||||
use std::io::Read;
|
||||
use std::fs::read_dir;
|
||||
use std::collections::HashMap;
|
||||
|
||||
use ming_wm_lib::dirs;
|
||||
use ming_wm_lib::utils::get_rest_of_split;
|
||||
|
||||
fn get_font_char(dir: &str, c: char) -> Option<(char, Vec<Vec<u8>>, u8)> {
|
||||
let c = if c == '/' { '𐘋' } else if c == '\\' { '𐚆' } else if c == '.' { '𐘅' } else { c };
|
||||
if let Ok(mut file) = File::open(dir.to_string() + "/" + &c.to_string() + ".alpha") {
|
||||
let mut ch: Vec<Vec<u8>> = Vec::new();
|
||||
let mut contents = String::new();
|
||||
file.read_to_string(&mut contents).unwrap();
|
||||
let lines: Vec<&str> = contents.split("\n").collect();
|
||||
for ln in 1..lines.len() {
|
||||
//.unwrap_or(0) is important because zeroes are just empty
|
||||
ch.push(lines[ln].replace(":", ",,,,").replace(";", ",,,").replace(".", ",,").split(",").map(|n| n.parse().unwrap_or(0)).collect());
|
||||
}
|
||||
return Some((c, ch, lines[0].parse().unwrap()));
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn get_font_char_from_fonts(fonts: &[String], c: char) -> (char, Vec<Vec<u8>>, u8) {
|
||||
for font in fonts {
|
||||
let p = dirs::exe_dir(Some(&("ming_bmps/".to_string() + &font))).to_string_lossy().to_string();
|
||||
if let Some(font_char) = get_font_char(&p, c) {
|
||||
return font_char;
|
||||
}
|
||||
}
|
||||
let p = dirs::exe_dir(Some(&("ming_bmps/".to_string() + &fonts[0]))).to_string_lossy().to_string();
|
||||
//so a ? char should be in every font. otherwise will just return blank
|
||||
get_font_char(&p, '?').unwrap_or(('?', vec![vec![0]], 0))
|
||||
}
|
||||
|
||||
//Category, Vec<Display name, file name>
|
||||
pub type ExeWindowInfos = HashMap<String, Vec<(String, String)>>;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user