From 029667c3d9c8abec82900a1f35615b426ce8bab6 Mon Sep 17 00:00:00 2001 From: Jeremy Anderson Date: Mon, 13 Jul 2026 12:33:27 -0400 Subject: [PATCH] A hotkey-first programmer's editor built in Rust on the iced GUI framework. Scitano combines the menu structure of SciTE, strict GNU nano hotkeys, and Geany-inspired sidebar features into a single unified editing environment. --- Cargo.lock | 4381 ++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 10 + LICENSE | 273 +++ README.md | 223 +++ build.sh | 2 + screenshot.png | Bin 0 -> 64384 bytes src/config.rs | 8 + src/editor.rs | 193 +++ src/main.rs | 727 ++++++++ src/theme.rs | 99 ++ 10 files changed, 5916 insertions(+) create mode 100755 Cargo.lock create mode 100755 Cargo.toml create mode 100644 LICENSE create mode 100644 README.md create mode 100755 build.sh create mode 100644 screenshot.png create mode 100755 src/config.rs create mode 100755 src/editor.rs create mode 100755 src/main.rs create mode 100755 src/theme.rs diff --git a/Cargo.lock b/Cargo.lock new file mode 100755 index 0000000..0fde0d5 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,4381 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "ab_glyph" +version = "0.2.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01c0457472c38ea5bd1c3b5ada5e368271cb550be7a4ca4a0b4634e9913f6cc2" +dependencies = [ + "ab_glyph_rasterizer", + "owned_ttf_parser", +] + +[[package]] +name = "ab_glyph_rasterizer" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "366ffbaa4442f4684d91e2cd7c5ea7c4ed8add41959a31447066e279e432b618" + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "ahash" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" +dependencies = [ + "getrandom 0.2.17", + "once_cell", + "version_check", +] + +[[package]] +name = "ahash" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +dependencies = [ + "cfg-if", + "getrandom 0.3.4", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + +[[package]] +name = "android-activity" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f2a1bb052857d5dd49572219344a7332b31b76405648eabac5bc68978251bcd" +dependencies = [ + "android-properties", + "bitflags 2.13.0", + "cc", + "jni", + "libc", + "log", + "ndk", + "ndk-context", + "ndk-sys 0.6.0+11769913", + "num_enum", + "thiserror 2.0.18", +] + +[[package]] +name = "android-properties" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "approx" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" +dependencies = [ + "num-traits", +] + +[[package]] +name = "arrayref" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" + +[[package]] +name = "arrayvec" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3fb67a6e08acf24fdeccbac2cb6ac4305825bd1f117462e0e6f2f193345ad56" + +[[package]] +name = "as-raw-xcb-connection" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175571dd1d178ced59193a6fc02dde1b972eb0bc56c892cde9beeceac5bf0f6b" + +[[package]] +name = "ash" +version = "0.37.3+1.3.251" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39e9c3835d686b0a6084ab4234fcd1b07dbf6e4767dce60874b12356a25ecd4a" +dependencies = [ + "libloading 0.7.4", +] + +[[package]] +name = "async-broadcast" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532" +dependencies = [ + "event-listener", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-channel" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2" +dependencies = [ + "concurrent-queue", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-executor" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c96bf972d85afc50bf5ab8fe2d54d1586b4e0b46c97c50a0c9e71e2f7bcd812a" +dependencies = [ + "async-task", + "concurrent-queue", + "fastrand", + "futures-lite", + "pin-project-lite", + "slab", +] + +[[package]] +name = "async-fs" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8034a681df4aed8b8edbd7fbe472401ecf009251c8b40556b304567052e294c5" +dependencies = [ + "async-lock", + "blocking", + "futures-lite", +] + +[[package]] +name = "async-io" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "456b8a8feb6f42d237746d4b3e9a178494627745c3c56c6ea55d92ba50d026fc" +dependencies = [ + "autocfg", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite", + "parking", + "polling", + "rustix 1.1.4", + "slab", + "windows-sys 0.61.2", +] + +[[package]] +name = "async-lock" +version = "3.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311" +dependencies = [ + "event-listener", + "event-listener-strategy", + "pin-project-lite", +] + +[[package]] +name = "async-process" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc50921ec0055cdd8a16de48773bfeec5c972598674347252c0399676be7da75" +dependencies = [ + "async-channel", + "async-io", + "async-lock", + "async-signal", + "async-task", + "blocking", + "cfg-if", + "event-listener", + "futures-lite", + "rustix 1.1.4", +] + +[[package]] +name = "async-recursion" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.118", +] + +[[package]] +name = "async-signal" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52b5aaafa020cf5053a01f2a60e8ff5dccf550f0f77ec54a4e47285ac2bab485" +dependencies = [ + "async-io", + "async-lock", + "atomic-waker", + "cfg-if", + "futures-core", + "futures-io", + "rustix 1.1.4", + "signal-hook-registry", + "slab", + "windows-sys 0.61.2", +] + +[[package]] +name = "async-task" +version = "4.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" + +[[package]] +name = "async-trait" +version = "0.1.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.118", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8" + +[[package]] +name = "block" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block2" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" +dependencies = [ + "objc2 0.5.2", +] + +[[package]] +name = "blocking" +version = "1.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e83f8d02be6967315521be875afa792a316e28d57b5a2d401897e2a7921b7f21" +dependencies = [ + "async-channel", + "async-task", + "futures-io", + "futures-lite", + "piper", +] + +[[package]] +name = "bumpalo" +version = "3.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" + +[[package]] +name = "by_address" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64fa3c856b712db6612c019f14756e64e4bcea13337a6b33b696333a9eaa2d06" + +[[package]] +name = "bytemuck" +version = "1.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6aedf8ae72766347502cf3cb4f41cf5e9cc37d28bee90f1fdaaae15f9cf9424" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f65693059b6b9c588b9f62fed1cedbf0a8b805631457ea162d68f0de186f3de5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.118", +] + +[[package]] +name = "bytes" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" + +[[package]] +name = "calloop" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec" +dependencies = [ + "bitflags 2.13.0", + "log", + "polling", + "rustix 0.38.44", + "slab", + "thiserror 1.0.69", +] + +[[package]] +name = "calloop" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dbf9978365bac10f54d1d4b04f7ce4427e51f71d61f2fe15e3fed5166474df7" +dependencies = [ + "bitflags 2.13.0", + "polling", + "rustix 1.1.4", + "slab", + "tracing", +] + +[[package]] +name = "calloop-wayland-source" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95a66a987056935f7efce4ab5668920b5d0dac4a7c99991a67395f13702ddd20" +dependencies = [ + "calloop 0.13.0", + "rustix 0.38.44", + "wayland-backend", + "wayland-client", +] + +[[package]] +name = "calloop-wayland-source" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138efcf0940a02ebf0cc8d1eff41a1682a46b431630f4c52450d6265876021fa" +dependencies = [ + "calloop 0.14.4", + "rustix 1.1.4", + "wayland-backend", + "wayland-client", +] + +[[package]] +name = "cc" +version = "1.2.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e17dd265a7d0f31ef544e1b20e03add05d3b45b491b633b10d67145d2acc1a38" +dependencies = [ + "find-msvc-tools", + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "cfg_aliases" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "clipboard-win" +version = "5.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bde03770d3df201d4fb868f2c9c59e66a3e4e2bd06692a0fe701e7103c7e84d4" +dependencies = [ + "error-code", +] + +[[package]] +name = "clipboard_macos" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b7f4aaa047ba3c3630b080bb9860894732ff23e2aee290a418909aa6d5df38f" +dependencies = [ + "objc2 0.5.2", + "objc2-app-kit", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "clipboard_wayland" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "003f886bc4e2987729d10c1db3424e7f80809f3fc22dbc16c685738887cb37b8" +dependencies = [ + "smithay-clipboard", +] + +[[package]] +name = "clipboard_x11" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd63e33452ffdafd39924c4f05a5dd1e94db646c779c6bd59148a3d95fff5ad4" +dependencies = [ + "thiserror 2.0.18", + "x11rb", +] + +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + +[[package]] +name = "com" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e17887fd17353b65b1b2ef1c526c83e26cd72e74f598a8dc1bee13a48f3d9f6" +dependencies = [ + "com_macros", +] + +[[package]] +name = "com_macros" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d375883580a668c7481ea6631fc1a8863e33cc335bf56bfad8d7e6d4b04b13a5" +dependencies = [ + "com_macros_support", + "proc-macro2", + "syn 1.0.109", +] + +[[package]] +name = "com_macros_support" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad899a1087a9296d5644792d7cb72b8e34c1bec8e7d4fbc002230169a6e8710c" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "core-graphics" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "core-graphics-types", + "foreign-types", + "libc", +] + +[[package]] +name = "core-graphics-types" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "libc", +] + +[[package]] +name = "cosmic-text" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59fd57d82eb4bfe7ffa9b1cec0c05e2fd378155b47f255a67983cb4afe0e80c2" +dependencies = [ + "bitflags 2.13.0", + "fontdb", + "log", + "rangemap", + "rayon", + "rustc-hash 1.1.0", + "rustybuzz", + "self_cell", + "swash", + "sys-locale", + "ttf-parser 0.21.1", + "unicode-bidi", + "unicode-linebreak", + "unicode-script", + "unicode-segmentation", +] + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5181e0de7b61eb03a81e347d6dd8797bae9da5146707b51077e2d71a54ec0ceb" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d6914041f254d6e9176c01941b21115dcfb7089e55135a35411081bd106ef3f" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17" + +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + +[[package]] +name = "crypto-common" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "ctor" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83cf0d42651b16c6dfe68685716d18480d18a9c39c62d76e8cf3eb6ed5d8bcbf" +dependencies = [ + "dtor", +] + +[[package]] +name = "cursor-icon" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f27ae1dd37df86211c42e150270f82743308803d90a6f6e6651cd730d5e1732f" + +[[package]] +name = "d3d12" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e3d747f100290a1ca24b752186f61f6637e1deffe3bf6320de6fcb29510a307" +dependencies = [ + "bitflags 2.13.0", + "libloading 0.8.9", + "winapi", +] + +[[package]] +name = "dark-light" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a76fa97167fa740dcdbfe18e8895601e1bc36525f09b044e00916e717c03a3c" +dependencies = [ + "dconf_rs", + "detect-desktop-environment", + "dirs", + "objc", + "rust-ini", + "web-sys", + "winreg", + "zbus", +] + +[[package]] +name = "dconf_rs" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7046468a81e6a002061c01e6a7c83139daf91b11c30e66795b13217c2d885c8b" + +[[package]] +name = "deranged" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" + +[[package]] +name = "detect-desktop-environment" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21d8ad60dd5b13a4ee6bd8fa2d5d88965c597c67bce32b5fc49c94f55cb50810" + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "dirs" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "dispatch" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" + +[[package]] +name = "dispatch2" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" +dependencies = [ + "bitflags 2.13.0", + "objc2 0.6.4", +] + +[[package]] +name = "dlib" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab8ecd87370524b461f8557c119c405552c396ed91fc0a8eec68679eab26f94a" +dependencies = [ + "libloading 0.8.9", +] + +[[package]] +name = "dlv-list" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0688c2a7f92e427f44895cd63841bff7b29f8d7a1648b9e7e07a4a365b2e1257" + +[[package]] +name = "downcast-rs" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" + +[[package]] +name = "dpi" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b14ccef22fc6f5a8f4d7d768562a182c04ce9a3b3157b91390b52ddfdf1a76" + +[[package]] +name = "drm" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80bc8c5c6c2941f70a55c15f8d9f00f9710ebda3ffda98075f996a0e6c92756f" +dependencies = [ + "bitflags 2.13.0", + "bytemuck", + "drm-ffi", + "drm-fourcc", + "libc", + "rustix 0.38.44", +] + +[[package]] +name = "drm-ffi" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51a91c9b32ac4e8105dec255e849e0d66e27d7c34d184364fb93e469db08f690" +dependencies = [ + "drm-sys", + "rustix 1.1.4", +] + +[[package]] +name = "drm-fourcc" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0aafbcdb8afc29c1a7ee5fbe53b5d62f4565b35a042a662ca9fecd0b54dae6f4" + +[[package]] +name = "drm-sys" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8e1361066d91f5ffccff060a3c3be9c3ecde15be2959c1937595f7a82a9f8" +dependencies = [ + "libc", + "linux-raw-sys 0.9.4", +] + +[[package]] +name = "dtor" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edf234dd1594d6dd434a8fb8cada51ddbbc593e40e4a01556a0b31c62da2775b" + +[[package]] +name = "either" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" + +[[package]] +name = "endi" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66b7e2430c6dff6a955451e2cfc438f09cea1965a9d6f87f7e3b90decc014099" + +[[package]] +name = "enumflags2" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1027f7680c853e056ebcec683615fb6fbbc07dbaa13b4d5d9442b146ded4ecef" +dependencies = [ + "enumflags2_derive", + "serde", +] + +[[package]] +name = "enumflags2_derive" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.118", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "error-code" +version = "3.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dea2df4cf52843e0452895c455a1a2cfbb842a1e7329671acf418fdc53ed4c59" + +[[package]] +name = "etagere" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc89bf99e5dc15954a60f707c1e09d7540e5cd9af85fa75caa0b510bc08c5342" +dependencies = [ + "euclid", + "svg_fmt", +] + +[[package]] +name = "euclid" +version = "0.22.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1a05365e3b1c6d1650318537c7460c6923f1abdd272ad6842baa2b509957a06" +dependencies = [ + "num-traits", +] + +[[package]] +name = "event-listener" +version = "5.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" +dependencies = [ + "event-listener", + "pin-project-lite", +] + +[[package]] +name = "fast-srgb8" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd2e7510819d6fbf51a5545c8f922716ecfb14df168a3242f7d33e0239efe6a1" + +[[package]] +name = "fastrand" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" + +[[package]] +name = "fdeflate" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "flate2" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "font-types" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3971f9a5ca983419cdc386941ba3b9e1feba01a0ab888adf78739feb2798492" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "fontconfig-parser" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbc773e24e02d4ddd8395fd30dc147524273a83e54e0f312d986ea30de5f5646" +dependencies = [ + "roxmltree", +] + +[[package]] +name = "fontdb" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0299020c3ef3f60f526a4f64ab4a3d4ce116b1acbf24cdd22da0068e5d81dc3" +dependencies = [ + "fontconfig-parser", + "log", + "memmap2", + "slotmap", + "tinyvec", + "ttf-parser 0.20.0", +] + +[[package]] +name = "foreign-types" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" +dependencies = [ + "foreign-types-macros", + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-macros" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.118", +] + +[[package]] +name = "foreign-types-shared" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" + +[[package]] +name = "futures" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" + +[[package]] +name = "futures-executor" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" + +[[package]] +name = "futures-lite" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "parking", + "pin-project-lite", +] + +[[package]] +name = "futures-macro" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.118", +] + +[[package]] +name = "futures-sink" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" + +[[package]] +name = "futures-task" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" + +[[package]] +name = "futures-util" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "gethostname" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bd49230192a3797a9a4d6abe9b3eed6f7fa4c8a8a4947977c6f80025f92cbd8" +dependencies = [ + "rustix 1.1.4", + "windows-link", +] + +[[package]] +name = "getrandom" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi 5.3.0", + "wasip2", +] + +[[package]] +name = "getrandom" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" +dependencies = [ + "cfg-if", + "libc", + "r-efi 6.0.0", +] + +[[package]] +name = "gl_generator" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a95dfc23a2b4a9a2f5ab41d194f8bfda3cabec42af4e39f08c339eb2a0c124d" +dependencies = [ + "khronos_api", + "log", + "xml-rs", +] + +[[package]] +name = "glam" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "151665d9be52f9bb40fc7966565d39666f2d1e69233571b71b87791c7e0528b3" + +[[package]] +name = "glow" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd348e04c43b32574f2de31c8bb397d96c9fcfa1371bd4ca6d8bdc464ab121b1" +dependencies = [ + "js-sys", + "slotmap", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "glutin_wgl_sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8098adac955faa2d31079b65dc48841251f69efd3ac25477903fc424362ead" +dependencies = [ + "gl_generator", +] + +[[package]] +name = "gpu-alloc" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45cf04b2726f02df5508c6de726acdc90cdf97ac771a9a0ffd8ba10a6e696bf9" +dependencies = [ + "bitflags 2.13.0", + "gpu-alloc-types", +] + +[[package]] +name = "gpu-alloc-types" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2bbed164dd10ed526c2e4fe3e721ca4a71c61730e5aafac6844b417b3227058" +dependencies = [ + "bitflags 2.13.0", +] + +[[package]] +name = "gpu-allocator" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f56f6318968d03c18e1bcf4857ff88c61157e9da8e47c5f29055d60e1228884" +dependencies = [ + "log", + "presser", + "thiserror 1.0.69", + "winapi", + "windows", +] + +[[package]] +name = "gpu-descriptor" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc11df1ace8e7e564511f53af41f3e42ddc95b56fd07b3f4445d2a6048bc682c" +dependencies = [ + "bitflags 2.13.0", + "gpu-descriptor-types", + "hashbrown 0.14.5", +] + +[[package]] +name = "gpu-descriptor-types" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bf0b36e6f090b7e1d8a4b49c0cb81c1f8376f72198c65dd3ad9ff3556b8b78c" +dependencies = [ + "bitflags 2.13.0", +] + +[[package]] +name = "guillotiere" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b62d5865c036cb1393e23c50693df631d3f5d7bcca4c04fe4cc0fd592e74a782" +dependencies = [ + "euclid", + "svg_fmt", +] + +[[package]] +name = "half" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" +dependencies = [ + "cfg-if", + "crunchy", + "zerocopy", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash 0.7.8", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash 0.8.12", + "allocator-api2", +] + +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" + +[[package]] +name = "hassle-rs" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af2a7e73e1f34c48da31fb668a907f250794837e08faa144fd24f0b8b741e890" +dependencies = [ + "bitflags 2.13.0", + "com", + "libc", + "libloading 0.8.9", + "thiserror 1.0.69", + "widestring", + "winapi", +] + +[[package]] +name = "hermit-abi" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hexf-parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" + +[[package]] +name = "iced" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88acfabc84ec077eaf9ede3457ffa3a104626d79022a9bf7f296093b1d60c73f" +dependencies = [ + "iced_core", + "iced_futures", + "iced_highlighter", + "iced_renderer", + "iced_widget", + "iced_winit", + "thiserror 1.0.69", +] + +[[package]] +name = "iced_core" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0013a238275494641bf8f1732a23a808196540dc67b22ff97099c044ae4c8a1c" +dependencies = [ + "bitflags 2.13.0", + "bytes", + "dark-light", + "glam", + "log", + "num-traits", + "once_cell", + "palette", + "rustc-hash 2.1.3", + "smol_str", + "thiserror 1.0.69", + "web-time", +] + +[[package]] +name = "iced_futures" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c04a6745ba2e80f32cf01e034fd00d853aa4f4cd8b91888099cb7aaee0d5d7c" +dependencies = [ + "futures", + "iced_core", + "log", + "rustc-hash 2.1.3", + "wasm-bindgen-futures", + "wasm-timer", +] + +[[package]] +name = "iced_glyphon" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41c3bb56f1820ca252bc1d0994ece33d233a55657c0c263ea7cb16895adbde82" +dependencies = [ + "cosmic-text", + "etagere", + "lru", + "rustc-hash 2.1.3", + "wgpu", +] + +[[package]] +name = "iced_graphics" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba25a18cfa6d5cc160aca7e1b34f73ccdff21680fa8702168c09739767b6c66f" +dependencies = [ + "bitflags 2.13.0", + "bytemuck", + "cosmic-text", + "half", + "iced_core", + "iced_futures", + "log", + "once_cell", + "raw-window-handle", + "rustc-hash 2.1.3", + "thiserror 1.0.69", + "unicode-segmentation", +] + +[[package]] +name = "iced_highlighter" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bad88b25a1328cd4bb0b72d8e20f8207c0433649dc788f67e911423b9406f45c" +dependencies = [ + "iced_core", + "once_cell", + "syntect", +] + +[[package]] +name = "iced_renderer" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73558208059f9e622df2bf434e044ee2f838ce75201a023cf0ca3e1244f46c2a" +dependencies = [ + "iced_graphics", + "iced_tiny_skia", + "iced_wgpu", + "log", + "thiserror 1.0.69", +] + +[[package]] +name = "iced_runtime" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "348b5b2c61c934d88ca3b0ed1ed913291e923d086a66fa288ce9669da9ef62b5" +dependencies = [ + "bytes", + "iced_core", + "iced_futures", + "raw-window-handle", + "thiserror 1.0.69", +] + +[[package]] +name = "iced_tiny_skia" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c625d368284fcc43b0b36b176f76eff1abebe7959dd58bd8ce6897d641962a50" +dependencies = [ + "bytemuck", + "cosmic-text", + "iced_graphics", + "kurbo", + "log", + "rustc-hash 2.1.3", + "softbuffer", + "tiny-skia", +] + +[[package]] +name = "iced_wgpu" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15708887133671d2bcc6c1d01d1f176f43a64d6cdc3b2bf893396c3ee498295f" +dependencies = [ + "bitflags 2.13.0", + "bytemuck", + "futures", + "glam", + "guillotiere", + "iced_glyphon", + "iced_graphics", + "log", + "once_cell", + "rustc-hash 2.1.3", + "thiserror 1.0.69", + "wgpu", +] + +[[package]] +name = "iced_widget" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81429e1b950b0e4bca65be4c4278fea6678ea782030a411778f26fa9f8983e1d" +dependencies = [ + "iced_highlighter", + "iced_renderer", + "iced_runtime", + "num-traits", + "once_cell", + "rustc-hash 2.1.3", + "thiserror 1.0.69", + "unicode-segmentation", +] + +[[package]] +name = "iced_winit" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f44cd4e1c594b6334f409282937bf972ba14d31fedf03c23aa595d982a2fda28" +dependencies = [ + "iced_futures", + "iced_graphics", + "iced_runtime", + "log", + "rustc-hash 2.1.3", + "thiserror 1.0.69", + "tracing", + "wasm-bindgen-futures", + "web-sys", + "winapi", + "window_clipboard", + "winit", +] + +[[package]] +name = "indexmap" +version = "2.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" +dependencies = [ + "equivalent", + "hashbrown 0.17.1", +] + +[[package]] +name = "instant" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "jni" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498" +dependencies = [ + "cfg-if", + "combine", + "jni-macros", + "jni-sys 0.4.1", + "log", + "simd_cesu8", + "thiserror 2.0.18", + "walkdir", + "windows-link", +] + +[[package]] +name = "jni-macros" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3" +dependencies = [ + "proc-macro2", + "quote", + "rustc_version", + "simd_cesu8", + "syn 2.0.118", +] + +[[package]] +name = "jni-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41a652e1f9b6e0275df1f15b32661cf0d4b78d4d87ddec5e0c3c20f097433258" +dependencies = [ + "jni-sys 0.4.1", +] + +[[package]] +name = "jni-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2" +dependencies = [ + "jni-sys-macros", +] + +[[package]] +name = "jni-sys-macros" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" +dependencies = [ + "quote", + "syn 2.0.118", +] + +[[package]] +name = "jobserver" +version = "0.1.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c00acbd29eabad4a2392fa0e921c874934dbbf4194312ad20f04a0ed67a3cb3" +dependencies = [ + "getrandom 0.4.3", + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53b44bfcdb3f8d5837a46dae1ca9660a837176eee74a28b229bc626816589102" +dependencies = [ + "cfg-if", + "futures-util", + "wasm-bindgen", +] + +[[package]] +name = "khronos-egl" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6aae1df220ece3c0ada96b8153459b67eebe9ae9212258bb0134ae60416fdf76" +dependencies = [ + "libc", + "libloading 0.8.9", + "pkg-config", +] + +[[package]] +name = "khronos_api" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" + +[[package]] +name = "kurbo" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1618d4ebd923e97d67e7cd363d80aef35fe961005cbbbb3d2dad8bdd1bc63440" +dependencies = [ + "arrayvec", + "smallvec", +] + +[[package]] +name = "libc" +version = "0.2.186" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" + +[[package]] +name = "libloading" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +dependencies = [ + "cfg-if", + "winapi", +] + +[[package]] +name = "libloading" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" +dependencies = [ + "cfg-if", + "windows-link", +] + +[[package]] +name = "libm" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" + +[[package]] +name = "libredox" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c943259e342f1e06ff2da7a83eabdfe7f92ce10262688dbf1895ff0b3e6e4652" +dependencies = [ + "bitflags 2.13.0", + "libc", + "plain", + "redox_syscall 0.9.0", +] + +[[package]] +name = "linked-hash-map" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" + +[[package]] +name = "linux-raw-sys" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + +[[package]] +name = "linux-raw-sys" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" + +[[package]] +name = "linux-raw-sys" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" + +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" + +[[package]] +name = "lru" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" + +[[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" +dependencies = [ + "libc", +] + +[[package]] +name = "memchr" +version = "2.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" + +[[package]] +name = "memmap2" +version = "0.9.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1219ed1b7f229ee7104d281dd01d6802fe28bb6e95d292942c4daacdeb798c0" +dependencies = [ + "libc", +] + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "metal" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c43f73953f8cbe511f021b58f18c3ce1c3d1ae13fe953293e13345bf83217f25" +dependencies = [ + "bitflags 2.13.0", + "block", + "core-graphics-types", + "foreign-types", + "log", + "objc", + "paste", +] + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "naga" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50e3524642f53d9af419ab5e8dd29d3ba155708267667c2f3f06c88c9e130843" +dependencies = [ + "bit-set", + "bitflags 2.13.0", + "codespan-reporting", + "hexf-parse", + "indexmap", + "log", + "num-traits", + "rustc-hash 1.1.0", + "spirv", + "termcolor", + "thiserror 1.0.69", + "unicode-xid", +] + +[[package]] +name = "ndk" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" +dependencies = [ + "bitflags 2.13.0", + "jni-sys 0.3.1", + "log", + "ndk-sys 0.6.0+11769913", + "num_enum", + "raw-window-handle", + "thiserror 1.0.69", +] + +[[package]] +name = "ndk-context" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" + +[[package]] +name = "ndk-sys" +version = "0.5.0+25.2.9519653" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c196769dd60fd4f363e11d948139556a344e79d451aeb2fa2fd040738ef7691" +dependencies = [ + "jni-sys 0.3.1", +] + +[[package]] +name = "ndk-sys" +version = "0.6.0+11769913" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" +dependencies = [ + "jni-sys 0.3.1", +] + +[[package]] +name = "nix" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" +dependencies = [ + "bitflags 2.13.0", + "cfg-if", + "cfg_aliases 0.2.1", + "libc", + "memoffset", +] + +[[package]] +name = "num-conv" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_enum" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0bca838442ec211fa11de3a8b0e0e8f3a4522575b5c4c06ed722e005036f26" +dependencies = [ + "num_enum_derive", + "rustversion", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "680998035259dcfcafe653688bf2aa6d3e2dc05e98be6ab46afb089dc84f1df8" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.118", +] + +[[package]] +name = "objc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" +dependencies = [ + "malloc_buf", + "objc_exception", +] + +[[package]] +name = "objc-sys" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310" + +[[package]] +name = "objc2" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804" +dependencies = [ + "objc-sys", + "objc2-encode", +] + +[[package]] +name = "objc2" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f" +dependencies = [ + "objc2-encode", +] + +[[package]] +name = "objc2-app-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" +dependencies = [ + "bitflags 2.13.0", + "block2", + "libc", + "objc2 0.5.2", + "objc2-core-data", + "objc2-core-image", + "objc2-foundation 0.2.2", + "objc2-quartz-core 0.2.2", +] + +[[package]] +name = "objc2-cloud-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009" +dependencies = [ + "bitflags 2.13.0", + "block2", + "objc2 0.5.2", + "objc2-core-location", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-contacts" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5ff520e9c33812fd374d8deecef01d4a840e7b41862d849513de77e44aa4889" +dependencies = [ + "block2", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-core-data" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" +dependencies = [ + "bitflags 2.13.0", + "block2", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-core-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" +dependencies = [ + "bitflags 2.13.0", + "dispatch2", + "objc2 0.6.4", +] + +[[package]] +name = "objc2-core-graphics" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807" +dependencies = [ + "bitflags 2.13.0", + "dispatch2", + "objc2 0.6.4", + "objc2-core-foundation", + "objc2-io-surface", +] + +[[package]] +name = "objc2-core-image" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" +dependencies = [ + "block2", + "objc2 0.5.2", + "objc2-foundation 0.2.2", + "objc2-metal", +] + +[[package]] +name = "objc2-core-location" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "000cfee34e683244f284252ee206a27953279d370e309649dc3ee317b37e5781" +dependencies = [ + "block2", + "objc2 0.5.2", + "objc2-contacts", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-encode" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" + +[[package]] +name = "objc2-foundation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" +dependencies = [ + "bitflags 2.13.0", + "block2", + "dispatch", + "libc", + "objc2 0.5.2", +] + +[[package]] +name = "objc2-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" +dependencies = [ + "bitflags 2.13.0", + "objc2 0.6.4", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-io-surface" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d" +dependencies = [ + "bitflags 2.13.0", + "objc2 0.6.4", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-link-presentation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398" +dependencies = [ + "block2", + "objc2 0.5.2", + "objc2-app-kit", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-metal" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" +dependencies = [ + "bitflags 2.13.0", + "block2", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-quartz-core" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" +dependencies = [ + "bitflags 2.13.0", + "block2", + "objc2 0.5.2", + "objc2-foundation 0.2.2", + "objc2-metal", +] + +[[package]] +name = "objc2-quartz-core" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f" +dependencies = [ + "bitflags 2.13.0", + "objc2 0.6.4", + "objc2-core-foundation", + "objc2-foundation 0.3.2", +] + +[[package]] +name = "objc2-symbols" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a684efe3dec1b305badae1a28f6555f6ddd3bb2c2267896782858d5a78404dc" +dependencies = [ + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-ui-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f" +dependencies = [ + "bitflags 2.13.0", + "block2", + "objc2 0.5.2", + "objc2-cloud-kit", + "objc2-core-data", + "objc2-core-image", + "objc2-core-location", + "objc2-foundation 0.2.2", + "objc2-link-presentation", + "objc2-quartz-core 0.2.2", + "objc2-symbols", + "objc2-uniform-type-identifiers", + "objc2-user-notifications", +] + +[[package]] +name = "objc2-uniform-type-identifiers" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44fa5f9748dbfe1ca6c0b79ad20725a11eca7c2218bceb4b005cb1be26273bfe" +dependencies = [ + "block2", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-user-notifications" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3" +dependencies = [ + "bitflags 2.13.0", + "block2", + "objc2 0.5.2", + "objc2-core-location", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc_exception" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad970fb455818ad6cba4c122ad012fae53ae8b4795f86378bce65e4f6bab2ca4" +dependencies = [ + "cc", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "onig" +version = "6.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cc3cbf698f9438986c11a880c90a6d04b9de27575afd28bbf45b154b6c709e2" +dependencies = [ + "bitflags 2.13.0", + "libc", + "once_cell", + "onig_sys", +] + +[[package]] +name = "onig_sys" +version = "69.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e68317604e77e53b85896388e1a803c1d21b74c899ec9e5e1112db90735edd7" +dependencies = [ + "cc", + "pkg-config", +] + +[[package]] +name = "orbclient" +version = "0.3.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5df339f526ea9a60e371768d50efc2f2508c7203290731565d1f7a6f71d21747" +dependencies = [ + "libc", + "libredox", +] + +[[package]] +name = "ordered-multimap" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccd746e37177e1711c20dd619a1620f34f5c8b569c53590a72dedd5344d8924a" +dependencies = [ + "dlv-list", + "hashbrown 0.12.3", +] + +[[package]] +name = "ordered-stream" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50" +dependencies = [ + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "owned_ttf_parser" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36820e9051aca1014ddc75770aab4d68bc1e9e632f0f5627c4086bc216fb583b" +dependencies = [ + "ttf-parser 0.25.1", +] + +[[package]] +name = "palette" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cbf71184cc5ecc2e4e1baccdb21026c20e5fc3dcf63028a086131b3ab00b6e6" +dependencies = [ + "approx", + "fast-srgb8", + "palette_derive", + "phf", +] + +[[package]] +name = "palette_derive" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5030daf005bface118c096f510ffb781fc28f9ab6a32ab224d8631be6851d30" +dependencies = [ + "by_address", + "proc-macro2", + "quote", + "syn 2.0.118", +] + +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + +[[package]] +name = "parking_lot" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core 0.8.6", +] + +[[package]] +name = "parking_lot" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +dependencies = [ + "lock_api", + "parking_lot_core 0.9.12", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" +dependencies = [ + "cfg-if", + "instant", + "libc", + "redox_syscall 0.2.16", + "smallvec", + "winapi", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.5.18", + "smallvec", + "windows-link", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "phf" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" +dependencies = [ + "phf_macros", + "phf_shared", +] + +[[package]] +name = "phf_generator" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" +dependencies = [ + "phf_shared", + "rand", +] + +[[package]] +name = "phf_macros" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216" +dependencies = [ + "phf_generator", + "phf_shared", + "proc-macro2", + "quote", + "syn 2.0.118", +] + +[[package]] +name = "phf_shared" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" +dependencies = [ + "siphasher", +] + +[[package]] +name = "pin-project" +version = "1.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2466b2336ed02bcdca6b294417127b90ec92038d1d5c4fbeac971a922e0e0924" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c96395f0a926bc13b1c17622aaddda1ecb55d49c8f1bf9777e4d877800a43f8b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.118", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "piper" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c835479a4443ded371d6c535cbfd8d31ad92c5d23ae9770a61bc155e4992a3c1" +dependencies = [ + "atomic-waker", + "fastrand", + "futures-io", +] + +[[package]] +name = "pkg-config" +version = "0.3.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" + +[[package]] +name = "plain" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" + +[[package]] +name = "plist" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da1d65da6dd5d1e44199ac0f58712d241c0f439f80adea8924d832384087f85" +dependencies = [ + "base64", + "indexmap", + "quick-xml 0.41.0", + "serde", + "time", +] + +[[package]] +name = "png" +version = "0.17.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526" +dependencies = [ + "bitflags 1.3.2", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + +[[package]] +name = "polling" +version = "3.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi", + "pin-project-lite", + "rustix 1.1.4", + "windows-sys 0.61.2", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "presser" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8cf8e6a8aa66ce33f63993ffc4ea4271eb5b0530a9002db8455ea6050c77bfa" + +[[package]] +name = "proc-macro-crate" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" +dependencies = [ + "toml_edit", +] + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "profiling" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d595e54a326bc53c1c197b32d295e14b169e3cfeaa8dc82b529f947fba6bcf5" + +[[package]] +name = "quick-xml" +version = "0.39.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdcc8dd4e2f670d309a5f0e83fe36dfdc05af317008fea29144da1a2ac858e5e" +dependencies = [ + "memchr", +] + +[[package]] +name = "quick-xml" +version = "0.41.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e660451e55124f798a69a5af3f49ccfbefbd41910eefd25caf2393e1f3473ec1" +dependencies = [ + "memchr", +] + +[[package]] +name = "quote" +version = "1.0.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + +[[package]] +name = "rand" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22f6172bdec972074665ed81ed53b71da00bfc44b65a753cfde883ec4c702a1a" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.17", +] + +[[package]] +name = "range-alloc" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca45419789ae5a7899559e9512e58ca889e41f04f1f2445e9f4b290ceccd1d08" + +[[package]] +name = "rangemap" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "973443cf09a9c8656b574a866ab68dfa19f0867d0340648c7d2f6a71b8a8ea68" + +[[package]] +name = "raw-window-handle" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" + +[[package]] +name = "rayon" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "read-fonts" +version = "0.22.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69aacb76b5c29acfb7f90155d39759a29496aebb49395830e928a9703d2eec2f" +dependencies = [ + "bytemuck", + "font-types", +] + +[[package]] +name = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags 2.13.0", +] + +[[package]] +name = "redox_syscall" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5102a6aaa05aa011a238e178e6bca86d2cb56fc9f586d37cb80f5bca6e07759" +dependencies = [ + "bitflags 2.13.0", +] + +[[package]] +name = "redox_users" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +dependencies = [ + "getrandom 0.2.17", + "libredox", + "thiserror 1.0.69", +] + +[[package]] +name = "regex-syntax" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" + +[[package]] +name = "renderdoc-sys" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832" + +[[package]] +name = "roxmltree" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c20b6793b5c2fa6553b250154b78d6d0db37e72700ae35fad9387a46f487c97" + +[[package]] +name = "rust-ini" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6d5f2436026b4f6e79dc829837d467cc7e9a55ee40e750d716713540715a2df" +dependencies = [ + "cfg-if", + "ordered-multimap", +] + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc-hash" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d" + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustix" +version = "0.38.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" +dependencies = [ + "bitflags 2.13.0", + "errno", + "libc", + "linux-raw-sys 0.4.15", + "windows-sys 0.59.0", +] + +[[package]] +name = "rustix" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" +dependencies = [ + "bitflags 2.13.0", + "errno", + "libc", + "linux-raw-sys 0.12.1", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustversion" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f" + +[[package]] +name = "rustybuzz" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfb9cf8877777222e4a3bc7eb247e398b56baba500c38c1c46842431adc8b55c" +dependencies = [ + "bitflags 2.13.0", + "bytemuck", + "libm", + "smallvec", + "ttf-parser 0.21.1", + "unicode-bidi-mirroring", + "unicode-ccc", + "unicode-properties", + "unicode-script", +] + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "scitano" +version = "1.0.0" +dependencies = [ + "iced", +] + +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "sctk-adwaita" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6277f0217056f77f1d8f49f2950ac6c278c0d607c45f5ee99328d792ede24ec" +dependencies = [ + "ab_glyph", + "log", + "memmap2", + "smithay-client-toolkit 0.19.2", + "tiny-skia", +] + +[[package]] +name = "self_cell" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b12e76d157a900eb52e81bc6e9f3069344290341720e9178cde2407113ac8d89" + +[[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.118", +] + +[[package]] +name = "serde_json" +version = "1.0.150" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "serde_repr" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.118", +] + +[[package]] +name = "sha1" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a978451301f4db1d02937a4ab3ccce137717b81826e79b7d49ffe3244a13c3b8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "shlex" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" + +[[package]] +name = "signal-hook-registry" +version = "1.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" +dependencies = [ + "errno", + "libc", +] + +[[package]] +name = "simd-adler32" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" + +[[package]] +name = "simd_cesu8" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94f90157bb87cddf702797c5dadfa0be7d266cdf49e22da2fcaa32eff75b2c33" +dependencies = [ + "rustc_version", + "simdutf8", +] + +[[package]] +name = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + +[[package]] +name = "siphasher" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649" + +[[package]] +name = "skrifa" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1c44ad1f6c5bdd4eefed8326711b7dbda9ea45dfd36068c427d332aa382cbe" +dependencies = [ + "bytemuck", + "read-fonts", +] + +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "slotmap" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdd58c3c93c3d278ca835519292445cb4b0d4dc59ccfdf7ceadaab3f8aeb4038" +dependencies = [ + "version_check", +] + +[[package]] +name = "smallvec" +version = "1.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" + +[[package]] +name = "smithay-client-toolkit" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3457dea1f0eb631b4034d61d4d8c32074caa6cd1ab2d59f2327bd8461e2c0016" +dependencies = [ + "bitflags 2.13.0", + "calloop 0.13.0", + "calloop-wayland-source 0.3.0", + "cursor-icon", + "libc", + "log", + "memmap2", + "rustix 0.38.44", + "thiserror 1.0.69", + "wayland-backend", + "wayland-client", + "wayland-csd-frame", + "wayland-cursor", + "wayland-protocols", + "wayland-protocols-wlr", + "wayland-scanner", + "xkeysym", +] + +[[package]] +name = "smithay-client-toolkit" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0512da38f5e2b31201a93524adb8d3136276fa4fe4aafab4e1f727a82b534cc0" +dependencies = [ + "bitflags 2.13.0", + "calloop 0.14.4", + "calloop-wayland-source 0.4.1", + "cursor-icon", + "libc", + "log", + "memmap2", + "rustix 1.1.4", + "thiserror 2.0.18", + "wayland-backend", + "wayland-client", + "wayland-csd-frame", + "wayland-cursor", + "wayland-protocols", + "wayland-protocols-experimental", + "wayland-protocols-misc", + "wayland-protocols-wlr", + "wayland-scanner", + "xkeysym", +] + +[[package]] +name = "smithay-clipboard" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71704c03f739f7745053bde45fa203a46c58d25bc5c4efba1d9a60e9dba81226" +dependencies = [ + "libc", + "smithay-client-toolkit 0.20.0", + "wayland-backend", +] + +[[package]] +name = "smol_str" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd538fb6910ac1099850255cf94a94df6551fbdd602454387d0adb2d1ca6dead" +dependencies = [ + "serde", +] + +[[package]] +name = "softbuffer" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aac18da81ebbf05109ab275b157c22a653bb3c12cf884450179942f81bcbf6c3" +dependencies = [ + "as-raw-xcb-connection", + "bytemuck", + "drm", + "fastrand", + "js-sys", + "memmap2", + "ndk", + "objc2 0.6.4", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-foundation 0.3.2", + "objc2-quartz-core 0.3.2", + "raw-window-handle", + "redox_syscall 0.5.18", + "rustix 1.1.4", + "tiny-xlib", + "tracing", + "wasm-bindgen", + "wayland-backend", + "wayland-client", + "wayland-sys", + "web-sys", + "windows-sys 0.61.2", + "x11rb", +] + +[[package]] +name = "spirv" +version = "0.3.0+sdk-1.3.268.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844" +dependencies = [ + "bitflags 2.13.0", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "strict-num" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731" + +[[package]] +name = "svg_fmt" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0193cc4331cfd2f3d2011ef287590868599a2f33c3e69bc22c1a3d3acf9e02fb" + +[[package]] +name = "swash" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbd59f3f359ddd2c95af4758c18270eddd9c730dde98598023cdabff472c2ca2" +dependencies = [ + "skrifa", + "yazi", + "zeno", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.118" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syntect" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "656b45c05d95a5704399aeef6bd0ddec7b2b3531b7c9e900abbf7c4d2190c925" +dependencies = [ + "bincode", + "flate2", + "fnv", + "once_cell", + "onig", + "plist", + "regex-syntax", + "serde", + "serde_derive", + "serde_json", + "thiserror 2.0.18", + "walkdir", + "yaml-rust", +] + +[[package]] +name = "sys-locale" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eab9a99a024a169fe8a903cf9d4a3b3601109bcc13bd9e3c6fff259138626c4" +dependencies = [ + "libc", +] + +[[package]] +name = "tempfile" +version = "3.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" +dependencies = [ + "fastrand", + "getrandom 0.4.3", + "once_cell", + "rustix 1.1.4", + "windows-sys 0.61.2", +] + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +dependencies = [ + "thiserror-impl 2.0.18", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.118", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.118", +] + +[[package]] +name = "time" +version = "0.3.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18dfaaeddcb932337b5e7866ee7d0ce9b76d2fd092997146f187ec09b4558a50" +dependencies = [ + "deranged", + "num-conv", + "powerfmt", + "serde_core", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109" + +[[package]] +name = "time-macros" +version = "0.2.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c431b87111666e491a90baa837f914fb45cd5dc3c268591b0220ff5057f2085f" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tiny-skia" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83d13394d44dae3207b52a326c0c85a8bf87f1541f23b0d143811088497b09ab" +dependencies = [ + "arrayref", + "arrayvec", + "bytemuck", + "cfg-if", + "log", + "png", + "tiny-skia-path", +] + +[[package]] +name = "tiny-skia-path" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c9e7fc0c2e86a30b117d0462aa261b72b7a99b7ebd7deb3a14ceda95c5bdc93" +dependencies = [ + "arrayref", + "bytemuck", + "strict-num", +] + +[[package]] +name = "tiny-xlib" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a90a0ca3ee6a69f2ad28fd11621a4c3f03b371f366be500b64df260c4ffbafb4" +dependencies = [ + "as-raw-xcb-connection", + "ctor", + "libloading 0.8.9", + "pkg-config", + "tracing", +] + +[[package]] +name = "tinyvec" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb4ebadaa0af04fab11ae01eb5f9fdb5f9c5b875506e210e71c07873528baa7f" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "toml_datetime" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_edit" +version = "0.25.12+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2153edc6955a6c354fad8f5efd38b6a8769bdccf9fe50f8e1329f81b0baa5d7" +dependencies = [ + "indexmap", + "toml_datetime", + "toml_parser", + "winnow", +] + +[[package]] +name = "toml_parser" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" +dependencies = [ + "winnow", +] + +[[package]] +name = "tracing" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +dependencies = [ + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.118", +] + +[[package]] +name = "tracing-core" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +dependencies = [ + "once_cell", +] + +[[package]] +name = "ttf-parser" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17f77d76d837a7830fe1d4f12b7b4ba4192c1888001c7164257e4bc6d21d96b4" + +[[package]] +name = "ttf-parser" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c591d83f69777866b9126b24c6dd9a18351f177e49d625920d19f989fd31cf8" + +[[package]] +name = "ttf-parser" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31" + +[[package]] +name = "typenum" +version = "1.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" + +[[package]] +name = "uds_windows" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f6fb2847f6742cd76af783a2a2c49e9375d0a111c7bef6f71cd9e738c72d6e" +dependencies = [ + "memoffset", + "tempfile", + "windows-sys 0.61.2", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" + +[[package]] +name = "unicode-bidi-mirroring" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23cb788ffebc92c5948d0e997106233eeb1d8b9512f93f41651f52b6c5f5af86" + +[[package]] +name = "unicode-ccc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1df77b101bcc4ea3d78dafc5ad7e4f58ceffe0b2b16bf446aeb50b6cb4157656" + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "unicode-linebreak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" + +[[package]] +name = "unicode-properties" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7df058c713841ad818f1dc5d3fd88063241cc61f49f5fbea4b951e8cf5a8d71d" + +[[package]] +name = "unicode-script" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "383ad40bb927465ec0ce7720e033cb4ca06912855fc35db31b5755d0de75b1ee" + +[[package]] +name = "unicode-segmentation" +version = "1.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8" + +[[package]] +name = "unicode-width" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasip2" +version = "1.0.4+wasi-0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b067c0c11094aef6b7a801c1e34a26affafdf3d051dba08456b868789aaf9a4" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.76" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c62df1340f32221cb9c54d6a27b030e3dba64361d4a95bed55f9aacb44da291d" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "167ce5e579f6bcf889c4f7175a8a5a585de84e8ff93976ce393efa5f2837aab1" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3997c7839262f4ef12cf90b818d6340c18e80f263f1a94bf157d0ec4420380e" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn 2.0.118", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc1b4cb0cc549fcf58d7dfc081778139b3d283a081644e833e84682ad71cea24" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wasm-timer" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be0ecb0db480561e9a7642b5d3e4187c128914e58aa84330b9493e3eb68c5e7f" +dependencies = [ + "futures", + "js-sys", + "parking_lot 0.11.2", + "pin-utils", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "wayland-backend" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2857dd20b54e916ec7253b3d6b4d5c4d7d4ca2c33c2e11c6c76a99bd8744755d" +dependencies = [ + "cc", + "downcast-rs", + "rustix 1.1.4", + "scoped-tls", + "smallvec", + "wayland-sys", +] + +[[package]] +name = "wayland-client" +version = "0.31.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c7c96bb74690c3189b5c9cb4ca1627062bb23693a4fad9d8c3de958260144" +dependencies = [ + "bitflags 2.13.0", + "rustix 1.1.4", + "wayland-backend", + "wayland-scanner", +] + +[[package]] +name = "wayland-csd-frame" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e" +dependencies = [ + "bitflags 2.13.0", + "cursor-icon", + "wayland-backend", +] + +[[package]] +name = "wayland-cursor" +version = "0.31.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a52d18780be9b1314328a3de5f930b73d2200112e3849ca6cb11822793fb34d" +dependencies = [ + "rustix 1.1.4", + "wayland-client", + "xcursor", +] + +[[package]] +name = "wayland-protocols" +version = "0.32.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23d0c813de3daa2ed6520af85a3bd49b0e722a3078506899aa9686fea58dc4b6" +dependencies = [ + "bitflags 2.13.0", + "wayland-backend", + "wayland-client", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-experimental" +version = "20250721.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40a1f863128dcaaec790d7b4b396cc9b9a7a079e878e18c47e6c2d2c5a8dcbb1" +dependencies = [ + "bitflags 2.13.0", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-misc" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e9567599ef23e09b8dad6e429e5738d4509dfc46b3b21f32841a304d16b29c8" +dependencies = [ + "bitflags 2.13.0", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-plasma" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b6d8cf1eb2c1c31ed1f5643c88a6e53538129d4af80030c8cabd1f9fa884d91" +dependencies = [ + "bitflags 2.13.0", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-wlr" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb04e52f7836d7c7976c78ca0250d61e33873c34156a2a1fc9474828ec268234" +dependencies = [ + "bitflags 2.13.0", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-scanner" +version = "0.31.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c324a910fd86ebdc364a3e61ec1f11737d3b1d6c273c0239ee8ff4bc0d24b4a" +dependencies = [ + "proc-macro2", + "quick-xml 0.39.4", + "quote", +] + +[[package]] +name = "wayland-sys" +version = "0.31.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8eab23fefc9e41f8e841df4a9c707e8a8c4ed26e944ef69297184de2785e3be" +dependencies = [ + "dlib", + "log", + "once_cell", + "pkg-config", +] + +[[package]] +name = "web-sys" +version = "0.3.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8622dcb61c0bcc9fffa6938bed81210af2da9a7e4a1a834b2e37a59b6dfb6141" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "wgpu" +version = "0.19.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbd7311dbd2abcfebaabf1841a2824ed7c8be443a0f29166e5d3c6a53a762c01" +dependencies = [ + "arrayvec", + "cfg-if", + "cfg_aliases 0.1.1", + "js-sys", + "log", + "naga", + "parking_lot 0.12.5", + "profiling", + "raw-window-handle", + "smallvec", + "static_assertions", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "wgpu-core", + "wgpu-hal", + "wgpu-types", +] + +[[package]] +name = "wgpu-core" +version = "0.19.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28b94525fc99ba9e5c9a9e24764f2bc29bad0911a7446c12f446a8277369bf3a" +dependencies = [ + "arrayvec", + "bit-vec", + "bitflags 2.13.0", + "cfg_aliases 0.1.1", + "codespan-reporting", + "indexmap", + "log", + "naga", + "once_cell", + "parking_lot 0.12.5", + "profiling", + "raw-window-handle", + "rustc-hash 1.1.0", + "smallvec", + "thiserror 1.0.69", + "web-sys", + "wgpu-hal", + "wgpu-types", +] + +[[package]] +name = "wgpu-hal" +version = "0.19.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfabcfc55fd86611a855816326b2d54c3b2fd7972c27ce414291562650552703" +dependencies = [ + "android_system_properties", + "arrayvec", + "ash", + "bit-set", + "bitflags 2.13.0", + "block", + "cfg_aliases 0.1.1", + "core-graphics-types", + "d3d12", + "glow", + "glutin_wgl_sys", + "gpu-alloc", + "gpu-allocator", + "gpu-descriptor", + "hassle-rs", + "js-sys", + "khronos-egl", + "libc", + "libloading 0.8.9", + "log", + "metal", + "naga", + "ndk-sys 0.5.0+25.2.9519653", + "objc", + "once_cell", + "parking_lot 0.12.5", + "profiling", + "range-alloc", + "raw-window-handle", + "renderdoc-sys", + "rustc-hash 1.1.0", + "smallvec", + "thiserror 1.0.69", + "wasm-bindgen", + "web-sys", + "wgpu-types", + "winapi", +] + +[[package]] +name = "wgpu-types" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b671ff9fb03f78b46ff176494ee1ebe7d603393f42664be55b64dc8d53969805" +dependencies = [ + "bitflags 2.13.0", + "js-sys", + "web-sys", +] + +[[package]] +name = "widestring" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72069c3113ab32ab29e5584db3c6ec55d416895e60715417b5b883a357c3e471" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "window_clipboard" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6d692d46038c433f9daee7ad8757e002a4248c20b0a3fbc991d99521d3bcb6d" +dependencies = [ + "clipboard-win", + "clipboard_macos", + "clipboard_wayland", + "clipboard_x11", + "raw-window-handle", + "thiserror 1.0.69", +] + +[[package]] +name = "windows" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" +dependencies = [ + "windows-core", + "windows-targets", +] + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winit" +version = "0.30.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6755fa58a9f8350bd1e472d4c3fcc25f824ec358933bba33306d0b63df5978d" +dependencies = [ + "ahash 0.8.12", + "android-activity", + "atomic-waker", + "bitflags 2.13.0", + "block2", + "bytemuck", + "calloop 0.13.0", + "cfg_aliases 0.2.1", + "concurrent-queue", + "core-foundation", + "core-graphics", + "cursor-icon", + "dpi", + "js-sys", + "libc", + "memmap2", + "ndk", + "objc2 0.5.2", + "objc2-app-kit", + "objc2-foundation 0.2.2", + "objc2-ui-kit", + "orbclient", + "percent-encoding", + "pin-project", + "raw-window-handle", + "redox_syscall 0.4.1", + "rustix 0.38.44", + "sctk-adwaita", + "smithay-client-toolkit 0.19.2", + "smol_str", + "tracing", + "unicode-segmentation", + "wasm-bindgen", + "wasm-bindgen-futures", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-protocols-plasma", + "web-sys", + "web-time", + "windows-sys 0.52.0", + "x11-dl", + "x11rb", + "xkbcommon-dl", +] + +[[package]] +name = "winnow" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0592e1c9d151f854e6fd382574c3a0855250e1d9b2f99d9281c6e6391af352f1" +dependencies = [ + "memchr", +] + +[[package]] +name = "winreg" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" +dependencies = [ + "winapi", +] + +[[package]] +name = "wit-bindgen" +version = "0.57.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" + +[[package]] +name = "x11-dl" +version = "2.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38735924fedd5314a6e548792904ed8c6de6636285cb9fec04d5b1db85c1516f" +dependencies = [ + "libc", + "once_cell", + "pkg-config", +] + +[[package]] +name = "x11rb" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9993aa5be5a26815fe2c3eacfc1fde061fc1a1f094bf1ad2a18bf9c495dd7414" +dependencies = [ + "as-raw-xcb-connection", + "gethostname", + "libc", + "libloading 0.8.9", + "once_cell", + "rustix 1.1.4", + "x11rb-protocol", +] + +[[package]] +name = "x11rb-protocol" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea6fc2961e4ef194dcbfe56bb845534d0dc8098940c7e5c012a258bfec6701bd" + +[[package]] +name = "xcursor" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec9e4a500ca8864c5b47b8b482a73d62e4237670e5b5f1d6b9e3cae50f28f2b" + +[[package]] +name = "xdg-home" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec1cdab258fb55c0da61328dc52c8764709b249011b2cad0454c72f0bf10a1f6" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + +[[package]] +name = "xkbcommon-dl" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039de8032a9a8856a6be89cea3e5d12fdd82306ab7c94d74e6deab2460651c5" +dependencies = [ + "bitflags 2.13.0", + "dlib", + "log", + "once_cell", + "xkeysym", +] + +[[package]] +name = "xkeysym" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" + +[[package]] +name = "xml-rs" +version = "0.8.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ae8337f8a065cfc972643663ea4279e04e7256de865aa66fe25cec5fb912d3f" + +[[package]] +name = "yaml-rust" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" +dependencies = [ + "linked-hash-map", +] + +[[package]] +name = "yazi" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c94451ac9513335b5e23d7a8a2b61a7102398b8cca5160829d313e84c9d98be1" + +[[package]] +name = "zbus" +version = "4.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb97012beadd29e654708a0fdb4c84bc046f537aecfde2c3ee0a9e4b4d48c725" +dependencies = [ + "async-broadcast", + "async-executor", + "async-fs", + "async-io", + "async-lock", + "async-process", + "async-recursion", + "async-task", + "async-trait", + "blocking", + "enumflags2", + "event-listener", + "futures-core", + "futures-sink", + "futures-util", + "hex", + "nix", + "ordered-stream", + "rand", + "serde", + "serde_repr", + "sha1", + "static_assertions", + "tracing", + "uds_windows", + "windows-sys 0.52.0", + "xdg-home", + "zbus_macros", + "zbus_names", + "zvariant", +] + +[[package]] +name = "zbus_macros" +version = "4.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "267db9407081e90bbfa46d841d3cbc60f59c0351838c4bc65199ecd79ab1983e" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.118", + "zvariant_utils", +] + +[[package]] +name = "zbus_names" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b9b1fef7d021261cc16cba64c351d291b715febe0fa10dc3a443ac5a5022e6c" +dependencies = [ + "serde", + "static_assertions", + "zvariant", +] + +[[package]] +name = "zeno" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd15f8e0dbb966fd9245e7498c7e9e5055d9e5c8b676b95bd67091cd11a1e697" + +[[package]] +name = "zerocopy" +version = "0.8.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7cbbc0a705a0fd05cc3676525980d2bf5a9bc4adac6d6475209a7887cf59d19" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2e817b7b52d0c7358d3246da9d69935ebb18116b2b102b4230dac079b4862f5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.118", +] + +[[package]] +name = "zmij" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" + +[[package]] +name = "zvariant" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2084290ab9a1c471c38fc524945837734fbf124487e105daec2bb57fd48c81fe" +dependencies = [ + "endi", + "enumflags2", + "serde", + "static_assertions", + "zvariant_derive", +] + +[[package]] +name = "zvariant_derive" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73e2ba546bda683a90652bac4a279bc146adad1386f25379cf73200d2002c449" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.118", + "zvariant_utils", +] + +[[package]] +name = "zvariant_utils" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c51bcff7cc3dbb5055396bcf774748c3dab426b4b8659046963523cee4808340" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.118", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100755 index 0000000..6ddf10a --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "scitano" +version = "1.0.0" +edition = "2021" +description = "Scitano Unified Editor - SciTE menus, strict Nano hotkeys, Geany features in Rust/iced" +license = "GPL-2.0-only" +repository = "https://git.dcos.net/dcosnet/scitano/" + +[dependencies] +iced = { version = "0.13", features = ["highlighter", "advanced"] } \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..b49440c --- /dev/null +++ b/LICENSE @@ -0,0 +1,273 @@ +GNU GENERAL PUBLIC LICENSE +Version 2, June 1991 + +Copyright (C) 1989, 1991 Free Software Foundation, Inc. +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Everyone is permitted to copy and distribute verbatim copies +of this license document, but changing it is not allowed. + +Preamble + +The licenses for most software are designed to take away your freedom to +share and change it. By contrast, the GNU General Public License is +intended to guarantee your freedom to share and change free software--to +make sure the software is free for all its users. This General Public +License applies to most of the Free Software Foundation's software and to +any other program whose authors commit to using it. (Some other Free +Software Foundation software is covered by the GNU Library General Public +License instead.) You can apply it to your programs, too. + +When we speak of free software, we are referring to freedom, not price. +Our General Public Licenses are designed to make sure that you have the +freedom to distribute copies of free software (and charge for this service +if you wish), that you receive source code or can get it if you want it, +that you can change the software or use pieces of it in new free programs; +and that you know you can do these things. + +To protect your rights, we need to make restrictions that forbid anyone to +deny you these rights or to ask you to surrender the rights. These +restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + +For example, if you distribute copies of such a program, whether gratis or +for a fee, you must give the recipients all the rights that you have. You +must make sure that they, too, receive or can get the source code. And you +must show them these terms so they know their rights. + +We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + +Also, for each author's protection and ours, we want to make certain that +everyone understands that there is no warranty for this free software. If +the software is modified by someone else and passed on, we want its +recipients to know that what they have is not the original, so that any +problems introduced by others will not reflect on the original authors' +reputations. + +Finally, any free program is threatened constantly by software patents. +We wish to avoid the danger that redistributors of a free program will +individually obtain patent licenses, in effect making the program +proprietary. To prevent this, we have made it clear that any patent must +be licensed for everyone's free use or not licensed at all. + +The precise terms and conditions for copying, distribution and +modification follow. + +GNU GENERAL PUBLIC LICENSE +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + +0. This License applies to any program or other work which contains a +notice placed by the copyright holder saying it may be distributed under +the terms of this General Public License. The "Program", below, refers to +any such program or work, and a "work based on the Program" means either +the Program or any derivative work under copyright law: that is to say, a +work containing the Program or a portion of it, either verbatim or with +modifications and/or translated into another language. (Hereinafter, +translation is included without limitation in the term "modification".) +Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of running +the Program is not restricted, and the output from the Program is covered +only if its contents constitute a work based on the Program (independent +of having been made by running the Program). Whether that is true +depends on what the Program does. + +1. You may copy and distribute verbatim copies of the Program's source +code as you receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice and +disclaimer of warranty; keep intact all the notices that refer to this +License and to the absence of any warranty; and give any other recipients +of the Program a copy of this License along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + +2. You may modify your copy or copies of the Program or any portion of it, +thus forming a work based on the Program, and copy and distribute such +modifications or work under the terms of Section 1 above, provided that +you also meet all of these conditions: + +a) You must cause the modified files to carry prominent notices stating +that you changed the files and the date of any change. + +b) You must cause any work that you distribute or publish, that in whole +or in part contains or is derived from the Program or any part thereof, +to be licensed as a whole at no charge to all third parties under the +terms of this License. + +c) If the modified program normally reads commands interactively when +run, you must cause it, when started running for such interactive use in +the most ordinary way, to print or display an announcement including an +appropriate copyright notice and a notice that there is no warranty (or +else, saying that you provide a warranty) and that users may redistribute +the program under these conditions, and telling the user how to view a +copy of this License. (Exception: if the Program itself is interactive +but does not normally print such an announcement, your work based on the +Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, and +can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based on +the Program, the distribution of the whole must be on the terms of this +License, whose permissions for other licensees extend to the entire whole, +and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or collective +works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of a +storage or distribution medium does not bring the other work under the +scope of this License. + +3. You may copy and distribute the Program (or a work based on it, under +Section 2) in object code or executable form under the terms of Sections 1 +and 2 above provided that you also do one of the following: + +a) Accompany it with the complete corresponding machine-readable source +code, which must be distributed under the terms of Sections 1 and 2 on a +medium customarily used for software interchange; or, + +b) Accompany it with a written offer, valid for at least three years, to +give any third party, for a charge no more than your cost of physically +performing source distribution, a complete machine-readable copy of the +corresponding source code, to be distributed under the terms of Sections +1 and 2 on a medium customarily used for software interchange; or, + +c) Accompany it with the information you received as to the offer to +distribute corresponding source code. (This alternative is allowed only +for noncommercial distribution and only if you received the program in +object code or executable form with such an offer, in accord with +Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source code +means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to control +compilation and installation of the executable. However, as a special +exception, the source code distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on which +the executable runs, unless that component itself accompanies the +executable. + +If distribution of executable or object code is made by offering access +to copy from a designated place, then offering equivalent access to copy +the source code from the same place counts as distribution of the source +code, even though third parties are not compelled to copy the source +along with the object code. + +4. You may not copy, modify, sublicense, or distribute the Program except +as expressly provided under this License. Any attempt otherwise to copy, +modify, sublicense or distribute the Program is void, and will +automatically terminate your rights under this License. However, parties +who have received copies, or rights, from you under this License will not +have their licenses terminated so long as such parties remain in full +compliance. + +5. You are not required to accept this License, since you have not signed +it. However, nothing else grants you permission to modify or distribute +the Program or its derivative works. These actions are prohibited by law +if you do not accept this License. Therefore, by modifying or +distributing the Program (or any work based on the Program), you +indicate your acceptance of this License to do so, and all its terms and +conditions for copying, distributing or modifying the Program or works +based on it. + +6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the original +licensor to copy, distribute or modify the Program subject to these terms +and conditions. You may not impose any further restrictions on the +recipients' exercise of the rights granted herein. You are not +responsible for enforcing compliance by third parties to this License. + +7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot distribute +so as to satisfy simultaneously your obligations under this License and +any other pertinent obligations, then as a consequence you may not +distribute the Program at all. For example, if a patent license would not +permit royalty-free redistribution of the Program by all those who +receive copies directly or indirectly through you, then the only way you +could satisfy both it and this License would be to refrain entirely from +distribution of the Program. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any such +claims; this section has the sole purpose of protecting the integrity of +the free software distribution system, which is implemented by public +license practices. Many people have made generous contributions to the +wide range of software distributed through that system in reliance on +consistent application of that system; it is up to the author/donor to +decide if he or she is willing to distribute software through any other +system and a licensee cannot impose that choice. + +This section is intended to make thoroughly clear what is believed to be a +consequence of the rest of this License. + +8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + +9. The Free Software Foundation may publish revised and/or new versions of +the General Public License from time to time. Such new versions will be +similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free +Software Foundation. + +10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals of +preserving the free status of all derivatives of our free software and of +promoting the sharing and reuse of software generally. + +NO WARRANTY + +11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + +12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + +END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..35e09e6 --- /dev/null +++ b/README.md @@ -0,0 +1,223 @@ +# Scitano 1.0 + +**Jeremy Anderson** — info@dcos.net +https://git.dcos.net/dcosnet/scitano/ + +A hotkey-first programmer's editor built in Rust on the iced GUI framework. Scitano combines the menu structure of SciTE, strict GNU nano hotkeys, and Geany-inspired sidebar and context features into a single unified editing environment. + +![Scitano 1.0 screenshot](screenshot.png) + +--- + +## Features + +- **Strict Nano Hotkeys** — `^K`/`^U` kill-ring, `^O` writeout, `^X` exit, `^W` search, and more — all faithful to GNU nano behavior +- **SciTE-Style Menus** — File, Edit, Search, View, Build, Tools, Syntax, Options, Help, and AI-Bridge menus across the top +- **Geany-Inspired Sidebar** — Symbol tree auto-parses `fn`, `struct`, `impl`, `enum`, `trait`, `class`, `def`, `mod`, and `macro_rules!` definitions +- **Multi-Tab Editing** — Multiple buffers with dirty indicators (`●`), right-click close, and `+` to create new tabs +- **Syntax Highlighting** — 20+ languages: Rust, Python, C/C++, Shell, JavaScript, TypeScript, Markdown, HTML, CSS, JSON, XML, YAML, Go, Ruby, PHP, Java, C#, SQL, and more +- **Dual Highlight Tones** — CandyPop (Base16 Ocean) and Matte (Base16 Mocha) switchable from the View menu +- **Bottom Panel** — Messages, Diagnostics, Build Logs, and AI Terminal panes with color-coded output +- **Right-Click Context Menu** — Quick access to Save, Close, Build, Lint, Comment/Uncomment, and case transforms +- **Build Integration** — Compile, build-and-run, run-only, and lint with output routed to the Build Logs pane +- **AI Bridge** — Aider and Hermes/Odysseus integration points for AI-assisted editing + +--- + +## Quickstart + +### Prerequisites + +- Rust 1.70+ (edition 2021) +- A system display server (X11 or Wayland with XWayland) + +### Build + +```bash +git clone https://git.dcos.net/dcosnet/scitano.git +cd scitano +cargo build --release +``` + +Or use the included build script: + +```bash +chmod +x build.sh +./build.sh +``` + +The release binary will be at `target/release/scitano`. + +### Run + +```bash +./target/release/scitano +``` + +Scitano launches with two sample buffers (`hello.rs` and `script.py`) so you can start editing immediately. + +### Install (system-wide) + +```bash +cargo install --path . +``` + +--- + +## Hotkey Reference + +All hotkeys follow GNU nano conventions. `^` denotes `Ctrl`. Hotkeys are active when no text is selected and the editor has focus. + +### Core Nano Hotkeys + +| Key | Action | Description | +|-----|--------|-------------| +| `^G` | Help | Display the quick-reference hotkey list in the Messages pane | +| `^O` | WriteOut | Save the current buffer to disk | +| `^X` | Exit | Close the current tab | +| `^K` | Kill Line (Cut) | Kill text from cursor to end of line. Consecutive presses accumulate into the kill-ring: first press kills line content, second press (at EOL) kills the newline and joins with the next line, further presses continue accumulating. Any non-`^K` action resets the accumulation. | +| `^U` | Unkill (Paste/Yank) | Insert the entire kill-ring at the cursor position. Cursor advances to the end of the pasted text. Resets the consecutive-kill flag. | +| `^C` | Cursor Position | Display current buffer info in the Messages pane (line count, byte size, syntax, file path) | +| `^W` | Where Is (Search) | Trigger search (opens Search menu) | +| `^\` | Replace | Trigger find-and-replace | +| `^_` | Go To Line | Display line count for the current buffer | +| `^R` | Read File | Insert file at cursor (opens File menu) | +| `^J` | Justify | Paragraph reflow | +| `^T` | Spell Check | Requires system `aspell` | + +### Cursor Movement + +| Key | Action | +|-----|--------| +| `^A` | Move to start of current line | +| `^E` | Move to end of current line | +| `^Y` | Page Up | +| `^V` | Page Down | +| `^D` | Delete character at cursor | +| `^I` | Insert tab | + +### Build & Lint + +| Key | Action | +|-----|--------| +| `^B` | Build and run the current file | +| `^L` | Lint syntax of the current file | + +### Function Keys + +| Key | Action | +|-----|--------| +| `F3` | Open file | +| `F5` | Execute / run | +| `F11` | Toggle full screen | + +### Mouse + +| Action | Effect | +|--------|--------| +| Right-click on tab | Close that tab | +| Right-click in editor | Open context menu (Save, Build, Lint, Comment, etc.) | + +### Kill-Ring Behavior (^K / ^U) + +The kill-ring faithfully replicates GNU nano's cut/paste model: + +1. **Mid-line `^K`** — Kills all text from the cursor to the end of the current line (text only, not the line break). Cursor stays in place. +2. **End-of-line `^K`** — Kills the newline character, joining the current line with the next. Cursor sits at the junction point. +3. **Empty-line `^K`** — Same as end-of-line: removes the line by joining with the next. +4. **Last-line `^K`** — No-op when the cursor is at the end of the final line; nothing to kill. +5. **Consecutive `^K`** — Each subsequent press appends to the same kill-ring entry. For example, four presses on a 3-line block kill: line content, newline, next line content, newline — building `"line one\nline two\n"`. +6. **`^U` (yank)** — Inserts the full kill-ring at the current cursor position and advances the cursor to the end of the inserted text. Resets the consecutive-kill flag. +7. **Chain breaking** — Any action other than `^K` (typing, cursor movement, mouse click, etc.) resets the kill chain so the next `^K` starts a fresh kill-ring entry. + +--- + +## Menu Structure + +### File +`New` · `Open (F3)` · `Open Selected` · `^O WriteOut (Save)` · `Save As...` · `^X Close Tab` · `Reload File` · `Save Session` · `Load Session` · `Print...` · `Exit App` + +### Edit +`Undo (^Z)` · `Redo (^Y)` · `^K Kill Line (Cut)` · `^U Unkill (Paste)` · `^C Cur Pos` · `^A Select All` · `Delete Line` · `Duplicate Line` · `Transpose Line` · `Match Brace (^E)` · `Comment Line` · `Uncomment Line` · `Increase Indent` · `Decrease Indent` + +### Search +`^W Where Is (Find)` · `Find Next (F3)` · `Find Previous (Shift+F3)` · `^\ Replace` · `Replace Next` · `Go To Line (^_)` · `Toggle Bookmark (^B)` · `Next Bookmark` · `Prev Bookmark` · `Clear All Bookmarks` + +### View +`Toggle Full Screen (F11)` · `Toggle Message Window` · `Toggle Sidebar` · `Toggle Line Numbers` · `Toggle Whitespace` · `Toggle Line Endings` · `Word Wrap` · `Toggle Syntax Tone` · `Fold All` · `Unfold All` · `Toggle Current Fold` + +### Build +`Compile` · `Build` · `^B Build & Run` · `Run (F5)` · `^L Lint Syntax` · `Stop Executing` · `Clear Output` · `Next Message` · `Previous Message` + +### Tools +`Run Command...` · `Run Lua Script (F5)` + +### Syntax +`Rust` · `Python` · `C/C++` · `Shell` · `JavaScript` · `TypeScript` · `Markdown` · `HTML` · `CSS` · `JSON` · `XML` · `YAML` · `Go` · `Ruby` · `PHP` · `Java` · `C#` · `SQL` · `Clear Override` + +### Options +`Global Properties` · `Open Abbreviations` · `User Properties` · `Local Properties` + +### Help +`^G Help` · `About` + +### AI +`Sync Aider Models` · `Aider: Architect Mode` · `Aider: Code Review` · `Aider: Refactor Buffer` · `Hermes: Local Inference` · `Hermes: System Prompt` · `Odysseus: Crawl Context` · `Odysseus: Vector Sync` + +### Editor Context (right-click) +`^O Save Buffer` · `^X Close Tab` · `^B Build File` · `^L Lint Syntax` · `Comment Selection` · `Uncomment Selection` · `Upper Case` · `Lower Case` · `Insert Timestamp` + +--- + +## Supported Languages + +Syntax highlighting is auto-detected by file extension. Manual override is available via the Syntax menu. + +| Extension | Language | Extension | Language | +|-----------|----------|-----------|----------| +| `.rs` | Rust | `.rb` | Ruby | +| `.py` `.pyw` | Python | `.php` `.phtml` | PHP | +| `.c` `.h` | C | `.java` | Java | +| `.cpp` `.hpp` `.cc` `.cxx` | C++ | `.cs` | C# | +| `.sh` `.bash` `.zsh` | Shell | `.sql` | SQL | +| `.js` `.mjs` `.cjs` | JavaScript | `.r` | R | +| `.ts` `.tsx` | TypeScript | `.lua` | Lua | +| `.md` | Markdown | `.pl` `.pm` | Perl | +| `.html` `.htm` | HTML | `.ex` `.exs` | Elixir | +| `.css` `.scss` `.sass` `.less` | CSS | `.hs` | Haskell | +| `.json` | JSON | `.scala` | Scala | +| `.xml` | XML | `.swift` | Swift | +| `.yaml` `.yml` | YAML | `.kt` `.kts` | Kotlin | +| `.toml` | TOML | `.dart` | Dart | +| `.ps1` `.psm1` | PowerShell | `.bat` `.cmd` | Batch | +| `.conf` `.cfg` `.ini` | Config/INI | `.vbs` | VBScript | +| Dockerfile / Containerfile | Dockerfile | `.go` | Go | + +Special filenames: `Makefile`, `*.rc` (Shell), `nginx*` (Nginx), `apache*`/`httpd*` (Apache) + +--- + +## Project Structure + +``` +scitano/ +├── Cargo.toml # Package manifest (iced 0.13, edition 2021, GPLv2) +├── Cargo.lock # Dependency lockfile +├── LICENSE # GPLv2 full text +├── build.sh # Release build script +├── screenshot.png # Application screenshot +├── README.md # This file +└── src/ + ├── main.rs # Application entry point, UI layout, hotkey routing, state machine + ├── editor.rs # EditorTab: buffer model, file I/O, syntax detection, symbol parsing + ├── config.rs # User configuration (tab width, wrap, auto-save) + └── theme.rs # Dark theme: color constants, panel/button/container styles +``` + +--- + +## License + +GPLv2 — see [LICENSE](LICENSE) for the full text. + +Jeremy Anderson — info@dcos.net — https://git.dcos.net/dcosnet/scitano/ \ No newline at end of file diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..660a808 --- /dev/null +++ b/build.sh @@ -0,0 +1,2 @@ +#!/bin/bash +CARGO_INCREMENTAL=0 cargo build --release \ No newline at end of file diff --git a/screenshot.png b/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..151c061f6a0acbd2b85b8ef6533c266ff2dfb8cd GIT binary patch literal 64384 zcmb5Wby$>P_brS8Dheoq3J9o(%23h`28}dBH&R1NH=+pAA|)-&4BZW)gmiZ)NVjx< zdwkFP{c*1Acdm2%XQZBap8MYS-fOS5_V~%kh!NnEo^j^&y}3wRwgdFN$;ICZ-$BMKiqv(@W7~j*fmdGL>^^tLWf}-xRs;q z%Vg1$tdxaOl6PIN*_))%7kwc9pzVxte(0#Kqns@HySo7OpUsZF1oy5Qp7kxBJ?ngz5AHf{o*f_G;5bfQJ7|k>} zxZSGao`Z3`w62+EoAyS=cB@_b0!{)-#GeE$pVHJ4_Bbd*D}+j5cYVr=Ul55=YKdl> zkDym!5LoQXuo^2}MJr}JprM(ekm{1j)vRFBsWpEX5F4uz%V`mOmq$NUl8TB-{kg@t z& zG3eBG5m8nWlatS@9@u0YS$}oxkUSGoo*8xC&NKYsM(ytSa~(BqP%-O}#glJzDtW*t z@BwwZSE$P;A+~PJZGMRo9_4OlXD8fnXB^Mg$D4`YP z<>i}$DcPvV7-K_1LQ+y@Fvu+PYw5If^2y$V)8iGku6t`7R9*~fg-V%ndaI))gYg99 z?87y#Wt{P$HsL4XOmiKv#uI9_Zq6bl`T0*NXe>txX+=ZMPaYp^1wHl+62K^=NiGlN zaZ%Az$U6SL#k^~_Bs7+Sb8koL#l7Q9%?cZ}qNX(!;r^F-mQz&osyfvgx$hkB8qhrm zb}7@`w$TC1|Rb)65M$orV-d#kQu80YO{->4`RpKD~1Oj;O+#on~5q=-~vvGiBb z7?r%-?`<`%dxX@2Zi~IN0;A<`4C1q{5)tWC?|WL=HTsj%Ym{c6PtC}f-&r1VTp3R4 zWHoFxi6P(IT^)<%vQp-u_dGqOm5O9f4v~EM;>BRLS_+NFhb+_p#`G4-tifz3x3R(r zVfLhOsfXYB@33mX%1F^|W^K3ncepWH0k;_0t1H@D(iazq0!n=b9cP+?)NgkrTTWEM zUAoRi8yB~>MKKTQs^dC3I+6~uA8*bycPz;bI;Wbqhj+P=67U`~DzMOA|5PI?sMf&dj z`;u>?=VLWT#$)s7X+xg-s zgnX2~)N%ro_-0N1QBiaDMP6?1{%kcx3gHx0ypOgS0}SE62fEdtFfJR%b&1S(#z(X& zJ?jhKv5VDvm6cc0N9RMqWoaVO|8Z+ExW?&C=Y!o{_GuUCMxKD-Jh~6Ej~_o4xa}ex zFW@@Je}UN5&|*a%XG2)r{GNHVkY}7}cd9S@w`5f@Jd4=55H^Asgp2V2&Q@ge-L@>W z%K!Rt%dG5KqY_R6IWMX|wD>{&K$eRA9Sesg6AfB&N|Pn)BIO+Qxq_Y62zvX=xi-m$ znj-J+^4Kig8?H=9(apF1{ep64Nms?UbiONbD708q$^OL_YP1;58*zy};H59&qCDjX z`j+-+w#S`~Y&6ed`z$0k9xK;yLVQKx(*KxCMs;jq>{b!2D)Oo@(QKhyyT>E zr7^TU7`jr^qc3TuNahFy5;{`vV!fI1ly>AGhEc7s;TYMKH$6Dzd6r{ZYBe>v5?IrR zx`i_Fil8XjAf;FCR}R{$=;paWkQeloY9PAIYASa?K2@jKB=m+>Vc#O2G=FCX-|lo{ zf=Jw0-^XPR(s_nyH)%S8T-AaXSBj*fm|W;g^M~opf~n@IaB*b48}Po1a)uDMpVPne z-N^pt9jOZqgx(*PZ=rnH=g*$^y{pE9c zlIKSQjo!RsYYpqBuD?k4^b36!nvRgHhg9W*z!qKAb!mcC(o2MQ!UWSbHC5^9qqwIn_wl);a8S0>B- zmFowd$VfR{ZJLDn7gbr#c+V-6Z*pa%_jF8Sh|^c&*_!^du56pIq^9ev^d9P^*Lw8x zvgvlQYw6#B_aZNlER5yZm9C3T{YjZG!mvB!nhQiSqt|#QU+Y})J9$G*!d!IlzuDa$~`Nr{rnW~12w5zzZ`Cp=wJzhwLe1z z@pnjs0?83fTIyrX49ks1KC)Yj`Et0XaP|k=jGR#luQ%CmSd=}~lFb~A8W}EslTsMw zuMSCgXt!+Bw0AfFW266WK#GPpgia-^+Q{|k7+;Q|*Nhv}^mrhGQ(dPhX1_5&;Ofl% zhP{}=&A-Lj**ChdPljLXa2|(>2T4?2Q`1q35SmL$#V{Rg36fVK;zxb(#YOERS{PzX4Pp}4G|DXFF?x{?WCKf{CR@ECrtv00 zD2W@=FUP(_h|%47f)lIAIi1n|m0ORJ=oKzLNw;$0G5PiDUu_b}=kx>c-&$H)&bgTC z0z{&5$$Od=DjDK3SS%i6gH}jW5}v4XT(5tBsibzZ;{j)fk_h9f?wnfyDZSBd^JGH7 zdb+{j;||(_6{7-2bz4RTiq>q}rajGuuZOX_vbKGulpQ0qHkt%&gaT+wGequ-;s*Xy-Jx=!@%_Ia6FgnRQson!3c5kZ`c|eY)HXr zo=GE4S%Kisp{uG=}VE(3hX7N7GoGa_nRchpkjdt)pnhd;kgcRhB4`) z?whH`gY8mt9c)B*xxXqPp{NfGYU@Snl?WA^4XtUjFS8m2sx_pmnU5Ar6v_GYe3}b3 zZWv7=aVNda=-5|qO)+1${uZOUNjm-uBl7^rnK>mV9RZJbQq3nS2byeeyjRFAP4ek4 zG}UYydePuiIip$4ZG6MkwP`QLpCv%J7ItrB*p&o_U+wO8XRhOqi@sT5^g~gk^rLrv zL5bvSIPCX$PhQdF_S!7_9QB%75$&8RE{eotJ2WS3HcL>`UQeo5kOBwCDQ0`2$6%=+ z-IS7Ap7tfl#-zq&hlD6wDC#oKx4!4bDmPtQGQUrj?%U4zWT|j9*mK!_sFCKIp)~7= z%qr;n`efx`Z9B*+drPA;4DTFHNDKxAX=}MV=_TOZ&xg_rI5_-t#2WX*-{t1k4P=IL z4hposqj|tWG6z4m zTc?!mJFAOuw>UU&eK&qB>)oWjEDZo39y!V}k^x1He@#ix+BAF2xp@#HUyH|K6G4BV zn|&g70eMHW9PzurpA(_}Rn$w9mfEfQXtc)+aVzNYN!~QMKO8fg~KX3P8JDj&QzXKNkUC85qx)3ef^-jQ; zu@QunysA{>ymkwZ6W#O$HkJmmINAY91d$A6s})(CMe;eW-T7fMhgN2OoaIT=hQ*BU>an*AEo2L)6^F)-j^X8QeZ}Km;0%N zqPX=4Rnw1kt1h84w=&C#z%$9oYUjtY3Dq7aE&}gIeJzOYP8AAlwX?a5u~1R3lB(ks zos1YKj!e=v1(F%8;qch}d8!aoRI~-)s_tlwPb$QLZF! zG-69QqvDlfW#)8+b)-z1`_qj9O`fywi3GU;jaRMLj-^W66rp2uaB?aSZ7>`wF&nyR zC-mps1-ylM=!}BIp5={PBV&c;slKCQ6_DG~0sE-;m7DC%rhVxnR08O{s$r{GI5&QU z#$CB#{l0{htQ%G>MBW99+ZBYe1Kkz#dOv(dsLI7csK`%YIW7@V9Zv@^o8P_n2$?1s zfk#Aj_wHS{a;y!M~94SA8SlO9JFlmwnf zt7V?22N{P|c8ke0oRkNq=-T7IZGhx6*$@axmK5klu$YO2nEy+FbPBuGq+4&Q1ZuuD z0`k3n>#nFBmuj{V4?Jv84T$M%EXg-E*Q1G|Qb)=}TrOGC1d)mdt$M5*68WN2m3C>Ig1$foF zKdR(ubDX~9)mLI?R7m}pj1GP^P4S98EyeDHV4(gCg2+7XWGI!@s6DgkU~9hQMqsK` z%T{f`ZRWwmvxd8~3*33o8S#Euo~&_=WKjF8G%NK9|3=-(ZY-hM_6nkFShWC{`i*gQ2hnL7-}XaCM*$=95QPE{S?ksA7*v3MkBQ4ZaJK5-ghb)t(44l z$Au&4c~wQH#k45V5UQNUr+vDx1mRV7ny25dGCv7aTgt+4FW!6QYX*#iRZsGVP&<0% z?C!O+mkKn8KNXIW$>NH?#T*4w@?~EdJZ~0-yygT^R5DB}8Q!gzER(BBlp>sZ(k0GB zxwc%cc)y|P=^G}ExbTbB)z!uBldkImv#K<+COJC{%W~zAf&h__vFLjnj*vX4_enIeHRrBdZ!@xe2mL@weHi^_82t@+b*yCgr2Tp9EJ%pOSDfeU??cpJY8NISpE z<4{pip{Xp*bJupQ29J%l)AX`gdx@E7-g8JJ8DSl^=Hbri06+Q10P^S zCLj8;DzUUL_*~c|{aP8JNL@goM${ zE)%AYx%g&W{{;@o6S-fIDScBGU#A7D1}?bx5T3UeR2O0#LM^@(z9hvPk0Mja;3j>v zHQ$vd($<22E{*mbg24f(sqmVhvp7Hh2$3Zj5OiQzurG_)~!Kc#C zgsFnZ8!wA=n!|a&DP$9|8ihDN=;CF)ye+?Bxb za`9&v^&h zHK`bW(mqt`fy~e@Kq%0uHFDv`U+mS0u!&M=g;Z#{mL@?8!SpjVzL_C;sYW6roIy5A z=I%nqBrVc9;N-r>)%Xmj-4WvwD-#8msh;JZD?<|alvAGDJz}EzDm6;dJcM#d-jZe$ePEfwMrS0eFx5(B z6d{f83lz$df?AZ{)!aJSGX@}Tzt!_H%Ki@Tuu1Q&U&tP zuLQ1JT*rAEo=o$AwAt=;nh*=3;EV6wR*^$R*NtEG06R2V@9-LZd{d3_|A_As#iXTR z-|%-{_P3ZzZRjIlf%7Wjq+6cJY_K6|!gF5QpZrLd|_ zy3i^da`@|x{0>3Hn|7TrcS`w{uIo#xie4JBZ*RDh>`%Ex${r;mNJnqjH@U;Dj%IC- zFL-;|-;+1*?nOnEOpjU>v#AY^YN|)*XJ??LQw5lJtBV!5fQgZa7iEA zVO~~rHhpUK804Dh@zMpH;K0Xr+4R!DxiZYEOAVQXv7kF|PVyF)WHkVi$j$EU^sg%E zBenL+%J?4MvQ?3swIhQbX{E}VeJVfP@I;({eBLtX;|oRUV3cdlPLB{bLMZu^*Pn~_ zHcn0jQw!yO{+gaW<0|65JS^4B(W^*T8SAU=zYiPB+s^xX1$hckW72(3>w^YkVDC&Ek8R-Vo`A;c ztT1PZoY3vELSHq*Fon1Wk)kReXgC7I--FXu7AUq=$$Lw_i-{pDV!R}C*k?qwA|fojP+aA)6jJU_JGZga<5lDAM)f{8dS?ijrGU9N z0W#DSekuDIKki7YMc^4;r1YpNFK>u8V>e?AAzXxtM?hfoP^)!H=@ARb!$)Fl3Nh)~ zigTkEwu=|<(2`|zg-LRpqa%E7l)}d66p9F%@o$jWVb%4<*OqWe7C3Q z2+Dz)5K2pgMWvy7wBuuKty=RkwCtP;AJ4zXyy6Y-4`|rE|5Y2uCE1`|y^$cN5o{_xxT!elm0#M-+pU5xumejN=94V zbh)5l*xMw0OSDh7)jO~5w9h0-&@qK zLsCuMD!V1iw3%o2VNHZUJA$I;cB09pZmA!i3%BjYE_>IV9%iZ42A|yid1!CUROets zb0b?vKeF#rOw8LXb5%hMgx!`GrAw8Ku^>wNx>-dD^v@ z1THniaG1q#TA&6MVz{g(3k<|)K4kt$etB~%)d|qy^tI)|ZGQBAmMsoKUzI6LikNZ* z^9<$TCYAA{Blfn%czFT9P~a)qlbO?5LykJ=`H_2l@>Ek>%APHCfP>f zN=`Q8&e+a05r|wi^t-q&k#eq>tYfpjn(Ap9)+kL)2u4Z`qUNa^a5M?BNUO^dRe@e#jQGSfV{@ z7b6a0!j7^DPYt{Ia6UXwX7HcIMRXJ<)Xqg^fY@Q7`+1)m7S}uneFP==da@o_G|1)w zDQrKIQRa;x z$xJ$5y!pW|*)wjhsYmlhv&x}^pUtw$NLSeNa+^y!rgcH}XZ57CZ*ZjALPOS0l=|W@ zRA1(hUb>k-6H1S0*I6sgM_6r_DSD{A`s6>(va(TfE&m$k&&o+5BfSf}6yVFO>v=oJ zCwo&tuUUky864~sbqQ(!Ia6%f=R-uDi}L9VHk+QyP@dM{oMnoCGju<16v!U7uJp$( zko)X#1dQ6hxE=gmlv|t$5#r2yG03tVYgLQR5Np#-_&x=)3>g~y-?wuYn>gbcvKD*Q` zN%Y_g!zatC#0De99mwvp?LOI^EdY5fRn4MqN3l0fR=@shVrDKrW`(XT;%3Bri6=rE z^IE`hO_QWei7Y*?yL__ng zMs(yZKp*9o0jSBj$ADw2K}9xWE?hAH;MSj24y*#c%-mz~5;Ju3?kvTd+O=tt`LXoD zO=u{GR_r9jIYhSzl$l$AM?|IBF^SF#w-3diUTpH9c*QTR=K1rW=_<}!0^TPBJZ5a) z7nQ0G%8<=kycO9rv=Qv>KOV+cB2m40ya7wAt2u6l9^(?e*MX4nSLKc4cH7S<>>|0$ z@%B*~ovV|Rs-Q3N`{1Z{wJ&8jB?aCX?WOF@TkQ;NOGIf0(Jv#O`QKv1^w?*nBsK|^ z@t3sAhcRkbmybA4H(Y7ESW?W(XU;R=I@?N0NftA;l`Y>cK^yTtB&6%+_Nq3{bPA%3 zRS%$R*c--aPg!F}shzMv;LwP!R3Z8+?%NI^5AZB8DZ09afyV=T} z>r2b;Qv3oF4Ygolvh-cVSgEi zZ|mOm$qL)%e_srTL73aNJi&f3{Qpb;8F%Wqj(%5rrC#N)F&JBzzm|GYOsqLG^9hz= z`$i-B;i;jf>cM+2lIiJbee9n)ZR;yv<|3f8zzK-}u!!Z~e)Xih_&?v(fA4llh``(P z?4&Fs!}!4^ZO8)nZ0X#fgvTi>g%hn~)e-*kL@9QY0c?5~RZpB-ME!YHBtE@mW7)_HmYgNCI}Tzb=_ zxU7GD({J?W;pJsgFE)XqAWDqP)jWt$(e7af>f@;KwvJ|v3rFq!EM(Ro@LPU2AMZjx zt6TpL7@HX&!$==$1N-rrR!US@ShLbjB4o1GeN5aCfy9IZbNKV;&#zyO#ywQ<#>5gCrIGDJUkPX_E|uTld-8 zR#wt|BO_|E&s9~2n}R4fUi%T#qWUwF#B|&?MNZ;`JZtOfJl&)QO3YL~v{yTCRaRC~ z@j0ygs(%kmq%$bpkScGGlBS*8mIK!SG-8JQ`XT|h1~4Ez{)>Q5CTI5d7*uk{Kiz*B z{u+;f{59V9C~X%yv%zdhJD@q0UMOB!1{TvV@#}*QILmpasBGZR>h>mG{i8Ms+~(TJ z93A%n+?)WP;JUlQ!WR)h;?<899|2q-k_~0?4q5_uY5dzv*(MpK@3MS-n}OEU#WqOqf_YB^S?#|NYb?EdF7niQ0k zaur#-!X9@40wFFkM|6N3DtxsMI>`>&r%&b33VIq+nPMfwt)^Im%Uh*IJ!UfLC=RU% zE=+MuujE;OcV4Nl3Wf*F1@I6+bdj?p3k|2El2AIW#Q3J5+H-tEbq*PLJ*>*$iqK<`UJ-%>rBG=yHhe91w%rLIW(Y%468kdP4HyE%lK z3mdPgl0+K!8K$z_yhd@`9gk-6z@wI%*30@ky zLg=sW-Zd{JmFidScv@>F$f0-=xXHu&p+zF>k^N%t>}uK6B;aA#L1r+!vZ&HIrQexd3u={Hi*8*s)B_GdzZl;&Qs4_tvz!;-w%63NJLqqF*FUsqSx@xZaS zp1#RDqnBz-p=7MJbS8T31X)k#mX|eB#c$w#7jv)4TuL)a0UY4wa~*rsG0mP)Jvka> zP^vqtMgFug*J(n3-}Vx*&{%8#I#4D^n;~YDlGkpy&a*C!Kl2%@ap&EwTXdZLIU0K( zZfieHz8Z)xg3d4h^ZWPj)m01O#{yxaP`%p|1gh{;QP2@rs+XWdduM@8u$^lc-Ii9% z)v2>|@bUGfr{Dv2lh63)r+QZF-`_tZLW;SgxbgQdYw~ijT9Hx7tKWZG!pONH>gEP= zu=}i#;hS?^d&IWUrX}+rD^xh_ku>>J-M1dvz>ETMl_8s0%5Mh}TVov%wdfP@3dBe- zi)Ji&rHBTR10&0eWW>_X3@P+oPgWl~(WX8yjAk{&f~Q0T3tBIgb(9r>gD3~;TP4&U zR0dHyw*k>i#f)G`&IoT1KT26}ae1UDkt4E5wJkQ^7#rYTOCm_#JFbnJ5?aFve2070 zVR=w`6}V)zwat`O)98;P&z?O4YYlj%_5eYPu<{}AXCt#B6Qr3YE@GdF?Gi|+QhLoF zYfV!_Nfry!>Bnl!*K8^VYAer{yru}f@w~|$7X7NUpxOzUNe15`{creLhEl=!JuGY<#-Be!oF6 z56;*~p&?t|A})OQQ;fh0ZA$(xM05Ce+7#?nJntEI#)X_QVZXq6+x+f-D3SjyM*sWk zQvL0|t%>(^?>fG`8~*a|g1?^M`y=)3#^ba?IEZ(!mrW2A6cqel#rS_L!vFh~TU(k8 zz+$wyxru!+uuJUm<*DSC`Rv|=9zC-tHR>35(eTwPtMd2C(-2@g@6qmq}v z3kh!J&mW~yb2R`2P{Iy*)A{ z8ZTmvp)|fcA0Tou z;~8=2m?YK=Duv%How#y=uc)Pw4Xa~i|IstU4d|~UKxZz^dFFK^8r-?eMkpz*!PLGL^F335LM zAAygcZMy7DuAul6C~H_R_Q3C{g=zXpH%`bzqz^zt+hlyJpNa{^Pll6hHk_}wvotW2 zt@aP#;3&My>AH?#9|E<0V9#c*9c`Y@eH$E)^PgPAqp^}EY@Q+=^DYk9fCgo`xVUI| zAGip!j@enZ==ISZKR_B?zzXK{d9f?9hn?JzRaRAK*VDd;R@YL-r*u9#5+?yuJ6m(bD2bP@gfrrhoNp_Cvk&fjY zz#^rI$|WTYmR?rt64XF@Q_@Rc&|H&d)G6_~EJl?C$jt$at5dVkapmO5Sz4$3>G-FKI<^!Z3(S|~TfKK3p@abJ8foTs>a*4_0h z*2Ak-jBSqTwX5#HVP~RH-n+@)KYZQY-8(`!PXD$sLnpuk`wx1uQoGVH8!@ZZB>zc& zs!XEb>e`y+BC|?v+^m$Q{xHBns0cyAncyu1)16Elw;sF`j^DF;-Y1og^XVfW{R8Fd zyLZ3U*ViKkqo>kLg{Np#gg|WuHE{)!`u@Q|2^i~oSbpCQpB+^pz0lz&4qE_XB50*) z++r0@o5^@`Ej@GIK|LvAU2sD{(SRh(4)5|-7(8(;d%u0DF@q`?CAzc{;Og4MnYIE{ z&8Gw(*BA4+?Qf`PI~#U?eGW$r3;X`_CsA-1KxjhCms|e^c+1PjN6|uj=gu8+@))=+ zZt9(l4LQTVkh)7B+w84PKnR&AK(=80cL8hGw@PS`r~yZ@j)5DbuM3Pz8Ktt#CqN`% z+U!?HcYu~nbo<*fq~j^@`sXL1vtwIG4Uu~7>-tcI{8lN_0K_VV+CWEAK#fr^SpuWN z%>#ir|6m!J>RiarpPsm_UYy=>s&n{0dF?K@Tzw(n_JTSGeQ?VnP8!RNP2KiKufW|r zB-Y_OmwF3W6$wDnaH|H}@NQd}@YCb1F2A_o&UF$-^?vw89OB>4KRkW-umNZK#fOc$ z{(QY3Z)TcGOnRmvw2VTks*V5)O}Q-RKz4s*^FTU={Q%lHO-)UQweb;1cyL&8KKg$D z1?G>k$on#o^)9}EZ~ZcD{8##Mbn7nvvzh2-{NKNd*Fb1Plb!|K%TT5~4b-%zKKukc~D1ZLfww}wgXL(R=z_0jb^dbH!=nW4mqNwy-yESmLt^t7G*JZ(Y>Y$ zCy~2-sgs&}>6;6rR&v$N{Z#8~ZjRr!T7B#O%LVwK>+;ylHggzi2plkePTl5E)a}Ee z5cDqMs)y6|%e}vAR|prw2hn}QGV7}zR^4;Y3sexL!~{~?I)k3W^?Eh)+ntNieTPXd zCrdS~M-iTkqT4bNRZeS?@$~LaD=#lyy43a(4guB*fTbHuu3rw7bart;q^&^k0lbA% z11?^!gj-g@!`v2~n+@00imm4YEtyz&PcFP*BRxYK?um#hc#8>7Tnz~9S^V>d-DP{h zs`g+GP;g|YYuWmTNqqP2a$DwYhs;ohtG>*4<=q-8R_BRF5|s=!B6hNW^DI_K#Eh2h z)N)YOlqQzdxc&LN7gU#cx@1>&*Yc2q#ek8jz-c|MW>8?{sO^djb)$dohQ@QkSs2Lml@dyQ*6WhdZ%Es0jK9_usAXv^wb1im+HN z%xY58LgH@FzL76aXzr@Ny_t?%SN-w;Vy-2E<|I5?Y$x+@jDz{_vLn&bQv}}9{O5sr z-aRcn1HIkch3%QVOME4}t?_I>MC!&)d@Q(a1%LiEadLXC>eT*hxWJ$pP{}c5?7?_^ zucYT^SH15)zwaZB=`W!g;q^5pB)w)oUiY^xLOxVpv^TJm zH0Sh|r}n&9+jnnXQ>z-_(VfMa?R~)EzmixcWVKlBEHxL;=d?DmYCIE%exP~Cut?M{ zbe;H4vZp7}!B~AyeIb92AS$BH{PbDfx0`0N*~h4~k+biAZu<{1VVcqtIdcw;B1Y6I zolO~2$uT~Q^P2>tkdyOz9Pe{Yxhe9YgoVA+>Ogr0 z*Mj_sTnGT8dli?x#nZ5ke$%R|s;O${K5_TtO$mGZ`0jTx$P>Bn~jjJ6577 zE`=O;ZWztVPN6yfj>Vgm?u&|^=8gBP&88jlY&Ab(d8APAs?+MximPXT=`8~M&i#Ux zhAAR&`hBU|ex=(zty62El;7Ilzz~?M)OU!hzT+mx6DKqqJ*g#CcQm5hmZJAtK50)M z?>nc(CPn9#ml00GldglVC86ck0(zqi zDZD64AxA|SMede3=B+GS9fA!4?xNZDlb=WG^|aK?i^m4@n>kG?>&P0VB85%d7lt!i zRh{&bl-e%)3#}>sUnBkYzKj|S1!{TL9H=OVWUJfErcHPXUXGh96gZoy%iSMXz~`r| zUEL6gV9q|Gx673Kmho+SvJc6%%$gLyIpecQ5x6j4ta_qfw{t9QVY|h2WIpn~;}pqf z$kV8sQ7kjzxv1^=>|`KCrMcn{qGUC;N;b6jnzv*rEqUY@4&BJnI)|eHadr#dG&u{m zEftH`jph_T=9wZjevkjn8a=4qQahid%w}}2n(VFv*DI;4c>xD47Z?Vj_B?(A)fU`7 z7JvarplFG&g8rZa^&g5i1-iF%LM0q;K(%u2#pHM{ViQey$BsEAwrzikFlXGU=QEx~ zIhm8}OTjNcN4E~u?sqsGP~YE!fUlG4eRh8`{=33Yq>i-Fiqpn1#4QMegA=qPHG73E9C+QRYg=H3|e9 z-ldCXg`&N5;;%cyoKKIo7)|A>mjw5nQq?e(vyRLAF*Anhr|as?SF4yaf2CX7oNVuW zlky@fG|Fdrlg1ix>nf5lRUCa?wH&2qkHK5eK8$DmL&WIO zeXCo4pK`ZN`DyHIQrNN#YHVq$vF0}0d`C7F@&;)vm+WM=LqpAFMkM-Cn)xfY=55M~ zfcZh8669djjOY9xpD)&)Oh!xE@}qy39)8D%Wh_!zxa*BrFC69{uq`qdm0z~g8|7=Gy-j+3}V?)5=W&*z_}{3hxM zC3{sb;9WC;25fV>5l|@whvdHHMWPe{ZBTWLkxsblV$85!$byNP!2ex2VXpFi7&Qv@>KUw&WDy1duL zksHj(RmIv4*=<|4P5G!~l(O037}KOeW_w~bjUOpmXc9KKtivqp$KNV{Xn$6Ha#r{4 zOtT~ll~my!{g;23+tF&gBs zPfMEq9&-`NhVni3&o4Y1b%1e)#1zMC-|DojwE0xXDe@lh8lXOz)@Sp9ZIc%W5ok%E z=_Yf^hFJvUIS`vgtgZ7y)eSrM>tbvF1m_ZH*Y2JLxXfFYhobh`6G>B=tKXPCuzEtA zF*anmJiixITUN{clq?)Cr%en+Z*!+58KE4QFg9dm{PXYGO_elyQT0RECe?BX}5$$gthpbJH(Uce#9KD?ZuDI)R)v-2$~u2#o%c<=f5F2 z-yua`A{uFZC$XkzuXI2E!_p_jU}JeFXXrboOCsJPf3`ZyOnV=lsBg{2lqPON*_~sI z7+RMSLLP6M$#lhWb&lurS9+d$oUncV*%K-SrfP9#zmub-$SUzZ*}M)hVD7Pz)vjva~@J906b3VPdkq~P0Zq3`+&Yo#y z^Xv6_BzMuyOU$`SZa!Y_hYkusX0DkorV}^++WlxY9V+`*~=YnfmB{K$1Nny zQZb*Jl3)s@Gv;*8knr=N4P1Dk-#Cvz5aRCR#ZB6&b2ObvSL>EqDpt-i#y=x%V~980 z`H2#qe^u1S5xd+dK$J_?8OLlJN-i=zZgQ*DD}yruv-9`;`l_|e`buBVeD~*ItX^k0+X5|Hj{0@?@nmPadv$?ldw$=h})4aUAohkv? zd7lR5%cQtbwMV~d&t`c&Uq5UNV6Ih#VGW=-TCUloXJ%%?;4AF#EOdb2w?;-Y)e0@~ zS_6luTjj6{o3)C_&K&xp{+LFL1EDz>nDWQ}7=odfu`a*82fes$p&BLXv zJYqIxX;k-D?p${*cpIP_Azq{|goJ>AH`gA`=Wu-XQX#@(eO#iG)Gwspf9JL!r2?as zrOJn*GNDOxgP&`Z{vk)jxg(Z6-A-AK2U$b!YfvMIp%p=EIN391#zL`-Qk5x>t&}Zz z#{PEuv3bqATTSuq{=!SmBUIxv&_17tAIni-+B_7QH*Vcixdp@%nCSX>NN6ffss1{) zg{aqZu5&=@tLJ)Oc3jwa*b}xa%Xw$`>*?FWQ{$6nP6`U0y29>cqFeUlLyPq_q7NP* zzq76vL_Y{u+f*?F9kwUa&fXS#ShEN$K~L3WxwP$SBU@z7d+U=5jg@)y{p4FDl# zF+`83j&-NI-1c7uMVY;}?{YEOyuZ~H>o1xkWML7kQLVSBUSo!4IIz#j+gVP#5T#_g zB2eWB5EvO9;}yuPrTeul=M>K#@A_q!=keo@J*n=an$v*61+eAjmu`^28-s^ndw ze(ADWG6c1gL-*TT?q=i$cB}~F1^{;v8b)9Tkkb^buRrcQh4hRXDVzmfw_T^>naRO5 zJ-01|$uA&cDxXc(e4(YB{e+dIvVkolb7=qZV+Oc4yy?9eW1{ogQ+q=cvXA2TyW228 zJFr-?;qh_iq=+Bi zsm85d8o%TC^Paw=m%scA2IxgdRbxPn0@)ECA5Uqn&2xLc+U{YJi@^%}lU6VI3Gh&L z=lBP(f;4dJKu}UVL#6%w+Bti&*-SlXDrcAbsmk*l&c;SUf7b$#9j=fvVXl-JTm{j0 z!diQJdUjXY?-HMFGW=>GAtBjrqOby*4=~<$yiW)MP_VhV_qV!)LVD`ph+2$&K2D2* zmcS?cK>si@Wlw9g%6z@pG3ZPZrqSAo@M|}|UtL+T$@(uBAZa;wLL4SMTmLG0y0*j} zjvqK*oWL=4A%C%@MzvobxMJ)W_1k{b{>JY&yV%(QpxvBI{0O{F*=EhTeizRU=}WsL zjl(;u=G|Ytc)o4U5UnY|+~CZ9y7kI1 z3-U5#i9$##cZfi$l77PyI;HiG%$Lo4IHfda`WHYDVjugQqGxbUfBg7iFkab2_(lz{m0cP1PA4(PIHv*UdiFB;U zSQg7Wy(K+=UjYrKXE6Sp0Y?r}2XF$|F@R9bbLY;1f^TDM%Z9zI>hI6;sR}?;vrz!^ zE$6om*TvrXTN05E*U{?O04z40`SmN`ab0`nJ{X+RVXOjllz+eDnc4y-&APg}a}A%t z6#^72MaTfS_mLFsAdmwY*#-6X?9`n`4L%-0Ct27J_|;R8{jl;Y_RXs@o{Gb}C;?*a z=pw+w#a$gPpurmE*^JmfXTd@P>3EmlX(Nz~?cW;oU|UgW+28~_KmGzz3RXM@DooS{ znWyaz_X-;$JL#x`y|yf^CE~pj>g@Cch*?tzdnc!T&~%jZv?)nR4If5@g(-s98ygJY zBtO%8?@a0Z>f2hr6Q7ny*}JmEC`wFl=cz7;`(OyuC_zPpq5>(na?M8y3y#2TQ46vj zG(!|93&B6+ZT6q|~H$8d0NF==w^efOsJ*#8Y8fpP}Sa)Fo!{Y8d! ztizw5q43mSF3>wOX_UU|I|h-MJ#a(~W*&laWeDP!bp(qP)iPmF3+rf)l)P#htp&O+ znA|qNX`=3;4c~@mKLH&+<~u0X=xV)PA~IIttRgVQ$O@hGuk<{{bml;F^Xr?}9Bb^J zBpry39$LjFJy?YePDPCaCeVHVx3B1nyOfkjF2$Zg7}^DWhmDWVekrvDlg|mH2iRjq zRr9c3F+~-~53yP&0xsM6ubjc517oVJ3HXm?;x@Ln=oQlgzZd-{R`f3ZP;|m$HAhc-Z zZU==g0+OYG2k)?=xlBY<2MsW=FDc^6;0Pc{=``wy0Y)6z$lgHYSKC2ehgl8^S=mitB5%Z?Oagy}VcYvIfzAX04d)hMcbis79xJ&9_Mo5HL&SiQ>B1$# zKdli`0x;~?yG>dHzK7grv%i1q5jsQD3?CSPK7*iD{|wjx&7b*|6&hZFO2}rUha`^} z6)j=dMvU71^)Oa7?w|*+7Ixwfq%Wiq`w>hP!Lm4&IAHWfzr6E#l_*$)@*@}6O;I<( zp5kwcjP?_T>>v@CKQSE1{Zdg;p|-}V?_PBy0^i_aG>mCt@QvvL4xroXar`KMMc%KI z^$T%&5dLSM5X#FrQG+du^^pv6U*F=}#S}`09u5R%Co^Dh`*i2>)HxcpjE#+HCEEHK z7Fj}Jg6|j{U*QaDSWy!x!v5sR&lPHJ>tEpQJQ+31qk9bge$LK(W7akd)Q!Ncp61ht zZS3i%DtWwP_81l_jK|if$ReHjs+0^Hnu*JDoLhuuSq8bJ^lTYIBa}NhIC$^OJ;yu_ z$|(;ij~Upwyuj&UY48&yRef}L5CV}r#q88&ybH5=~wFmOTnA#Kd;>@7?peCi`>%mP!Y zY$4tt5jX$v)FM4@^-)~uv3j<|x~+zh73JPEo6dS?__`<8u-j?K*Q(S1kG(gK=6e0t zhuh7`RFRTMDnsTukp@)CJj)bO=FDR>5Q(Hv2$h*c$vjn(%rhZFhRpMr@prwo_gUwh zXPxJKf4^rv&p*%EYp>Pb;^RHs_iMOb*LB^`_Req_i#mfJusRUs|Entez`lK11|{SN z&Vf1g9;`cp@{XowYm@g-9`-Zh<$dyl&P#LVc5F%-_alX^x)Ik_Axu23uQ6upj4t!zOo*?6pbFBmrLVU}G+$mhzRslyDo=YS)^8p-R>VgzxOVWnC?4_9jm2`eTaEOI6V zW%7xf$_vFmXk6ee8Nft1Z zZlHW@(v_IBtq%o7aNU<_LfJ*pk}b`Cv=t-4RaBfe$P_7xE$yVGUee1DJb;wig#aD(x@p46rPD^4j}>7CTorJb(MZszSuA8Id| ze?4d^_Ul4vljVL2b3kuW(#I8Ee}OB(9zMc!h|p-x+hZ%E9EikZ^*FP`OfJ`4|q4XP<&$!?=&}}!NfX+f)>5B2?r51 zjkTH>Rli80s~Se*_&OYG5}BHmPC^4wlj#Duvp z?WL=hfKfFQQ4hhcX!=vEdY-yCP^8uj^D6?7OK5`QCx8`ibn!U{Kqr*gNNee$1S@2- zKTN%d$Mn(t=(}gW9of!CgSn0V9P|c13N70sTk@mXyvXizng~s571QhPCntXp66)_S zhc*;p`;DVLQYl!j`)Vf#v->09zr;dcdHLS!%~-kl;46SKDY;UnJt>nxM7Y@Z8fZNZ z($NK;XiRvy0KhB-Hd!ysT#e-eTc}3aB}HShio6(D&>zyf1KV{^(M^d)Q4O8kqci*$jMcArGV%OCYRt& z3&9&*c+{s*MC{P9ObBg5>BTRTt|H6-gym8&J0m0GyCw7w(5j6mz3Ph7OJK>h>XBl~ z>5b2cp(UJgR%$Mg96eoGwd|a)>-O95<1pRXL`k|V5_$_9r^1S8v) zuUG9B*u&R^-l<@5=(r(>SxpJM2T&6j=mk}|-nzACdN3EYd^(+~mOO>4jU`eyTj0Fcs__H~D5t9I_F zUU7_`|GcCf`$9-D2J{Y~nR*0%0KOa zDt4-!Z_-z+^>a}nD~aRSc6(XmPhYKu3(i+pyARlD#sUP$vERD%$x#tk&xJJtWe z0yt1PqE&d+$K;w=oSmDS#CPsKsbFFN4X2hm*g3?$wFl*6X?8dhc{QC79h}yeaJQ4d z-VmVad4*Dc6oooy779!0%{mXIZ69Y4f^f91VUrYMJEg3hnw&bK^y{50)m9RMiWs=| z@+-!mTPSW`!x}cV{E&B9kvhD-c4r2Hok;TZSnl{SqrinGep!Nqwr>?3%5HIK^ot;G zMf07+0&q9VW`-LXs=}nU%9`h3_lBM^(G#mpk;| zwFxsiW@IAb9tlDW8eJVP=Q2A&tkdF-klMK4s5;^nXkKc%w;I1vp_v*7VK*5JB&=j& zha`DoxUh^O0m<57HtClj)Oj{~l37V=DX5cdu(UFE${-7=L=YKycNh2%?vve;c5aY` zVe}vR4dsOh!X)TVv==AKj;GN1$4b9^WYIYABRg$TMa}7V-!otUCKAk7H?74^8Ke1~ zyvf_gk(j7ATF?VtQ-i7M^QN#O(|MxWq1I2gaU+2E<39QM z`5@DNKo|q5G4%R=-+^H-ySq$s5u%AV608Pl7>6}bL=8LVt2;n@uUg;W_IA)zjo@@u zxP|Wz!CVCi0*Edz3Z^uhA6Ztd#?+79a96l-XB42JFa11u>>$3p^!hJfj{#$3kVmSi zN^!Ed>-RHgrq9}FLB4??MActGo8>3ao_5{;eT?9HokKjJk4mEu-LuA{9j;urCqQHx z_{3?G9u!egQCBwk%VEf1yBR_+pfr9B5{(Td3o`q_hg5ZwZ>SDreM*vuN+Z{9I5>cv zT7;}z>HV*|U6mYSgK52Ef}>?`2N}jfep}r)`yH|LbE37jopVGB9ssa*d8u3v91GWY z3lFR8QX=ES)MOGWlYPB=U%;&d~)7^*=<{rE(jYbn7BIw;tN6(qF^c`hdTv9`W z8`YW>LW)h5xFWqN>2Pz*B^t?3MBms3sHX#!dTKtm<{3jil~jZ1`tJZc;_?!ePKX@j zGp;*Qo2Rxm0|9Q!jU#$8F8Czx6mJaqx;C{qx6Lf-w;*^r$zQ?+(i1p-SaWW9ypk+Ff8tO zt>>zlkC*lqyw8p{d}C1E%hp8ED_jruDr!hJa$llVzN^wr%V%^M)CGDK^K5MHAvHVA zS^h2bOd?bXj`1&yzehj20S2@3R^Qr`6KrIOuj(SL16va6Vm?RMAF&&X>#I*?D*!#2 zg@mm`H|yr7<UCA@OAk*wS$siUg|GRvn*nW9|xP z1pl~+DS4!?=YvsTHBE`Eo@_I0?y3oj#l8tspSCf?zZA0W{f68S?-Bn#aW=2}1M=Mh zy`r>P)0>b0N>4@ezhcVnZKEKVvKKaQ{Apl=nAR5g^n(q_ZXdB2kta)ZN_LY@4DKNKa; zwiPiOT-8^)D9@+JGXZ!hg4fXJ^)J(ue4|s*(Iy=RU)$SPfJgj>l1JC6kGf6i;q;Z$ z9PGcF?t_Mz0!koYGtGDUp0nF%vD7FTIQL7ksQ_~X%QzPWqBg)4N#1gSkhOfo=jV~e z%9F`JKr*(e%2-0MOUUY-xIz$*Lo(6h+9w|d!&=HVPvI|_SGBysiZMPeQnq&#_@FCr zF9)Ef|Nb$XTPU=$S9}LtdViHZEh#Q8{yLFCb1Xn8=!DZ$bOe+6Q`i-;R2jdkgCJSR^Ar~zuA0WV6y*eBj6tw04+pivPA4tRX849Q`;Oo|`UJp? ztUU<}v2=FG9H>azir_9LZ*{3L5jBwHI}@a2shN@?st+hlv9_jwl%3$`Z&)moYD`zw zQ6jyPW+a0dXNBw*1?nB>^RFKPF2_`McIRGpbuLpwX3H~nZ*x0Vj#)Do1;E&Ya%QKg%IPyKoOuT8tf z2?MO9nZcg^ej%t7h>sDpDrM>ZL(u%F_*wSl5^x}loMxw{ zAf{hScj;$1nZ$Fm^5fTgv`Mvw`p;s=1=H!15I+TN~RZJn%{u$YY-_TO>`pgcw`KzW>?`GEZnDv*-4wl+u2yc7C8A5N6);k#D* zIfO4K`^&%##r8_&<+$K>8W@Do@3P}!=aq_k`m`SNl)~S?!T_0Qij21x&^RBTInz^> zU(-fGD^%TC@q#OD)>~uBaK{8$Do?Iw5zQl(Q{6x2Y@~)%KiJpm&p!0C%eweukWj$=EY2`)1kNQ2AP*pJ#=RuuGD^W*=9Wcn#OYm)1SU3pI`B zp8aRuq)`B?Tx>+Wv(5=?$;NLo;^u7iiN0HxR$@BGJMzLBLR!1Jhpd-c&26;V0~a|* z3zb(}rrvqEQ*LKkP2ZpXfIY0->_`#Xb9h6;nTL^r!XN%vM>C5b(j;}(*V_Q+N$iGn z)dthNA}{gyGDx$Mk%lqFsd#d<95JZ{u23in3t>6te4$?kqx_hLxM@~GsfreeJq;+o z_~QKd8vL0qM~JpKHxXqsn-{ha%COtouL0<=VJ%{c1x(5q7H;SX(x9e|KBb^Af1uIc z-R4WIrg^_?gw;Yx^^l0L=zzFmMQ5&K#@{@|7HK)b`j;PEoDzIoeC+>_5YxlB1O|l1 z!{stu7gP-f1 z&+nunkdV+z9|DurgE8~$YV&qqa*yjPeEqlN8Q-*}jO~1?BY*A=cUSj4lB>B~Z6`!d z%HH5Rvo`gtR5vCm`O;Nw-mIDDtvwY@e4PTz7ND&iw~rsFFFn5^9hNL^ywZPL+}&iY z9<(=y@b3b*e$A9QYD`@}k=pgKAbW|;Az3uL=NdB&vu9CsRfFKR=^dA5&aqK^y~4O0 z7eESt3pL*XKz1PT0bCW)`?w*^9gKc-+0Ze%_lG+K_90GA>g_+w1n(<2b1fv+O9HDTBZD2C-C@!!sSG3atYuS9@_$2XsiR!p=eyq+-GLIaykCqdXK&?b;_k@SJ7?y3bFzKcMr+FaXqcGBnS}$w?#%P|-h1#y zEG2Tw)OG$RhQ&D#8D9k~X5JcCna{ImqDT;R%0B;9w?3BUHCms5wU`$ z(T9p)WCZg_Ol8sXzmZ*Ghg({U`{K+XV2&lIu3klAn1KwT^4!+mUiGT{ruYv9_+P^I zv05KVwrN)_5g?T4H$(J;w4|5-e>QZ3L-A^(s9*+a1kpgFR2NVTxsq8_asTYgUAIb} zB{iQLJAeJ7T^r|7>%(W(E=w>a>cuZc1hD_&y@1EPd|ceiOETfYjrOQ-;lQ_0j_G_m zDKz#Y*Cpk`?BQMWhpWuR6a$N`^$||OE-KearUub>{A}KuU#MY%2S%F_G$6@C=X*}A@kZopO}kM2C6=+7pWnobp43# z2#tn;+IPJPX?Om*Gw&O?$Cg<%D#_-m|26@hl+SB9)o~`bIjbH$DD=s&GN(}CN_N?} zX_Ly0GCWs(DYZp5t>o0Qdn6uCKK)j*<8So#+6#>=4E4+|Hrx1e8mkUzB}`4PNi#`@ z8Ee(4yNTrw&fMy8Yf+_mt68DSeI=8%eJZ#rY3`2aHmDkmxMuV&N(-`va2n+Fn0Dvy zOd1V2wbnCzFO$^1v`hcU=gOTz{>h@M@zSrpQ}l5JsRex$=uAayW zJv;8M&H!3FvA%Ie_sr$^KGSKPY4LFeS3bvbt}Aa!M6y?}-Md3JL=ivk-sEnU_6}U& zdYu<@6<*a1j@d*Z;I)@QBx~a3*4(WA?te&OTS9gP6c#SK+>npIBAdCe_gFzlqOVrG z$*anzLZ(tu-8bwX$y&XjQEK&_uB$nAE>!D>ORcqy@&PKs;bg8}PJB@7egHd$o$z5O z#lRfLQskkB#e)PTqj=GMC>%U4nQC1_s*sGDFL!0h^$LX zc)JNquDI76;2Vu7C}Go^zN)ht#F8qD-_1}s(0_Wnrv`ufbh ztpJ)#*)HCD{r)P(cW$e{bscIHwzvUfi#`Lt-u=&fH_lzM>hlxo*oQ$W)*pB*rlLQa zTnoQmcx`jCO8cah`L{=mCUP!Tt%H?uy3d!-*0xGU9e%w!vKBW<`DUk;e>n7EP>juJ zm1K3#pqs%u^+Pi;vhSJiVI8e?XB5%mtZP&VSsO-Z?hqaU8%C)9yFWY6fdlkMNcVm$ zM8H(_+O_Ba36KgePID@|z-h29%gieP?+ zP(V)0|Bd+02@15zCjH&rig>BWEc;5SDJgFbHLyaDOY}syso6X(jA8&AG(dO?5I=H3 z0rRxP1kr)P!EB7udw%|BVh~hWiL7LRh=jPgYaE5qJhtQ7Q1oII7!sf04NBC7M!-rq z{(`LM6)_*gmIuNR!FT-;(RCf7#a=eS)KV_sv^oqtkyA0Z5kq%N{5Yi_38P{PWWjM5 zFi2W3_w@Es?cHlc{8j4NLlQ&OyLa;%d?h6=|6|lAXzq7H{7X2O65pYY31Qq1IHmyi zUtU@9B0KQU4}MX?F$4N&AU532y7`}dXa3crX9~Q~J%#ccgM|_Se%I3cxYzyrV;%V? z@hFI2|JXVntv;K=YYB{|f>9h`3Wo9vdUXO_*`SD3kPv8c4_8Y@L80b3fro?zzkcP> zEZ}vq!YmK{81DRQad8a9IwW4}S4>rW9k~x)-x&~&V@RsJ1U?|4*C#&p&rdQiM5d;u zBC8C$ouTO_ry-s^84}qS6 zRBL1Fn)=Y$(Gd_&=RZy@)>zC5gb2Ot8CNH$4blvJRC%jf}!arq|7j~gP*f76soMrzrABx9x8Lw`%N9};8+@YDM9{5 zARIb(4B0`);>N$2iNYNk5Gwl`p=+*qM~!)DK5t^f&~ZUwngj!V#`S)eA%A zGI+dTnxpncJpiyY=r^>i9HwV1djd*Tv$PI-*;-ja2vG*Ci&n^D8H5cyg)t(IK9THc zg6{#Vh;D%^*vjwS2H+9>T);GV@+Rgxzq+~z&rb>p3S!yHog!LT%wb*N+wAV{o=zY? zxH~{I2QEHiwX9_mlQR4kdXjg!qta%Z!}6TlHFa;B`8tBaGvNW%@x2&wv90K0YtuZRhL59I?rT1Qr))LQB8V%=_53>CxTy8PC*XOxR$?4+o405xx^OweQK}9{~ zF!n+fFlWWDbC{j%7rv>duC5MW0!&&zfH7i+%|8cT4LpPt*&c!obnzwtN|@@(lR{8tyHt+ALAEQ=s}P`|49R1>pW zbk&5B#E~ykzPQn@!PAE%*uW1H;Ns!}L#Xc~R$4r>69W@z?t$mY@*#O0c64+H=PT%( zjFdJ$lexcTo1~egSE;Xc(~ zXnpNzfG~z7s#N@KKN&OcaWXTr1CPH}@tnuLaOe*H3D&)L_bz)&wW6%AxA%po$NU0p zQM%M_PJZ@jZUX)z$kEU44uB#+@I*y9h)DCfs0gd_ZFeJbAUur#UQiRn&-Ru0cn3lXA2(NJ>XKop~l!uH)cYUFsr3}ExN_sdi28+8C?YlemXifyOk`daUP#X zzs~(+ba=m)#av=rF=@+G%ku@qC}r|nJ$^zB7Bw$FIdtC2wCR^k??(*7o&uBWK&`_w z1!^nAb}5n;9NdKy%2pO<{RVQ&k2tm`NC(gwf{TJA&5hfb_|U}}bs;8j1FWnYJ{T*d zqdE#3@qc?zM>zIu$tyGseY0haoLae-*H`$Y7ttR zHpwq=HgvnDd~M;^j+IBr&&>=Nfe@d9=>q6eH)I+Ku0G)bBWgQP19{0HR&<#GqBs9| zcIc7NDS#Oj85`}P`bQa~gPC~{Lm>#8m>v+;$4JwinU=cxv9ZODRJz+?6>z(x_)|&A zd9PPnDIdZY455hh`(Il=W8An1wpFIscOaZhOiW-`m=PPZG>-e*(Wu+uilYjDRoB+O z1L{jS{}lGt!1L)XH4c4=T3-ZgH}$rCPuQ{NSZ{TtJ03FVi{N>y>vNXjG_D*Rm;x*l zX@|&>qQ8+;C%e}T^}1O9kjVefd;_RogolI3t@K)A$8Z%=Si&^;B}rJes8f97lrbU& z)m$%{oHZR5<^FRI1#fnpCbCch^&Lw8$fP7wRA4xBAzcWBfkF^z0itVW-F)T7fyUtu zbIBFU{2&xEe|y+mDBkYjSOJ1pe@~AMC0-fIHnHob*wohk{0#f8Zsx?0ENIti{ zIUG!beFVYMBz$WGP9R&M&Ij7*G~JBEXc|Ht+(3-^gGyi~_Z^`Ld$3@t?D#Kk)a&4; zNg^c#Rt6?~^=Gi0JD!SInS`(aV$A#y?Y{cFFOm%g>cOTV0#7ARVUX2 zG#wG3ak2!e%M{GD60a=^;M6HGDKBQ*G@rf_>OR>lhm#V;msJ>tbCgw>Lah@@#-kOrsj>rg9PnDkdzm8dChPZS*2Uof;4^+`y;n#2Fz(E(XJqjTEW8 z`0M4TY*n7Maz_=@rcr)N&3K7YZ)}7WU}8%O_nR$*cwwTK7}zO>OK)LmETM{oU)viN z!>|6zNBQ|}@p4H#q|XzxHR61X%5q(J`4Ei#?@>4d;>(!wt?D|}_Hn!~DcjddZFMPd z)lRjyCM=uq?={pkND?2!>W@6IxrzpbfV%BNX#$3vcp?K(`5z~tt=-W?M=VV_5@O65 z!=esK+H~77^bq#g8<-R_&4Mw3^wStBWO)kjHSN4gIuNFU*`_PMVxqB|opC;bncSDk z%49TWCh+vS@LQT%oJa|Ax372b;mi|3G}~GQuGy`(mgWSQuc$)&6^)E$7dlPu9kqDk$(n0R#&|&9^WR1xIEDMl9%kXy8bO{xN9KcYuO3(fzZ> z4m^RTERs8=&y5vnet|o!BCpI&3I;wLbM|kH0b)eJNeBZ}5+IZ;Az)mQgEZYvGmmgb z=&Q%`45?RhYm(lwWecGYa{NK(>gu}g;PVd5RgBNSY*2hu_wosG5Lb(Ifd456DvJBP-7z28zrP+o>T9>&1^1N&?&EATL|K5+DlrKksJJgg+hmzg+} zVEt+U@QWH@05d%~dBSl*Pfzcq9g(aaQn9`Vo6?KaWA}f;2$(lHz5#e-DJUJxZromI zKdSks`IhjcwEqd=7y2D*2Zwdp)bhR4+jF@g%fWmcHGdR3UE+7%z5!e$w+3k%;|6ki zQAg~|KVOFllP9V;OT20+P`+YY!6^Vf0_v|A&`DiS*6(qv#FGUM^{|jhj@b*xr2=C zPsdM(OZm6gwvdvqpiom@j)FoPd=OG{aw6)kx9^e)j9(1E1kA>>W)O8u1*p(O7~cWZ z`gfi%#Dx=30DT%k((>DPX99Y!;0%COh}D1ke4k5F0j=OUrGP$&Gz^rD_z^%rjUadd zI`PC~+xBPu|G_GrWoBlU-9uHoot*s7ck>hKGb|~vVDwN@1_T7Gzq9kVPkWcVfes^a zbLfBE`LGHE_Be*MVE7HN;y(t!1P9x(f?VohJLHFof7a6%?LR~LfB7V?|C=HG`b$8% zl6bJYDI8D@vXmhjAZQ-~IJHH37#m#8wUQJL_Q<`sT;@aL&Ft;v`QG3d3xe_#2mn6c*g=yhHE~*G=Nnr`b!+89HPhwoX9Fk@hwEW7wgg9L@AGK)A`{}-@ zi>=nlTCSY-I=e9i&GgjAyjriluH%g_a~;Z8?-Z2q{$hQ?XxdTq@GJd`wd4Q^6mJBP z8tnl-JV95b3AYsf`*CLGJjf$saA$`15}*PcT&5BZdn^L?=N`r-V2w4CoZt zQ}H~hrqfboZo+u)&7TuN*sMxz6+TU;e)m2_UvMK7$;`Yywi26lk50s$XzucmwNxJ`}YiJ({y*$ z^7`(MdT9D&e4ByPCm6dE)V2Af5)o(Q)^hwamDKkNlmco}Tq6u^^`{YxDs>ybJ?FVo zeVL6P?5cjk*#W;*FJ&D&g?!n`rs|J_b^J)M-sg+EU;xQ6`oW?FYm@e(Es7u1JfX71;A>KEvwM=(JEajizVvgn^>AILdha)lf)kHlGKnU%;^yXj0Cq}y zenPCz$<9vD25%IZgrJK%&b+A0c4~B&=Py^wxMNB_fBgKaT@iKTo^Y+*3mbhue*6fo z15xJt+)Xr>4dEriIok$AY0VhoOkUG{jaxDQMXEN#u@r9!TNlXv5^%Cn5Q>YV!alsc zU__wFc*b~c>pzeAPoe|;#;m{eX&el>;SdQ?)(`Nu0Da)+r~%eWht?_czNN9Nj3^vV zS#xhU8uz3aOXE$FyLce#M}hURE3d503!KGn1^;Ms-%sZ{{eCv8KVzkRvAhz!SBdI! z-c_@_&c&DS+rXpAL6-simf&Z2F}QKRzNe4A0;~-z6+(H1CX3f8bH3r)PAV3?jFsi( z8KtMR;%>{>)kMQXlup>KK*p+3V%&XNm(eK4aTz8jM4nnAIJGwLv)|-h{6|B7UrfO~ z^=!%2w8cQ~h?~gPq&s&GcNP|oenO8$IK(0%*ys}F*2!q1!-jP|)F>c>5le;bEuh*T zuvEMo#j@?bhle`b2Yh3y(B`vUtdqDN$Yg#Jkr6#4dJ9XpLQnI=!?Mr0&oKS_XbcVX zmvZty((I9Kf2Z}8|9x2cu*yw)dqU9$A9Q_jWr$I638#?FrA$Wc7_^Pt=yCjN$t0AOHKmj#qd3zA9L zKfYdw>Uqdk$Sx584bad_orMwaJEKZk854+>iF9jrn6i7)#?Fp## zOHhf;lRR#>;#l-u?O3K=MBS&xwTe?c?`V1SzhEdt^_5)={1NC>2ikLy*fRszWo2bi z;x|`+@t;Cg0V|Loa&i?c=wltgHt#@NQ8Q?)Xtu%6;aRkM)P-#42*sHgnpiQhAUi*g znek3{JQYbFs#@0dRV}!SsNQhsd`ZbE_e)v-U;+IY0|V@P$ABNVsK@Y7 zRoS6G$EzVRKy*-MyL7YbO)Zr)K!~@8e-a$js*~f-DOdvuYkqVj*o(?Po9Ao;%~Xc# zLpJ*9H&F;^FfoceNOfOZt*MbG_VErz%5I+ecT4xl4xmQcy~NnKHE8$B%8FmZkiQQ7 zbZ5f;y{=1fs^q^4C%O*JcKZ9Usi)6&UnRRf%Q5);Yr+g)O51a9Hb)4lSe4@+zt>7q zO;%<{@=Vxu@IG;Trep#>nQikbVW?S)sE~*mP*W5L_cMs+MoTz(6UydzUiFb|!ZMt| zA0ZTZB1_$hcZo{8w57!f>jp_dq3wyL0hCAbzJwMheS&0}#2WEts2WtR|G)~0f3AV) z(Shk?FhGrLA;WN8s|ob;KvE(KjSF>_y$QXq-D+MPW~I5U2s!Qee5m;wv1wnC7)skF&L+H$j{p{6(i5+AG#5<5&^-#t z0tFA*D%tc$^BOSVh3m!CEnAW3=ora!?DHDq(O} zz9LzRyy7rW^XY;D-kOr$DXVS|#H2se+e8%7iI)>2_RGblo?J^Z1Zp0C;d$3YaO<-& zE4F=!fd9xFx2~)PpoT!r%phXRf~tls-O0rT6d#aeTZcaMGLY@Lp4|9i1ZYG>yzv#J z4FBaQ1nedX<0f=Z1Wr|!ffg&BCjjeWi?|^noMh{M1WrG-B!>>v4ayw+&GAUOMp-hf z0L)Zp6+KHZ6dz5^QY;~}%dbE- zNmP*y6Rh-pyO~gq0?2H%*2%S(*}2B8BHacb_X70c@F*}rg&!I~JV6h6MhO!t%v_74 zadsK`^y(KUqSg|Z3qXh>nIKN_Rc^LAErzD4vi)? z(fJxnoUaEyC~>0RS%TUF(Z=*hGiGJa*fn5N`~10O92Vv6GoFv}!Ld4D9- zYzvEvgqk(gCDEH4{sOa{N9m5{1N(q3Qe_2iN<~_kR(XtsghbIS&6T4BU@;s;cK0^` zev7>vZ%liUhL$!_@mjYRs>&Z2abu7;3EaT+2L`ZtutOPYuCph26!N=j;Y7ZR=WBX6 z77(soT&15-`+&+!#-srgn5Q#jM2?%Q0OssRD;nFJDQtZuYfW)zBYX&n%E378VR|KVK=LkHU8St=a9oq#}t^!Smf>)HnY zFd*B0v;si3?VLZO_r{vV1X*B2WiWV!M9tlP@I1%HTmIQLAuZ@GQ=IhLPUQHNP|r7^ zDSnr3HsS1e6l0gT$qLXbV$5*Uda=_f2GL75$2I|dxCs{c3Q;8$x~%|I6aU@2r<@yM zmSFxv?+R=^wp9)Dk_xmhEM$bI2X@r_aC7xY!->0SeG?tCP`zT3)nERsdPME$Zy3@- z{6T1}2(daLZ(NzIRK_;DCU){b&a(BpX*uSDbO%rRwp&{8^pl3rn?2RqqGCA8!}PNL z%N`Y%TOnPxqOPHt`?BB9(u8Tc=6%kcJrKNlSEbE%pF{l0^IPVHEmw2rZjit;0taP8 z>_Teo+I5IXt)JdLTEO{^yQ6gP$d}Ax2j3dY?jLGOhVsU!s7mWcy0H82ud`cMHKSEa zAaUGO#o*(!UCq5E!;(6=&G6G>P50Sp@*L}&x#2zLmwN~5c3@0A(VlBv(lFmpQ&_oY z@u;vV%!iqF!6#a-F$IU_8LzgY9tJqd+Lp9}^TLk%C)E81oS!5Fdbb-8(7X@X*nz^L z(rrryvAisPETF932iGak*hJu(E|2GreVC->gr*FWA=swyfKaWpLeyRAiPwmy$bWHl zppR!QJoM_P%*x6bcMP(JQX1@{pZtzYp}sP2PBE^!$(lOF#6?8F+5bewGP9Tr+Ehr< zjAHX5hAIYC5^5idH@kP*RNbC(F>?Dca!-={QQi*NQI$L}*cGh^ZZK-?c4+Ldxf%%x z%weT6rJn9F!<`)o`>FTqj25Tltk`E;&sWohzi3S1cXTZEpSS4bAL~@>IIf&*PTT)M zs!ZXl5;@V_+&wq6qb@B<*+@cdny^11+DPzCk4a|16-Gir;>L5pEzkm%(eWR zN+;0L+pS){Z`WzBJ8kz2v+Wf6Hs}6DPqgT5^rzStRCUIkK?KQSpiUop_~^_txumok z`7~(fL2uwp=Ni%K?dlrPdG!ENr=Ngv2af7tZ$|T<0^e!~N7o0>;emjY(EIC`Jv<$X zA{HXs3$Kpc<9&wN@NCDz(GiQT)f2k0df>^+#coqU0>PBSQM#R1^ zq-zknz>xjC0U!XG$;-cG!hfZQ@1$8>lTk$$x+;i*m(b~LDco28u0T)SoZ8E8;L>T8 z9sDN=4sj%j2kkrnas78pMN@0(1 zScdDhVFUxy)t}wpyi=c=y0uOBU!ZoZzh0^xZ!!!_>&n*hz~*x9;FgHMvP1$qC!Bq_ zbe7>NvL2rZ+K+U}qK`Y$3g2rbkMCDJQ*Y$IZI&C!>T^&u?-VQN8qo<&zn$6oD)a4V z$Ykw1>Zg9^yYO~^W*x-ji%2SwJID)Bs35c?UWh-P1-}fGKX#!s8_+qN|HM1Tk~sf$ zeJWCgDieizSd6^OhF41Od=v^DIE%`aNRsoV8V@;?iuS zs(a(_kzXx~={*Yu80NdyTlQTaZIBO0opiAo>zGkGA#`M7s5HGWGO_UluapX)cwtwd_^@~+a{}@tF3G5m7PhX z*2!esa<^ak*Q^~?-|%(mGX8W^zD9eUriYQGi>QdDgV-L>=}>SdINXGb%Yi!U_@=lNnvgVIjTJCF%jbFV>)2+6s)hmUbTYr0P)h_&C*>|t{?lFmK&y3rs zbSJh8gX;RdU(Jv4%zA+qUBO&GaZTaf7~#t!$oH6p-?YgLi4x5%frTpuem;b%$$Jnm z5Zo^a_R<~Ym%!$cmx(DN{a>i1DC<#p!|2GV>*HVPfZS1Dvu*M(LdAly;T{aJz)Sc$ z(QWiD!f}+QT~@?S zg=3l>L?IP$SP~9l3vd)9`oWJ+?-SrZzzZBk1j+;sn)xtBoc2?E1F!)BuDvtxGTY4< z^$!*hz~%|2KxbhmMli$;M)1pSols|$3Gu@$Ta$2W5P&ZUwi#YSnNOJq;PXF3M+{6Z z#2|;Mp-RR8k?0N4R01Zly?K*cF$VX9*As<)jQ~j|Bp5NpC83}I@VSh@14}(XqCG=H zp(5kQnJ`4#2UMSM=>d*FwDFGC1WS@tWsA0!R)syNld!NJ?}QBlZWu7r5|%8%S6F{m zrRX*i8UTVrZ5jXhWh*c~gcR6f2r9;4{)sH;igQc;CZ*nH-bRgyo3v7JO5iudNzmlr zQvr}~A0=ffIwEvzfRtB(X%l7vipQCm<0d9bk#Qmw zb2ul^#Qyn~JH13D1Y`gVOjt#j65l9CyOHs+D`tkoQoYT**WpiH|1Z?@f9n3?X4ymQ zkXP;NV$88%QDZcR<7TufU|bD<1G`fX9KGb7=r>q+r-4gu=-3z zVc<~(OBhHY+ljxPpuh$Zi1~#5_|-wcxEqI&+JUQw;|mAimxZkdhBCO^Du6jV(eC?t z5n`$TJh&uS(uTM)$&JLZNFdhngBkcYB6OOc2)kv0tUZ6nT_un|b#;jk8*2Wqn9b{x z%NG=$9vmtH z{^bL~{__E0|MUO<+WDdX^PK+YIbomv&p!L#JlgR8t9>)H_WdM9R{W!thZK^VH*Yq3 zd03D#^`SPEOY=Sf6a9;PvHSf5VxNDJh}1UFzj)dAD6Q$p(K($BJHLP0=yS;DaQ?Hk ztIXr8^Pk4vAJ;357%wRa3r9k2ZC|c>k?X*^eFvil<=O3wUoN~lbY%U%JSdqw?>;8J zhX3`YB02l#zqa!zvi$$^n~T4+wVgbARPygfvYqGHn>TMNCf(n?`*rv4uX*!aH7vd& z_0O|Z|L>pW%x;hIg0}OK`qamRhuhoclQW%zxW->z%P=2?U*MK?JRVmXDI18 z+97@U@+n)E(*~Y>WhZbrW%Uu7U6ePE9_~K6z4|`IIDk!Ak3ebJdt1{@n%_R+zFZ*c zFlKV+VC^N!!_hb_66PR5H+i?`d3YT0E%2Aybfrxzl0#US)GE8?09{*--MMYsPDTUz z@GKJ8dt9aLy^BNSLmJD5#6A-PgZx`dJQccwb%NVhI5?m{*XaI{ZA!W6HRbalep7)& zox!pU)w!eNFAB!zrwy;EnrIa?GSAjO<>h_CC$~yP<-+`G*f;p68^v3*Y)^-zCDlan zZ@0?5yg1CH7hGFUi}*3RjBB;+@{!2@%ffE4@q)LstlNvwr$J0QvS{W%T(2%Y@2}7E z4HfpCLnA-3C2!pL;&;Gd@@<-p#^p~<$>&1_lgVla2GmzdKe>T#XVkty zgOaL}ug4D6zBAyvOxJ6ut}Y>8L)M$OXp)@?96Xaj{rob5ZLf%7HcGBa=%Wo~o z4&R`+rJ6e^F&3i}YuX&FzG-aiZBvu#NeBA#$1>8{?7mJPo z+7jSkmwp}+LMOWKkUzEa<;Ni*#!GWDAm%@MD`2h}XJsHaU~>j*?r}Hh3yx;t$GLXJ zmtSCCbH{t*pfm!3`nsXvwk@9D+TA6rYHN86%SF1hm;0Bh!k4-Ydph#BEifx*3azfp zUz9jgcEw4@WV6XcMaV<>C)@Ky?9Fnldj6WU-o4j;t+({_O8M~7?YrjB(Q9Q<`rfQ* z&nG#%wm94Vvrcb`fdm{>3vcONYdcnMo5@_dv^Jb_Z@Um^|NC}LQc82Vzl)A;P>gv) z*)aCqN{ht#_95y%taY*n>NvN1JTz&jN2{($zhuB5_E#*KSHqK#rboeEv0FY$noUS0 zi=;FOPoC5J7I6|wCGc*lQ5@T2_w0Pfb^y2E&na!XTygon*$BPepw(1Q;MRMl=8iV* zny${z);?U2`$oydT*C;w;G@8%zP0(zIElAZ*$=+yB(gvE+UI_Rn^pea<3}wmCyMUR z-nK1q`_z#iw=`?YwIyux(82PakAI0rdyx%0&6=?IjCPK1tIaZPo}3#!Fy7`Mm3W4d zA<{ej)%BAc>=icF?^VcT5j5`5`S_HnobQg=Xf49W=a6uEDc!ioZ+K&mziITvJt;Ub z(lk%qTAANs#PjEqmE!Vk6#9qS%APsgt}^S$qu=~0NTu}Nww1|j-IRzcc=@ssq`MQf zdGfyS|MUqadz}7izj>SUc*m{XCX^vH%g>pVy?0VRdv$pG&KHN4)sAp-o^hi+U0^>@ zqfA85-Vn+?dvp^Noy@Avjxf%=PfL5`=SLH|I!w{NbN_+=Z9CDl)*kQKq#lh|`hps3x zy}P=jDl%}Gr-XS%{aQ^cWytRZDR$*ZmuGDDL1ucp4>Qj=UMp9aH4jflKsheR;xgdk zel2+3_JcKxMq}LWx?{1&`b=7wMN=<$UzYZ(^owJvKL5-vjfRW)`xz@6o8q{0Mn*Vy zP5}}Bk*{w?YCHwkPQk#ZN*ZRHzdiX@^7Y9#yV1Iz114IVxM#R)*^<}}uAb!N-hQ@1 z_|*MF2dg9Uw-&#q3SNC>@lsC8ci_0S_-wbH4&yFb+6P9EU`CzU_Y9e+_YgJq`f$1Bi&i2r5meji%h*Y?K$Ik)h<=> z%FTTdzR)x_$HRk?Y$31c13g)uEk4JGYc~#IPyMmGokPFxgu^BX}U9x ztuoxSQ1e#Xx2VC3`%f7hSmeszZ8xaUzA8}ea^khRtbJAGrk`WlTCXS=5AxNozDwKa zR!D0vs+drjeMUn;-a&_?tMaTzSEOys>(}&Gi$I+?pssFZbrB;Ist4r7I(p{c6Ye_S z3GlYXX&*tZN=i?^e4*O2r|3Ru+4Di}dB;$!)w;vSI`#hmICm>h( z{g_A8_xOM~#kSh0{+E(G4miF7=3iS~wO=vRtnJ;q_dDzN!Zp%{L-r(_|GbXxMd|O} z-940d^JmU8H9Kz+kDF7;qHD9T?>3T>f(ISVRd1DKO$7tGiT``3}J-x?6mFY40)W8{qA%t$lm7Nb@Z7_qhwQvbgl7 z0H*#1gCB8G(mR>MNScs&>6be?f7FpaicHA9=tSW)(6w(5-_tUgvg1cn#z~Whl-@}# zm8oU6ug1}+>1&0?OMR^Pa{cnAongCqGP}*fFNIwBMeb>n|Gv9#^J?4ezrtS%J-(mp zk-yYi*ZKK=>_76H+MQ>ATq_t-bT_s=aVnczc;U^v^mM6>?mW(C1#T!P z_z>O?8WOrrFi%KPYE|E`$S&+DMh=Kh7a zQO-Oc>T;ZPekkBPnf}Rr?g!~c>gwurT{%2D7+cR&+;jJSwtLT0QW3hg&f%ufV)0@< zZXqF0?K=`@&%O@{NhmG+JXq@$=UT?{S%M+*KDL}k=It}e?(fN5zmp#f)#sNBCwU@$ zNKmk&s_IveT5I>w1{1wQkIZiyyfax@NnxQsv{$!1$AX4)^RO@%`}pe0Nxi2`e0*(( zekKKY#P?Qp3d#9hsxB?t(P6_prZaZXpGK%-U?qyH;`9+$W=EH~xAx{PH_ROMrL6CV zcxu>AhzFZ?wdzI69k2~+*?pLM%GK6ce=PW1S7;Z#%`M(1yie$3LN)RN3n#a)jn0jF z!<6w{tA>UKn*-_DoI_ce@7@J>^3-oVHZa-q-EF0n$!f)UpDT02?LjC(WF#c`O+YVi znHxPn>9FP|?rL;UgsLXrC8;uuqEzgFW1(=ulr8%~y~%F|lL202cdNp~&PjxX^}EfT zVSVuI&i`WXEu*U3zjk2>=~#423j$IC(p>^diU`tO5+WeoAxMjWG=eB0Ez%_*ASESA z2}q}Op1Iun|31(Aj`5B&p7Z&9*n6mp0gHRx_ixU5%_|NzURzmN$qdPO<@8eGJ7|Eq zjM58_BI&Frt20Vrf18t}54Xl2M5s(tdjOD4_jqU8hvSwKGodZcij7+R{u(Q2>*`sE$%R#3kuKH^p8dXB z^@q$9JYfQlAJuE-t*gFz3~!{y?!Ga`H4Pc8;o@Qy(Ax`RaY;xN5mF_betR5u?PO-~ z%?l{whs$%p&bZ70piE_?;1QmxKUEgH&Ch?b{=KNpSq)?%z{-0_?{CI_?zgrb?e8wj zQ5TaOeC zCZNqtvf!Y$kn-KOn1ISBk-2AdZLd&gBBxW|Jq$0vV3DV?;*_HMo%~zk_fbk(s%)6O-=0M)O_K5H`u8oBzHP zLW$z`KbzH~!T=fe^7f9R2%vb&iUB>zKA04;^MD!tj%#-uBQU3Xjcb9l0E~?wQV5f5 znsoSSWy)ZcEF}DXL!f!pP>Sg9yINT6K>x)kDysj?(cC<5DIS@*2pmV)h(fH=3uIUx z@DYG%M#94gzp+5-8=*n$AXlziYNGT$4{@m~s`$HysLxmj6RIXOAG zxYl9E&?fD5u)eai^tMTo6%hifjjpzDo;rY!Ln{n)T-@`hw1VH{B~7A~-o2N@^z#-m zhf16`>C#Jjbt9WS1lzVgc(aWyNWCw9@Pm3vkYTIeNlKOU744Ao@;ZS_4h+>GGl1N| zL;nhk449?l=PyDs(Vmoo%N07;qixe}tL3@AKD7v10|SF)61N3lVE~gc@iP!daB(?d zK4D~>169Q`DK%lBg{5UEtsBZsCDfoL_}NGUhqAJka$rq-E(dCEF;Lp>-6QB<+}er_ zfoUG(ozA2j*sxmiJ}B0RWZipEXD56$Ow(L-eSIBxA%Q1Dl-(?9RQ#~y)BfaYX<;@& zcuhRwcjPaWG%7g@GqYjfckgkFh&+R}3D7->-`^9y1Tc95WmFdaRQT7&mFG!fDPJZDT#yr0;b?Vn*^)^gGO;yjzdcjC+iM)A5 zqw?K&i>=?2Q#-NMp;6|eaQV0NkJAkWxNeEu`#rwSR}ig46Q4*&@3%5puocH{yY4QT(|t#UYDT%LJH6M@!50V{Z8GOmw7z&?DIpS++5qMCm%ZeLv5_=a$Tpb=4-^8 z+(|9_O4c85rkyfuJ6VkRdqmz1U42OP&XcOnKa%0^U44mz!-@qq0qC0Jz&Qd^jS%d; zM1V*YM4bwy5!lpYpm&l8cm>puRnSI*b;lKyfLhwmz+1~wj5=qQ+0_itfZ<}2SZzUV+uXA&&sz1`j2L9vyS_ISEs z1w3=WKnd2?(xkv0P`~C48(h4Mx}f0+;s|yDegOeeebN)mAcP$za|8JBHLPuJ#`v5| z48KL&XuXq@RZSKk9yV+b*%L7;yj*b|6E|8Ss8$v1Y46*tgS^Ycj+eS(qLP;Cm2Pm5 zZnO{|&%^SSqQiToWTDw=CAu{)?N7h@lC6X>C+pfuENqtFe^-8Zb0dRp%HU|gAO8g5 zv}j>%UC?1{bgO*MTZ;aCvg`0v`@xvM<*qT~>O~JrHOCXRo5kn9_bWeaZivi!vrFUt zsBke|3QqRLGMqNm)i{bAO}&Br&$-!fMyi5nlL|Dr`oRfUN?Hi;e_^l-$0Fj;1k;O~ zh1I}dRVh`qiNaM7%$eaMJuu$ew zoAmZFDtd5@hpDZQ-3Zn^+Fe`&^+JKNhR-`gc}mOmT3U5Mh4|Cgi9tQzVxw%1Q^0OP z{08@@6zr{mHWVHjO68Ts!O?-mjAD*ohl`DM%d-rQ*0y&;Ec>0LA~)|#ADW#wYiVMc zFi80vA@0jqF`EvSQ!9~Oa16@|UWF=7KHzLo+@l+~m`Y7Tu_1{UMe`lHou z9+c!N&a6z*DD^e3P(4KDKrH_hE0Hl#WSL}eNpgFtOS1YK^o6GCYi<_cmg_*waOlV{}#j%Hu> z_?^OtnQ!&1nnAlOWMt59jkAclg&ui>?@B1S7g$Eog z-d8>QmZLad8g+4;oOl1>c#=}+N#}fUi^TZtyI-;(yXoT6YN7CaRN>yisJLlEOnm!0qk+vuDr&97m`|_u0Qnzi1(NX&g)Xo`x+n zYt>$&)vL_e-87CZYVC6sUxB$x`re5QnW`Wzeg-TIPm2E6>{h?#=jYT_#wotml$9Yk zy417GUlK_Ao#{!skYZHuzxT>@(V74CYqlO|bi3zc<`A4Z!ngevyBCuE{nwxSe>}MP zZrCe=9X&Q!U8JrWasAVHh5hN=!66VZd&-fZHOX+4O|*H~IT5P~Q9*;N#=lu8u>zSE|gO08iu`5=1e*aGbY4 zbzdqNU`1dCT% z!_)+B2nayzBc)v#xDea8gY*|3DH8#iF7Sn7B00aSrZ#d=l>id+WyNfwQGVN(gFI^{3&=S1_t*XgAE9yNs$J^oR1lNv7+ z*whja9z3A*pfre(n_@yYOoop!66nq!Ty*%Td2<=pH7f4Bb| zZ=~_zFa;h%H;>-mvjSlzPI_R?mWhHWobf%R^O5ot2E7w8&&_37P{sg~jxSSqb{+j$ zjEMp;xN(|_N=j~yGW_jZ`R*CHg>O@BJJ9~8dwrG@Aa~@Gxu^VZ_qy;&PUb&Zl= z_)ohVLV1HU;J<=mXU@GAkT zby2A)DSeP31UzQo@cW$ak3XdV(}qQ`2tfK6f(FXl+glR>oFY1)*bWAtnPWjxXlk3m)?@FjM9ANojx=j!a^>Sft=F zdIWT*ecHY$&;xeh-Z33hWc&`r{eq-!r0gt zGDiyI0+`P=?DA?#42rzwO-Sg--q#btN*5Sltn_>$};ujPI6_K`s!#Xh15cS5O;wU_$?al!r*fkN? z1(*?%L-UzkAb#!gY)MK5e?l1S-GI`&u~;Bn%#nHttXHJr1N3>o>+x_sc}o?S27PGT zN;aZ1nu_^WNpUe^dt!XmGFoAG65#HFaK3GkbM-Pz!MSjrv&8sD4$(9V{* zeoD!|m{ftbRtN@q_|_WQ%O*gAVj!v}3#*Zzc~GLixVBbgkvk7pZwGE8J~IefycMQn zLnQ|eUwGAdd3m($0I}YnlV6WAe~CiMafu$oI^D*r^5-rM^}tmFwW*C(+An9o<1^8| zGMc*!_h?TaI8K>hn9`Z|N{f?ilMQu?dld+eVRZNRhp{M1IER-py!2}|lIsTsY~(2S zt#YE--@j|XCN)~x??D;p3iS^3ICfb_K7)*NNdFNLtIC2=08lSq^DAA^=E^XwqQ|uY zE|gwjiZ?ix~be_E;km zIeF5n^uBvUrNWD>VTPHwB%&Z;1HzLT%_1nYI{Xs3;{5Td13e&dHPnxhQ9+DL13cD1 zz$wYZgxYxl3SD3Xe%NsCyH4Kl>61t&d3!bZPN#lwp~~iP2yX;eT|YlR_H_V&^Gso; zmdgOqXV-LM!aM)wGA=$9J(?8b{m)2*1(DZwMMm$#mpq?&Fw6jd()PRiovtfMZu?XHprgDp) zz7emKWZLU#;55Z9C#LXSo}I~5Ca??mK7vj#&Q zWuTz!ZO0OYJ-k=a1vCOSSEhonJb_$>)xl^Lat(-f9LWrO*QoPKSaRi9H|4ubrGDu- zhR)IFz6Ty&p>=L01OzEY#L5IjPC~zxV~NMN4v@i%$jEr}2xa}>9xKCFc}Pe|Msdwe zT$mcJ&b<+<81dv5ZrSC6QUf9zVh8#h{`<~a%ZfVQzx$}E*Jrsv1fCJ z%$Xp{gm`6C?(vo2&(6-8*xF(q#T1y) zT+Ph~{R*Wi*R^-7psI=HBzW19)ZU%VVcIx$*+(T=%exVg}1IId9MU=yCKoSe&jGrn1BnYp+)1ReewBo}idiU)wntFmIF(ag&q zx2Z=n;U;&7E=wF)D32-30~q?0BYD=Qi`^_^`$jsLD^Gg+2F?9-o&G33?&%n*J}$aV zz$M3j>*lABmvb>nrbG$%cU*-&0S zc6O}z=K^S!4wKM4u}jD+1IQD$Rt;6i6lItJ>n#tjYXXB}FBfW1(Mw=|{jTjCIVzAJf?kzuH!g2SYs zhlyZQesx1zkrGRQrax#%nst@i*i<^v#FYtUzL58+S?OH9$#A@)o)7rqP4FnUceG&1 zQOK-j`*q`4$j&YEDp$uRCI&Yn9soooC(U&$%GNQUxR`6X2=qlMyjlmd+fX>Z{J@=? zk!@d2arpw!OS$EhaFwPI<>1N?(II_hB3p4YbJVCDFriVFbDec_rOW+Z>zrN6m#|vu z;Aiq3QkYTkJ8@byR0nV>aF&85yH>UV_%#n@l;)S|>-{j4``xDO41;bmx@rE=pl0Et z_=-@JC0Y7>lVH@2a13t6V{$L_^RPePt`+oY98pV23{yzuhf@BT)1{1ksAy>$z*s%~BM3pUo`eRnu(9=q41aG!>m}+Zq&@%%OA%qQj0xV< z&!527XESb-3EE=Jb3{MkT{P*H{*!&KHDa305E&YnQV8mM)G^9jYu0Aru`mY~i&*hT z)7eqn?Ap->%q2g$3yC~^2TNBmNT~x*UNPT#@>}hOwhMVTT8e^f_0!zqc9?k3A0VcK zFvfguI{{)jUi=U(oP1RF?iZPW-Z#-L-vYIJUBawGtNKE+^+D3Mj>?k0Ni;~mr$2ok z7yIqz02oB|qLUMr3c@)j7*t^PP~|OM8p+~Zx%rNAJ@VA#9Ru|N1D^a3{+3AsLc;Ms zG&Mbov3YL{O8uKzdLjoge2%b?eJv$@m~hCK9X4{jA7?Tz0v6|~n?-&U$ZiIsemSRK zjV*Qc_TuiOt6`#}x9}uXNK%*SX1+ zO_U&8VSTI~GHqG^GKttGE@00?X$<=f7R;G72@#}4_lw*?#0@*cR(83O(!A|kXz_gV zq#+23(O*g)L{yrte?UYT*m2AE}h3ge6{FmS6e{P%aFU| zbZl)bX7+i|02SVnIL``~y3vCvZ7AS0{fH7vo_fp1sh8G{X{vTd| z+{MaZvoWy(dM-+e{omnazWs{Kgw;>|D6LN}&UQcLNVLBdN9&~epDxqiPdj{CI?lMh zpqQ%tPV@E$qfha^R(4vtUN{$wQ#RfHznGmIXbiiYR=QjcOV@;n8j_G{Xwzr9O+L@$ zR{?J#dH?zlDc6la>39WvqoMOg<`mlrmvA<;^Vwg&f@nLwfsz5s3(zSIpJu`_dLMIMGr#U3?Jfn{={(s z^F?u6Kmi6BHOU#J1%+f+6$}q6XqYHNj3$UR6c~^aL+M zwbj831vD}*L-!xi$g(;S&`XNDuj>gA(#5ByJW|VQnD+pGw$(AqOhG5avS2AuIQUZLzMB_R5ayV<%BwxwHy$UBmE++AZ~B?~>^_R#eQYFv zhD+#;$$#t8niM(NUVMgAH~7+McwvfO)VKb_X|y)Q?R%<`$JSD()5pzo7YdkJ{mK_h z7p$IP$p`mJBp*(De8KNpeGw$&6Wa$R+IUKmP{=%xO_l|-@isV(!CY_&Nynh$eEIqu zFn(E$ddRB`nRO;u{B~pEg*6l~1q8EGl58A@juA?bd5AE3q_ak$k2n@yA&-1IprVgK zErChzlU;%j`sHvPX=e}ysifz&WU)(Q#blF{zwi+;X}R*9vRgl$0DF;-5i7{jvxN2( zbaaeoK{P@Dk?C1X`aO{?G_#lY1SuS24|C18ogel+PsDtEe6r)?G#-EMi>={nfTtD? zXg)KLcDfduFnvKqpkYPC2b_iwDWXJ^z2UOL4APLC(hRy0&>?&08E#hR6VqDo>~OB# z&DM-o2kT}STC<5Eu~j|fXxK~PgCe}^MYiXqX8g|K(B^Fw=*3LY(wR#lroF!*#rHEC#z?k9SPb7tBAAq*7P-B84p=(7lu{0x zXtIpy;M50jr=*kcBGt}26XswM)x|9!Q@!`hC(w*hq5`A-ND+K&yeItlYDPeguchs}**hIP@6!eINU z_FJd8vfY2sGAH1gfVIvDeSw({GWQ)kfuQ@>xD366e3OXW*SVi8lm5=nu#xQzh1h8A z3kzE0Ee|ipy`uZy5{p0AqR)+I35i#fcaNZrRyDIW{bX~Xq zkZd3%c6twIa-8RABH+8RAZJ-wp6{1JT)9V_FNX~sY?{;jxgFT{vOV5%6e2E}`kTr< z?tbidOYj{qTSLGXEiF)^kc`Xe20B$^Co|sd z%-oD$+dcCB!K6bPSSV)^1V<7Tbz8IjGj!|q3szHpi53N)UY0=9C1G`Xn6mhwvi%4D zx1z%oD`xWQYn27#4S(33v~%kE4wrZC#C}I%|L)KsYntF~_XB6t`>VvvuRLSAM{Cc` z3Mvx!_g|M&a7)Fg_vtn4uCCG3C)kzAK2)U)E5j!&Ub|4tqONeBd3@hAhHh$PZT_Pj zry!nxW_6_=aStIoKJGr*9*c3> z9IbY=d{~i?xSu>Dx?%hSf5~pTupwrwY5Hwvfnko)y_x2xY;$iHUt#X`(Y2ps#>kwW z^q|HSsGKYpWFDeoTz)F^4Xw~s!KXgWH!+@Ub6Vmw^ugUemsYVG>qnbY|24e!O!OCP z`l#HR_iXfQzm*7W2F&?@AVD@KzF==4M71b7g{u$47##_4B&( z{>ZOf8$Dwiha&t=bjRks%CQsmuY9{cZ0(-U*_B{^p?)5mXiYy-tm`#5k}M%sm&AMf zlNYn@Z=S3fq3xb|tHzqIk7xxpDz6W6bpLE%>w7o1N)?4VY9C;Fw9)XyJ2qtg=9!rP z3LpQ5gNho}()qF5Weu8pT54L;twBRU)LebC`s^Y;LyWD5jmMqKb5AYsn+Nu%YHk;Q zTl4O`EAr>`r%+9Pm1xy9!3`cGZ?12F56s-e61R5-GebJu_SIgTpYVuq{yr|9KvW#s zgbbqD-1?!#D*L$WC6E0lpUkaSm8j00=6;9PeyQF(oSi7vU1cWD3*GCIq%mhaN`fKc zk8hh;$KF2lJF{}+x$SLXWf^%&nDDCKq0#+E$@{P4O_$%XE$oVQe^A=3zv_HK^!EUf zbu&*n!8x1>YaVo3`QkDbLl)lznYu$F!3^Z|p+|tR>WK*VCaAXsX_+y({&6~b_)ev+ zW|_j>)z?ZTC=zj-u%vK($}qW4MYXBsN$Z$qb@1WE&!ZBNm(=d$pW9yy9&O4UzA3Q0 zn=!~@GF~KiGS=sKKVR#b;QCu0JRj1;x=TIzYVx(VHWK{z-Df;J?MnJvrHW=iL~fng-z?CF=asGf7_`@v14I)o`yZ7&QtIH_gFGI&qJkp}`>~H(I~7du>Ns=YxfQQ$+)(1;^i`hVmV6>U5?>vZGfvIjnvgdFMqY z_9o|vg_V|Tn3^?{amyYli2t=0KEqg{m$S@vSufPhzcr-m^H8I7em-Z_iI6>GhP3 z+V4YpVtYzzp5^V9_0LLTH`&Z{3=R#VOGy zn$2diRHH^kKnT_|eqMCoEtP zZWeDXE^C#Oj?896yonpE{bwP=#B!Wxh2iR3q1lI@bgJN?Dd)0XeI)sytkp4i zCqiiAd(!eqfz}<|5;+{Uo9jkxug{+hEE;|&j(YO0{Vh{9*|f)c=4w;dPcgPr_oCnQ zDMeXZiYyb~^>vC8ibQ-3gx74|9{8ooODZd>T5;o??9?YON3dhz?eq9QI(1iLjxS2v z9DTPK(8+8#`dRUC%XD3m@?uVdM|;%M=Ri|}j&NuQ%EbBbZIOrbk;q7Mba1|S znem}r&K&kluO&Z!*V863xTj}CMX*-BRHErR)_pQvDq%dg+q}qIn@<@LkurWHTs<1z zF0TIWaakW>|Ni`8iH0PnD&FZ{L|yUMcAlaS`>Q&Zy-pc9f%Vl-R?hp4a)zy5dxT&6 zF|xLIj45_76aRP)Q%<6pZtZ65?vG=RiJ)I&?QMr;QZ^3OV?PM0 zu8UvJyBLLI|KdOA7JCX9ZySS~R~!YQJ!j?6*4XjU*GY-6b2_&dIN|>^lv+uiUS8zm zPU3NGiRlS~r%O>gkt_QRwEv;hkqVNA@Cc-)ie#x1rihk*8ErqmJPb$wSD*E!jPyV( z%00$%6uS4IH z_x{5RND~BytRa_m=*nS>!uAb%{xh)sd`fBrCRlgLz|fdNp$A+T2*Uv4e;GR+~81ogl}MDn4-{o&GL_G^H~!*AHUxAEgall-6v42J0EkT)z0N#5YO=IHSJ_p9@1 zueB2Jm;>EcB-2$CAn`5A%F0fDbmDp9;OIEyusi_N07V4_pdQ}+QU34R5v*$TKR!MO zkn;t-R1+`{ex-hctpRK;nB(r#uOjy~wY<0h9|chky061OYpw$^FD5clCbxFpk1JMo z^;rB587=KP&W)Y}kb+a|Har z!5uxx*4DO78fi=i`=kjZqgKO_r%DMTp`tVNe~04tDb<*C8w zq@TePhiLR`hS*0~4g*nf$kPG#w}=cmla9{Lw#uMWH-J`haOC(<0d)x!WX!HD%bvYqtQy zqXyA3_0JlxTIucs1Fn|t(CZKD-ETH9=a+RJPnMaYx#7B+^rwqIBNi#^g(ynguKQ{C zRt1;UGmk;jm!w5*9urT>A>#>jix*vXuX%tXYGb8_;tX7)wcQ9emuh8gzqc)&lY z@9dnI!+U zp&N>jSo#E*m6*Gj^;s4?qN$A=ngQb%^}`j7-!LcJlq4p?&TmHxz_;pEeB{m2-Asvw zZhG%tjUj8Sud#=)K%@GUpK(fZnS8;60Zl7bF88|*zYl*DUUwQuVuF8|`C!v>W@oM5$G=v8 zO{OBO4bnKSbhKi9Aaaov#=f7Ow>iL22OVw8wac%U3KAB5XlJFs&XHDv=N$JJ%I}wh zqPikj4ZvQ&V+5?U0qKB6NpKG{6m2Jr_dy*dSe#%nE!Hoq!m|rD6cAF9`4(5h1K>t5 z9RwFnDr)%O!$MrD#{jEAs2y$VGMrhA9Ee^sunn4j)KhyE1LK!-AqD!oK^op5@YP4V zRH4MG%8!atm6mS#yLCRsZJ}w69K7(^l#!-qD0wS{5az$hnB6+%*2G3 z#-nHL386wB=$oFn-(INIMhK%f35foH_2WAs!2{eVgb?X_1p@i2_e!d200}Lei{fc& zF*X%G{=ft0GDC|J04xkzJjSHYzvA|L596HO~Z zta?vK{nGv+O(BZd4ZX&copB@YyGnN=%Ef~NjO@>Zi8+=?$a3#f7J^rJ_iI}Npy7Uw zWPSemT^|LP?nrPoA7mZuDLllWZcUlhbI>ZZwrfao*5V@55qq|4fmaJen1Ajj>h_Tb zwUq)QV}-Ex)jt%G}^1`gDBztXPND&|nW& z?33gz)>iq5*WtQ42bQw7Rb0ffubNu0IP$Vo= zQ&R&tn=IK*cNyO4OvJ4H1rKn7GK!H@uxB0EKe5--+B4+JVi?pvC2BKMzJSx2$px6r z6ZT<#syGCAxwn@w(K`xdrjsFGE-oqQO_B_?9ZDUyIt6$&JE6adLqM`D*3W!CCJBTd zj&n#wMFoN{FO;_+4twjWZ~X1sJ(5f)`GLHK)OX7=8F)2}C{cesfZZNAXirT}>bqzn zBzglC==0a|%W*~R!h${AzCW_ETf0hEyES8@yFtDUxMeU3Z}>)#yE*eJuMLxDcVovf7MK5e3YDz%Ng4S_6ys6$5IHNcDaZfOddm zB51l>E4tD-@WWI(*nwAr$CeOQc45=d#3FnOL33{?A73>xM&fYx9QSi;j)yO`f+h?q zEU<~U(a1Q9p)?~FC@~9F1Zb{R@NVmmVY%NQ^kA6{?0q&AMryt~`-WO72E3?{mA6lL zcOXkDb|0d?@=El9l(qq+>Y#)T3!-{7pwCN@|d2?Y%KIuy%A@b#CP2>5PH1 zP}S&_)_`SNNsOO_9WlEith`Ugz@ThpnAHtMv;Lj!CTc(=rY-y+LUncZZVvR??vN3X z_T{W|SukP@4t8lWsDzQm+ooLWd3A-6hwptvKT)0>19rR2HU~+Wu!$$m=(k5E=CTgb z%WdD|e(C=3k*PHN6S%+!0Lbka^bcdG2C zbDTY#3O{^S{BO)T;|W3zb@L_ncug_+J*&(F48z{z)`phQFnNmiud_5GbK36AcM*wO z^ig0aCCgOC=apdW`!NP?V3-O&<7Va3^x-lg`w|~0eZPhViBj!4eSSn5Q|HSTnsKo< zJCdo~+;kEd1C?cnJpbbR9{COT3k6HME{yvt3bleMNy7G({FJ6R(eg=!*5JsTB-Bvk) zG`6zX5EYY_&A3$OrwFQ@0nlh_Bnc{30{7?II9%t6Ss4~;3d zceEAWhmS|_o?N*eorKs<%0|QeQ>(fk?#N}-pm#?VCD=5a2x*CKW+C7%^YKnf)(Qur zfag&yuei7m82O6+Uc1pG`JU#*pU{VK1+0osp|8;(;$4K}8~uddXB(xe)azMogx)CB z-LBPyYwLnW3mdqP7=1mEXQQp zj(_r(@x4KhwKW0jES2JyWt$rs5!Co6B;wha{jKv~s$HcsF6tFNyQR4|%@K8q+MA$qjG zX~M4JBNR}qFts6;B^26DF;UT6D}jOR<2J4a2zA=^enfIzEspRQ{3f`?X^U?sd3bn? zAJL!@r#K;w`J2M^f^Ixm7-;)C0RC5V-(Y*MyJ+(frNvDoVR2j;k5ooR%e+DxC zX(yCAIzFb-X@{g&2sAQvX?Yi{unpY4_s!lARYBDVHIRVdzM2}|uTLa+uNZ}F-yc*K&qS|ybE+szyPdoZoUK;c`!?R z9T#_{8PyyTOHeWIj3LO#LSuaPM;~}nWZZvz!6gf1-bT1%V8jG|`+`4(Y3Xhe5EiEK zaBzlqdPxx1%sZo7XBnb_Eq(;OmV(TmmzW)`%gk+VVq*0$3&50RL`pq^O~jOM2p)AK z1vLrKV)Z@+nr6g)4oO+zn|HW>9D(@>!(EGJipGTY?vH@uqR%X5dK#41X)IpGe2vMq zgw1~nQJ+I#4cW*Ph=9rx${DJ^zKT)B=0u<760HUK2}@aAcBu;&`KJ#bc#?0EQgm*^ zP7!?fFgaRx6(!nQsx@hCPK6<5D`_u|aSBE;^Th%UF2ZQyx>yBP`s(Lq69qENORAeMXz5rhq z{f5?T4I_)=P;Mwg2q~(O%3mb)bNJi0)~0{OcCt^^KlrT1io#&^pvmdZ-y<0HFIb?^ z0=>gu_@TQO!-)#{eUY!4cYOO+S*DKs`{h&vc-kSZfJubT-`92%{`WA$+3Txw5FGQt zupWdy*Nu_69WYzHTmk7An9#TO_Nx9UhXxGTqp+|C3hfaPk`!dX?n9e2=)WTbaJ?nZ z_q0=y2}Ye+bg#0FZ{L3ew0Y>6clYD}|((!hbmp z^5+V|v8#VV^CMz$;hb2Uf;VJ7XDhCe`T=A-v)YTmR3KIe)Y^blCg368UaX8lUhp?Z zp8Y{(4c0{o?v@HWgP>4`dYumnfM@FZO=n>6*9>tG@}-k83S4?%=m$=2;NlPJx%@ng?$2qLmcU`HQxAX7AUyiyxeuMB&yh0}LYq%M z9?$|JIDkqzNx*X^>XW>X`T;a#4p&UklThJ#mGIooj-lo?*60OUUK_$T@kAZveH)uP zu#RE+%-Tc?L|!a;e>_A8nqO@3rdaJC56n~UPY*xNu%y~Pwp_dAbwBp|g@n~HGz~R< zd#e%!-y;-Cx{6l>x5RsX=p0!q&E$2lNmyZKTT~L^hThqH=g6tEC3xr)73=rZxrFmM zDSCCpHliQkCy@aItZ#?#Z~zaME_}Waen~1nthP-M)-Vc_a8#nERJf+ZEf&x(%zwj+YeL+`zh${kI55?*-U6a6HA8O3uFEF@X z0F0Dl41WBl;CT<9@e3bM-RIR&SVjdyM{q5xAp;FMHbshEVIdeqwhb1_y8T-3{D4zw zRmbm+599%s1v9kIvaXiJJPj}m22O*i;hn2k35ki|hsk|Nn#~<2^hVOu%q(aK7}Xr|Fo1iCCWY@jT7;}f=A+XO@yHno(1edZrwC*_iS0Y}2rx2&T7 zLRU9L;ocAt`R@Kw{J?i=Zg5W$&;(QcHsaL(^X2C&d$FIQyIslg*UCM3PGgK`7Ejwp z^$8OMNi!jEnqeX+F4#T?{h92dD{#J$ArQNkAfny<`Th_f7iNTqyL)F~1zv7BGIvUh z$U!kB4v{rHaSU9S&_IS+cNZ6s2Iw{W`ND(kmK2iP{SElT_3tT^@7#%uin=BEl}-*l z2}bdN#xMr0$dtKWODn6~@&AAZ61E6cL7KV%9+AKl%njU6rThC+k#3`br;!Bh_%PO+~F z1MJzcXfq67I7ilt>ii=v(h|+!_lku`AFGW}1d1}l=ZV1ekmbS`6_lGcq zB+05TUV)ehbWt4Z@Cx74jgL>Ogdk@=4gXIl>x+ct3f{Q0KcSAO5z;!GGoc*b+p~e4 zu@U0;O)b+>Q?W;?^`NY#5mSM>9v4pP>1(PM6db%5c2zWr zK(oH$=h_vB+0&p&VjIuF1N*?IrRXoFakY_M=2 z$iS0{hF1x$$QpITXi)d~i8HmOUE-1|09-uys-r`GM@^cR@U3j24t@tmF{L9bk=bwC zn|OTtsBnVH&49iuQUE=8gpfDJBAQbt3}ZE1GnfDwY7#Dksg1kU^M1A+yxwubBV-S8 z%N?||5+u)qKA;-rEPWc}(bIB16PQknG@&aOo>oy+4SwYb2qBa_W`6*Ep_5DQWVQo1 zi=@rX?cvn3ZzRIQdc3?{h%S0bAIhQTU2>M>{CrkC3A&7zPC21kuF}}uv}!2m9Fw=q zICpZT{MFo$8cMK5@!c7N&T7rdpEE4v{? z*EA{Oyx7jTmZBduFfLT)W zanoYw>|!QeA-We;rBMZP68u7}2wL<4kV(H=KdRqqs(-qss~k1se`)9?D7#OJKS2~> zLsSOMF;#nRNk8;A;N-5cN)l4SZoAwrE^q*z0!9OY3IfHKuLc*6K$^Am#ebuEeDDG| zZE^-Z!c7n_@q9$-`Y^v;cs`pekk$zuys&uF_0T*>00QF>D-0P-2nrVr^PKQ zNn41q_xDx5oPm8ZDB^>;mo>H&f;x{Aq`w+9coN;pt;aYYXFRxCMr@%!9gEN4r=iFF z35u4=_dGvFWr};B$W3Oxp#L7~@4rVGRC6o}Ed%_JZJ8nH_XP|*SZgD)tr%mi`%+xM zU_a+%5}Ec4L5m^W(!{+NxsE;8BZeRPmhwEhF<8itPsdK;jB6^3gKQ+@m~zVk75;zL z*X$@o!;9J2@nvN$d&>u!ux{uI!N@S=ljL`9X2)@V7q=1}9Sx=exTCi#W?2}@!t$?t zL#tuDVB(fve&@&ah?zYc%4FMKuD6~m7)Zl_{bk3XQc5oY+;mWV>i`dkMqpF4hO7%DJ4PUb-Y!Y zB<^=c>9Pv3RX3hj8KgpgHmPi0I%g^4>a*R72~BaBIWwM&ZxqT4S^=9lHT4u; z6jcJp0Hu*?`v=0d)NDi?h6Z0X-WMW>aSOf(1Y&>bmDTjv4{T-9auLcaZW=U`2`#3XS%B`8CDV5uhZ~Ooov|Fo`lSgT&R{<-C&;K3zQnLsdtV(T zllbBny8w1LXEJJ#;WM^tzciPBz;vHVh>12NWTvs#|M{~*;kB~4m6aR*=2zIfp4YPr zqMl=yEN*UcH}_)RBImeg-VDM))Qxelf)}ub_7qTr9z)B9C+jq>WyTxQ(?zGt^b>?ZD z4~B|gt)X0)zB?D#QV%dLILE)t%46S7)_gkH51H>Q8fbM6wyCEI_B!l`6tmeJ&7C=? zC-3#EImlVKhfxhx{ytr@T6!{`j!QxAi9#M1n+&;Gr>_V;W|Xz|wW<7F?N3V{SdVWJ z9;Pq8qVzo+{{6Fy45Re?_xi5Oogt5o%BvOV6&hWHc;G;_3y?9^Bq9PD6#dS6&(w?z zUvPSd2}QwANtqn50wf!j(FArVvpkWxvk;tt2mS;>`!UT8LU}9r30M^n+Vu^0B-wSV=?z?dyU%B){G)k3&cf zFBg=#Ye1Xrlcy!@B}F5sEGit?f(;5-W4W%_m=^NI?(*eKYBb4VLEy(#v?ri7w87KC zA*Z}fT2IMd1Cu4GUcI{`3@?_Z5z?CCYh`gZ2H}v4U=M;rzQ`2gMGvmoFw>+mir{^0 zG0o{K;M*mLhZ+;~e(&Hw*FPH>&f?c|L|E_ue(?sh`E%_k z8%mXPfAZ$_&_ISEr~PsZv0B?yhNnSU@C%Y0n31!%>~kuT4n3?-0ELSa);P_?NW4Pz z_uwN$qVc$I=ika3t3fhq?&;F)zdV6VR?zki9EY!9Gb$=W*pLaKs3@?J#){!rRCwCH z6cq``lbRH0AcgB-6v4*9A^tn`19?oJj&b4P6M)xrOZ4Hx>K_?#gDV1n3+bg%ZfUT-n>VKf-AMWEz}Y2z20p z&RdE!n7$qCqo ziq^Oeu@yqj!*I}=pWCd9amcIhP<$3B<=fH83sf+GnwhHT=k8t;^Zgy*GvK3`CH^eP zg~Th{+WVht@r)Y++@kZ(zXu2Gl14BNRI1dt^GvkQS+R0XQl( z8AXtHl02#z14LT*qv(tRkpz}s05}&$0YJX??Ha&AfM%vkc#m~-ya7Z6YbGN-eYXme zgDCzS*g4x3aDXhMT3qRoM$HL>K8y)jJ4B~nvMEqgGYAM&wFoUa5q8|94ru*sfKc{a zfmjfK9|qU{EU6C`xxIr`fDkP!0K66y6r`o4HJbt2!ZSdDH9PzI@K&kwLYe_BfHC8w z3Uj}uJ~0;;yP_V_5^gnX=@RLSU$7Hb8_n#MEb`dGXBwo8MdS@V%zY5-+;y#7O^( z3crPP27<%p*Ox2({=K3`%m1sg>knr-kK=5Mm1RVS{MfKq`e9ro#%(h!dNK=jy6boO zDu+z5^CPx3avf8Xaw9fRCRa)8>7E`J(#fgV+PIvE4)d&B9a(hZ-qqdn^zZ%qeZGHv zKkv`y`+C1WuODEEt9GH~v+0;DU~?2;m@RBUhS?Fy{9sgd4wibBT1sS#BG7%J^)GCM zGp|ghB(19w6BD;c{qj189i4M~#~nu#@KOii%SK<)Zq;Zq-kO-^%8Y||Qc@bIHs%|- zW4JUF#)Oe21!G4M$3j-8LcdjRJf0~GkEXQ~Ep2TTx*6Kmkg%}e0>(BPb!eqG%v?pj zZMCNl5DQfq2(C`0EU66?-yRPTElQ>j3?G;`AQCRGt7r-66OSCi@r#S`TJQE+C>z^g zl2{&}S<^47lobOeU2)H}t;okMepjb#>oxUX-dUV{Md-C!)B|{Wu7-;erOKl820UOUZ|*Fa*pX3 z9B(ljA4V8?QFS=VLl}Oo{_1DvHPHGv_Fkww{GkICigh8ae2c;Iw0fZjN|czpo$o0u z11o}5F4rn9>6U=tl6>oou~)|A$jPM7!xV|+JsFuq%6@aDw0(z58-z7SV|zB-1FBZR zSPaO~{%3WOOp;)x?j-V zjqO@XX2*sA&O)P5lj}LM?sE4Jhvo<`s(~oXp%tvrP<03z`TwS`5TvVVjFtUn@>kz~z)}Ebn*pc~docHFH#qF&GSwv<%u+ zD$I5oKwFF$J}}_p#Mz-1GAKVoKyF2pf^C3}z5RD(V8oLj zAY||87i^dkmzNi^?I-9JEQG3u{~5SXC&4y&c2xNVIR7l35&C&*EzL_-;F9U#AZ0P~G8O>-PI#0^w=@w&{1D{66}PN~?Jvg?zBQQ3!L!K9S$M5pTBs3>L# zC3L4E+CR&eB$LZW3s&JBvkTQM7ArUAFf-?=, + pub override_syntax: Option, + pub symbols: Vec<(usize, String)>, + pub bookmarks: Vec, +} + +impl EditorTab { + pub fn new(title: &str, initial_text: &str) -> Self { + let mut tab = Self { + title: title.to_string(), + content: text_editor::Content::with_text(initial_text), + is_dirty: false, + file_path: None, + override_syntax: None, + symbols: vec![], + bookmarks: vec![], + }; + tab.parse_symbols(); + tab + } + + pub fn parse_symbols(&mut self) { + self.symbols.clear(); + for (i, line) in self.content.text().lines().enumerate() { + let t = line.trim_start(); + if t.starts_with("fn ") + || t.starts_with("def ") + || t.starts_with("class ") + || t.starts_with("struct ") + || t.starts_with("impl ") + || t.starts_with("enum ") + || t.starts_with("trait ") + || t.starts_with("mod ") + || t.starts_with("pub fn ") + || t.starts_with("pub struct ") + || t.starts_with("pub enum ") + || t.starts_with("pub trait ") + || t.starts_with("pub mod ") + || t.starts_with("macro_rules!") + { + let name = t + .split('{') + .next() + .unwrap_or(t) + .split('(') + .next() + .unwrap_or(t) + .split('!') + .next() + .unwrap_or(t) + .trim() + .to_string(); + self.symbols.push((i + 1, name)); + } + } + } + + pub fn toggle_bookmark(&mut self, line: usize) { + if self.bookmarks.contains(&line) { + self.bookmarks.retain(|&b| b != line); + } else { + self.bookmarks.push(line); + self.bookmarks.sort(); + } + } + + pub fn save(&mut self) -> Result { + let path = self + .file_path + .clone() + .unwrap_or_else(|| PathBuf::from(&self.title)); + let text = self.content.text(); + fs::write(&path, text)?; + self.is_dirty = false; + self.file_path = Some(path.clone()); + Ok(path.to_string_lossy().to_string()) + } + + pub fn save_as(&mut self, new_path: &str) -> Result { + let path = PathBuf::from(new_path); + let text = self.content.text(); + fs::write(&path, text)?; + self.is_dirty = false; + self.file_path = Some(path.clone()); + self.title = path + .file_name() + .unwrap_or_default() + .to_string_lossy() + .to_string(); + Ok(path.to_string_lossy().to_string()) + } + + pub fn line_count(&self) -> usize { + self.content.text().lines().count().max(1) + } + + pub fn byte_size(&self) -> usize { + self.content.text().len() + } + + pub fn get_syntax(&self) -> &'static str { + if let Some(ref syn) = self.override_syntax { + return match syn.as_str() { + "Rust" => "rs", + "Python" => "py", + "C/C++" | "C" | "C++" => "cpp", + "Shell" | "Bash" => "sh", + "JavaScript" => "js", + "TypeScript" => "ts", + "Markdown" => "md", + "HTML" => "html", + "CSS" => "css", + "JSON" => "json", + "XML" => "xml", + "YAML" => "yaml", + "Go" => "go", + "Ruby" => "rb", + "PHP" => "php", + "Java" => "java", + "C#" => "cs", + "SQL" => "sql", + _ => "txt", + }; + } + + let name = self.title.to_lowercase(); + if name.contains("dockerfile") || name.contains("containerfile") { + return "dockerfile"; + } + if name.contains("nginx") { + return "nginx"; + } + if name.contains("apache") || name.contains("httpd") { + return "apache"; + } + if name.ends_with("rc") { + return "sh"; + } + if name.ends_with("makefile") || name == "makefile" { + return "makefile"; + } + + let parts: Vec<&str> = name.split('.').collect(); + if let Some(ext) = parts.last() { + match *ext { + "rs" => "rs", + "sh" | "bash" | "zsh" | "command" => "sh", + "ps1" | "psm1" => "ps1", + "bat" | "cmd" | "dosbat" => "bat", + "vbs" | "vbe" | "wscript" | "vbasic" => "vbs", + "conf" | "cfg" | "ini" | "service" | "target" => "ini", + "yaml" | "yml" => "yaml", + "toml" => "toml", + "json" => "json", + "xml" => "xml", + "html" | "htm" | "xhtml" => "html", + "css" | "scss" | "sass" | "less" => "css", + "js" | "mjs" | "cjs" => "js", + "ts" | "tsx" => "ts", + "py" | "pyw" => "py", + "c" | "h" => "c", + "cpp" | "hpp" | "cc" | "cxx" | "hxx" => "cpp", + "go" => "go", + "rb" => "rb", + "php" | "phtml" => "php", + "java" => "java", + "cs" => "cs", + "sql" => "sql", + "md" | "markdown" => "md", + "r" => "r", + "lua" => "lua", + "pl" | "pm" => "pl", + "ex" | "exs" => "ex", + "hs" => "hs", + "scala" => "scala", + "swift" => "swift", + "kt" | "kts" => "kt", + "dart" => "dart", + _ => "txt", + } + } else { + "txt" + } + } +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs new file mode 100755 index 0000000..4f66097 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,727 @@ +#![allow(dead_code)] +// Scitano v1.0.0 -- Unified Editor Engine +// SciTE menus | Strict Nano hotkeys | Geany sidebar/context features + +use iced::widget::{ + button, column, container, mouse_area, row, scrollable, text, text_editor, Space, +}; +use iced::{Element, Length, Task, Theme, Font, Subscription}; +use iced::keyboard::{Key, Modifiers}; +use iced::highlighter::Theme as HighlighterTheme; +use std::process::Command; + +mod theme; +mod config; +mod editor; + +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum HighlightTone { CandyPop, Matte } + +impl HighlightTone { + fn to_iced_theme(&self) -> HighlighterTheme { + match self { + HighlightTone::CandyPop => HighlighterTheme::Base16Ocean, + HighlightTone::Matte => HighlighterTheme::Base16Mocha, + } + } +} + +#[derive(Debug, Clone, PartialEq)] +pub enum BottomTab { Diagnostics, BuildLogs, AiTerminal, Messages } + +#[derive(Debug, Clone)] +pub enum Message { + MenuToggle(String), + SubMenuAction(String), + TabSelected(usize), + CloseTab(usize), + BottomTabSelected(BottomTab), + EditorAction(text_editor::Action), + EditorRightClick, + KeyboardEvent(Key, Modifiers), + SyncAiderModels, + ToggleWordWrap(bool), + ToggleLineNumbers(bool), + ToggleSymbolTree(bool), +} + +struct Scitano { + config: config::Config, + active_menu: Option, + active_tab: usize, + highlight_tone: HighlightTone, + tabs: Vec, + bottom_tab: BottomTab, + chat_log: Vec, + aider_models: Vec, + kill_ring: String, + last_action_was_kill: bool, + show_symbol_tree: bool, + search_term: String, +} + +impl Default for Scitano { + fn default() -> Self { + Self { + config: config::Config { + default_tone: "CandyPop".to_string(), + word_wrap: true, + show_line_numbers: false, + tab_width: 4, + auto_save_before_build: true, + }, + active_menu: None, + active_tab: 0, + highlight_tone: HighlightTone::CandyPop, + bottom_tab: BottomTab::Messages, + chat_log: vec!["sys> Scitano v1.0.0 initialized. Nano hotkeys active. Type ^G for help.".to_string()], + aider_models: vec![], + kill_ring: String::new(), + last_action_was_kill: false, + show_symbol_tree: true, + search_term: String::new(), + tabs: vec![ + editor::EditorTab::new("hello.rs", + "fn main() {\n println!(\"Hello from Scitano v1.0.0!\");\n}\n\nfn greet(name: &str) {\n println!(\"Welcome, {}!\", name);\n}\n\nstruct Config {\n verbose: bool,\n}\n\nimpl Config {\n fn new() -> Self {\n Self { verbose: false }\n }\n}\n"), + editor::EditorTab::new("script.py", + "import os\nimport sys\n\ndef main():\n print('Python works in Scitano!')\n print(f'CWD: {os.getcwd()}')\n\nclass Runner:\n def __init__(self):\n self.ready = True\n\n def run(self):\n if self.ready:\n main()\n\nif __name__ == '__main__':\n Runner().run()\n"), + ], + } + } +} + +impl Scitano { + // -- Nano Keybindings (STRICT) -------------------------------- + fn nano_help(&mut self) { + self.last_action_was_kill = false; + for line in &[ + "nano> -- Scitano Quick Reference --", + "nano> ^G=Help ^O=Save ^R=Insert ^W=Search ^\\=Replace ^_=GotoLine", + "nano> ^K=Cut ^U=Paste ^C=CurPos ^X=Exit ^Y=PageUp ^V=PageDn", + "nano> ^A=LineStart ^E=LineEnd ^J=Justify ^T=Spell ^D=DelChar", + "nano> ^I=Tab ^B=Build ^L=Lint F3=Open F5=Exec", + ] { + self.chat_log.push(line.to_string()); + } + self.bottom_tab = BottomTab::Messages; + } + + fn nano_writeout(&mut self) { + self.last_action_was_kill = false; + if self.tabs.is_empty() { return; } + match self.tabs[self.active_tab].save() { + Ok(path) => self.chat_log.push(format!("nano> [^O] Written to '{}'", path)), + Err(e) => self.chat_log.push(format!("sys> [ERROR] WriteOut failed: {}", e)), + } + } + + fn nano_exit(&mut self) { + self.last_action_was_kill = false; + if self.tabs.is_empty() { return; } + let title = self.tabs[self.active_tab].title.clone(); + self.tabs.remove(self.active_tab); + if self.tabs.is_empty() { self.active_tab = 0; } + else if self.active_tab >= self.tabs.len() { self.active_tab = self.tabs.len() - 1; } + self.chat_log.push(format!("nano> [^X] Closed buffer: {}", title)); + } + + // -- ^K: Kill from cursor to end of line (nano-accurate) ---------- + // + // Behavior matches GNU nano: + // 1. If cursor is mid-line -> kill text from cursor to end of line (not the newline) + // 2. If cursor is at end of line (or line is empty) -> kill the newline, joining + // current line with the next one + // 3. At end of last line -> no-op + // 4. Consecutive ^K presses -> append into the same kill-ring entry + // + // NOTE: iced 0.13.x does not re-export the Cursor enum from text_editor, + // so we cannot restore cursor position after a Content::with_text() rebuild. + // Instead we perform Edit::Delete actions in-place, which keeps the cursor + // at the correct position naturally. + // + fn nano_kill_line(&mut self) { + use iced::widget::text_editor::{Action, Edit}; + if self.tabs.is_empty() { return; } + let tab = &mut self.tabs[self.active_tab]; + let (cur_line, cur_col) = tab.content.cursor_position(); + let text = tab.content.text(); + let lines: Vec<&str> = text.lines().collect(); + + if lines.is_empty() || cur_line >= lines.len() { + self.last_action_was_kill = false; + return; + } + + let current_line = lines[cur_line]; + let killed: String; + + if cur_col < current_line.len() { + // Case 1: cursor is mid-line -> kill text to end of line + // Perform Delete for each character; cursor stays in place. + killed = current_line[cur_col..].to_string(); + for _ in 0..killed.chars().count() { + tab.content.perform(Action::Edit(Edit::Delete)); + } + } else if cur_line + 1 < lines.len() { + // Case 2: cursor at EOL (or empty line) -> kill the newline. + // A single Delete at EOL joins this line with the next. + killed = "\n".to_string(); + tab.content.perform(Action::Edit(Edit::Delete)); + } else { + // Case 3: at end of last line -> nothing to kill + self.last_action_was_kill = false; + return; + } + + // Accumulate into kill-ring (append on consecutive kills, like nano) + if self.last_action_was_kill { + self.kill_ring.push_str(&killed); + } else { + self.kill_ring = killed; + } + + tab.is_dirty = true; + tab.parse_symbols(); + self.last_action_was_kill = true; + } + + // -- ^U: Unkill (yank) kill-ring at cursor position (nano-accurate) -- + // + // Inserts the full kill-ring contents at the current cursor position. + // Uses Edit::Paste which handles cursor advancement automatically. + // + fn nano_unkill(&mut self) { + use iced::widget::text_editor::{Action, Edit}; + self.last_action_was_kill = false; + if self.tabs.is_empty() || self.kill_ring.is_empty() { return; } + let tab = &mut self.tabs[self.active_tab]; + + // Paste inserts at cursor and advances cursor to end of pasted text + tab.content.perform(Action::Edit(Edit::Paste(self.kill_ring.clone()))); + tab.is_dirty = true; + tab.parse_symbols(); + } + + fn nano_cur_pos(&mut self) { + self.last_action_was_kill = false; + if self.tabs.is_empty() { return; } + let tab = &self.tabs[self.active_tab]; + let text = tab.content.text(); + let total_lines = text.lines().count(); + let total_chars = text.len(); + let size_kb = total_chars as f64 / 1024.0; + let file_name = tab.file_path.as_ref() + .map(|p| p.to_string_lossy().to_string()) + .unwrap_or_else(|| tab.title.clone()); + self.chat_log.push(format!( + "nano> [^C] {} | Lines: {} | Chars: {} | Size: {:.2} KB | Syntax: {}", + file_name, total_lines, total_chars, size_kb, tab.get_syntax().to_uppercase() + )); + self.bottom_tab = BottomTab::Messages; + } + + fn nano_where_is(&mut self) { + self.last_action_was_kill = false; + self.chat_log.push("nano> [^W] Where Is: Search triggered.".into()); + self.bottom_tab = BottomTab::Messages; + } + + fn nano_replace(&mut self) { + self.last_action_was_kill = false; + self.chat_log.push("nano> [^\\] Replace: Use menu action for find/replace.".into()); + self.bottom_tab = BottomTab::Messages; + } + + fn nano_goto_line(&mut self) { + self.last_action_was_kill = false; + if self.tabs.is_empty() { return; } + self.chat_log.push(format!("nano> [^_] Go To Line: Buffer has {} lines.", self.tabs[self.active_tab].line_count())); + self.bottom_tab = BottomTab::Messages; + } + + fn nano_read_file(&mut self) { + self.last_action_was_kill = false; + self.chat_log.push("nano> [^R] Read File: Insert file at cursor. Use File > Open.".into()); + self.bottom_tab = BottomTab::Messages; + } + + fn nano_justify(&mut self) { + self.last_action_was_kill = false; + self.chat_log.push("nano> [^J] Justify: Paragraph reflow triggered.".into()); + } + + fn nano_spell(&mut self) { + self.last_action_was_kill = false; + self.chat_log.push("nano> [^T] Spell Check: Requires system 'aspell'.".into()); + } + + // -- Build System (Geany-style: separate Compile/Build/Run) -- + fn auto_save_if_dirty(&mut self) -> bool { + if self.tabs.is_empty() { return false; } + if self.config.auto_save_before_build { + if let Err(e) = self.tabs[self.active_tab].save() { + self.chat_log.push(format!("sys> [ERROR] Save failed: {}", e)); + return false; + } + } + true + } + + fn compile_only(&mut self) { + self.last_action_was_kill = false; + if self.tabs.is_empty() { return; } + if !self.auto_save_if_dirty() { self.bottom_tab = BottomTab::BuildLogs; return; } + let tab = &self.tabs[self.active_tab]; + let syntax = tab.get_syntax(); + let path_str = tab.file_path.as_ref().unwrap().to_string_lossy().to_string(); + self.chat_log.push(format!("build> Compiling ({}) ...", syntax)); + let (cmd, args) = match syntax { + "rs" => ("rustc", vec!["--emit=metadata".into(), "--error-format=short".into(), path_str]), + "c" => ("gcc", vec!["-fsyntax-only".into(), "-Wall".into(), path_str]), + "cpp" => ("g++", vec!["-fsyntax-only".into(), "-Wall".into(), path_str]), + "py" => ("python3", vec!["-m".into(), "py_compile".into(), path_str]), + "sh" | "bash" => ("shellcheck", vec!["--format=gcc".into(), path_str]), + "js" => ("node", vec!["--check".into(), path_str]), + _ => { self.chat_log.push(format!("build> [FAIL] No compiler for '{}'.", syntax)); self.bottom_tab = BottomTab::BuildLogs; return; } + }; + match Command::new(cmd).args(&args).output() { + Ok(o) => { self.log_output(&o); if o.status.success() && String::from_utf8_lossy(&o.stdout).is_empty() && String::from_utf8_lossy(&o.stderr).is_empty() { self.chat_log.push("build> Compile: OK".into()); } } + Err(e) => self.chat_log.push(format!("sys> [ERROR] {} missing: {}", cmd, e)), + } + self.bottom_tab = BottomTab::BuildLogs; + } + + fn build_and_run(&mut self) { + self.last_action_was_kill = false; + if self.tabs.is_empty() { return; } + if !self.auto_save_if_dirty() { self.bottom_tab = BottomTab::BuildLogs; return; } + let tab = &self.tabs[self.active_tab]; + let syntax = tab.get_syntax(); + let fp = tab.file_path.as_ref().unwrap(); + let path_str = fp.to_string_lossy().to_string(); + let stem = fp.file_stem().unwrap_or_default().to_string_lossy(); + let dir = fp.parent().unwrap_or(std::path::Path::new(".")).to_string_lossy(); + self.chat_log.push(format!("build> Build & Run ({}) ...", syntax)); + let (cmd, args) = match syntax { + "rs" => ("sh", vec!["-c".into(), format!("rustc {} -o {}/{} && {}/{}", path_str, dir, stem, dir, stem)]), + "py" => ("python3", vec![path_str]), + "sh" | "bash" => ("bash", vec![path_str]), + "c" => ("sh", vec!["-c".into(), format!("gcc {} -o {}/{} -lm && {}/{}", path_str, dir, stem, dir, stem)]), + "cpp" => ("sh", vec!["-c".into(), format!("g++ {} -o {}/{} && {}/{}", path_str, dir, stem, dir, stem)]), + "js" => ("node", vec![path_str]), + "go" => ("go", vec!["run".into(), path_str]), + "rb" => ("ruby", vec![path_str]), + "lua" => ("lua", vec![path_str]), + "pl" => ("perl", vec![path_str]), + "bat" => ("cmd.exe", vec!["/c".into(), path_str]), + _ => { self.chat_log.push(format!("build> [FAIL] No runner for '{}'.", syntax)); self.bottom_tab = BottomTab::BuildLogs; return; } + }; + match Command::new(cmd).args(&args).output() { + Ok(o) => self.log_output(&o), + Err(e) => self.chat_log.push(format!("sys> [ERROR] {}", e)), + } + self.bottom_tab = BottomTab::BuildLogs; + } + + fn run_only(&mut self) { + self.last_action_was_kill = false; + if self.tabs.is_empty() { return; } + let tab = &self.tabs[self.active_tab]; + let fp = match &tab.file_path { + Some(p) => p.clone(), + None => { self.chat_log.push("sys> [ERROR] Run: No file path. Save first (^O).".into()); return; } + }; + let path_str = fp.to_string_lossy().to_string(); + let stem = fp.file_stem().unwrap_or_default().to_string_lossy(); + let dir = fp.parent().unwrap_or(std::path::Path::new(".")).to_string_lossy(); + let (cmd, args) = match tab.get_syntax() { + "rs" => ("sh", vec!["-c".into(), format!("{}/{}", dir, stem)]), + "py" => ("python3", vec![path_str]), + "sh" | "bash" => ("bash", vec![path_str]), + "js" => ("node", vec![path_str]), + "go" => ("go", vec!["run".into(), path_str]), + _ => { self.chat_log.push("build> [FAIL] No runner for this syntax.".into()); return; } + }; + match Command::new(cmd).args(&args).output() { + Ok(o) => self.log_output(&o), + Err(e) => self.chat_log.push(format!("sys> [ERROR] {}", e)), + } + self.bottom_tab = BottomTab::BuildLogs; + } + + fn lint_syntax(&mut self) { + self.last_action_was_kill = false; + if self.tabs.is_empty() { return; } + if !self.auto_save_if_dirty() { self.bottom_tab = BottomTab::Diagnostics; return; } + let tab = &self.tabs[self.active_tab]; + let syntax = tab.get_syntax(); + let path_str = tab.file_path.as_ref().unwrap().to_string_lossy().to_string(); + self.chat_log.push(format!("diag> Linting: {}", syntax)); + let (cmd, args) = match syntax { + "rs" => ("rustc", vec!["--emit=metadata".into(), "--error-format=short".into(), path_str]), + "py" => ("python3", vec!["-m".into(), "py_compile".into(), path_str]), + "sh" | "bash" => ("shellcheck", vec!["--format=gcc".into(), path_str]), + "c" => ("gcc", vec!["-fsyntax-only".into(), "-Wall".into(), "-Wextra".into(), path_str]), + "cpp" => ("g++", vec!["-fsyntax-only".into(), "-Wall".into(), "-Wextra".into(), path_str]), + "js" => ("node", vec!["--check".into(), path_str]), + _ => { self.chat_log.push(format!("diag> [SKIP] No linter for '{}'.", syntax)); self.bottom_tab = BottomTab::Diagnostics; return; } + }; + match Command::new(cmd).args(&args).output() { + Ok(o) => { + self.log_output(&o); + let out = String::from_utf8_lossy(&o.stdout); + let err = String::from_utf8_lossy(&o.stderr); + if out.is_empty() && err.is_empty() && o.status.success() { + self.chat_log.push("diag> OK: No issues.".into()); + } + } + Err(e) => self.chat_log.push(format!("sys> [ERROR] Linter missing: {}", e)), + } + self.bottom_tab = BottomTab::Diagnostics; + } + + fn log_output(&mut self, output: &std::process::Output) { + let stdout = String::from_utf8_lossy(&output.stdout); + let stderr = String::from_utf8_lossy(&output.stderr); + for line in stdout.lines() { self.chat_log.push(format!("out> {}", line)); } + for line in stderr.lines() { self.chat_log.push(format!("err> {}", line)); } + if stdout.is_empty() && stderr.is_empty() { + self.chat_log.push("build> Execution completed (no output).".into()); + } + } + + fn fetch_aider_models() -> Vec { + let env_path = format!("{}/.local/bin:{}", std::env::var("HOME").unwrap_or_default(), std::env::var("PATH").unwrap_or_default()); + if let Ok(out) = Command::new("aider").env("PATH", env_path).args(["--list-models", "ollama"]).output() { + let txt = String::from_utf8_lossy(&out.stdout); + let mut models: Vec = txt.lines().filter(|l| l.trim().starts_with("- ")).map(|l| l.trim().replace("- ", "")).collect(); + models.sort(); models.dedup(); + if !models.is_empty() { return models; } + } + vec!["ollama/llama3".into(), "ollama/mistral".into()] + } + + fn save_session(&mut self) { + self.last_action_was_kill = false; + let count = self.tabs.iter().filter(|t| t.file_path.is_some()).count(); + self.chat_log.push(format!("session> Saved {} files in session.", count)); + } + + fn load_session(&mut self) { + self.last_action_was_kill = false; + self.chat_log.push("session> Load Session: Restore previously saved files.".into()); + self.bottom_tab = BottomTab::Messages; + } + + fn toggle_bookmark(&mut self) { + self.last_action_was_kill = false; + if !self.tabs.is_empty() { + let tab = &mut self.tabs[self.active_tab]; + tab.toggle_bookmark(1); + self.chat_log.push(format!("bookmark> Toggled. Total: {}", tab.bookmarks.len())); + } + } + + fn clear_bookmarks(&mut self) { + self.last_action_was_kill = false; + if !self.tabs.is_empty() { + self.tabs[self.active_tab].bookmarks.clear(); + self.chat_log.push("bookmark> All cleared.".into()); + } + } + + fn subscription(&self) -> Subscription { + iced::keyboard::on_key_press(|key, modifiers| Some(Message::KeyboardEvent(key.clone(), modifiers))) + } + + fn update(&mut self, message: Message) -> Task { + match message { + Message::KeyboardEvent(key, modifiers) => { + if modifiers.control() { + if let Key::Character(c) = &key { + match c.as_ref() { + "g" | "G" => self.nano_help(), + "o" | "O" => self.nano_writeout(), + "x" | "X" => self.nano_exit(), + "k" | "K" => self.nano_kill_line(), + "u" | "U" => self.nano_unkill(), + "c" | "C" => self.nano_cur_pos(), + "w" | "W" => self.nano_where_is(), + "r" | "R" => self.nano_read_file(), + "j" | "J" => self.nano_justify(), + "t" | "T" => self.nano_spell(), + "b" | "B" => self.build_and_run(), + "l" | "L" => self.lint_syntax(), + _ => { self.last_action_was_kill = false; } + } + } + if let Key::Character(c) = &key { + if c.as_ref() == "_" { self.nano_goto_line(); } + } + } else { + self.last_action_was_kill = false; + } + } + Message::MenuToggle(name) => { + self.last_action_was_kill = false; + self.active_menu = if self.active_menu.as_deref() == Some(name.as_str()) { None } else { Some(name) }; + } + Message::SubMenuAction(action) => { + let act = action.as_str(); + if act != "^K Kill Line (Cut)" { self.last_action_was_kill = false; } + match act { + "New" => { let n = format!("Untitled-{}", self.tabs.len()+1); self.tabs.push(editor::EditorTab::new(&n, "")); self.active_tab = self.tabs.len()-1; self.chat_log.push(format!("sys> New: {}", n)); } + "Open (F3)" => self.chat_log.push("file> Open: F3.".into()), + "Open Selected" => self.chat_log.push("file> Open Selected: path under cursor.".into()), + "^O WriteOut (Save)" => self.nano_writeout(), + "Save As..." => { self.chat_log.push("file> Save As: enter path.".into()); } + "^X Close Tab" => self.nano_exit(), + "Reload File" => self.chat_log.push("file> Reload from disk.".into()), + "Save Session" => self.save_session(), + "Load Session" => self.load_session(), + "Print..." => self.chat_log.push("file> Print.".into()), + "Exit App" => std::process::exit(0), + "Undo (^Z)" => self.chat_log.push("edit> Undo.".into()), + "Redo (^Y)" => self.chat_log.push("edit> Redo.".into()), + "^K Kill Line (Cut)" => self.nano_kill_line(), + "^U Unkill (Paste)" => self.nano_unkill(), + "^C Cur Pos" => self.nano_cur_pos(), + "^A Select All" => self.chat_log.push("edit> Select All.".into()), + "Delete Line" => self.chat_log.push("edit> Delete Line.".into()), + "Duplicate Line" => self.chat_log.push("edit> Duplicate Line.".into()), + "Transpose Line" => self.chat_log.push("edit> Transpose Line.".into()), + "Match Brace ^E" => self.chat_log.push("edit> Match Brace.".into()), + "Comment Line" => self.chat_log.push("edit> Toggle line comment.".into()), + "Uncomment Line" => self.chat_log.push("edit> Uncomment.".into()), + "Increase Indent" => self.chat_log.push("edit> Indent.".into()), + "Decrease Indent" => self.chat_log.push("edit> Unindent.".into()), + "^W Where Is (Find)" => self.nano_where_is(), + "Find Next (F3)" => self.chat_log.push("search> Find Next.".into()), + "Find Previous (Shift+F3)" => self.chat_log.push("search> Find Previous.".into()), + "^\\ Replace" => self.nano_replace(), + "Replace Next" => self.chat_log.push("search> Replace Next.".into()), + "Go To Line (^_)" => self.nano_goto_line(), + "Toggle Bookmark (^B)" => self.toggle_bookmark(), + "Next Bookmark" => self.chat_log.push("search> Next bookmark.".into()), + "Prev Bookmark" => self.chat_log.push("search> Prev bookmark.".into()), + "Clear All Bookmarks" => self.clear_bookmarks(), + "Toggle Full Screen (F11)" => self.chat_log.push("view> Toggle Full Screen.".into()), + "Toggle Message Window" => self.chat_log.push("view> Toggle messages.".into()), + "Toggle Sidebar" => { self.show_symbol_tree = !self.show_symbol_tree; self.chat_log.push(format!("view> Sidebar: {}.", if self.show_symbol_tree { "ON" } else { "OFF" })); } + "Toggle Line Numbers" => { self.config.show_line_numbers = !self.config.show_line_numbers; self.chat_log.push(format!("view> Line numbers: {}.", if self.config.show_line_numbers { "ON" } else { "OFF" })); } + "Toggle Whitespace" => self.chat_log.push("view> Toggle whitespace.".into()), + "Toggle Line Endings" => self.chat_log.push("view> Toggle line ending markers.".into()), + "Word Wrap" => { self.config.word_wrap = !self.config.word_wrap; self.chat_log.push(format!("view> Word wrap: {}.", if self.config.word_wrap { "ON" } else { "OFF" })); } + "Toggle Syntax Tone" => { self.highlight_tone = match self.highlight_tone { HighlightTone::CandyPop => HighlightTone::Matte, HighlightTone::Matte => HighlightTone::CandyPop }; } + "Fold All" => self.chat_log.push("view> Fold All.".into()), + "Unfold All" => self.chat_log.push("view> Unfold All.".into()), + "Toggle Current Fold" => self.chat_log.push("view> Toggle fold.".into()), + "Compile" => self.compile_only(), + "Build" => self.build_and_run(), + "^B Build & Run" => self.build_and_run(), + "Run (F5)" => self.run_only(), + "^L Lint Syntax" => self.lint_syntax(), + "Stop Executing" => self.chat_log.push("build> Stop.".into()), + "Clear Output" => { self.chat_log.clear(); self.chat_log.push("sys> Cleared.".into()); } + "Next Message" => self.chat_log.push("build> Next message.".into()), + "Previous Message" => self.chat_log.push("build> Prev message.".into()), + "Run Command..." => self.chat_log.push("tools> Run command.".into()), + "Run Lua Script (F5)" => self.chat_log.push("tools> Lua script.".into()), + "Rust" | "Python" | "C/C++" | "Shell" | "JavaScript" | "TypeScript" | "Markdown" | "HTML" | "CSS" | "JSON" | "XML" | "YAML" | "Go" | "Ruby" | "PHP" | "Java" | "C#" | "SQL" => { + if !self.tabs.is_empty() { self.tabs[self.active_tab].override_syntax = Some(act.to_string()); self.chat_log.push(format!("syntax> Override: {}", act)); } + } + "Clear Override" => { if !self.tabs.is_empty() { self.tabs[self.active_tab].override_syntax = None; self.chat_log.push("syntax> Override cleared.".into()); } } + "Global Properties" => self.chat_log.push("opts> Global properties.".into()), + "User Properties" => self.chat_log.push("opts> User properties.".into()), + "Local Properties" => self.chat_log.push("opts> Local properties.".into()), + "Open Abbreviations" => self.chat_log.push("opts> Abbreviations.".into()), + "^G Help" => self.nano_help(), + "About" => { self.chat_log.push("sys> Jeremy Anderson info@dcos.net Scitano version 1.0 https://git.dcos.net/dcosnet/scitano".into()); self.bottom_tab = BottomTab::Messages; } + "Sync Aider Models" => { self.chat_log.push("ai> Probing Ollama/Aider...".into()); self.aider_models = Self::fetch_aider_models(); self.chat_log.push(format!("ai> Models: {:?}", self.aider_models)); self.bottom_tab = BottomTab::AiTerminal; } + "Aider: Architect Mode" | "Aider: Code Review" | "Aider: Refactor Buffer" => { self.chat_log.push(format!("ai> {}", act)); self.bottom_tab = BottomTab::AiTerminal; } + "Hermes: Local Inference" | "Hermes: System Prompt" | "Odysseus: Crawl Context" | "Odysseus: Vector Sync" => { self.chat_log.push(format!("ai> {}", act)); self.bottom_tab = BottomTab::AiTerminal; } + "Comment Selection" => self.chat_log.push("ctx> Comment selection.".into()), + "Uncomment Selection" => self.chat_log.push("ctx> Uncomment selection.".into()), + "Upper Case" => self.chat_log.push("ctx> Uppercase.".into()), + "Lower Case" => self.chat_log.push("ctx> Lowercase.".into()), + "Insert Timestamp" => self.chat_log.push("ctx> Insert timestamp.".into()), + _ => { self.chat_log.push(format!("sys> Action: '{}'.", act)); } + } + self.active_menu = None; + } + Message::TabSelected(i) => { self.last_action_was_kill = false; self.active_tab = i; } + Message::CloseTab(i) => { + self.last_action_was_kill = false; + if i < self.tabs.len() { + let title = self.tabs[i].title.clone(); + self.tabs.remove(i); + if self.tabs.is_empty() { self.active_tab = 0; } else if self.active_tab >= self.tabs.len() { self.active_tab = self.tabs.len() - 1; } + self.chat_log.push(format!("nano> Closed: {}", title)); + } + } + Message::BottomTabSelected(tab) => { self.last_action_was_kill = false; self.bottom_tab = tab; } + Message::EditorAction(action) => { + self.last_action_was_kill = false; + if !self.tabs.is_empty() { + self.tabs[self.active_tab].content.perform(action); + self.tabs[self.active_tab].is_dirty = true; + self.tabs[self.active_tab].parse_symbols(); + } + } + Message::EditorRightClick => { + self.last_action_was_kill = false; + self.active_menu = if self.active_menu.as_deref() == Some("EditorContext") { None } else { Some("EditorContext".into()) }; + } + Message::SyncAiderModels => {} + Message::ToggleWordWrap(v) => { self.config.word_wrap = v; } + Message::ToggleLineNumbers(v) => { self.config.show_line_numbers = v; } + Message::ToggleSymbolTree(v) => { self.show_symbol_tree = v; } + } + Task::none() + } + + // -- View ------------------------------------------------------ + fn view(&self) -> Element<'_, Message> { + let menu_bar = container( + row![ + button(text("File").size(13)).style(theme::menu_button).padding([2,8]).on_press(Message::MenuToggle("File".into())), + button(text("Edit").size(13)).style(theme::menu_button).padding([2,8]).on_press(Message::MenuToggle("Edit".into())), + button(text("Search").size(13)).style(theme::menu_button).padding([2,8]).on_press(Message::MenuToggle("Search".into())), + button(text("View").size(13)).style(theme::menu_button).padding([2,8]).on_press(Message::MenuToggle("View".into())), + button(text("Build").size(13)).style(theme::menu_button).padding([2,8]).on_press(Message::MenuToggle("Build".into())), + button(text("Tools").size(13)).style(theme::menu_button).padding([2,8]).on_press(Message::MenuToggle("Tools".into())), + button(text("Syntax").size(13)).style(theme::menu_button).padding([2,8]).on_press(Message::MenuToggle("Syntax".into())), + button(text("Options").size(13)).style(theme::menu_button).padding([2,8]).on_press(Message::MenuToggle("Options".into())), + button(text("Help").size(13)).style(theme::menu_button).padding([2,8]).on_press(Message::MenuToggle("Help".into())), + Space::with_width(Length::Fill), + button(text("AI-Bridge").size(13).color(theme::ACCENT_BLUE)).style(theme::menu_button).padding([2,8]).on_press(Message::MenuToggle("AI".into())), + Space::with_width(Length::Fill), + text("Scitano v1.0.0").size(11).color(theme::TEXT_DIM).font(Font::MONOSPACE), + ].spacing(1).align_y(iced::Alignment::Center), + ).style(theme::panel_container).width(Length::Fill).padding([2,4]); + + let mut layout = column![menu_bar]; + + // -- Submenus ------------------------------------------- + if let Some(ref am) = self.active_menu { + let items: Vec<&str> = match am.as_str() { + "File" => vec!["New","Open (F3)","Open Selected","^O WriteOut (Save)","Save As...","^X Close Tab","Reload File","-","Save Session","Load Session","Print...","Exit App"], + "Edit" => vec!["Undo (^Z)","Redo (^Y)","-","^K Kill Line (Cut)","^U Unkill (Paste)","^C Cur Pos","-","^A Select All","Delete Line","Duplicate Line","Transpose Line","-","Match Brace ^E","Comment Line","Uncomment Line","Increase Indent","Decrease Indent"], + "Search" => vec!["^W Where Is (Find)","Find Next (F3)","Find Previous (Shift+F3)","^\\ Replace","Replace Next","-","Go To Line (^_)","-","Toggle Bookmark (^B)","Next Bookmark","Prev Bookmark","Clear All Bookmarks"], + "View" => vec!["Toggle Full Screen (F11)","Toggle Message Window","Toggle Sidebar","Toggle Line Numbers","Toggle Whitespace","Toggle Line Endings","Word Wrap","Toggle Syntax Tone","-","Fold All","Unfold All","Toggle Current Fold"], + "Build" => vec!["Compile","Build","^B Build & Run","Run (F5)","-","^L Lint Syntax","-","Stop Executing","Clear Output","-","Next Message","Previous Message"], + "Tools" => vec!["Run Command...","Run Lua Script (F5)"], + "Syntax" => vec!["Rust","Python","C/C++","Shell","JavaScript","TypeScript","Markdown","HTML","CSS","JSON","XML","YAML","Go","Ruby","PHP","Java","C#","SQL","Clear Override"], + "Options" => vec!["Global Properties","Open Abbreviations","User Properties","Local Properties"], + "Help" => vec!["^G Help","About"], + "AI" => vec!["Sync Aider Models","Aider: Architect Mode","Aider: Code Review","Aider: Refactor Buffer","Hermes: Local Inference","Hermes: System Prompt","Odysseus: Crawl Context","Odysseus: Vector Sync"], + "EditorContext" => vec!["^O Save Buffer","^X Close Tab","-","^B Build File","^L Lint Syntax","-","Comment Selection","Uncomment Selection","-","Upper Case","Lower Case","Insert Timestamp"], + _ => vec![], + }; + let mut sr = row![].spacing(4); + for item in items { + if item == "-" { + sr = sr.push(Space::with_width(Length::Fixed(8.0))); + } else { + sr = sr.push(button(text(item).size(12).font(Font::MONOSPACE) + .color(if item.starts_with('^') { theme::ACCENT_YELLOW } else { theme::TEXT_PRIMARY })) + .style(theme::menu_button).padding([4,10]).on_press(Message::SubMenuAction(item.to_string()))); + } + } + layout = layout.push(container(scrollable(sr).direction( + iced::widget::scrollable::Direction::Horizontal(iced::widget::scrollable::Scrollbar::new().width(0).margin(0)))) + .width(Length::Fill).style(theme::panel_container).padding([4,8])); + } + + // -- Tabs ----------------------------------------------- + let mut tab_row = row![].spacing(0); + for (i, tab) in self.tabs.iter().enumerate() { + let active = self.active_tab == i; + let display = if tab.is_dirty { format!("\u{25cf} {}", tab.title) } else { tab.title.clone() }; + let btn = button(text(display).size(13).font(Font::MONOSPACE).color(if active { theme::TEXT_PRIMARY } else { theme::TEXT_MUTED })) + .style(if active { theme::active_tab_button } else { theme::inactive_tab_button }) + .on_press(Message::TabSelected(i)).padding([4,12]); + tab_row = tab_row.push(mouse_area(btn).on_right_press(Message::CloseTab(i))); + } + tab_row = tab_row.push(button(text("+").size(14).font(Font::MONOSPACE).color(theme::TEXT_MUTED)).style(theme::menu_button).padding([4,8]).on_press(Message::SubMenuAction("New".into()))); + let tab_container = container(scrollable(tab_row).direction( + iced::widget::scrollable::Direction::Horizontal(iced::widget::scrollable::Scrollbar::new().width(0).margin(0)))) + .width(Length::Fill).style(theme::panel_container); + + // -- Editor + Sidebar ------------------------------------ + let mut core_row = row![].width(Length::Fill).height(Length::Fill); + if self.show_symbol_tree { + let mut tc = column![text("SYMBOLS").size(11).font(Font::MONOSPACE).color(theme::TEXT_MUTED)].spacing(6).padding(8); + if !self.tabs.is_empty() { + if self.tabs[self.active_tab].symbols.is_empty() { + tc = tc.push(text(" (no symbols)").size(10).font(Font::MONOSPACE).color(theme::TEXT_DIM)); + } + for (ln, sym) in &self.tabs[self.active_tab].symbols { + let d = if sym.len() > 22 { format!("{}: {}..", ln, &sym[..20]) } else { format!("{}: {}", ln, sym) }; + tc = tc.push(text(d).size(10).font(Font::MONOSPACE).color(theme::ACCENT_BLUE)); + } + } + core_row = core_row.push(container(scrollable(tc)).width(Length::Fixed(180.0)).height(Length::Fill).style(theme::tree_container)); + } + let editor_area = if self.tabs.is_empty() { + container(text("[ No files open -- ^G for help ]").color(theme::TEXT_MUTED).font(Font::MONOSPACE)) + .style(theme::app_container).width(Length::Fill).height(Length::Fill).center_x(Length::Fill).center_y(Length::Fill) + } else { + let syn = self.tabs[self.active_tab].get_syntax(); + let ed = text_editor(&self.tabs[self.active_tab].content).highlight(syn, self.highlight_tone.to_iced_theme()) + .on_action(Message::EditorAction).font(Font::MONOSPACE).height(Length::Fill); + container(mouse_area(ed).on_right_press(Message::EditorRightClick)) + .style(theme::app_container).width(Length::Fill).height(Length::Fill).padding(8) + }; + core_row = core_row.push(editor_area); + + // -- Status Bar ----------------------------------------- + let st = if self.tabs.is_empty() { " Idle".to_string() } else { + let t = &self.tabs[self.active_tab]; + format!(" {} {} | Syntax: {} | Bookmarks: {}", t.title, if t.is_dirty { "[MODIFIED]" } else { "[saved]" }, t.get_syntax().to_uppercase(), t.bookmarks.len()) + }; + let status_bar = container(row![ + text(st).size(12).font(Font::MONOSPACE), + Space::with_width(Length::Fill), + text(if self.config.word_wrap { "Wrap" } else { " nowrap" }).size(11).color(theme::TEXT_MUTED).font(Font::MONOSPACE), + text(" | UTF-8 | LF").size(11).color(theme::TEXT_MUTED).font(Font::MONOSPACE), + ].padding([4,12])).style(theme::status_bar).width(Length::Fill); + + // -- Bottom Panel ---------------------------------------- + let bt = row![ + button(text("Messages").size(11).font(Font::MONOSPACE)).style(if self.bottom_tab==BottomTab::Messages{theme::active_tab_button}else{theme::inactive_tab_button}).padding([2,10]).on_press(Message::BottomTabSelected(BottomTab::Messages)), + button(text("Diagnostics").size(11).font(Font::MONOSPACE)).style(if self.bottom_tab==BottomTab::Diagnostics{theme::active_tab_button}else{theme::inactive_tab_button}).padding([2,10]).on_press(Message::BottomTabSelected(BottomTab::Diagnostics)), + button(text("Build Logs").size(11).font(Font::MONOSPACE)).style(if self.bottom_tab==BottomTab::BuildLogs{theme::active_tab_button}else{theme::inactive_tab_button}).padding([2,10]).on_press(Message::BottomTabSelected(BottomTab::BuildLogs)), + button(text("AI Terminal").size(11).font(Font::MONOSPACE).color(theme::ACCENT_BLUE)).style(if self.bottom_tab==BottomTab::AiTerminal{theme::active_tab_button}else{theme::inactive_tab_button}).padding([2,10]).on_press(Message::BottomTabSelected(BottomTab::AiTerminal)), + ].spacing(0); + let mut cc = column![].spacing(1); + for line in &self.chat_log { + let c = if line.starts_with("err>") { theme::ACCENT_RED } else if line.starts_with("nano>") { theme::ACCENT_GREEN } else if line.starts_with("ai>") { theme::ACCENT_BLUE } else if line.starts_with("sys>") { theme::TEXT_MUTED } else { theme::TEXT_PRIMARY }; + cc = cc.push(text(line).size(12).color(c).font(Font::MONOSPACE)); + } + let bottom = column![ + container(bt).width(Length::Fill).style(theme::panel_container), + container(scrollable(cc)).height(Length::Fixed(160.0)).width(Length::Fill).style(theme::panel_container).padding(6), + ]; + + // -- Footer --------------------------------------------- + let ft = if self.tabs.is_empty() { + " ^G=Help ^O=Save ^X=Exit ^W=Search ^K=Cut ^U=Paste ^C=CurPos ^R=Insert".to_string() + } else { + let tab = &self.tabs[self.active_tab]; + format!(" {} | Lines: {} | {:.2} KB | {} | ^G=Help ^O=Save ^X=Exit ^W=Find ^K=Cut ^U=Paste", + tab.file_path.as_ref().map(|p|p.to_string_lossy().to_string()).unwrap_or_else(||tab.title.clone()), + tab.line_count(), tab.byte_size() as f64/1024.0, tab.get_syntax().to_uppercase()) + }; + let footer = container(text(ft).size(10).font(Font::MONOSPACE).color(theme::TEXT_MUTED)).width(Length::Fill).padding([2,8]).style(theme::footer_bar); + + layout.push(tab_container).push(core_row).push(status_bar).push(bottom).push(footer).width(Length::Fill).height(Length::Fill).into() + } +} + +pub fn main() -> iced::Result { + iced::application("Scitano 1.0 - https://git.dcos.net/dcosnet/scitano/", Scitano::update, Scitano::view) + .theme(|_| Theme::Dark) + .subscription(Scitano::subscription) + .run() +} \ No newline at end of file diff --git a/src/theme.rs b/src/theme.rs new file mode 100755 index 0000000..29f411d --- /dev/null +++ b/src/theme.rs @@ -0,0 +1,99 @@ +use iced::widget::{button, container}; +use iced::{Background, Color, Theme, Border, Shadow}; + +pub const TEXT_PRIMARY: Color = Color::from_rgb(0.9, 0.9, 0.9); +pub const TEXT_MUTED: Color = Color::from_rgb(0.5, 0.5, 0.5); +pub const TEXT_DIM: Color = Color::from_rgb(0.35, 0.35, 0.35); +pub const ACCENT_BLUE: Color = Color::from_rgb(0.4, 0.7, 1.0); +pub const ACCENT_GREEN: Color = Color::from_rgb(0.5, 0.85, 0.5); +pub const ACCENT_YELLOW: Color = Color::from_rgb(0.95, 0.85, 0.4); +pub const ACCENT_RED: Color = Color::from_rgb(0.9, 0.4, 0.4); +pub const BG_PANEL: Color = Color::from_rgb(0.12, 0.12, 0.12); +pub const BG_ACTIVE: Color = Color::from_rgb(0.18, 0.18, 0.18); +pub const BG_STATUS: Color = Color::from_rgb(0.15, 0.25, 0.45); +pub const BG_TREE: Color = Color::from_rgb(0.08, 0.08, 0.08); +pub const BG_FOOTER: Color = Color::from_rgb(0.10, 0.10, 0.10); + +pub fn panel_container(_theme: &Theme) -> container::Style { + container::Style { + text_color: Some(TEXT_PRIMARY), + background: Some(Background::Color(BG_PANEL)), + border: Border::default(), + shadow: Shadow::default(), + } +} + +pub fn tree_container(_theme: &Theme) -> container::Style { + container::Style { + text_color: Some(TEXT_PRIMARY), + background: Some(Background::Color(BG_TREE)), + border: Border { + color: Color::from_rgb(0.2, 0.2, 0.2), + width: 1.0, + radius: 0.0.into(), + }, + shadow: Shadow::default(), + } +} + +pub fn app_container(_theme: &Theme) -> container::Style { + container::Style { + text_color: Some(TEXT_PRIMARY), + background: Some(Background::Color(Color::BLACK)), + border: Border::default(), + shadow: Shadow::default(), + } +} + +pub fn status_bar(_theme: &Theme) -> container::Style { + container::Style { + text_color: Some(Color::WHITE), + background: Some(Background::Color(BG_STATUS)), + border: Border::default(), + shadow: Shadow::default(), + } +} + +pub fn footer_bar(_theme: &Theme) -> container::Style { + container::Style { + text_color: Some(TEXT_MUTED), + background: Some(Background::Color(BG_FOOTER)), + border: Border { + color: Color::from_rgb(0.2, 0.2, 0.2), + width: 1.0, + radius: 0.0.into(), + }, + shadow: Shadow::default(), + } +} + +pub fn menu_button(_theme: &Theme, status: button::Status) -> button::Style { + match status { + button::Status::Hovered => button::Style { + background: Some(Background::Color(BG_ACTIVE)), + text_color: TEXT_PRIMARY, + ..button::Style::default() + }, + _ => button::Style { + background: Some(Background::Color(Color::TRANSPARENT)), + text_color: TEXT_PRIMARY, + ..button::Style::default() + }, + } +} + +pub fn active_tab_button(_theme: &Theme, _status: button::Status) -> button::Style { + button::Style { + background: Some(Background::Color(BG_ACTIVE)), + text_color: TEXT_PRIMARY, + ..button::Style::default() + } +} + +pub fn inactive_tab_button(_theme: &Theme, _status: button::Status) -> button::Style { + button::Style { + background: Some(Background::Color(BG_PANEL)), + text_color: TEXT_MUTED, + ..button::Style::default() + } +} \ No newline at end of file