From 4311b424c85e9a15be9d68bfaefe3005901ea412 Mon Sep 17 00:00:00 2001 From: stjet <49297268+stjet@users.noreply.github.com> Date: Thu, 17 Oct 2024 23:49:27 +0000 Subject: [PATCH] improve window render, malvim draft, fixes --- bmps/times-new-roman/#1.bmp | Bin 0 -> 362 bytes bmps/times-new-roman/%1.bmp | Bin 0 -> 582 bytes bmps/times-new-roman/&1.bmp | Bin 0 -> 538 bytes bmps/times-new-roman/'0.bmp | Bin 0 -> 70 bytes bmps/times-new-roman/+2.bmp | Bin 0 -> 310 bytes bmps/times-new-roman/;1.bmp | Bin 0 -> 186 bytes bmps/times-new-roman/<2.bmp | Bin 0 -> 278 bytes bmps/times-new-roman/>2.bmp | Bin 0 -> 278 bytes bmps/times-new-roman/@0.bmp | Bin 0 -> 782 bytes bmps/times-new-roman/[0.bmp | Bin 0 -> 294 bytes bmps/times-new-roman/]0.bmp | Bin 0 -> 294 bytes bmps/times-new-roman/^0.bmp | Bin 0 -> 194 bytes bmps/times-new-roman/_9.bmp | Bin 0 -> 166 bytes bmps/times-new-roman/`0.bmp | Bin 0 -> 78 bytes bmps/times-new-roman/|0.bmp | Bin 0 -> 110 bytes bmps/times-new-roman/~5.bmp | Bin 0 -> 126 bytes bmps/times-new-romono/!0.bmp | Bin 0 -> 150 bytes "bmps/times-new-romono/\"0.bmp" | Bin 0 -> 154 bytes bmps/times-new-romono/#1.bmp | Bin 0 -> 362 bytes bmps/times-new-romono/$2.bmp | Bin 0 -> 446 bytes bmps/times-new-romono/%1.bmp | Bin 0 -> 582 bytes bmps/times-new-romono/&1.bmp | Bin 0 -> 538 bytes bmps/times-new-romono/'0.bmp | Bin 0 -> 70 bytes bmps/times-new-romono/(0.bmp | Bin 0 -> 374 bytes bmps/times-new-romono/)0.bmp | Bin 0 -> 374 bytes bmps/times-new-romono/*0.bmp | Bin 0 -> 222 bytes bmps/times-new-romono/+2.bmp | Bin 0 -> 310 bytes bmps/times-new-romono/,9.bmp | Bin 0 -> 114 bytes bmps/times-new-romono/-8.bmp | Bin 0 -> 70 bytes bmps/times-new-romono/.9.bmp | Bin 0 -> 70 bytes bmps/times-new-romono/00.bmp | Bin 0 -> 390 bytes bmps/times-new-romono/10.bmp | Bin 0 -> 330 bytes bmps/times-new-romono/20.bmp | Bin 0 -> 522 bytes bmps/times-new-romono/30.bmp | Bin 0 -> 426 bytes bmps/times-new-romono/40.bmp | Bin 0 -> 522 bytes bmps/times-new-romono/50.bmp | Bin 0 -> 474 bytes bmps/times-new-romono/60.bmp | Bin 0 -> 474 bytes bmps/times-new-romono/70.bmp | Bin 0 -> 474 bytes bmps/times-new-romono/80.bmp | Bin 0 -> 474 bytes bmps/times-new-romono/90.bmp | Bin 0 -> 474 bytes bmps/times-new-romono/:4.bmp | Bin 0 -> 118 bytes bmps/times-new-romono/;1.bmp | Bin 0 -> 186 bytes bmps/times-new-romono/<2.bmp | Bin 0 -> 278 bytes bmps/times-new-romono/>2.bmp | Bin 0 -> 278 bytes bmps/times-new-romono/?0.bmp | Bin 0 -> 342 bytes bmps/times-new-romono/@0.bmp | Bin 0 -> 782 bytes bmps/times-new-romono/A0.bmp | Bin 0 -> 534 bytes bmps/times-new-romono/B1.bmp | Bin 0 -> 494 bytes bmps/times-new-romono/C0.bmp | Bin 0 -> 534 bytes bmps/times-new-romono/D1.bmp | Bin 0 -> 494 bytes bmps/times-new-romono/E1.bmp | Bin 0 -> 494 bytes bmps/times-new-romono/F1.bmp | Bin 0 -> 450 bytes bmps/times-new-romono/G0.bmp | Bin 0 -> 534 bytes bmps/times-new-romono/H1.bmp | Bin 0 -> 494 bytes bmps/times-new-romono/I1.bmp | Bin 0 -> 274 bytes bmps/times-new-romono/J0.bmp | Bin 0 -> 342 bytes bmps/times-new-romono/K1.bmp | Bin 0 -> 494 bytes bmps/times-new-romono/L1.bmp | Bin 0 -> 494 bytes bmps/times-new-romono/M1.bmp | Bin 0 -> 494 bytes bmps/times-new-romono/N0.bmp | Bin 0 -> 534 bytes bmps/times-new-romono/O0.bmp | Bin 0 -> 534 bytes bmps/times-new-romono/P1.bmp | Bin 0 -> 450 bytes bmps/times-new-romono/Q0.bmp | Bin 0 -> 654 bytes bmps/times-new-romono/R1.bmp | Bin 0 -> 494 bytes bmps/times-new-romono/S0.bmp | Bin 0 -> 438 bytes bmps/times-new-romono/T1.bmp | Bin 0 -> 494 bytes bmps/times-new-romono/U0.bmp | Bin 0 -> 534 bytes bmps/times-new-romono/V0.bmp | Bin 0 -> 534 bytes bmps/times-new-romono/W0.bmp | Bin 0 -> 534 bytes bmps/times-new-romono/X1.bmp | Bin 0 -> 494 bytes bmps/times-new-romono/Y1.bmp | Bin 0 -> 494 bytes bmps/times-new-romono/Z1.bmp | Bin 0 -> 494 bytes bmps/times-new-romono/[0.bmp | Bin 0 -> 294 bytes bmps/times-new-romono/]0.bmp | Bin 0 -> 294 bytes bmps/times-new-romono/^0.bmp | Bin 0 -> 194 bytes bmps/times-new-romono/_9.bmp | Bin 0 -> 166 bytes bmps/times-new-romono/`0.bmp | Bin 0 -> 78 bytes bmps/times-new-romono/a4.bmp | Bin 0 -> 362 bytes bmps/times-new-romono/b0.bmp | Bin 0 -> 522 bytes bmps/times-new-romono/c4.bmp | Bin 0 -> 330 bytes bmps/times-new-romono/d0.bmp | Bin 0 -> 522 bytes bmps/times-new-romono/e4.bmp | Bin 0 -> 362 bytes bmps/times-new-romono/f0.bmp | Bin 0 -> 474 bytes bmps/times-new-romono/g4.bmp | Bin 0 -> 522 bytes bmps/times-new-romono/h0.bmp | Bin 0 -> 522 bytes bmps/times-new-romono/i0.bmp | Bin 0 -> 330 bytes bmps/times-new-romono/j2.bmp | Bin 0 -> 458 bytes bmps/times-new-romono/k0.bmp | Bin 0 -> 570 bytes bmps/times-new-romono/l0.bmp | Bin 0 -> 330 bytes bmps/times-new-romono/m4.bmp | Bin 0 -> 374 bytes bmps/times-new-romono/n4.bmp | Bin 0 -> 394 bytes bmps/times-new-romono/o4.bmp | Bin 0 -> 362 bytes bmps/times-new-romono/p4.bmp | Bin 0 -> 522 bytes bmps/times-new-romono/q4.bmp | Bin 0 -> 522 bytes bmps/times-new-romono/r4.bmp | Bin 0 -> 330 bytes bmps/times-new-romono/s4.bmp | Bin 0 -> 298 bytes bmps/times-new-romono/t2.bmp | Bin 0 -> 338 bytes bmps/times-new-romono/u4.bmp | Bin 0 -> 426 bytes bmps/times-new-romono/v4.bmp | Bin 0 -> 394 bytes bmps/times-new-romono/w4.bmp | Bin 0 -> 522 bytes bmps/times-new-romono/x4.bmp | Bin 0 -> 394 bytes bmps/times-new-romono/y4.bmp | Bin 0 -> 490 bytes bmps/times-new-romono/z4.bmp | Bin 0 -> 362 bytes bmps/times-new-romono/{0.bmp | Bin 0 -> 374 bytes bmps/times-new-romono/|0.bmp | Bin 0 -> 110 bytes bmps/times-new-romono/}0.bmp | Bin 0 -> 374 bytes bmps/times-new-romono/~5.bmp | Bin 0 -> 126 bytes bmps/times-new-romono/█1.bmp | Bin 0 -> 618 bytes bmps/times-new-romono/𐘋0.bmp | Bin 0 -> 294 bytes src/components/highlight_button.rs | 4 +- src/components/toggle_button.rs | 2 +- src/framebuffer.rs | 33 ++- src/fs.rs | 1 - src/keyboard.rs | 1 + src/main.rs | 2 + src/messages.rs | 1 + src/themes.rs | 6 +- src/utils.rs | 28 ++ src/window_likes/lock_screen.rs | 10 +- src/window_likes/malvim.rs | 354 ++++++++++++++++++++++++ src/window_likes/minesweeper.rs | 46 +-- src/window_likes/mod.rs | 1 + src/window_likes/start_menu.rs | 2 + src/window_likes/terminal.rs | 16 +- src/window_likes/workspace_indicator.rs | 4 +- src/window_manager.rs | 53 +++- 126 files changed, 487 insertions(+), 77 deletions(-) create mode 100644 bmps/times-new-roman/#1.bmp create mode 100644 bmps/times-new-roman/%1.bmp create mode 100644 bmps/times-new-roman/&1.bmp create mode 100644 bmps/times-new-roman/'0.bmp create mode 100644 bmps/times-new-roman/+2.bmp create mode 100644 bmps/times-new-roman/;1.bmp create mode 100644 bmps/times-new-roman/<2.bmp create mode 100644 bmps/times-new-roman/>2.bmp create mode 100644 bmps/times-new-roman/@0.bmp create mode 100644 bmps/times-new-roman/[0.bmp create mode 100644 bmps/times-new-roman/]0.bmp create mode 100644 bmps/times-new-roman/^0.bmp create mode 100644 bmps/times-new-roman/_9.bmp create mode 100644 bmps/times-new-roman/`0.bmp create mode 100644 bmps/times-new-roman/|0.bmp create mode 100644 bmps/times-new-roman/~5.bmp create mode 100644 bmps/times-new-romono/!0.bmp create mode 100644 "bmps/times-new-romono/\"0.bmp" create mode 100644 bmps/times-new-romono/#1.bmp create mode 100644 bmps/times-new-romono/$2.bmp create mode 100644 bmps/times-new-romono/%1.bmp create mode 100644 bmps/times-new-romono/&1.bmp create mode 100644 bmps/times-new-romono/'0.bmp create mode 100644 bmps/times-new-romono/(0.bmp create mode 100644 bmps/times-new-romono/)0.bmp create mode 100644 bmps/times-new-romono/*0.bmp create mode 100644 bmps/times-new-romono/+2.bmp create mode 100644 bmps/times-new-romono/,9.bmp create mode 100644 bmps/times-new-romono/-8.bmp create mode 100644 bmps/times-new-romono/.9.bmp create mode 100644 bmps/times-new-romono/00.bmp create mode 100644 bmps/times-new-romono/10.bmp create mode 100644 bmps/times-new-romono/20.bmp create mode 100644 bmps/times-new-romono/30.bmp create mode 100644 bmps/times-new-romono/40.bmp create mode 100644 bmps/times-new-romono/50.bmp create mode 100644 bmps/times-new-romono/60.bmp create mode 100644 bmps/times-new-romono/70.bmp create mode 100644 bmps/times-new-romono/80.bmp create mode 100644 bmps/times-new-romono/90.bmp create mode 100644 bmps/times-new-romono/:4.bmp create mode 100644 bmps/times-new-romono/;1.bmp create mode 100644 bmps/times-new-romono/<2.bmp create mode 100644 bmps/times-new-romono/>2.bmp create mode 100644 bmps/times-new-romono/?0.bmp create mode 100644 bmps/times-new-romono/@0.bmp create mode 100644 bmps/times-new-romono/A0.bmp create mode 100644 bmps/times-new-romono/B1.bmp create mode 100644 bmps/times-new-romono/C0.bmp create mode 100644 bmps/times-new-romono/D1.bmp create mode 100644 bmps/times-new-romono/E1.bmp create mode 100644 bmps/times-new-romono/F1.bmp create mode 100644 bmps/times-new-romono/G0.bmp create mode 100644 bmps/times-new-romono/H1.bmp create mode 100644 bmps/times-new-romono/I1.bmp create mode 100644 bmps/times-new-romono/J0.bmp create mode 100644 bmps/times-new-romono/K1.bmp create mode 100644 bmps/times-new-romono/L1.bmp create mode 100644 bmps/times-new-romono/M1.bmp create mode 100644 bmps/times-new-romono/N0.bmp create mode 100644 bmps/times-new-romono/O0.bmp create mode 100644 bmps/times-new-romono/P1.bmp create mode 100644 bmps/times-new-romono/Q0.bmp create mode 100644 bmps/times-new-romono/R1.bmp create mode 100644 bmps/times-new-romono/S0.bmp create mode 100644 bmps/times-new-romono/T1.bmp create mode 100644 bmps/times-new-romono/U0.bmp create mode 100644 bmps/times-new-romono/V0.bmp create mode 100644 bmps/times-new-romono/W0.bmp create mode 100644 bmps/times-new-romono/X1.bmp create mode 100644 bmps/times-new-romono/Y1.bmp create mode 100644 bmps/times-new-romono/Z1.bmp create mode 100644 bmps/times-new-romono/[0.bmp create mode 100644 bmps/times-new-romono/]0.bmp create mode 100644 bmps/times-new-romono/^0.bmp create mode 100644 bmps/times-new-romono/_9.bmp create mode 100644 bmps/times-new-romono/`0.bmp create mode 100644 bmps/times-new-romono/a4.bmp create mode 100644 bmps/times-new-romono/b0.bmp create mode 100644 bmps/times-new-romono/c4.bmp create mode 100644 bmps/times-new-romono/d0.bmp create mode 100644 bmps/times-new-romono/e4.bmp create mode 100644 bmps/times-new-romono/f0.bmp create mode 100644 bmps/times-new-romono/g4.bmp create mode 100644 bmps/times-new-romono/h0.bmp create mode 100644 bmps/times-new-romono/i0.bmp create mode 100644 bmps/times-new-romono/j2.bmp create mode 100644 bmps/times-new-romono/k0.bmp create mode 100644 bmps/times-new-romono/l0.bmp create mode 100644 bmps/times-new-romono/m4.bmp create mode 100644 bmps/times-new-romono/n4.bmp create mode 100644 bmps/times-new-romono/o4.bmp create mode 100644 bmps/times-new-romono/p4.bmp create mode 100644 bmps/times-new-romono/q4.bmp create mode 100644 bmps/times-new-romono/r4.bmp create mode 100644 bmps/times-new-romono/s4.bmp create mode 100644 bmps/times-new-romono/t2.bmp create mode 100644 bmps/times-new-romono/u4.bmp create mode 100644 bmps/times-new-romono/v4.bmp create mode 100644 bmps/times-new-romono/w4.bmp create mode 100644 bmps/times-new-romono/x4.bmp create mode 100644 bmps/times-new-romono/y4.bmp create mode 100644 bmps/times-new-romono/z4.bmp create mode 100644 bmps/times-new-romono/{0.bmp create mode 100644 bmps/times-new-romono/|0.bmp create mode 100644 bmps/times-new-romono/}0.bmp create mode 100644 bmps/times-new-romono/~5.bmp create mode 100644 bmps/times-new-romono/█1.bmp create mode 100644 bmps/times-new-romono/𐘋0.bmp create mode 100644 src/utils.rs create mode 100644 src/window_likes/malvim.rs diff --git a/bmps/times-new-roman/#1.bmp b/bmps/times-new-roman/#1.bmp new file mode 100644 index 0000000000000000000000000000000000000000..c4bebdb12e65f74a4c72b95aba5a4cd0f3a77d72 GIT binary patch literal 362 zcmZvWy9&ZU5Jfi@3i=bG2zG+6HlPR=S_&3I%78x*#LmuE?0kT~BmUERX1U-L2F~W( z+)O63^*#&fnsWA`0WHWvn=^#5`V@Z023^J&?a2^IbLB4iD6iue*V)(ZF5jG2bRV$0 z@peAKUoZ#rGwjT@r@(W0ju-L{zJe2&58xsHwb-Id(bdk4Jdx{^Fm Hx4^ewcz0Vt literal 0 HcmV?d00001 diff --git a/bmps/times-new-roman/%1.bmp b/bmps/times-new-roman/%1.bmp new file mode 100644 index 0000000000000000000000000000000000000000..76f5b1a43d408283607257be2b602f7bd693c9c7 GIT binary patch literal 582 zcmZ9KKTE@45QmedTS_roi3lP=i|*ZY5Nro=sY40{1?iAMaBy|$8rO^tp;JFYC%=Mp zaBy&uLTN|onm!lqASCd-?{mMq{3X|S{f1K>J=QL?zz5ekW_6qc?U#ivMNx=(kb^IE z6|xt2hdEqW504dZHOuO8s? yE^cjpM|Pz%U-+Z-@c|@O>&${|1Wnk&X{|5M8(D^*!3-pSwcK_x`9*T@B-;Z!Ey2J5 literal 0 HcmV?d00001 diff --git a/bmps/times-new-roman/&1.bmp b/bmps/times-new-roman/&1.bmp new file mode 100644 index 0000000000000000000000000000000000000000..c01ebf16721087e1585028a9405c28cc931c2d10 GIT binary patch literal 538 zcmZwDF-t;G6u|NOLR{342NAqM6beLKeGx>14o-rbegSC^!O<_!P|$~vTB<<=7a>}+ zDO`jGvB9A^NOO?q|HygpxOCxn@44q3&bz#F%{wsr<+JCJP>#tG8MAcuhrOMUc)KEy*LCv&9lR)l$- zlOy+u0*)Zx`9KUURIL6CxqFPUg|Bm5;yIF5e~R267C6)1Cb7I{gksoF+|Yc9^9Jp( mW}no$Sn53acT>1_pVrT*eIu^-H)8LRf;|NsAIfMKAB9}s)N_~U!@Brd6AXWlmb0EG1 m#P5I@BzYN#qkwoK5UaxU5K9B~qyzDFAa(@eY9Rgs!~p=+wKd)V literal 0 HcmV?d00001 diff --git a/bmps/times-new-roman/<2.bmp b/bmps/times-new-roman/<2.bmp new file mode 100644 index 0000000000000000000000000000000000000000..286c6c40a93c8ece420eff3d683dbfa5b36bbd25 GIT binary patch literal 278 zcmZ?r6=P%o12Z700mK|Y%nrni3<^M!f#Cs|L?!J^O%SYk-&=Ssca&io^6z1hQL!SOzACP6OpsfVc^W WrvWj@PDXS!AU+Uq0&yY`&jkQHZd_de literal 0 HcmV?d00001 diff --git a/bmps/times-new-roman/>2.bmp b/bmps/times-new-roman/>2.bmp new file mode 100644 index 0000000000000000000000000000000000000000..3b5f7da44e06792090fef6c108266a1e3e9eda9c GIT binary patch literal 278 zcmZ?r6=P%o12Z700mK|Y%nrni3<^M!f#Cs|#2{t^MG}FS^Z)<<4A?MG&KQWhfOrBB zYhhCZ5(5G;AT9%9keQ)C%z{lVP@D^hR|D}rWO*Q83W)1~co`6b^fLo7$X6~v3^KD9 Th?UUvECGte12G4(IE)Pd!hT<1 literal 0 HcmV?d00001 diff --git a/bmps/times-new-roman/@0.bmp b/bmps/times-new-roman/@0.bmp new file mode 100644 index 0000000000000000000000000000000000000000..c4850c8bf41b189515bae77a9b2db05e7f09f6ea GIT binary patch literal 782 zcmZwF&nrYx7{>8?hazJpNf}X$l@!Hd$dtzHD3T}&DMq6#DUJLpJMv>|Z7GY{U}Y~0 zJ9e`44=Aha`%LetGn!kUd!F|_=brA|Ir-^iT~N6)-20F~5@FE8JqSKxm7(euMN!}| zk;f5su!j>IVh*8Or;)1>rS6LG z2CVKT@8Sjt>%Ehoae)!Mp$Pq+edvo!;m+2F0fVx-WA&XzO9eb*EdVm TnA7>#!ZtRr4xIyOcI*ED97XjO literal 0 HcmV?d00001 diff --git a/bmps/times-new-roman/[0.bmp b/bmps/times-new-roman/[0.bmp new file mode 100644 index 0000000000000000000000000000000000000000..a815fb186858f06f4769f63860a2dddbbc96f99d GIT binary patch literal 294 zcmZ?rRbylT12Z700mLjo%n!tj3<^M!f#Cy~#323yMUDgUawrDzWB>pE&j7+eFdXh(#&j7b={~4%_0Wg_FaR2}S literal 0 HcmV?d00001 diff --git a/bmps/times-new-roman/`0.bmp b/bmps/times-new-roman/`0.bmp new file mode 100644 index 0000000000000000000000000000000000000000..dbbd47b16e437be438ff2431392178de38dbf00d GIT binary patch literal 78 ycmZ?r^<#hlGa#h_#7scU48)8K3P6&9K>|#o6951I2MJ^Vu`&=Z1>(&>Tm}HW^9IlW literal 0 HcmV?d00001 diff --git a/bmps/times-new-roman/|0.bmp b/bmps/times-new-roman/|0.bmp new file mode 100644 index 0000000000000000000000000000000000000000..365983d0553067866a315211062331be803eb4d9 GIT binary patch literal 110 kcmZ?r&0~N7Ga#h_#Ed}92c{K(Bm;v5n8YCF0Yym00GZATXaE2J literal 0 HcmV?d00001 diff --git a/bmps/times-new-roman/~5.bmp b/bmps/times-new-roman/~5.bmp new file mode 100644 index 0000000000000000000000000000000000000000..742ea5749a696e9da0d8e0f5b3d5c3d30745a10f GIT binary patch literal 126 zcmZ?rtz&=yGa#h_#GF9P1jLLC3P6&9!2?WU5Y_+x|7QSUAP@%PI3QjR#Jhob5fJ+T Wu|E*62I74{ycCE-ftVjjUnu~0$`noj literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/!0.bmp b/bmps/times-new-romono/!0.bmp new file mode 100644 index 0000000000000000000000000000000000000000..1a31840dda263a7da3dc8853a148198873e836cf GIT binary patch literal 150 zcmZX|!3{t_6olc&SrKkjpa6GjaHkO4fcqYn9z;Y$9}-Q7)AKKGCi!NP$%{_jWK4<> n5dw*6k?QGREj%LzSXC8|B%hM?YBXqJ;Lu~mh8+h^T$nN4|AiHu literal 0 HcmV?d00001 diff --git "a/bmps/times-new-romono/\"0.bmp" "b/bmps/times-new-romono/\"0.bmp" new file mode 100644 index 0000000000000000000000000000000000000000..45b4972e6bf4e3b571c10b20a6013c3cdc8ba672 GIT binary patch literal 154 zcmZ?roy7nFWb-Id(bdk4Jdx{^Fm Hx4^ewcz0Vt literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/$2.bmp b/bmps/times-new-romono/$2.bmp new file mode 100644 index 0000000000000000000000000000000000000000..b8c3b7cdec5b98f51f48fa1cc817498bd628f18a GIT binary patch literal 446 zcmZwDp$|b(6vy!^VKW62iLxM=V7e-rqA7yn4=}UW1!g9h3H|`nY>Fgkib>KF6yf=v zw{y(Q+dlXH-Z}T(_wK9JcM%s}CB_1xNFw6$jLr?UAKvH?1c5V@Jj*h3wXnn#N6b*w zo=+}n_Q+|R(ZI;|A%}Z1_aObupPoGLTm5U#CiNFq)+5W2ZjcW=Af@Zeg9c9u7&vRGq)EhgBbV(%u)zgoy_wKtcU BiS7UZ literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/%1.bmp b/bmps/times-new-romono/%1.bmp new file mode 100644 index 0000000000000000000000000000000000000000..76f5b1a43d408283607257be2b602f7bd693c9c7 GIT binary patch literal 582 zcmZ9KKTE@45QmedTS_roi3lP=i|*ZY5Nro=sY40{1?iAMaBy|$8rO^tp;JFYC%=Mp zaBy&uLTN|onm!lqASCd-?{mMq{3X|S{f1K>J=QL?zz5ekW_6qc?U#ivMNx=(kb^IE z6|xt2hdEqW504dZHOuO8s? yE^cjpM|Pz%U-+Z-@c|@O>&${|1Wnk&X{|5M8(D^*!3-pSwcK_x`9*T@B-;Z!Ey2J5 literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/&1.bmp b/bmps/times-new-romono/&1.bmp new file mode 100644 index 0000000000000000000000000000000000000000..c01ebf16721087e1585028a9405c28cc931c2d10 GIT binary patch literal 538 zcmZwDF-t;G6u|NOLR{342NAqM6beLKeGx>14o-rbegSC^!O<_!P|$~vTB<<=7a>}+ zDO`jGvB9A^NOO?q|HygpxOCxn@44q3&bz#F%{wsr<+JCJP>#tG8MAcuhrOMUc)KEy*LCv&9lR)l$- zlOy+u0*)Zx`9KUURIL6CxqFPUg|Bm5;yIF5e~R267C6)1Cb7I{gksoF+|Yc9^9Jp( mW}no$Sn53acT>1_pVrT*eIu^-H)8LMsSR3K&n zi2;EY5MKad9wasUf&5Y=z8jDaQmla_HXF$Q48)8`VmE;ND= F1OSr>|e6S^|m$Jcr-`w6OFTf|WP15sQF@BIFPjqV4)-adDY} zH#6Vc{FaNglTc&&05a%;lRjN!@;eXV-&s_}+mQ8n;hUKqxIv-UP;EHCG`VL> I&STd31py9?mH+?% literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/*0.bmp b/bmps/times-new-romono/*0.bmp new file mode 100644 index 0000000000000000000000000000000000000000..05f21b49ac1ac4843bcc149a5168f380c7cdec7c GIT binary patch literal 222 zcmZ?ry~h9nWg)crhFR literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/+2.bmp b/bmps/times-new-romono/+2.bmp new file mode 100644 index 0000000000000000000000000000000000000000..2edb95fb6a1bf15987d723e7e9cc55fd25b09a9f GIT binary patch literal 310 zcmZ?rHDhD|12Z700mK|o%*dbsWB~zG9>Rf;|NsAIfMKAB9}s)N_~I3P6&9!3IoX5ZOQxumAu5Gk`D2M`|z T;@d#{6^LH|@j4*>0L1YCZ(I(% literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/-8.bmp b/bmps/times-new-romono/-8.bmp new file mode 100644 index 0000000000000000000000000000000000000000..6631a2247ac635e165558f6160900c68cb24031b GIT binary patch literal 70 kcmZ?rbz^`4Ga#h_#4JF}2*wIPl7T@0OkxoKfg*4W0CS@SW&i*H literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/.9.bmp b/bmps/times-new-romono/.9.bmp new file mode 100644 index 0000000000000000000000000000000000000000..665aada1aeac235496181bd520e74f9828294716 GIT binary patch literal 70 ocmZ?rbz^`4Ga#h_#7t1k$e;jZF)#>#Neto$P~n+a literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/00.bmp b/bmps/times-new-romono/00.bmp new file mode 100644 index 0000000000000000000000000000000000000000..d8958fef017bec837bb7c39d6082962fd9e22e55 GIT binary patch literal 390 zcmXZWKMO%o7{~E*{YlA2G0Dgq@B$1rrMM}Z7hv!bq%1bwfyICYg~eYS4+v@P@hvaD%@5P@Y uPQF3zIAem1c46`r2drS@4xjcd@&`4ULEdOBb1G#q%mc)X37d>ui=GYAQKAyGcZ69i2vWoJ*c?h&{vIw z9de=yt*;p!jE#jG($dr%($d%#%$&(-!*!imC8pm9rW-_q>_GzoK>igVehk2X5IuCA4n$v@l_-~E0CQJ#LGeM0RU95V!HqU literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/20.bmp b/bmps/times-new-romono/20.bmp new file mode 100644 index 0000000000000000000000000000000000000000..ba52be3881444f35863192ee4e39bf0bce216a1c GIT binary patch literal 522 zcmZwCze@sf7{~GN<&X4G2qYQ=GYC;fjV1?iX>t)v1P7OH4_AqEXlbZTa1a_?goa$S zweTNkYHkh(hvw`3cs_6(eereAj}KpuYc%ZxvpWwwhe#j=%j8Xj>RQIUq_DV~nEAia8tTW6U#@bQi8Tci~Dl#~{4dnXHQq t4soh`t?aHLA9jHolr@ved4)7*$lw!q=wkuN7J7%igcY{<#v@Xa{{b}nsUrXY literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/30.bmp b/bmps/times-new-romono/30.bmp new file mode 100644 index 0000000000000000000000000000000000000000..605f7981e01af2f76fe61a6d92b0a828f954ef56 GIT binary patch literal 426 zcmZ?rUB$=%23Yts?m@*3hrVhg z?2r>xXnoD-U~DYhkd~(Ake0@_VCGCt8?NijDlz>=Fx?=U1(^e3Zv;}`fp|X<&je!q z|NnuOFfe2Su{o5@4rH$ZVr>u~83V=afp{IV7*vlVQ2Zqp@jjsV2dEm5bF_gN6byfW zcsW#@56G?t;`cy&2#AG|%>nYQfjAvm48{hEKLBD)AT~l01KIN$hzo!?6o`v~*c6Co X0Wrw4E+Dl)PzuB^f%rKPSAxUFa%mc)X3n;0=8%@gwqWK=P8+W4%qlVcMljtVngy8yWdHyF9|c2|0BvE& zMwbKeNtFkxzl(4h-20NEffptujnPXppa zeC`9vF9TvVAjZ%S)h7y++YH2+ehn`K1G!M}pMe2_K>Yts?m@*3hrVhg z?2r>xXnoD-U~DYhkd~(Ake0@_VCGCt8?NijDlz>=Fx?=U1(^e3_XDYqK>P-Xw*s-p z|Ns9PKo|%X0&yh}a{)0(YZeeU!{pIvpxhiFc10J5nw0{STY*Ck6b#4E<$z*JKn!x* zB4jxr-v@{v1MxQ?)&ydAAl?APATf}`zW{MC)LscF{{oQi0Ad+5v-*HyCdgtiHc%X- VcQ+81BVi*X`Cgzn$UYc81OSi{oYw#V literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/60.bmp b/bmps/times-new-romono/60.bmp new file mode 100644 index 0000000000000000000000000000000000000000..8bb175e8905b1e9e9fed7d87684c465789f3bb80 GIT binary patch literal 474 zcmaLTF-QVY9LMo@Sc<7rv^1oHq>CszxHQNixG0K4Q-jkjjt(srw-o3ifrKvNR-jXp ztN2nMas)aEtsFOxcYi literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/70.bmp b/bmps/times-new-romono/70.bmp new file mode 100644 index 0000000000000000000000000000000000000000..3ab4e732a3b0d2b6bf4d3c483ddd0cd06f64cff0 GIT binary patch literal 474 zcmZ?ry~W4?23+ehn`K1G!M}pMe2_K>Yts?m@*3hrVhg z?2r>xXnoD-U~DYhkd~(Ake0@_VCGCt8?NijDlz>=Fx?=U1(^e6|Ns9VjDgG&ATERP zk!hf~G7uj}7DHwOuS{NUh28y!+@e?5C0^$f{IS?BN76EYp5H|wxd?3yR;xs5;2&6$+ O35fpzF-QY4ehUEoDz+>D literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/80.bmp b/bmps/times-new-romono/80.bmp new file mode 100644 index 0000000000000000000000000000000000000000..d2a0f312d9a66894ccde4cbe579a273fe0ee29a4 GIT binary patch literal 474 zcmYk(KS)AB9Ki8=8b(r6I2sNj&DkK*ATCZpN~42IHwZN(QA5~ksG%iDMRdto-q2QK zIJER<4IG0avemWo`|I6-$NRkd{ki+`;1##Wp88)`yic)+Wq2y3qU<~LgOw1eT}G+! zk=ztZm4-i>uGb#c5~+)cSIA~peXTPEtz&~;Z)q$39!*!TH{5O67v_^NmeM(Haf~MR zA)g_iH$uc1qXbLN`uN3xtJ_|g+84%XxE^r~kNAX~d4|l7;|?VV+w7k0 z<%xgrhxXk3P4X!|kV6Z;y>n0ejik*Z#IMkJ!KIsH`#01A9AW5s#QYKUggwZNLv(S5 IKI(FI2EM9rmH+?% literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/90.bmp b/bmps/times-new-romono/90.bmp new file mode 100644 index 0000000000000000000000000000000000000000..cc6a555a2a062cfab773e69b6777abcfe6b0a4e7 GIT binary patch literal 474 zcmZ?ry~W4?23+ehn`K1G!M}pMe2_K>Yts?m@*3hrVhg z?2r>xXnoD-U~DYhkd~(Ake0@_VCGCt8?NijDlz>=Fx?=U1(^e3y923wAnpNT<^TWx zGoWLjxI7S_1!5m`IS?NR)PVRC5If_LZvx6a1!8`vdJQ1E8i@0N805acK%5Q4RzUm} zh*tu!D-ah0@f#pM48#Y3_&E@>!|VXEmjm$&ApQu%GhyOTJEj1|en92x(B#$v#qR*| sIw0;slLLuQ1Y!dqz5>J?Q1g6%?AJgn3FU*rZ7C2>2jV?ItO^nb0B;tJ5&!@I literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/:4.bmp b/bmps/times-new-romono/:4.bmp new file mode 100644 index 0000000000000000000000000000000000000000..fe835514747c105732b3730e19567fa54d8b2ddb GIT binary patch literal 118 zcmZ?rEn|QHGa#h_#7scU0mO_93P6&9!2wKS5Ql*x2Y`415YPGl|33ph3{*22h^GPZ IQ6N4E0D-L^EdT%j literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/;1.bmp b/bmps/times-new-romono/;1.bmp new file mode 100644 index 0000000000000000000000000000000000000000..9448781691f9bc86b4366f48cf48333dd5ed2be2 GIT binary patch literal 186 zcmZ?r-NgU_WU!@Brd6AXWlmb0EG1 m#P5I@BzYN#qkwoK5UaxU5K9B~qyzDFAa(@eY9Rgs!~p=+wKd)V literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/<2.bmp b/bmps/times-new-romono/<2.bmp new file mode 100644 index 0000000000000000000000000000000000000000..286c6c40a93c8ece420eff3d683dbfa5b36bbd25 GIT binary patch literal 278 zcmZ?r6=P%o12Z700mK|Y%nrni3<^M!f#Cs|L?!J^O%SYk-&=Ssca&io^6z1hQL!SOzACP6OpsfVc^W WrvWj@PDXS!AU+Uq0&yY`&jkQHZd_de literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/>2.bmp b/bmps/times-new-romono/>2.bmp new file mode 100644 index 0000000000000000000000000000000000000000..3b5f7da44e06792090fef6c108266a1e3e9eda9c GIT binary patch literal 278 zcmZ?r6=P%o12Z700mK|Y%nrni3<^M!f#Cs|#2{t^MG}FS^Z)<<4A?MG&KQWhfOrBB zYhhCZ5(5G;AT9%9keQ)C%z{lVP@D^hR|D}rWO*Q83W)1~co`6b^fLo7$X6~v3^KD9 Th?UUvECGte12G4(IE)Pd!hT<1 literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/?0.bmp b/bmps/times-new-romono/?0.bmp new file mode 100644 index 0000000000000000000000000000000000000000..cfb9e10839905952c9cd2a6ed20126b7507a1ee3 GIT binary patch literal 342 zcmZ?r4P#^g12Z700mN)T%mc)X3<^M!fk6Q(59UCL|NsAkSWG~C7Kj@`d>97uK{|E- zaS==mMgzszU~FU>DDDHqLdaquHV~)+aS*yVRBjVcP8?khC>8_6o3V(4y!IT3V}ZB@ zh`nHHfb7{od8?hazJpNf}X$l@!Hd$dtzHD3T}&DMq6#DUJLpJMv>|Z7GY{U}Y~0 zJ9e`44=Aha`%LetGn!kUd!F|_=brA|Ir-^iT~N6)-20F~5@FE8JqSKxm7(euMN!}| zk;f5su!j>IVh*8Or;)1>rS6LG z2CVKT@8Sjt>%Ehoae)!Mp$Pq+edvo!;m+2F0fVx-WA&XzO9eb*EdVm TnA7>#!ZtRr4xIyOcI*ED97XjO literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/A0.bmp b/bmps/times-new-romono/A0.bmp new file mode 100644 index 0000000000000000000000000000000000000000..3fe298fff9ffa5dd52da4dcfaa72ec93d88ebe7d GIT binary patch literal 534 zcmZvYJqp4=5QR5_fh1P{B8_hzo*M zOxOPzhbaTu;CH#_+>f(6)@VH)6FxQ8GF)Wgm=dco8$Az;@6u&^fyEI^EU?2Kp0(Bp z9v`x){Pbk%So^-_ym(IgY5Fe&3Ar4ZH}3y(oMj;Ql>3Zgxi!5BR(RlsretEds@5sa x>$u_sH*j4=QJ literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/C0.bmp b/bmps/times-new-romono/C0.bmp new file mode 100644 index 0000000000000000000000000000000000000000..b6771845ea94cac459e970cb4a814e13e734ca13 GIT binary patch literal 534 zcmZwDu?s;_6vy%VkO70j+muWe*-Qr6rThi{0T~Sz#cX4eWMQx=e}Zhx2ED;xu^2># z=X+n>I&SaQ=bn3h=hTZv(~YR$RJlt?AO%MixRvspp!{9F?< z#AR;3nfIW7N8O&8o>>P;T(C8{tmOKCTj`8bhKD{PW{-CsXUs&Fp&wy~1?HHbg~1Q~ CkJw!R literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/D1.bmp b/bmps/times-new-romono/D1.bmp new file mode 100644 index 0000000000000000000000000000000000000000..64d9457373e98d8f56d47c012f63f01f42e37629 GIT binary patch literal 494 zcma*ju@1pN7{Kwb3kfe_^aMtOM8se)605~KcnJxE#9}2XB4OesJb^UERw9JO`Cs#0 zq=V`uzw3Ry|I*f4p(pXGu$NIl5uTLTMfQ3h58tiFF~9>GOt65Dx-mu^<~dGowog_A zHw@i-&Lbo`ZTq}`qpI_-E=Ln#nbzsuf$ox_ThYBTbVs@%t>ZqAE7pIy0ge4hP3@+f a6aR&|jXTELbUB~#g#ES|w%DO#8|wp6y2NP! literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/E1.bmp b/bmps/times-new-romono/E1.bmp new file mode 100644 index 0000000000000000000000000000000000000000..41558b35789e0a0aec3ea96441c3636fb355ce62 GIT binary patch literal 494 zcmaLUJqp4=5QgE6AVN}z_KKyAt%aqXg^i%#A0EO>1abmJ5HDb36ST1N1fIjnR@ZmJ zh#S}#cy=c<9|@cEhmXKySC_So5D@~?Vl^h!d3N(#=9D*B+_A+5dtC5B$66Vi6{MKT zy^G!evF65_8@ZWp&208B$GnP?llMN4%o?F5ccdSy1N*Zex1?WFP4-hkE_V(xJybmJ i&E@or4YHBe3u^g(zFb1TjtQ=i+!^vO#11LmD1QKZ9-S5d literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/F1.bmp b/bmps/times-new-romono/F1.bmp new file mode 100644 index 0000000000000000000000000000000000000000..86622f4ebf8ca4e2bb1e3d9a4a4a698244d42ec7 GIT binary patch literal 450 zcmZ?rJ;cZW24+A~1Bf|+m>Y;085Dpd149o~9?U@y5kTevApQ@;7l1e(h`Im&|IdJo zfnvcx3{q2sERM_u%6UW8q#=tVvvH{bio@;1rUod+1;n{9vyjvr0VhXL6j0TeYrJ{u5k2jXZTJ_y7hH83}W M+`Sx#ZvycP07;ylivR!s literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/G0.bmp b/bmps/times-new-romono/G0.bmp new file mode 100644 index 0000000000000000000000000000000000000000..600e6fd4ff6c1be633d63b5de32b5bcb883a4585 GIT binary patch literal 534 zcmajcu?qoV7{~GV*sxg4WHDGQ%4#<$vt8*Xe}Q6>g@Fa7*c6LDz$&W=gR+Qk=c1lP{di((Y?sY|%PKda{@)5AK*XY;085Dpd1H%reJeY$ZVu8#TK>QVmGl7@~iqnAfcOZTS z#0mfZ{|8bGYk~L_h>eVaVi$mTIZO=5o(seWV0;)25(CL0@oAwB_z1#0JIDb0AIt02gJxivR!s literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/I1.bmp b/bmps/times-new-romono/I1.bmp new file mode 100644 index 0000000000000000000000000000000000000000..c048c29d1789d29cf4ac39eb0b4aa21ffa474a04 GIT binary patch literal 274 zcmZ?r6=Gxn12Z700mQ68%nihh3<^M!f#D9A#2_MoB1eGuKM)@U;^_bXK}?2NAO zKx_oWcY&A{DlP$Ja{#d%5Q7vt!Sq1oVdBX+#Pe{7=hInS8|wZFn7u&0EfBAQieCfL F(EyEmZW#ao literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/K1.bmp b/bmps/times-new-romono/K1.bmp new file mode 100644 index 0000000000000000000000000000000000000000..4f87b99bb223868c6270fef609d78f6766c688f6 GIT binary patch literal 494 zcmaixp$fuK6o&7DK`ml2h+-0LreU@(TLi&}5WCM|noUh2h)FEIfJL*Sf-D-H-?`l3 zVGJC6m-GMUgWa)S5P8NvK4%LGPz293IE~r5y$!!($QZ#B25}tArU_?|aD|EMcg!o9 zU9OPtaDlq&7v#`6dFCVBpq4mpXFYnk*&N>BYbWJR*?*v)c9bV~5oes`C{NxugW!)B q;^bfroh+ALe{Y$*hiclT+rTpEncHxHlIlj}7wG@dB|qQ<_P$@4NwUBI literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/L1.bmp b/bmps/times-new-romono/L1.bmp new file mode 100644 index 0000000000000000000000000000000000000000..ebf012f20084e1958d29a02b8bbce2db8ebadc22 GIT binary patch literal 494 zcmZ?reaFZE24+A~1BkhRm>Y;085Dpd1H%reJeY$ZB7w}~K>QzwUjy-OAYKE+2Z8t& z5QD^Z{{IJ245?6lGKi0if#TsnTn|+j0#z4;tOmvg$`uo-j*%F3Nao_TcMzzHg@y}8 X_#wFs6plxr>Mj6jP?(FuvW=^Q1KiZC5?6?B%)j2 zZ0^KbO!D1(&$%a)nVRid%0DG)7UGZqOJ%4^?Pc$acX1fcQ1(1eyM2g48Wx~UM|N}R z`lb`qMOT<_dKNvDp2xq#M0A1q@*_9KU%?b2@Go~{*8m%;@Rh^M!2|TyV=#hWxdHwr z@Rk|62p{i5AD|V;HPPKrZi#+EDv(Q}ccGk%-kOZ*cx$+7&FO(2I%aP=UR!p~3mnIs AjsO4v literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/N0.bmp b/bmps/times-new-romono/N0.bmp new file mode 100644 index 0000000000000000000000000000000000000000..9a731220f529d4a9f9f614ad22a39042bdc89ae0 GIT binary patch literal 534 zcmZ?r6=Pxm12Z700mNKD%mc)X3<^M!f#Crom_jGCfC4jtcr6gy{r~@;0fvEmb|CIR z;(Gx34KO~828jXjCM3QQke>nLgJ>Yo1mYh+jI7QO$WMo<1F}IrI1I!$fp{L0IJ&w_ zp!`1|b_U|<*wg{VC4u-o5YL9%k4xP;pqdvzEQm`TP%a3FL7s>}vJ2h3QlR`3Al?R3 ygTuU6KsBF%SRRi$KcGCwzCvU*Q1doG>0F>Z$gI;q%nVZpWD5du84!O0;v@hI@WELC literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/O0.bmp b/bmps/times-new-romono/O0.bmp new file mode 100644 index 0000000000000000000000000000000000000000..e4138804410a08044251d5fa990803ead375886d GIT binary patch literal 534 zcmZ9|KMR3T6vy%V7!(zplAfdh)K4C8WoaciJQNGn3?gLQQ*iHb-xW K9tN18pfewpqRyxQ literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/P1.bmp b/bmps/times-new-romono/P1.bmp new file mode 100644 index 0000000000000000000000000000000000000000..fa6370177e0c92e09e7b7ff32783e61eb9d6f05d GIT binary patch literal 450 zcmZ?rJ;cZW24+A~1Bf|+m>Y;085Dpd149o~9?U@y5kTeGKLaub zip2vlNKGoTI5Hb3=MPmAi!6@JCRGhkJsS{nBbxzYBbl=T$gTk51wi}^h}(gf15FLw zJwUlsAO;yQ0goCUsG1je)JQ?qJcFtMg&W9Ruw6i!35aJx#R`FRI1nF%@^1p^bwGR! Lhz|jAB*+W^%bJ$I literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/Q0.bmp b/bmps/times-new-romono/Q0.bmp new file mode 100644 index 0000000000000000000000000000000000000000..d4185aebdda2dafc2d82eceae530920d85f8aa86 GIT binary patch literal 654 zcmZ|IF)Kx37zglkO&DB@Nw>(Ngaw1qNG2(F@c}5Sfx#!ZC7*(%3~VT+m~0XyNr`Mk z3dir<&QrIO^VaWu&insAb*5$;ZAtS?xCiN^N+s!YC&@zIHy` z9elCM6_3#sr|ymmvVWcz`*`b4dF7L%$cs~V#s@cC7W;VT{k6G8w%;CIOj!>f1Y0qrvLx| literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/R1.bmp b/bmps/times-new-romono/R1.bmp new file mode 100644 index 0000000000000000000000000000000000000000..2189d0148e2f4ccf1093129452097c4d065e64a8 GIT binary patch literal 494 zcmaKoy$%6E6h>!Tq9YQOQlnMN_LK@Bnm&BsH}4* zGixH&BxmM+_nz!d#;@HxrB{W$1Sv>^r;6-K&CFbf&(@+mzzaH1h@yx?<>3MwXq(=M z`Y5%99Ks%QPH#ZoI=MlX?^kV4PFCzuXW-_M>IP$+tf_G;&gf%RnoZ#vEF_%~A w!xMbhCCB$O_Yn6A^M9UkPk75OFQDhXOPwqa(X}3R6L#=`DNJAmJ@Bme1`3X~h5!Hn literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/S0.bmp b/bmps/times-new-romono/S0.bmp new file mode 100644 index 0000000000000000000000000000000000000000..e10d89da208c844098e7a88488fcac82690eff97 GIT binary patch literal 438 zcmZ9|Aq&D#6o%nDMGzF5*#(1Lu-GhO5VOH72-XFI2xg02SP?7>2G_*sPf(+1F<2~u zWxi*eix&sa{XF0CGFYn{dnSDvoHgW8glBwCV`jQfhu^W{=L8Wpng_C%Bne@z2vLw( zJD>T10p!0~yR%8R#u+2q*`zDuj+gCh(zS7cygYRJD)UZz*=Y;085Dpd1H%reJeUI|{{R2a0K!0E0K~OG4C4F&;(Q?1 zg2|)PK)H`Vd<|V3oexy=0Eo|_i=*?0syd*%Es*_!%^yH98z5c`#EdYt=<0xc79d^; b#E*dZHV|(C;#ENW6^P$M*&wl}K>P#%{8sQ? literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/U0.bmp b/bmps/times-new-romono/U0.bmp new file mode 100644 index 0000000000000000000000000000000000000000..f78080127809e2469855422d53e69facf67879bb GIT binary patch literal 534 zcmc(aJqp4=5QR4?2>vt{Ha0ebklq8>if2e;E+W{92M`qxU~EJ|OA(J@V{4<<>$hPa ztc|S$-@JKmCot&`n+20skKTm})F3i#x-qvXm#=26H4Z9 zaDr-(rT90LmHF=nWQj878C>M0WDS@GevaSCOUc|HF9N^DZ{ze)o^5XbSogR=-BU}1S|zzMkiy1?Fd&%17tqGS z#z(NY;@-d%w#oUOumf`opWFS-49n$meq9aSex31bqJ%O6*Wl?~7VNjeBhPcEXxy3e zfE;Poo!SZBOkk-Kl+{hg;m>1BE$qgg+c& zjz=spM8(_{lYb<$5`5wc^65HeZbDx9xqHrX_Yn^8VCG)PBR_Y+IW@hhIj8huKiB8H lHoe5xYt*+W`7C!Y%-on<$1`@gL>uyM@=fHo%isQn*MGkyuj2p! literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/X1.bmp b/bmps/times-new-romono/X1.bmp new file mode 100644 index 0000000000000000000000000000000000000000..505b655d74c12b1b3f3ff897f2a84f5db4f3d249 GIT binary patch literal 494 zcmaLUu?qoV9LDkYj)?`6Mb2h4psdOwy89;#7A1?(e_@bC87(G*)u5DQuwXVBD4Wjr zcfD^eU9LXwJ@51WyoGxEZmHm@vKEm*5|(mUm0IcZVDnvu#3$Cs`@SzHaf~3F7Y4eo zk!O+(_ASU<-*kGmN7vLjMm}Hz`)AIknN4@174`idxrQ<0; zzTXL%KXVJtFOZ*g95qMZfL!Y8ySrpBJj*_XD|V(Q%fGTjPJhlN?;&>`QPzElyu}&b E2i#7x^8f$< literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/Y1.bmp b/bmps/times-new-romono/Y1.bmp new file mode 100644 index 0000000000000000000000000000000000000000..8c7f5610bd999cf7ddb8b9eeb63999cf5e69c364 GIT binary patch literal 494 zcmb7=p$Y;)5Qg^zgIY}{!J=IR%LThHV9-YpOeVqNI~WaOQ@CU>Trl|@CW97}pzAls z3@oz6fp2&A`-g?y!SJ5AqI#@ts6q`A*JO3>sCjYF#e44rsss~wzzxQh#dh)&>|>HPR5Zlp5{`WJj)3T5>T`V5{h`vT{y+Nb~k literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/Z1.bmp b/bmps/times-new-romono/Z1.bmp new file mode 100644 index 0000000000000000000000000000000000000000..9f2ee00e86249d3c4acaefce872e1a9d835fa417 GIT binary patch literal 494 zcmZwEF%AJi6vpw{2oVwo(4bQ&#R0Uk2hd1VZs7p*Y6=RSjz*=S)2KwHQc$4K82`7~ z7n8|M@|$_{y|YQRN0MLr~Tye-;R_Pdn`R0?k|iXuY5x0^VVA9 zBCB8_8LI~=Chm;ZKsAtIPT~1aLA8e6HvmNyXE4cs3mAgDN`~iQZ!t4M5 literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/[0.bmp b/bmps/times-new-romono/[0.bmp new file mode 100644 index 0000000000000000000000000000000000000000..a815fb186858f06f4769f63860a2dddbbc96f99d GIT binary patch literal 294 zcmZ?rRbylT12Z700mLjo%n!tj3<^M!f#Cy~#323yMUDgUawrDzWB>pE&j7+eFdXh(#&j7b={~4%_0Wg_FaR2}S literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/`0.bmp b/bmps/times-new-romono/`0.bmp new file mode 100644 index 0000000000000000000000000000000000000000..dbbd47b16e437be438ff2431392178de38dbf00d GIT binary patch literal 78 ycmZ?r^<#hlGa#h_#7scU48)8K3P6&9K>|#o6951I2MJ^Vu`&=Z1>(&>Tm}HW^9IlW literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/a4.bmp b/bmps/times-new-romono/a4.bmp new file mode 100644 index 0000000000000000000000000000000000000000..6ce75a20aea552487332a88302c61b56898d92a8 GIT binary patch literal 362 zcmZ?r&0=H#gDxOh1H|k=%mKuV37g?ui=GYAQKAyGcZ69i2vWoJ*c?h&{vIw z9de=yt*;p!jE#jG($dr%($d%#%$&(-!*!imC8pm9rW-`FAafw>cp&u-h_3^&FA&!O z@qHk62jbU2yd8+SfY=9!?*j2LAO^|Z0^+*=|Nk?9Fc547;tf!?6Oer#h;@R literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/b0.bmp b/bmps/times-new-romono/b0.bmp new file mode 100644 index 0000000000000000000000000000000000000000..7aa6910a268f25c3945a3e4416407ef396b4fe4c GIT binary patch literal 522 zcmZ?rFa%mc)X3n;0=8%@gwqWK=P8+W4%qlVcMljtVngy8yWdHvUG?0No1BjOZ z@lhb20>qPnSP~=$mEQv79|K|zC|?uEegMR>Nb;*;>Y-vF^A_NduLa7#z$4!dl>drN z9w-hB9fq?&d7d>ui=GYAQKAyGcZ69i2vWoJ*c?h&{vIw z9de=yt*;p!jE#jG($dr%($d%#%$&(-!*!imC8pm9rW-`FAaj81|NnsoGB9KU@dF@! z3dBWFu^=EDB)J8MBY=1^5XS)VQ6N4K#4I3nP_^km{yQMfgNZ@Kd4OWCf!G^a94fa5 nC>{$F2eKW2*d2&%fOs1aGeXs!1+q6l*&z8|Af64xApPFa%mc)X3n;0=8%@gwqWK=P8+W4%qlVcMljtVngy8yWdHvUG?0NI6^QQu z@e?2hIcYf%uLELNAPxs&kfNDD%mu_UKztd9?*g$Z5T60!2SCgQG7DHgV zUI3FrlHUbo-vi3`VUgbnm7fKaUxOyU1}FxTmj<$50I?iYJwK5B5+)B7GY9fPdOCo3 r0}x*UVz7QRbD5y(mtm8KsRhcd#U&3ER{-L(c;sz?a-i_t3^ES@DJ8Ij literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/e4.bmp b/bmps/times-new-romono/e4.bmp new file mode 100644 index 0000000000000000000000000000000000000000..ec694144d875372355f4b6a8f4033f8409a20726 GIT binary patch literal 362 zcmZ?r&0=H#gDxOh1H|k=%mKuV37g?ui=GYAQKAyGcZ69i2vWoJ*c?h&{vIw z9de=yt*;p!jE#jG($dr%($d%#%$&(-!*!imC8pm9rW-`FAaj81|NnsoGB7v*@lhcD z48&J}I21LB!L4Dv$<5VHdS Dli5x4 literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/f0.bmp b/bmps/times-new-romono/f0.bmp new file mode 100644 index 0000000000000000000000000000000000000000..c305bf7706538d6a8a45f803246a1e8bd36f8bb6 GIT binary patch literal 474 zcmZ?ry~W4?23+ehn`K1G!M}pMe2_K>Yts?m@*3hrVhg z?2r>xXnoD-U~DYhkd~(Ake0@_VCGCt8?NijDlz>=Fx?=U1(^e3M*^ukKnygQp#zAW z{{R2a0K-6j3lRSWVrG~aj0TF81MycFADO179MGf~}v*!Q+ literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/g4.bmp b/bmps/times-new-romono/g4.bmp new file mode 100644 index 0000000000000000000000000000000000000000..91e8dcb47037f509348975e1d3ec2cc63dd655a1 GIT binary patch literal 522 zcmYk(JxIeq6u|KpE7AsasV){uhf*z08gX(cL1;lbSa5T2$|4lRK?jE{E`sQwU_nbq zK}QwmQqbAOS=7nu=AuLTf6WE%$S?Qay&U%uzwVC6upRL}KpNw4q#!B!&=I+vh>@BW ziNufQkzZ}>hTY$}t;hUy;qc3;cwROPf>I?2#yYK5X2pF?6*o^7liAvj+DROj=-PP0 zA3o4QF^X7BE=SAQ_t_zQi`JagIGS2hyT=$p8QV literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/h0.bmp b/bmps/times-new-romono/h0.bmp new file mode 100644 index 0000000000000000000000000000000000000000..c34b689818920622eb9a00e4d0ad5bbab987e8f2 GIT binary patch literal 522 zcmZ?rFa%mc)X3n;0=8%@gwqWK=P8+W4%qlVcMljtVngy8yVaEWeFF<@9h~0qL z42TZ{G0-N4{Qv(!6vHVXo(5t=`FTM82P8g7{RAX_4v_x>iBGCL$o!{h`llfA8-Vgx zkoX|;j{|W65Gw=m2_W8rCO-iv<^aU!f%qm68zadd0rKJQhl#^zpxkL(@<4GdAby5N P-W4df8HoE}<{{Gn_PM@7 literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/i0.bmp b/bmps/times-new-romono/i0.bmp new file mode 100644 index 0000000000000000000000000000000000000000..1060f093aba2f57bfe6e6b7958daa9a747582474 GIT binary patch literal 330 zcmZ?r^#q%mc)X37d>ui=GYAQKAyGcZ69i2vWoJ*c?h&{vIw z9de=yt*;p!jE#jG($dr%($d%#%$&(-!*!imC8pm9rW-_q>_Gz|K>lkW{tm?H|NjFm zU|`q?#1}zqD1SMSe-aOW1)BUO7#~QR0r7PtzA2DB6NtCL%p*ht)y4sF2}~VS|8@`` E0EstkXaE2J literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/j2.bmp b/bmps/times-new-romono/j2.bmp new file mode 100644 index 0000000000000000000000000000000000000000..4ad08f81f3632b51709e78bde659ddb7a1f25825 GIT binary patch literal 458 zcmZ?rJ;lfX23Yts?m@*3hrVhg z?2r>xXnoD-U~DYhkd~(Ake0@_VCGCt8?NijDlz>=Fx?=U1(^e3Zw6A|fOtL-hyDK# zw19yj4~Si%>_b4d2Z#;BK>jKqUJBzw)hz;woxmb?gNkB{fp(yqw+>kh$o2)|+h}5n bKz>EIQ7l_3{Vo>qrK>j%(2KjCa5Wfdv4VXNd znhv1cA0YNdmPb+pGXEM7H=)ZTsR7v~2*hiF*a}@8Pz>xIsCsrFe+3YSA*(}H165Z6 s6x$8N^+0R@6$9xzhpZ2s4U}JxPYqB`9f&UwP~!lUUjoF((9MVO0XhBBegFUf literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/l0.bmp b/bmps/times-new-romono/l0.bmp new file mode 100644 index 0000000000000000000000000000000000000000..a41c814fb778dc29e7cd97c7ee1cfb5cdc5a1fe9 GIT binary patch literal 330 zcmZ?r^#q%mc)X37d>ui=GYAQKAyGcZ69i2vWoJ*c?h&{vIw z9de=yt*;p!jE#jG($dr%($d%#%$&(-!*!imC8pm9rW-_q>_G#;K>j-*{s_d$|NjFm sU|`q@#D_p^D1Rf6zl(<8Niq&0x}IuhRz$X)@&TR`ps02rHO)Bpeg literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/m4.bmp b/bmps/times-new-romono/m4.bmp new file mode 100644 index 0000000000000000000000000000000000000000..dc765665b8e1e001dc3cbced4f11b3df9238887c GIT binary patch literal 374 zcmb`=u?_)25XSLY6r4gK*GXtjC^c%?xKiUC)Dp$za-vr#HQvK3h(=B0A%sMsu>P~z zga>fRZ+7PP%Z{C7M*KIV_7I^8BOR*9DBSzuTNbnqOLTF>83WAl#s>PF<{HlFAq95Y zhxyK&paKol!vCCp`;)sdxAE^>oi}xF6!xy^{a(&8UWk!Gb8|Ftz#d~*JW;|F7xZz$ L6)j|VV5NILDC15o literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/n4.bmp b/bmps/times-new-romono/n4.bmp new file mode 100644 index 0000000000000000000000000000000000000000..454b97781346c04454a9cc3764c2b875d6a7e547 GIT binary patch literal 394 zcmZ?r?P6pAgDxOh1H>Fq%*dd?zzmWB%CF&tU=SAq{xdK@5QzKV$vvpJ;m}u&gdK9C z3azgh9gK~I8`9F$9MaO*7R;Q@Xnp6Ns+@u`>{x1Mx8+ z{s+Xl|NjFmWMH@i#1lbmD8CTMe~H9D3gmYo@$-TFhe&)v@*w;0=|2mU??p1N3dp|- p;sb#$5WfIokR7o=EDdFEg37x9`I~^a1Bm^A_z4g{24XXiJOG{eaV-D< literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/o4.bmp b/bmps/times-new-romono/o4.bmp new file mode 100644 index 0000000000000000000000000000000000000000..4c16844d89f4e6cc7e482332e0b485dbf01ff072 GIT binary patch literal 362 zcmZ?r&0=H#gDxOh1H|k=%mKuV37g?ui=GYAQKAyGcZ69i2vWoJ*c?h&{vIw z9de=yt*;p!jE#jG($dr%($d%#%$&(-!*!imC8pm9rW-`FAaj81|NnsoGBAVy@p&Mg z2gI|1*a0eT3uONR;xH&5Fa%mc)X3n;0=8%@gwqWK=P8+W4%qlVcMljtVngy8yVW$GA*FgLph|~Z7 z|IdJqf#O?%cn`Wbj1QDs1H@Zkd~_Nn52Ve2I0=X?kkvrtKLY7&AXWn61|Xgb#7rP{ zKmaoTG@73CK(S;b`R!=(lYsKakmOO^2b608;?H>G7XjtpL*>^4*(ZP)<{nT~y@iTd r0O{*Md=`j7ZVm?GZ9oiicnlD01MzeqUJS&xKztL3UjcC=5HkV*c8IBW literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/q4.bmp b/bmps/times-new-romono/q4.bmp new file mode 100644 index 0000000000000000000000000000000000000000..5f79f692a0d53fb02e0c7828a0639fafeda5983d GIT binary patch literal 522 zcmZ?rFa%mc)X3n;0=8%@gwqWK=P8+W4%qlVcMljtVngy8yWdHyF9|Z%2LV)-w z5Pt^ZbaZ(T9|%?e@d<2lQ27Nw`2#R{Ae#?}!-3crh(X?40K{NPwUQn}zf$R%N^7n!4)iArz?FY*J1ma3O@{fV?C3xgP_RmI>Uj`I| lxew%ikh|5Oc5?#Rw_x&6F-0JMJ`gVi;zK|@9f&u87d>ui=GYAQKAyGcZ69i2vWoJ*c?h&{vIw z9de=yt*;p!jE#jG($dr%($d%#%$&(-!*!imC8pm9rW-`FAafw>SRnNRi2nj{Ef5R+ z|Nox>gn?iM5Z{6EVKh)|2@s!!@nJL`@ufJ_uK|kR1!86-GjxIc3qbq;h>L(Y6No{< TWCz5HfcOXyTLbY^AU*&9n0aFc literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/s4.bmp b/bmps/times-new-romono/s4.bmp new file mode 100644 index 0000000000000000000000000000000000000000..5eccdbce5cda32419af96d9245614a131f34b5ea GIT binary patch literal 298 zcmZ?r)na4-gDxOh1H`OA%mKuV3{Xl935Z40nEFjhd z;uAp3@&7;2G6n{FAU+MmflxlksndY?6O?ZWWM2Sckm7bAE(PL$Kzs*?qk$OY(@#L$ g2gIyUJ?236bs&b>VGCpz12KpOsROxXJrL&r0OZv+J^%m! literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/t2.bmp b/bmps/times-new-romono/t2.bmp new file mode 100644 index 0000000000000000000000000000000000000000..4db29b7f0233f81707ac86c8a5d4e74047765dd2 GIT binary patch literal 338 zcmZ?r4Ps;fgDxOh1H`OA%mu`Z37p_ui=GYAQKAyGcZ69i2vWoJ*c?h&{vIw z9de=yt*;p!jE#jG($dr%($d%#%$&(-!*!imC8pm9rW-`FAaj81|NnsoGB8*H@e?4v z3B-0#vDrZO3n1nLVh^a;dLa88hz-L)KGnp4X7vK`A0P(V+X2L>PY!rK;;+-&e F003HsZm9qO literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/u4.bmp b/bmps/times-new-romono/u4.bmp new file mode 100644 index 0000000000000000000000000000000000000000..5c54ad1ef2b0f0fe1348b44a3e93b61aba9a4290 GIT binary patch literal 426 zcmZ?rUB$=%23Yts?m@*3hrVhg z?2r>xXnoD-U~DYhkd~(Ake0@_VCGCt8?NijDlz>=Fx?=U1(^e6|Njp(kb!{@h<5|= zCm`Mc#3Dd^0*Ds@u`N_h9+3S9h~0r$8Hhp7ehS3rfmj==W+IS%55$IHApZ&wuSVi8 z1oE%K_#hexE&%Zom>7_aOU+^u)hq{^g>KhnpcvR3Ae{)r&tYnSG#3zO1MyEF2CD%8 D#bk%m literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/v4.bmp b/bmps/times-new-romono/v4.bmp new file mode 100644 index 0000000000000000000000000000000000000000..288869cad6b699ffa056bafde87449fd7306c21a GIT binary patch literal 394 zcmZ?r?P6pAgDxOh1H>Fq%*dd?zzmWB%CF&tU=SAq{xdK@5QzKV$vvpJ;m}u&gdK9C z3azgh9gK~I8`9F$9MaO*7R;QYlFEMNDXa*g401$L#xC=wCLdEAQT7LC|0O;cD^O#3t6^C{HDbfuq!Oa*5I` zt<>_8T9?Y_SHW<8(0EJlc(>n9u~66!d_Pm4ba;Rkcn%Fq%*dd?zzmWB%CF&tU=SAq{xdK@5QzKV$vvpJ;m}u&gdK9C z3azgh9gK~I8`9F$9MaO*7R;Q|P-C28d1n{|6e*z+eHy zAA$HU5Z6J)<^tJTP__Y7t{%jPig5$QmI5(55FY{Jb3n`rlZUD?28x{k;-5gQgDeM? zR{)BC0pflva-h)K1;jUjcqI@EAgclLbATA+cyA!q0phhl%mg*J8p!?y#327z0Y;0859_pfph{;ehn`K1G!M}pMe2_K>Yts?m@*3hrVhg z?2r>xXnoD-U~DYhkd~(Ake0@_VCGCt8?NijDlz>=Fx?=U1(^e3X9B6uKs*I07cY&A*iySaS7%l{1Kq|B9J%`%m-pAm>MA44v7B&u?|$;7RatflHUd7?}G86 aYCvM3sOke^kfBF`SOqGl2xOlF;t2qK8nO-m literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/z4.bmp b/bmps/times-new-romono/z4.bmp new file mode 100644 index 0000000000000000000000000000000000000000..959bbbe6501c1c8c2b3bbb476cf8e20ac9db8fe4 GIT binary patch literal 362 zcmZ?r&0=H#gDxOh1H|k=%mKuV37g?ui=GYAQKAyGcZ69i2vWoJ*c?h&{vIw z9de=yt*;p!jE#jG($dr%($d%#%$&(-!*!imC8pm9rW-`FAafw>D?sWG5YGkTnNYk1 zNS_2^T_FAr#LfTz|7U<r|P@~k<(X?aZm literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/~5.bmp b/bmps/times-new-romono/~5.bmp new file mode 100644 index 0000000000000000000000000000000000000000..742ea5749a696e9da0d8e0f5b3d5c3d30745a10f GIT binary patch literal 126 zcmZ?rtz&=yGa#h_#GF9P1jLLC3P6&9!2?WU5Y_+x|7QSUAP@%PI3QjR#Jhob5fJ+T Wu|E*62I74{ycCE-ftVjjUnu~0$`noj literal 0 HcmV?d00001 diff --git a/bmps/times-new-romono/█1.bmp b/bmps/times-new-romono/█1.bmp new file mode 100644 index 0000000000000000000000000000000000000000..fd27b3405277f4fd8edf59a7c11af1d85042f95d GIT binary patch literal 618 zcmZ?r&0=BzgDxOh1H>Fa%n!tj35>Zpx7d0F{u6}Kyd+NaUeech?CL8*nncIk;S0;rvb%f Rk;Q?0TOck&69a|L1^^*Nb|(M; literal 0 HcmV?d00001 diff --git a/src/components/highlight_button.rs b/src/components/highlight_button.rs index 516c8fc..fca949e 100644 --- a/src/components/highlight_button.rs +++ b/src/components/highlight_button.rs @@ -38,12 +38,12 @@ impl Component for HighlightButton { vec![ //highlight background DrawInstructions::Rect(self.top_left, self.size, theme_info.top), - DrawInstructions::Text([self.top_left[0] + 4, self.top_left[1] + (self.size[1] - font_height) / 2], "times-new-roman", self.text.to_string(), theme_info.text_top, theme_info.top, None), + DrawInstructions::Text([self.top_left[0] + 4, self.top_left[1] + (self.size[1] - font_height) / 2], "times-new-roman", self.text.to_string(), theme_info.top_text, theme_info.top, None, None), ] } else { vec![ DrawInstructions::Rect(self.top_left, self.size, theme_info.background), - DrawInstructions::Text([self.top_left[0] + 4, self.top_left[1] + (self.size[1] - font_height) / 2], "times-new-roman", self.text.to_string(), theme_info.text, theme_info.background, None), + DrawInstructions::Text([self.top_left[0] + 4, self.top_left[1] + (self.size[1] - font_height) / 2], "times-new-roman", self.text.to_string(), theme_info.text, theme_info.background, None, None), ] } } diff --git a/src/components/toggle_button.rs b/src/components/toggle_button.rs index 5368df2..c519df4 100644 --- a/src/components/toggle_button.rs +++ b/src/components/toggle_button.rs @@ -54,7 +54,7 @@ impl Component for ToggleButton { //the background if self.draw_bg //DrawInstructions::Rect(), //the text (for now, hardcoded top left) - DrawInstructions::Text([self.top_left[0] + 4, self.top_left[1] + (self.size[1] - font_height) / 2], "times-new-roman", self.text.to_string(), theme_info.text, theme_info.background, None), + DrawInstructions::Text([self.top_left[0] + 4, self.top_left[1] + (self.size[1] - font_height) / 2], "times-new-roman", self.text.to_string(), theme_info.text, theme_info.background, None, None), ] } diff --git a/src/framebuffer.rs b/src/framebuffer.rs index 871ec81..e3692ad 100644 --- a/src/framebuffer.rs +++ b/src/framebuffer.rs @@ -164,27 +164,26 @@ impl FramebufferWriter { //todo, config space for c in text.chars() { if c == ' ' { - top_left[0] += 5; + top_left[0] += mono_width.unwrap_or(5) as usize; } else { - let char_info = get_font_char(&("./bmps/".to_string() + font_name), c); - if let Some(char_info) = char_info { - let char_width = char_info.1[0].len(); - let add_after: usize; - if let Some(mono_width) = mono_width { - let mono_width = mono_width as usize; - let remainder = if mono_width < char_width { - 0 - } else { - mono_width - char_width - }; + //so a ? char must be in every font + let char_info = get_font_char(&("./bmps/".to_string() + font_name), c).unwrap_or(get_font_char(&("./bmps/".to_string() + font_name), '?').unwrap()); + let char_width = char_info.1[0].len(); + let add_after: usize; + if let Some(mono_width) = mono_width { + let mono_width = mono_width as usize; + if mono_width < char_width { + add_after = mono_width; + } else { + let remainder = mono_width - char_width; top_left[0] += remainder / 2; add_after = remainder - remainder / 2 + char_width; - } else { - add_after = char_width + horiz_spacing; - } - self.draw_char(top_left, &char_info, color, bg_color); - top_left[0] += add_after; + }; + } else { + add_after = char_width + horiz_spacing; } + self.draw_char(top_left, &char_info, color, bg_color); + top_left[0] += add_after; } } } diff --git a/src/fs.rs b/src/fs.rs index 9a577b5..d91cd93 100644 --- a/src/fs.rs +++ b/src/fs.rs @@ -4,7 +4,6 @@ use bmp_rust::bmp::BMP; pub fn get_font_char(dir: &str, c: char) -> Option<(char, Vec>, u8)> { let c = if c == '/' { '𐘋' } else { c }; - let mut font: Vec<(char, Vec>, u8)> = Vec::new(); for entry in read_dir(dir).unwrap() { let path = entry.unwrap().path(); let path_chars: Vec = path.file_name().unwrap().to_str().unwrap().to_string().chars().collect(); diff --git a/src/keyboard.rs b/src/keyboard.rs index a6cb19d..1dcedb7 100644 --- a/src/keyboard.rs +++ b/src/keyboard.rs @@ -13,6 +13,7 @@ pub fn key_to_char(key: Key) -> Option { Key::Char(c) => Some(KeyChar::Press(c)), Key::Alt(c) => Some(KeyChar::Alt(c)), Key::Backspace => Some(KeyChar::Press('𐘁')), + Key::Esc => Some(KeyChar::Press('𐘃')), _ => None, } } diff --git a/src/main.rs b/src/main.rs index 5ed51ae..74c2118 100644 --- a/src/main.rs +++ b/src/main.rs @@ -18,6 +18,8 @@ mod messages; mod fs; +mod utils; + fn main() { let mut fb = Framebuffer::new("/dev/fb0").unwrap(); let bytes_per_pixel = (fb.var_screen_info.bits_per_pixel as usize) / 8; diff --git a/src/messages.rs b/src/messages.rs index 420b7cc..6db678a 100644 --- a/src/messages.rs +++ b/src/messages.rs @@ -69,6 +69,7 @@ pub enum ShortcutType { MoveWindowToEdge(Direction), CenterWindow, FullscreenWindow, + HalfWidthWindow, //half width, full height // } diff --git a/src/themes.rs b/src/themes.rs index 7ac1b99..8343fe0 100644 --- a/src/themes.rs +++ b/src/themes.rs @@ -13,9 +13,10 @@ pub struct ThemeInfo { pub border_left_top: RGBColor, pub border_right_bottom: RGBColor, pub text: RGBColor, - pub text_top: RGBColor, + pub top_text: RGBColor, pub alt_background: RGBColor, pub alt_text: RGBColor, + pub alt_secondary: RGBColor, // } @@ -26,9 +27,10 @@ const THEME_INFOS: [(Themes, ThemeInfo); 1] = [ border_left_top: [255, 255, 255], border_right_bottom: [0, 0, 0], text: [0, 0, 0], - text_top: [255, 255, 255], + top_text: [255, 255, 255], alt_background: [0, 0, 0], alt_text: [255, 255, 255], + alt_secondary: [128, 128, 128], // }), ]; diff --git a/src/utils.rs b/src/utils.rs new file mode 100644 index 0000000..805afc8 --- /dev/null +++ b/src/utils.rs @@ -0,0 +1,28 @@ + +//the tuple is first, line #, actual line +pub fn calc_actual_lines<'a>(lines: impl Iterator, max_chars_per_line: usize) -> Vec<(bool, usize, String)> { + let mut actual_lines = Vec::new(); + let mut line_num = 0; + for real_line in lines { + let mut line = real_line.to_string(); + let mut first = true; + loop { + if line.chars().count() <= max_chars_per_line { + actual_lines.push((first, line_num, line)); + break; + } else { + let mut line_chars = line.chars(); + let mut push_string = String::new(); + for _i in 0..max_chars_per_line { + push_string += &line_chars.next().unwrap().to_string(); + } + actual_lines.push((first, line_num, push_string)); + line = line_chars.collect(); + } + first = false; + } + line_num += 1; + } + actual_lines +} + diff --git a/src/window_likes/lock_screen.rs b/src/window_likes/lock_screen.rs index 76fc895..b1cca50 100644 --- a/src/window_likes/lock_screen.rs +++ b/src/window_likes/lock_screen.rs @@ -50,11 +50,11 @@ impl WindowLike for LockScreen { fn draw(&self, _theme_info: &ThemeInfo) -> Vec { vec![ DrawInstructions::Rect([0, 0], self.dimensions, [0, 0, 0]), - DrawInstructions::Text([4, 4], "times-new-roman", "The bulldozer outside the kitchen window was quite a big one.".to_string(), [255, 255, 255], [0, 0, 0], None), - DrawInstructions::Text([4, 4 + 16], "times-new-roman", "\"Yellow,\" he thought, and stomped off back to his bedroom to get dressed.".to_string(), [255, 255, 255], [0, 0, 0], None), - DrawInstructions::Text([4, 4 + 16 * 2], "times-new-roman", "He stared at it.".to_string(), [255, 255, 255], [0, 0, 0], None), - DrawInstructions::Text([4, 4 + 16 * 3], "times-new-roman", "Password: ".to_string(), [255, 255, 255], [0, 0, 0], None), - DrawInstructions::Text([77, 4 + 16 * 3], "times-new-roman", "*".repeat(self.input_password.len()), [255, 255, 255], [0, 0, 0], None), + DrawInstructions::Text([4, 4], "times-new-roman", "The bulldozer outside the kitchen window was quite a big one.".to_string(), [255, 255, 255], [0, 0, 0], None, None), + DrawInstructions::Text([4, 4 + 16], "times-new-roman", "\"Yellow,\" he thought, and stomped off back to his bedroom to get dressed.".to_string(), [255, 255, 255], [0, 0, 0], None, None), + DrawInstructions::Text([4, 4 + 16 * 2], "times-new-roman", "He stared at it.".to_string(), [255, 255, 255], [0, 0, 0], None, None), + DrawInstructions::Text([4, 4 + 16 * 3], "times-new-roman", "Password: ".to_string(), [255, 255, 255], [0, 0, 0], None, None), + DrawInstructions::Text([77, 4 + 16 * 3], "times-new-roman", "*".repeat(self.input_password.len()), [255, 255, 255], [0, 0, 0], None, None), ] } diff --git a/src/window_likes/malvim.rs b/src/window_likes/malvim.rs new file mode 100644 index 0000000..36d2dc3 --- /dev/null +++ b/src/window_likes/malvim.rs @@ -0,0 +1,354 @@ +use std::vec::Vec; +use std::vec; +use std::fmt; +use std::path::PathBuf; +use std::fs::{ read_to_string, write }; + +use crate::messages::{ WindowMessage, WindowMessageResponse }; +use crate::themes::ThemeInfo; +use crate::framebuffer::Dimensions; +use crate::window_manager::{ DrawInstructions, WindowLike, WindowLikeType }; +use crate::utils::calc_actual_lines; + +const MONO_WIDTH: u8 = 10; +const LINE_HEIGHT: usize = 18; +const PADDING: usize = 2; +const BAND_HEIGHT: usize = 18; + +struct FileInfo { + pub name: String, + pub path: String, + pub changed: bool, + pub top_line_pos: usize, + pub line_pos: usize, + pub cursor_pos: usize, + pub content: Vec, + // +} + +#[derive(Default, PartialEq)] +enum State { + #[default] + None, + // +} + +#[derive(Default, PartialEq)] +enum Mode { + #[default] + Normal, + Insert, + Command, +} + +impl fmt::Display for Mode { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + let write_str = match self { + Mode::Normal => "NORMAL", + Mode::Insert => "INSERT", + Mode::Command => "COMMAND", + }; + fmt.write_str(write_str)?; + Ok(()) + } +} + +#[derive(Default)] +struct Current { + pub actual_lines: Vec<(bool, usize, String)>, //first, line #, actual line + pub line_num_width: usize, //file line digits * MONO_WIDTH + pub max_lines: usize, //max actual lines on screen + pub max_chars_per_line: usize, +} + +#[derive(Default)] +pub struct Malvim { + dimensions: Dimensions, + state: State, + mode: Mode, + command: Option, + bottom_message: Option, + maybe_num: Option, + files: Vec, + current_file_index: usize, + current: Current, +} + +impl WindowLike for Malvim { + fn handle_message(&mut self, message: WindowMessage) -> WindowMessageResponse { + match message { + WindowMessage::Init(dimensions) => { + self.dimensions = dimensions; + WindowMessageResponse::JustRerender + }, + WindowMessage::KeyPress(key_press) => { + if key_press.key == '𐘃' { //escape key + self.mode = Mode::Normal; + self.state = State::None; + } else if key_press.key == ':' && self.mode == Mode::Normal && self.state == State::None { + self.mode = Mode::Command; + self.command = Some(String::new()); + } else if key_press.key == 'i' && self.mode == Mode::Normal && self.state == State::None && self.files.len() > 0 { + self.mode = Mode::Insert; + } else if self.mode == Mode::Insert { + let current_file = &self.files[self.current_file_index]; + if key_press.key == '𐘂' { //the enter key + // + } else if key_press.key == '𐘁' { //backspace + // + } else { + // + } + } else if self.mode == Mode::Normal && self.files.len() > 0 { + let current_file = &mut self.files[self.current_file_index]; + if key_press.key == 'h' { + current_file.cursor_pos = current_file.cursor_pos.checked_sub(1).unwrap_or(0); + } else if key_press.key == 'j' { + // + } else if key_press.key == 'k' { + // + } else if key_press.key == 'l' { + current_file.cursor_pos += 1; + if current_file.cursor_pos == current_file.content[current_file.line_pos].len() { + current_file.cursor_pos = current_file.content[current_file.line_pos].len() - 1; + } + } else if key_press.key == '0' { + current_file.cursor_pos = 0; + } else if key_press.key == '$' { + current_file.cursor_pos = current_file.content[current_file.line_pos].len().checked_sub(1).unwrap_or(0); + } + // + } else if self.mode == Mode::Command { + self.bottom_message = None; + let command = self.command.clone().unwrap_or("".to_string()); + if key_press.key == '𐘂' { //the enter key + self.process_command(); + self.command = None; + self.mode = Mode::Normal; + } else if key_press.key == '𐘁' { //backspace + if command.len() > 0 { + self.command = Some(command[..command.len() - 1].to_string()); + } + } else { + self.command = Some(command.to_string() + &key_press.key.to_string()); + } + } else { + return WindowMessageResponse::DoNothing; + } + self.calc_current(); //too over zealous but whatever + WindowMessageResponse::JustRerender + }, + WindowMessage::ChangeDimensions(dimensions) => { + self.dimensions = dimensions; + WindowMessageResponse::JustRerender + }, + _ => WindowMessageResponse::DoNothing, + } + } + + fn draw(&self, theme_info: &ThemeInfo) -> Vec { + let mut instructions = vec![ + //the top white bar + DrawInstructions::Rect([0, 0], [self.dimensions[0], BAND_HEIGHT], theme_info.alt_text), + //black background + DrawInstructions::Rect([0, BAND_HEIGHT], [self.dimensions[0], self.dimensions[1] - BAND_HEIGHT * 3], theme_info.alt_background), + //slight above bottom blue bar + DrawInstructions::Rect([0, self.dimensions[1] - BAND_HEIGHT * 2], [self.dimensions[0], BAND_HEIGHT], theme_info.top), + //black background + DrawInstructions::Rect([0, self.dimensions[1] - BAND_HEIGHT], [self.dimensions[0], BAND_HEIGHT], theme_info.alt_background), + ]; + //write file tabs + let mut used_width = 0; + for file_index in 0..self.files.len() { + let file_info = &self.files[file_index]; + let future_used_width = used_width + 4 + file_info.name.len() * MONO_WIDTH as usize; + //just cut off when too many file tabs open to fit + if future_used_width > self.dimensions[0] { + break; + } + let background = if file_index == self.current_file_index { + theme_info.alt_background + } else { + theme_info.alt_secondary + }; + instructions.extend(vec![ + DrawInstructions::Rect([used_width, 2], [file_info.name.len() * MONO_WIDTH as usize + 4, BAND_HEIGHT - 2], background), + DrawInstructions::Text([used_width + 2, 2], "times-new-romono", file_info.name.clone(), theme_info.alt_text, background, Some(0), Some(MONO_WIDTH)), + ]); + used_width = future_used_width; + } + //write the actual current file + let mut sub_line_num = 0; //a line in a file can be split into multiple lines for display + if self.files.len() > 0 { + let current_file = &self.files[self.current_file_index]; + let current = &self.current; + for line_num in current_file.top_line_pos..(current_file.top_line_pos + current.max_lines) { + if line_num == current.actual_lines.len() { + break; + } + let line = ¤t.actual_lines[line_num]; + let rel_line_num = line_num - current_file.top_line_pos; + //write line num text (if start of line) + let y0 = BAND_HEIGHT + rel_line_num * LINE_HEIGHT + PADDING; + if line.0 { + instructions.push(DrawInstructions::Text([PADDING, y0], "times-new-romono", line.1.to_string(), theme_info.alt_secondary, theme_info.alt_background, Some(0), Some(MONO_WIDTH))); + sub_line_num = 0; + } + let x1 = current.line_num_width + PADDING * 2; + //write actual line + //line.2 + instructions.push(DrawInstructions::Text([x1, y0], "times-new-romono", line.2.clone(), theme_info.alt_text, theme_info.alt_background, Some(0), Some(MONO_WIDTH))); + sub_line_num += 1; + let max = sub_line_num * current.max_chars_per_line; + let min = max - current.max_chars_per_line; + if line.1 == current_file.line_pos && current_file.cursor_pos >= min && current_file.cursor_pos < max { + let top_left = [x1 + (current_file.cursor_pos - min) * MONO_WIDTH as usize, y0]; + //the cursor is on this line, draw it + instructions.push(DrawInstructions::Rect(top_left, [MONO_WIDTH as usize, LINE_HEIGHT], theme_info.top)); + //draw the char over it + instructions.push(DrawInstructions::Text(top_left, "times-new-romono", line.2.chars().nth(current_file.cursor_pos - min).unwrap().to_string(), theme_info.top_text, theme_info.top, Some(0), Some(MONO_WIDTH))); + } + } + } + //bottom blue band stuff + //write mode + instructions.push(DrawInstructions::Text([0, self.dimensions[1] - BAND_HEIGHT * 2 + 1], "times-new-romono", self.mode.to_string(), theme_info.top_text, theme_info.top, Some(0), Some(MONO_WIDTH))); + let file_status; + if self.files.len() > 0 { + file_status = self.files[self.current_file_index].name.clone(); + } else { + file_status = "No file open".to_string(); + } + instructions.push(DrawInstructions::Text([self.dimensions[0] - file_status.len() * (MONO_WIDTH as usize), self.dimensions[1] - BAND_HEIGHT * 2 + 1], "times-new-romono", file_status, theme_info.top_text, theme_info.top, Some(0), Some(MONO_WIDTH))); + //write command or bottom message + if self.mode == Mode::Command { + instructions.push(DrawInstructions::Text([0, self.dimensions[1] - BAND_HEIGHT], "times-new-romono", ":".to_string() + &self.command.clone().unwrap_or("".to_string()), theme_info.top_text, theme_info.top, Some(0), Some(MONO_WIDTH))); + } else if self.mode == Mode::Normal && self.bottom_message.is_some() { + instructions.push(DrawInstructions::Text([0, self.dimensions[1] - BAND_HEIGHT], "times-new-romono", self.bottom_message.clone().unwrap(), theme_info.top_text, theme_info.top, Some(0), Some(MONO_WIDTH))); + } + instructions + } + + fn title(&self) -> &'static str { + "Malvim" + } + + fn subtype(&self) -> WindowLikeType { + WindowLikeType::Window + } + + fn ideal_dimensions(&self, _dimensions: Dimensions) -> Dimensions { + [410, 410] + } + + fn resizable(&self) -> bool { + true + } +} + +impl Malvim { + pub fn new() -> Self { + Default::default() + } + + fn calc_current(&mut self) { + if self.files.len() == 0 { + return; + } + let current_file = &self.files[self.current_file_index]; + let line_num_width = current_file.content.len().to_string().len() * MONO_WIDTH as usize; + let max_chars_per_line = (self.dimensions[0] - line_num_width - PADDING * 2) / MONO_WIDTH as usize; + let actual_lines = calc_actual_lines(current_file.content.iter(), max_chars_per_line); + //now, see if the line_pos is still visible from the top_line_pos, + //if not, move top_line_pos down until it is + let max_lines = (self.dimensions[1] - BAND_HEIGHT * 3 - PADDING) / LINE_HEIGHT; + if current_file.top_line_pos + max_lines < current_file.line_pos { + self.files[self.current_file_index].top_line_pos = current_file.line_pos.checked_sub(max_lines).unwrap_or(0); + } + self.current = Current { + actual_lines, + line_num_width, + max_lines, + max_chars_per_line, + }; + } + + fn process_command(&mut self) { + let mut parts = self.command.as_ref().unwrap().split(" "); + let first = parts.next().unwrap(); + let arg = parts.next().unwrap_or(""); + if first == "e" || first == "edit" || ((first == "t" || first == "tabe") && self.files.len() > 0) { + //find the file and open it + let mut failed = false; + let mut new_path = if self.files.len() > 0 { + PathBuf::from(self.files[self.current_file_index].path.clone()).parent().unwrap().to_path_buf() + } else { + PathBuf::from("/") + }; + for part in arg.split("/") { + if part == ".." { + if let Some(parent) = new_path.parent() { + new_path = parent.to_path_buf(); + } else { + failed = true; + } + } else { + new_path.push(part); + } + } + if !failed && new_path.is_file() { + let name = new_path.file_name().unwrap().to_string_lossy().into_owned(); + let path = new_path.to_string_lossy().into_owned(); + if let Ok(content) = read_to_string(new_path) { + let file_info = FileInfo { + name, + path, + changed: false, + top_line_pos: 0, + line_pos: 0, + cursor_pos: 0, + content: content.split("\n").map(|s| s.to_string()).collect(), + }; + if first == "e" || first == "edit" { + if self.files.len() > 0 { + self.files[self.current_file_index] = file_info; + } else { + self.files.push(file_info); + } + } else { + //t(abe) + self.current_file_index += 1; + if self.current_file_index == self.files.len() - 1 { + self.files.push(file_info); + } else { + self.files.insert(self.current_file_index, file_info); + } + } + } else { + self.bottom_message = Some("Failed to open that file".to_string()); + } + } else { + self.bottom_message = Some("That is not a file or does not exist".to_string()); + } + } else if self.files.len() == 0 { + self.bottom_message = Some("No files are open, so can only do :e(dit)".to_string()); + } else if first == "w" || first == "write" { + let current_file = &self.files[self.current_file_index]; + write(¤t_file.path, ¤t_file.content.join("\n")); + self.files[self.current_file_index].changed = false; + } else if first == "q" || first == "quit" { + self.files.remove(self.current_file_index); + self.current_file_index = self.current_file_index.checked_sub(1).unwrap_or(0); + } else if first == "p" || first == "tabp" { + self.current_file_index = self.current_file_index.checked_sub(1).unwrap_or(self.files.len() - 1); + } else if first == "n" || first == "tabn" { + self.current_file_index += 1; + if self.current_file_index == self.files.len() { + self.current_file_index = 0; + } + } else { + self.bottom_message = Some("Not a command".to_string()); + } + } +} + diff --git a/src/window_likes/minesweeper.rs b/src/window_likes/minesweeper.rs index 664f4f2..8e16048 100644 --- a/src/window_likes/minesweeper.rs +++ b/src/window_likes/minesweeper.rs @@ -3,7 +3,7 @@ use std::vec; use std::collections::VecDeque; use core::convert::TryFrom; -use crate::window_manager::{ DrawInstructions, WindowLike, WindowLikeType, WINDOW_TOP_HEIGHT }; +use crate::window_manager::{ DrawInstructions, WindowLike, WindowLikeType }; use crate::messages::{ WindowMessage, WindowMessageResponse }; use crate::framebuffer::Dimensions; use crate::themes::ThemeInfo; @@ -156,20 +156,20 @@ impl WindowLike for Minesweeper { fn draw(&self, theme_info: &ThemeInfo) -> Vec { if self.state == MinesweeperState::Seed { vec![ - DrawInstructions::Text([4, WINDOW_TOP_HEIGHT + 4], "times-new-roman", "Type in random characters to initalise the seed".to_string(), theme_info.text, theme_info.background, None), - DrawInstructions::Text([4, WINDOW_TOP_HEIGHT + 4 + 16], "times-new-roman", self.random_chars.clone(), theme_info.text, theme_info.background, None), + DrawInstructions::Text([4, 4], "times-new-roman", "Type in random characters to initalise the seed".to_string(), theme_info.text, theme_info.background, None, None), + DrawInstructions::Text([4, 4 + 16], "times-new-roman", self.random_chars.clone(), theme_info.text, theme_info.background, None, None), ] } else { let mut instructions = vec![ //top border - DrawInstructions::Rect([1, WINDOW_TOP_HEIGHT], [self.dimensions[0] - 7, 5], [128, 128, 128]), - DrawInstructions::Rect([self.dimensions[0] - 6, WINDOW_TOP_HEIGHT], [4, 1], [128, 128, 128]), - DrawInstructions::Rect([self.dimensions[0] - 6, WINDOW_TOP_HEIGHT + 1], [3, 1], [128, 128, 128]), - DrawInstructions::Rect([self.dimensions[0] - 6, WINDOW_TOP_HEIGHT + 2], [2, 1], [128, 128, 128]), - DrawInstructions::Rect([self.dimensions[0] - 6, WINDOW_TOP_HEIGHT + 3], [1, 1], [128, 128, 128]), - DrawInstructions::Rect([self.dimensions[0] - 6, WINDOW_TOP_HEIGHT + 4], [1, 1], [128, 128, 128]), + DrawInstructions::Rect([1, 0], [self.dimensions[0] - 7, 5], [128, 128, 128]), + DrawInstructions::Rect([self.dimensions[0] - 6, 0], [4, 1], [128, 128, 128]), + DrawInstructions::Rect([self.dimensions[0] - 6, 1], [3, 1], [128, 128, 128]), + DrawInstructions::Rect([self.dimensions[0] - 6, 2], [2, 1], [128, 128, 128]), + DrawInstructions::Rect([self.dimensions[0] - 6, 3], [1, 1], [128, 128, 128]), + DrawInstructions::Rect([self.dimensions[0] - 6, 4], [1, 1], [128, 128, 128]), //left border - DrawInstructions::Rect([1, WINDOW_TOP_HEIGHT], [5, self.dimensions[1] - WINDOW_TOP_HEIGHT - 5], [128, 128, 128]), + DrawInstructions::Rect([1, 0], [5, self.dimensions[1] - 5], [128, 128, 128]), DrawInstructions::Rect([1, self.dimensions[1] - 5], [1, 4], [128, 128, 128]), DrawInstructions::Rect([2, self.dimensions[1] - 5], [1, 3], [128, 128, 128]), DrawInstructions::Rect([3, self.dimensions[1] - 5], [1, 2], [128, 128, 128]), @@ -181,12 +181,12 @@ impl WindowLike for Minesweeper { DrawInstructions::Rect([3, self.dimensions[1] - 3], [1, 2], [255, 255, 255]), DrawInstructions::Rect([2, self.dimensions[1] - 2], [1, 1], [255, 255, 255]), //right border - DrawInstructions::Rect([self.dimensions[0] - 6, WINDOW_TOP_HEIGHT + 5], [5, self.dimensions[1] - WINDOW_TOP_HEIGHT], [255, 255, 255]), - DrawInstructions::Rect([self.dimensions[0] - 2, WINDOW_TOP_HEIGHT], [1, 5], [255, 255, 255]), - DrawInstructions::Rect([self.dimensions[0] - 3, WINDOW_TOP_HEIGHT + 1], [1, 4], [255, 255, 255]), - DrawInstructions::Rect([self.dimensions[0] - 4, WINDOW_TOP_HEIGHT + 2], [1, 3], [255, 255, 255]), - DrawInstructions::Rect([self.dimensions[0] - 5, WINDOW_TOP_HEIGHT + 3], [1, 2], [255, 255, 255]), - DrawInstructions::Rect([self.dimensions[0] - 6, WINDOW_TOP_HEIGHT + 4], [1, 1], [255, 255, 255]), + DrawInstructions::Rect([self.dimensions[0] - 6, 5], [5, self.dimensions[1]], [255, 255, 255]), + DrawInstructions::Rect([self.dimensions[0] - 2, 0], [1, 5], [255, 255, 255]), + DrawInstructions::Rect([self.dimensions[0] - 3, 1], [1, 4], [255, 255, 255]), + DrawInstructions::Rect([self.dimensions[0] - 4, 2], [1, 3], [255, 255, 255]), + DrawInstructions::Rect([self.dimensions[0] - 5, 3], [1, 2], [255, 255, 255]), + DrawInstructions::Rect([self.dimensions[0] - 6, 4], [1, 1], [255, 255, 255]), ]; let tile_size = (self.dimensions[0] - 10) / 16; for y in 0..16 { @@ -194,7 +194,7 @@ impl WindowLike for Minesweeper { let tile = &self.tiles[y][x]; if tile.revealed { if tile.mine { - instructions.push(DrawInstructions::Text([x * tile_size + tile_size / 2 + 2, WINDOW_TOP_HEIGHT + y * tile_size + tile_size / 2], "times-new-roman", "x".to_string(), [255, 0, 0], theme_info.background, None)); + instructions.push(DrawInstructions::Text([x * tile_size + tile_size / 2 + 2, y * tile_size + tile_size / 2], "times-new-roman", "x".to_string(), [255, 0, 0], theme_info.background, None, None)); } else { let color = match tile.touching { 1 => [0, 0, 255], @@ -207,10 +207,10 @@ impl WindowLike for Minesweeper { //8 _ => [128, 128, 128], }; - instructions.push(DrawInstructions::Text([x * tile_size + tile_size / 2 + 5, WINDOW_TOP_HEIGHT + y * tile_size + tile_size / 2 + 2], "times-new-roman", tile.touching.to_string(), color, theme_info.background, None)); + instructions.push(DrawInstructions::Text([x * tile_size + tile_size / 2 + 5, y * tile_size + tile_size / 2 + 2], "times-new-roman", tile.touching.to_string(), color, theme_info.background, None, None)); } } else { - let top_left = [x * tile_size + 6, WINDOW_TOP_HEIGHT + y * tile_size + 5]; + let top_left = [x * tile_size + 6, y * tile_size + 5]; //do not do the corners in respect of our poor poor heap (vector size too big would be bad) instructions.extend(vec![ //top border @@ -225,15 +225,15 @@ impl WindowLike for Minesweeper { //right bottom DrawInstructions::Rect([top_left[0] + tile_size - 4, top_left[1] + 3], [3, tile_size - 4], [128, 128, 128]), // - DrawInstructions::Text([x * tile_size + tile_size / 2 - 2, WINDOW_TOP_HEIGHT + y * tile_size + tile_size / 2], "times-new-roman", u8_to_hex((y * 16 + x) as u8), theme_info.text, theme_info.background, None), + DrawInstructions::Text([x * tile_size + tile_size / 2 - 2, y * tile_size + tile_size / 2], "times-new-roman", u8_to_hex((y * 16 + x) as u8), theme_info.text, theme_info.background, None, None), ]); } } } if self.state == MinesweeperState::Lost { - instructions.extend(vec![DrawInstructions::Text([4, WINDOW_TOP_HEIGHT + 4], "times-new-roman", "You LOST!!! Press a key to play again.".to_string(), theme_info.text, theme_info.background, None)]); + instructions.extend(vec![DrawInstructions::Text([4, 4], "times-new-roman", "You LOST!!! Press a key to play again.".to_string(), theme_info.text, theme_info.background, None, None)]); } else if self.state == MinesweeperState::Won { - instructions.extend(vec![DrawInstructions::Text([4, WINDOW_TOP_HEIGHT + 4], "times-new-roman", "You WON!!! Press a key to play again.".to_string(), theme_info.text, theme_info.background, None)]); + instructions.extend(vec![DrawInstructions::Text([4, 4], "times-new-roman", "You WON!!! Press a key to play again.".to_string(), theme_info.text, theme_info.background, None, None)]); } instructions } @@ -249,7 +249,7 @@ impl WindowLike for Minesweeper { } fn ideal_dimensions(&self, _dimensions: Dimensions) -> Dimensions { - [410, 410 + WINDOW_TOP_HEIGHT] + [410, 410] } } diff --git a/src/window_likes/mod.rs b/src/window_likes/mod.rs index 31435b7..dea554b 100644 --- a/src/window_likes/mod.rs +++ b/src/window_likes/mod.rs @@ -6,4 +6,5 @@ pub mod workspace_indicator; pub mod minesweeper; pub mod terminal; +pub mod malvim; diff --git a/src/window_likes/start_menu.rs b/src/window_likes/start_menu.rs index 17a82ed..493457d 100644 --- a/src/window_likes/start_menu.rs +++ b/src/window_likes/start_menu.rs @@ -141,6 +141,8 @@ impl StartMenu { let mut to_add: Vec<&str> = Vec::new(); if name == "Games" { to_add.push("Minesweeper"); + } else if name == "Editing" { + to_add.push("Malvim"); } else if name == "Files" { to_add.push("Terminal"); } diff --git a/src/window_likes/terminal.rs b/src/window_likes/terminal.rs index 4ac3169..df3c774 100644 --- a/src/window_likes/terminal.rs +++ b/src/window_likes/terminal.rs @@ -5,12 +5,12 @@ use std::str::from_utf8; use std::path::PathBuf; use std::io; -use crate::window_manager::{ DrawInstructions, WindowLike, WindowLikeType, WINDOW_TOP_HEIGHT }; +use crate::window_manager::{ DrawInstructions, WindowLike, WindowLikeType }; use crate::messages::{ WindowMessage, WindowMessageResponse }; use crate::framebuffer::Dimensions; use crate::themes::ThemeInfo; -const MONO_WIDTH: u8 = 8; +const MONO_WIDTH: u8 = 10; const LINE_HEIGHT: usize = 15; const PADDING: usize = 4; @@ -84,17 +84,16 @@ impl WindowLike for Terminal { fn draw(&self, theme_info: &ThemeInfo) -> Vec { let mut instructions = vec![ DrawInstructions::Rect([0, 0], self.dimensions, theme_info.alt_background), - // ]; //add the visible lines of text let end_line = self.actual_line_num + self.get_max_lines(); - let mut text_y = WINDOW_TOP_HEIGHT + PADDING; + let mut text_y = PADDING; for line_num in self.actual_line_num..end_line { if line_num == self.actual_lines.len() { break; } let line = self.actual_lines[line_num].clone(); - instructions.push(DrawInstructions::Text([PADDING, text_y], "times-new-roman", line, theme_info.alt_text, theme_info.alt_background, Some(MONO_WIDTH))); + instructions.push(DrawInstructions::Text([PADDING, text_y], "times-new-romono", line, theme_info.alt_text, theme_info.alt_background, Some(0), Some(MONO_WIDTH))); text_y += LINE_HEIGHT; } instructions @@ -109,7 +108,7 @@ impl WindowLike for Terminal { } fn ideal_dimensions(&self, _dimensions: Dimensions) -> Dimensions { - [410, 410 + WINDOW_TOP_HEIGHT] + [410, 410] } fn resizable(&self) -> bool { @@ -123,7 +122,7 @@ impl Terminal { } fn get_max_lines(&self) -> usize { - (self.dimensions[1] - WINDOW_TOP_HEIGHT- PADDING * 2) / LINE_HEIGHT + (self.dimensions[1] - PADDING * 2) / LINE_HEIGHT } fn process_command(&mut self) -> CommandResponse { @@ -177,13 +176,12 @@ impl Terminal { //cannot index or do .len() because those count bytes not characters loop { if working_line.chars().count() <= max_chars_per_line { - self.actual_lines.push(working_line); break; } else { let mut working_line_chars = working_line.chars(); let mut push_string = String::new(); - for i in 0..max_chars_per_line { + for _i in 0..max_chars_per_line { push_string += &working_line_chars.next().unwrap().to_string(); } self.actual_lines.push(push_string); diff --git a/src/window_likes/workspace_indicator.rs b/src/window_likes/workspace_indicator.rs index 53b7b4b..3433f35 100644 --- a/src/window_likes/workspace_indicator.rs +++ b/src/window_likes/workspace_indicator.rs @@ -44,9 +44,9 @@ impl WindowLike for WorkspaceIndicator { for w in 0..9 { if w == self.current_workspace as usize { instructions.push(DrawInstructions::Rect([w * WIDTH, 0], [WIDTH, self.dimensions[1]], theme_info.top)); - instructions.push(DrawInstructions::Text([w * WIDTH + 5, 4], "times-new-roman", (w + 1).to_string(), theme_info.text_top, theme_info.top, None)); + instructions.push(DrawInstructions::Text([w * WIDTH + 5, 4], "times-new-roman", (w + 1).to_string(), theme_info.top_text, theme_info.top, None, None)); } else { - instructions.push(DrawInstructions::Text([w * WIDTH + 5, 4], "times-new-roman", (w + 1).to_string(), theme_info.text, theme_info.background, None)); + instructions.push(DrawInstructions::Text([w * WIDTH + 5, 4], "times-new-roman", (w + 1).to_string(), theme_info.text, theme_info.background, None, None)); } } instructions diff --git a/src/window_manager.rs b/src/window_manager.rs index 5a6afee..0ec6508 100644 --- a/src/window_manager.rs +++ b/src/window_manager.rs @@ -1,6 +1,6 @@ use std::vec::Vec; use std::vec; -use std::collections::HashMap; +use std::collections::{ HashMap, VecDeque }; use std::fmt; use std::boxed::Box; use std::sync::{ LazyLock, Mutex }; @@ -24,10 +24,13 @@ use crate::messages::*; use crate::window_likes::start_menu::StartMenu; use crate::window_likes::minesweeper::Minesweeper; use crate::window_likes::terminal::Terminal; +use crate::window_likes::malvim::Malvim; + +//todo, better error handling for windows pub const TASKBAR_HEIGHT: usize = 38; pub const INDICATOR_HEIGHT: usize = 20; -pub const WINDOW_TOP_HEIGHT: usize = 26; +const WINDOW_TOP_HEIGHT: usize = 26; static WRITER: LazyLock> = LazyLock::new(|| Mutex::new(Default::default())); @@ -48,7 +51,9 @@ pub fn init(framebuffer: Framebuffer, framebuffer_info: FramebufferInfo) { for c in stdin.keys() { if let Some(kc) = key_to_char(c.unwrap()) { + //do not allow exit when locked unless debugging if kc == KeyChar::Alt('e') { + //if kc == KeyChar::Alt('e') && !wm.locked { write!(stdout, "{}", cursor::Show).unwrap(); stdout.suspend_raw_mode().unwrap(); exit(0); @@ -68,7 +73,7 @@ pub fn min(one: usize, two: usize) -> usize { #[derive(Debug)] pub enum DrawInstructions { Rect(Point, Dimensions, RGBColor), - Text(Point, &'static str, String, RGBColor, RGBColor, Option), //font and text + Text(Point, &'static str, String, RGBColor, RGBColor, Option, Option), //font and text Gradient(Point, Dimensions, RGBColor, RGBColor, usize), Mingde(Point), } @@ -126,7 +131,7 @@ pub struct WindowManager { dimensions: Dimensions, theme: Themes, focused_id: usize, - locked: bool, + pub locked: bool, current_workspace: u8, framebuffer: Framebuffer, } @@ -156,6 +161,7 @@ impl WindowManager { let id = self.id_count; self.focused_id = id; window_like.handle_message(WindowMessage::Init(dimensions)); + let dimensions = if window_like.subtype() == WindowLikeType::Window { [dimensions[0], dimensions[1] + WINDOW_TOP_HEIGHT] } else { dimensions }; self.window_infos.push(WindowLikeInfo { id, window_like, @@ -242,11 +248,13 @@ impl WindowManager { if !self.locked { //keyboard shortcut let shortcuts = HashMap::from([ + //alt+e is terminate program (ctrl+c) ('s', ShortcutType::StartMenu), (']', ShortcutType::FocusNextWindow), ('q', ShortcutType::QuitWindow), ('c', ShortcutType::CenterWindow), ('f', ShortcutType::FullscreenWindow), + ('w', ShortcutType::HalfWidthWindow), //move window a small amount ('h', ShortcutType::MoveWindow(Direction::Left)), ('j', ShortcutType::MoveWindow(Direction::Down)), @@ -422,11 +430,14 @@ impl WindowManager { } else { new_dimensions = self.window_infos[focused_index].dimensions; } - self.window_infos[focused_index].window_like.handle_message(WindowMessage::ChangeDimensions(new_dimensions)); + self.window_infos[focused_index].window_like.handle_message(WindowMessage::ChangeDimensions([new_dimensions[0], new_dimensions[1] - WINDOW_TOP_HEIGHT])); press_response = WindowMessageResponse::JustRerender; } } - } + }, + &ShortcutType::HalfWidthWindow => { + // + }, }; } } @@ -471,6 +482,7 @@ impl WindowManager { } let w: WindowBox = match w { "Minesweeper" => Box::new(Minesweeper::new()), + "Malvim" => Box::new(Malvim::new()), "Terminal" => Box::new(Terminal::new()), "StartMenu" => Box::new(StartMenu::new()), _ => panic!("no such window"), @@ -510,6 +522,10 @@ impl WindowManager { }; } + fn get_true_top_left(top_left: &Point, is_window: bool) -> Point { + [top_left[0], top_left[1] + if is_window { WINDOW_TOP_HEIGHT } else { 0 }] + } + //another issue with a huge vector of draw instructions; it takes up heap memory pub fn render(&mut self, maybe_redraw_ids: Option>, use_saved_buffer: bool) { let theme_info = get_theme_info(&self.theme).unwrap(); @@ -540,17 +556,24 @@ impl WindowManager { } else { window_info.dimensions }; - let mut instructions = Vec::new(); - if window_info.window_like.subtype() == WindowLikeType::Window { + let mut instructions = VecDeque::from(window_info.window_like.draw(&theme_info)); + let is_window = window_info.window_like.subtype() == WindowLikeType::Window; + if is_window { //if this is the top most window to draw, snapshot if w_index == max_index && !use_saved_buffer && redraw_ids.len() == 0 { WRITER.lock().unwrap().save_buffer(); } + //offset top left by the window top height for windows (because windows can't draw in that region) + instructions = instructions.iter().map(|instruction| { + match instruction { + DrawInstructions::Rect(top_left, dimensions, color) => DrawInstructions::Rect(WindowManager::get_true_top_left(top_left, is_window), *dimensions, *color), + DrawInstructions::Text(top_left, font_name, text, color, bg_color, horiz_spacing, mono_width) => DrawInstructions::Text(WindowManager::get_true_top_left(top_left, is_window), font_name, text.clone(), *color, *bg_color, *horiz_spacing, *mono_width), + DrawInstructions::Mingde(top_left) => DrawInstructions::Mingde(WindowManager::get_true_top_left(top_left, is_window)), + DrawInstructions::Gradient(top_left, dimensions, start_color, end_color, steps) => DrawInstructions::Gradient(WindowManager::get_true_top_left(top_left, is_window), *dimensions, *start_color, *end_color, *steps), + } + }).collect(); //draw window background - instructions.push(DrawInstructions::Rect([0, 0], window_dimensions, theme_info.background)); - } - instructions.extend(window_info.window_like.draw(&theme_info)); - if window_info.window_like.subtype() == WindowLikeType::Window { + instructions.push_front(DrawInstructions::Rect([0, 0], window_dimensions, theme_info.background)); //draw window top decorations and what not instructions.extend(vec![ //left top border @@ -558,7 +581,7 @@ impl WindowManager { DrawInstructions::Rect([0, 0], [1, window_dimensions[1]], theme_info.border_left_top), //top DrawInstructions::Rect([1, 1], [window_dimensions[0] - 2, WINDOW_TOP_HEIGHT - 3], theme_info.top), - DrawInstructions::Text([4, 4], "times-new-roman", window_info.window_like.title().to_string(), theme_info.text_top, theme_info.top, None), + DrawInstructions::Text([4, 4], "times-new-roman", window_info.window_like.title().to_string(), theme_info.top_text, theme_info.top, None, None), //top bottom border DrawInstructions::Rect([1, WINDOW_TOP_HEIGHT - 2], [window_dimensions[0] - 2, 2], theme_info.border_left_top), //right bottom border @@ -587,8 +610,8 @@ impl WindowManager { ]; window_writer.draw_rect(top_left, true_dimensions, color); }, - DrawInstructions::Text(top_left, font_name, text, color, bg_color, mono_width) => { - window_writer.draw_text(top_left, font_name, &text, color, bg_color, 1, mono_width); + DrawInstructions::Text(top_left, font_name, text, color, bg_color, horiz_spacing, mono_width) => { + window_writer.draw_text(top_left, font_name, &text, color, bg_color, horiz_spacing.unwrap_or(1), mono_width); }, DrawInstructions::Mingde(top_left) => { window_writer._draw_mingde(top_left);