From 7a0e300ff9d5190a31b49155df51dde5c0db2a29 Mon Sep 17 00:00:00 2001 From: elilchen Date: Sun, 12 Feb 2023 00:48:38 +0800 Subject: [PATCH] UI --- .github/workflows/build.yaml | 22 +- Cargo.toml | 1 + ui/.gitignore | 4 + ui/Cargo.lock | 3787 +++++++++++ ui/Cargo.toml | 31 + ui/build.rs | 21 + ui/html/editor/codemirror.css | 344 + ui/html/editor/codemirror.js | 9874 +++++++++++++++++++++++++++++ ui/html/editor/toml.js | 88 + ui/html/index.html | 22 + ui/html/main.js | 153 + ui/html/style.css | 34 + ui/icons/128x128.png | Bin 0 -> 8097 bytes ui/icons/128x128@2x.png | Bin 0 -> 17636 bytes ui/icons/32x32.png | Bin 0 -> 1759 bytes ui/icons/Square107x107Logo.png | Bin 0 -> 6955 bytes ui/icons/Square142x142Logo.png | Bin 0 -> 9445 bytes ui/icons/Square150x150Logo.png | Bin 0 -> 10013 bytes ui/icons/Square284x284Logo.png | Bin 0 -> 21381 bytes ui/icons/Square30x30Logo.png | Bin 0 -> 1712 bytes ui/icons/Square310x310Logo.png | Bin 0 -> 24091 bytes ui/icons/Square44x44Logo.png | Bin 0 -> 2772 bytes ui/icons/Square71x71Logo.png | Bin 0 -> 4658 bytes ui/icons/Square89x89Logo.png | Bin 0 -> 5919 bytes ui/icons/StoreLogo.png | Bin 0 -> 3184 bytes ui/icons/icon.icns | Bin 0 -> 222208 bytes ui/icons/icon.ico | Bin 0 -> 30589 bytes ui/icons/icon.png | Bin 0 -> 42074 bytes ui/setup.nsi | 108 + ui/setup/service/nssm.exe | Bin 0 -> 294912 bytes ui/setup/service/run.cmd | 23 + ui/src/adapter/mod.rs | 5 + ui/src/adapter/service/mod.rs | 3 + ui/src/adapter/service/windows.rs | 130 + ui/src/adapter/view/desktop.rs | 220 + ui/src/adapter/view/mod.rs | 3 + ui/src/lib.rs | 17 + ui/src/main.rs | 25 + ui/src/usecase/mod.rs | 9 + ui/src/usecase/presenter.rs | 59 + ui/src/usecase/service.rs | 24 + ui/src/usecase/view.rs | 22 + ui/src/usecase/watcher.rs | 46 + ui/tauri.conf.json | 89 + 44 files changed, 15162 insertions(+), 2 deletions(-) create mode 100644 ui/.gitignore create mode 100644 ui/Cargo.lock create mode 100644 ui/Cargo.toml create mode 100644 ui/build.rs create mode 100644 ui/html/editor/codemirror.css create mode 100644 ui/html/editor/codemirror.js create mode 100644 ui/html/editor/toml.js create mode 100644 ui/html/index.html create mode 100644 ui/html/main.js create mode 100644 ui/html/style.css create mode 100644 ui/icons/128x128.png create mode 100644 ui/icons/128x128@2x.png create mode 100644 ui/icons/32x32.png create mode 100644 ui/icons/Square107x107Logo.png create mode 100644 ui/icons/Square142x142Logo.png create mode 100644 ui/icons/Square150x150Logo.png create mode 100644 ui/icons/Square284x284Logo.png create mode 100644 ui/icons/Square30x30Logo.png create mode 100644 ui/icons/Square310x310Logo.png create mode 100644 ui/icons/Square44x44Logo.png create mode 100644 ui/icons/Square71x71Logo.png create mode 100644 ui/icons/Square89x89Logo.png create mode 100644 ui/icons/StoreLogo.png create mode 100644 ui/icons/icon.icns create mode 100644 ui/icons/icon.ico create mode 100644 ui/icons/icon.png create mode 100644 ui/setup.nsi create mode 100644 ui/setup/service/nssm.exe create mode 100644 ui/setup/service/run.cmd create mode 100644 ui/src/adapter/mod.rs create mode 100644 ui/src/adapter/service/mod.rs create mode 100644 ui/src/adapter/service/windows.rs create mode 100644 ui/src/adapter/view/desktop.rs create mode 100644 ui/src/adapter/view/mod.rs create mode 100644 ui/src/lib.rs create mode 100644 ui/src/main.rs create mode 100644 ui/src/usecase/mod.rs create mode 100644 ui/src/usecase/presenter.rs create mode 100644 ui/src/usecase/service.rs create mode 100644 ui/src/usecase/view.rs create mode 100644 ui/src/usecase/watcher.rs create mode 100644 ui/tauri.conf.json diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index c227484..fdd221f 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -95,7 +95,24 @@ jobs: with: command: build args: --release --all-features --target=x86_64-pc-windows-msvc - use-cross: true + use-cross: true + + - name: Install NSIS + run: | + iwr -useb get.scoop.sh -outfile 'install.ps1' + .\install.ps1 -RunAsAdmin + scoop update + scoop bucket add extras + scoop install nsis + + - run: rustup default nightly + - run: cargo build --release + working-directory: ./ui + - run: xcopy /y target\x86_64-pc-windows-msvc\release\*.exe ui\setup\bin\ + - run: xcopy /y ui\target\release\*.exe ui\setup\ + - run: mkdir ui\setup\logs + - run: makensis /V1 setup.nsi + working-directory: ./ui - name: Publish Artifacts uses: actions/upload-artifact@v3 @@ -104,7 +121,8 @@ jobs: path: | target\x86_64-pc-windows-msvc\release\hbbr.exe target\x86_64-pc-windows-msvc\release\hbbs.exe - target\x86_64-pc-windows-msvc\release\rustdesk-utils.exe + target\x86_64-pc-windows-msvc\release\rustdesk-utils.exe + ui\RustDeskServer.Setup.exe if-no-files-found: error # github (draft) release with all binaries diff --git a/Cargo.toml b/Cargo.toml index c7e7e0f..9417e2b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -57,3 +57,4 @@ hbb_common = { path = "libs/hbb_common" } [workspace] members = ["libs/hbb_common"] +exclude = ["ui"] diff --git a/ui/.gitignore b/ui/.gitignore new file mode 100644 index 0000000..f4dfb82 --- /dev/null +++ b/ui/.gitignore @@ -0,0 +1,4 @@ +# Generated by Cargo +# will have compiled files and executables +/target/ + diff --git a/ui/Cargo.lock b/ui/Cargo.lock new file mode 100644 index 0000000..7c45be6 --- /dev/null +++ b/ui/Cargo.lock @@ -0,0 +1,3787 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "aho-corasick" +version = "0.7.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" +dependencies = [ + "memchr", +] + +[[package]] +name = "alloc-no-stdlib" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" + +[[package]] +name = "alloc-stdlib" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" +dependencies = [ + "alloc-no-stdlib", +] + +[[package]] +name = "anyhow" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800" + +[[package]] +name = "async-attributes" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3203e79f4dd9bdda415ed03cf14dae5a2bf775c683a00f94e9cd1faf0f596e5" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "async-channel" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf46fee83e5ccffc220104713af3292ff9bc7c64c7de289f66dae8e38d826833" +dependencies = [ + "concurrent-queue", + "event-listener", + "futures-core", +] + +[[package]] +name = "async-executor" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17adb73da160dfb475c183343c8cccd80721ea5a605d3eb57125f0a7b7a92d0b" +dependencies = [ + "async-lock", + "async-task", + "concurrent-queue", + "fastrand", + "futures-lite", + "slab", +] + +[[package]] +name = "async-global-executor" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1b6f5d7df27bd294849f8eec66ecfc63d11814df7a4f5d74168a2394467b776" +dependencies = [ + "async-channel", + "async-executor", + "async-io", + "async-lock", + "blocking", + "futures-lite", + "once_cell", +] + +[[package]] +name = "async-io" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c374dda1ed3e7d8f0d9ba58715f924862c63eae6849c92d3a18e7fbde9e2794" +dependencies = [ + "async-lock", + "autocfg", + "concurrent-queue", + "futures-lite", + "libc", + "log", + "parking", + "polling", + "slab", + "socket2", + "waker-fn", + "windows-sys 0.42.0", +] + +[[package]] +name = "async-lock" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8101efe8695a6c17e02911402145357e718ac92d3ff88ae8419e84b1707b685" +dependencies = [ + "event-listener", + "futures-lite", +] + +[[package]] +name = "async-process" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6381ead98388605d0d9ff86371043b5aa922a3905824244de40dc263a14fcba4" +dependencies = [ + "async-io", + "async-lock", + "autocfg", + "blocking", + "cfg-if", + "event-listener", + "futures-lite", + "libc", + "signal-hook", + "windows-sys 0.42.0", +] + +[[package]] +name = "async-std" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d" +dependencies = [ + "async-attributes", + "async-channel", + "async-global-executor", + "async-io", + "async-lock", + "async-process", + "crossbeam-utils", + "futures-channel", + "futures-core", + "futures-io", + "futures-lite", + "gloo-timers", + "kv-log-macro", + "log", + "memchr", + "once_cell", + "pin-project-lite", + "pin-utils", + "slab", + "wasm-bindgen-futures", +] + +[[package]] +name = "async-task" +version = "4.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a40729d2133846d9ed0ea60a8b9541bccddab49cd30f0715a1da672fe9a2524" + +[[package]] +name = "atk" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c3d816ce6f0e2909a96830d6911c2aff044370b1ef92d7f267b43bae5addedd" +dependencies = [ + "atk-sys", + "bitflags", + "glib", + "libc", +] + +[[package]] +name = "atk-sys" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58aeb089fb698e06db8089971c7ee317ab9644bade33383f63631437b03aafb6" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps 6.0.3", +] + +[[package]] +name = "atomic-waker" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "debc29dde2e69f9e47506b525f639ed42300fc014a3e007832592448fa8e4599" + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[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.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" +dependencies = [ + "generic-array", +] + +[[package]] +name = "blocking" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c67b173a56acffd6d2326fb7ab938ba0b00a71480e14902b2591c87bc5741e8" +dependencies = [ + "async-channel", + "async-lock", + "async-task", + "atomic-waker", + "fastrand", + "futures-lite", +] + +[[package]] +name = "brotli" +version = "3.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1a0b1dbcc8ae29329621f8d4f0d835787c1c38bb1401979b49d13b0b305ff68" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", + "brotli-decompressor", +] + +[[package]] +name = "brotli-decompressor" +version = "2.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b6561fd3f895a11e8f72af2cb7d22e08366bebc2b6b57f7744c4bda27034744" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", +] + +[[package]] +name = "bstr" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7f0778972c64420fdedc63f09919c8a88bda7b25135357fd25a5d9f3257e832" +dependencies = [ + "memchr", + "serde", +] + +[[package]] +name = "bumpalo" +version = "3.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" + +[[package]] +name = "bytemuck" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c041d3eab048880cb0b86b256447da3f18859a163c3b8d8893f4e6368abe6393" + +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "bytes" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" + +[[package]] +name = "cairo-rs" +version = "0.15.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c76ee391b03d35510d9fa917357c7f1855bd9a6659c95a1b392e33f49b3369bc" +dependencies = [ + "bitflags", + "cairo-sys-rs", + "glib", + "libc", + "thiserror", +] + +[[package]] +name = "cairo-sys-rs" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c55d429bef56ac9172d25fecb85dc8068307d17acd74b377866b7a1ef25d3c8" +dependencies = [ + "glib-sys", + "libc", + "system-deps 6.0.3", +] + +[[package]] +name = "cargo_toml" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "497049e9477329f8f6a559972ee42e117487d01d1e8c2cc9f836ea6fa23a9e1a" +dependencies = [ + "serde", + "toml", +] + +[[package]] +name = "cc" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" + +[[package]] +name = "cesu8" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" + +[[package]] +name = "cfb" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74f89d248799e3f15f91b70917f65381062a01bb8e222700ea0e5a7ff9785f9c" +dependencies = [ + "byteorder", + "uuid 0.8.2", +] + +[[package]] +name = "cfg-expr" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3431df59f28accaf4cb4eed4a9acc66bea3f3c3753aa6cdc2f024174ef232af7" +dependencies = [ + "smallvec", +] + +[[package]] +name = "cfg-expr" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0357a6402b295ca3a86bc148e84df46c02e41f41fef186bda662557ef6328aa" +dependencies = [ + "smallvec", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cocoa" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f425db7937052c684daec3bd6375c8abe2d146dca4b8b143d6db777c39138f3a" +dependencies = [ + "bitflags", + "block", + "cocoa-foundation", + "core-foundation", + "core-graphics", + "foreign-types", + "libc", + "objc", +] + +[[package]] +name = "cocoa-foundation" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ade49b65d560ca58c403a479bb396592b155c0185eada742ee323d1d68d6318" +dependencies = [ + "bitflags", + "block", + "core-foundation", + "core-graphics-types", + "foreign-types", + "libc", + "objc", +] + +[[package]] +name = "color_quant" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" + +[[package]] +name = "combine" +version = "4.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35ed6e9d84f0b51a7f52daf1c7d71dd136fd7a3f41a8462b8cdb8c78d920fad4" +dependencies = [ + "bytes", + "memchr", +] + +[[package]] +name = "concurrent-queue" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c278839b831783b70278b14df4d45e1beb1aad306c07bb796637de9a0e323e8e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + +[[package]] +name = "core-foundation" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" + +[[package]] +name = "core-graphics" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb" +dependencies = [ + "bitflags", + "core-foundation", + "core-graphics-types", + "foreign-types", + "libc", +] + +[[package]] +name = "core-graphics-types" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a68b68b3446082644c91ac778bf50cd4104bfb002b5a6a7c44cca5a2c70788b" +dependencies = [ + "bitflags", + "core-foundation", + "foreign-types", + "libc", +] + +[[package]] +name = "cpufeatures" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "cssparser" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "754b69d351cdc2d8ee09ae203db831e005560fc6030da058f86ad60c92a9cb0a" +dependencies = [ + "cssparser-macros", + "dtoa-short", + "itoa 0.4.8", + "matches", + "phf 0.8.0", + "proc-macro2", + "quote", + "smallvec", + "syn", +] + +[[package]] +name = "cssparser-macros" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfae75de57f2b2e85e8768c3ea840fd159c8f33e2b6522c7835b7abac81be16e" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "ctor" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "cty" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35" + +[[package]] +name = "darling" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" +dependencies = [ + "darling_core", + "quote", + "syn", +] + +[[package]] +name = "derive-new" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3418329ca0ad70234b9735dc4ceed10af4df60eff9c8e7b06cb5e520d92c3535" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version 0.4.0", + "syn", +] + +[[package]] +name = "digest" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "dirs-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +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 = "dtoa" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56899898ce76aaf4a0f24d914c97ea6ed976d42fec6ad33fcbb0a1103e07b2b0" + +[[package]] +name = "dtoa-short" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bde03329ae10e79ede66c9ce4dc930aa8599043b0743008548680f25b91502d6" +dependencies = [ + "dtoa", +] + +[[package]] +name = "dunce" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bd4b30a6560bbd9b4620f4de34c3f14f60848e58a9b7216801afcb4c7b31c3c" + +[[package]] +name = "embed_plist" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ef6b89e5b37196644d8796de5268852ff179b44e96276cf4290264843743bb7" + +[[package]] +name = "encoding_rs" +version = "0.8.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "err-derive" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c34a887c8df3ed90498c1c437ce21f211c8e27672921a8ffa293cb8d6d4caa9e" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "rustversion", + "syn", + "synstructure", +] + +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + +[[package]] +name = "fastrand" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" +dependencies = [ + "instant", +] + +[[package]] +name = "field-offset" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e1c54951450cbd39f3dbcf1005ac413b49487dabf18a720ad2383eccfeffb92" +dependencies = [ + "memoffset", + "rustc_version 0.3.3", +] + +[[package]] +name = "filetime" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a3de6e8d11b22ff9edc6d916f890800597d60f8b2da1caf2955c274638d6412" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "windows-sys 0.45.0", +] + +[[package]] +name = "flate2" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841" +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 = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "form_urlencoded" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "fsevent-sys" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2" +dependencies = [ + "libc", +] + +[[package]] +name = "futf" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df420e2e84819663797d1ec6544b13c5be84629e7bb00dc960d6917db2987843" +dependencies = [ + "mac", + "new_debug_unreachable", +] + +[[package]] +name = "futures-channel" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e5317663a9089767a1ec00a487df42e0ca174b61b4483213ac24448e4664df5" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec90ff4d0fe1f57d600049061dc6bb68ed03c7d2fbd697274c41805dcb3f8608" + +[[package]] +name = "futures-executor" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8de0a35a6ab97ec8869e32a2473f4b1324459e14c29275d14b10cb1fd19b50e" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfb8371b6fb2aeb2d280374607aeabfc99d95c72edfe51692e42d3d7f0d08531" + +[[package]] +name = "futures-lite" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7694489acd39452c77daa48516b894c153f192c3578d5a839b62c58099fcbf48" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "memchr", + "parking", + "pin-project-lite", + "waker-fn", +] + +[[package]] +name = "futures-macro" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95a73af87da33b5acf53acfebdc339fe592ecf5357ac7c0a7734ab9d8c876a70" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-task" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcf79a1bf610b10f42aea489289c5a2c478a786509693b80cd39c44ccd936366" + +[[package]] +name = "futures-util" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c1d6de3acfef38d2be4b1f543f553131788603495be83da675e180c8d6b7bd1" +dependencies = [ + "futures-core", + "futures-macro", + "futures-task", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + +[[package]] +name = "gdk" +version = "0.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6e05c1f572ab0e1f15be94217f0dc29088c248b14f792a5ff0af0d84bcda9e8" +dependencies = [ + "bitflags", + "cairo-rs", + "gdk-pixbuf", + "gdk-sys", + "gio", + "glib", + "libc", + "pango", +] + +[[package]] +name = "gdk-pixbuf" +version = "0.15.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad38dd9cc8b099cceecdf41375bb6d481b1b5a7cd5cd603e10a69a9383f8619a" +dependencies = [ + "bitflags", + "gdk-pixbuf-sys", + "gio", + "glib", + "libc", +] + +[[package]] +name = "gdk-pixbuf-sys" +version = "0.15.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "140b2f5378256527150350a8346dbdb08fadc13453a7a2d73aecd5fab3c402a7" +dependencies = [ + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "system-deps 6.0.3", +] + +[[package]] +name = "gdk-sys" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32e7a08c1e8f06f4177fb7e51a777b8c1689f743a7bc11ea91d44d2226073a88" +dependencies = [ + "cairo-sys-rs", + "gdk-pixbuf-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "pango-sys", + "pkg-config", + "system-deps 6.0.3", +] + +[[package]] +name = "gdkx11-sys" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4b7f8c7a84b407aa9b143877e267e848ff34106578b64d1e0a24bf550716178" +dependencies = [ + "gdk-sys", + "glib-sys", + "libc", + "system-deps 6.0.3", + "x11", +] + +[[package]] +name = "generator" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d266041a359dfa931b370ef684cceb84b166beb14f7f0421f4a6a3d0c446d12e" +dependencies = [ + "cc", + "libc", + "log", + "rustversion", + "windows", +] + +[[package]] +name = "generic-array" +version = "0.14.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", +] + +[[package]] +name = "gio" +version = "0.15.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68fdbc90312d462781a395f7a16d96a2b379bb6ef8cd6310a2df272771c4283b" +dependencies = [ + "bitflags", + "futures-channel", + "futures-core", + "futures-io", + "gio-sys", + "glib", + "libc", + "once_cell", + "thiserror", +] + +[[package]] +name = "gio-sys" +version = "0.15.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32157a475271e2c4a023382e9cab31c4584ee30a97da41d3c4e9fdd605abcf8d" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps 6.0.3", + "winapi", +] + +[[package]] +name = "glib" +version = "0.15.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edb0306fbad0ab5428b0ca674a23893db909a98582969c9b537be4ced78c505d" +dependencies = [ + "bitflags", + "futures-channel", + "futures-core", + "futures-executor", + "futures-task", + "glib-macros", + "glib-sys", + "gobject-sys", + "libc", + "once_cell", + "smallvec", + "thiserror", +] + +[[package]] +name = "glib-macros" +version = "0.15.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25a68131a662b04931e71891fb14aaf65ee4b44d08e8abc10f49e77418c86c64" +dependencies = [ + "anyhow", + "heck 0.4.1", + "proc-macro-crate", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "glib-sys" +version = "0.15.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef4b192f8e65e9cf76cbf4ea71fa8e3be4a0e18ffe3d68b8da6836974cc5bad4" +dependencies = [ + "libc", + "system-deps 6.0.3", +] + +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + +[[package]] +name = "globset" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "029d74589adefde59de1a0c4f4732695c32805624aec7b68d91503d4dba79afc" +dependencies = [ + "aho-corasick", + "bstr", + "fnv", + "log", + "regex", +] + +[[package]] +name = "gloo-timers" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" +dependencies = [ + "futures-channel", + "futures-core", + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "gobject-sys" +version = "0.15.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d57ce44246becd17153bd035ab4d32cfee096a657fc01f2231c9278378d1e0a" +dependencies = [ + "glib-sys", + "libc", + "system-deps 6.0.3", +] + +[[package]] +name = "gtk" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92e3004a2d5d6d8b5057d2b57b3712c9529b62e82c77f25c1fecde1fd5c23bd0" +dependencies = [ + "atk", + "bitflags", + "cairo-rs", + "field-offset", + "futures-channel", + "gdk", + "gdk-pixbuf", + "gio", + "glib", + "gtk-sys", + "gtk3-macros", + "libc", + "once_cell", + "pango", + "pkg-config", +] + +[[package]] +name = "gtk-sys" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5bc2f0587cba247f60246a0ca11fe25fb733eabc3de12d1965fc07efab87c84" +dependencies = [ + "atk-sys", + "cairo-sys-rs", + "gdk-pixbuf-sys", + "gdk-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "pango-sys", + "system-deps 6.0.3", +] + +[[package]] +name = "gtk3-macros" +version = "0.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24f518afe90c23fba585b2d7697856f9e6a7bbc62f65588035e66f6afb01a2e9" +dependencies = [ + "anyhow", + "proc-macro-crate", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "heck" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "hermit-abi" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" +dependencies = [ + "libc", +] + +[[package]] +name = "html5ever" +version = "0.25.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5c13fb08e5d4dfc151ee5e88bae63f7773d61852f3bdc73c9f4b9e1bde03148" +dependencies = [ + "log", + "mac", + "markup5ever", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "http" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" +dependencies = [ + "bytes", + "fnv", + "itoa 1.0.5", +] + +[[package]] +name = "http-range" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21dec9db110f5f872ed9699c3ecf50cf16f423502706ba5c72462e28d3157573" + +[[package]] +name = "ico" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "031530fe562d8c8d71c0635013d6d155bbfe8ba0aa4b4d2d24ce8af6b71047bd" +dependencies = [ + "byteorder", + "png", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "ignore" +version = "0.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "713f1b139373f96a2e0ce3ac931cd01ee973c3c5dd7c40c0c2efe96ad2b6751d" +dependencies = [ + "crossbeam-utils", + "globset", + "lazy_static", + "log", + "memchr", + "regex", + "same-file", + "thread_local", + "walkdir", + "winapi-util", +] + +[[package]] +name = "image" +version = "0.24.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69b7ea949b537b0fd0af141fff8c77690f2ce96f4f41f042ccb6c69c6c965945" +dependencies = [ + "bytemuck", + "byteorder", + "color_quant", + "num-rational", + "num-traits", +] + +[[package]] +name = "indexmap" +version = "1.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" +dependencies = [ + "autocfg", + "hashbrown", +] + +[[package]] +name = "infer" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20b2b533137b9cad970793453d4f921c2e91312a6d88b1085c07bc15fc51bb3b" +dependencies = [ + "cfb", +] + +[[package]] +name = "inotify" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff" +dependencies = [ + "bitflags", + "inotify-sys", + "libc", +] + +[[package]] +name = "inotify-sys" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" +dependencies = [ + "libc", +] + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "itoa" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" + +[[package]] +name = "itoa" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" + +[[package]] +name = "javascriptcore-rs" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf053e7843f2812ff03ef5afe34bb9c06ffee120385caad4f6b9967fcd37d41c" +dependencies = [ + "bitflags", + "glib", + "javascriptcore-rs-sys", +] + +[[package]] +name = "javascriptcore-rs-sys" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "905fbb87419c5cde6e3269537e4ea7d46431f3008c5d057e915ef3f115e7793c" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps 5.0.0", +] + +[[package]] +name = "jni" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "039022cdf4d7b1cf548d31f60ae783138e5fd42013f6271049d7df7afadef96c" +dependencies = [ + "cesu8", + "combine", + "jni-sys", + "log", + "thiserror", + "walkdir", +] + +[[package]] +name = "jni-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + +[[package]] +name = "js-sys" +version = "0.3.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "json-patch" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb3fa5a61630976fc4c353c70297f2e93f1930e3ccee574d59d618ccbd5154ce" +dependencies = [ + "serde", + "serde_json", + "treediff", +] + +[[package]] +name = "kqueue" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c8fc60ba15bf51257aa9807a48a61013db043fcf3a78cb0d916e8e396dcad98" +dependencies = [ + "kqueue-sys", + "libc", +] + +[[package]] +name = "kqueue-sys" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8367585489f01bc55dd27404dcf56b95e6da061a256a666ab23be9ba96a2e587" +dependencies = [ + "bitflags", + "libc", +] + +[[package]] +name = "kuchiki" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ea8e9c6e031377cff82ee3001dc8026cdf431ed4e2e6b51f98ab8c73484a358" +dependencies = [ + "cssparser", + "html5ever", + "matches", + "selectors", +] + +[[package]] +name = "kv-log-macro" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" +dependencies = [ + "log", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libappindicator" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2d3cb96d092b4824cb306c9e544c856a4cb6210c1081945187f7f1924b47e8" +dependencies = [ + "glib", + "gtk", + "gtk-sys", + "libappindicator-sys", + "log", +] + +[[package]] +name = "libappindicator-sys" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1b3b6681973cea8cc3bce7391e6d7d5502720b80a581c9a95c9cbaf592826aa" +dependencies = [ + "gtk-sys", + "libloading", + "once_cell", +] + +[[package]] +name = "libc" +version = "0.2.139" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" + +[[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 = "line-wrap" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f30344350a2a51da54c1d53be93fade8a237e545dbcc4bdbe635413f2117cab9" +dependencies = [ + "safemem", +] + +[[package]] +name = "lock_api" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", + "value-bag", +] + +[[package]] +name = "loom" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff50ecb28bb86013e935fb6683ab1f6d3a20016f123c76fd4c27470076ac30f5" +dependencies = [ + "cfg-if", + "generator", + "scoped-tls", + "serde", + "serde_json", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "mac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" + +[[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" +dependencies = [ + "libc", +] + +[[package]] +name = "markup5ever" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a24f40fb03852d1cdd84330cddcaf98e9ec08a7b7768e952fad3b4cf048ec8fd" +dependencies = [ + "log", + "phf 0.8.0", + "phf_codegen", + "string_cache", + "string_cache_codegen", + "tendril", +] + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata", +] + +[[package]] +name = "matches" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "memoffset" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +dependencies = [ + "autocfg", +] + +[[package]] +name = "miniz_oxide" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de" +dependencies = [ + "libc", + "log", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys 0.42.0", +] + +[[package]] +name = "ndk" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2032c77e030ddee34a6787a64166008da93f6a352b629261d0fee232b8742dd4" +dependencies = [ + "bitflags", + "jni-sys", + "ndk-sys", + "num_enum", + "thiserror", +] + +[[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.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e5a6ae77c8ee183dcbbba6150e2e6b9f3f4196a7666c02a715a95692ec1fa97" +dependencies = [ + "jni-sys", +] + +[[package]] +name = "new_debug_unreachable" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" + +[[package]] +name = "nodrop" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" + +[[package]] +name = "nom8" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae01545c9c7fc4486ab7debaf2aad7003ac19431791868fb2e8066df97fad2f8" +dependencies = [ + "memchr", +] + +[[package]] +name = "notify" +version = "5.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58ea850aa68a06e48fdb069c0ec44d0d64c8dbffa49bf3b6f7f0a901fdea1ba9" +dependencies = [ + "bitflags", + "crossbeam-channel", + "filetime", + "fsevent-sys", + "inotify", + "kqueue", + "libc", + "mio", + "walkdir", + "windows-sys 0.42.0", +] + +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "num_enum" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d829733185c1ca374f17e52b762f24f535ec625d2cc1f070e34c8a9068f341b" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2be1598bf1c313dcdd12092e3f1920f463462525a21b7b4e11b4168353d0123e" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] + +[[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_exception" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad970fb455818ad6cba4c122ad012fae53ae8b4795f86378bce65e4f6bab2ca4" +dependencies = [ + "cc", +] + +[[package]] +name = "objc_id" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b" +dependencies = [ + "objc", +] + +[[package]] +name = "once_cell" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" + +[[package]] +name = "open" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2078c0039e6a54a0c42c28faa984e115fb4c2d5bf2208f77d1961002df8576f8" +dependencies = [ + "pathdiff", + "windows-sys 0.42.0", +] + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "pango" +version = "0.15.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e4045548659aee5313bde6c582b0d83a627b7904dd20dc2d9ef0895d414e4f" +dependencies = [ + "bitflags", + "glib", + "libc", + "once_cell", + "pango-sys", +] + +[[package]] +name = "pango-sys" +version = "0.15.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2a00081cde4661982ed91d80ef437c20eacaf6aa1a5962c0279ae194662c3aa" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps 6.0.3", +] + +[[package]] +name = "parking" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" + +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-sys 0.45.0", +] + +[[package]] +name = "paste" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d01a5bd0424d00070b0098dd17ebca6f961a959dead1dbcbbbc1d1cd8d3deeba" + +[[package]] +name = "pathdiff" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" + +[[package]] +name = "percent-encoding" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" + +[[package]] +name = "pest" +version = "2.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "028accff104c4e513bad663bbcd2ad7cfd5304144404c31ed0a77ac103d00660" +dependencies = [ + "thiserror", + "ucd-trie", +] + +[[package]] +name = "phf" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" +dependencies = [ + "phf_macros 0.8.0", + "phf_shared 0.8.0", + "proc-macro-hack", +] + +[[package]] +name = "phf" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" +dependencies = [ + "phf_macros 0.10.0", + "phf_shared 0.10.0", + "proc-macro-hack", +] + +[[package]] +name = "phf_codegen" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbffee61585b0411840d3ece935cce9cb6321f01c45477d30066498cd5e1a815" +dependencies = [ + "phf_generator 0.8.0", + "phf_shared 0.8.0", +] + +[[package]] +name = "phf_generator" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17367f0cc86f2d25802b2c26ee58a7b23faeccf78a396094c13dced0d0182526" +dependencies = [ + "phf_shared 0.8.0", + "rand 0.7.3", +] + +[[package]] +name = "phf_generator" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" +dependencies = [ + "phf_shared 0.10.0", + "rand 0.8.5", +] + +[[package]] +name = "phf_macros" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6fde18ff429ffc8fe78e2bf7f8b7a5a5a6e2a8b58bc5a9ac69198bbda9189c" +dependencies = [ + "phf_generator 0.8.0", + "phf_shared 0.8.0", + "proc-macro-hack", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "phf_macros" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58fdf3184dd560f160dd73922bea2d5cd6e8f064bf4b13110abd81b03697b4e0" +dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", + "proc-macro-hack", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "phf_shared" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7" +dependencies = [ + "siphasher", +] + +[[package]] +name = "phf_shared" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +dependencies = [ + "siphasher", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" + +[[package]] +name = "plist" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5329b8f106a176ab0dce4aae5da86bfcb139bb74fb00882859e03745011f3635" +dependencies = [ + "base64", + "indexmap", + "line-wrap", + "quick-xml", + "serde", + "time", +] + +[[package]] +name = "png" +version = "0.17.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d708eaf860a19b19ce538740d2b4bdeeb8337fa53f7738455e706623ad5c638" +dependencies = [ + "bitflags", + "crc32fast", + "flate2", + "miniz_oxide", +] + +[[package]] +name = "polling" +version = "2.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22122d5ec4f9fe1b3916419b76be1e80bcb93f618d071d2edf841b137b2a2bd6" +dependencies = [ + "autocfg", + "cfg-if", + "libc", + "log", + "wepoll-ffi", + "windows-sys 0.42.0", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + +[[package]] +name = "proc-macro-crate" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66618389e4ec1c7afe67d51a9bf34ff9236480f8d51e7489b7d5ab0303c13f34" +dependencies = [ + "once_cell", + "toml_edit", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro-hack" +version = "0.5.20+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" + +[[package]] +name = "proc-macro2" +version = "1.0.51" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quick-xml" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f50b1c63b38611e7d4d7f68b82d3ad0cc71a2ad2e7f61fc10f1328d917c93cd" +dependencies = [ + "memchr", +] + +[[package]] +name = "quote" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom 0.1.16", + "libc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc", + "rand_pcg", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core 0.5.1", +] + +[[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 0.6.4", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.8", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", +] + +[[package]] +name = "rand_pcg" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429" +dependencies = [ + "rand_core 0.5.1", +] + +[[package]] +name = "raw-window-handle" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed7e3d950b66e19e0c372f3fa3fbbcf85b1746b571f74e0c2af6042a5c93420a" +dependencies = [ + "cty", +] + +[[package]] +name = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags", +] + +[[package]] +name = "redox_users" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +dependencies = [ + "getrandom 0.2.8", + "redox_syscall", + "thiserror", +] + +[[package]] +name = "regex" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" + +[[package]] +name = "remove_dir_all" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +dependencies = [ + "winapi", +] + +[[package]] +name = "rustc_version" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" +dependencies = [ + "semver 0.11.0", +] + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver 1.0.16", +] + +[[package]] +name = "rustdesk_server" +version = "0.1.1" +dependencies = [ + "async-std", + "crossbeam-channel", + "derive-new", + "notify", + "once_cell", + "serde", + "serde_json", + "tauri", + "tauri-build", + "windows-service", + "winres", +] + +[[package]] +name = "rustversion" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5583e89e108996506031660fe09baa5011b9dd0341b89029313006d1fb508d70" + +[[package]] +name = "ryu" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" + +[[package]] +name = "safemem" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" + +[[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 = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "selectors" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df320f1889ac4ba6bc0cdc9c9af7af4bd64bb927bccdf32d81140dc1f9be12fe" +dependencies = [ + "bitflags", + "cssparser", + "derive_more", + "fxhash", + "log", + "matches", + "phf 0.8.0", + "phf_codegen", + "precomputed-hash", + "servo_arc", + "smallvec", + "thin-slice", +] + +[[package]] +name = "semver" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a" +dependencies = [ + "serde", +] + +[[package]] +name = "semver-parser" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" +dependencies = [ + "pest", +] + +[[package]] +name = "serde" +version = "1.0.152" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.152" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76" +dependencies = [ + "itoa 1.0.5", + "ryu", + "serde", +] + +[[package]] +name = "serde_repr" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a5ec9fa74a20ebbe5d9ac23dac1fc96ba0ecfe9f50f2843b52e537b10fbcb4e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_with" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "678b5a069e50bf00ecd22d0cd8ddf7c236f68581b03db652061ed5eb13a312ff" +dependencies = [ + "serde", + "serde_with_macros", +] + +[[package]] +name = "serde_with_macros" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e182d6ec6f05393cc0e5ed1bf81ad6db3a8feedf8ee515ecdd369809bcce8082" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serialize-to-javascript" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9823f2d3b6a81d98228151fdeaf848206a7855a7a042bbf9bf870449a66cafb" +dependencies = [ + "serde", + "serde_json", + "serialize-to-javascript-impl", +] + +[[package]] +name = "serialize-to-javascript-impl" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74064874e9f6a15f04c1f3cb627902d0e6b410abbf36668afa873c61889f1763" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "servo_arc" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d98238b800e0d1576d8b6e3de32827c2d74bee68bb97748dcf5071fb53965432" +dependencies = [ + "nodrop", + "stable_deref_trait", +] + +[[package]] +name = "sha2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sharded-slab" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "signal-hook" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a253b5e89e2698464fc26b545c9edceb338e18a89effeeecfea192c3025be29d" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" +dependencies = [ + "libc", +] + +[[package]] +name = "siphasher" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" + +[[package]] +name = "slab" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" + +[[package]] +name = "socket2" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "soup2" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2b4d76501d8ba387cf0fefbe055c3e0a59891d09f0f995ae4e4b16f6b60f3c0" +dependencies = [ + "bitflags", + "gio", + "glib", + "libc", + "once_cell", + "soup2-sys", +] + +[[package]] +name = "soup2-sys" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "009ef427103fcb17f802871647a7fa6c60cbb654b4c4e4c0ac60a31c5f6dc9cf" +dependencies = [ + "bitflags", + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "system-deps 5.0.0", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "state" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbe866e1e51e8260c9eed836a042a5e7f6726bb2b411dffeaa712e19c388f23b" +dependencies = [ + "loom", +] + +[[package]] +name = "string_cache" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "213494b7a2b503146286049378ce02b482200519accc31872ee8be91fa820a08" +dependencies = [ + "new_debug_unreachable", + "once_cell", + "parking_lot", + "phf_shared 0.10.0", + "precomputed-hash", + "serde", +] + +[[package]] +name = "string_cache_codegen" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988" +dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", + "proc-macro2", + "quote", +] + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "syn" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "synstructure" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "unicode-xid", +] + +[[package]] +name = "system-deps" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18db855554db7bd0e73e06cf7ba3df39f97812cb11d3f75e71c39bf45171797e" +dependencies = [ + "cfg-expr 0.9.1", + "heck 0.3.3", + "pkg-config", + "toml", + "version-compare 0.0.11", +] + +[[package]] +name = "system-deps" +version = "6.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2955b1fe31e1fa2fbd1976b71cc69a606d7d4da16f6de3333d0c92d51419aeff" +dependencies = [ + "cfg-expr 0.11.0", + "heck 0.4.1", + "pkg-config", + "toml", + "version-compare 0.1.1", +] + +[[package]] +name = "tao" +version = "0.15.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac8e6399427c8494f9849b58694754d7cc741293348a6836b6c8d2c5aa82d8e6" +dependencies = [ + "bitflags", + "cairo-rs", + "cc", + "cocoa", + "core-foundation", + "core-graphics", + "crossbeam-channel", + "dirs-next", + "dispatch", + "gdk", + "gdk-pixbuf", + "gdk-sys", + "gdkx11-sys", + "gio", + "glib", + "glib-sys", + "gtk", + "image", + "instant", + "jni", + "lazy_static", + "libappindicator", + "libc", + "log", + "ndk", + "ndk-context", + "ndk-sys", + "objc", + "once_cell", + "parking_lot", + "paste", + "png", + "raw-window-handle", + "scopeguard", + "serde", + "unicode-segmentation", + "uuid 1.3.0", + "windows", + "windows-implement", + "x11-dl", +] + +[[package]] +name = "tar" +version = "0.4.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b55807c0344e1e6c04d7c965f5289c39a8d94ae23ed5c0b57aabac549f871c6" +dependencies = [ + "filetime", + "libc", + "xattr", +] + +[[package]] +name = "tauri" +version = "1.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe7e0f1d535e7cbbbab43c82be4fc992b84f9156c16c160955617e0260ebc449" +dependencies = [ + "anyhow", + "cocoa", + "dirs-next", + "embed_plist", + "encoding_rs", + "flate2", + "futures-util", + "glib", + "glob", + "gtk", + "heck 0.4.1", + "http", + "ignore", + "objc", + "once_cell", + "open", + "percent-encoding", + "rand 0.8.5", + "raw-window-handle", + "regex", + "semver 1.0.16", + "serde", + "serde_json", + "serde_repr", + "serialize-to-javascript", + "state", + "tar", + "tauri-macros", + "tauri-runtime", + "tauri-runtime-wry", + "tauri-utils", + "tempfile", + "thiserror", + "tokio", + "url", + "uuid 1.3.0", + "webkit2gtk", + "webview2-com", + "windows", +] + +[[package]] +name = "tauri-build" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8807c85d656b2b93927c19fe5a5f1f1f348f96c2de8b90763b3c2d561511f9b4" +dependencies = [ + "anyhow", + "cargo_toml", + "heck 0.4.1", + "json-patch", + "semver 1.0.16", + "serde_json", + "tauri-utils", + "winres", +] + +[[package]] +name = "tauri-codegen" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14388d484b6b1b5dc0f6a7d6cc6433b3b230bec85eaa576adcdf3f9fafa49251" +dependencies = [ + "base64", + "brotli", + "ico", + "json-patch", + "plist", + "png", + "proc-macro2", + "quote", + "regex", + "semver 1.0.16", + "serde", + "serde_json", + "sha2", + "tauri-utils", + "thiserror", + "time", + "uuid 1.3.0", + "walkdir", +] + +[[package]] +name = "tauri-macros" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "069319e5ecbe653a799b94b0690d9f9bf5d00f7b1d3989aa331c524d4e354075" +dependencies = [ + "heck 0.4.1", + "proc-macro2", + "quote", + "syn", + "tauri-codegen", + "tauri-utils", +] + +[[package]] +name = "tauri-runtime" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c507d954d08ac8705d235bc70ec6975b9054fb95ff7823af72dbb04186596f3b" +dependencies = [ + "gtk", + "http", + "http-range", + "rand 0.8.5", + "raw-window-handle", + "serde", + "serde_json", + "tauri-utils", + "thiserror", + "uuid 1.3.0", + "webview2-com", + "windows", +] + +[[package]] +name = "tauri-runtime-wry" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36b1c5764a41a13176a4599b5b7bd0881bea7d94dfe45e1e755f789b98317e30" +dependencies = [ + "cocoa", + "gtk", + "percent-encoding", + "rand 0.8.5", + "raw-window-handle", + "tauri-runtime", + "tauri-utils", + "uuid 1.3.0", + "webkit2gtk", + "webview2-com", + "windows", + "wry", +] + +[[package]] +name = "tauri-utils" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5abbc109a6eb45127956ffcc26ef0e875d160150ac16cfa45d26a6b2871686f1" +dependencies = [ + "brotli", + "ctor", + "glob", + "heck 0.4.1", + "html5ever", + "infer", + "json-patch", + "kuchiki", + "memchr", + "phf 0.10.1", + "proc-macro2", + "quote", + "semver 1.0.16", + "serde", + "serde_json", + "serde_with", + "thiserror", + "url", + "walkdir", + "windows", +] + +[[package]] +name = "tempfile" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" +dependencies = [ + "cfg-if", + "fastrand", + "libc", + "redox_syscall", + "remove_dir_all", + "winapi", +] + +[[package]] +name = "tendril" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d24a120c5fc464a3458240ee02c299ebcb9d67b5249c8848b09d639dca8d7bb0" +dependencies = [ + "futf", + "mac", + "utf-8", +] + +[[package]] +name = "thin-slice" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaa81235c7058867fa8c0e7314f33dcce9c215f535d1913822a2b3f5e289f3c" + +[[package]] +name = "thiserror" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "thread_local" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" +dependencies = [ + "once_cell", +] + +[[package]] +name = "time" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376" +dependencies = [ + "itoa 1.0.5", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" + +[[package]] +name = "time-macros" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d967f99f534ca7e495c575c62638eebc2898a8c84c119b89e250477bc4ba16b2" +dependencies = [ + "time-core", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +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 = "tokio" +version = "1.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8e00990ebabbe4c14c08aca901caed183ecd5c09562a12c824bb53d3c3fd3af" +dependencies = [ + "autocfg", + "bytes", + "memchr", + "num_cpus", + "pin-project-lite", + "windows-sys 0.42.0", +] + +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_datetime" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4553f467ac8e3d374bc9a177a26801e5d0f9b211aa1673fb137a403afd1c9cf5" + +[[package]] +name = "toml_edit" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56c59d8dd7d0dcbc6428bf7aa2f0e823e26e43b3c9aca15bbc9475d23e5fa12b" +dependencies = [ + "indexmap", + "nom8", + "toml_datetime", +] + +[[package]] +name = "tracing" +version = "0.1.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +dependencies = [ + "cfg-if", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" +dependencies = [ + "lazy_static", + "log", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6176eae26dd70d0c919749377897b54a9276bd7061339665dd68777926b5a70" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "treediff" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "761e8d5ad7ce14bb82b7e61ccc0ca961005a275a060b9644a2431aa11553c2ff" +dependencies = [ + "serde_json", +] + +[[package]] +name = "typenum" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" + +[[package]] +name = "ucd-trie" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81" + +[[package]] +name = "unicode-bidi" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d54675592c1dbefd78cbd98db9bacd89886e1ca50692a0692baefffdeb92dd58" + +[[package]] +name = "unicode-ident" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" + +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-segmentation" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" + +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + +[[package]] +name = "url" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + +[[package]] +name = "uuid" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" + +[[package]] +name = "uuid" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1674845326ee10d37ca60470760d4288a6f80f304007d92e5c53bab78c9cfd79" +dependencies = [ + "getrandom 0.2.8", +] + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "value-bag" +version = "1.0.0-alpha.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2209b78d1249f7e6f3293657c9779fe31ced465df091bbd433a1cf88e916ec55" +dependencies = [ + "ctor", + "version_check", +] + +[[package]] +name = "version-compare" +version = "0.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c18c859eead79d8b95d09e4678566e8d70105c4e7b251f707a03df32442661b" + +[[package]] +name = "version-compare" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "579a42fc0b8e0c63b76519a339be31bed574929511fa53c1a3acae26eb258f29" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "waker-fn" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" + +[[package]] +name = "walkdir" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" +dependencies = [ + "same-file", + "winapi", + "winapi-util", +] + +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" + +[[package]] +name = "web-sys" +version = "0.3.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webkit2gtk" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8f859735e4a452aeb28c6c56a852967a8a76c8eb1cc32dbf931ad28a13d6370" +dependencies = [ + "bitflags", + "cairo-rs", + "gdk", + "gdk-sys", + "gio", + "gio-sys", + "glib", + "glib-sys", + "gobject-sys", + "gtk", + "gtk-sys", + "javascriptcore-rs", + "libc", + "once_cell", + "soup2", + "webkit2gtk-sys", +] + +[[package]] +name = "webkit2gtk-sys" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d76ca6ecc47aeba01ec61e480139dda143796abcae6f83bcddf50d6b5b1dcf3" +dependencies = [ + "atk-sys", + "bitflags", + "cairo-sys-rs", + "gdk-pixbuf-sys", + "gdk-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "gtk-sys", + "javascriptcore-rs-sys", + "libc", + "pango-sys", + "pkg-config", + "soup2-sys", + "system-deps 6.0.3", +] + +[[package]] +name = "webview2-com" +version = "0.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4a769c9f1a64a8734bde70caafac2b96cada12cd4aefa49196b3a386b8b4178" +dependencies = [ + "webview2-com-macros", + "webview2-com-sys", + "windows", + "windows-implement", +] + +[[package]] +name = "webview2-com-macros" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaebe196c01691db62e9e4ca52c5ef1e4fd837dcae27dae3ada599b5a8fd05ac" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "webview2-com-sys" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aac48ef20ddf657755fdcda8dfed2a7b4fc7e4581acce6fe9b88c3d64f29dee7" +dependencies = [ + "regex", + "serde", + "serde_json", + "thiserror", + "windows", + "windows-bindgen", + "windows-metadata", +] + +[[package]] +name = "wepoll-ffi" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d743fdedc5c64377b5fc2bc036b01c7fd642205a0d96356034ae3404d49eb7fb" +dependencies = [ + "cc", +] + +[[package]] +name = "widestring" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "653f141f39ec16bba3c5abe400a0c60da7468261cc2cbf36805022876bc721a8" + +[[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.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[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 = "windows" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1c4bd0a50ac6020f65184721f758dba47bb9fbc2133df715ec74a237b26794a" +dependencies = [ + "windows-implement", + "windows_aarch64_msvc 0.39.0", + "windows_i686_gnu 0.39.0", + "windows_i686_msvc 0.39.0", + "windows_x86_64_gnu 0.39.0", + "windows_x86_64_msvc 0.39.0", +] + +[[package]] +name = "windows-bindgen" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68003dbd0e38abc0fb85b939240f4bce37c43a5981d3df37ccbaaa981b47cb41" +dependencies = [ + "windows-metadata", + "windows-tokens", +] + +[[package]] +name = "windows-implement" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba01f98f509cb5dc05f4e5fc95e535f78260f15fea8fe1a8abdd08f774f1cee7" +dependencies = [ + "syn", + "windows-tokens", +] + +[[package]] +name = "windows-metadata" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ee5e275231f07c6e240d14f34e1b635bf1faa1c76c57cfd59a5cdb9848e4278" + +[[package]] +name = "windows-service" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "917fdb865e7ff03af9dd86609f8767bc88fefba89e8efd569de8e208af8724b3" +dependencies = [ + "bitflags", + "err-derive", + "widestring", + "windows-sys 0.36.1", +] + +[[package]] +name = "windows-sys" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +dependencies = [ + "windows_aarch64_msvc 0.36.1", + "windows_i686_gnu 0.36.1", + "windows_i686_msvc 0.36.1", + "windows_x86_64_gnu 0.36.1", + "windows_x86_64_msvc 0.36.1", +] + +[[package]] +name = "windows-sys" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc 0.42.1", + "windows_i686_gnu 0.42.1", + "windows_i686_msvc 0.42.1", + "windows_x86_64_gnu 0.42.1", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc 0.42.1", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc 0.42.1", + "windows_i686_gnu 0.42.1", + "windows_i686_msvc 0.42.1", + "windows_x86_64_gnu 0.42.1", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc 0.42.1", +] + +[[package]] +name = "windows-tokens" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f838de2fe15fe6bac988e74b798f26499a8b21a9d97edec321e79b28d1d7f597" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec7711666096bd4096ffa835238905bb33fb87267910e154b18b44eaabb340f2" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" + +[[package]] +name = "windows_i686_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" + +[[package]] +name = "windows_i686_gnu" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "763fc57100a5f7042e3057e7e8d9bdd7860d330070251a73d003563a3bb49e1b" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" + +[[package]] +name = "windows_i686_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" + +[[package]] +name = "windows_i686_msvc" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bc7cbfe58828921e10a9f446fcaaf649204dcfe6c1ddd712c5eebae6bda1106" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6868c165637d653ae1e8dc4d82c25d4f97dd6605eaa8d784b5c6e0ab2a252b65" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e4d40883ae9cae962787ca76ba76390ffa29214667a111db9e0a1ad8377e809" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" + +[[package]] +name = "winres" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b68db261ef59e9e52806f688020631e987592bd83619edccda9c47d42cde4f6c" +dependencies = [ + "toml", +] + +[[package]] +name = "wry" +version = "0.23.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c1ad8e2424f554cc5bdebe8aa374ef5b433feff817aebabca0389961fc7ef98" +dependencies = [ + "base64", + "block", + "cocoa", + "core-graphics", + "crossbeam-channel", + "dunce", + "gdk", + "gio", + "glib", + "gtk", + "html5ever", + "http", + "kuchiki", + "libc", + "log", + "objc", + "objc_id", + "once_cell", + "serde", + "serde_json", + "sha2", + "soup2", + "tao", + "thiserror", + "url", + "webkit2gtk", + "webkit2gtk-sys", + "webview2-com", + "windows", + "windows-implement", +] + +[[package]] +name = "x11" +version = "2.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "502da5464ccd04011667b11c435cb992822c2c0dbde1770c988480d312a0db2e" +dependencies = [ + "libc", + "pkg-config", +] + +[[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 = "xattr" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d1526bbe5aaeb5eb06885f4d987bcdfa5e23187055de9b83fe00156a821fabc" +dependencies = [ + "libc", +] diff --git a/ui/Cargo.toml b/ui/Cargo.toml new file mode 100644 index 0000000..9cd47ac --- /dev/null +++ b/ui/Cargo.toml @@ -0,0 +1,31 @@ +[package] +name = "rustdesk_server" +version = "0.1.1" +description = "rustdesk server gui" +authors = ["elilchen"] +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[build-dependencies] +tauri-build = { version = "1.2", features = [] } +winres = "0.1" + +[dependencies] +async-std = { version = "1.12", features = ["attributes", "unstable"] } +crossbeam-channel = "0.5" +derive-new = "0.5" +notify = "5.1" +once_cell = "1.17" +serde_json = "1.0" +serde = { version = "1.0", features = ["derive"] } +tauri = { version = "1.2", features = ["fs-exists", "fs-read-dir", "fs-read-file", "fs-write-file", "path-all", "shell-open", "system-tray"] } +windows-service = "0.5.0" + +[features] +# by default Tauri runs in production mode +# when `tauri dev` runs it is executed with `cargo run --no-default-features` if `devPath` is an URL +default = ["custom-protocol"] +# this feature is used used for production builds where `devPath` points to the filesystem +# DO NOT remove this +custom-protocol = ["tauri/custom-protocol"] diff --git a/ui/build.rs b/ui/build.rs new file mode 100644 index 0000000..811b4a2 --- /dev/null +++ b/ui/build.rs @@ -0,0 +1,21 @@ +fn main() { + tauri_build::build(); + if cfg!(target_os = "windows") { + let mut res = winres::WindowsResource::new(); + res.set_icon("icons\\icon.ico"); + res.set_manifest( + r#" + + + + + + + + + +"#, + ); + res.compile().unwrap(); + } +} diff --git a/ui/html/editor/codemirror.css b/ui/html/editor/codemirror.css new file mode 100644 index 0000000..f4d5718 --- /dev/null +++ b/ui/html/editor/codemirror.css @@ -0,0 +1,344 @@ +/* BASICS */ + +.CodeMirror { + /* Set height, width, borders, and global font properties here */ + font-family: monospace; + height: 300px; + color: black; + direction: ltr; +} + +/* PADDING */ + +.CodeMirror-lines { + padding: 4px 0; /* Vertical padding around content */ +} +.CodeMirror pre.CodeMirror-line, +.CodeMirror pre.CodeMirror-line-like { + padding: 0 4px; /* Horizontal padding of content */ +} + +.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { + background-color: white; /* The little square between H and V scrollbars */ +} + +/* GUTTER */ + +.CodeMirror-gutters { + border-right: 1px solid #ddd; + background-color: #f7f7f7; + white-space: nowrap; +} +.CodeMirror-linenumbers {} +.CodeMirror-linenumber { + padding: 0 3px 0 5px; + min-width: 20px; + text-align: right; + color: #999; + white-space: nowrap; +} + +.CodeMirror-guttermarker { color: black; } +.CodeMirror-guttermarker-subtle { color: #999; } + +/* CURSOR */ + +.CodeMirror-cursor { + border-left: 1px solid black; + border-right: none; + width: 0; +} +/* Shown when moving in bi-directional text */ +.CodeMirror div.CodeMirror-secondarycursor { + border-left: 1px solid silver; +} +.cm-fat-cursor .CodeMirror-cursor { + width: auto; + border: 0 !important; + background: #7e7; +} +.cm-fat-cursor div.CodeMirror-cursors { + z-index: 1; +} +.cm-fat-cursor .CodeMirror-line::selection, +.cm-fat-cursor .CodeMirror-line > span::selection, +.cm-fat-cursor .CodeMirror-line > span > span::selection { background: transparent; } +.cm-fat-cursor .CodeMirror-line::-moz-selection, +.cm-fat-cursor .CodeMirror-line > span::-moz-selection, +.cm-fat-cursor .CodeMirror-line > span > span::-moz-selection { background: transparent; } +.cm-fat-cursor { caret-color: transparent; } +@-moz-keyframes blink { + 0% {} + 50% { background-color: transparent; } + 100% {} +} +@-webkit-keyframes blink { + 0% {} + 50% { background-color: transparent; } + 100% {} +} +@keyframes blink { + 0% {} + 50% { background-color: transparent; } + 100% {} +} + +/* Can style cursor different in overwrite (non-insert) mode */ +.CodeMirror-overwrite .CodeMirror-cursor {} + +.cm-tab { display: inline-block; text-decoration: inherit; } + +.CodeMirror-rulers { + position: absolute; + left: 0; right: 0; top: -50px; bottom: 0; + overflow: hidden; +} +.CodeMirror-ruler { + border-left: 1px solid #ccc; + top: 0; bottom: 0; + position: absolute; +} + +/* DEFAULT THEME */ + +.cm-s-default .cm-header {color: blue;} +.cm-s-default .cm-quote {color: #090;} +.cm-negative {color: #d44;} +.cm-positive {color: #292;} +.cm-header, .cm-strong {font-weight: bold;} +.cm-em {font-style: italic;} +.cm-link {text-decoration: underline;} +.cm-strikethrough {text-decoration: line-through;} + +.cm-s-default .cm-keyword {color: #708;} +.cm-s-default .cm-atom {color: #219;} +.cm-s-default .cm-number {color: #164;} +.cm-s-default .cm-def {color: #00f;} +.cm-s-default .cm-variable, +.cm-s-default .cm-punctuation, +.cm-s-default .cm-property, +.cm-s-default .cm-operator {} +.cm-s-default .cm-variable-2 {color: #05a;} +.cm-s-default .cm-variable-3, .cm-s-default .cm-type {color: #085;} +.cm-s-default .cm-comment {color: #a50;} +.cm-s-default .cm-string {color: #a11;} +.cm-s-default .cm-string-2 {color: #f50;} +.cm-s-default .cm-meta {color: #555;} +.cm-s-default .cm-qualifier {color: #555;} +.cm-s-default .cm-builtin {color: #30a;} +.cm-s-default .cm-bracket {color: #997;} +.cm-s-default .cm-tag {color: #170;} +.cm-s-default .cm-attribute {color: #00c;} +.cm-s-default .cm-hr {color: #999;} +.cm-s-default .cm-link {color: #00c;} + +.cm-s-default .cm-error {color: #f00;} +.cm-invalidchar {color: #f00;} + +.CodeMirror-composing { border-bottom: 2px solid; } + +/* Default styles for common addons */ + +div.CodeMirror span.CodeMirror-matchingbracket {color: #0b0;} +div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #a22;} +.CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); } +.CodeMirror-activeline-background {background: #e8f2ff;} + +/* STOP */ + +/* The rest of this file contains styles related to the mechanics of + the editor. You probably shouldn't touch them. */ + +.CodeMirror { + position: relative; + overflow: hidden; + background: white; +} + +.CodeMirror-scroll { + overflow: scroll !important; /* Things will break if this is overridden */ + /* 50px is the magic margin used to hide the element's real scrollbars */ + /* See overflow: hidden in .CodeMirror */ + margin-bottom: -50px; margin-right: -50px; + padding-bottom: 50px; + height: 100%; + outline: none; /* Prevent dragging from highlighting the element */ + position: relative; + z-index: 0; +} +.CodeMirror-sizer { + position: relative; + border-right: 50px solid transparent; +} + +/* The fake, visible scrollbars. Used to force redraw during scrolling + before actual scrolling happens, thus preventing shaking and + flickering artifacts. */ +.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { + position: absolute; + z-index: 6; + display: none; + outline: none; +} +.CodeMirror-vscrollbar { + right: 0; top: 0; + overflow-x: hidden; + overflow-y: scroll; +} +.CodeMirror-hscrollbar { + bottom: 0; left: 0; + overflow-y: hidden; + overflow-x: scroll; +} +.CodeMirror-scrollbar-filler { + right: 0; bottom: 0; +} +.CodeMirror-gutter-filler { + left: 0; bottom: 0; +} + +.CodeMirror-gutters { + position: absolute; left: 0; top: 0; + min-height: 100%; + z-index: 3; +} +.CodeMirror-gutter { + white-space: normal; + height: 100%; + display: inline-block; + vertical-align: top; + margin-bottom: -50px; +} +.CodeMirror-gutter-wrapper { + position: absolute; + z-index: 4; + background: none !important; + border: none !important; +} +.CodeMirror-gutter-background { + position: absolute; + top: 0; bottom: 0; + z-index: 4; +} +.CodeMirror-gutter-elt { + position: absolute; + cursor: default; + z-index: 4; +} +.CodeMirror-gutter-wrapper ::selection { background-color: transparent } +.CodeMirror-gutter-wrapper ::-moz-selection { background-color: transparent } + +.CodeMirror-lines { + cursor: text; + min-height: 1px; /* prevents collapsing before first draw */ +} +.CodeMirror pre.CodeMirror-line, +.CodeMirror pre.CodeMirror-line-like { + /* Reset some styles that the rest of the page might have set */ + -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0; + border-width: 0; + background: transparent; + font-family: inherit; + font-size: inherit; + margin: 0; + white-space: pre; + word-wrap: normal; + line-height: inherit; + color: inherit; + z-index: 2; + position: relative; + overflow: visible; + -webkit-tap-highlight-color: transparent; + -webkit-font-variant-ligatures: contextual; + font-variant-ligatures: contextual; +} +.CodeMirror-wrap pre.CodeMirror-line, +.CodeMirror-wrap pre.CodeMirror-line-like { + word-wrap: break-word; + white-space: pre-wrap; + word-break: normal; +} + +.CodeMirror-linebackground { + position: absolute; + left: 0; right: 0; top: 0; bottom: 0; + z-index: 0; +} + +.CodeMirror-linewidget { + position: relative; + z-index: 2; + padding: 0.1px; /* Force widget margins to stay inside of the container */ +} + +.CodeMirror-widget {} + +.CodeMirror-rtl pre { direction: rtl; } + +.CodeMirror-code { + outline: none; +} + +/* Force content-box sizing for the elements where we expect it */ +.CodeMirror-scroll, +.CodeMirror-sizer, +.CodeMirror-gutter, +.CodeMirror-gutters, +.CodeMirror-linenumber { + -moz-box-sizing: content-box; + box-sizing: content-box; +} + +.CodeMirror-measure { + position: absolute; + width: 100%; + height: 0; + overflow: hidden; + visibility: hidden; +} + +.CodeMirror-cursor { + position: absolute; + pointer-events: none; +} +.CodeMirror-measure pre { position: static; } + +div.CodeMirror-cursors { + visibility: hidden; + position: relative; + z-index: 3; +} +div.CodeMirror-dragcursors { + visibility: visible; +} + +.CodeMirror-focused div.CodeMirror-cursors { + visibility: visible; +} + +.CodeMirror-selected { background: #d9d9d9; } +.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; } +.CodeMirror-crosshair { cursor: crosshair; } +.CodeMirror-line::selection, .CodeMirror-line > span::selection, .CodeMirror-line > span > span::selection { background: #d7d4f0; } +.CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0; } + +.cm-searching { + background-color: #ffa; + background-color: rgba(255, 255, 0, .4); +} + +/* Used to force a border model for a node */ +.cm-force-border { padding-right: .1px; } + +@media print { + /* Hide the cursor when printing */ + .CodeMirror div.CodeMirror-cursors { + visibility: hidden; + } +} + +/* See issue #2901 */ +.cm-tab-wrap-hack:after { content: ''; } + +/* Help users use markselection to safely style text background */ +span.CodeMirror-selectedtext { background: none; } diff --git a/ui/html/editor/codemirror.js b/ui/html/editor/codemirror.js new file mode 100644 index 0000000..b434882 --- /dev/null +++ b/ui/html/editor/codemirror.js @@ -0,0 +1,9874 @@ +// CodeMirror, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: https://codemirror.net/5/LICENSE + +// This is CodeMirror (https://codemirror.net/5), a code editor +// implemented in JavaScript on top of the browser's DOM. +// +// You can find some technical background for some of the code below +// at http://marijnhaverbeke.nl/blog/#cm-internals . + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, global.CodeMirror = factory()); +}(this, (function () { 'use strict'; + + // Kludges for bugs and behavior differences that can't be feature + // detected are enabled based on userAgent etc sniffing. + var userAgent = navigator.userAgent; + var platform = navigator.platform; + + var gecko = /gecko\/\d/i.test(userAgent); + var ie_upto10 = /MSIE \d/.test(userAgent); + var ie_11up = /Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(userAgent); + var edge = /Edge\/(\d+)/.exec(userAgent); + var ie = ie_upto10 || ie_11up || edge; + var ie_version = ie && (ie_upto10 ? document.documentMode || 6 : +(edge || ie_11up)[1]); + var webkit = !edge && /WebKit\//.test(userAgent); + var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(userAgent); + var chrome = !edge && /Chrome\/(\d+)/.exec(userAgent); + var chrome_version = chrome && +chrome[1]; + var presto = /Opera\//.test(userAgent); + var safari = /Apple Computer/.test(navigator.vendor); + var mac_geMountainLion = /Mac OS X 1\d\D([8-9]|\d\d)\D/.test(userAgent); + var phantom = /PhantomJS/.test(userAgent); + + var ios = safari && (/Mobile\/\w+/.test(userAgent) || navigator.maxTouchPoints > 2); + var android = /Android/.test(userAgent); + // This is woefully incomplete. Suggestions for alternative methods welcome. + var mobile = ios || android || /webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(userAgent); + var mac = ios || /Mac/.test(platform); + var chromeOS = /\bCrOS\b/.test(userAgent); + var windows = /win/i.test(platform); + + var presto_version = presto && userAgent.match(/Version\/(\d*\.\d*)/); + if (presto_version) { presto_version = Number(presto_version[1]); } + if (presto_version && presto_version >= 15) { presto = false; webkit = true; } + // Some browsers use the wrong event properties to signal cmd/ctrl on OS X + var flipCtrlCmd = mac && (qtwebkit || presto && (presto_version == null || presto_version < 12.11)); + var captureRightClick = gecko || (ie && ie_version >= 9); + + function classTest(cls) { return new RegExp("(^|\\s)" + cls + "(?:$|\\s)\\s*") } + + var rmClass = function(node, cls) { + var current = node.className; + var match = classTest(cls).exec(current); + if (match) { + var after = current.slice(match.index + match[0].length); + node.className = current.slice(0, match.index) + (after ? match[1] + after : ""); + } + }; + + function removeChildren(e) { + for (var count = e.childNodes.length; count > 0; --count) + { e.removeChild(e.firstChild); } + return e + } + + function removeChildrenAndAdd(parent, e) { + return removeChildren(parent).appendChild(e) + } + + function elt(tag, content, className, style) { + var e = document.createElement(tag); + if (className) { e.className = className; } + if (style) { e.style.cssText = style; } + if (typeof content == "string") { e.appendChild(document.createTextNode(content)); } + else if (content) { for (var i = 0; i < content.length; ++i) { e.appendChild(content[i]); } } + return e + } + // wrapper for elt, which removes the elt from the accessibility tree + function eltP(tag, content, className, style) { + var e = elt(tag, content, className, style); + e.setAttribute("role", "presentation"); + return e + } + + var range; + if (document.createRange) { range = function(node, start, end, endNode) { + var r = document.createRange(); + r.setEnd(endNode || node, end); + r.setStart(node, start); + return r + }; } + else { range = function(node, start, end) { + var r = document.body.createTextRange(); + try { r.moveToElementText(node.parentNode); } + catch(e) { return r } + r.collapse(true); + r.moveEnd("character", end); + r.moveStart("character", start); + return r + }; } + + function contains(parent, child) { + if (child.nodeType == 3) // Android browser always returns false when child is a textnode + { child = child.parentNode; } + if (parent.contains) + { return parent.contains(child) } + do { + if (child.nodeType == 11) { child = child.host; } + if (child == parent) { return true } + } while (child = child.parentNode) + } + + function activeElt(doc) { + // IE and Edge may throw an "Unspecified Error" when accessing document.activeElement. + // IE < 10 will throw when accessed while the page is loading or in an iframe. + // IE > 9 and Edge will throw when accessed in an iframe if document.body is unavailable. + var activeElement; + try { + activeElement = doc.activeElement; + } catch(e) { + activeElement = doc.body || null; + } + while (activeElement && activeElement.shadowRoot && activeElement.shadowRoot.activeElement) + { activeElement = activeElement.shadowRoot.activeElement; } + return activeElement + } + + function addClass(node, cls) { + var current = node.className; + if (!classTest(cls).test(current)) { node.className += (current ? " " : "") + cls; } + } + function joinClasses(a, b) { + var as = a.split(" "); + for (var i = 0; i < as.length; i++) + { if (as[i] && !classTest(as[i]).test(b)) { b += " " + as[i]; } } + return b + } + + var selectInput = function(node) { node.select(); }; + if (ios) // Mobile Safari apparently has a bug where select() is broken. + { selectInput = function(node) { node.selectionStart = 0; node.selectionEnd = node.value.length; }; } + else if (ie) // Suppress mysterious IE10 errors + { selectInput = function(node) { try { node.select(); } catch(_e) {} }; } + + function doc(cm) { return cm.display.wrapper.ownerDocument } + + function win(cm) { return doc(cm).defaultView } + + function bind(f) { + var args = Array.prototype.slice.call(arguments, 1); + return function(){return f.apply(null, args)} + } + + function copyObj(obj, target, overwrite) { + if (!target) { target = {}; } + for (var prop in obj) + { if (obj.hasOwnProperty(prop) && (overwrite !== false || !target.hasOwnProperty(prop))) + { target[prop] = obj[prop]; } } + return target + } + + // Counts the column offset in a string, taking tabs into account. + // Used mostly to find indentation. + function countColumn(string, end, tabSize, startIndex, startValue) { + if (end == null) { + end = string.search(/[^\s\u00a0]/); + if (end == -1) { end = string.length; } + } + for (var i = startIndex || 0, n = startValue || 0;;) { + var nextTab = string.indexOf("\t", i); + if (nextTab < 0 || nextTab >= end) + { return n + (end - i) } + n += nextTab - i; + n += tabSize - (n % tabSize); + i = nextTab + 1; + } + } + + var Delayed = function() { + this.id = null; + this.f = null; + this.time = 0; + this.handler = bind(this.onTimeout, this); + }; + Delayed.prototype.onTimeout = function (self) { + self.id = 0; + if (self.time <= +new Date) { + self.f(); + } else { + setTimeout(self.handler, self.time - +new Date); + } + }; + Delayed.prototype.set = function (ms, f) { + this.f = f; + var time = +new Date + ms; + if (!this.id || time < this.time) { + clearTimeout(this.id); + this.id = setTimeout(this.handler, ms); + this.time = time; + } + }; + + function indexOf(array, elt) { + for (var i = 0; i < array.length; ++i) + { if (array[i] == elt) { return i } } + return -1 + } + + // Number of pixels added to scroller and sizer to hide scrollbar + var scrollerGap = 50; + + // Returned or thrown by various protocols to signal 'I'm not + // handling this'. + var Pass = {toString: function(){return "CodeMirror.Pass"}}; + + // Reused option objects for setSelection & friends + var sel_dontScroll = {scroll: false}, sel_mouse = {origin: "*mouse"}, sel_move = {origin: "+move"}; + + // The inverse of countColumn -- find the offset that corresponds to + // a particular column. + function findColumn(string, goal, tabSize) { + for (var pos = 0, col = 0;;) { + var nextTab = string.indexOf("\t", pos); + if (nextTab == -1) { nextTab = string.length; } + var skipped = nextTab - pos; + if (nextTab == string.length || col + skipped >= goal) + { return pos + Math.min(skipped, goal - col) } + col += nextTab - pos; + col += tabSize - (col % tabSize); + pos = nextTab + 1; + if (col >= goal) { return pos } + } + } + + var spaceStrs = [""]; + function spaceStr(n) { + while (spaceStrs.length <= n) + { spaceStrs.push(lst(spaceStrs) + " "); } + return spaceStrs[n] + } + + function lst(arr) { return arr[arr.length-1] } + + function map(array, f) { + var out = []; + for (var i = 0; i < array.length; i++) { out[i] = f(array[i], i); } + return out + } + + function insertSorted(array, value, score) { + var pos = 0, priority = score(value); + while (pos < array.length && score(array[pos]) <= priority) { pos++; } + array.splice(pos, 0, value); + } + + function nothing() {} + + function createObj(base, props) { + var inst; + if (Object.create) { + inst = Object.create(base); + } else { + nothing.prototype = base; + inst = new nothing(); + } + if (props) { copyObj(props, inst); } + return inst + } + + var nonASCIISingleCaseWordChar = /[\u00df\u0587\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/; + function isWordCharBasic(ch) { + return /\w/.test(ch) || ch > "\x80" && + (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch)) + } + function isWordChar(ch, helper) { + if (!helper) { return isWordCharBasic(ch) } + if (helper.source.indexOf("\\w") > -1 && isWordCharBasic(ch)) { return true } + return helper.test(ch) + } + + function isEmpty(obj) { + for (var n in obj) { if (obj.hasOwnProperty(n) && obj[n]) { return false } } + return true + } + + // Extending unicode characters. A series of a non-extending char + + // any number of extending chars is treated as a single unit as far + // as editing and measuring is concerned. This is not fully correct, + // since some scripts/fonts/browsers also treat other configurations + // of code points as a group. + var extendingChars = /[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/; + function isExtendingChar(ch) { return ch.charCodeAt(0) >= 768 && extendingChars.test(ch) } + + // Returns a number from the range [`0`; `str.length`] unless `pos` is outside that range. + function skipExtendingChars(str, pos, dir) { + while ((dir < 0 ? pos > 0 : pos < str.length) && isExtendingChar(str.charAt(pos))) { pos += dir; } + return pos + } + + // Returns the value from the range [`from`; `to`] that satisfies + // `pred` and is closest to `from`. Assumes that at least `to` + // satisfies `pred`. Supports `from` being greater than `to`. + function findFirst(pred, from, to) { + // At any point we are certain `to` satisfies `pred`, don't know + // whether `from` does. + var dir = from > to ? -1 : 1; + for (;;) { + if (from == to) { return from } + var midF = (from + to) / 2, mid = dir < 0 ? Math.ceil(midF) : Math.floor(midF); + if (mid == from) { return pred(mid) ? from : to } + if (pred(mid)) { to = mid; } + else { from = mid + dir; } + } + } + + // BIDI HELPERS + + function iterateBidiSections(order, from, to, f) { + if (!order) { return f(from, to, "ltr", 0) } + var found = false; + for (var i = 0; i < order.length; ++i) { + var part = order[i]; + if (part.from < to && part.to > from || from == to && part.to == from) { + f(Math.max(part.from, from), Math.min(part.to, to), part.level == 1 ? "rtl" : "ltr", i); + found = true; + } + } + if (!found) { f(from, to, "ltr"); } + } + + var bidiOther = null; + function getBidiPartAt(order, ch, sticky) { + var found; + bidiOther = null; + for (var i = 0; i < order.length; ++i) { + var cur = order[i]; + if (cur.from < ch && cur.to > ch) { return i } + if (cur.to == ch) { + if (cur.from != cur.to && sticky == "before") { found = i; } + else { bidiOther = i; } + } + if (cur.from == ch) { + if (cur.from != cur.to && sticky != "before") { found = i; } + else { bidiOther = i; } + } + } + return found != null ? found : bidiOther + } + + // Bidirectional ordering algorithm + // See http://unicode.org/reports/tr9/tr9-13.html for the algorithm + // that this (partially) implements. + + // One-char codes used for character types: + // L (L): Left-to-Right + // R (R): Right-to-Left + // r (AL): Right-to-Left Arabic + // 1 (EN): European Number + // + (ES): European Number Separator + // % (ET): European Number Terminator + // n (AN): Arabic Number + // , (CS): Common Number Separator + // m (NSM): Non-Spacing Mark + // b (BN): Boundary Neutral + // s (B): Paragraph Separator + // t (S): Segment Separator + // w (WS): Whitespace + // N (ON): Other Neutrals + + // Returns null if characters are ordered as they appear + // (left-to-right), or an array of sections ({from, to, level} + // objects) in the order in which they occur visually. + var bidiOrdering = (function() { + // Character types for codepoints 0 to 0xff + var lowTypes = "bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN"; + // Character types for codepoints 0x600 to 0x6f9 + var arabicTypes = "nnnnnnNNr%%r,rNNmmmmmmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmmmnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmnNmmmmmmrrmmNmmmmrr1111111111"; + function charType(code) { + if (code <= 0xf7) { return lowTypes.charAt(code) } + else if (0x590 <= code && code <= 0x5f4) { return "R" } + else if (0x600 <= code && code <= 0x6f9) { return arabicTypes.charAt(code - 0x600) } + else if (0x6ee <= code && code <= 0x8ac) { return "r" } + else if (0x2000 <= code && code <= 0x200b) { return "w" } + else if (code == 0x200c) { return "b" } + else { return "L" } + } + + var bidiRE = /[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/; + var isNeutral = /[stwN]/, isStrong = /[LRr]/, countsAsLeft = /[Lb1n]/, countsAsNum = /[1n]/; + + function BidiSpan(level, from, to) { + this.level = level; + this.from = from; this.to = to; + } + + return function(str, direction) { + var outerType = direction == "ltr" ? "L" : "R"; + + if (str.length == 0 || direction == "ltr" && !bidiRE.test(str)) { return false } + var len = str.length, types = []; + for (var i = 0; i < len; ++i) + { types.push(charType(str.charCodeAt(i))); } + + // W1. Examine each non-spacing mark (NSM) in the level run, and + // change the type of the NSM to the type of the previous + // character. If the NSM is at the start of the level run, it will + // get the type of sor. + for (var i$1 = 0, prev = outerType; i$1 < len; ++i$1) { + var type = types[i$1]; + if (type == "m") { types[i$1] = prev; } + else { prev = type; } + } + + // W2. Search backwards from each instance of a European number + // until the first strong type (R, L, AL, or sor) is found. If an + // AL is found, change the type of the European number to Arabic + // number. + // W3. Change all ALs to R. + for (var i$2 = 0, cur = outerType; i$2 < len; ++i$2) { + var type$1 = types[i$2]; + if (type$1 == "1" && cur == "r") { types[i$2] = "n"; } + else if (isStrong.test(type$1)) { cur = type$1; if (type$1 == "r") { types[i$2] = "R"; } } + } + + // W4. A single European separator between two European numbers + // changes to a European number. A single common separator between + // two numbers of the same type changes to that type. + for (var i$3 = 1, prev$1 = types[0]; i$3 < len - 1; ++i$3) { + var type$2 = types[i$3]; + if (type$2 == "+" && prev$1 == "1" && types[i$3+1] == "1") { types[i$3] = "1"; } + else if (type$2 == "," && prev$1 == types[i$3+1] && + (prev$1 == "1" || prev$1 == "n")) { types[i$3] = prev$1; } + prev$1 = type$2; + } + + // W5. A sequence of European terminators adjacent to European + // numbers changes to all European numbers. + // W6. Otherwise, separators and terminators change to Other + // Neutral. + for (var i$4 = 0; i$4 < len; ++i$4) { + var type$3 = types[i$4]; + if (type$3 == ",") { types[i$4] = "N"; } + else if (type$3 == "%") { + var end = (void 0); + for (end = i$4 + 1; end < len && types[end] == "%"; ++end) {} + var replace = (i$4 && types[i$4-1] == "!") || (end < len && types[end] == "1") ? "1" : "N"; + for (var j = i$4; j < end; ++j) { types[j] = replace; } + i$4 = end - 1; + } + } + + // W7. Search backwards from each instance of a European number + // until the first strong type (R, L, or sor) is found. If an L is + // found, then change the type of the European number to L. + for (var i$5 = 0, cur$1 = outerType; i$5 < len; ++i$5) { + var type$4 = types[i$5]; + if (cur$1 == "L" && type$4 == "1") { types[i$5] = "L"; } + else if (isStrong.test(type$4)) { cur$1 = type$4; } + } + + // N1. A sequence of neutrals takes the direction of the + // surrounding strong text if the text on both sides has the same + // direction. European and Arabic numbers act as if they were R in + // terms of their influence on neutrals. Start-of-level-run (sor) + // and end-of-level-run (eor) are used at level run boundaries. + // N2. Any remaining neutrals take the embedding direction. + for (var i$6 = 0; i$6 < len; ++i$6) { + if (isNeutral.test(types[i$6])) { + var end$1 = (void 0); + for (end$1 = i$6 + 1; end$1 < len && isNeutral.test(types[end$1]); ++end$1) {} + var before = (i$6 ? types[i$6-1] : outerType) == "L"; + var after = (end$1 < len ? types[end$1] : outerType) == "L"; + var replace$1 = before == after ? (before ? "L" : "R") : outerType; + for (var j$1 = i$6; j$1 < end$1; ++j$1) { types[j$1] = replace$1; } + i$6 = end$1 - 1; + } + } + + // Here we depart from the documented algorithm, in order to avoid + // building up an actual levels array. Since there are only three + // levels (0, 1, 2) in an implementation that doesn't take + // explicit embedding into account, we can build up the order on + // the fly, without following the level-based algorithm. + var order = [], m; + for (var i$7 = 0; i$7 < len;) { + if (countsAsLeft.test(types[i$7])) { + var start = i$7; + for (++i$7; i$7 < len && countsAsLeft.test(types[i$7]); ++i$7) {} + order.push(new BidiSpan(0, start, i$7)); + } else { + var pos = i$7, at = order.length, isRTL = direction == "rtl" ? 1 : 0; + for (++i$7; i$7 < len && types[i$7] != "L"; ++i$7) {} + for (var j$2 = pos; j$2 < i$7;) { + if (countsAsNum.test(types[j$2])) { + if (pos < j$2) { order.splice(at, 0, new BidiSpan(1, pos, j$2)); at += isRTL; } + var nstart = j$2; + for (++j$2; j$2 < i$7 && countsAsNum.test(types[j$2]); ++j$2) {} + order.splice(at, 0, new BidiSpan(2, nstart, j$2)); + at += isRTL; + pos = j$2; + } else { ++j$2; } + } + if (pos < i$7) { order.splice(at, 0, new BidiSpan(1, pos, i$7)); } + } + } + if (direction == "ltr") { + if (order[0].level == 1 && (m = str.match(/^\s+/))) { + order[0].from = m[0].length; + order.unshift(new BidiSpan(0, 0, m[0].length)); + } + if (lst(order).level == 1 && (m = str.match(/\s+$/))) { + lst(order).to -= m[0].length; + order.push(new BidiSpan(0, len - m[0].length, len)); + } + } + + return direction == "rtl" ? order.reverse() : order + } + })(); + + // Get the bidi ordering for the given line (and cache it). Returns + // false for lines that are fully left-to-right, and an array of + // BidiSpan objects otherwise. + function getOrder(line, direction) { + var order = line.order; + if (order == null) { order = line.order = bidiOrdering(line.text, direction); } + return order + } + + // EVENT HANDLING + + // Lightweight event framework. on/off also work on DOM nodes, + // registering native DOM handlers. + + var noHandlers = []; + + var on = function(emitter, type, f) { + if (emitter.addEventListener) { + emitter.addEventListener(type, f, false); + } else if (emitter.attachEvent) { + emitter.attachEvent("on" + type, f); + } else { + var map = emitter._handlers || (emitter._handlers = {}); + map[type] = (map[type] || noHandlers).concat(f); + } + }; + + function getHandlers(emitter, type) { + return emitter._handlers && emitter._handlers[type] || noHandlers + } + + function off(emitter, type, f) { + if (emitter.removeEventListener) { + emitter.removeEventListener(type, f, false); + } else if (emitter.detachEvent) { + emitter.detachEvent("on" + type, f); + } else { + var map = emitter._handlers, arr = map && map[type]; + if (arr) { + var index = indexOf(arr, f); + if (index > -1) + { map[type] = arr.slice(0, index).concat(arr.slice(index + 1)); } + } + } + } + + function signal(emitter, type /*, values...*/) { + var handlers = getHandlers(emitter, type); + if (!handlers.length) { return } + var args = Array.prototype.slice.call(arguments, 2); + for (var i = 0; i < handlers.length; ++i) { handlers[i].apply(null, args); } + } + + // The DOM events that CodeMirror handles can be overridden by + // registering a (non-DOM) handler on the editor for the event name, + // and preventDefault-ing the event in that handler. + function signalDOMEvent(cm, e, override) { + if (typeof e == "string") + { e = {type: e, preventDefault: function() { this.defaultPrevented = true; }}; } + signal(cm, override || e.type, cm, e); + return e_defaultPrevented(e) || e.codemirrorIgnore + } + + function signalCursorActivity(cm) { + var arr = cm._handlers && cm._handlers.cursorActivity; + if (!arr) { return } + var set = cm.curOp.cursorActivityHandlers || (cm.curOp.cursorActivityHandlers = []); + for (var i = 0; i < arr.length; ++i) { if (indexOf(set, arr[i]) == -1) + { set.push(arr[i]); } } + } + + function hasHandler(emitter, type) { + return getHandlers(emitter, type).length > 0 + } + + // Add on and off methods to a constructor's prototype, to make + // registering events on such objects more convenient. + function eventMixin(ctor) { + ctor.prototype.on = function(type, f) {on(this, type, f);}; + ctor.prototype.off = function(type, f) {off(this, type, f);}; + } + + // Due to the fact that we still support jurassic IE versions, some + // compatibility wrappers are needed. + + function e_preventDefault(e) { + if (e.preventDefault) { e.preventDefault(); } + else { e.returnValue = false; } + } + function e_stopPropagation(e) { + if (e.stopPropagation) { e.stopPropagation(); } + else { e.cancelBubble = true; } + } + function e_defaultPrevented(e) { + return e.defaultPrevented != null ? e.defaultPrevented : e.returnValue == false + } + function e_stop(e) {e_preventDefault(e); e_stopPropagation(e);} + + function e_target(e) {return e.target || e.srcElement} + function e_button(e) { + var b = e.which; + if (b == null) { + if (e.button & 1) { b = 1; } + else if (e.button & 2) { b = 3; } + else if (e.button & 4) { b = 2; } + } + if (mac && e.ctrlKey && b == 1) { b = 3; } + return b + } + + // Detect drag-and-drop + var dragAndDrop = function() { + // There is *some* kind of drag-and-drop support in IE6-8, but I + // couldn't get it to work yet. + if (ie && ie_version < 9) { return false } + var div = elt('div'); + return "draggable" in div || "dragDrop" in div + }(); + + var zwspSupported; + function zeroWidthElement(measure) { + if (zwspSupported == null) { + var test = elt("span", "\u200b"); + removeChildrenAndAdd(measure, elt("span", [test, document.createTextNode("x")])); + if (measure.firstChild.offsetHeight != 0) + { zwspSupported = test.offsetWidth <= 1 && test.offsetHeight > 2 && !(ie && ie_version < 8); } + } + var node = zwspSupported ? elt("span", "\u200b") : + elt("span", "\u00a0", null, "display: inline-block; width: 1px; margin-right: -1px"); + node.setAttribute("cm-text", ""); + return node + } + + // Feature-detect IE's crummy client rect reporting for bidi text + var badBidiRects; + function hasBadBidiRects(measure) { + if (badBidiRects != null) { return badBidiRects } + var txt = removeChildrenAndAdd(measure, document.createTextNode("A\u062eA")); + var r0 = range(txt, 0, 1).getBoundingClientRect(); + var r1 = range(txt, 1, 2).getBoundingClientRect(); + removeChildren(measure); + if (!r0 || r0.left == r0.right) { return false } // Safari returns null in some cases (#2780) + return badBidiRects = (r1.right - r0.right < 3) + } + + // See if "".split is the broken IE version, if so, provide an + // alternative way to split lines. + var splitLinesAuto = "\n\nb".split(/\n/).length != 3 ? function (string) { + var pos = 0, result = [], l = string.length; + while (pos <= l) { + var nl = string.indexOf("\n", pos); + if (nl == -1) { nl = string.length; } + var line = string.slice(pos, string.charAt(nl - 1) == "\r" ? nl - 1 : nl); + var rt = line.indexOf("\r"); + if (rt != -1) { + result.push(line.slice(0, rt)); + pos += rt + 1; + } else { + result.push(line); + pos = nl + 1; + } + } + return result + } : function (string) { return string.split(/\r\n?|\n/); }; + + var hasSelection = window.getSelection ? function (te) { + try { return te.selectionStart != te.selectionEnd } + catch(e) { return false } + } : function (te) { + var range; + try {range = te.ownerDocument.selection.createRange();} + catch(e) {} + if (!range || range.parentElement() != te) { return false } + return range.compareEndPoints("StartToEnd", range) != 0 + }; + + var hasCopyEvent = (function () { + var e = elt("div"); + if ("oncopy" in e) { return true } + e.setAttribute("oncopy", "return;"); + return typeof e.oncopy == "function" + })(); + + var badZoomedRects = null; + function hasBadZoomedRects(measure) { + if (badZoomedRects != null) { return badZoomedRects } + var node = removeChildrenAndAdd(measure, elt("span", "x")); + var normal = node.getBoundingClientRect(); + var fromRange = range(node, 0, 1).getBoundingClientRect(); + return badZoomedRects = Math.abs(normal.left - fromRange.left) > 1 + } + + // Known modes, by name and by MIME + var modes = {}, mimeModes = {}; + + // Extra arguments are stored as the mode's dependencies, which is + // used by (legacy) mechanisms like loadmode.js to automatically + // load a mode. (Preferred mechanism is the require/define calls.) + function defineMode(name, mode) { + if (arguments.length > 2) + { mode.dependencies = Array.prototype.slice.call(arguments, 2); } + modes[name] = mode; + } + + function defineMIME(mime, spec) { + mimeModes[mime] = spec; + } + + // Given a MIME type, a {name, ...options} config object, or a name + // string, return a mode config object. + function resolveMode(spec) { + if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) { + spec = mimeModes[spec]; + } else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) { + var found = mimeModes[spec.name]; + if (typeof found == "string") { found = {name: found}; } + spec = createObj(found, spec); + spec.name = found.name; + } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec)) { + return resolveMode("application/xml") + } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+json$/.test(spec)) { + return resolveMode("application/json") + } + if (typeof spec == "string") { return {name: spec} } + else { return spec || {name: "null"} } + } + + // Given a mode spec (anything that resolveMode accepts), find and + // initialize an actual mode object. + function getMode(options, spec) { + spec = resolveMode(spec); + var mfactory = modes[spec.name]; + if (!mfactory) { return getMode(options, "text/plain") } + var modeObj = mfactory(options, spec); + if (modeExtensions.hasOwnProperty(spec.name)) { + var exts = modeExtensions[spec.name]; + for (var prop in exts) { + if (!exts.hasOwnProperty(prop)) { continue } + if (modeObj.hasOwnProperty(prop)) { modeObj["_" + prop] = modeObj[prop]; } + modeObj[prop] = exts[prop]; + } + } + modeObj.name = spec.name; + if (spec.helperType) { modeObj.helperType = spec.helperType; } + if (spec.modeProps) { for (var prop$1 in spec.modeProps) + { modeObj[prop$1] = spec.modeProps[prop$1]; } } + + return modeObj + } + + // This can be used to attach properties to mode objects from + // outside the actual mode definition. + var modeExtensions = {}; + function extendMode(mode, properties) { + var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {}); + copyObj(properties, exts); + } + + function copyState(mode, state) { + if (state === true) { return state } + if (mode.copyState) { return mode.copyState(state) } + var nstate = {}; + for (var n in state) { + var val = state[n]; + if (val instanceof Array) { val = val.concat([]); } + nstate[n] = val; + } + return nstate + } + + // Given a mode and a state (for that mode), find the inner mode and + // state at the position that the state refers to. + function innerMode(mode, state) { + var info; + while (mode.innerMode) { + info = mode.innerMode(state); + if (!info || info.mode == mode) { break } + state = info.state; + mode = info.mode; + } + return info || {mode: mode, state: state} + } + + function startState(mode, a1, a2) { + return mode.startState ? mode.startState(a1, a2) : true + } + + // STRING STREAM + + // Fed to the mode parsers, provides helper functions to make + // parsers more succinct. + + var StringStream = function(string, tabSize, lineOracle) { + this.pos = this.start = 0; + this.string = string; + this.tabSize = tabSize || 8; + this.lastColumnPos = this.lastColumnValue = 0; + this.lineStart = 0; + this.lineOracle = lineOracle; + }; + + StringStream.prototype.eol = function () {return this.pos >= this.string.length}; + StringStream.prototype.sol = function () {return this.pos == this.lineStart}; + StringStream.prototype.peek = function () {return this.string.charAt(this.pos) || undefined}; + StringStream.prototype.next = function () { + if (this.pos < this.string.length) + { return this.string.charAt(this.pos++) } + }; + StringStream.prototype.eat = function (match) { + var ch = this.string.charAt(this.pos); + var ok; + if (typeof match == "string") { ok = ch == match; } + else { ok = ch && (match.test ? match.test(ch) : match(ch)); } + if (ok) {++this.pos; return ch} + }; + StringStream.prototype.eatWhile = function (match) { + var start = this.pos; + while (this.eat(match)){} + return this.pos > start + }; + StringStream.prototype.eatSpace = function () { + var start = this.pos; + while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) { ++this.pos; } + return this.pos > start + }; + StringStream.prototype.skipToEnd = function () {this.pos = this.string.length;}; + StringStream.prototype.skipTo = function (ch) { + var found = this.string.indexOf(ch, this.pos); + if (found > -1) {this.pos = found; return true} + }; + StringStream.prototype.backUp = function (n) {this.pos -= n;}; + StringStream.prototype.column = function () { + if (this.lastColumnPos < this.start) { + this.lastColumnValue = countColumn(this.string, this.start, this.tabSize, this.lastColumnPos, this.lastColumnValue); + this.lastColumnPos = this.start; + } + return this.lastColumnValue - (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0) + }; + StringStream.prototype.indentation = function () { + return countColumn(this.string, null, this.tabSize) - + (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0) + }; + StringStream.prototype.match = function (pattern, consume, caseInsensitive) { + if (typeof pattern == "string") { + var cased = function (str) { return caseInsensitive ? str.toLowerCase() : str; }; + var substr = this.string.substr(this.pos, pattern.length); + if (cased(substr) == cased(pattern)) { + if (consume !== false) { this.pos += pattern.length; } + return true + } + } else { + var match = this.string.slice(this.pos).match(pattern); + if (match && match.index > 0) { return null } + if (match && consume !== false) { this.pos += match[0].length; } + return match + } + }; + StringStream.prototype.current = function (){return this.string.slice(this.start, this.pos)}; + StringStream.prototype.hideFirstChars = function (n, inner) { + this.lineStart += n; + try { return inner() } + finally { this.lineStart -= n; } + }; + StringStream.prototype.lookAhead = function (n) { + var oracle = this.lineOracle; + return oracle && oracle.lookAhead(n) + }; + StringStream.prototype.baseToken = function () { + var oracle = this.lineOracle; + return oracle && oracle.baseToken(this.pos) + }; + + // Find the line object corresponding to the given line number. + function getLine(doc, n) { + n -= doc.first; + if (n < 0 || n >= doc.size) { throw new Error("There is no line " + (n + doc.first) + " in the document.") } + var chunk = doc; + while (!chunk.lines) { + for (var i = 0;; ++i) { + var child = chunk.children[i], sz = child.chunkSize(); + if (n < sz) { chunk = child; break } + n -= sz; + } + } + return chunk.lines[n] + } + + // Get the part of a document between two positions, as an array of + // strings. + function getBetween(doc, start, end) { + var out = [], n = start.line; + doc.iter(start.line, end.line + 1, function (line) { + var text = line.text; + if (n == end.line) { text = text.slice(0, end.ch); } + if (n == start.line) { text = text.slice(start.ch); } + out.push(text); + ++n; + }); + return out + } + // Get the lines between from and to, as array of strings. + function getLines(doc, from, to) { + var out = []; + doc.iter(from, to, function (line) { out.push(line.text); }); // iter aborts when callback returns truthy value + return out + } + + // Update the height of a line, propagating the height change + // upwards to parent nodes. + function updateLineHeight(line, height) { + var diff = height - line.height; + if (diff) { for (var n = line; n; n = n.parent) { n.height += diff; } } + } + + // Given a line object, find its line number by walking up through + // its parent links. + function lineNo(line) { + if (line.parent == null) { return null } + var cur = line.parent, no = indexOf(cur.lines, line); + for (var chunk = cur.parent; chunk; cur = chunk, chunk = chunk.parent) { + for (var i = 0;; ++i) { + if (chunk.children[i] == cur) { break } + no += chunk.children[i].chunkSize(); + } + } + return no + cur.first + } + + // Find the line at the given vertical position, using the height + // information in the document tree. + function lineAtHeight(chunk, h) { + var n = chunk.first; + outer: do { + for (var i$1 = 0; i$1 < chunk.children.length; ++i$1) { + var child = chunk.children[i$1], ch = child.height; + if (h < ch) { chunk = child; continue outer } + h -= ch; + n += child.chunkSize(); + } + return n + } while (!chunk.lines) + var i = 0; + for (; i < chunk.lines.length; ++i) { + var line = chunk.lines[i], lh = line.height; + if (h < lh) { break } + h -= lh; + } + return n + i + } + + function isLine(doc, l) {return l >= doc.first && l < doc.first + doc.size} + + function lineNumberFor(options, i) { + return String(options.lineNumberFormatter(i + options.firstLineNumber)) + } + + // A Pos instance represents a position within the text. + function Pos(line, ch, sticky) { + if ( sticky === void 0 ) sticky = null; + + if (!(this instanceof Pos)) { return new Pos(line, ch, sticky) } + this.line = line; + this.ch = ch; + this.sticky = sticky; + } + + // Compare two positions, return 0 if they are the same, a negative + // number when a is less, and a positive number otherwise. + function cmp(a, b) { return a.line - b.line || a.ch - b.ch } + + function equalCursorPos(a, b) { return a.sticky == b.sticky && cmp(a, b) == 0 } + + function copyPos(x) {return Pos(x.line, x.ch)} + function maxPos(a, b) { return cmp(a, b) < 0 ? b : a } + function minPos(a, b) { return cmp(a, b) < 0 ? a : b } + + // Most of the external API clips given positions to make sure they + // actually exist within the document. + function clipLine(doc, n) {return Math.max(doc.first, Math.min(n, doc.first + doc.size - 1))} + function clipPos(doc, pos) { + if (pos.line < doc.first) { return Pos(doc.first, 0) } + var last = doc.first + doc.size - 1; + if (pos.line > last) { return Pos(last, getLine(doc, last).text.length) } + return clipToLen(pos, getLine(doc, pos.line).text.length) + } + function clipToLen(pos, linelen) { + var ch = pos.ch; + if (ch == null || ch > linelen) { return Pos(pos.line, linelen) } + else if (ch < 0) { return Pos(pos.line, 0) } + else { return pos } + } + function clipPosArray(doc, array) { + var out = []; + for (var i = 0; i < array.length; i++) { out[i] = clipPos(doc, array[i]); } + return out + } + + var SavedContext = function(state, lookAhead) { + this.state = state; + this.lookAhead = lookAhead; + }; + + var Context = function(doc, state, line, lookAhead) { + this.state = state; + this.doc = doc; + this.line = line; + this.maxLookAhead = lookAhead || 0; + this.baseTokens = null; + this.baseTokenPos = 1; + }; + + Context.prototype.lookAhead = function (n) { + var line = this.doc.getLine(this.line + n); + if (line != null && n > this.maxLookAhead) { this.maxLookAhead = n; } + return line + }; + + Context.prototype.baseToken = function (n) { + if (!this.baseTokens) { return null } + while (this.baseTokens[this.baseTokenPos] <= n) + { this.baseTokenPos += 2; } + var type = this.baseTokens[this.baseTokenPos + 1]; + return {type: type && type.replace(/( |^)overlay .*/, ""), + size: this.baseTokens[this.baseTokenPos] - n} + }; + + Context.prototype.nextLine = function () { + this.line++; + if (this.maxLookAhead > 0) { this.maxLookAhead--; } + }; + + Context.fromSaved = function (doc, saved, line) { + if (saved instanceof SavedContext) + { return new Context(doc, copyState(doc.mode, saved.state), line, saved.lookAhead) } + else + { return new Context(doc, copyState(doc.mode, saved), line) } + }; + + Context.prototype.save = function (copy) { + var state = copy !== false ? copyState(this.doc.mode, this.state) : this.state; + return this.maxLookAhead > 0 ? new SavedContext(state, this.maxLookAhead) : state + }; + + + // Compute a style array (an array starting with a mode generation + // -- for invalidation -- followed by pairs of end positions and + // style strings), which is used to highlight the tokens on the + // line. + function highlightLine(cm, line, context, forceToEnd) { + // A styles array always starts with a number identifying the + // mode/overlays that it is based on (for easy invalidation). + var st = [cm.state.modeGen], lineClasses = {}; + // Compute the base array of styles + runMode(cm, line.text, cm.doc.mode, context, function (end, style) { return st.push(end, style); }, + lineClasses, forceToEnd); + var state = context.state; + + // Run overlays, adjust style array. + var loop = function ( o ) { + context.baseTokens = st; + var overlay = cm.state.overlays[o], i = 1, at = 0; + context.state = true; + runMode(cm, line.text, overlay.mode, context, function (end, style) { + var start = i; + // Ensure there's a token end at the current position, and that i points at it + while (at < end) { + var i_end = st[i]; + if (i_end > end) + { st.splice(i, 1, end, st[i+1], i_end); } + i += 2; + at = Math.min(end, i_end); + } + if (!style) { return } + if (overlay.opaque) { + st.splice(start, i - start, end, "overlay " + style); + i = start + 2; + } else { + for (; start < i; start += 2) { + var cur = st[start+1]; + st[start+1] = (cur ? cur + " " : "") + "overlay " + style; + } + } + }, lineClasses); + context.state = state; + context.baseTokens = null; + context.baseTokenPos = 1; + }; + + for (var o = 0; o < cm.state.overlays.length; ++o) loop( o ); + + return {styles: st, classes: lineClasses.bgClass || lineClasses.textClass ? lineClasses : null} + } + + function getLineStyles(cm, line, updateFrontier) { + if (!line.styles || line.styles[0] != cm.state.modeGen) { + var context = getContextBefore(cm, lineNo(line)); + var resetState = line.text.length > cm.options.maxHighlightLength && copyState(cm.doc.mode, context.state); + var result = highlightLine(cm, line, context); + if (resetState) { context.state = resetState; } + line.stateAfter = context.save(!resetState); + line.styles = result.styles; + if (result.classes) { line.styleClasses = result.classes; } + else if (line.styleClasses) { line.styleClasses = null; } + if (updateFrontier === cm.doc.highlightFrontier) + { cm.doc.modeFrontier = Math.max(cm.doc.modeFrontier, ++cm.doc.highlightFrontier); } + } + return line.styles + } + + function getContextBefore(cm, n, precise) { + var doc = cm.doc, display = cm.display; + if (!doc.mode.startState) { return new Context(doc, true, n) } + var start = findStartLine(cm, n, precise); + var saved = start > doc.first && getLine(doc, start - 1).stateAfter; + var context = saved ? Context.fromSaved(doc, saved, start) : new Context(doc, startState(doc.mode), start); + + doc.iter(start, n, function (line) { + processLine(cm, line.text, context); + var pos = context.line; + line.stateAfter = pos == n - 1 || pos % 5 == 0 || pos >= display.viewFrom && pos < display.viewTo ? context.save() : null; + context.nextLine(); + }); + if (precise) { doc.modeFrontier = context.line; } + return context + } + + // Lightweight form of highlight -- proceed over this line and + // update state, but don't save a style array. Used for lines that + // aren't currently visible. + function processLine(cm, text, context, startAt) { + var mode = cm.doc.mode; + var stream = new StringStream(text, cm.options.tabSize, context); + stream.start = stream.pos = startAt || 0; + if (text == "") { callBlankLine(mode, context.state); } + while (!stream.eol()) { + readToken(mode, stream, context.state); + stream.start = stream.pos; + } + } + + function callBlankLine(mode, state) { + if (mode.blankLine) { return mode.blankLine(state) } + if (!mode.innerMode) { return } + var inner = innerMode(mode, state); + if (inner.mode.blankLine) { return inner.mode.blankLine(inner.state) } + } + + function readToken(mode, stream, state, inner) { + for (var i = 0; i < 10; i++) { + if (inner) { inner[0] = innerMode(mode, state).mode; } + var style = mode.token(stream, state); + if (stream.pos > stream.start) { return style } + } + throw new Error("Mode " + mode.name + " failed to advance stream.") + } + + var Token = function(stream, type, state) { + this.start = stream.start; this.end = stream.pos; + this.string = stream.current(); + this.type = type || null; + this.state = state; + }; + + // Utility for getTokenAt and getLineTokens + function takeToken(cm, pos, precise, asArray) { + var doc = cm.doc, mode = doc.mode, style; + pos = clipPos(doc, pos); + var line = getLine(doc, pos.line), context = getContextBefore(cm, pos.line, precise); + var stream = new StringStream(line.text, cm.options.tabSize, context), tokens; + if (asArray) { tokens = []; } + while ((asArray || stream.pos < pos.ch) && !stream.eol()) { + stream.start = stream.pos; + style = readToken(mode, stream, context.state); + if (asArray) { tokens.push(new Token(stream, style, copyState(doc.mode, context.state))); } + } + return asArray ? tokens : new Token(stream, style, context.state) + } + + function extractLineClasses(type, output) { + if (type) { for (;;) { + var lineClass = type.match(/(?:^|\s+)line-(background-)?(\S+)/); + if (!lineClass) { break } + type = type.slice(0, lineClass.index) + type.slice(lineClass.index + lineClass[0].length); + var prop = lineClass[1] ? "bgClass" : "textClass"; + if (output[prop] == null) + { output[prop] = lineClass[2]; } + else if (!(new RegExp("(?:^|\\s)" + lineClass[2] + "(?:$|\\s)")).test(output[prop])) + { output[prop] += " " + lineClass[2]; } + } } + return type + } + + // Run the given mode's parser over a line, calling f for each token. + function runMode(cm, text, mode, context, f, lineClasses, forceToEnd) { + var flattenSpans = mode.flattenSpans; + if (flattenSpans == null) { flattenSpans = cm.options.flattenSpans; } + var curStart = 0, curStyle = null; + var stream = new StringStream(text, cm.options.tabSize, context), style; + var inner = cm.options.addModeClass && [null]; + if (text == "") { extractLineClasses(callBlankLine(mode, context.state), lineClasses); } + while (!stream.eol()) { + if (stream.pos > cm.options.maxHighlightLength) { + flattenSpans = false; + if (forceToEnd) { processLine(cm, text, context, stream.pos); } + stream.pos = text.length; + style = null; + } else { + style = extractLineClasses(readToken(mode, stream, context.state, inner), lineClasses); + } + if (inner) { + var mName = inner[0].name; + if (mName) { style = "m-" + (style ? mName + " " + style : mName); } + } + if (!flattenSpans || curStyle != style) { + while (curStart < stream.start) { + curStart = Math.min(stream.start, curStart + 5000); + f(curStart, curStyle); + } + curStyle = style; + } + stream.start = stream.pos; + } + while (curStart < stream.pos) { + // Webkit seems to refuse to render text nodes longer than 57444 + // characters, and returns inaccurate measurements in nodes + // starting around 5000 chars. + var pos = Math.min(stream.pos, curStart + 5000); + f(pos, curStyle); + curStart = pos; + } + } + + // Finds the line to start with when starting a parse. Tries to + // find a line with a stateAfter, so that it can start with a + // valid state. If that fails, it returns the line with the + // smallest indentation, which tends to need the least context to + // parse correctly. + function findStartLine(cm, n, precise) { + var minindent, minline, doc = cm.doc; + var lim = precise ? -1 : n - (cm.doc.mode.innerMode ? 1000 : 100); + for (var search = n; search > lim; --search) { + if (search <= doc.first) { return doc.first } + var line = getLine(doc, search - 1), after = line.stateAfter; + if (after && (!precise || search + (after instanceof SavedContext ? after.lookAhead : 0) <= doc.modeFrontier)) + { return search } + var indented = countColumn(line.text, null, cm.options.tabSize); + if (minline == null || minindent > indented) { + minline = search - 1; + minindent = indented; + } + } + return minline + } + + function retreatFrontier(doc, n) { + doc.modeFrontier = Math.min(doc.modeFrontier, n); + if (doc.highlightFrontier < n - 10) { return } + var start = doc.first; + for (var line = n - 1; line > start; line--) { + var saved = getLine(doc, line).stateAfter; + // change is on 3 + // state on line 1 looked ahead 2 -- so saw 3 + // test 1 + 2 < 3 should cover this + if (saved && (!(saved instanceof SavedContext) || line + saved.lookAhead < n)) { + start = line + 1; + break + } + } + doc.highlightFrontier = Math.min(doc.highlightFrontier, start); + } + + // Optimize some code when these features are not used. + var sawReadOnlySpans = false, sawCollapsedSpans = false; + + function seeReadOnlySpans() { + sawReadOnlySpans = true; + } + + function seeCollapsedSpans() { + sawCollapsedSpans = true; + } + + // TEXTMARKER SPANS + + function MarkedSpan(marker, from, to) { + this.marker = marker; + this.from = from; this.to = to; + } + + // Search an array of spans for a span matching the given marker. + function getMarkedSpanFor(spans, marker) { + if (spans) { for (var i = 0; i < spans.length; ++i) { + var span = spans[i]; + if (span.marker == marker) { return span } + } } + } + + // Remove a span from an array, returning undefined if no spans are + // left (we don't store arrays for lines without spans). + function removeMarkedSpan(spans, span) { + var r; + for (var i = 0; i < spans.length; ++i) + { if (spans[i] != span) { (r || (r = [])).push(spans[i]); } } + return r + } + + // Add a span to a line. + function addMarkedSpan(line, span, op) { + var inThisOp = op && window.WeakSet && (op.markedSpans || (op.markedSpans = new WeakSet)); + if (inThisOp && line.markedSpans && inThisOp.has(line.markedSpans)) { + line.markedSpans.push(span); + } else { + line.markedSpans = line.markedSpans ? line.markedSpans.concat([span]) : [span]; + if (inThisOp) { inThisOp.add(line.markedSpans); } + } + span.marker.attachLine(line); + } + + // Used for the algorithm that adjusts markers for a change in the + // document. These functions cut an array of spans at a given + // character position, returning an array of remaining chunks (or + // undefined if nothing remains). + function markedSpansBefore(old, startCh, isInsert) { + var nw; + if (old) { for (var i = 0; i < old.length; ++i) { + var span = old[i], marker = span.marker; + var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= startCh : span.from < startCh); + if (startsBefore || span.from == startCh && marker.type == "bookmark" && (!isInsert || !span.marker.insertLeft)) { + var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= startCh : span.to > startCh) + ;(nw || (nw = [])).push(new MarkedSpan(marker, span.from, endsAfter ? null : span.to)); + } + } } + return nw + } + function markedSpansAfter(old, endCh, isInsert) { + var nw; + if (old) { for (var i = 0; i < old.length; ++i) { + var span = old[i], marker = span.marker; + var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= endCh : span.to > endCh); + if (endsAfter || span.from == endCh && marker.type == "bookmark" && (!isInsert || span.marker.insertLeft)) { + var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= endCh : span.from < endCh) + ;(nw || (nw = [])).push(new MarkedSpan(marker, startsBefore ? null : span.from - endCh, + span.to == null ? null : span.to - endCh)); + } + } } + return nw + } + + // Given a change object, compute the new set of marker spans that + // cover the line in which the change took place. Removes spans + // entirely within the change, reconnects spans belonging to the + // same marker that appear on both sides of the change, and cuts off + // spans partially within the change. Returns an array of span + // arrays with one element for each line in (after) the change. + function stretchSpansOverChange(doc, change) { + if (change.full) { return null } + var oldFirst = isLine(doc, change.from.line) && getLine(doc, change.from.line).markedSpans; + var oldLast = isLine(doc, change.to.line) && getLine(doc, change.to.line).markedSpans; + if (!oldFirst && !oldLast) { return null } + + var startCh = change.from.ch, endCh = change.to.ch, isInsert = cmp(change.from, change.to) == 0; + // Get the spans that 'stick out' on both sides + var first = markedSpansBefore(oldFirst, startCh, isInsert); + var last = markedSpansAfter(oldLast, endCh, isInsert); + + // Next, merge those two ends + var sameLine = change.text.length == 1, offset = lst(change.text).length + (sameLine ? startCh : 0); + if (first) { + // Fix up .to properties of first + for (var i = 0; i < first.length; ++i) { + var span = first[i]; + if (span.to == null) { + var found = getMarkedSpanFor(last, span.marker); + if (!found) { span.to = startCh; } + else if (sameLine) { span.to = found.to == null ? null : found.to + offset; } + } + } + } + if (last) { + // Fix up .from in last (or move them into first in case of sameLine) + for (var i$1 = 0; i$1 < last.length; ++i$1) { + var span$1 = last[i$1]; + if (span$1.to != null) { span$1.to += offset; } + if (span$1.from == null) { + var found$1 = getMarkedSpanFor(first, span$1.marker); + if (!found$1) { + span$1.from = offset; + if (sameLine) { (first || (first = [])).push(span$1); } + } + } else { + span$1.from += offset; + if (sameLine) { (first || (first = [])).push(span$1); } + } + } + } + // Make sure we didn't create any zero-length spans + if (first) { first = clearEmptySpans(first); } + if (last && last != first) { last = clearEmptySpans(last); } + + var newMarkers = [first]; + if (!sameLine) { + // Fill gap with whole-line-spans + var gap = change.text.length - 2, gapMarkers; + if (gap > 0 && first) + { for (var i$2 = 0; i$2 < first.length; ++i$2) + { if (first[i$2].to == null) + { (gapMarkers || (gapMarkers = [])).push(new MarkedSpan(first[i$2].marker, null, null)); } } } + for (var i$3 = 0; i$3 < gap; ++i$3) + { newMarkers.push(gapMarkers); } + newMarkers.push(last); + } + return newMarkers + } + + // Remove spans that are empty and don't have a clearWhenEmpty + // option of false. + function clearEmptySpans(spans) { + for (var i = 0; i < spans.length; ++i) { + var span = spans[i]; + if (span.from != null && span.from == span.to && span.marker.clearWhenEmpty !== false) + { spans.splice(i--, 1); } + } + if (!spans.length) { return null } + return spans + } + + // Used to 'clip' out readOnly ranges when making a change. + function removeReadOnlyRanges(doc, from, to) { + var markers = null; + doc.iter(from.line, to.line + 1, function (line) { + if (line.markedSpans) { for (var i = 0; i < line.markedSpans.length; ++i) { + var mark = line.markedSpans[i].marker; + if (mark.readOnly && (!markers || indexOf(markers, mark) == -1)) + { (markers || (markers = [])).push(mark); } + } } + }); + if (!markers) { return null } + var parts = [{from: from, to: to}]; + for (var i = 0; i < markers.length; ++i) { + var mk = markers[i], m = mk.find(0); + for (var j = 0; j < parts.length; ++j) { + var p = parts[j]; + if (cmp(p.to, m.from) < 0 || cmp(p.from, m.to) > 0) { continue } + var newParts = [j, 1], dfrom = cmp(p.from, m.from), dto = cmp(p.to, m.to); + if (dfrom < 0 || !mk.inclusiveLeft && !dfrom) + { newParts.push({from: p.from, to: m.from}); } + if (dto > 0 || !mk.inclusiveRight && !dto) + { newParts.push({from: m.to, to: p.to}); } + parts.splice.apply(parts, newParts); + j += newParts.length - 3; + } + } + return parts + } + + // Connect or disconnect spans from a line. + function detachMarkedSpans(line) { + var spans = line.markedSpans; + if (!spans) { return } + for (var i = 0; i < spans.length; ++i) + { spans[i].marker.detachLine(line); } + line.markedSpans = null; + } + function attachMarkedSpans(line, spans) { + if (!spans) { return } + for (var i = 0; i < spans.length; ++i) + { spans[i].marker.attachLine(line); } + line.markedSpans = spans; + } + + // Helpers used when computing which overlapping collapsed span + // counts as the larger one. + function extraLeft(marker) { return marker.inclusiveLeft ? -1 : 0 } + function extraRight(marker) { return marker.inclusiveRight ? 1 : 0 } + + // Returns a number indicating which of two overlapping collapsed + // spans is larger (and thus includes the other). Falls back to + // comparing ids when the spans cover exactly the same range. + function compareCollapsedMarkers(a, b) { + var lenDiff = a.lines.length - b.lines.length; + if (lenDiff != 0) { return lenDiff } + var aPos = a.find(), bPos = b.find(); + var fromCmp = cmp(aPos.from, bPos.from) || extraLeft(a) - extraLeft(b); + if (fromCmp) { return -fromCmp } + var toCmp = cmp(aPos.to, bPos.to) || extraRight(a) - extraRight(b); + if (toCmp) { return toCmp } + return b.id - a.id + } + + // Find out whether a line ends or starts in a collapsed span. If + // so, return the marker for that span. + function collapsedSpanAtSide(line, start) { + var sps = sawCollapsedSpans && line.markedSpans, found; + if (sps) { for (var sp = (void 0), i = 0; i < sps.length; ++i) { + sp = sps[i]; + if (sp.marker.collapsed && (start ? sp.from : sp.to) == null && + (!found || compareCollapsedMarkers(found, sp.marker) < 0)) + { found = sp.marker; } + } } + return found + } + function collapsedSpanAtStart(line) { return collapsedSpanAtSide(line, true) } + function collapsedSpanAtEnd(line) { return collapsedSpanAtSide(line, false) } + + function collapsedSpanAround(line, ch) { + var sps = sawCollapsedSpans && line.markedSpans, found; + if (sps) { for (var i = 0; i < sps.length; ++i) { + var sp = sps[i]; + if (sp.marker.collapsed && (sp.from == null || sp.from < ch) && (sp.to == null || sp.to > ch) && + (!found || compareCollapsedMarkers(found, sp.marker) < 0)) { found = sp.marker; } + } } + return found + } + + // Test whether there exists a collapsed span that partially + // overlaps (covers the start or end, but not both) of a new span. + // Such overlap is not allowed. + function conflictingCollapsedRange(doc, lineNo, from, to, marker) { + var line = getLine(doc, lineNo); + var sps = sawCollapsedSpans && line.markedSpans; + if (sps) { for (var i = 0; i < sps.length; ++i) { + var sp = sps[i]; + if (!sp.marker.collapsed) { continue } + var found = sp.marker.find(0); + var fromCmp = cmp(found.from, from) || extraLeft(sp.marker) - extraLeft(marker); + var toCmp = cmp(found.to, to) || extraRight(sp.marker) - extraRight(marker); + if (fromCmp >= 0 && toCmp <= 0 || fromCmp <= 0 && toCmp >= 0) { continue } + if (fromCmp <= 0 && (sp.marker.inclusiveRight && marker.inclusiveLeft ? cmp(found.to, from) >= 0 : cmp(found.to, from) > 0) || + fromCmp >= 0 && (sp.marker.inclusiveRight && marker.inclusiveLeft ? cmp(found.from, to) <= 0 : cmp(found.from, to) < 0)) + { return true } + } } + } + + // A visual line is a line as drawn on the screen. Folding, for + // example, can cause multiple logical lines to appear on the same + // visual line. This finds the start of the visual line that the + // given line is part of (usually that is the line itself). + function visualLine(line) { + var merged; + while (merged = collapsedSpanAtStart(line)) + { line = merged.find(-1, true).line; } + return line + } + + function visualLineEnd(line) { + var merged; + while (merged = collapsedSpanAtEnd(line)) + { line = merged.find(1, true).line; } + return line + } + + // Returns an array of logical lines that continue the visual line + // started by the argument, or undefined if there are no such lines. + function visualLineContinued(line) { + var merged, lines; + while (merged = collapsedSpanAtEnd(line)) { + line = merged.find(1, true).line + ;(lines || (lines = [])).push(line); + } + return lines + } + + // Get the line number of the start of the visual line that the + // given line number is part of. + function visualLineNo(doc, lineN) { + var line = getLine(doc, lineN), vis = visualLine(line); + if (line == vis) { return lineN } + return lineNo(vis) + } + + // Get the line number of the start of the next visual line after + // the given line. + function visualLineEndNo(doc, lineN) { + if (lineN > doc.lastLine()) { return lineN } + var line = getLine(doc, lineN), merged; + if (!lineIsHidden(doc, line)) { return lineN } + while (merged = collapsedSpanAtEnd(line)) + { line = merged.find(1, true).line; } + return lineNo(line) + 1 + } + + // Compute whether a line is hidden. Lines count as hidden when they + // are part of a visual line that starts with another line, or when + // they are entirely covered by collapsed, non-widget span. + function lineIsHidden(doc, line) { + var sps = sawCollapsedSpans && line.markedSpans; + if (sps) { for (var sp = (void 0), i = 0; i < sps.length; ++i) { + sp = sps[i]; + if (!sp.marker.collapsed) { continue } + if (sp.from == null) { return true } + if (sp.marker.widgetNode) { continue } + if (sp.from == 0 && sp.marker.inclusiveLeft && lineIsHiddenInner(doc, line, sp)) + { return true } + } } + } + function lineIsHiddenInner(doc, line, span) { + if (span.to == null) { + var end = span.marker.find(1, true); + return lineIsHiddenInner(doc, end.line, getMarkedSpanFor(end.line.markedSpans, span.marker)) + } + if (span.marker.inclusiveRight && span.to == line.text.length) + { return true } + for (var sp = (void 0), i = 0; i < line.markedSpans.length; ++i) { + sp = line.markedSpans[i]; + if (sp.marker.collapsed && !sp.marker.widgetNode && sp.from == span.to && + (sp.to == null || sp.to != span.from) && + (sp.marker.inclusiveLeft || span.marker.inclusiveRight) && + lineIsHiddenInner(doc, line, sp)) { return true } + } + } + + // Find the height above the given line. + function heightAtLine(lineObj) { + lineObj = visualLine(lineObj); + + var h = 0, chunk = lineObj.parent; + for (var i = 0; i < chunk.lines.length; ++i) { + var line = chunk.lines[i]; + if (line == lineObj) { break } + else { h += line.height; } + } + for (var p = chunk.parent; p; chunk = p, p = chunk.parent) { + for (var i$1 = 0; i$1 < p.children.length; ++i$1) { + var cur = p.children[i$1]; + if (cur == chunk) { break } + else { h += cur.height; } + } + } + return h + } + + // Compute the character length of a line, taking into account + // collapsed ranges (see markText) that might hide parts, and join + // other lines onto it. + function lineLength(line) { + if (line.height == 0) { return 0 } + var len = line.text.length, merged, cur = line; + while (merged = collapsedSpanAtStart(cur)) { + var found = merged.find(0, true); + cur = found.from.line; + len += found.from.ch - found.to.ch; + } + cur = line; + while (merged = collapsedSpanAtEnd(cur)) { + var found$1 = merged.find(0, true); + len -= cur.text.length - found$1.from.ch; + cur = found$1.to.line; + len += cur.text.length - found$1.to.ch; + } + return len + } + + // Find the longest line in the document. + function findMaxLine(cm) { + var d = cm.display, doc = cm.doc; + d.maxLine = getLine(doc, doc.first); + d.maxLineLength = lineLength(d.maxLine); + d.maxLineChanged = true; + doc.iter(function (line) { + var len = lineLength(line); + if (len > d.maxLineLength) { + d.maxLineLength = len; + d.maxLine = line; + } + }); + } + + // LINE DATA STRUCTURE + + // Line objects. These hold state related to a line, including + // highlighting info (the styles array). + var Line = function(text, markedSpans, estimateHeight) { + this.text = text; + attachMarkedSpans(this, markedSpans); + this.height = estimateHeight ? estimateHeight(this) : 1; + }; + + Line.prototype.lineNo = function () { return lineNo(this) }; + eventMixin(Line); + + // Change the content (text, markers) of a line. Automatically + // invalidates cached information and tries to re-estimate the + // line's height. + function updateLine(line, text, markedSpans, estimateHeight) { + line.text = text; + if (line.stateAfter) { line.stateAfter = null; } + if (line.styles) { line.styles = null; } + if (line.order != null) { line.order = null; } + detachMarkedSpans(line); + attachMarkedSpans(line, markedSpans); + var estHeight = estimateHeight ? estimateHeight(line) : 1; + if (estHeight != line.height) { updateLineHeight(line, estHeight); } + } + + // Detach a line from the document tree and its markers. + function cleanUpLine(line) { + line.parent = null; + detachMarkedSpans(line); + } + + // Convert a style as returned by a mode (either null, or a string + // containing one or more styles) to a CSS style. This is cached, + // and also looks for line-wide styles. + var styleToClassCache = {}, styleToClassCacheWithMode = {}; + function interpretTokenStyle(style, options) { + if (!style || /^\s*$/.test(style)) { return null } + var cache = options.addModeClass ? styleToClassCacheWithMode : styleToClassCache; + return cache[style] || + (cache[style] = style.replace(/\S+/g, "cm-$&")) + } + + // Render the DOM representation of the text of a line. Also builds + // up a 'line map', which points at the DOM nodes that represent + // specific stretches of text, and is used by the measuring code. + // The returned object contains the DOM node, this map, and + // information about line-wide styles that were set by the mode. + function buildLineContent(cm, lineView) { + // The padding-right forces the element to have a 'border', which + // is needed on Webkit to be able to get line-level bounding + // rectangles for it (in measureChar). + var content = eltP("span", null, null, webkit ? "padding-right: .1px" : null); + var builder = {pre: eltP("pre", [content], "CodeMirror-line"), content: content, + col: 0, pos: 0, cm: cm, + trailingSpace: false, + splitSpaces: cm.getOption("lineWrapping")}; + lineView.measure = {}; + + // Iterate over the logical lines that make up this visual line. + for (var i = 0; i <= (lineView.rest ? lineView.rest.length : 0); i++) { + var line = i ? lineView.rest[i - 1] : lineView.line, order = (void 0); + builder.pos = 0; + builder.addToken = buildToken; + // Optionally wire in some hacks into the token-rendering + // algorithm, to deal with browser quirks. + if (hasBadBidiRects(cm.display.measure) && (order = getOrder(line, cm.doc.direction))) + { builder.addToken = buildTokenBadBidi(builder.addToken, order); } + builder.map = []; + var allowFrontierUpdate = lineView != cm.display.externalMeasured && lineNo(line); + insertLineContent(line, builder, getLineStyles(cm, line, allowFrontierUpdate)); + if (line.styleClasses) { + if (line.styleClasses.bgClass) + { builder.bgClass = joinClasses(line.styleClasses.bgClass, builder.bgClass || ""); } + if (line.styleClasses.textClass) + { builder.textClass = joinClasses(line.styleClasses.textClass, builder.textClass || ""); } + } + + // Ensure at least a single node is present, for measuring. + if (builder.map.length == 0) + { builder.map.push(0, 0, builder.content.appendChild(zeroWidthElement(cm.display.measure))); } + + // Store the map and a cache object for the current logical line + if (i == 0) { + lineView.measure.map = builder.map; + lineView.measure.cache = {}; + } else { + (lineView.measure.maps || (lineView.measure.maps = [])).push(builder.map) + ;(lineView.measure.caches || (lineView.measure.caches = [])).push({}); + } + } + + // See issue #2901 + if (webkit) { + var last = builder.content.lastChild; + if (/\bcm-tab\b/.test(last.className) || (last.querySelector && last.querySelector(".cm-tab"))) + { builder.content.className = "cm-tab-wrap-hack"; } + } + + signal(cm, "renderLine", cm, lineView.line, builder.pre); + if (builder.pre.className) + { builder.textClass = joinClasses(builder.pre.className, builder.textClass || ""); } + + return builder + } + + function defaultSpecialCharPlaceholder(ch) { + var token = elt("span", "\u2022", "cm-invalidchar"); + token.title = "\\u" + ch.charCodeAt(0).toString(16); + token.setAttribute("aria-label", token.title); + return token + } + + // Build up the DOM representation for a single token, and add it to + // the line map. Takes care to render special characters separately. + function buildToken(builder, text, style, startStyle, endStyle, css, attributes) { + if (!text) { return } + var displayText = builder.splitSpaces ? splitSpaces(text, builder.trailingSpace) : text; + var special = builder.cm.state.specialChars, mustWrap = false; + var content; + if (!special.test(text)) { + builder.col += text.length; + content = document.createTextNode(displayText); + builder.map.push(builder.pos, builder.pos + text.length, content); + if (ie && ie_version < 9) { mustWrap = true; } + builder.pos += text.length; + } else { + content = document.createDocumentFragment(); + var pos = 0; + while (true) { + special.lastIndex = pos; + var m = special.exec(text); + var skipped = m ? m.index - pos : text.length - pos; + if (skipped) { + var txt = document.createTextNode(displayText.slice(pos, pos + skipped)); + if (ie && ie_version < 9) { content.appendChild(elt("span", [txt])); } + else { content.appendChild(txt); } + builder.map.push(builder.pos, builder.pos + skipped, txt); + builder.col += skipped; + builder.pos += skipped; + } + if (!m) { break } + pos += skipped + 1; + var txt$1 = (void 0); + if (m[0] == "\t") { + var tabSize = builder.cm.options.tabSize, tabWidth = tabSize - builder.col % tabSize; + txt$1 = content.appendChild(elt("span", spaceStr(tabWidth), "cm-tab")); + txt$1.setAttribute("role", "presentation"); + txt$1.setAttribute("cm-text", "\t"); + builder.col += tabWidth; + } else if (m[0] == "\r" || m[0] == "\n") { + txt$1 = content.appendChild(elt("span", m[0] == "\r" ? "\u240d" : "\u2424", "cm-invalidchar")); + txt$1.setAttribute("cm-text", m[0]); + builder.col += 1; + } else { + txt$1 = builder.cm.options.specialCharPlaceholder(m[0]); + txt$1.setAttribute("cm-text", m[0]); + if (ie && ie_version < 9) { content.appendChild(elt("span", [txt$1])); } + else { content.appendChild(txt$1); } + builder.col += 1; + } + builder.map.push(builder.pos, builder.pos + 1, txt$1); + builder.pos++; + } + } + builder.trailingSpace = displayText.charCodeAt(text.length - 1) == 32; + if (style || startStyle || endStyle || mustWrap || css || attributes) { + var fullStyle = style || ""; + if (startStyle) { fullStyle += startStyle; } + if (endStyle) { fullStyle += endStyle; } + var token = elt("span", [content], fullStyle, css); + if (attributes) { + for (var attr in attributes) { if (attributes.hasOwnProperty(attr) && attr != "style" && attr != "class") + { token.setAttribute(attr, attributes[attr]); } } + } + return builder.content.appendChild(token) + } + builder.content.appendChild(content); + } + + // Change some spaces to NBSP to prevent the browser from collapsing + // trailing spaces at the end of a line when rendering text (issue #1362). + function splitSpaces(text, trailingBefore) { + if (text.length > 1 && !/ /.test(text)) { return text } + var spaceBefore = trailingBefore, result = ""; + for (var i = 0; i < text.length; i++) { + var ch = text.charAt(i); + if (ch == " " && spaceBefore && (i == text.length - 1 || text.charCodeAt(i + 1) == 32)) + { ch = "\u00a0"; } + result += ch; + spaceBefore = ch == " "; + } + return result + } + + // Work around nonsense dimensions being reported for stretches of + // right-to-left text. + function buildTokenBadBidi(inner, order) { + return function (builder, text, style, startStyle, endStyle, css, attributes) { + style = style ? style + " cm-force-border" : "cm-force-border"; + var start = builder.pos, end = start + text.length; + for (;;) { + // Find the part that overlaps with the start of this text + var part = (void 0); + for (var i = 0; i < order.length; i++) { + part = order[i]; + if (part.to > start && part.from <= start) { break } + } + if (part.to >= end) { return inner(builder, text, style, startStyle, endStyle, css, attributes) } + inner(builder, text.slice(0, part.to - start), style, startStyle, null, css, attributes); + startStyle = null; + text = text.slice(part.to - start); + start = part.to; + } + } + } + + function buildCollapsedSpan(builder, size, marker, ignoreWidget) { + var widget = !ignoreWidget && marker.widgetNode; + if (widget) { builder.map.push(builder.pos, builder.pos + size, widget); } + if (!ignoreWidget && builder.cm.display.input.needsContentAttribute) { + if (!widget) + { widget = builder.content.appendChild(document.createElement("span")); } + widget.setAttribute("cm-marker", marker.id); + } + if (widget) { + builder.cm.display.input.setUneditable(widget); + builder.content.appendChild(widget); + } + builder.pos += size; + builder.trailingSpace = false; + } + + // Outputs a number of spans to make up a line, taking highlighting + // and marked text into account. + function insertLineContent(line, builder, styles) { + var spans = line.markedSpans, allText = line.text, at = 0; + if (!spans) { + for (var i$1 = 1; i$1 < styles.length; i$1+=2) + { builder.addToken(builder, allText.slice(at, at = styles[i$1]), interpretTokenStyle(styles[i$1+1], builder.cm.options)); } + return + } + + var len = allText.length, pos = 0, i = 1, text = "", style, css; + var nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, collapsed, attributes; + for (;;) { + if (nextChange == pos) { // Update current marker set + spanStyle = spanEndStyle = spanStartStyle = css = ""; + attributes = null; + collapsed = null; nextChange = Infinity; + var foundBookmarks = [], endStyles = (void 0); + for (var j = 0; j < spans.length; ++j) { + var sp = spans[j], m = sp.marker; + if (m.type == "bookmark" && sp.from == pos && m.widgetNode) { + foundBookmarks.push(m); + } else if (sp.from <= pos && (sp.to == null || sp.to > pos || m.collapsed && sp.to == pos && sp.from == pos)) { + if (sp.to != null && sp.to != pos && nextChange > sp.to) { + nextChange = sp.to; + spanEndStyle = ""; + } + if (m.className) { spanStyle += " " + m.className; } + if (m.css) { css = (css ? css + ";" : "") + m.css; } + if (m.startStyle && sp.from == pos) { spanStartStyle += " " + m.startStyle; } + if (m.endStyle && sp.to == nextChange) { (endStyles || (endStyles = [])).push(m.endStyle, sp.to); } + // support for the old title property + // https://github.com/codemirror/CodeMirror/pull/5673 + if (m.title) { (attributes || (attributes = {})).title = m.title; } + if (m.attributes) { + for (var attr in m.attributes) + { (attributes || (attributes = {}))[attr] = m.attributes[attr]; } + } + if (m.collapsed && (!collapsed || compareCollapsedMarkers(collapsed.marker, m) < 0)) + { collapsed = sp; } + } else if (sp.from > pos && nextChange > sp.from) { + nextChange = sp.from; + } + } + if (endStyles) { for (var j$1 = 0; j$1 < endStyles.length; j$1 += 2) + { if (endStyles[j$1 + 1] == nextChange) { spanEndStyle += " " + endStyles[j$1]; } } } + + if (!collapsed || collapsed.from == pos) { for (var j$2 = 0; j$2 < foundBookmarks.length; ++j$2) + { buildCollapsedSpan(builder, 0, foundBookmarks[j$2]); } } + if (collapsed && (collapsed.from || 0) == pos) { + buildCollapsedSpan(builder, (collapsed.to == null ? len + 1 : collapsed.to) - pos, + collapsed.marker, collapsed.from == null); + if (collapsed.to == null) { return } + if (collapsed.to == pos) { collapsed = false; } + } + } + if (pos >= len) { break } + + var upto = Math.min(len, nextChange); + while (true) { + if (text) { + var end = pos + text.length; + if (!collapsed) { + var tokenText = end > upto ? text.slice(0, upto - pos) : text; + builder.addToken(builder, tokenText, style ? style + spanStyle : spanStyle, + spanStartStyle, pos + tokenText.length == nextChange ? spanEndStyle : "", css, attributes); + } + if (end >= upto) {text = text.slice(upto - pos); pos = upto; break} + pos = end; + spanStartStyle = ""; + } + text = allText.slice(at, at = styles[i++]); + style = interpretTokenStyle(styles[i++], builder.cm.options); + } + } + } + + + // These objects are used to represent the visible (currently drawn) + // part of the document. A LineView may correspond to multiple + // logical lines, if those are connected by collapsed ranges. + function LineView(doc, line, lineN) { + // The starting line + this.line = line; + // Continuing lines, if any + this.rest = visualLineContinued(line); + // Number of logical lines in this visual line + this.size = this.rest ? lineNo(lst(this.rest)) - lineN + 1 : 1; + this.node = this.text = null; + this.hidden = lineIsHidden(doc, line); + } + + // Create a range of LineView objects for the given lines. + function buildViewArray(cm, from, to) { + var array = [], nextPos; + for (var pos = from; pos < to; pos = nextPos) { + var view = new LineView(cm.doc, getLine(cm.doc, pos), pos); + nextPos = pos + view.size; + array.push(view); + } + return array + } + + var operationGroup = null; + + function pushOperation(op) { + if (operationGroup) { + operationGroup.ops.push(op); + } else { + op.ownsGroup = operationGroup = { + ops: [op], + delayedCallbacks: [] + }; + } + } + + function fireCallbacksForOps(group) { + // Calls delayed callbacks and cursorActivity handlers until no + // new ones appear + var callbacks = group.delayedCallbacks, i = 0; + do { + for (; i < callbacks.length; i++) + { callbacks[i].call(null); } + for (var j = 0; j < group.ops.length; j++) { + var op = group.ops[j]; + if (op.cursorActivityHandlers) + { while (op.cursorActivityCalled < op.cursorActivityHandlers.length) + { op.cursorActivityHandlers[op.cursorActivityCalled++].call(null, op.cm); } } + } + } while (i < callbacks.length) + } + + function finishOperation(op, endCb) { + var group = op.ownsGroup; + if (!group) { return } + + try { fireCallbacksForOps(group); } + finally { + operationGroup = null; + endCb(group); + } + } + + var orphanDelayedCallbacks = null; + + // Often, we want to signal events at a point where we are in the + // middle of some work, but don't want the handler to start calling + // other methods on the editor, which might be in an inconsistent + // state or simply not expect any other events to happen. + // signalLater looks whether there are any handlers, and schedules + // them to be executed when the last operation ends, or, if no + // operation is active, when a timeout fires. + function signalLater(emitter, type /*, values...*/) { + var arr = getHandlers(emitter, type); + if (!arr.length) { return } + var args = Array.prototype.slice.call(arguments, 2), list; + if (operationGroup) { + list = operationGroup.delayedCallbacks; + } else if (orphanDelayedCallbacks) { + list = orphanDelayedCallbacks; + } else { + list = orphanDelayedCallbacks = []; + setTimeout(fireOrphanDelayed, 0); + } + var loop = function ( i ) { + list.push(function () { return arr[i].apply(null, args); }); + }; + + for (var i = 0; i < arr.length; ++i) + loop( i ); + } + + function fireOrphanDelayed() { + var delayed = orphanDelayedCallbacks; + orphanDelayedCallbacks = null; + for (var i = 0; i < delayed.length; ++i) { delayed[i](); } + } + + // When an aspect of a line changes, a string is added to + // lineView.changes. This updates the relevant part of the line's + // DOM structure. + function updateLineForChanges(cm, lineView, lineN, dims) { + for (var j = 0; j < lineView.changes.length; j++) { + var type = lineView.changes[j]; + if (type == "text") { updateLineText(cm, lineView); } + else if (type == "gutter") { updateLineGutter(cm, lineView, lineN, dims); } + else if (type == "class") { updateLineClasses(cm, lineView); } + else if (type == "widget") { updateLineWidgets(cm, lineView, dims); } + } + lineView.changes = null; + } + + // Lines with gutter elements, widgets or a background class need to + // be wrapped, and have the extra elements added to the wrapper div + function ensureLineWrapped(lineView) { + if (lineView.node == lineView.text) { + lineView.node = elt("div", null, null, "position: relative"); + if (lineView.text.parentNode) + { lineView.text.parentNode.replaceChild(lineView.node, lineView.text); } + lineView.node.appendChild(lineView.text); + if (ie && ie_version < 8) { lineView.node.style.zIndex = 2; } + } + return lineView.node + } + + function updateLineBackground(cm, lineView) { + var cls = lineView.bgClass ? lineView.bgClass + " " + (lineView.line.bgClass || "") : lineView.line.bgClass; + if (cls) { cls += " CodeMirror-linebackground"; } + if (lineView.background) { + if (cls) { lineView.background.className = cls; } + else { lineView.background.parentNode.removeChild(lineView.background); lineView.background = null; } + } else if (cls) { + var wrap = ensureLineWrapped(lineView); + lineView.background = wrap.insertBefore(elt("div", null, cls), wrap.firstChild); + cm.display.input.setUneditable(lineView.background); + } + } + + // Wrapper around buildLineContent which will reuse the structure + // in display.externalMeasured when possible. + function getLineContent(cm, lineView) { + var ext = cm.display.externalMeasured; + if (ext && ext.line == lineView.line) { + cm.display.externalMeasured = null; + lineView.measure = ext.measure; + return ext.built + } + return buildLineContent(cm, lineView) + } + + // Redraw the line's text. Interacts with the background and text + // classes because the mode may output tokens that influence these + // classes. + function updateLineText(cm, lineView) { + var cls = lineView.text.className; + var built = getLineContent(cm, lineView); + if (lineView.text == lineView.node) { lineView.node = built.pre; } + lineView.text.parentNode.replaceChild(built.pre, lineView.text); + lineView.text = built.pre; + if (built.bgClass != lineView.bgClass || built.textClass != lineView.textClass) { + lineView.bgClass = built.bgClass; + lineView.textClass = built.textClass; + updateLineClasses(cm, lineView); + } else if (cls) { + lineView.text.className = cls; + } + } + + function updateLineClasses(cm, lineView) { + updateLineBackground(cm, lineView); + if (lineView.line.wrapClass) + { ensureLineWrapped(lineView).className = lineView.line.wrapClass; } + else if (lineView.node != lineView.text) + { lineView.node.className = ""; } + var textClass = lineView.textClass ? lineView.textClass + " " + (lineView.line.textClass || "") : lineView.line.textClass; + lineView.text.className = textClass || ""; + } + + function updateLineGutter(cm, lineView, lineN, dims) { + if (lineView.gutter) { + lineView.node.removeChild(lineView.gutter); + lineView.gutter = null; + } + if (lineView.gutterBackground) { + lineView.node.removeChild(lineView.gutterBackground); + lineView.gutterBackground = null; + } + if (lineView.line.gutterClass) { + var wrap = ensureLineWrapped(lineView); + lineView.gutterBackground = elt("div", null, "CodeMirror-gutter-background " + lineView.line.gutterClass, + ("left: " + (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px; width: " + (dims.gutterTotalWidth) + "px")); + cm.display.input.setUneditable(lineView.gutterBackground); + wrap.insertBefore(lineView.gutterBackground, lineView.text); + } + var markers = lineView.line.gutterMarkers; + if (cm.options.lineNumbers || markers) { + var wrap$1 = ensureLineWrapped(lineView); + var gutterWrap = lineView.gutter = elt("div", null, "CodeMirror-gutter-wrapper", ("left: " + (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px")); + gutterWrap.setAttribute("aria-hidden", "true"); + cm.display.input.setUneditable(gutterWrap); + wrap$1.insertBefore(gutterWrap, lineView.text); + if (lineView.line.gutterClass) + { gutterWrap.className += " " + lineView.line.gutterClass; } + if (cm.options.lineNumbers && (!markers || !markers["CodeMirror-linenumbers"])) + { lineView.lineNumber = gutterWrap.appendChild( + elt("div", lineNumberFor(cm.options, lineN), + "CodeMirror-linenumber CodeMirror-gutter-elt", + ("left: " + (dims.gutterLeft["CodeMirror-linenumbers"]) + "px; width: " + (cm.display.lineNumInnerWidth) + "px"))); } + if (markers) { for (var k = 0; k < cm.display.gutterSpecs.length; ++k) { + var id = cm.display.gutterSpecs[k].className, found = markers.hasOwnProperty(id) && markers[id]; + if (found) + { gutterWrap.appendChild(elt("div", [found], "CodeMirror-gutter-elt", + ("left: " + (dims.gutterLeft[id]) + "px; width: " + (dims.gutterWidth[id]) + "px"))); } + } } + } + } + + function updateLineWidgets(cm, lineView, dims) { + if (lineView.alignable) { lineView.alignable = null; } + var isWidget = classTest("CodeMirror-linewidget"); + for (var node = lineView.node.firstChild, next = (void 0); node; node = next) { + next = node.nextSibling; + if (isWidget.test(node.className)) { lineView.node.removeChild(node); } + } + insertLineWidgets(cm, lineView, dims); + } + + // Build a line's DOM representation from scratch + function buildLineElement(cm, lineView, lineN, dims) { + var built = getLineContent(cm, lineView); + lineView.text = lineView.node = built.pre; + if (built.bgClass) { lineView.bgClass = built.bgClass; } + if (built.textClass) { lineView.textClass = built.textClass; } + + updateLineClasses(cm, lineView); + updateLineGutter(cm, lineView, lineN, dims); + insertLineWidgets(cm, lineView, dims); + return lineView.node + } + + // A lineView may contain multiple logical lines (when merged by + // collapsed spans). The widgets for all of them need to be drawn. + function insertLineWidgets(cm, lineView, dims) { + insertLineWidgetsFor(cm, lineView.line, lineView, dims, true); + if (lineView.rest) { for (var i = 0; i < lineView.rest.length; i++) + { insertLineWidgetsFor(cm, lineView.rest[i], lineView, dims, false); } } + } + + function insertLineWidgetsFor(cm, line, lineView, dims, allowAbove) { + if (!line.widgets) { return } + var wrap = ensureLineWrapped(lineView); + for (var i = 0, ws = line.widgets; i < ws.length; ++i) { + var widget = ws[i], node = elt("div", [widget.node], "CodeMirror-linewidget" + (widget.className ? " " + widget.className : "")); + if (!widget.handleMouseEvents) { node.setAttribute("cm-ignore-events", "true"); } + positionLineWidget(widget, node, lineView, dims); + cm.display.input.setUneditable(node); + if (allowAbove && widget.above) + { wrap.insertBefore(node, lineView.gutter || lineView.text); } + else + { wrap.appendChild(node); } + signalLater(widget, "redraw"); + } + } + + function positionLineWidget(widget, node, lineView, dims) { + if (widget.noHScroll) { + (lineView.alignable || (lineView.alignable = [])).push(node); + var width = dims.wrapperWidth; + node.style.left = dims.fixedPos + "px"; + if (!widget.coverGutter) { + width -= dims.gutterTotalWidth; + node.style.paddingLeft = dims.gutterTotalWidth + "px"; + } + node.style.width = width + "px"; + } + if (widget.coverGutter) { + node.style.zIndex = 5; + node.style.position = "relative"; + if (!widget.noHScroll) { node.style.marginLeft = -dims.gutterTotalWidth + "px"; } + } + } + + function widgetHeight(widget) { + if (widget.height != null) { return widget.height } + var cm = widget.doc.cm; + if (!cm) { return 0 } + if (!contains(document.body, widget.node)) { + var parentStyle = "position: relative;"; + if (widget.coverGutter) + { parentStyle += "margin-left: -" + cm.display.gutters.offsetWidth + "px;"; } + if (widget.noHScroll) + { parentStyle += "width: " + cm.display.wrapper.clientWidth + "px;"; } + removeChildrenAndAdd(cm.display.measure, elt("div", [widget.node], null, parentStyle)); + } + return widget.height = widget.node.parentNode.offsetHeight + } + + // Return true when the given mouse event happened in a widget + function eventInWidget(display, e) { + for (var n = e_target(e); n != display.wrapper; n = n.parentNode) { + if (!n || (n.nodeType == 1 && n.getAttribute("cm-ignore-events") == "true") || + (n.parentNode == display.sizer && n != display.mover)) + { return true } + } + } + + // POSITION MEASUREMENT + + function paddingTop(display) {return display.lineSpace.offsetTop} + function paddingVert(display) {return display.mover.offsetHeight - display.lineSpace.offsetHeight} + function paddingH(display) { + if (display.cachedPaddingH) { return display.cachedPaddingH } + var e = removeChildrenAndAdd(display.measure, elt("pre", "x", "CodeMirror-line-like")); + var style = window.getComputedStyle ? window.getComputedStyle(e) : e.currentStyle; + var data = {left: parseInt(style.paddingLeft), right: parseInt(style.paddingRight)}; + if (!isNaN(data.left) && !isNaN(data.right)) { display.cachedPaddingH = data; } + return data + } + + function scrollGap(cm) { return scrollerGap - cm.display.nativeBarWidth } + function displayWidth(cm) { + return cm.display.scroller.clientWidth - scrollGap(cm) - cm.display.barWidth + } + function displayHeight(cm) { + return cm.display.scroller.clientHeight - scrollGap(cm) - cm.display.barHeight + } + + // Ensure the lineView.wrapping.heights array is populated. This is + // an array of bottom offsets for the lines that make up a drawn + // line. When lineWrapping is on, there might be more than one + // height. + function ensureLineHeights(cm, lineView, rect) { + var wrapping = cm.options.lineWrapping; + var curWidth = wrapping && displayWidth(cm); + if (!lineView.measure.heights || wrapping && lineView.measure.width != curWidth) { + var heights = lineView.measure.heights = []; + if (wrapping) { + lineView.measure.width = curWidth; + var rects = lineView.text.firstChild.getClientRects(); + for (var i = 0; i < rects.length - 1; i++) { + var cur = rects[i], next = rects[i + 1]; + if (Math.abs(cur.bottom - next.bottom) > 2) + { heights.push((cur.bottom + next.top) / 2 - rect.top); } + } + } + heights.push(rect.bottom - rect.top); + } + } + + // Find a line map (mapping character offsets to text nodes) and a + // measurement cache for the given line number. (A line view might + // contain multiple lines when collapsed ranges are present.) + function mapFromLineView(lineView, line, lineN) { + if (lineView.line == line) + { return {map: lineView.measure.map, cache: lineView.measure.cache} } + if (lineView.rest) { + for (var i = 0; i < lineView.rest.length; i++) + { if (lineView.rest[i] == line) + { return {map: lineView.measure.maps[i], cache: lineView.measure.caches[i]} } } + for (var i$1 = 0; i$1 < lineView.rest.length; i$1++) + { if (lineNo(lineView.rest[i$1]) > lineN) + { return {map: lineView.measure.maps[i$1], cache: lineView.measure.caches[i$1], before: true} } } + } + } + + // Render a line into the hidden node display.externalMeasured. Used + // when measurement is needed for a line that's not in the viewport. + function updateExternalMeasurement(cm, line) { + line = visualLine(line); + var lineN = lineNo(line); + var view = cm.display.externalMeasured = new LineView(cm.doc, line, lineN); + view.lineN = lineN; + var built = view.built = buildLineContent(cm, view); + view.text = built.pre; + removeChildrenAndAdd(cm.display.lineMeasure, built.pre); + return view + } + + // Get a {top, bottom, left, right} box (in line-local coordinates) + // for a given character. + function measureChar(cm, line, ch, bias) { + return measureCharPrepared(cm, prepareMeasureForLine(cm, line), ch, bias) + } + + // Find a line view that corresponds to the given line number. + function findViewForLine(cm, lineN) { + if (lineN >= cm.display.viewFrom && lineN < cm.display.viewTo) + { return cm.display.view[findViewIndex(cm, lineN)] } + var ext = cm.display.externalMeasured; + if (ext && lineN >= ext.lineN && lineN < ext.lineN + ext.size) + { return ext } + } + + // Measurement can be split in two steps, the set-up work that + // applies to the whole line, and the measurement of the actual + // character. Functions like coordsChar, that need to do a lot of + // measurements in a row, can thus ensure that the set-up work is + // only done once. + function prepareMeasureForLine(cm, line) { + var lineN = lineNo(line); + var view = findViewForLine(cm, lineN); + if (view && !view.text) { + view = null; + } else if (view && view.changes) { + updateLineForChanges(cm, view, lineN, getDimensions(cm)); + cm.curOp.forceUpdate = true; + } + if (!view) + { view = updateExternalMeasurement(cm, line); } + + var info = mapFromLineView(view, line, lineN); + return { + line: line, view: view, rect: null, + map: info.map, cache: info.cache, before: info.before, + hasHeights: false + } + } + + // Given a prepared measurement object, measures the position of an + // actual character (or fetches it from the cache). + function measureCharPrepared(cm, prepared, ch, bias, varHeight) { + if (prepared.before) { ch = -1; } + var key = ch + (bias || ""), found; + if (prepared.cache.hasOwnProperty(key)) { + found = prepared.cache[key]; + } else { + if (!prepared.rect) + { prepared.rect = prepared.view.text.getBoundingClientRect(); } + if (!prepared.hasHeights) { + ensureLineHeights(cm, prepared.view, prepared.rect); + prepared.hasHeights = true; + } + found = measureCharInner(cm, prepared, ch, bias); + if (!found.bogus) { prepared.cache[key] = found; } + } + return {left: found.left, right: found.right, + top: varHeight ? found.rtop : found.top, + bottom: varHeight ? found.rbottom : found.bottom} + } + + var nullRect = {left: 0, right: 0, top: 0, bottom: 0}; + + function nodeAndOffsetInLineMap(map, ch, bias) { + var node, start, end, collapse, mStart, mEnd; + // First, search the line map for the text node corresponding to, + // or closest to, the target character. + for (var i = 0; i < map.length; i += 3) { + mStart = map[i]; + mEnd = map[i + 1]; + if (ch < mStart) { + start = 0; end = 1; + collapse = "left"; + } else if (ch < mEnd) { + start = ch - mStart; + end = start + 1; + } else if (i == map.length - 3 || ch == mEnd && map[i + 3] > ch) { + end = mEnd - mStart; + start = end - 1; + if (ch >= mEnd) { collapse = "right"; } + } + if (start != null) { + node = map[i + 2]; + if (mStart == mEnd && bias == (node.insertLeft ? "left" : "right")) + { collapse = bias; } + if (bias == "left" && start == 0) + { while (i && map[i - 2] == map[i - 3] && map[i - 1].insertLeft) { + node = map[(i -= 3) + 2]; + collapse = "left"; + } } + if (bias == "right" && start == mEnd - mStart) + { while (i < map.length - 3 && map[i + 3] == map[i + 4] && !map[i + 5].insertLeft) { + node = map[(i += 3) + 2]; + collapse = "right"; + } } + break + } + } + return {node: node, start: start, end: end, collapse: collapse, coverStart: mStart, coverEnd: mEnd} + } + + function getUsefulRect(rects, bias) { + var rect = nullRect; + if (bias == "left") { for (var i = 0; i < rects.length; i++) { + if ((rect = rects[i]).left != rect.right) { break } + } } else { for (var i$1 = rects.length - 1; i$1 >= 0; i$1--) { + if ((rect = rects[i$1]).left != rect.right) { break } + } } + return rect + } + + function measureCharInner(cm, prepared, ch, bias) { + var place = nodeAndOffsetInLineMap(prepared.map, ch, bias); + var node = place.node, start = place.start, end = place.end, collapse = place.collapse; + + var rect; + if (node.nodeType == 3) { // If it is a text node, use a range to retrieve the coordinates. + for (var i$1 = 0; i$1 < 4; i$1++) { // Retry a maximum of 4 times when nonsense rectangles are returned + while (start && isExtendingChar(prepared.line.text.charAt(place.coverStart + start))) { --start; } + while (place.coverStart + end < place.coverEnd && isExtendingChar(prepared.line.text.charAt(place.coverStart + end))) { ++end; } + if (ie && ie_version < 9 && start == 0 && end == place.coverEnd - place.coverStart) + { rect = node.parentNode.getBoundingClientRect(); } + else + { rect = getUsefulRect(range(node, start, end).getClientRects(), bias); } + if (rect.left || rect.right || start == 0) { break } + end = start; + start = start - 1; + collapse = "right"; + } + if (ie && ie_version < 11) { rect = maybeUpdateRectForZooming(cm.display.measure, rect); } + } else { // If it is a widget, simply get the box for the whole widget. + if (start > 0) { collapse = bias = "right"; } + var rects; + if (cm.options.lineWrapping && (rects = node.getClientRects()).length > 1) + { rect = rects[bias == "right" ? rects.length - 1 : 0]; } + else + { rect = node.getBoundingClientRect(); } + } + if (ie && ie_version < 9 && !start && (!rect || !rect.left && !rect.right)) { + var rSpan = node.parentNode.getClientRects()[0]; + if (rSpan) + { rect = {left: rSpan.left, right: rSpan.left + charWidth(cm.display), top: rSpan.top, bottom: rSpan.bottom}; } + else + { rect = nullRect; } + } + + var rtop = rect.top - prepared.rect.top, rbot = rect.bottom - prepared.rect.top; + var mid = (rtop + rbot) / 2; + var heights = prepared.view.measure.heights; + var i = 0; + for (; i < heights.length - 1; i++) + { if (mid < heights[i]) { break } } + var top = i ? heights[i - 1] : 0, bot = heights[i]; + var result = {left: (collapse == "right" ? rect.right : rect.left) - prepared.rect.left, + right: (collapse == "left" ? rect.left : rect.right) - prepared.rect.left, + top: top, bottom: bot}; + if (!rect.left && !rect.right) { result.bogus = true; } + if (!cm.options.singleCursorHeightPerLine) { result.rtop = rtop; result.rbottom = rbot; } + + return result + } + + // Work around problem with bounding client rects on ranges being + // returned incorrectly when zoomed on IE10 and below. + function maybeUpdateRectForZooming(measure, rect) { + if (!window.screen || screen.logicalXDPI == null || + screen.logicalXDPI == screen.deviceXDPI || !hasBadZoomedRects(measure)) + { return rect } + var scaleX = screen.logicalXDPI / screen.deviceXDPI; + var scaleY = screen.logicalYDPI / screen.deviceYDPI; + return {left: rect.left * scaleX, right: rect.right * scaleX, + top: rect.top * scaleY, bottom: rect.bottom * scaleY} + } + + function clearLineMeasurementCacheFor(lineView) { + if (lineView.measure) { + lineView.measure.cache = {}; + lineView.measure.heights = null; + if (lineView.rest) { for (var i = 0; i < lineView.rest.length; i++) + { lineView.measure.caches[i] = {}; } } + } + } + + function clearLineMeasurementCache(cm) { + cm.display.externalMeasure = null; + removeChildren(cm.display.lineMeasure); + for (var i = 0; i < cm.display.view.length; i++) + { clearLineMeasurementCacheFor(cm.display.view[i]); } + } + + function clearCaches(cm) { + clearLineMeasurementCache(cm); + cm.display.cachedCharWidth = cm.display.cachedTextHeight = cm.display.cachedPaddingH = null; + if (!cm.options.lineWrapping) { cm.display.maxLineChanged = true; } + cm.display.lineNumChars = null; + } + + function pageScrollX(doc) { + // Work around https://bugs.chromium.org/p/chromium/issues/detail?id=489206 + // which causes page_Offset and bounding client rects to use + // different reference viewports and invalidate our calculations. + if (chrome && android) { return -(doc.body.getBoundingClientRect().left - parseInt(getComputedStyle(doc.body).marginLeft)) } + return doc.defaultView.pageXOffset || (doc.documentElement || doc.body).scrollLeft + } + function pageScrollY(doc) { + if (chrome && android) { return -(doc.body.getBoundingClientRect().top - parseInt(getComputedStyle(doc.body).marginTop)) } + return doc.defaultView.pageYOffset || (doc.documentElement || doc.body).scrollTop + } + + function widgetTopHeight(lineObj) { + var ref = visualLine(lineObj); + var widgets = ref.widgets; + var height = 0; + if (widgets) { for (var i = 0; i < widgets.length; ++i) { if (widgets[i].above) + { height += widgetHeight(widgets[i]); } } } + return height + } + + // Converts a {top, bottom, left, right} box from line-local + // coordinates into another coordinate system. Context may be one of + // "line", "div" (display.lineDiv), "local"./null (editor), "window", + // or "page". + function intoCoordSystem(cm, lineObj, rect, context, includeWidgets) { + if (!includeWidgets) { + var height = widgetTopHeight(lineObj); + rect.top += height; rect.bottom += height; + } + if (context == "line") { return rect } + if (!context) { context = "local"; } + var yOff = heightAtLine(lineObj); + if (context == "local") { yOff += paddingTop(cm.display); } + else { yOff -= cm.display.viewOffset; } + if (context == "page" || context == "window") { + var lOff = cm.display.lineSpace.getBoundingClientRect(); + yOff += lOff.top + (context == "window" ? 0 : pageScrollY(doc(cm))); + var xOff = lOff.left + (context == "window" ? 0 : pageScrollX(doc(cm))); + rect.left += xOff; rect.right += xOff; + } + rect.top += yOff; rect.bottom += yOff; + return rect + } + + // Coverts a box from "div" coords to another coordinate system. + // Context may be "window", "page", "div", or "local"./null. + function fromCoordSystem(cm, coords, context) { + if (context == "div") { return coords } + var left = coords.left, top = coords.top; + // First move into "page" coordinate system + if (context == "page") { + left -= pageScrollX(doc(cm)); + top -= pageScrollY(doc(cm)); + } else if (context == "local" || !context) { + var localBox = cm.display.sizer.getBoundingClientRect(); + left += localBox.left; + top += localBox.top; + } + + var lineSpaceBox = cm.display.lineSpace.getBoundingClientRect(); + return {left: left - lineSpaceBox.left, top: top - lineSpaceBox.top} + } + + function charCoords(cm, pos, context, lineObj, bias) { + if (!lineObj) { lineObj = getLine(cm.doc, pos.line); } + return intoCoordSystem(cm, lineObj, measureChar(cm, lineObj, pos.ch, bias), context) + } + + // Returns a box for a given cursor position, which may have an + // 'other' property containing the position of the secondary cursor + // on a bidi boundary. + // A cursor Pos(line, char, "before") is on the same visual line as `char - 1` + // and after `char - 1` in writing order of `char - 1` + // A cursor Pos(line, char, "after") is on the same visual line as `char` + // and before `char` in writing order of `char` + // Examples (upper-case letters are RTL, lower-case are LTR): + // Pos(0, 1, ...) + // before after + // ab a|b a|b + // aB a|B aB| + // Ab |Ab A|b + // AB B|A B|A + // Every position after the last character on a line is considered to stick + // to the last character on the line. + function cursorCoords(cm, pos, context, lineObj, preparedMeasure, varHeight) { + lineObj = lineObj || getLine(cm.doc, pos.line); + if (!preparedMeasure) { preparedMeasure = prepareMeasureForLine(cm, lineObj); } + function get(ch, right) { + var m = measureCharPrepared(cm, preparedMeasure, ch, right ? "right" : "left", varHeight); + if (right) { m.left = m.right; } else { m.right = m.left; } + return intoCoordSystem(cm, lineObj, m, context) + } + var order = getOrder(lineObj, cm.doc.direction), ch = pos.ch, sticky = pos.sticky; + if (ch >= lineObj.text.length) { + ch = lineObj.text.length; + sticky = "before"; + } else if (ch <= 0) { + ch = 0; + sticky = "after"; + } + if (!order) { return get(sticky == "before" ? ch - 1 : ch, sticky == "before") } + + function getBidi(ch, partPos, invert) { + var part = order[partPos], right = part.level == 1; + return get(invert ? ch - 1 : ch, right != invert) + } + var partPos = getBidiPartAt(order, ch, sticky); + var other = bidiOther; + var val = getBidi(ch, partPos, sticky == "before"); + if (other != null) { val.other = getBidi(ch, other, sticky != "before"); } + return val + } + + // Used to cheaply estimate the coordinates for a position. Used for + // intermediate scroll updates. + function estimateCoords(cm, pos) { + var left = 0; + pos = clipPos(cm.doc, pos); + if (!cm.options.lineWrapping) { left = charWidth(cm.display) * pos.ch; } + var lineObj = getLine(cm.doc, pos.line); + var top = heightAtLine(lineObj) + paddingTop(cm.display); + return {left: left, right: left, top: top, bottom: top + lineObj.height} + } + + // Positions returned by coordsChar contain some extra information. + // xRel is the relative x position of the input coordinates compared + // to the found position (so xRel > 0 means the coordinates are to + // the right of the character position, for example). When outside + // is true, that means the coordinates lie outside the line's + // vertical range. + function PosWithInfo(line, ch, sticky, outside, xRel) { + var pos = Pos(line, ch, sticky); + pos.xRel = xRel; + if (outside) { pos.outside = outside; } + return pos + } + + // Compute the character position closest to the given coordinates. + // Input must be lineSpace-local ("div" coordinate system). + function coordsChar(cm, x, y) { + var doc = cm.doc; + y += cm.display.viewOffset; + if (y < 0) { return PosWithInfo(doc.first, 0, null, -1, -1) } + var lineN = lineAtHeight(doc, y), last = doc.first + doc.size - 1; + if (lineN > last) + { return PosWithInfo(doc.first + doc.size - 1, getLine(doc, last).text.length, null, 1, 1) } + if (x < 0) { x = 0; } + + var lineObj = getLine(doc, lineN); + for (;;) { + var found = coordsCharInner(cm, lineObj, lineN, x, y); + var collapsed = collapsedSpanAround(lineObj, found.ch + (found.xRel > 0 || found.outside > 0 ? 1 : 0)); + if (!collapsed) { return found } + var rangeEnd = collapsed.find(1); + if (rangeEnd.line == lineN) { return rangeEnd } + lineObj = getLine(doc, lineN = rangeEnd.line); + } + } + + function wrappedLineExtent(cm, lineObj, preparedMeasure, y) { + y -= widgetTopHeight(lineObj); + var end = lineObj.text.length; + var begin = findFirst(function (ch) { return measureCharPrepared(cm, preparedMeasure, ch - 1).bottom <= y; }, end, 0); + end = findFirst(function (ch) { return measureCharPrepared(cm, preparedMeasure, ch).top > y; }, begin, end); + return {begin: begin, end: end} + } + + function wrappedLineExtentChar(cm, lineObj, preparedMeasure, target) { + if (!preparedMeasure) { preparedMeasure = prepareMeasureForLine(cm, lineObj); } + var targetTop = intoCoordSystem(cm, lineObj, measureCharPrepared(cm, preparedMeasure, target), "line").top; + return wrappedLineExtent(cm, lineObj, preparedMeasure, targetTop) + } + + // Returns true if the given side of a box is after the given + // coordinates, in top-to-bottom, left-to-right order. + function boxIsAfter(box, x, y, left) { + return box.bottom <= y ? false : box.top > y ? true : (left ? box.left : box.right) > x + } + + function coordsCharInner(cm, lineObj, lineNo, x, y) { + // Move y into line-local coordinate space + y -= heightAtLine(lineObj); + var preparedMeasure = prepareMeasureForLine(cm, lineObj); + // When directly calling `measureCharPrepared`, we have to adjust + // for the widgets at this line. + var widgetHeight = widgetTopHeight(lineObj); + var begin = 0, end = lineObj.text.length, ltr = true; + + var order = getOrder(lineObj, cm.doc.direction); + // If the line isn't plain left-to-right text, first figure out + // which bidi section the coordinates fall into. + if (order) { + var part = (cm.options.lineWrapping ? coordsBidiPartWrapped : coordsBidiPart) + (cm, lineObj, lineNo, preparedMeasure, order, x, y); + ltr = part.level != 1; + // The awkward -1 offsets are needed because findFirst (called + // on these below) will treat its first bound as inclusive, + // second as exclusive, but we want to actually address the + // characters in the part's range + begin = ltr ? part.from : part.to - 1; + end = ltr ? part.to : part.from - 1; + } + + // A binary search to find the first character whose bounding box + // starts after the coordinates. If we run across any whose box wrap + // the coordinates, store that. + var chAround = null, boxAround = null; + var ch = findFirst(function (ch) { + var box = measureCharPrepared(cm, preparedMeasure, ch); + box.top += widgetHeight; box.bottom += widgetHeight; + if (!boxIsAfter(box, x, y, false)) { return false } + if (box.top <= y && box.left <= x) { + chAround = ch; + boxAround = box; + } + return true + }, begin, end); + + var baseX, sticky, outside = false; + // If a box around the coordinates was found, use that + if (boxAround) { + // Distinguish coordinates nearer to the left or right side of the box + var atLeft = x - boxAround.left < boxAround.right - x, atStart = atLeft == ltr; + ch = chAround + (atStart ? 0 : 1); + sticky = atStart ? "after" : "before"; + baseX = atLeft ? boxAround.left : boxAround.right; + } else { + // (Adjust for extended bound, if necessary.) + if (!ltr && (ch == end || ch == begin)) { ch++; } + // To determine which side to associate with, get the box to the + // left of the character and compare it's vertical position to the + // coordinates + sticky = ch == 0 ? "after" : ch == lineObj.text.length ? "before" : + (measureCharPrepared(cm, preparedMeasure, ch - (ltr ? 1 : 0)).bottom + widgetHeight <= y) == ltr ? + "after" : "before"; + // Now get accurate coordinates for this place, in order to get a + // base X position + var coords = cursorCoords(cm, Pos(lineNo, ch, sticky), "line", lineObj, preparedMeasure); + baseX = coords.left; + outside = y < coords.top ? -1 : y >= coords.bottom ? 1 : 0; + } + + ch = skipExtendingChars(lineObj.text, ch, 1); + return PosWithInfo(lineNo, ch, sticky, outside, x - baseX) + } + + function coordsBidiPart(cm, lineObj, lineNo, preparedMeasure, order, x, y) { + // Bidi parts are sorted left-to-right, and in a non-line-wrapping + // situation, we can take this ordering to correspond to the visual + // ordering. This finds the first part whose end is after the given + // coordinates. + var index = findFirst(function (i) { + var part = order[i], ltr = part.level != 1; + return boxIsAfter(cursorCoords(cm, Pos(lineNo, ltr ? part.to : part.from, ltr ? "before" : "after"), + "line", lineObj, preparedMeasure), x, y, true) + }, 0, order.length - 1); + var part = order[index]; + // If this isn't the first part, the part's start is also after + // the coordinates, and the coordinates aren't on the same line as + // that start, move one part back. + if (index > 0) { + var ltr = part.level != 1; + var start = cursorCoords(cm, Pos(lineNo, ltr ? part.from : part.to, ltr ? "after" : "before"), + "line", lineObj, preparedMeasure); + if (boxIsAfter(start, x, y, true) && start.top > y) + { part = order[index - 1]; } + } + return part + } + + function coordsBidiPartWrapped(cm, lineObj, _lineNo, preparedMeasure, order, x, y) { + // In a wrapped line, rtl text on wrapping boundaries can do things + // that don't correspond to the ordering in our `order` array at + // all, so a binary search doesn't work, and we want to return a + // part that only spans one line so that the binary search in + // coordsCharInner is safe. As such, we first find the extent of the + // wrapped line, and then do a flat search in which we discard any + // spans that aren't on the line. + var ref = wrappedLineExtent(cm, lineObj, preparedMeasure, y); + var begin = ref.begin; + var end = ref.end; + if (/\s/.test(lineObj.text.charAt(end - 1))) { end--; } + var part = null, closestDist = null; + for (var i = 0; i < order.length; i++) { + var p = order[i]; + if (p.from >= end || p.to <= begin) { continue } + var ltr = p.level != 1; + var endX = measureCharPrepared(cm, preparedMeasure, ltr ? Math.min(end, p.to) - 1 : Math.max(begin, p.from)).right; + // Weigh against spans ending before this, so that they are only + // picked if nothing ends after + var dist = endX < x ? x - endX + 1e9 : endX - x; + if (!part || closestDist > dist) { + part = p; + closestDist = dist; + } + } + if (!part) { part = order[order.length - 1]; } + // Clip the part to the wrapped line. + if (part.from < begin) { part = {from: begin, to: part.to, level: part.level}; } + if (part.to > end) { part = {from: part.from, to: end, level: part.level}; } + return part + } + + var measureText; + // Compute the default text height. + function textHeight(display) { + if (display.cachedTextHeight != null) { return display.cachedTextHeight } + if (measureText == null) { + measureText = elt("pre", null, "CodeMirror-line-like"); + // Measure a bunch of lines, for browsers that compute + // fractional heights. + for (var i = 0; i < 49; ++i) { + measureText.appendChild(document.createTextNode("x")); + measureText.appendChild(elt("br")); + } + measureText.appendChild(document.createTextNode("x")); + } + removeChildrenAndAdd(display.measure, measureText); + var height = measureText.offsetHeight / 50; + if (height > 3) { display.cachedTextHeight = height; } + removeChildren(display.measure); + return height || 1 + } + + // Compute the default character width. + function charWidth(display) { + if (display.cachedCharWidth != null) { return display.cachedCharWidth } + var anchor = elt("span", "xxxxxxxxxx"); + var pre = elt("pre", [anchor], "CodeMirror-line-like"); + removeChildrenAndAdd(display.measure, pre); + var rect = anchor.getBoundingClientRect(), width = (rect.right - rect.left) / 10; + if (width > 2) { display.cachedCharWidth = width; } + return width || 10 + } + + // Do a bulk-read of the DOM positions and sizes needed to draw the + // view, so that we don't interleave reading and writing to the DOM. + function getDimensions(cm) { + var d = cm.display, left = {}, width = {}; + var gutterLeft = d.gutters.clientLeft; + for (var n = d.gutters.firstChild, i = 0; n; n = n.nextSibling, ++i) { + var id = cm.display.gutterSpecs[i].className; + left[id] = n.offsetLeft + n.clientLeft + gutterLeft; + width[id] = n.clientWidth; + } + return {fixedPos: compensateForHScroll(d), + gutterTotalWidth: d.gutters.offsetWidth, + gutterLeft: left, + gutterWidth: width, + wrapperWidth: d.wrapper.clientWidth} + } + + // Computes display.scroller.scrollLeft + display.gutters.offsetWidth, + // but using getBoundingClientRect to get a sub-pixel-accurate + // result. + function compensateForHScroll(display) { + return display.scroller.getBoundingClientRect().left - display.sizer.getBoundingClientRect().left + } + + // Returns a function that estimates the height of a line, to use as + // first approximation until the line becomes visible (and is thus + // properly measurable). + function estimateHeight(cm) { + var th = textHeight(cm.display), wrapping = cm.options.lineWrapping; + var perLine = wrapping && Math.max(5, cm.display.scroller.clientWidth / charWidth(cm.display) - 3); + return function (line) { + if (lineIsHidden(cm.doc, line)) { return 0 } + + var widgetsHeight = 0; + if (line.widgets) { for (var i = 0; i < line.widgets.length; i++) { + if (line.widgets[i].height) { widgetsHeight += line.widgets[i].height; } + } } + + if (wrapping) + { return widgetsHeight + (Math.ceil(line.text.length / perLine) || 1) * th } + else + { return widgetsHeight + th } + } + } + + function estimateLineHeights(cm) { + var doc = cm.doc, est = estimateHeight(cm); + doc.iter(function (line) { + var estHeight = est(line); + if (estHeight != line.height) { updateLineHeight(line, estHeight); } + }); + } + + // Given a mouse event, find the corresponding position. If liberal + // is false, it checks whether a gutter or scrollbar was clicked, + // and returns null if it was. forRect is used by rectangular + // selections, and tries to estimate a character position even for + // coordinates beyond the right of the text. + function posFromMouse(cm, e, liberal, forRect) { + var display = cm.display; + if (!liberal && e_target(e).getAttribute("cm-not-content") == "true") { return null } + + var x, y, space = display.lineSpace.getBoundingClientRect(); + // Fails unpredictably on IE[67] when mouse is dragged around quickly. + try { x = e.clientX - space.left; y = e.clientY - space.top; } + catch (e$1) { return null } + var coords = coordsChar(cm, x, y), line; + if (forRect && coords.xRel > 0 && (line = getLine(cm.doc, coords.line).text).length == coords.ch) { + var colDiff = countColumn(line, line.length, cm.options.tabSize) - line.length; + coords = Pos(coords.line, Math.max(0, Math.round((x - paddingH(cm.display).left) / charWidth(cm.display)) - colDiff)); + } + return coords + } + + // Find the view element corresponding to a given line. Return null + // when the line isn't visible. + function findViewIndex(cm, n) { + if (n >= cm.display.viewTo) { return null } + n -= cm.display.viewFrom; + if (n < 0) { return null } + var view = cm.display.view; + for (var i = 0; i < view.length; i++) { + n -= view[i].size; + if (n < 0) { return i } + } + } + + // Updates the display.view data structure for a given change to the + // document. From and to are in pre-change coordinates. Lendiff is + // the amount of lines added or subtracted by the change. This is + // used for changes that span multiple lines, or change the way + // lines are divided into visual lines. regLineChange (below) + // registers single-line changes. + function regChange(cm, from, to, lendiff) { + if (from == null) { from = cm.doc.first; } + if (to == null) { to = cm.doc.first + cm.doc.size; } + if (!lendiff) { lendiff = 0; } + + var display = cm.display; + if (lendiff && to < display.viewTo && + (display.updateLineNumbers == null || display.updateLineNumbers > from)) + { display.updateLineNumbers = from; } + + cm.curOp.viewChanged = true; + + if (from >= display.viewTo) { // Change after + if (sawCollapsedSpans && visualLineNo(cm.doc, from) < display.viewTo) + { resetView(cm); } + } else if (to <= display.viewFrom) { // Change before + if (sawCollapsedSpans && visualLineEndNo(cm.doc, to + lendiff) > display.viewFrom) { + resetView(cm); + } else { + display.viewFrom += lendiff; + display.viewTo += lendiff; + } + } else if (from <= display.viewFrom && to >= display.viewTo) { // Full overlap + resetView(cm); + } else if (from <= display.viewFrom) { // Top overlap + var cut = viewCuttingPoint(cm, to, to + lendiff, 1); + if (cut) { + display.view = display.view.slice(cut.index); + display.viewFrom = cut.lineN; + display.viewTo += lendiff; + } else { + resetView(cm); + } + } else if (to >= display.viewTo) { // Bottom overlap + var cut$1 = viewCuttingPoint(cm, from, from, -1); + if (cut$1) { + display.view = display.view.slice(0, cut$1.index); + display.viewTo = cut$1.lineN; + } else { + resetView(cm); + } + } else { // Gap in the middle + var cutTop = viewCuttingPoint(cm, from, from, -1); + var cutBot = viewCuttingPoint(cm, to, to + lendiff, 1); + if (cutTop && cutBot) { + display.view = display.view.slice(0, cutTop.index) + .concat(buildViewArray(cm, cutTop.lineN, cutBot.lineN)) + .concat(display.view.slice(cutBot.index)); + display.viewTo += lendiff; + } else { + resetView(cm); + } + } + + var ext = display.externalMeasured; + if (ext) { + if (to < ext.lineN) + { ext.lineN += lendiff; } + else if (from < ext.lineN + ext.size) + { display.externalMeasured = null; } + } + } + + // Register a change to a single line. Type must be one of "text", + // "gutter", "class", "widget" + function regLineChange(cm, line, type) { + cm.curOp.viewChanged = true; + var display = cm.display, ext = cm.display.externalMeasured; + if (ext && line >= ext.lineN && line < ext.lineN + ext.size) + { display.externalMeasured = null; } + + if (line < display.viewFrom || line >= display.viewTo) { return } + var lineView = display.view[findViewIndex(cm, line)]; + if (lineView.node == null) { return } + var arr = lineView.changes || (lineView.changes = []); + if (indexOf(arr, type) == -1) { arr.push(type); } + } + + // Clear the view. + function resetView(cm) { + cm.display.viewFrom = cm.display.viewTo = cm.doc.first; + cm.display.view = []; + cm.display.viewOffset = 0; + } + + function viewCuttingPoint(cm, oldN, newN, dir) { + var index = findViewIndex(cm, oldN), diff, view = cm.display.view; + if (!sawCollapsedSpans || newN == cm.doc.first + cm.doc.size) + { return {index: index, lineN: newN} } + var n = cm.display.viewFrom; + for (var i = 0; i < index; i++) + { n += view[i].size; } + if (n != oldN) { + if (dir > 0) { + if (index == view.length - 1) { return null } + diff = (n + view[index].size) - oldN; + index++; + } else { + diff = n - oldN; + } + oldN += diff; newN += diff; + } + while (visualLineNo(cm.doc, newN) != newN) { + if (index == (dir < 0 ? 0 : view.length - 1)) { return null } + newN += dir * view[index - (dir < 0 ? 1 : 0)].size; + index += dir; + } + return {index: index, lineN: newN} + } + + // Force the view to cover a given range, adding empty view element + // or clipping off existing ones as needed. + function adjustView(cm, from, to) { + var display = cm.display, view = display.view; + if (view.length == 0 || from >= display.viewTo || to <= display.viewFrom) { + display.view = buildViewArray(cm, from, to); + display.viewFrom = from; + } else { + if (display.viewFrom > from) + { display.view = buildViewArray(cm, from, display.viewFrom).concat(display.view); } + else if (display.viewFrom < from) + { display.view = display.view.slice(findViewIndex(cm, from)); } + display.viewFrom = from; + if (display.viewTo < to) + { display.view = display.view.concat(buildViewArray(cm, display.viewTo, to)); } + else if (display.viewTo > to) + { display.view = display.view.slice(0, findViewIndex(cm, to)); } + } + display.viewTo = to; + } + + // Count the number of lines in the view whose DOM representation is + // out of date (or nonexistent). + function countDirtyView(cm) { + var view = cm.display.view, dirty = 0; + for (var i = 0; i < view.length; i++) { + var lineView = view[i]; + if (!lineView.hidden && (!lineView.node || lineView.changes)) { ++dirty; } + } + return dirty + } + + function updateSelection(cm) { + cm.display.input.showSelection(cm.display.input.prepareSelection()); + } + + function prepareSelection(cm, primary) { + if ( primary === void 0 ) primary = true; + + var doc = cm.doc, result = {}; + var curFragment = result.cursors = document.createDocumentFragment(); + var selFragment = result.selection = document.createDocumentFragment(); + + var customCursor = cm.options.$customCursor; + if (customCursor) { primary = true; } + for (var i = 0; i < doc.sel.ranges.length; i++) { + if (!primary && i == doc.sel.primIndex) { continue } + var range = doc.sel.ranges[i]; + if (range.from().line >= cm.display.viewTo || range.to().line < cm.display.viewFrom) { continue } + var collapsed = range.empty(); + if (customCursor) { + var head = customCursor(cm, range); + if (head) { drawSelectionCursor(cm, head, curFragment); } + } else if (collapsed || cm.options.showCursorWhenSelecting) { + drawSelectionCursor(cm, range.head, curFragment); + } + if (!collapsed) + { drawSelectionRange(cm, range, selFragment); } + } + return result + } + + // Draws a cursor for the given range + function drawSelectionCursor(cm, head, output) { + var pos = cursorCoords(cm, head, "div", null, null, !cm.options.singleCursorHeightPerLine); + + var cursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor")); + cursor.style.left = pos.left + "px"; + cursor.style.top = pos.top + "px"; + cursor.style.height = Math.max(0, pos.bottom - pos.top) * cm.options.cursorHeight + "px"; + + if (/\bcm-fat-cursor\b/.test(cm.getWrapperElement().className)) { + var charPos = charCoords(cm, head, "div", null, null); + var width = charPos.right - charPos.left; + cursor.style.width = (width > 0 ? width : cm.defaultCharWidth()) + "px"; + } + + if (pos.other) { + // Secondary cursor, shown when on a 'jump' in bi-directional text + var otherCursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor CodeMirror-secondarycursor")); + otherCursor.style.display = ""; + otherCursor.style.left = pos.other.left + "px"; + otherCursor.style.top = pos.other.top + "px"; + otherCursor.style.height = (pos.other.bottom - pos.other.top) * .85 + "px"; + } + } + + function cmpCoords(a, b) { return a.top - b.top || a.left - b.left } + + // Draws the given range as a highlighted selection + function drawSelectionRange(cm, range, output) { + var display = cm.display, doc = cm.doc; + var fragment = document.createDocumentFragment(); + var padding = paddingH(cm.display), leftSide = padding.left; + var rightSide = Math.max(display.sizerWidth, displayWidth(cm) - display.sizer.offsetLeft) - padding.right; + var docLTR = doc.direction == "ltr"; + + function add(left, top, width, bottom) { + if (top < 0) { top = 0; } + top = Math.round(top); + bottom = Math.round(bottom); + fragment.appendChild(elt("div", null, "CodeMirror-selected", ("position: absolute; left: " + left + "px;\n top: " + top + "px; width: " + (width == null ? rightSide - left : width) + "px;\n height: " + (bottom - top) + "px"))); + } + + function drawForLine(line, fromArg, toArg) { + var lineObj = getLine(doc, line); + var lineLen = lineObj.text.length; + var start, end; + function coords(ch, bias) { + return charCoords(cm, Pos(line, ch), "div", lineObj, bias) + } + + function wrapX(pos, dir, side) { + var extent = wrappedLineExtentChar(cm, lineObj, null, pos); + var prop = (dir == "ltr") == (side == "after") ? "left" : "right"; + var ch = side == "after" ? extent.begin : extent.end - (/\s/.test(lineObj.text.charAt(extent.end - 1)) ? 2 : 1); + return coords(ch, prop)[prop] + } + + var order = getOrder(lineObj, doc.direction); + iterateBidiSections(order, fromArg || 0, toArg == null ? lineLen : toArg, function (from, to, dir, i) { + var ltr = dir == "ltr"; + var fromPos = coords(from, ltr ? "left" : "right"); + var toPos = coords(to - 1, ltr ? "right" : "left"); + + var openStart = fromArg == null && from == 0, openEnd = toArg == null && to == lineLen; + var first = i == 0, last = !order || i == order.length - 1; + if (toPos.top - fromPos.top <= 3) { // Single line + var openLeft = (docLTR ? openStart : openEnd) && first; + var openRight = (docLTR ? openEnd : openStart) && last; + var left = openLeft ? leftSide : (ltr ? fromPos : toPos).left; + var right = openRight ? rightSide : (ltr ? toPos : fromPos).right; + add(left, fromPos.top, right - left, fromPos.bottom); + } else { // Multiple lines + var topLeft, topRight, botLeft, botRight; + if (ltr) { + topLeft = docLTR && openStart && first ? leftSide : fromPos.left; + topRight = docLTR ? rightSide : wrapX(from, dir, "before"); + botLeft = docLTR ? leftSide : wrapX(to, dir, "after"); + botRight = docLTR && openEnd && last ? rightSide : toPos.right; + } else { + topLeft = !docLTR ? leftSide : wrapX(from, dir, "before"); + topRight = !docLTR && openStart && first ? rightSide : fromPos.right; + botLeft = !docLTR && openEnd && last ? leftSide : toPos.left; + botRight = !docLTR ? rightSide : wrapX(to, dir, "after"); + } + add(topLeft, fromPos.top, topRight - topLeft, fromPos.bottom); + if (fromPos.bottom < toPos.top) { add(leftSide, fromPos.bottom, null, toPos.top); } + add(botLeft, toPos.top, botRight - botLeft, toPos.bottom); + } + + if (!start || cmpCoords(fromPos, start) < 0) { start = fromPos; } + if (cmpCoords(toPos, start) < 0) { start = toPos; } + if (!end || cmpCoords(fromPos, end) < 0) { end = fromPos; } + if (cmpCoords(toPos, end) < 0) { end = toPos; } + }); + return {start: start, end: end} + } + + var sFrom = range.from(), sTo = range.to(); + if (sFrom.line == sTo.line) { + drawForLine(sFrom.line, sFrom.ch, sTo.ch); + } else { + var fromLine = getLine(doc, sFrom.line), toLine = getLine(doc, sTo.line); + var singleVLine = visualLine(fromLine) == visualLine(toLine); + var leftEnd = drawForLine(sFrom.line, sFrom.ch, singleVLine ? fromLine.text.length + 1 : null).end; + var rightStart = drawForLine(sTo.line, singleVLine ? 0 : null, sTo.ch).start; + if (singleVLine) { + if (leftEnd.top < rightStart.top - 2) { + add(leftEnd.right, leftEnd.top, null, leftEnd.bottom); + add(leftSide, rightStart.top, rightStart.left, rightStart.bottom); + } else { + add(leftEnd.right, leftEnd.top, rightStart.left - leftEnd.right, leftEnd.bottom); + } + } + if (leftEnd.bottom < rightStart.top) + { add(leftSide, leftEnd.bottom, null, rightStart.top); } + } + + output.appendChild(fragment); + } + + // Cursor-blinking + function restartBlink(cm) { + if (!cm.state.focused) { return } + var display = cm.display; + clearInterval(display.blinker); + var on = true; + display.cursorDiv.style.visibility = ""; + if (cm.options.cursorBlinkRate > 0) + { display.blinker = setInterval(function () { + if (!cm.hasFocus()) { onBlur(cm); } + display.cursorDiv.style.visibility = (on = !on) ? "" : "hidden"; + }, cm.options.cursorBlinkRate); } + else if (cm.options.cursorBlinkRate < 0) + { display.cursorDiv.style.visibility = "hidden"; } + } + + function ensureFocus(cm) { + if (!cm.hasFocus()) { + cm.display.input.focus(); + if (!cm.state.focused) { onFocus(cm); } + } + } + + function delayBlurEvent(cm) { + cm.state.delayingBlurEvent = true; + setTimeout(function () { if (cm.state.delayingBlurEvent) { + cm.state.delayingBlurEvent = false; + if (cm.state.focused) { onBlur(cm); } + } }, 100); + } + + function onFocus(cm, e) { + if (cm.state.delayingBlurEvent && !cm.state.draggingText) { cm.state.delayingBlurEvent = false; } + + if (cm.options.readOnly == "nocursor") { return } + if (!cm.state.focused) { + signal(cm, "focus", cm, e); + cm.state.focused = true; + addClass(cm.display.wrapper, "CodeMirror-focused"); + // This test prevents this from firing when a context + // menu is closed (since the input reset would kill the + // select-all detection hack) + if (!cm.curOp && cm.display.selForContextMenu != cm.doc.sel) { + cm.display.input.reset(); + if (webkit) { setTimeout(function () { return cm.display.input.reset(true); }, 20); } // Issue #1730 + } + cm.display.input.receivedFocus(); + } + restartBlink(cm); + } + function onBlur(cm, e) { + if (cm.state.delayingBlurEvent) { return } + + if (cm.state.focused) { + signal(cm, "blur", cm, e); + cm.state.focused = false; + rmClass(cm.display.wrapper, "CodeMirror-focused"); + } + clearInterval(cm.display.blinker); + setTimeout(function () { if (!cm.state.focused) { cm.display.shift = false; } }, 150); + } + + // Read the actual heights of the rendered lines, and update their + // stored heights to match. + function updateHeightsInViewport(cm) { + var display = cm.display; + var prevBottom = display.lineDiv.offsetTop; + var viewTop = Math.max(0, display.scroller.getBoundingClientRect().top); + var oldHeight = display.lineDiv.getBoundingClientRect().top; + var mustScroll = 0; + for (var i = 0; i < display.view.length; i++) { + var cur = display.view[i], wrapping = cm.options.lineWrapping; + var height = (void 0), width = 0; + if (cur.hidden) { continue } + oldHeight += cur.line.height; + if (ie && ie_version < 8) { + var bot = cur.node.offsetTop + cur.node.offsetHeight; + height = bot - prevBottom; + prevBottom = bot; + } else { + var box = cur.node.getBoundingClientRect(); + height = box.bottom - box.top; + // Check that lines don't extend past the right of the current + // editor width + if (!wrapping && cur.text.firstChild) + { width = cur.text.firstChild.getBoundingClientRect().right - box.left - 1; } + } + var diff = cur.line.height - height; + if (diff > .005 || diff < -.005) { + if (oldHeight < viewTop) { mustScroll -= diff; } + updateLineHeight(cur.line, height); + updateWidgetHeight(cur.line); + if (cur.rest) { for (var j = 0; j < cur.rest.length; j++) + { updateWidgetHeight(cur.rest[j]); } } + } + if (width > cm.display.sizerWidth) { + var chWidth = Math.ceil(width / charWidth(cm.display)); + if (chWidth > cm.display.maxLineLength) { + cm.display.maxLineLength = chWidth; + cm.display.maxLine = cur.line; + cm.display.maxLineChanged = true; + } + } + } + if (Math.abs(mustScroll) > 2) { display.scroller.scrollTop += mustScroll; } + } + + // Read and store the height of line widgets associated with the + // given line. + function updateWidgetHeight(line) { + if (line.widgets) { for (var i = 0; i < line.widgets.length; ++i) { + var w = line.widgets[i], parent = w.node.parentNode; + if (parent) { w.height = parent.offsetHeight; } + } } + } + + // Compute the lines that are visible in a given viewport (defaults + // the the current scroll position). viewport may contain top, + // height, and ensure (see op.scrollToPos) properties. + function visibleLines(display, doc, viewport) { + var top = viewport && viewport.top != null ? Math.max(0, viewport.top) : display.scroller.scrollTop; + top = Math.floor(top - paddingTop(display)); + var bottom = viewport && viewport.bottom != null ? viewport.bottom : top + display.wrapper.clientHeight; + + var from = lineAtHeight(doc, top), to = lineAtHeight(doc, bottom); + // Ensure is a {from: {line, ch}, to: {line, ch}} object, and + // forces those lines into the viewport (if possible). + if (viewport && viewport.ensure) { + var ensureFrom = viewport.ensure.from.line, ensureTo = viewport.ensure.to.line; + if (ensureFrom < from) { + from = ensureFrom; + to = lineAtHeight(doc, heightAtLine(getLine(doc, ensureFrom)) + display.wrapper.clientHeight); + } else if (Math.min(ensureTo, doc.lastLine()) >= to) { + from = lineAtHeight(doc, heightAtLine(getLine(doc, ensureTo)) - display.wrapper.clientHeight); + to = ensureTo; + } + } + return {from: from, to: Math.max(to, from + 1)} + } + + // SCROLLING THINGS INTO VIEW + + // If an editor sits on the top or bottom of the window, partially + // scrolled out of view, this ensures that the cursor is visible. + function maybeScrollWindow(cm, rect) { + if (signalDOMEvent(cm, "scrollCursorIntoView")) { return } + + var display = cm.display, box = display.sizer.getBoundingClientRect(), doScroll = null; + var doc = display.wrapper.ownerDocument; + if (rect.top + box.top < 0) { doScroll = true; } + else if (rect.bottom + box.top > (doc.defaultView.innerHeight || doc.documentElement.clientHeight)) { doScroll = false; } + if (doScroll != null && !phantom) { + var scrollNode = elt("div", "\u200b", null, ("position: absolute;\n top: " + (rect.top - display.viewOffset - paddingTop(cm.display)) + "px;\n height: " + (rect.bottom - rect.top + scrollGap(cm) + display.barHeight) + "px;\n left: " + (rect.left) + "px; width: " + (Math.max(2, rect.right - rect.left)) + "px;")); + cm.display.lineSpace.appendChild(scrollNode); + scrollNode.scrollIntoView(doScroll); + cm.display.lineSpace.removeChild(scrollNode); + } + } + + // Scroll a given position into view (immediately), verifying that + // it actually became visible (as line heights are accurately + // measured, the position of something may 'drift' during drawing). + function scrollPosIntoView(cm, pos, end, margin) { + if (margin == null) { margin = 0; } + var rect; + if (!cm.options.lineWrapping && pos == end) { + // Set pos and end to the cursor positions around the character pos sticks to + // If pos.sticky == "before", that is around pos.ch - 1, otherwise around pos.ch + // If pos == Pos(_, 0, "before"), pos and end are unchanged + end = pos.sticky == "before" ? Pos(pos.line, pos.ch + 1, "before") : pos; + pos = pos.ch ? Pos(pos.line, pos.sticky == "before" ? pos.ch - 1 : pos.ch, "after") : pos; + } + for (var limit = 0; limit < 5; limit++) { + var changed = false; + var coords = cursorCoords(cm, pos); + var endCoords = !end || end == pos ? coords : cursorCoords(cm, end); + rect = {left: Math.min(coords.left, endCoords.left), + top: Math.min(coords.top, endCoords.top) - margin, + right: Math.max(coords.left, endCoords.left), + bottom: Math.max(coords.bottom, endCoords.bottom) + margin}; + var scrollPos = calculateScrollPos(cm, rect); + var startTop = cm.doc.scrollTop, startLeft = cm.doc.scrollLeft; + if (scrollPos.scrollTop != null) { + updateScrollTop(cm, scrollPos.scrollTop); + if (Math.abs(cm.doc.scrollTop - startTop) > 1) { changed = true; } + } + if (scrollPos.scrollLeft != null) { + setScrollLeft(cm, scrollPos.scrollLeft); + if (Math.abs(cm.doc.scrollLeft - startLeft) > 1) { changed = true; } + } + if (!changed) { break } + } + return rect + } + + // Scroll a given set of coordinates into view (immediately). + function scrollIntoView(cm, rect) { + var scrollPos = calculateScrollPos(cm, rect); + if (scrollPos.scrollTop != null) { updateScrollTop(cm, scrollPos.scrollTop); } + if (scrollPos.scrollLeft != null) { setScrollLeft(cm, scrollPos.scrollLeft); } + } + + // Calculate a new scroll position needed to scroll the given + // rectangle into view. Returns an object with scrollTop and + // scrollLeft properties. When these are undefined, the + // vertical/horizontal position does not need to be adjusted. + function calculateScrollPos(cm, rect) { + var display = cm.display, snapMargin = textHeight(cm.display); + if (rect.top < 0) { rect.top = 0; } + var screentop = cm.curOp && cm.curOp.scrollTop != null ? cm.curOp.scrollTop : display.scroller.scrollTop; + var screen = displayHeight(cm), result = {}; + if (rect.bottom - rect.top > screen) { rect.bottom = rect.top + screen; } + var docBottom = cm.doc.height + paddingVert(display); + var atTop = rect.top < snapMargin, atBottom = rect.bottom > docBottom - snapMargin; + if (rect.top < screentop) { + result.scrollTop = atTop ? 0 : rect.top; + } else if (rect.bottom > screentop + screen) { + var newTop = Math.min(rect.top, (atBottom ? docBottom : rect.bottom) - screen); + if (newTop != screentop) { result.scrollTop = newTop; } + } + + var gutterSpace = cm.options.fixedGutter ? 0 : display.gutters.offsetWidth; + var screenleft = cm.curOp && cm.curOp.scrollLeft != null ? cm.curOp.scrollLeft : display.scroller.scrollLeft - gutterSpace; + var screenw = displayWidth(cm) - display.gutters.offsetWidth; + var tooWide = rect.right - rect.left > screenw; + if (tooWide) { rect.right = rect.left + screenw; } + if (rect.left < 10) + { result.scrollLeft = 0; } + else if (rect.left < screenleft) + { result.scrollLeft = Math.max(0, rect.left + gutterSpace - (tooWide ? 0 : 10)); } + else if (rect.right > screenw + screenleft - 3) + { result.scrollLeft = rect.right + (tooWide ? 0 : 10) - screenw; } + return result + } + + // Store a relative adjustment to the scroll position in the current + // operation (to be applied when the operation finishes). + function addToScrollTop(cm, top) { + if (top == null) { return } + resolveScrollToPos(cm); + cm.curOp.scrollTop = (cm.curOp.scrollTop == null ? cm.doc.scrollTop : cm.curOp.scrollTop) + top; + } + + // Make sure that at the end of the operation the current cursor is + // shown. + function ensureCursorVisible(cm) { + resolveScrollToPos(cm); + var cur = cm.getCursor(); + cm.curOp.scrollToPos = {from: cur, to: cur, margin: cm.options.cursorScrollMargin}; + } + + function scrollToCoords(cm, x, y) { + if (x != null || y != null) { resolveScrollToPos(cm); } + if (x != null) { cm.curOp.scrollLeft = x; } + if (y != null) { cm.curOp.scrollTop = y; } + } + + function scrollToRange(cm, range) { + resolveScrollToPos(cm); + cm.curOp.scrollToPos = range; + } + + // When an operation has its scrollToPos property set, and another + // scroll action is applied before the end of the operation, this + // 'simulates' scrolling that position into view in a cheap way, so + // that the effect of intermediate scroll commands is not ignored. + function resolveScrollToPos(cm) { + var range = cm.curOp.scrollToPos; + if (range) { + cm.curOp.scrollToPos = null; + var from = estimateCoords(cm, range.from), to = estimateCoords(cm, range.to); + scrollToCoordsRange(cm, from, to, range.margin); + } + } + + function scrollToCoordsRange(cm, from, to, margin) { + var sPos = calculateScrollPos(cm, { + left: Math.min(from.left, to.left), + top: Math.min(from.top, to.top) - margin, + right: Math.max(from.right, to.right), + bottom: Math.max(from.bottom, to.bottom) + margin + }); + scrollToCoords(cm, sPos.scrollLeft, sPos.scrollTop); + } + + // Sync the scrollable area and scrollbars, ensure the viewport + // covers the visible area. + function updateScrollTop(cm, val) { + if (Math.abs(cm.doc.scrollTop - val) < 2) { return } + if (!gecko) { updateDisplaySimple(cm, {top: val}); } + setScrollTop(cm, val, true); + if (gecko) { updateDisplaySimple(cm); } + startWorker(cm, 100); + } + + function setScrollTop(cm, val, forceScroll) { + val = Math.max(0, Math.min(cm.display.scroller.scrollHeight - cm.display.scroller.clientHeight, val)); + if (cm.display.scroller.scrollTop == val && !forceScroll) { return } + cm.doc.scrollTop = val; + cm.display.scrollbars.setScrollTop(val); + if (cm.display.scroller.scrollTop != val) { cm.display.scroller.scrollTop = val; } + } + + // Sync scroller and scrollbar, ensure the gutter elements are + // aligned. + function setScrollLeft(cm, val, isScroller, forceScroll) { + val = Math.max(0, Math.min(val, cm.display.scroller.scrollWidth - cm.display.scroller.clientWidth)); + if ((isScroller ? val == cm.doc.scrollLeft : Math.abs(cm.doc.scrollLeft - val) < 2) && !forceScroll) { return } + cm.doc.scrollLeft = val; + alignHorizontally(cm); + if (cm.display.scroller.scrollLeft != val) { cm.display.scroller.scrollLeft = val; } + cm.display.scrollbars.setScrollLeft(val); + } + + // SCROLLBARS + + // Prepare DOM reads needed to update the scrollbars. Done in one + // shot to minimize update/measure roundtrips. + function measureForScrollbars(cm) { + var d = cm.display, gutterW = d.gutters.offsetWidth; + var docH = Math.round(cm.doc.height + paddingVert(cm.display)); + return { + clientHeight: d.scroller.clientHeight, + viewHeight: d.wrapper.clientHeight, + scrollWidth: d.scroller.scrollWidth, clientWidth: d.scroller.clientWidth, + viewWidth: d.wrapper.clientWidth, + barLeft: cm.options.fixedGutter ? gutterW : 0, + docHeight: docH, + scrollHeight: docH + scrollGap(cm) + d.barHeight, + nativeBarWidth: d.nativeBarWidth, + gutterWidth: gutterW + } + } + + var NativeScrollbars = function(place, scroll, cm) { + this.cm = cm; + var vert = this.vert = elt("div", [elt("div", null, null, "min-width: 1px")], "CodeMirror-vscrollbar"); + var horiz = this.horiz = elt("div", [elt("div", null, null, "height: 100%; min-height: 1px")], "CodeMirror-hscrollbar"); + vert.tabIndex = horiz.tabIndex = -1; + place(vert); place(horiz); + + on(vert, "scroll", function () { + if (vert.clientHeight) { scroll(vert.scrollTop, "vertical"); } + }); + on(horiz, "scroll", function () { + if (horiz.clientWidth) { scroll(horiz.scrollLeft, "horizontal"); } + }); + + this.checkedZeroWidth = false; + // Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8). + if (ie && ie_version < 8) { this.horiz.style.minHeight = this.vert.style.minWidth = "18px"; } + }; + + NativeScrollbars.prototype.update = function (measure) { + var needsH = measure.scrollWidth > measure.clientWidth + 1; + var needsV = measure.scrollHeight > measure.clientHeight + 1; + var sWidth = measure.nativeBarWidth; + + if (needsV) { + this.vert.style.display = "block"; + this.vert.style.bottom = needsH ? sWidth + "px" : "0"; + var totalHeight = measure.viewHeight - (needsH ? sWidth : 0); + // A bug in IE8 can cause this value to be negative, so guard it. + this.vert.firstChild.style.height = + Math.max(0, measure.scrollHeight - measure.clientHeight + totalHeight) + "px"; + } else { + this.vert.scrollTop = 0; + this.vert.style.display = ""; + this.vert.firstChild.style.height = "0"; + } + + if (needsH) { + this.horiz.style.display = "block"; + this.horiz.style.right = needsV ? sWidth + "px" : "0"; + this.horiz.style.left = measure.barLeft + "px"; + var totalWidth = measure.viewWidth - measure.barLeft - (needsV ? sWidth : 0); + this.horiz.firstChild.style.width = + Math.max(0, measure.scrollWidth - measure.clientWidth + totalWidth) + "px"; + } else { + this.horiz.style.display = ""; + this.horiz.firstChild.style.width = "0"; + } + + if (!this.checkedZeroWidth && measure.clientHeight > 0) { + if (sWidth == 0) { this.zeroWidthHack(); } + this.checkedZeroWidth = true; + } + + return {right: needsV ? sWidth : 0, bottom: needsH ? sWidth : 0} + }; + + NativeScrollbars.prototype.setScrollLeft = function (pos) { + if (this.horiz.scrollLeft != pos) { this.horiz.scrollLeft = pos; } + if (this.disableHoriz) { this.enableZeroWidthBar(this.horiz, this.disableHoriz, "horiz"); } + }; + + NativeScrollbars.prototype.setScrollTop = function (pos) { + if (this.vert.scrollTop != pos) { this.vert.scrollTop = pos; } + if (this.disableVert) { this.enableZeroWidthBar(this.vert, this.disableVert, "vert"); } + }; + + NativeScrollbars.prototype.zeroWidthHack = function () { + var w = mac && !mac_geMountainLion ? "12px" : "18px"; + this.horiz.style.height = this.vert.style.width = w; + this.horiz.style.visibility = this.vert.style.visibility = "hidden"; + this.disableHoriz = new Delayed; + this.disableVert = new Delayed; + }; + + NativeScrollbars.prototype.enableZeroWidthBar = function (bar, delay, type) { + bar.style.visibility = ""; + function maybeDisable() { + // To find out whether the scrollbar is still visible, we + // check whether the element under the pixel in the bottom + // right corner of the scrollbar box is the scrollbar box + // itself (when the bar is still visible) or its filler child + // (when the bar is hidden). If it is still visible, we keep + // it enabled, if it's hidden, we disable pointer events. + var box = bar.getBoundingClientRect(); + var elt = type == "vert" ? document.elementFromPoint(box.right - 1, (box.top + box.bottom) / 2) + : document.elementFromPoint((box.right + box.left) / 2, box.bottom - 1); + if (elt != bar) { bar.style.visibility = "hidden"; } + else { delay.set(1000, maybeDisable); } + } + delay.set(1000, maybeDisable); + }; + + NativeScrollbars.prototype.clear = function () { + var parent = this.horiz.parentNode; + parent.removeChild(this.horiz); + parent.removeChild(this.vert); + }; + + var NullScrollbars = function () {}; + + NullScrollbars.prototype.update = function () { return {bottom: 0, right: 0} }; + NullScrollbars.prototype.setScrollLeft = function () {}; + NullScrollbars.prototype.setScrollTop = function () {}; + NullScrollbars.prototype.clear = function () {}; + + function updateScrollbars(cm, measure) { + if (!measure) { measure = measureForScrollbars(cm); } + var startWidth = cm.display.barWidth, startHeight = cm.display.barHeight; + updateScrollbarsInner(cm, measure); + for (var i = 0; i < 4 && startWidth != cm.display.barWidth || startHeight != cm.display.barHeight; i++) { + if (startWidth != cm.display.barWidth && cm.options.lineWrapping) + { updateHeightsInViewport(cm); } + updateScrollbarsInner(cm, measureForScrollbars(cm)); + startWidth = cm.display.barWidth; startHeight = cm.display.barHeight; + } + } + + // Re-synchronize the fake scrollbars with the actual size of the + // content. + function updateScrollbarsInner(cm, measure) { + var d = cm.display; + var sizes = d.scrollbars.update(measure); + + d.sizer.style.paddingRight = (d.barWidth = sizes.right) + "px"; + d.sizer.style.paddingBottom = (d.barHeight = sizes.bottom) + "px"; + d.heightForcer.style.borderBottom = sizes.bottom + "px solid transparent"; + + if (sizes.right && sizes.bottom) { + d.scrollbarFiller.style.display = "block"; + d.scrollbarFiller.style.height = sizes.bottom + "px"; + d.scrollbarFiller.style.width = sizes.right + "px"; + } else { d.scrollbarFiller.style.display = ""; } + if (sizes.bottom && cm.options.coverGutterNextToScrollbar && cm.options.fixedGutter) { + d.gutterFiller.style.display = "block"; + d.gutterFiller.style.height = sizes.bottom + "px"; + d.gutterFiller.style.width = measure.gutterWidth + "px"; + } else { d.gutterFiller.style.display = ""; } + } + + var scrollbarModel = {"native": NativeScrollbars, "null": NullScrollbars}; + + function initScrollbars(cm) { + if (cm.display.scrollbars) { + cm.display.scrollbars.clear(); + if (cm.display.scrollbars.addClass) + { rmClass(cm.display.wrapper, cm.display.scrollbars.addClass); } + } + + cm.display.scrollbars = new scrollbarModel[cm.options.scrollbarStyle](function (node) { + cm.display.wrapper.insertBefore(node, cm.display.scrollbarFiller); + // Prevent clicks in the scrollbars from killing focus + on(node, "mousedown", function () { + if (cm.state.focused) { setTimeout(function () { return cm.display.input.focus(); }, 0); } + }); + node.setAttribute("cm-not-content", "true"); + }, function (pos, axis) { + if (axis == "horizontal") { setScrollLeft(cm, pos); } + else { updateScrollTop(cm, pos); } + }, cm); + if (cm.display.scrollbars.addClass) + { addClass(cm.display.wrapper, cm.display.scrollbars.addClass); } + } + + // Operations are used to wrap a series of changes to the editor + // state in such a way that each change won't have to update the + // cursor and display (which would be awkward, slow, and + // error-prone). Instead, display updates are batched and then all + // combined and executed at once. + + var nextOpId = 0; + // Start a new operation. + function startOperation(cm) { + cm.curOp = { + cm: cm, + viewChanged: false, // Flag that indicates that lines might need to be redrawn + startHeight: cm.doc.height, // Used to detect need to update scrollbar + forceUpdate: false, // Used to force a redraw + updateInput: 0, // Whether to reset the input textarea + typing: false, // Whether this reset should be careful to leave existing text (for compositing) + changeObjs: null, // Accumulated changes, for firing change events + cursorActivityHandlers: null, // Set of handlers to fire cursorActivity on + cursorActivityCalled: 0, // Tracks which cursorActivity handlers have been called already + selectionChanged: false, // Whether the selection needs to be redrawn + updateMaxLine: false, // Set when the widest line needs to be determined anew + scrollLeft: null, scrollTop: null, // Intermediate scroll position, not pushed to DOM yet + scrollToPos: null, // Used to scroll to a specific position + focus: false, + id: ++nextOpId, // Unique ID + markArrays: null // Used by addMarkedSpan + }; + pushOperation(cm.curOp); + } + + // Finish an operation, updating the display and signalling delayed events + function endOperation(cm) { + var op = cm.curOp; + if (op) { finishOperation(op, function (group) { + for (var i = 0; i < group.ops.length; i++) + { group.ops[i].cm.curOp = null; } + endOperations(group); + }); } + } + + // The DOM updates done when an operation finishes are batched so + // that the minimum number of relayouts are required. + function endOperations(group) { + var ops = group.ops; + for (var i = 0; i < ops.length; i++) // Read DOM + { endOperation_R1(ops[i]); } + for (var i$1 = 0; i$1 < ops.length; i$1++) // Write DOM (maybe) + { endOperation_W1(ops[i$1]); } + for (var i$2 = 0; i$2 < ops.length; i$2++) // Read DOM + { endOperation_R2(ops[i$2]); } + for (var i$3 = 0; i$3 < ops.length; i$3++) // Write DOM (maybe) + { endOperation_W2(ops[i$3]); } + for (var i$4 = 0; i$4 < ops.length; i$4++) // Read DOM + { endOperation_finish(ops[i$4]); } + } + + function endOperation_R1(op) { + var cm = op.cm, display = cm.display; + maybeClipScrollbars(cm); + if (op.updateMaxLine) { findMaxLine(cm); } + + op.mustUpdate = op.viewChanged || op.forceUpdate || op.scrollTop != null || + op.scrollToPos && (op.scrollToPos.from.line < display.viewFrom || + op.scrollToPos.to.line >= display.viewTo) || + display.maxLineChanged && cm.options.lineWrapping; + op.update = op.mustUpdate && + new DisplayUpdate(cm, op.mustUpdate && {top: op.scrollTop, ensure: op.scrollToPos}, op.forceUpdate); + } + + function endOperation_W1(op) { + op.updatedDisplay = op.mustUpdate && updateDisplayIfNeeded(op.cm, op.update); + } + + function endOperation_R2(op) { + var cm = op.cm, display = cm.display; + if (op.updatedDisplay) { updateHeightsInViewport(cm); } + + op.barMeasure = measureForScrollbars(cm); + + // If the max line changed since it was last measured, measure it, + // and ensure the document's width matches it. + // updateDisplay_W2 will use these properties to do the actual resizing + if (display.maxLineChanged && !cm.options.lineWrapping) { + op.adjustWidthTo = measureChar(cm, display.maxLine, display.maxLine.text.length).left + 3; + cm.display.sizerWidth = op.adjustWidthTo; + op.barMeasure.scrollWidth = + Math.max(display.scroller.clientWidth, display.sizer.offsetLeft + op.adjustWidthTo + scrollGap(cm) + cm.display.barWidth); + op.maxScrollLeft = Math.max(0, display.sizer.offsetLeft + op.adjustWidthTo - displayWidth(cm)); + } + + if (op.updatedDisplay || op.selectionChanged) + { op.preparedSelection = display.input.prepareSelection(); } + } + + function endOperation_W2(op) { + var cm = op.cm; + + if (op.adjustWidthTo != null) { + cm.display.sizer.style.minWidth = op.adjustWidthTo + "px"; + if (op.maxScrollLeft < cm.doc.scrollLeft) + { setScrollLeft(cm, Math.min(cm.display.scroller.scrollLeft, op.maxScrollLeft), true); } + cm.display.maxLineChanged = false; + } + + var takeFocus = op.focus && op.focus == activeElt(doc(cm)); + if (op.preparedSelection) + { cm.display.input.showSelection(op.preparedSelection, takeFocus); } + if (op.updatedDisplay || op.startHeight != cm.doc.height) + { updateScrollbars(cm, op.barMeasure); } + if (op.updatedDisplay) + { setDocumentHeight(cm, op.barMeasure); } + + if (op.selectionChanged) { restartBlink(cm); } + + if (cm.state.focused && op.updateInput) + { cm.display.input.reset(op.typing); } + if (takeFocus) { ensureFocus(op.cm); } + } + + function endOperation_finish(op) { + var cm = op.cm, display = cm.display, doc = cm.doc; + + if (op.updatedDisplay) { postUpdateDisplay(cm, op.update); } + + // Abort mouse wheel delta measurement, when scrolling explicitly + if (display.wheelStartX != null && (op.scrollTop != null || op.scrollLeft != null || op.scrollToPos)) + { display.wheelStartX = display.wheelStartY = null; } + + // Propagate the scroll position to the actual DOM scroller + if (op.scrollTop != null) { setScrollTop(cm, op.scrollTop, op.forceScroll); } + + if (op.scrollLeft != null) { setScrollLeft(cm, op.scrollLeft, true, true); } + // If we need to scroll a specific position into view, do so. + if (op.scrollToPos) { + var rect = scrollPosIntoView(cm, clipPos(doc, op.scrollToPos.from), + clipPos(doc, op.scrollToPos.to), op.scrollToPos.margin); + maybeScrollWindow(cm, rect); + } + + // Fire events for markers that are hidden/unidden by editing or + // undoing + var hidden = op.maybeHiddenMarkers, unhidden = op.maybeUnhiddenMarkers; + if (hidden) { for (var i = 0; i < hidden.length; ++i) + { if (!hidden[i].lines.length) { signal(hidden[i], "hide"); } } } + if (unhidden) { for (var i$1 = 0; i$1 < unhidden.length; ++i$1) + { if (unhidden[i$1].lines.length) { signal(unhidden[i$1], "unhide"); } } } + + if (display.wrapper.offsetHeight) + { doc.scrollTop = cm.display.scroller.scrollTop; } + + // Fire change events, and delayed event handlers + if (op.changeObjs) + { signal(cm, "changes", cm, op.changeObjs); } + if (op.update) + { op.update.finish(); } + } + + // Run the given function in an operation + function runInOp(cm, f) { + if (cm.curOp) { return f() } + startOperation(cm); + try { return f() } + finally { endOperation(cm); } + } + // Wraps a function in an operation. Returns the wrapped function. + function operation(cm, f) { + return function() { + if (cm.curOp) { return f.apply(cm, arguments) } + startOperation(cm); + try { return f.apply(cm, arguments) } + finally { endOperation(cm); } + } + } + // Used to add methods to editor and doc instances, wrapping them in + // operations. + function methodOp(f) { + return function() { + if (this.curOp) { return f.apply(this, arguments) } + startOperation(this); + try { return f.apply(this, arguments) } + finally { endOperation(this); } + } + } + function docMethodOp(f) { + return function() { + var cm = this.cm; + if (!cm || cm.curOp) { return f.apply(this, arguments) } + startOperation(cm); + try { return f.apply(this, arguments) } + finally { endOperation(cm); } + } + } + + // HIGHLIGHT WORKER + + function startWorker(cm, time) { + if (cm.doc.highlightFrontier < cm.display.viewTo) + { cm.state.highlight.set(time, bind(highlightWorker, cm)); } + } + + function highlightWorker(cm) { + var doc = cm.doc; + if (doc.highlightFrontier >= cm.display.viewTo) { return } + var end = +new Date + cm.options.workTime; + var context = getContextBefore(cm, doc.highlightFrontier); + var changedLines = []; + + doc.iter(context.line, Math.min(doc.first + doc.size, cm.display.viewTo + 500), function (line) { + if (context.line >= cm.display.viewFrom) { // Visible + var oldStyles = line.styles; + var resetState = line.text.length > cm.options.maxHighlightLength ? copyState(doc.mode, context.state) : null; + var highlighted = highlightLine(cm, line, context, true); + if (resetState) { context.state = resetState; } + line.styles = highlighted.styles; + var oldCls = line.styleClasses, newCls = highlighted.classes; + if (newCls) { line.styleClasses = newCls; } + else if (oldCls) { line.styleClasses = null; } + var ischange = !oldStyles || oldStyles.length != line.styles.length || + oldCls != newCls && (!oldCls || !newCls || oldCls.bgClass != newCls.bgClass || oldCls.textClass != newCls.textClass); + for (var i = 0; !ischange && i < oldStyles.length; ++i) { ischange = oldStyles[i] != line.styles[i]; } + if (ischange) { changedLines.push(context.line); } + line.stateAfter = context.save(); + context.nextLine(); + } else { + if (line.text.length <= cm.options.maxHighlightLength) + { processLine(cm, line.text, context); } + line.stateAfter = context.line % 5 == 0 ? context.save() : null; + context.nextLine(); + } + if (+new Date > end) { + startWorker(cm, cm.options.workDelay); + return true + } + }); + doc.highlightFrontier = context.line; + doc.modeFrontier = Math.max(doc.modeFrontier, context.line); + if (changedLines.length) { runInOp(cm, function () { + for (var i = 0; i < changedLines.length; i++) + { regLineChange(cm, changedLines[i], "text"); } + }); } + } + + // DISPLAY DRAWING + + var DisplayUpdate = function(cm, viewport, force) { + var display = cm.display; + + this.viewport = viewport; + // Store some values that we'll need later (but don't want to force a relayout for) + this.visible = visibleLines(display, cm.doc, viewport); + this.editorIsHidden = !display.wrapper.offsetWidth; + this.wrapperHeight = display.wrapper.clientHeight; + this.wrapperWidth = display.wrapper.clientWidth; + this.oldDisplayWidth = displayWidth(cm); + this.force = force; + this.dims = getDimensions(cm); + this.events = []; + }; + + DisplayUpdate.prototype.signal = function (emitter, type) { + if (hasHandler(emitter, type)) + { this.events.push(arguments); } + }; + DisplayUpdate.prototype.finish = function () { + for (var i = 0; i < this.events.length; i++) + { signal.apply(null, this.events[i]); } + }; + + function maybeClipScrollbars(cm) { + var display = cm.display; + if (!display.scrollbarsClipped && display.scroller.offsetWidth) { + display.nativeBarWidth = display.scroller.offsetWidth - display.scroller.clientWidth; + display.heightForcer.style.height = scrollGap(cm) + "px"; + display.sizer.style.marginBottom = -display.nativeBarWidth + "px"; + display.sizer.style.borderRightWidth = scrollGap(cm) + "px"; + display.scrollbarsClipped = true; + } + } + + function selectionSnapshot(cm) { + if (cm.hasFocus()) { return null } + var active = activeElt(doc(cm)); + if (!active || !contains(cm.display.lineDiv, active)) { return null } + var result = {activeElt: active}; + if (window.getSelection) { + var sel = win(cm).getSelection(); + if (sel.anchorNode && sel.extend && contains(cm.display.lineDiv, sel.anchorNode)) { + result.anchorNode = sel.anchorNode; + result.anchorOffset = sel.anchorOffset; + result.focusNode = sel.focusNode; + result.focusOffset = sel.focusOffset; + } + } + return result + } + + function restoreSelection(snapshot) { + if (!snapshot || !snapshot.activeElt || snapshot.activeElt == activeElt(snapshot.activeElt.ownerDocument)) { return } + snapshot.activeElt.focus(); + if (!/^(INPUT|TEXTAREA)$/.test(snapshot.activeElt.nodeName) && + snapshot.anchorNode && contains(document.body, snapshot.anchorNode) && contains(document.body, snapshot.focusNode)) { + var doc = snapshot.activeElt.ownerDocument; + var sel = doc.defaultView.getSelection(), range = doc.createRange(); + range.setEnd(snapshot.anchorNode, snapshot.anchorOffset); + range.collapse(false); + sel.removeAllRanges(); + sel.addRange(range); + sel.extend(snapshot.focusNode, snapshot.focusOffset); + } + } + + // Does the actual updating of the line display. Bails out + // (returning false) when there is nothing to be done and forced is + // false. + function updateDisplayIfNeeded(cm, update) { + var display = cm.display, doc = cm.doc; + + if (update.editorIsHidden) { + resetView(cm); + return false + } + + // Bail out if the visible area is already rendered and nothing changed. + if (!update.force && + update.visible.from >= display.viewFrom && update.visible.to <= display.viewTo && + (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo) && + display.renderedView == display.view && countDirtyView(cm) == 0) + { return false } + + if (maybeUpdateLineNumberWidth(cm)) { + resetView(cm); + update.dims = getDimensions(cm); + } + + // Compute a suitable new viewport (from & to) + var end = doc.first + doc.size; + var from = Math.max(update.visible.from - cm.options.viewportMargin, doc.first); + var to = Math.min(end, update.visible.to + cm.options.viewportMargin); + if (display.viewFrom < from && from - display.viewFrom < 20) { from = Math.max(doc.first, display.viewFrom); } + if (display.viewTo > to && display.viewTo - to < 20) { to = Math.min(end, display.viewTo); } + if (sawCollapsedSpans) { + from = visualLineNo(cm.doc, from); + to = visualLineEndNo(cm.doc, to); + } + + var different = from != display.viewFrom || to != display.viewTo || + display.lastWrapHeight != update.wrapperHeight || display.lastWrapWidth != update.wrapperWidth; + adjustView(cm, from, to); + + display.viewOffset = heightAtLine(getLine(cm.doc, display.viewFrom)); + // Position the mover div to align with the current scroll position + cm.display.mover.style.top = display.viewOffset + "px"; + + var toUpdate = countDirtyView(cm); + if (!different && toUpdate == 0 && !update.force && display.renderedView == display.view && + (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo)) + { return false } + + // For big changes, we hide the enclosing element during the + // update, since that speeds up the operations on most browsers. + var selSnapshot = selectionSnapshot(cm); + if (toUpdate > 4) { display.lineDiv.style.display = "none"; } + patchDisplay(cm, display.updateLineNumbers, update.dims); + if (toUpdate > 4) { display.lineDiv.style.display = ""; } + display.renderedView = display.view; + // There might have been a widget with a focused element that got + // hidden or updated, if so re-focus it. + restoreSelection(selSnapshot); + + // Prevent selection and cursors from interfering with the scroll + // width and height. + removeChildren(display.cursorDiv); + removeChildren(display.selectionDiv); + display.gutters.style.height = display.sizer.style.minHeight = 0; + + if (different) { + display.lastWrapHeight = update.wrapperHeight; + display.lastWrapWidth = update.wrapperWidth; + startWorker(cm, 400); + } + + display.updateLineNumbers = null; + + return true + } + + function postUpdateDisplay(cm, update) { + var viewport = update.viewport; + + for (var first = true;; first = false) { + if (!first || !cm.options.lineWrapping || update.oldDisplayWidth == displayWidth(cm)) { + // Clip forced viewport to actual scrollable area. + if (viewport && viewport.top != null) + { viewport = {top: Math.min(cm.doc.height + paddingVert(cm.display) - displayHeight(cm), viewport.top)}; } + // Updated line heights might result in the drawn area not + // actually covering the viewport. Keep looping until it does. + update.visible = visibleLines(cm.display, cm.doc, viewport); + if (update.visible.from >= cm.display.viewFrom && update.visible.to <= cm.display.viewTo) + { break } + } else if (first) { + update.visible = visibleLines(cm.display, cm.doc, viewport); + } + if (!updateDisplayIfNeeded(cm, update)) { break } + updateHeightsInViewport(cm); + var barMeasure = measureForScrollbars(cm); + updateSelection(cm); + updateScrollbars(cm, barMeasure); + setDocumentHeight(cm, barMeasure); + update.force = false; + } + + update.signal(cm, "update", cm); + if (cm.display.viewFrom != cm.display.reportedViewFrom || cm.display.viewTo != cm.display.reportedViewTo) { + update.signal(cm, "viewportChange", cm, cm.display.viewFrom, cm.display.viewTo); + cm.display.reportedViewFrom = cm.display.viewFrom; cm.display.reportedViewTo = cm.display.viewTo; + } + } + + function updateDisplaySimple(cm, viewport) { + var update = new DisplayUpdate(cm, viewport); + if (updateDisplayIfNeeded(cm, update)) { + updateHeightsInViewport(cm); + postUpdateDisplay(cm, update); + var barMeasure = measureForScrollbars(cm); + updateSelection(cm); + updateScrollbars(cm, barMeasure); + setDocumentHeight(cm, barMeasure); + update.finish(); + } + } + + // Sync the actual display DOM structure with display.view, removing + // nodes for lines that are no longer in view, and creating the ones + // that are not there yet, and updating the ones that are out of + // date. + function patchDisplay(cm, updateNumbersFrom, dims) { + var display = cm.display, lineNumbers = cm.options.lineNumbers; + var container = display.lineDiv, cur = container.firstChild; + + function rm(node) { + var next = node.nextSibling; + // Works around a throw-scroll bug in OS X Webkit + if (webkit && mac && cm.display.currentWheelTarget == node) + { node.style.display = "none"; } + else + { node.parentNode.removeChild(node); } + return next + } + + var view = display.view, lineN = display.viewFrom; + // Loop over the elements in the view, syncing cur (the DOM nodes + // in display.lineDiv) with the view as we go. + for (var i = 0; i < view.length; i++) { + var lineView = view[i]; + if (lineView.hidden) ; else if (!lineView.node || lineView.node.parentNode != container) { // Not drawn yet + var node = buildLineElement(cm, lineView, lineN, dims); + container.insertBefore(node, cur); + } else { // Already drawn + while (cur != lineView.node) { cur = rm(cur); } + var updateNumber = lineNumbers && updateNumbersFrom != null && + updateNumbersFrom <= lineN && lineView.lineNumber; + if (lineView.changes) { + if (indexOf(lineView.changes, "gutter") > -1) { updateNumber = false; } + updateLineForChanges(cm, lineView, lineN, dims); + } + if (updateNumber) { + removeChildren(lineView.lineNumber); + lineView.lineNumber.appendChild(document.createTextNode(lineNumberFor(cm.options, lineN))); + } + cur = lineView.node.nextSibling; + } + lineN += lineView.size; + } + while (cur) { cur = rm(cur); } + } + + function updateGutterSpace(display) { + var width = display.gutters.offsetWidth; + display.sizer.style.marginLeft = width + "px"; + // Send an event to consumers responding to changes in gutter width. + signalLater(display, "gutterChanged", display); + } + + function setDocumentHeight(cm, measure) { + cm.display.sizer.style.minHeight = measure.docHeight + "px"; + cm.display.heightForcer.style.top = measure.docHeight + "px"; + cm.display.gutters.style.height = (measure.docHeight + cm.display.barHeight + scrollGap(cm)) + "px"; + } + + // Re-align line numbers and gutter marks to compensate for + // horizontal scrolling. + function alignHorizontally(cm) { + var display = cm.display, view = display.view; + if (!display.alignWidgets && (!display.gutters.firstChild || !cm.options.fixedGutter)) { return } + var comp = compensateForHScroll(display) - display.scroller.scrollLeft + cm.doc.scrollLeft; + var gutterW = display.gutters.offsetWidth, left = comp + "px"; + for (var i = 0; i < view.length; i++) { if (!view[i].hidden) { + if (cm.options.fixedGutter) { + if (view[i].gutter) + { view[i].gutter.style.left = left; } + if (view[i].gutterBackground) + { view[i].gutterBackground.style.left = left; } + } + var align = view[i].alignable; + if (align) { for (var j = 0; j < align.length; j++) + { align[j].style.left = left; } } + } } + if (cm.options.fixedGutter) + { display.gutters.style.left = (comp + gutterW) + "px"; } + } + + // Used to ensure that the line number gutter is still the right + // size for the current document size. Returns true when an update + // is needed. + function maybeUpdateLineNumberWidth(cm) { + if (!cm.options.lineNumbers) { return false } + var doc = cm.doc, last = lineNumberFor(cm.options, doc.first + doc.size - 1), display = cm.display; + if (last.length != display.lineNumChars) { + var test = display.measure.appendChild(elt("div", [elt("div", last)], + "CodeMirror-linenumber CodeMirror-gutter-elt")); + var innerW = test.firstChild.offsetWidth, padding = test.offsetWidth - innerW; + display.lineGutter.style.width = ""; + display.lineNumInnerWidth = Math.max(innerW, display.lineGutter.offsetWidth - padding) + 1; + display.lineNumWidth = display.lineNumInnerWidth + padding; + display.lineNumChars = display.lineNumInnerWidth ? last.length : -1; + display.lineGutter.style.width = display.lineNumWidth + "px"; + updateGutterSpace(cm.display); + return true + } + return false + } + + function getGutters(gutters, lineNumbers) { + var result = [], sawLineNumbers = false; + for (var i = 0; i < gutters.length; i++) { + var name = gutters[i], style = null; + if (typeof name != "string") { style = name.style; name = name.className; } + if (name == "CodeMirror-linenumbers") { + if (!lineNumbers) { continue } + else { sawLineNumbers = true; } + } + result.push({className: name, style: style}); + } + if (lineNumbers && !sawLineNumbers) { result.push({className: "CodeMirror-linenumbers", style: null}); } + return result + } + + // Rebuild the gutter elements, ensure the margin to the left of the + // code matches their width. + function renderGutters(display) { + var gutters = display.gutters, specs = display.gutterSpecs; + removeChildren(gutters); + display.lineGutter = null; + for (var i = 0; i < specs.length; ++i) { + var ref = specs[i]; + var className = ref.className; + var style = ref.style; + var gElt = gutters.appendChild(elt("div", null, "CodeMirror-gutter " + className)); + if (style) { gElt.style.cssText = style; } + if (className == "CodeMirror-linenumbers") { + display.lineGutter = gElt; + gElt.style.width = (display.lineNumWidth || 1) + "px"; + } + } + gutters.style.display = specs.length ? "" : "none"; + updateGutterSpace(display); + } + + function updateGutters(cm) { + renderGutters(cm.display); + regChange(cm); + alignHorizontally(cm); + } + + // The display handles the DOM integration, both for input reading + // and content drawing. It holds references to DOM nodes and + // display-related state. + + function Display(place, doc, input, options) { + var d = this; + this.input = input; + + // Covers bottom-right square when both scrollbars are present. + d.scrollbarFiller = elt("div", null, "CodeMirror-scrollbar-filler"); + d.scrollbarFiller.setAttribute("cm-not-content", "true"); + // Covers bottom of gutter when coverGutterNextToScrollbar is on + // and h scrollbar is present. + d.gutterFiller = elt("div", null, "CodeMirror-gutter-filler"); + d.gutterFiller.setAttribute("cm-not-content", "true"); + // Will contain the actual code, positioned to cover the viewport. + d.lineDiv = eltP("div", null, "CodeMirror-code"); + // Elements are added to these to represent selection and cursors. + d.selectionDiv = elt("div", null, null, "position: relative; z-index: 1"); + d.cursorDiv = elt("div", null, "CodeMirror-cursors"); + // A visibility: hidden element used to find the size of things. + d.measure = elt("div", null, "CodeMirror-measure"); + // When lines outside of the viewport are measured, they are drawn in this. + d.lineMeasure = elt("div", null, "CodeMirror-measure"); + // Wraps everything that needs to exist inside the vertically-padded coordinate system + d.lineSpace = eltP("div", [d.measure, d.lineMeasure, d.selectionDiv, d.cursorDiv, d.lineDiv], + null, "position: relative; outline: none"); + var lines = eltP("div", [d.lineSpace], "CodeMirror-lines"); + // Moved around its parent to cover visible view. + d.mover = elt("div", [lines], null, "position: relative"); + // Set to the height of the document, allowing scrolling. + d.sizer = elt("div", [d.mover], "CodeMirror-sizer"); + d.sizerWidth = null; + // Behavior of elts with overflow: auto and padding is + // inconsistent across browsers. This is used to ensure the + // scrollable area is big enough. + d.heightForcer = elt("div", null, null, "position: absolute; height: " + scrollerGap + "px; width: 1px;"); + // Will contain the gutters, if any. + d.gutters = elt("div", null, "CodeMirror-gutters"); + d.lineGutter = null; + // Actual scrollable element. + d.scroller = elt("div", [d.sizer, d.heightForcer, d.gutters], "CodeMirror-scroll"); + d.scroller.setAttribute("tabIndex", "-1"); + // The element in which the editor lives. + d.wrapper = elt("div", [d.scrollbarFiller, d.gutterFiller, d.scroller], "CodeMirror"); + // See #6982. FIXME remove when this has been fixed for a while in Chrome + if (chrome && chrome_version >= 105) { d.wrapper.style.clipPath = "inset(0px)"; } + + // This attribute is respected by automatic translation systems such as Google Translate, + // and may also be respected by tools used by human translators. + d.wrapper.setAttribute('translate', 'no'); + + // Work around IE7 z-index bug (not perfect, hence IE7 not really being supported) + if (ie && ie_version < 8) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0; } + if (!webkit && !(gecko && mobile)) { d.scroller.draggable = true; } + + if (place) { + if (place.appendChild) { place.appendChild(d.wrapper); } + else { place(d.wrapper); } + } + + // Current rendered range (may be bigger than the view window). + d.viewFrom = d.viewTo = doc.first; + d.reportedViewFrom = d.reportedViewTo = doc.first; + // Information about the rendered lines. + d.view = []; + d.renderedView = null; + // Holds info about a single rendered line when it was rendered + // for measurement, while not in view. + d.externalMeasured = null; + // Empty space (in pixels) above the view + d.viewOffset = 0; + d.lastWrapHeight = d.lastWrapWidth = 0; + d.updateLineNumbers = null; + + d.nativeBarWidth = d.barHeight = d.barWidth = 0; + d.scrollbarsClipped = false; + + // Used to only resize the line number gutter when necessary (when + // the amount of lines crosses a boundary that makes its width change) + d.lineNumWidth = d.lineNumInnerWidth = d.lineNumChars = null; + // Set to true when a non-horizontal-scrolling line widget is + // added. As an optimization, line widget aligning is skipped when + // this is false. + d.alignWidgets = false; + + d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null; + + // Tracks the maximum line length so that the horizontal scrollbar + // can be kept static when scrolling. + d.maxLine = null; + d.maxLineLength = 0; + d.maxLineChanged = false; + + // Used for measuring wheel scrolling granularity + d.wheelDX = d.wheelDY = d.wheelStartX = d.wheelStartY = null; + + // True when shift is held down. + d.shift = false; + + // Used to track whether anything happened since the context menu + // was opened. + d.selForContextMenu = null; + + d.activeTouch = null; + + d.gutterSpecs = getGutters(options.gutters, options.lineNumbers); + renderGutters(d); + + input.init(d); + } + + // Since the delta values reported on mouse wheel events are + // unstandardized between browsers and even browser versions, and + // generally horribly unpredictable, this code starts by measuring + // the scroll effect that the first few mouse wheel events have, + // and, from that, detects the way it can convert deltas to pixel + // offsets afterwards. + // + // The reason we want to know the amount a wheel event will scroll + // is that it gives us a chance to update the display before the + // actual scrolling happens, reducing flickering. + + var wheelSamples = 0, wheelPixelsPerUnit = null; + // Fill in a browser-detected starting value on browsers where we + // know one. These don't have to be accurate -- the result of them + // being wrong would just be a slight flicker on the first wheel + // scroll (if it is large enough). + if (ie) { wheelPixelsPerUnit = -.53; } + else if (gecko) { wheelPixelsPerUnit = 15; } + else if (chrome) { wheelPixelsPerUnit = -.7; } + else if (safari) { wheelPixelsPerUnit = -1/3; } + + function wheelEventDelta(e) { + var dx = e.wheelDeltaX, dy = e.wheelDeltaY; + if (dx == null && e.detail && e.axis == e.HORIZONTAL_AXIS) { dx = e.detail; } + if (dy == null && e.detail && e.axis == e.VERTICAL_AXIS) { dy = e.detail; } + else if (dy == null) { dy = e.wheelDelta; } + return {x: dx, y: dy} + } + function wheelEventPixels(e) { + var delta = wheelEventDelta(e); + delta.x *= wheelPixelsPerUnit; + delta.y *= wheelPixelsPerUnit; + return delta + } + + function onScrollWheel(cm, e) { + // On Chrome 102, viewport updates somehow stop wheel-based + // scrolling. Turning off pointer events during the scroll seems + // to avoid the issue. + if (chrome && chrome_version == 102) { + if (cm.display.chromeScrollHack == null) { cm.display.sizer.style.pointerEvents = "none"; } + else { clearTimeout(cm.display.chromeScrollHack); } + cm.display.chromeScrollHack = setTimeout(function () { + cm.display.chromeScrollHack = null; + cm.display.sizer.style.pointerEvents = ""; + }, 100); + } + var delta = wheelEventDelta(e), dx = delta.x, dy = delta.y; + var pixelsPerUnit = wheelPixelsPerUnit; + if (e.deltaMode === 0) { + dx = e.deltaX; + dy = e.deltaY; + pixelsPerUnit = 1; + } + + var display = cm.display, scroll = display.scroller; + // Quit if there's nothing to scroll here + var canScrollX = scroll.scrollWidth > scroll.clientWidth; + var canScrollY = scroll.scrollHeight > scroll.clientHeight; + if (!(dx && canScrollX || dy && canScrollY)) { return } + + // Webkit browsers on OS X abort momentum scrolls when the target + // of the scroll event is removed from the scrollable element. + // This hack (see related code in patchDisplay) makes sure the + // element is kept around. + if (dy && mac && webkit) { + outer: for (var cur = e.target, view = display.view; cur != scroll; cur = cur.parentNode) { + for (var i = 0; i < view.length; i++) { + if (view[i].node == cur) { + cm.display.currentWheelTarget = cur; + break outer + } + } + } + } + + // On some browsers, horizontal scrolling will cause redraws to + // happen before the gutter has been realigned, causing it to + // wriggle around in a most unseemly way. When we have an + // estimated pixels/delta value, we just handle horizontal + // scrolling entirely here. It'll be slightly off from native, but + // better than glitching out. + if (dx && !gecko && !presto && pixelsPerUnit != null) { + if (dy && canScrollY) + { updateScrollTop(cm, Math.max(0, scroll.scrollTop + dy * pixelsPerUnit)); } + setScrollLeft(cm, Math.max(0, scroll.scrollLeft + dx * pixelsPerUnit)); + // Only prevent default scrolling if vertical scrolling is + // actually possible. Otherwise, it causes vertical scroll + // jitter on OSX trackpads when deltaX is small and deltaY + // is large (issue #3579) + if (!dy || (dy && canScrollY)) + { e_preventDefault(e); } + display.wheelStartX = null; // Abort measurement, if in progress + return + } + + // 'Project' the visible viewport to cover the area that is being + // scrolled into view (if we know enough to estimate it). + if (dy && pixelsPerUnit != null) { + var pixels = dy * pixelsPerUnit; + var top = cm.doc.scrollTop, bot = top + display.wrapper.clientHeight; + if (pixels < 0) { top = Math.max(0, top + pixels - 50); } + else { bot = Math.min(cm.doc.height, bot + pixels + 50); } + updateDisplaySimple(cm, {top: top, bottom: bot}); + } + + if (wheelSamples < 20 && e.deltaMode !== 0) { + if (display.wheelStartX == null) { + display.wheelStartX = scroll.scrollLeft; display.wheelStartY = scroll.scrollTop; + display.wheelDX = dx; display.wheelDY = dy; + setTimeout(function () { + if (display.wheelStartX == null) { return } + var movedX = scroll.scrollLeft - display.wheelStartX; + var movedY = scroll.scrollTop - display.wheelStartY; + var sample = (movedY && display.wheelDY && movedY / display.wheelDY) || + (movedX && display.wheelDX && movedX / display.wheelDX); + display.wheelStartX = display.wheelStartY = null; + if (!sample) { return } + wheelPixelsPerUnit = (wheelPixelsPerUnit * wheelSamples + sample) / (wheelSamples + 1); + ++wheelSamples; + }, 200); + } else { + display.wheelDX += dx; display.wheelDY += dy; + } + } + } + + // Selection objects are immutable. A new one is created every time + // the selection changes. A selection is one or more non-overlapping + // (and non-touching) ranges, sorted, and an integer that indicates + // which one is the primary selection (the one that's scrolled into + // view, that getCursor returns, etc). + var Selection = function(ranges, primIndex) { + this.ranges = ranges; + this.primIndex = primIndex; + }; + + Selection.prototype.primary = function () { return this.ranges[this.primIndex] }; + + Selection.prototype.equals = function (other) { + if (other == this) { return true } + if (other.primIndex != this.primIndex || other.ranges.length != this.ranges.length) { return false } + for (var i = 0; i < this.ranges.length; i++) { + var here = this.ranges[i], there = other.ranges[i]; + if (!equalCursorPos(here.anchor, there.anchor) || !equalCursorPos(here.head, there.head)) { return false } + } + return true + }; + + Selection.prototype.deepCopy = function () { + var out = []; + for (var i = 0; i < this.ranges.length; i++) + { out[i] = new Range(copyPos(this.ranges[i].anchor), copyPos(this.ranges[i].head)); } + return new Selection(out, this.primIndex) + }; + + Selection.prototype.somethingSelected = function () { + for (var i = 0; i < this.ranges.length; i++) + { if (!this.ranges[i].empty()) { return true } } + return false + }; + + Selection.prototype.contains = function (pos, end) { + if (!end) { end = pos; } + for (var i = 0; i < this.ranges.length; i++) { + var range = this.ranges[i]; + if (cmp(end, range.from()) >= 0 && cmp(pos, range.to()) <= 0) + { return i } + } + return -1 + }; + + var Range = function(anchor, head) { + this.anchor = anchor; this.head = head; + }; + + Range.prototype.from = function () { return minPos(this.anchor, this.head) }; + Range.prototype.to = function () { return maxPos(this.anchor, this.head) }; + Range.prototype.empty = function () { return this.head.line == this.anchor.line && this.head.ch == this.anchor.ch }; + + // Take an unsorted, potentially overlapping set of ranges, and + // build a selection out of it. 'Consumes' ranges array (modifying + // it). + function normalizeSelection(cm, ranges, primIndex) { + var mayTouch = cm && cm.options.selectionsMayTouch; + var prim = ranges[primIndex]; + ranges.sort(function (a, b) { return cmp(a.from(), b.from()); }); + primIndex = indexOf(ranges, prim); + for (var i = 1; i < ranges.length; i++) { + var cur = ranges[i], prev = ranges[i - 1]; + var diff = cmp(prev.to(), cur.from()); + if (mayTouch && !cur.empty() ? diff > 0 : diff >= 0) { + var from = minPos(prev.from(), cur.from()), to = maxPos(prev.to(), cur.to()); + var inv = prev.empty() ? cur.from() == cur.head : prev.from() == prev.head; + if (i <= primIndex) { --primIndex; } + ranges.splice(--i, 2, new Range(inv ? to : from, inv ? from : to)); + } + } + return new Selection(ranges, primIndex) + } + + function simpleSelection(anchor, head) { + return new Selection([new Range(anchor, head || anchor)], 0) + } + + // Compute the position of the end of a change (its 'to' property + // refers to the pre-change end). + function changeEnd(change) { + if (!change.text) { return change.to } + return Pos(change.from.line + change.text.length - 1, + lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0)) + } + + // Adjust a position to refer to the post-change position of the + // same text, or the end of the change if the change covers it. + function adjustForChange(pos, change) { + if (cmp(pos, change.from) < 0) { return pos } + if (cmp(pos, change.to) <= 0) { return changeEnd(change) } + + var line = pos.line + change.text.length - (change.to.line - change.from.line) - 1, ch = pos.ch; + if (pos.line == change.to.line) { ch += changeEnd(change).ch - change.to.ch; } + return Pos(line, ch) + } + + function computeSelAfterChange(doc, change) { + var out = []; + for (var i = 0; i < doc.sel.ranges.length; i++) { + var range = doc.sel.ranges[i]; + out.push(new Range(adjustForChange(range.anchor, change), + adjustForChange(range.head, change))); + } + return normalizeSelection(doc.cm, out, doc.sel.primIndex) + } + + function offsetPos(pos, old, nw) { + if (pos.line == old.line) + { return Pos(nw.line, pos.ch - old.ch + nw.ch) } + else + { return Pos(nw.line + (pos.line - old.line), pos.ch) } + } + + // Used by replaceSelections to allow moving the selection to the + // start or around the replaced test. Hint may be "start" or "around". + function computeReplacedSel(doc, changes, hint) { + var out = []; + var oldPrev = Pos(doc.first, 0), newPrev = oldPrev; + for (var i = 0; i < changes.length; i++) { + var change = changes[i]; + var from = offsetPos(change.from, oldPrev, newPrev); + var to = offsetPos(changeEnd(change), oldPrev, newPrev); + oldPrev = change.to; + newPrev = to; + if (hint == "around") { + var range = doc.sel.ranges[i], inv = cmp(range.head, range.anchor) < 0; + out[i] = new Range(inv ? to : from, inv ? from : to); + } else { + out[i] = new Range(from, from); + } + } + return new Selection(out, doc.sel.primIndex) + } + + // Used to get the editor into a consistent state again when options change. + + function loadMode(cm) { + cm.doc.mode = getMode(cm.options, cm.doc.modeOption); + resetModeState(cm); + } + + function resetModeState(cm) { + cm.doc.iter(function (line) { + if (line.stateAfter) { line.stateAfter = null; } + if (line.styles) { line.styles = null; } + }); + cm.doc.modeFrontier = cm.doc.highlightFrontier = cm.doc.first; + startWorker(cm, 100); + cm.state.modeGen++; + if (cm.curOp) { regChange(cm); } + } + + // DOCUMENT DATA STRUCTURE + + // By default, updates that start and end at the beginning of a line + // are treated specially, in order to make the association of line + // widgets and marker elements with the text behave more intuitive. + function isWholeLineUpdate(doc, change) { + return change.from.ch == 0 && change.to.ch == 0 && lst(change.text) == "" && + (!doc.cm || doc.cm.options.wholeLineUpdateBefore) + } + + // Perform a change on the document data structure. + function updateDoc(doc, change, markedSpans, estimateHeight) { + function spansFor(n) {return markedSpans ? markedSpans[n] : null} + function update(line, text, spans) { + updateLine(line, text, spans, estimateHeight); + signalLater(line, "change", line, change); + } + function linesFor(start, end) { + var result = []; + for (var i = start; i < end; ++i) + { result.push(new Line(text[i], spansFor(i), estimateHeight)); } + return result + } + + var from = change.from, to = change.to, text = change.text; + var firstLine = getLine(doc, from.line), lastLine = getLine(doc, to.line); + var lastText = lst(text), lastSpans = spansFor(text.length - 1), nlines = to.line - from.line; + + // Adjust the line structure + if (change.full) { + doc.insert(0, linesFor(0, text.length)); + doc.remove(text.length, doc.size - text.length); + } else if (isWholeLineUpdate(doc, change)) { + // This is a whole-line replace. Treated specially to make + // sure line objects move the way they are supposed to. + var added = linesFor(0, text.length - 1); + update(lastLine, lastLine.text, lastSpans); + if (nlines) { doc.remove(from.line, nlines); } + if (added.length) { doc.insert(from.line, added); } + } else if (firstLine == lastLine) { + if (text.length == 1) { + update(firstLine, firstLine.text.slice(0, from.ch) + lastText + firstLine.text.slice(to.ch), lastSpans); + } else { + var added$1 = linesFor(1, text.length - 1); + added$1.push(new Line(lastText + firstLine.text.slice(to.ch), lastSpans, estimateHeight)); + update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0)); + doc.insert(from.line + 1, added$1); + } + } else if (text.length == 1) { + update(firstLine, firstLine.text.slice(0, from.ch) + text[0] + lastLine.text.slice(to.ch), spansFor(0)); + doc.remove(from.line + 1, nlines); + } else { + update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0)); + update(lastLine, lastText + lastLine.text.slice(to.ch), lastSpans); + var added$2 = linesFor(1, text.length - 1); + if (nlines > 1) { doc.remove(from.line + 1, nlines - 1); } + doc.insert(from.line + 1, added$2); + } + + signalLater(doc, "change", doc, change); + } + + // Call f for all linked documents. + function linkedDocs(doc, f, sharedHistOnly) { + function propagate(doc, skip, sharedHist) { + if (doc.linked) { for (var i = 0; i < doc.linked.length; ++i) { + var rel = doc.linked[i]; + if (rel.doc == skip) { continue } + var shared = sharedHist && rel.sharedHist; + if (sharedHistOnly && !shared) { continue } + f(rel.doc, shared); + propagate(rel.doc, doc, shared); + } } + } + propagate(doc, null, true); + } + + // Attach a document to an editor. + function attachDoc(cm, doc) { + if (doc.cm) { throw new Error("This document is already in use.") } + cm.doc = doc; + doc.cm = cm; + estimateLineHeights(cm); + loadMode(cm); + setDirectionClass(cm); + cm.options.direction = doc.direction; + if (!cm.options.lineWrapping) { findMaxLine(cm); } + cm.options.mode = doc.modeOption; + regChange(cm); + } + + function setDirectionClass(cm) { + (cm.doc.direction == "rtl" ? addClass : rmClass)(cm.display.lineDiv, "CodeMirror-rtl"); + } + + function directionChanged(cm) { + runInOp(cm, function () { + setDirectionClass(cm); + regChange(cm); + }); + } + + function History(prev) { + // Arrays of change events and selections. Doing something adds an + // event to done and clears undo. Undoing moves events from done + // to undone, redoing moves them in the other direction. + this.done = []; this.undone = []; + this.undoDepth = prev ? prev.undoDepth : Infinity; + // Used to track when changes can be merged into a single undo + // event + this.lastModTime = this.lastSelTime = 0; + this.lastOp = this.lastSelOp = null; + this.lastOrigin = this.lastSelOrigin = null; + // Used by the isClean() method + this.generation = this.maxGeneration = prev ? prev.maxGeneration : 1; + } + + // Create a history change event from an updateDoc-style change + // object. + function historyChangeFromChange(doc, change) { + var histChange = {from: copyPos(change.from), to: changeEnd(change), text: getBetween(doc, change.from, change.to)}; + attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1); + linkedDocs(doc, function (doc) { return attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1); }, true); + return histChange + } + + // Pop all selection events off the end of a history array. Stop at + // a change event. + function clearSelectionEvents(array) { + while (array.length) { + var last = lst(array); + if (last.ranges) { array.pop(); } + else { break } + } + } + + // Find the top change event in the history. Pop off selection + // events that are in the way. + function lastChangeEvent(hist, force) { + if (force) { + clearSelectionEvents(hist.done); + return lst(hist.done) + } else if (hist.done.length && !lst(hist.done).ranges) { + return lst(hist.done) + } else if (hist.done.length > 1 && !hist.done[hist.done.length - 2].ranges) { + hist.done.pop(); + return lst(hist.done) + } + } + + // Register a change in the history. Merges changes that are within + // a single operation, or are close together with an origin that + // allows merging (starting with "+") into a single event. + function addChangeToHistory(doc, change, selAfter, opId) { + var hist = doc.history; + hist.undone.length = 0; + var time = +new Date, cur; + var last; + + if ((hist.lastOp == opId || + hist.lastOrigin == change.origin && change.origin && + ((change.origin.charAt(0) == "+" && hist.lastModTime > time - (doc.cm ? doc.cm.options.historyEventDelay : 500)) || + change.origin.charAt(0) == "*")) && + (cur = lastChangeEvent(hist, hist.lastOp == opId))) { + // Merge this change into the last event + last = lst(cur.changes); + if (cmp(change.from, change.to) == 0 && cmp(change.from, last.to) == 0) { + // Optimized case for simple insertion -- don't want to add + // new changesets for every character typed + last.to = changeEnd(change); + } else { + // Add new sub-event + cur.changes.push(historyChangeFromChange(doc, change)); + } + } else { + // Can not be merged, start a new event. + var before = lst(hist.done); + if (!before || !before.ranges) + { pushSelectionToHistory(doc.sel, hist.done); } + cur = {changes: [historyChangeFromChange(doc, change)], + generation: hist.generation}; + hist.done.push(cur); + while (hist.done.length > hist.undoDepth) { + hist.done.shift(); + if (!hist.done[0].ranges) { hist.done.shift(); } + } + } + hist.done.push(selAfter); + hist.generation = ++hist.maxGeneration; + hist.lastModTime = hist.lastSelTime = time; + hist.lastOp = hist.lastSelOp = opId; + hist.lastOrigin = hist.lastSelOrigin = change.origin; + + if (!last) { signal(doc, "historyAdded"); } + } + + function selectionEventCanBeMerged(doc, origin, prev, sel) { + var ch = origin.charAt(0); + return ch == "*" || + ch == "+" && + prev.ranges.length == sel.ranges.length && + prev.somethingSelected() == sel.somethingSelected() && + new Date - doc.history.lastSelTime <= (doc.cm ? doc.cm.options.historyEventDelay : 500) + } + + // Called whenever the selection changes, sets the new selection as + // the pending selection in the history, and pushes the old pending + // selection into the 'done' array when it was significantly + // different (in number of selected ranges, emptiness, or time). + function addSelectionToHistory(doc, sel, opId, options) { + var hist = doc.history, origin = options && options.origin; + + // A new event is started when the previous origin does not match + // the current, or the origins don't allow matching. Origins + // starting with * are always merged, those starting with + are + // merged when similar and close together in time. + if (opId == hist.lastSelOp || + (origin && hist.lastSelOrigin == origin && + (hist.lastModTime == hist.lastSelTime && hist.lastOrigin == origin || + selectionEventCanBeMerged(doc, origin, lst(hist.done), sel)))) + { hist.done[hist.done.length - 1] = sel; } + else + { pushSelectionToHistory(sel, hist.done); } + + hist.lastSelTime = +new Date; + hist.lastSelOrigin = origin; + hist.lastSelOp = opId; + if (options && options.clearRedo !== false) + { clearSelectionEvents(hist.undone); } + } + + function pushSelectionToHistory(sel, dest) { + var top = lst(dest); + if (!(top && top.ranges && top.equals(sel))) + { dest.push(sel); } + } + + // Used to store marked span information in the history. + function attachLocalSpans(doc, change, from, to) { + var existing = change["spans_" + doc.id], n = 0; + doc.iter(Math.max(doc.first, from), Math.min(doc.first + doc.size, to), function (line) { + if (line.markedSpans) + { (existing || (existing = change["spans_" + doc.id] = {}))[n] = line.markedSpans; } + ++n; + }); + } + + // When un/re-doing restores text containing marked spans, those + // that have been explicitly cleared should not be restored. + function removeClearedSpans(spans) { + if (!spans) { return null } + var out; + for (var i = 0; i < spans.length; ++i) { + if (spans[i].marker.explicitlyCleared) { if (!out) { out = spans.slice(0, i); } } + else if (out) { out.push(spans[i]); } + } + return !out ? spans : out.length ? out : null + } + + // Retrieve and filter the old marked spans stored in a change event. + function getOldSpans(doc, change) { + var found = change["spans_" + doc.id]; + if (!found) { return null } + var nw = []; + for (var i = 0; i < change.text.length; ++i) + { nw.push(removeClearedSpans(found[i])); } + return nw + } + + // Used for un/re-doing changes from the history. Combines the + // result of computing the existing spans with the set of spans that + // existed in the history (so that deleting around a span and then + // undoing brings back the span). + function mergeOldSpans(doc, change) { + var old = getOldSpans(doc, change); + var stretched = stretchSpansOverChange(doc, change); + if (!old) { return stretched } + if (!stretched) { return old } + + for (var i = 0; i < old.length; ++i) { + var oldCur = old[i], stretchCur = stretched[i]; + if (oldCur && stretchCur) { + spans: for (var j = 0; j < stretchCur.length; ++j) { + var span = stretchCur[j]; + for (var k = 0; k < oldCur.length; ++k) + { if (oldCur[k].marker == span.marker) { continue spans } } + oldCur.push(span); + } + } else if (stretchCur) { + old[i] = stretchCur; + } + } + return old + } + + // Used both to provide a JSON-safe object in .getHistory, and, when + // detaching a document, to split the history in two + function copyHistoryArray(events, newGroup, instantiateSel) { + var copy = []; + for (var i = 0; i < events.length; ++i) { + var event = events[i]; + if (event.ranges) { + copy.push(instantiateSel ? Selection.prototype.deepCopy.call(event) : event); + continue + } + var changes = event.changes, newChanges = []; + copy.push({changes: newChanges}); + for (var j = 0; j < changes.length; ++j) { + var change = changes[j], m = (void 0); + newChanges.push({from: change.from, to: change.to, text: change.text}); + if (newGroup) { for (var prop in change) { if (m = prop.match(/^spans_(\d+)$/)) { + if (indexOf(newGroup, Number(m[1])) > -1) { + lst(newChanges)[prop] = change[prop]; + delete change[prop]; + } + } } } + } + } + return copy + } + + // The 'scroll' parameter given to many of these indicated whether + // the new cursor position should be scrolled into view after + // modifying the selection. + + // If shift is held or the extend flag is set, extends a range to + // include a given position (and optionally a second position). + // Otherwise, simply returns the range between the given positions. + // Used for cursor motion and such. + function extendRange(range, head, other, extend) { + if (extend) { + var anchor = range.anchor; + if (other) { + var posBefore = cmp(head, anchor) < 0; + if (posBefore != (cmp(other, anchor) < 0)) { + anchor = head; + head = other; + } else if (posBefore != (cmp(head, other) < 0)) { + head = other; + } + } + return new Range(anchor, head) + } else { + return new Range(other || head, head) + } + } + + // Extend the primary selection range, discard the rest. + function extendSelection(doc, head, other, options, extend) { + if (extend == null) { extend = doc.cm && (doc.cm.display.shift || doc.extend); } + setSelection(doc, new Selection([extendRange(doc.sel.primary(), head, other, extend)], 0), options); + } + + // Extend all selections (pos is an array of selections with length + // equal the number of selections) + function extendSelections(doc, heads, options) { + var out = []; + var extend = doc.cm && (doc.cm.display.shift || doc.extend); + for (var i = 0; i < doc.sel.ranges.length; i++) + { out[i] = extendRange(doc.sel.ranges[i], heads[i], null, extend); } + var newSel = normalizeSelection(doc.cm, out, doc.sel.primIndex); + setSelection(doc, newSel, options); + } + + // Updates a single range in the selection. + function replaceOneSelection(doc, i, range, options) { + var ranges = doc.sel.ranges.slice(0); + ranges[i] = range; + setSelection(doc, normalizeSelection(doc.cm, ranges, doc.sel.primIndex), options); + } + + // Reset the selection to a single range. + function setSimpleSelection(doc, anchor, head, options) { + setSelection(doc, simpleSelection(anchor, head), options); + } + + // Give beforeSelectionChange handlers a change to influence a + // selection update. + function filterSelectionChange(doc, sel, options) { + var obj = { + ranges: sel.ranges, + update: function(ranges) { + this.ranges = []; + for (var i = 0; i < ranges.length; i++) + { this.ranges[i] = new Range(clipPos(doc, ranges[i].anchor), + clipPos(doc, ranges[i].head)); } + }, + origin: options && options.origin + }; + signal(doc, "beforeSelectionChange", doc, obj); + if (doc.cm) { signal(doc.cm, "beforeSelectionChange", doc.cm, obj); } + if (obj.ranges != sel.ranges) { return normalizeSelection(doc.cm, obj.ranges, obj.ranges.length - 1) } + else { return sel } + } + + function setSelectionReplaceHistory(doc, sel, options) { + var done = doc.history.done, last = lst(done); + if (last && last.ranges) { + done[done.length - 1] = sel; + setSelectionNoUndo(doc, sel, options); + } else { + setSelection(doc, sel, options); + } + } + + // Set a new selection. + function setSelection(doc, sel, options) { + setSelectionNoUndo(doc, sel, options); + addSelectionToHistory(doc, doc.sel, doc.cm ? doc.cm.curOp.id : NaN, options); + } + + function setSelectionNoUndo(doc, sel, options) { + if (hasHandler(doc, "beforeSelectionChange") || doc.cm && hasHandler(doc.cm, "beforeSelectionChange")) + { sel = filterSelectionChange(doc, sel, options); } + + var bias = options && options.bias || + (cmp(sel.primary().head, doc.sel.primary().head) < 0 ? -1 : 1); + setSelectionInner(doc, skipAtomicInSelection(doc, sel, bias, true)); + + if (!(options && options.scroll === false) && doc.cm && doc.cm.getOption("readOnly") != "nocursor") + { ensureCursorVisible(doc.cm); } + } + + function setSelectionInner(doc, sel) { + if (sel.equals(doc.sel)) { return } + + doc.sel = sel; + + if (doc.cm) { + doc.cm.curOp.updateInput = 1; + doc.cm.curOp.selectionChanged = true; + signalCursorActivity(doc.cm); + } + signalLater(doc, "cursorActivity", doc); + } + + // Verify that the selection does not partially select any atomic + // marked ranges. + function reCheckSelection(doc) { + setSelectionInner(doc, skipAtomicInSelection(doc, doc.sel, null, false)); + } + + // Return a selection that does not partially select any atomic + // ranges. + function skipAtomicInSelection(doc, sel, bias, mayClear) { + var out; + for (var i = 0; i < sel.ranges.length; i++) { + var range = sel.ranges[i]; + var old = sel.ranges.length == doc.sel.ranges.length && doc.sel.ranges[i]; + var newAnchor = skipAtomic(doc, range.anchor, old && old.anchor, bias, mayClear); + var newHead = range.head == range.anchor ? newAnchor : skipAtomic(doc, range.head, old && old.head, bias, mayClear); + if (out || newAnchor != range.anchor || newHead != range.head) { + if (!out) { out = sel.ranges.slice(0, i); } + out[i] = new Range(newAnchor, newHead); + } + } + return out ? normalizeSelection(doc.cm, out, sel.primIndex) : sel + } + + function skipAtomicInner(doc, pos, oldPos, dir, mayClear) { + var line = getLine(doc, pos.line); + if (line.markedSpans) { for (var i = 0; i < line.markedSpans.length; ++i) { + var sp = line.markedSpans[i], m = sp.marker; + + // Determine if we should prevent the cursor being placed to the left/right of an atomic marker + // Historically this was determined using the inclusiveLeft/Right option, but the new way to control it + // is with selectLeft/Right + var preventCursorLeft = ("selectLeft" in m) ? !m.selectLeft : m.inclusiveLeft; + var preventCursorRight = ("selectRight" in m) ? !m.selectRight : m.inclusiveRight; + + if ((sp.from == null || (preventCursorLeft ? sp.from <= pos.ch : sp.from < pos.ch)) && + (sp.to == null || (preventCursorRight ? sp.to >= pos.ch : sp.to > pos.ch))) { + if (mayClear) { + signal(m, "beforeCursorEnter"); + if (m.explicitlyCleared) { + if (!line.markedSpans) { break } + else {--i; continue} + } + } + if (!m.atomic) { continue } + + if (oldPos) { + var near = m.find(dir < 0 ? 1 : -1), diff = (void 0); + if (dir < 0 ? preventCursorRight : preventCursorLeft) + { near = movePos(doc, near, -dir, near && near.line == pos.line ? line : null); } + if (near && near.line == pos.line && (diff = cmp(near, oldPos)) && (dir < 0 ? diff < 0 : diff > 0)) + { return skipAtomicInner(doc, near, pos, dir, mayClear) } + } + + var far = m.find(dir < 0 ? -1 : 1); + if (dir < 0 ? preventCursorLeft : preventCursorRight) + { far = movePos(doc, far, dir, far.line == pos.line ? line : null); } + return far ? skipAtomicInner(doc, far, pos, dir, mayClear) : null + } + } } + return pos + } + + // Ensure a given position is not inside an atomic range. + function skipAtomic(doc, pos, oldPos, bias, mayClear) { + var dir = bias || 1; + var found = skipAtomicInner(doc, pos, oldPos, dir, mayClear) || + (!mayClear && skipAtomicInner(doc, pos, oldPos, dir, true)) || + skipAtomicInner(doc, pos, oldPos, -dir, mayClear) || + (!mayClear && skipAtomicInner(doc, pos, oldPos, -dir, true)); + if (!found) { + doc.cantEdit = true; + return Pos(doc.first, 0) + } + return found + } + + function movePos(doc, pos, dir, line) { + if (dir < 0 && pos.ch == 0) { + if (pos.line > doc.first) { return clipPos(doc, Pos(pos.line - 1)) } + else { return null } + } else if (dir > 0 && pos.ch == (line || getLine(doc, pos.line)).text.length) { + if (pos.line < doc.first + doc.size - 1) { return Pos(pos.line + 1, 0) } + else { return null } + } else { + return new Pos(pos.line, pos.ch + dir) + } + } + + function selectAll(cm) { + cm.setSelection(Pos(cm.firstLine(), 0), Pos(cm.lastLine()), sel_dontScroll); + } + + // UPDATING + + // Allow "beforeChange" event handlers to influence a change + function filterChange(doc, change, update) { + var obj = { + canceled: false, + from: change.from, + to: change.to, + text: change.text, + origin: change.origin, + cancel: function () { return obj.canceled = true; } + }; + if (update) { obj.update = function (from, to, text, origin) { + if (from) { obj.from = clipPos(doc, from); } + if (to) { obj.to = clipPos(doc, to); } + if (text) { obj.text = text; } + if (origin !== undefined) { obj.origin = origin; } + }; } + signal(doc, "beforeChange", doc, obj); + if (doc.cm) { signal(doc.cm, "beforeChange", doc.cm, obj); } + + if (obj.canceled) { + if (doc.cm) { doc.cm.curOp.updateInput = 2; } + return null + } + return {from: obj.from, to: obj.to, text: obj.text, origin: obj.origin} + } + + // Apply a change to a document, and add it to the document's + // history, and propagating it to all linked documents. + function makeChange(doc, change, ignoreReadOnly) { + if (doc.cm) { + if (!doc.cm.curOp) { return operation(doc.cm, makeChange)(doc, change, ignoreReadOnly) } + if (doc.cm.state.suppressEdits) { return } + } + + if (hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange")) { + change = filterChange(doc, change, true); + if (!change) { return } + } + + // Possibly split or suppress the update based on the presence + // of read-only spans in its range. + var split = sawReadOnlySpans && !ignoreReadOnly && removeReadOnlyRanges(doc, change.from, change.to); + if (split) { + for (var i = split.length - 1; i >= 0; --i) + { makeChangeInner(doc, {from: split[i].from, to: split[i].to, text: i ? [""] : change.text, origin: change.origin}); } + } else { + makeChangeInner(doc, change); + } + } + + function makeChangeInner(doc, change) { + if (change.text.length == 1 && change.text[0] == "" && cmp(change.from, change.to) == 0) { return } + var selAfter = computeSelAfterChange(doc, change); + addChangeToHistory(doc, change, selAfter, doc.cm ? doc.cm.curOp.id : NaN); + + makeChangeSingleDoc(doc, change, selAfter, stretchSpansOverChange(doc, change)); + var rebased = []; + + linkedDocs(doc, function (doc, sharedHist) { + if (!sharedHist && indexOf(rebased, doc.history) == -1) { + rebaseHist(doc.history, change); + rebased.push(doc.history); + } + makeChangeSingleDoc(doc, change, null, stretchSpansOverChange(doc, change)); + }); + } + + // Revert a change stored in a document's history. + function makeChangeFromHistory(doc, type, allowSelectionOnly) { + var suppress = doc.cm && doc.cm.state.suppressEdits; + if (suppress && !allowSelectionOnly) { return } + + var hist = doc.history, event, selAfter = doc.sel; + var source = type == "undo" ? hist.done : hist.undone, dest = type == "undo" ? hist.undone : hist.done; + + // Verify that there is a useable event (so that ctrl-z won't + // needlessly clear selection events) + var i = 0; + for (; i < source.length; i++) { + event = source[i]; + if (allowSelectionOnly ? event.ranges && !event.equals(doc.sel) : !event.ranges) + { break } + } + if (i == source.length) { return } + hist.lastOrigin = hist.lastSelOrigin = null; + + for (;;) { + event = source.pop(); + if (event.ranges) { + pushSelectionToHistory(event, dest); + if (allowSelectionOnly && !event.equals(doc.sel)) { + setSelection(doc, event, {clearRedo: false}); + return + } + selAfter = event; + } else if (suppress) { + source.push(event); + return + } else { break } + } + + // Build up a reverse change object to add to the opposite history + // stack (redo when undoing, and vice versa). + var antiChanges = []; + pushSelectionToHistory(selAfter, dest); + dest.push({changes: antiChanges, generation: hist.generation}); + hist.generation = event.generation || ++hist.maxGeneration; + + var filter = hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange"); + + var loop = function ( i ) { + var change = event.changes[i]; + change.origin = type; + if (filter && !filterChange(doc, change, false)) { + source.length = 0; + return {} + } + + antiChanges.push(historyChangeFromChange(doc, change)); + + var after = i ? computeSelAfterChange(doc, change) : lst(source); + makeChangeSingleDoc(doc, change, after, mergeOldSpans(doc, change)); + if (!i && doc.cm) { doc.cm.scrollIntoView({from: change.from, to: changeEnd(change)}); } + var rebased = []; + + // Propagate to the linked documents + linkedDocs(doc, function (doc, sharedHist) { + if (!sharedHist && indexOf(rebased, doc.history) == -1) { + rebaseHist(doc.history, change); + rebased.push(doc.history); + } + makeChangeSingleDoc(doc, change, null, mergeOldSpans(doc, change)); + }); + }; + + for (var i$1 = event.changes.length - 1; i$1 >= 0; --i$1) { + var returned = loop( i$1 ); + + if ( returned ) return returned.v; + } + } + + // Sub-views need their line numbers shifted when text is added + // above or below them in the parent document. + function shiftDoc(doc, distance) { + if (distance == 0) { return } + doc.first += distance; + doc.sel = new Selection(map(doc.sel.ranges, function (range) { return new Range( + Pos(range.anchor.line + distance, range.anchor.ch), + Pos(range.head.line + distance, range.head.ch) + ); }), doc.sel.primIndex); + if (doc.cm) { + regChange(doc.cm, doc.first, doc.first - distance, distance); + for (var d = doc.cm.display, l = d.viewFrom; l < d.viewTo; l++) + { regLineChange(doc.cm, l, "gutter"); } + } + } + + // More lower-level change function, handling only a single document + // (not linked ones). + function makeChangeSingleDoc(doc, change, selAfter, spans) { + if (doc.cm && !doc.cm.curOp) + { return operation(doc.cm, makeChangeSingleDoc)(doc, change, selAfter, spans) } + + if (change.to.line < doc.first) { + shiftDoc(doc, change.text.length - 1 - (change.to.line - change.from.line)); + return + } + if (change.from.line > doc.lastLine()) { return } + + // Clip the change to the size of this doc + if (change.from.line < doc.first) { + var shift = change.text.length - 1 - (doc.first - change.from.line); + shiftDoc(doc, shift); + change = {from: Pos(doc.first, 0), to: Pos(change.to.line + shift, change.to.ch), + text: [lst(change.text)], origin: change.origin}; + } + var last = doc.lastLine(); + if (change.to.line > last) { + change = {from: change.from, to: Pos(last, getLine(doc, last).text.length), + text: [change.text[0]], origin: change.origin}; + } + + change.removed = getBetween(doc, change.from, change.to); + + if (!selAfter) { selAfter = computeSelAfterChange(doc, change); } + if (doc.cm) { makeChangeSingleDocInEditor(doc.cm, change, spans); } + else { updateDoc(doc, change, spans); } + setSelectionNoUndo(doc, selAfter, sel_dontScroll); + + if (doc.cantEdit && skipAtomic(doc, Pos(doc.firstLine(), 0))) + { doc.cantEdit = false; } + } + + // Handle the interaction of a change to a document with the editor + // that this document is part of. + function makeChangeSingleDocInEditor(cm, change, spans) { + var doc = cm.doc, display = cm.display, from = change.from, to = change.to; + + var recomputeMaxLength = false, checkWidthStart = from.line; + if (!cm.options.lineWrapping) { + checkWidthStart = lineNo(visualLine(getLine(doc, from.line))); + doc.iter(checkWidthStart, to.line + 1, function (line) { + if (line == display.maxLine) { + recomputeMaxLength = true; + return true + } + }); + } + + if (doc.sel.contains(change.from, change.to) > -1) + { signalCursorActivity(cm); } + + updateDoc(doc, change, spans, estimateHeight(cm)); + + if (!cm.options.lineWrapping) { + doc.iter(checkWidthStart, from.line + change.text.length, function (line) { + var len = lineLength(line); + if (len > display.maxLineLength) { + display.maxLine = line; + display.maxLineLength = len; + display.maxLineChanged = true; + recomputeMaxLength = false; + } + }); + if (recomputeMaxLength) { cm.curOp.updateMaxLine = true; } + } + + retreatFrontier(doc, from.line); + startWorker(cm, 400); + + var lendiff = change.text.length - (to.line - from.line) - 1; + // Remember that these lines changed, for updating the display + if (change.full) + { regChange(cm); } + else if (from.line == to.line && change.text.length == 1 && !isWholeLineUpdate(cm.doc, change)) + { regLineChange(cm, from.line, "text"); } + else + { regChange(cm, from.line, to.line + 1, lendiff); } + + var changesHandler = hasHandler(cm, "changes"), changeHandler = hasHandler(cm, "change"); + if (changeHandler || changesHandler) { + var obj = { + from: from, to: to, + text: change.text, + removed: change.removed, + origin: change.origin + }; + if (changeHandler) { signalLater(cm, "change", cm, obj); } + if (changesHandler) { (cm.curOp.changeObjs || (cm.curOp.changeObjs = [])).push(obj); } + } + cm.display.selForContextMenu = null; + } + + function replaceRange(doc, code, from, to, origin) { + var assign; + + if (!to) { to = from; } + if (cmp(to, from) < 0) { (assign = [to, from], from = assign[0], to = assign[1]); } + if (typeof code == "string") { code = doc.splitLines(code); } + makeChange(doc, {from: from, to: to, text: code, origin: origin}); + } + + // Rebasing/resetting history to deal with externally-sourced changes + + function rebaseHistSelSingle(pos, from, to, diff) { + if (to < pos.line) { + pos.line += diff; + } else if (from < pos.line) { + pos.line = from; + pos.ch = 0; + } + } + + // Tries to rebase an array of history events given a change in the + // document. If the change touches the same lines as the event, the + // event, and everything 'behind' it, is discarded. If the change is + // before the event, the event's positions are updated. Uses a + // copy-on-write scheme for the positions, to avoid having to + // reallocate them all on every rebase, but also avoid problems with + // shared position objects being unsafely updated. + function rebaseHistArray(array, from, to, diff) { + for (var i = 0; i < array.length; ++i) { + var sub = array[i], ok = true; + if (sub.ranges) { + if (!sub.copied) { sub = array[i] = sub.deepCopy(); sub.copied = true; } + for (var j = 0; j < sub.ranges.length; j++) { + rebaseHistSelSingle(sub.ranges[j].anchor, from, to, diff); + rebaseHistSelSingle(sub.ranges[j].head, from, to, diff); + } + continue + } + for (var j$1 = 0; j$1 < sub.changes.length; ++j$1) { + var cur = sub.changes[j$1]; + if (to < cur.from.line) { + cur.from = Pos(cur.from.line + diff, cur.from.ch); + cur.to = Pos(cur.to.line + diff, cur.to.ch); + } else if (from <= cur.to.line) { + ok = false; + break + } + } + if (!ok) { + array.splice(0, i + 1); + i = 0; + } + } + } + + function rebaseHist(hist, change) { + var from = change.from.line, to = change.to.line, diff = change.text.length - (to - from) - 1; + rebaseHistArray(hist.done, from, to, diff); + rebaseHistArray(hist.undone, from, to, diff); + } + + // Utility for applying a change to a line by handle or number, + // returning the number and optionally registering the line as + // changed. + function changeLine(doc, handle, changeType, op) { + var no = handle, line = handle; + if (typeof handle == "number") { line = getLine(doc, clipLine(doc, handle)); } + else { no = lineNo(handle); } + if (no == null) { return null } + if (op(line, no) && doc.cm) { regLineChange(doc.cm, no, changeType); } + return line + } + + // The document is represented as a BTree consisting of leaves, with + // chunk of lines in them, and branches, with up to ten leaves or + // other branch nodes below them. The top node is always a branch + // node, and is the document object itself (meaning it has + // additional methods and properties). + // + // All nodes have parent links. The tree is used both to go from + // line numbers to line objects, and to go from objects to numbers. + // It also indexes by height, and is used to convert between height + // and line object, and to find the total height of the document. + // + // See also http://marijnhaverbeke.nl/blog/codemirror-line-tree.html + + function LeafChunk(lines) { + this.lines = lines; + this.parent = null; + var height = 0; + for (var i = 0; i < lines.length; ++i) { + lines[i].parent = this; + height += lines[i].height; + } + this.height = height; + } + + LeafChunk.prototype = { + chunkSize: function() { return this.lines.length }, + + // Remove the n lines at offset 'at'. + removeInner: function(at, n) { + for (var i = at, e = at + n; i < e; ++i) { + var line = this.lines[i]; + this.height -= line.height; + cleanUpLine(line); + signalLater(line, "delete"); + } + this.lines.splice(at, n); + }, + + // Helper used to collapse a small branch into a single leaf. + collapse: function(lines) { + lines.push.apply(lines, this.lines); + }, + + // Insert the given array of lines at offset 'at', count them as + // having the given height. + insertInner: function(at, lines, height) { + this.height += height; + this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at)); + for (var i = 0; i < lines.length; ++i) { lines[i].parent = this; } + }, + + // Used to iterate over a part of the tree. + iterN: function(at, n, op) { + for (var e = at + n; at < e; ++at) + { if (op(this.lines[at])) { return true } } + } + }; + + function BranchChunk(children) { + this.children = children; + var size = 0, height = 0; + for (var i = 0; i < children.length; ++i) { + var ch = children[i]; + size += ch.chunkSize(); height += ch.height; + ch.parent = this; + } + this.size = size; + this.height = height; + this.parent = null; + } + + BranchChunk.prototype = { + chunkSize: function() { return this.size }, + + removeInner: function(at, n) { + this.size -= n; + for (var i = 0; i < this.children.length; ++i) { + var child = this.children[i], sz = child.chunkSize(); + if (at < sz) { + var rm = Math.min(n, sz - at), oldHeight = child.height; + child.removeInner(at, rm); + this.height -= oldHeight - child.height; + if (sz == rm) { this.children.splice(i--, 1); child.parent = null; } + if ((n -= rm) == 0) { break } + at = 0; + } else { at -= sz; } + } + // If the result is smaller than 25 lines, ensure that it is a + // single leaf node. + if (this.size - n < 25 && + (this.children.length > 1 || !(this.children[0] instanceof LeafChunk))) { + var lines = []; + this.collapse(lines); + this.children = [new LeafChunk(lines)]; + this.children[0].parent = this; + } + }, + + collapse: function(lines) { + for (var i = 0; i < this.children.length; ++i) { this.children[i].collapse(lines); } + }, + + insertInner: function(at, lines, height) { + this.size += lines.length; + this.height += height; + for (var i = 0; i < this.children.length; ++i) { + var child = this.children[i], sz = child.chunkSize(); + if (at <= sz) { + child.insertInner(at, lines, height); + if (child.lines && child.lines.length > 50) { + // To avoid memory thrashing when child.lines is huge (e.g. first view of a large file), it's never spliced. + // Instead, small slices are taken. They're taken in order because sequential memory accesses are fastest. + var remaining = child.lines.length % 25 + 25; + for (var pos = remaining; pos < child.lines.length;) { + var leaf = new LeafChunk(child.lines.slice(pos, pos += 25)); + child.height -= leaf.height; + this.children.splice(++i, 0, leaf); + leaf.parent = this; + } + child.lines = child.lines.slice(0, remaining); + this.maybeSpill(); + } + break + } + at -= sz; + } + }, + + // When a node has grown, check whether it should be split. + maybeSpill: function() { + if (this.children.length <= 10) { return } + var me = this; + do { + var spilled = me.children.splice(me.children.length - 5, 5); + var sibling = new BranchChunk(spilled); + if (!me.parent) { // Become the parent node + var copy = new BranchChunk(me.children); + copy.parent = me; + me.children = [copy, sibling]; + me = copy; + } else { + me.size -= sibling.size; + me.height -= sibling.height; + var myIndex = indexOf(me.parent.children, me); + me.parent.children.splice(myIndex + 1, 0, sibling); + } + sibling.parent = me.parent; + } while (me.children.length > 10) + me.parent.maybeSpill(); + }, + + iterN: function(at, n, op) { + for (var i = 0; i < this.children.length; ++i) { + var child = this.children[i], sz = child.chunkSize(); + if (at < sz) { + var used = Math.min(n, sz - at); + if (child.iterN(at, used, op)) { return true } + if ((n -= used) == 0) { break } + at = 0; + } else { at -= sz; } + } + } + }; + + // Line widgets are block elements displayed above or below a line. + + var LineWidget = function(doc, node, options) { + if (options) { for (var opt in options) { if (options.hasOwnProperty(opt)) + { this[opt] = options[opt]; } } } + this.doc = doc; + this.node = node; + }; + + LineWidget.prototype.clear = function () { + var cm = this.doc.cm, ws = this.line.widgets, line = this.line, no = lineNo(line); + if (no == null || !ws) { return } + for (var i = 0; i < ws.length; ++i) { if (ws[i] == this) { ws.splice(i--, 1); } } + if (!ws.length) { line.widgets = null; } + var height = widgetHeight(this); + updateLineHeight(line, Math.max(0, line.height - height)); + if (cm) { + runInOp(cm, function () { + adjustScrollWhenAboveVisible(cm, line, -height); + regLineChange(cm, no, "widget"); + }); + signalLater(cm, "lineWidgetCleared", cm, this, no); + } + }; + + LineWidget.prototype.changed = function () { + var this$1 = this; + + var oldH = this.height, cm = this.doc.cm, line = this.line; + this.height = null; + var diff = widgetHeight(this) - oldH; + if (!diff) { return } + if (!lineIsHidden(this.doc, line)) { updateLineHeight(line, line.height + diff); } + if (cm) { + runInOp(cm, function () { + cm.curOp.forceUpdate = true; + adjustScrollWhenAboveVisible(cm, line, diff); + signalLater(cm, "lineWidgetChanged", cm, this$1, lineNo(line)); + }); + } + }; + eventMixin(LineWidget); + + function adjustScrollWhenAboveVisible(cm, line, diff) { + if (heightAtLine(line) < ((cm.curOp && cm.curOp.scrollTop) || cm.doc.scrollTop)) + { addToScrollTop(cm, diff); } + } + + function addLineWidget(doc, handle, node, options) { + var widget = new LineWidget(doc, node, options); + var cm = doc.cm; + if (cm && widget.noHScroll) { cm.display.alignWidgets = true; } + changeLine(doc, handle, "widget", function (line) { + var widgets = line.widgets || (line.widgets = []); + if (widget.insertAt == null) { widgets.push(widget); } + else { widgets.splice(Math.min(widgets.length, Math.max(0, widget.insertAt)), 0, widget); } + widget.line = line; + if (cm && !lineIsHidden(doc, line)) { + var aboveVisible = heightAtLine(line) < doc.scrollTop; + updateLineHeight(line, line.height + widgetHeight(widget)); + if (aboveVisible) { addToScrollTop(cm, widget.height); } + cm.curOp.forceUpdate = true; + } + return true + }); + if (cm) { signalLater(cm, "lineWidgetAdded", cm, widget, typeof handle == "number" ? handle : lineNo(handle)); } + return widget + } + + // TEXTMARKERS + + // Created with markText and setBookmark methods. A TextMarker is a + // handle that can be used to clear or find a marked position in the + // document. Line objects hold arrays (markedSpans) containing + // {from, to, marker} object pointing to such marker objects, and + // indicating that such a marker is present on that line. Multiple + // lines may point to the same marker when it spans across lines. + // The spans will have null for their from/to properties when the + // marker continues beyond the start/end of the line. Markers have + // links back to the lines they currently touch. + + // Collapsed markers have unique ids, in order to be able to order + // them, which is needed for uniquely determining an outer marker + // when they overlap (they may nest, but not partially overlap). + var nextMarkerId = 0; + + var TextMarker = function(doc, type) { + this.lines = []; + this.type = type; + this.doc = doc; + this.id = ++nextMarkerId; + }; + + // Clear the marker. + TextMarker.prototype.clear = function () { + if (this.explicitlyCleared) { return } + var cm = this.doc.cm, withOp = cm && !cm.curOp; + if (withOp) { startOperation(cm); } + if (hasHandler(this, "clear")) { + var found = this.find(); + if (found) { signalLater(this, "clear", found.from, found.to); } + } + var min = null, max = null; + for (var i = 0; i < this.lines.length; ++i) { + var line = this.lines[i]; + var span = getMarkedSpanFor(line.markedSpans, this); + if (cm && !this.collapsed) { regLineChange(cm, lineNo(line), "text"); } + else if (cm) { + if (span.to != null) { max = lineNo(line); } + if (span.from != null) { min = lineNo(line); } + } + line.markedSpans = removeMarkedSpan(line.markedSpans, span); + if (span.from == null && this.collapsed && !lineIsHidden(this.doc, line) && cm) + { updateLineHeight(line, textHeight(cm.display)); } + } + if (cm && this.collapsed && !cm.options.lineWrapping) { for (var i$1 = 0; i$1 < this.lines.length; ++i$1) { + var visual = visualLine(this.lines[i$1]), len = lineLength(visual); + if (len > cm.display.maxLineLength) { + cm.display.maxLine = visual; + cm.display.maxLineLength = len; + cm.display.maxLineChanged = true; + } + } } + + if (min != null && cm && this.collapsed) { regChange(cm, min, max + 1); } + this.lines.length = 0; + this.explicitlyCleared = true; + if (this.atomic && this.doc.cantEdit) { + this.doc.cantEdit = false; + if (cm) { reCheckSelection(cm.doc); } + } + if (cm) { signalLater(cm, "markerCleared", cm, this, min, max); } + if (withOp) { endOperation(cm); } + if (this.parent) { this.parent.clear(); } + }; + + // Find the position of the marker in the document. Returns a {from, + // to} object by default. Side can be passed to get a specific side + // -- 0 (both), -1 (left), or 1 (right). When lineObj is true, the + // Pos objects returned contain a line object, rather than a line + // number (used to prevent looking up the same line twice). + TextMarker.prototype.find = function (side, lineObj) { + if (side == null && this.type == "bookmark") { side = 1; } + var from, to; + for (var i = 0; i < this.lines.length; ++i) { + var line = this.lines[i]; + var span = getMarkedSpanFor(line.markedSpans, this); + if (span.from != null) { + from = Pos(lineObj ? line : lineNo(line), span.from); + if (side == -1) { return from } + } + if (span.to != null) { + to = Pos(lineObj ? line : lineNo(line), span.to); + if (side == 1) { return to } + } + } + return from && {from: from, to: to} + }; + + // Signals that the marker's widget changed, and surrounding layout + // should be recomputed. + TextMarker.prototype.changed = function () { + var this$1 = this; + + var pos = this.find(-1, true), widget = this, cm = this.doc.cm; + if (!pos || !cm) { return } + runInOp(cm, function () { + var line = pos.line, lineN = lineNo(pos.line); + var view = findViewForLine(cm, lineN); + if (view) { + clearLineMeasurementCacheFor(view); + cm.curOp.selectionChanged = cm.curOp.forceUpdate = true; + } + cm.curOp.updateMaxLine = true; + if (!lineIsHidden(widget.doc, line) && widget.height != null) { + var oldHeight = widget.height; + widget.height = null; + var dHeight = widgetHeight(widget) - oldHeight; + if (dHeight) + { updateLineHeight(line, line.height + dHeight); } + } + signalLater(cm, "markerChanged", cm, this$1); + }); + }; + + TextMarker.prototype.attachLine = function (line) { + if (!this.lines.length && this.doc.cm) { + var op = this.doc.cm.curOp; + if (!op.maybeHiddenMarkers || indexOf(op.maybeHiddenMarkers, this) == -1) + { (op.maybeUnhiddenMarkers || (op.maybeUnhiddenMarkers = [])).push(this); } + } + this.lines.push(line); + }; + + TextMarker.prototype.detachLine = function (line) { + this.lines.splice(indexOf(this.lines, line), 1); + if (!this.lines.length && this.doc.cm) { + var op = this.doc.cm.curOp + ;(op.maybeHiddenMarkers || (op.maybeHiddenMarkers = [])).push(this); + } + }; + eventMixin(TextMarker); + + // Create a marker, wire it up to the right lines, and + function markText(doc, from, to, options, type) { + // Shared markers (across linked documents) are handled separately + // (markTextShared will call out to this again, once per + // document). + if (options && options.shared) { return markTextShared(doc, from, to, options, type) } + // Ensure we are in an operation. + if (doc.cm && !doc.cm.curOp) { return operation(doc.cm, markText)(doc, from, to, options, type) } + + var marker = new TextMarker(doc, type), diff = cmp(from, to); + if (options) { copyObj(options, marker, false); } + // Don't connect empty markers unless clearWhenEmpty is false + if (diff > 0 || diff == 0 && marker.clearWhenEmpty !== false) + { return marker } + if (marker.replacedWith) { + // Showing up as a widget implies collapsed (widget replaces text) + marker.collapsed = true; + marker.widgetNode = eltP("span", [marker.replacedWith], "CodeMirror-widget"); + if (!options.handleMouseEvents) { marker.widgetNode.setAttribute("cm-ignore-events", "true"); } + if (options.insertLeft) { marker.widgetNode.insertLeft = true; } + } + if (marker.collapsed) { + if (conflictingCollapsedRange(doc, from.line, from, to, marker) || + from.line != to.line && conflictingCollapsedRange(doc, to.line, from, to, marker)) + { throw new Error("Inserting collapsed marker partially overlapping an existing one") } + seeCollapsedSpans(); + } + + if (marker.addToHistory) + { addChangeToHistory(doc, {from: from, to: to, origin: "markText"}, doc.sel, NaN); } + + var curLine = from.line, cm = doc.cm, updateMaxLine; + doc.iter(curLine, to.line + 1, function (line) { + if (cm && marker.collapsed && !cm.options.lineWrapping && visualLine(line) == cm.display.maxLine) + { updateMaxLine = true; } + if (marker.collapsed && curLine != from.line) { updateLineHeight(line, 0); } + addMarkedSpan(line, new MarkedSpan(marker, + curLine == from.line ? from.ch : null, + curLine == to.line ? to.ch : null), doc.cm && doc.cm.curOp); + ++curLine; + }); + // lineIsHidden depends on the presence of the spans, so needs a second pass + if (marker.collapsed) { doc.iter(from.line, to.line + 1, function (line) { + if (lineIsHidden(doc, line)) { updateLineHeight(line, 0); } + }); } + + if (marker.clearOnEnter) { on(marker, "beforeCursorEnter", function () { return marker.clear(); }); } + + if (marker.readOnly) { + seeReadOnlySpans(); + if (doc.history.done.length || doc.history.undone.length) + { doc.clearHistory(); } + } + if (marker.collapsed) { + marker.id = ++nextMarkerId; + marker.atomic = true; + } + if (cm) { + // Sync editor state + if (updateMaxLine) { cm.curOp.updateMaxLine = true; } + if (marker.collapsed) + { regChange(cm, from.line, to.line + 1); } + else if (marker.className || marker.startStyle || marker.endStyle || marker.css || + marker.attributes || marker.title) + { for (var i = from.line; i <= to.line; i++) { regLineChange(cm, i, "text"); } } + if (marker.atomic) { reCheckSelection(cm.doc); } + signalLater(cm, "markerAdded", cm, marker); + } + return marker + } + + // SHARED TEXTMARKERS + + // A shared marker spans multiple linked documents. It is + // implemented as a meta-marker-object controlling multiple normal + // markers. + var SharedTextMarker = function(markers, primary) { + this.markers = markers; + this.primary = primary; + for (var i = 0; i < markers.length; ++i) + { markers[i].parent = this; } + }; + + SharedTextMarker.prototype.clear = function () { + if (this.explicitlyCleared) { return } + this.explicitlyCleared = true; + for (var i = 0; i < this.markers.length; ++i) + { this.markers[i].clear(); } + signalLater(this, "clear"); + }; + + SharedTextMarker.prototype.find = function (side, lineObj) { + return this.primary.find(side, lineObj) + }; + eventMixin(SharedTextMarker); + + function markTextShared(doc, from, to, options, type) { + options = copyObj(options); + options.shared = false; + var markers = [markText(doc, from, to, options, type)], primary = markers[0]; + var widget = options.widgetNode; + linkedDocs(doc, function (doc) { + if (widget) { options.widgetNode = widget.cloneNode(true); } + markers.push(markText(doc, clipPos(doc, from), clipPos(doc, to), options, type)); + for (var i = 0; i < doc.linked.length; ++i) + { if (doc.linked[i].isParent) { return } } + primary = lst(markers); + }); + return new SharedTextMarker(markers, primary) + } + + function findSharedMarkers(doc) { + return doc.findMarks(Pos(doc.first, 0), doc.clipPos(Pos(doc.lastLine())), function (m) { return m.parent; }) + } + + function copySharedMarkers(doc, markers) { + for (var i = 0; i < markers.length; i++) { + var marker = markers[i], pos = marker.find(); + var mFrom = doc.clipPos(pos.from), mTo = doc.clipPos(pos.to); + if (cmp(mFrom, mTo)) { + var subMark = markText(doc, mFrom, mTo, marker.primary, marker.primary.type); + marker.markers.push(subMark); + subMark.parent = marker; + } + } + } + + function detachSharedMarkers(markers) { + var loop = function ( i ) { + var marker = markers[i], linked = [marker.primary.doc]; + linkedDocs(marker.primary.doc, function (d) { return linked.push(d); }); + for (var j = 0; j < marker.markers.length; j++) { + var subMarker = marker.markers[j]; + if (indexOf(linked, subMarker.doc) == -1) { + subMarker.parent = null; + marker.markers.splice(j--, 1); + } + } + }; + + for (var i = 0; i < markers.length; i++) loop( i ); + } + + var nextDocId = 0; + var Doc = function(text, mode, firstLine, lineSep, direction) { + if (!(this instanceof Doc)) { return new Doc(text, mode, firstLine, lineSep, direction) } + if (firstLine == null) { firstLine = 0; } + + BranchChunk.call(this, [new LeafChunk([new Line("", null)])]); + this.first = firstLine; + this.scrollTop = this.scrollLeft = 0; + this.cantEdit = false; + this.cleanGeneration = 1; + this.modeFrontier = this.highlightFrontier = firstLine; + var start = Pos(firstLine, 0); + this.sel = simpleSelection(start); + this.history = new History(null); + this.id = ++nextDocId; + this.modeOption = mode; + this.lineSep = lineSep; + this.direction = (direction == "rtl") ? "rtl" : "ltr"; + this.extend = false; + + if (typeof text == "string") { text = this.splitLines(text); } + updateDoc(this, {from: start, to: start, text: text}); + setSelection(this, simpleSelection(start), sel_dontScroll); + }; + + Doc.prototype = createObj(BranchChunk.prototype, { + constructor: Doc, + // Iterate over the document. Supports two forms -- with only one + // argument, it calls that for each line in the document. With + // three, it iterates over the range given by the first two (with + // the second being non-inclusive). + iter: function(from, to, op) { + if (op) { this.iterN(from - this.first, to - from, op); } + else { this.iterN(this.first, this.first + this.size, from); } + }, + + // Non-public interface for adding and removing lines. + insert: function(at, lines) { + var height = 0; + for (var i = 0; i < lines.length; ++i) { height += lines[i].height; } + this.insertInner(at - this.first, lines, height); + }, + remove: function(at, n) { this.removeInner(at - this.first, n); }, + + // From here, the methods are part of the public interface. Most + // are also available from CodeMirror (editor) instances. + + getValue: function(lineSep) { + var lines = getLines(this, this.first, this.first + this.size); + if (lineSep === false) { return lines } + return lines.join(lineSep || this.lineSeparator()) + }, + setValue: docMethodOp(function(code) { + var top = Pos(this.first, 0), last = this.first + this.size - 1; + makeChange(this, {from: top, to: Pos(last, getLine(this, last).text.length), + text: this.splitLines(code), origin: "setValue", full: true}, true); + if (this.cm) { scrollToCoords(this.cm, 0, 0); } + setSelection(this, simpleSelection(top), sel_dontScroll); + }), + replaceRange: function(code, from, to, origin) { + from = clipPos(this, from); + to = to ? clipPos(this, to) : from; + replaceRange(this, code, from, to, origin); + }, + getRange: function(from, to, lineSep) { + var lines = getBetween(this, clipPos(this, from), clipPos(this, to)); + if (lineSep === false) { return lines } + if (lineSep === '') { return lines.join('') } + return lines.join(lineSep || this.lineSeparator()) + }, + + getLine: function(line) {var l = this.getLineHandle(line); return l && l.text}, + + getLineHandle: function(line) {if (isLine(this, line)) { return getLine(this, line) }}, + getLineNumber: function(line) {return lineNo(line)}, + + getLineHandleVisualStart: function(line) { + if (typeof line == "number") { line = getLine(this, line); } + return visualLine(line) + }, + + lineCount: function() {return this.size}, + firstLine: function() {return this.first}, + lastLine: function() {return this.first + this.size - 1}, + + clipPos: function(pos) {return clipPos(this, pos)}, + + getCursor: function(start) { + var range = this.sel.primary(), pos; + if (start == null || start == "head") { pos = range.head; } + else if (start == "anchor") { pos = range.anchor; } + else if (start == "end" || start == "to" || start === false) { pos = range.to(); } + else { pos = range.from(); } + return pos + }, + listSelections: function() { return this.sel.ranges }, + somethingSelected: function() {return this.sel.somethingSelected()}, + + setCursor: docMethodOp(function(line, ch, options) { + setSimpleSelection(this, clipPos(this, typeof line == "number" ? Pos(line, ch || 0) : line), null, options); + }), + setSelection: docMethodOp(function(anchor, head, options) { + setSimpleSelection(this, clipPos(this, anchor), clipPos(this, head || anchor), options); + }), + extendSelection: docMethodOp(function(head, other, options) { + extendSelection(this, clipPos(this, head), other && clipPos(this, other), options); + }), + extendSelections: docMethodOp(function(heads, options) { + extendSelections(this, clipPosArray(this, heads), options); + }), + extendSelectionsBy: docMethodOp(function(f, options) { + var heads = map(this.sel.ranges, f); + extendSelections(this, clipPosArray(this, heads), options); + }), + setSelections: docMethodOp(function(ranges, primary, options) { + if (!ranges.length) { return } + var out = []; + for (var i = 0; i < ranges.length; i++) + { out[i] = new Range(clipPos(this, ranges[i].anchor), + clipPos(this, ranges[i].head || ranges[i].anchor)); } + if (primary == null) { primary = Math.min(ranges.length - 1, this.sel.primIndex); } + setSelection(this, normalizeSelection(this.cm, out, primary), options); + }), + addSelection: docMethodOp(function(anchor, head, options) { + var ranges = this.sel.ranges.slice(0); + ranges.push(new Range(clipPos(this, anchor), clipPos(this, head || anchor))); + setSelection(this, normalizeSelection(this.cm, ranges, ranges.length - 1), options); + }), + + getSelection: function(lineSep) { + var ranges = this.sel.ranges, lines; + for (var i = 0; i < ranges.length; i++) { + var sel = getBetween(this, ranges[i].from(), ranges[i].to()); + lines = lines ? lines.concat(sel) : sel; + } + if (lineSep === false) { return lines } + else { return lines.join(lineSep || this.lineSeparator()) } + }, + getSelections: function(lineSep) { + var parts = [], ranges = this.sel.ranges; + for (var i = 0; i < ranges.length; i++) { + var sel = getBetween(this, ranges[i].from(), ranges[i].to()); + if (lineSep !== false) { sel = sel.join(lineSep || this.lineSeparator()); } + parts[i] = sel; + } + return parts + }, + replaceSelection: function(code, collapse, origin) { + var dup = []; + for (var i = 0; i < this.sel.ranges.length; i++) + { dup[i] = code; } + this.replaceSelections(dup, collapse, origin || "+input"); + }, + replaceSelections: docMethodOp(function(code, collapse, origin) { + var changes = [], sel = this.sel; + for (var i = 0; i < sel.ranges.length; i++) { + var range = sel.ranges[i]; + changes[i] = {from: range.from(), to: range.to(), text: this.splitLines(code[i]), origin: origin}; + } + var newSel = collapse && collapse != "end" && computeReplacedSel(this, changes, collapse); + for (var i$1 = changes.length - 1; i$1 >= 0; i$1--) + { makeChange(this, changes[i$1]); } + if (newSel) { setSelectionReplaceHistory(this, newSel); } + else if (this.cm) { ensureCursorVisible(this.cm); } + }), + undo: docMethodOp(function() {makeChangeFromHistory(this, "undo");}), + redo: docMethodOp(function() {makeChangeFromHistory(this, "redo");}), + undoSelection: docMethodOp(function() {makeChangeFromHistory(this, "undo", true);}), + redoSelection: docMethodOp(function() {makeChangeFromHistory(this, "redo", true);}), + + setExtending: function(val) {this.extend = val;}, + getExtending: function() {return this.extend}, + + historySize: function() { + var hist = this.history, done = 0, undone = 0; + for (var i = 0; i < hist.done.length; i++) { if (!hist.done[i].ranges) { ++done; } } + for (var i$1 = 0; i$1 < hist.undone.length; i$1++) { if (!hist.undone[i$1].ranges) { ++undone; } } + return {undo: done, redo: undone} + }, + clearHistory: function() { + var this$1 = this; + + this.history = new History(this.history); + linkedDocs(this, function (doc) { return doc.history = this$1.history; }, true); + }, + + markClean: function() { + this.cleanGeneration = this.changeGeneration(true); + }, + changeGeneration: function(forceSplit) { + if (forceSplit) + { this.history.lastOp = this.history.lastSelOp = this.history.lastOrigin = null; } + return this.history.generation + }, + isClean: function (gen) { + return this.history.generation == (gen || this.cleanGeneration) + }, + + getHistory: function() { + return {done: copyHistoryArray(this.history.done), + undone: copyHistoryArray(this.history.undone)} + }, + setHistory: function(histData) { + var hist = this.history = new History(this.history); + hist.done = copyHistoryArray(histData.done.slice(0), null, true); + hist.undone = copyHistoryArray(histData.undone.slice(0), null, true); + }, + + setGutterMarker: docMethodOp(function(line, gutterID, value) { + return changeLine(this, line, "gutter", function (line) { + var markers = line.gutterMarkers || (line.gutterMarkers = {}); + markers[gutterID] = value; + if (!value && isEmpty(markers)) { line.gutterMarkers = null; } + return true + }) + }), + + clearGutter: docMethodOp(function(gutterID) { + var this$1 = this; + + this.iter(function (line) { + if (line.gutterMarkers && line.gutterMarkers[gutterID]) { + changeLine(this$1, line, "gutter", function () { + line.gutterMarkers[gutterID] = null; + if (isEmpty(line.gutterMarkers)) { line.gutterMarkers = null; } + return true + }); + } + }); + }), + + lineInfo: function(line) { + var n; + if (typeof line == "number") { + if (!isLine(this, line)) { return null } + n = line; + line = getLine(this, line); + if (!line) { return null } + } else { + n = lineNo(line); + if (n == null) { return null } + } + return {line: n, handle: line, text: line.text, gutterMarkers: line.gutterMarkers, + textClass: line.textClass, bgClass: line.bgClass, wrapClass: line.wrapClass, + widgets: line.widgets} + }, + + addLineClass: docMethodOp(function(handle, where, cls) { + return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function (line) { + var prop = where == "text" ? "textClass" + : where == "background" ? "bgClass" + : where == "gutter" ? "gutterClass" : "wrapClass"; + if (!line[prop]) { line[prop] = cls; } + else if (classTest(cls).test(line[prop])) { return false } + else { line[prop] += " " + cls; } + return true + }) + }), + removeLineClass: docMethodOp(function(handle, where, cls) { + return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function (line) { + var prop = where == "text" ? "textClass" + : where == "background" ? "bgClass" + : where == "gutter" ? "gutterClass" : "wrapClass"; + var cur = line[prop]; + if (!cur) { return false } + else if (cls == null) { line[prop] = null; } + else { + var found = cur.match(classTest(cls)); + if (!found) { return false } + var end = found.index + found[0].length; + line[prop] = cur.slice(0, found.index) + (!found.index || end == cur.length ? "" : " ") + cur.slice(end) || null; + } + return true + }) + }), + + addLineWidget: docMethodOp(function(handle, node, options) { + return addLineWidget(this, handle, node, options) + }), + removeLineWidget: function(widget) { widget.clear(); }, + + markText: function(from, to, options) { + return markText(this, clipPos(this, from), clipPos(this, to), options, options && options.type || "range") + }, + setBookmark: function(pos, options) { + var realOpts = {replacedWith: options && (options.nodeType == null ? options.widget : options), + insertLeft: options && options.insertLeft, + clearWhenEmpty: false, shared: options && options.shared, + handleMouseEvents: options && options.handleMouseEvents}; + pos = clipPos(this, pos); + return markText(this, pos, pos, realOpts, "bookmark") + }, + findMarksAt: function(pos) { + pos = clipPos(this, pos); + var markers = [], spans = getLine(this, pos.line).markedSpans; + if (spans) { for (var i = 0; i < spans.length; ++i) { + var span = spans[i]; + if ((span.from == null || span.from <= pos.ch) && + (span.to == null || span.to >= pos.ch)) + { markers.push(span.marker.parent || span.marker); } + } } + return markers + }, + findMarks: function(from, to, filter) { + from = clipPos(this, from); to = clipPos(this, to); + var found = [], lineNo = from.line; + this.iter(from.line, to.line + 1, function (line) { + var spans = line.markedSpans; + if (spans) { for (var i = 0; i < spans.length; i++) { + var span = spans[i]; + if (!(span.to != null && lineNo == from.line && from.ch >= span.to || + span.from == null && lineNo != from.line || + span.from != null && lineNo == to.line && span.from >= to.ch) && + (!filter || filter(span.marker))) + { found.push(span.marker.parent || span.marker); } + } } + ++lineNo; + }); + return found + }, + getAllMarks: function() { + var markers = []; + this.iter(function (line) { + var sps = line.markedSpans; + if (sps) { for (var i = 0; i < sps.length; ++i) + { if (sps[i].from != null) { markers.push(sps[i].marker); } } } + }); + return markers + }, + + posFromIndex: function(off) { + var ch, lineNo = this.first, sepSize = this.lineSeparator().length; + this.iter(function (line) { + var sz = line.text.length + sepSize; + if (sz > off) { ch = off; return true } + off -= sz; + ++lineNo; + }); + return clipPos(this, Pos(lineNo, ch)) + }, + indexFromPos: function (coords) { + coords = clipPos(this, coords); + var index = coords.ch; + if (coords.line < this.first || coords.ch < 0) { return 0 } + var sepSize = this.lineSeparator().length; + this.iter(this.first, coords.line, function (line) { // iter aborts when callback returns a truthy value + index += line.text.length + sepSize; + }); + return index + }, + + copy: function(copyHistory) { + var doc = new Doc(getLines(this, this.first, this.first + this.size), + this.modeOption, this.first, this.lineSep, this.direction); + doc.scrollTop = this.scrollTop; doc.scrollLeft = this.scrollLeft; + doc.sel = this.sel; + doc.extend = false; + if (copyHistory) { + doc.history.undoDepth = this.history.undoDepth; + doc.setHistory(this.getHistory()); + } + return doc + }, + + linkedDoc: function(options) { + if (!options) { options = {}; } + var from = this.first, to = this.first + this.size; + if (options.from != null && options.from > from) { from = options.from; } + if (options.to != null && options.to < to) { to = options.to; } + var copy = new Doc(getLines(this, from, to), options.mode || this.modeOption, from, this.lineSep, this.direction); + if (options.sharedHist) { copy.history = this.history + ; }(this.linked || (this.linked = [])).push({doc: copy, sharedHist: options.sharedHist}); + copy.linked = [{doc: this, isParent: true, sharedHist: options.sharedHist}]; + copySharedMarkers(copy, findSharedMarkers(this)); + return copy + }, + unlinkDoc: function(other) { + if (other instanceof CodeMirror) { other = other.doc; } + if (this.linked) { for (var i = 0; i < this.linked.length; ++i) { + var link = this.linked[i]; + if (link.doc != other) { continue } + this.linked.splice(i, 1); + other.unlinkDoc(this); + detachSharedMarkers(findSharedMarkers(this)); + break + } } + // If the histories were shared, split them again + if (other.history == this.history) { + var splitIds = [other.id]; + linkedDocs(other, function (doc) { return splitIds.push(doc.id); }, true); + other.history = new History(null); + other.history.done = copyHistoryArray(this.history.done, splitIds); + other.history.undone = copyHistoryArray(this.history.undone, splitIds); + } + }, + iterLinkedDocs: function(f) {linkedDocs(this, f);}, + + getMode: function() {return this.mode}, + getEditor: function() {return this.cm}, + + splitLines: function(str) { + if (this.lineSep) { return str.split(this.lineSep) } + return splitLinesAuto(str) + }, + lineSeparator: function() { return this.lineSep || "\n" }, + + setDirection: docMethodOp(function (dir) { + if (dir != "rtl") { dir = "ltr"; } + if (dir == this.direction) { return } + this.direction = dir; + this.iter(function (line) { return line.order = null; }); + if (this.cm) { directionChanged(this.cm); } + }) + }); + + // Public alias. + Doc.prototype.eachLine = Doc.prototype.iter; + + // Kludge to work around strange IE behavior where it'll sometimes + // re-fire a series of drag-related events right after the drop (#1551) + var lastDrop = 0; + + function onDrop(e) { + var cm = this; + clearDragCursor(cm); + if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) + { return } + e_preventDefault(e); + if (ie) { lastDrop = +new Date; } + var pos = posFromMouse(cm, e, true), files = e.dataTransfer.files; + if (!pos || cm.isReadOnly()) { return } + // Might be a file drop, in which case we simply extract the text + // and insert it. + if (files && files.length && window.FileReader && window.File) { + var n = files.length, text = Array(n), read = 0; + var markAsReadAndPasteIfAllFilesAreRead = function () { + if (++read == n) { + operation(cm, function () { + pos = clipPos(cm.doc, pos); + var change = {from: pos, to: pos, + text: cm.doc.splitLines( + text.filter(function (t) { return t != null; }).join(cm.doc.lineSeparator())), + origin: "paste"}; + makeChange(cm.doc, change); + setSelectionReplaceHistory(cm.doc, simpleSelection(clipPos(cm.doc, pos), clipPos(cm.doc, changeEnd(change)))); + })(); + } + }; + var readTextFromFile = function (file, i) { + if (cm.options.allowDropFileTypes && + indexOf(cm.options.allowDropFileTypes, file.type) == -1) { + markAsReadAndPasteIfAllFilesAreRead(); + return + } + var reader = new FileReader; + reader.onerror = function () { return markAsReadAndPasteIfAllFilesAreRead(); }; + reader.onload = function () { + var content = reader.result; + if (/[\x00-\x08\x0e-\x1f]{2}/.test(content)) { + markAsReadAndPasteIfAllFilesAreRead(); + return + } + text[i] = content; + markAsReadAndPasteIfAllFilesAreRead(); + }; + reader.readAsText(file); + }; + for (var i = 0; i < files.length; i++) { readTextFromFile(files[i], i); } + } else { // Normal drop + // Don't do a replace if the drop happened inside of the selected text. + if (cm.state.draggingText && cm.doc.sel.contains(pos) > -1) { + cm.state.draggingText(e); + // Ensure the editor is re-focused + setTimeout(function () { return cm.display.input.focus(); }, 20); + return + } + try { + var text$1 = e.dataTransfer.getData("Text"); + if (text$1) { + var selected; + if (cm.state.draggingText && !cm.state.draggingText.copy) + { selected = cm.listSelections(); } + setSelectionNoUndo(cm.doc, simpleSelection(pos, pos)); + if (selected) { for (var i$1 = 0; i$1 < selected.length; ++i$1) + { replaceRange(cm.doc, "", selected[i$1].anchor, selected[i$1].head, "drag"); } } + cm.replaceSelection(text$1, "around", "paste"); + cm.display.input.focus(); + } + } + catch(e$1){} + } + } + + function onDragStart(cm, e) { + if (ie && (!cm.state.draggingText || +new Date - lastDrop < 100)) { e_stop(e); return } + if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) { return } + + e.dataTransfer.setData("Text", cm.getSelection()); + e.dataTransfer.effectAllowed = "copyMove"; + + // Use dummy image instead of default browsers image. + // Recent Safari (~6.0.2) have a tendency to segfault when this happens, so we don't do it there. + if (e.dataTransfer.setDragImage && !safari) { + var img = elt("img", null, null, "position: fixed; left: 0; top: 0;"); + img.src = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="; + if (presto) { + img.width = img.height = 1; + cm.display.wrapper.appendChild(img); + // Force a relayout, or Opera won't use our image for some obscure reason + img._top = img.offsetTop; + } + e.dataTransfer.setDragImage(img, 0, 0); + if (presto) { img.parentNode.removeChild(img); } + } + } + + function onDragOver(cm, e) { + var pos = posFromMouse(cm, e); + if (!pos) { return } + var frag = document.createDocumentFragment(); + drawSelectionCursor(cm, pos, frag); + if (!cm.display.dragCursor) { + cm.display.dragCursor = elt("div", null, "CodeMirror-cursors CodeMirror-dragcursors"); + cm.display.lineSpace.insertBefore(cm.display.dragCursor, cm.display.cursorDiv); + } + removeChildrenAndAdd(cm.display.dragCursor, frag); + } + + function clearDragCursor(cm) { + if (cm.display.dragCursor) { + cm.display.lineSpace.removeChild(cm.display.dragCursor); + cm.display.dragCursor = null; + } + } + + // These must be handled carefully, because naively registering a + // handler for each editor will cause the editors to never be + // garbage collected. + + function forEachCodeMirror(f) { + if (!document.getElementsByClassName) { return } + var byClass = document.getElementsByClassName("CodeMirror"), editors = []; + for (var i = 0; i < byClass.length; i++) { + var cm = byClass[i].CodeMirror; + if (cm) { editors.push(cm); } + } + if (editors.length) { editors[0].operation(function () { + for (var i = 0; i < editors.length; i++) { f(editors[i]); } + }); } + } + + var globalsRegistered = false; + function ensureGlobalHandlers() { + if (globalsRegistered) { return } + registerGlobalHandlers(); + globalsRegistered = true; + } + function registerGlobalHandlers() { + // When the window resizes, we need to refresh active editors. + var resizeTimer; + on(window, "resize", function () { + if (resizeTimer == null) { resizeTimer = setTimeout(function () { + resizeTimer = null; + forEachCodeMirror(onResize); + }, 100); } + }); + // When the window loses focus, we want to show the editor as blurred + on(window, "blur", function () { return forEachCodeMirror(onBlur); }); + } + // Called when the window resizes + function onResize(cm) { + var d = cm.display; + // Might be a text scaling operation, clear size caches. + d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null; + d.scrollbarsClipped = false; + cm.setSize(); + } + + var keyNames = { + 3: "Pause", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt", + 19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End", + 36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert", + 46: "Delete", 59: ";", 61: "=", 91: "Mod", 92: "Mod", 93: "Mod", + 106: "*", 107: "=", 109: "-", 110: ".", 111: "/", 145: "ScrollLock", + 173: "-", 186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\", + 221: "]", 222: "'", 224: "Mod", 63232: "Up", 63233: "Down", 63234: "Left", 63235: "Right", 63272: "Delete", + 63273: "Home", 63275: "End", 63276: "PageUp", 63277: "PageDown", 63302: "Insert" + }; + + // Number keys + for (var i = 0; i < 10; i++) { keyNames[i + 48] = keyNames[i + 96] = String(i); } + // Alphabetic keys + for (var i$1 = 65; i$1 <= 90; i$1++) { keyNames[i$1] = String.fromCharCode(i$1); } + // Function keys + for (var i$2 = 1; i$2 <= 12; i$2++) { keyNames[i$2 + 111] = keyNames[i$2 + 63235] = "F" + i$2; } + + var keyMap = {}; + + keyMap.basic = { + "Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown", + "End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown", + "Delete": "delCharAfter", "Backspace": "delCharBefore", "Shift-Backspace": "delCharBefore", + "Tab": "defaultTab", "Shift-Tab": "indentAuto", + "Enter": "newlineAndIndent", "Insert": "toggleOverwrite", + "Esc": "singleSelection" + }; + // Note that the save and find-related commands aren't defined by + // default. User code or addons can define them. Unknown commands + // are simply ignored. + keyMap.pcDefault = { + "Ctrl-A": "selectAll", "Ctrl-D": "deleteLine", "Ctrl-Z": "undo", "Shift-Ctrl-Z": "redo", "Ctrl-Y": "redo", + "Ctrl-Home": "goDocStart", "Ctrl-End": "goDocEnd", "Ctrl-Up": "goLineUp", "Ctrl-Down": "goLineDown", + "Ctrl-Left": "goGroupLeft", "Ctrl-Right": "goGroupRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd", + "Ctrl-Backspace": "delGroupBefore", "Ctrl-Delete": "delGroupAfter", "Ctrl-S": "save", "Ctrl-F": "find", + "Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll", + "Ctrl-[": "indentLess", "Ctrl-]": "indentMore", + "Ctrl-U": "undoSelection", "Shift-Ctrl-U": "redoSelection", "Alt-U": "redoSelection", + "fallthrough": "basic" + }; + // Very basic readline/emacs-style bindings, which are standard on Mac. + keyMap.emacsy = { + "Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown", + "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd", "Ctrl-V": "goPageDown", "Shift-Ctrl-V": "goPageUp", + "Ctrl-D": "delCharAfter", "Ctrl-H": "delCharBefore", "Alt-Backspace": "delWordBefore", "Ctrl-K": "killLine", + "Ctrl-T": "transposeChars", "Ctrl-O": "openLine" + }; + keyMap.macDefault = { + "Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo", + "Cmd-Home": "goDocStart", "Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goGroupLeft", + "Alt-Right": "goGroupRight", "Cmd-Left": "goLineLeft", "Cmd-Right": "goLineRight", "Alt-Backspace": "delGroupBefore", + "Ctrl-Alt-Backspace": "delGroupAfter", "Alt-Delete": "delGroupAfter", "Cmd-S": "save", "Cmd-F": "find", + "Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll", + "Cmd-[": "indentLess", "Cmd-]": "indentMore", "Cmd-Backspace": "delWrappedLineLeft", "Cmd-Delete": "delWrappedLineRight", + "Cmd-U": "undoSelection", "Shift-Cmd-U": "redoSelection", "Ctrl-Up": "goDocStart", "Ctrl-Down": "goDocEnd", + "fallthrough": ["basic", "emacsy"] + }; + keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault; + + // KEYMAP DISPATCH + + function normalizeKeyName(name) { + var parts = name.split(/-(?!$)/); + name = parts[parts.length - 1]; + var alt, ctrl, shift, cmd; + for (var i = 0; i < parts.length - 1; i++) { + var mod = parts[i]; + if (/^(cmd|meta|m)$/i.test(mod)) { cmd = true; } + else if (/^a(lt)?$/i.test(mod)) { alt = true; } + else if (/^(c|ctrl|control)$/i.test(mod)) { ctrl = true; } + else if (/^s(hift)?$/i.test(mod)) { shift = true; } + else { throw new Error("Unrecognized modifier name: " + mod) } + } + if (alt) { name = "Alt-" + name; } + if (ctrl) { name = "Ctrl-" + name; } + if (cmd) { name = "Cmd-" + name; } + if (shift) { name = "Shift-" + name; } + return name + } + + // This is a kludge to keep keymaps mostly working as raw objects + // (backwards compatibility) while at the same time support features + // like normalization and multi-stroke key bindings. It compiles a + // new normalized keymap, and then updates the old object to reflect + // this. + function normalizeKeyMap(keymap) { + var copy = {}; + for (var keyname in keymap) { if (keymap.hasOwnProperty(keyname)) { + var value = keymap[keyname]; + if (/^(name|fallthrough|(de|at)tach)$/.test(keyname)) { continue } + if (value == "...") { delete keymap[keyname]; continue } + + var keys = map(keyname.split(" "), normalizeKeyName); + for (var i = 0; i < keys.length; i++) { + var val = (void 0), name = (void 0); + if (i == keys.length - 1) { + name = keys.join(" "); + val = value; + } else { + name = keys.slice(0, i + 1).join(" "); + val = "..."; + } + var prev = copy[name]; + if (!prev) { copy[name] = val; } + else if (prev != val) { throw new Error("Inconsistent bindings for " + name) } + } + delete keymap[keyname]; + } } + for (var prop in copy) { keymap[prop] = copy[prop]; } + return keymap + } + + function lookupKey(key, map, handle, context) { + map = getKeyMap(map); + var found = map.call ? map.call(key, context) : map[key]; + if (found === false) { return "nothing" } + if (found === "...") { return "multi" } + if (found != null && handle(found)) { return "handled" } + + if (map.fallthrough) { + if (Object.prototype.toString.call(map.fallthrough) != "[object Array]") + { return lookupKey(key, map.fallthrough, handle, context) } + for (var i = 0; i < map.fallthrough.length; i++) { + var result = lookupKey(key, map.fallthrough[i], handle, context); + if (result) { return result } + } + } + } + + // Modifier key presses don't count as 'real' key presses for the + // purpose of keymap fallthrough. + function isModifierKey(value) { + var name = typeof value == "string" ? value : keyNames[value.keyCode]; + return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod" + } + + function addModifierNames(name, event, noShift) { + var base = name; + if (event.altKey && base != "Alt") { name = "Alt-" + name; } + if ((flipCtrlCmd ? event.metaKey : event.ctrlKey) && base != "Ctrl") { name = "Ctrl-" + name; } + if ((flipCtrlCmd ? event.ctrlKey : event.metaKey) && base != "Mod") { name = "Cmd-" + name; } + if (!noShift && event.shiftKey && base != "Shift") { name = "Shift-" + name; } + return name + } + + // Look up the name of a key as indicated by an event object. + function keyName(event, noShift) { + if (presto && event.keyCode == 34 && event["char"]) { return false } + var name = keyNames[event.keyCode]; + if (name == null || event.altGraphKey) { return false } + // Ctrl-ScrollLock has keyCode 3, same as Ctrl-Pause, + // so we'll use event.code when available (Chrome 48+, FF 38+, Safari 10.1+) + if (event.keyCode == 3 && event.code) { name = event.code; } + return addModifierNames(name, event, noShift) + } + + function getKeyMap(val) { + return typeof val == "string" ? keyMap[val] : val + } + + // Helper for deleting text near the selection(s), used to implement + // backspace, delete, and similar functionality. + function deleteNearSelection(cm, compute) { + var ranges = cm.doc.sel.ranges, kill = []; + // Build up a set of ranges to kill first, merging overlapping + // ranges. + for (var i = 0; i < ranges.length; i++) { + var toKill = compute(ranges[i]); + while (kill.length && cmp(toKill.from, lst(kill).to) <= 0) { + var replaced = kill.pop(); + if (cmp(replaced.from, toKill.from) < 0) { + toKill.from = replaced.from; + break + } + } + kill.push(toKill); + } + // Next, remove those actual ranges. + runInOp(cm, function () { + for (var i = kill.length - 1; i >= 0; i--) + { replaceRange(cm.doc, "", kill[i].from, kill[i].to, "+delete"); } + ensureCursorVisible(cm); + }); + } + + function moveCharLogically(line, ch, dir) { + var target = skipExtendingChars(line.text, ch + dir, dir); + return target < 0 || target > line.text.length ? null : target + } + + function moveLogically(line, start, dir) { + var ch = moveCharLogically(line, start.ch, dir); + return ch == null ? null : new Pos(start.line, ch, dir < 0 ? "after" : "before") + } + + function endOfLine(visually, cm, lineObj, lineNo, dir) { + if (visually) { + if (cm.doc.direction == "rtl") { dir = -dir; } + var order = getOrder(lineObj, cm.doc.direction); + if (order) { + var part = dir < 0 ? lst(order) : order[0]; + var moveInStorageOrder = (dir < 0) == (part.level == 1); + var sticky = moveInStorageOrder ? "after" : "before"; + var ch; + // With a wrapped rtl chunk (possibly spanning multiple bidi parts), + // it could be that the last bidi part is not on the last visual line, + // since visual lines contain content order-consecutive chunks. + // Thus, in rtl, we are looking for the first (content-order) character + // in the rtl chunk that is on the last line (that is, the same line + // as the last (content-order) character). + if (part.level > 0 || cm.doc.direction == "rtl") { + var prep = prepareMeasureForLine(cm, lineObj); + ch = dir < 0 ? lineObj.text.length - 1 : 0; + var targetTop = measureCharPrepared(cm, prep, ch).top; + ch = findFirst(function (ch) { return measureCharPrepared(cm, prep, ch).top == targetTop; }, (dir < 0) == (part.level == 1) ? part.from : part.to - 1, ch); + if (sticky == "before") { ch = moveCharLogically(lineObj, ch, 1); } + } else { ch = dir < 0 ? part.to : part.from; } + return new Pos(lineNo, ch, sticky) + } + } + return new Pos(lineNo, dir < 0 ? lineObj.text.length : 0, dir < 0 ? "before" : "after") + } + + function moveVisually(cm, line, start, dir) { + var bidi = getOrder(line, cm.doc.direction); + if (!bidi) { return moveLogically(line, start, dir) } + if (start.ch >= line.text.length) { + start.ch = line.text.length; + start.sticky = "before"; + } else if (start.ch <= 0) { + start.ch = 0; + start.sticky = "after"; + } + var partPos = getBidiPartAt(bidi, start.ch, start.sticky), part = bidi[partPos]; + if (cm.doc.direction == "ltr" && part.level % 2 == 0 && (dir > 0 ? part.to > start.ch : part.from < start.ch)) { + // Case 1: We move within an ltr part in an ltr editor. Even with wrapped lines, + // nothing interesting happens. + return moveLogically(line, start, dir) + } + + var mv = function (pos, dir) { return moveCharLogically(line, pos instanceof Pos ? pos.ch : pos, dir); }; + var prep; + var getWrappedLineExtent = function (ch) { + if (!cm.options.lineWrapping) { return {begin: 0, end: line.text.length} } + prep = prep || prepareMeasureForLine(cm, line); + return wrappedLineExtentChar(cm, line, prep, ch) + }; + var wrappedLineExtent = getWrappedLineExtent(start.sticky == "before" ? mv(start, -1) : start.ch); + + if (cm.doc.direction == "rtl" || part.level == 1) { + var moveInStorageOrder = (part.level == 1) == (dir < 0); + var ch = mv(start, moveInStorageOrder ? 1 : -1); + if (ch != null && (!moveInStorageOrder ? ch >= part.from && ch >= wrappedLineExtent.begin : ch <= part.to && ch <= wrappedLineExtent.end)) { + // Case 2: We move within an rtl part or in an rtl editor on the same visual line + var sticky = moveInStorageOrder ? "before" : "after"; + return new Pos(start.line, ch, sticky) + } + } + + // Case 3: Could not move within this bidi part in this visual line, so leave + // the current bidi part + + var searchInVisualLine = function (partPos, dir, wrappedLineExtent) { + var getRes = function (ch, moveInStorageOrder) { return moveInStorageOrder + ? new Pos(start.line, mv(ch, 1), "before") + : new Pos(start.line, ch, "after"); }; + + for (; partPos >= 0 && partPos < bidi.length; partPos += dir) { + var part = bidi[partPos]; + var moveInStorageOrder = (dir > 0) == (part.level != 1); + var ch = moveInStorageOrder ? wrappedLineExtent.begin : mv(wrappedLineExtent.end, -1); + if (part.from <= ch && ch < part.to) { return getRes(ch, moveInStorageOrder) } + ch = moveInStorageOrder ? part.from : mv(part.to, -1); + if (wrappedLineExtent.begin <= ch && ch < wrappedLineExtent.end) { return getRes(ch, moveInStorageOrder) } + } + }; + + // Case 3a: Look for other bidi parts on the same visual line + var res = searchInVisualLine(partPos + dir, dir, wrappedLineExtent); + if (res) { return res } + + // Case 3b: Look for other bidi parts on the next visual line + var nextCh = dir > 0 ? wrappedLineExtent.end : mv(wrappedLineExtent.begin, -1); + if (nextCh != null && !(dir > 0 && nextCh == line.text.length)) { + res = searchInVisualLine(dir > 0 ? 0 : bidi.length - 1, dir, getWrappedLineExtent(nextCh)); + if (res) { return res } + } + + // Case 4: Nowhere to move + return null + } + + // Commands are parameter-less actions that can be performed on an + // editor, mostly used for keybindings. + var commands = { + selectAll: selectAll, + singleSelection: function (cm) { return cm.setSelection(cm.getCursor("anchor"), cm.getCursor("head"), sel_dontScroll); }, + killLine: function (cm) { return deleteNearSelection(cm, function (range) { + if (range.empty()) { + var len = getLine(cm.doc, range.head.line).text.length; + if (range.head.ch == len && range.head.line < cm.lastLine()) + { return {from: range.head, to: Pos(range.head.line + 1, 0)} } + else + { return {from: range.head, to: Pos(range.head.line, len)} } + } else { + return {from: range.from(), to: range.to()} + } + }); }, + deleteLine: function (cm) { return deleteNearSelection(cm, function (range) { return ({ + from: Pos(range.from().line, 0), + to: clipPos(cm.doc, Pos(range.to().line + 1, 0)) + }); }); }, + delLineLeft: function (cm) { return deleteNearSelection(cm, function (range) { return ({ + from: Pos(range.from().line, 0), to: range.from() + }); }); }, + delWrappedLineLeft: function (cm) { return deleteNearSelection(cm, function (range) { + var top = cm.charCoords(range.head, "div").top + 5; + var leftPos = cm.coordsChar({left: 0, top: top}, "div"); + return {from: leftPos, to: range.from()} + }); }, + delWrappedLineRight: function (cm) { return deleteNearSelection(cm, function (range) { + var top = cm.charCoords(range.head, "div").top + 5; + var rightPos = cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div"); + return {from: range.from(), to: rightPos } + }); }, + undo: function (cm) { return cm.undo(); }, + redo: function (cm) { return cm.redo(); }, + undoSelection: function (cm) { return cm.undoSelection(); }, + redoSelection: function (cm) { return cm.redoSelection(); }, + goDocStart: function (cm) { return cm.extendSelection(Pos(cm.firstLine(), 0)); }, + goDocEnd: function (cm) { return cm.extendSelection(Pos(cm.lastLine())); }, + goLineStart: function (cm) { return cm.extendSelectionsBy(function (range) { return lineStart(cm, range.head.line); }, + {origin: "+move", bias: 1} + ); }, + goLineStartSmart: function (cm) { return cm.extendSelectionsBy(function (range) { return lineStartSmart(cm, range.head); }, + {origin: "+move", bias: 1} + ); }, + goLineEnd: function (cm) { return cm.extendSelectionsBy(function (range) { return lineEnd(cm, range.head.line); }, + {origin: "+move", bias: -1} + ); }, + goLineRight: function (cm) { return cm.extendSelectionsBy(function (range) { + var top = cm.cursorCoords(range.head, "div").top + 5; + return cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div") + }, sel_move); }, + goLineLeft: function (cm) { return cm.extendSelectionsBy(function (range) { + var top = cm.cursorCoords(range.head, "div").top + 5; + return cm.coordsChar({left: 0, top: top}, "div") + }, sel_move); }, + goLineLeftSmart: function (cm) { return cm.extendSelectionsBy(function (range) { + var top = cm.cursorCoords(range.head, "div").top + 5; + var pos = cm.coordsChar({left: 0, top: top}, "div"); + if (pos.ch < cm.getLine(pos.line).search(/\S/)) { return lineStartSmart(cm, range.head) } + return pos + }, sel_move); }, + goLineUp: function (cm) { return cm.moveV(-1, "line"); }, + goLineDown: function (cm) { return cm.moveV(1, "line"); }, + goPageUp: function (cm) { return cm.moveV(-1, "page"); }, + goPageDown: function (cm) { return cm.moveV(1, "page"); }, + goCharLeft: function (cm) { return cm.moveH(-1, "char"); }, + goCharRight: function (cm) { return cm.moveH(1, "char"); }, + goColumnLeft: function (cm) { return cm.moveH(-1, "column"); }, + goColumnRight: function (cm) { return cm.moveH(1, "column"); }, + goWordLeft: function (cm) { return cm.moveH(-1, "word"); }, + goGroupRight: function (cm) { return cm.moveH(1, "group"); }, + goGroupLeft: function (cm) { return cm.moveH(-1, "group"); }, + goWordRight: function (cm) { return cm.moveH(1, "word"); }, + delCharBefore: function (cm) { return cm.deleteH(-1, "codepoint"); }, + delCharAfter: function (cm) { return cm.deleteH(1, "char"); }, + delWordBefore: function (cm) { return cm.deleteH(-1, "word"); }, + delWordAfter: function (cm) { return cm.deleteH(1, "word"); }, + delGroupBefore: function (cm) { return cm.deleteH(-1, "group"); }, + delGroupAfter: function (cm) { return cm.deleteH(1, "group"); }, + indentAuto: function (cm) { return cm.indentSelection("smart"); }, + indentMore: function (cm) { return cm.indentSelection("add"); }, + indentLess: function (cm) { return cm.indentSelection("subtract"); }, + insertTab: function (cm) { return cm.replaceSelection("\t"); }, + insertSoftTab: function (cm) { + var spaces = [], ranges = cm.listSelections(), tabSize = cm.options.tabSize; + for (var i = 0; i < ranges.length; i++) { + var pos = ranges[i].from(); + var col = countColumn(cm.getLine(pos.line), pos.ch, tabSize); + spaces.push(spaceStr(tabSize - col % tabSize)); + } + cm.replaceSelections(spaces); + }, + defaultTab: function (cm) { + if (cm.somethingSelected()) { cm.indentSelection("add"); } + else { cm.execCommand("insertTab"); } + }, + // Swap the two chars left and right of each selection's head. + // Move cursor behind the two swapped characters afterwards. + // + // Doesn't consider line feeds a character. + // Doesn't scan more than one line above to find a character. + // Doesn't do anything on an empty line. + // Doesn't do anything with non-empty selections. + transposeChars: function (cm) { return runInOp(cm, function () { + var ranges = cm.listSelections(), newSel = []; + for (var i = 0; i < ranges.length; i++) { + if (!ranges[i].empty()) { continue } + var cur = ranges[i].head, line = getLine(cm.doc, cur.line).text; + if (line) { + if (cur.ch == line.length) { cur = new Pos(cur.line, cur.ch - 1); } + if (cur.ch > 0) { + cur = new Pos(cur.line, cur.ch + 1); + cm.replaceRange(line.charAt(cur.ch - 1) + line.charAt(cur.ch - 2), + Pos(cur.line, cur.ch - 2), cur, "+transpose"); + } else if (cur.line > cm.doc.first) { + var prev = getLine(cm.doc, cur.line - 1).text; + if (prev) { + cur = new Pos(cur.line, 1); + cm.replaceRange(line.charAt(0) + cm.doc.lineSeparator() + + prev.charAt(prev.length - 1), + Pos(cur.line - 1, prev.length - 1), cur, "+transpose"); + } + } + } + newSel.push(new Range(cur, cur)); + } + cm.setSelections(newSel); + }); }, + newlineAndIndent: function (cm) { return runInOp(cm, function () { + var sels = cm.listSelections(); + for (var i = sels.length - 1; i >= 0; i--) + { cm.replaceRange(cm.doc.lineSeparator(), sels[i].anchor, sels[i].head, "+input"); } + sels = cm.listSelections(); + for (var i$1 = 0; i$1 < sels.length; i$1++) + { cm.indentLine(sels[i$1].from().line, null, true); } + ensureCursorVisible(cm); + }); }, + openLine: function (cm) { return cm.replaceSelection("\n", "start"); }, + toggleOverwrite: function (cm) { return cm.toggleOverwrite(); } + }; + + + function lineStart(cm, lineN) { + var line = getLine(cm.doc, lineN); + var visual = visualLine(line); + if (visual != line) { lineN = lineNo(visual); } + return endOfLine(true, cm, visual, lineN, 1) + } + function lineEnd(cm, lineN) { + var line = getLine(cm.doc, lineN); + var visual = visualLineEnd(line); + if (visual != line) { lineN = lineNo(visual); } + return endOfLine(true, cm, line, lineN, -1) + } + function lineStartSmart(cm, pos) { + var start = lineStart(cm, pos.line); + var line = getLine(cm.doc, start.line); + var order = getOrder(line, cm.doc.direction); + if (!order || order[0].level == 0) { + var firstNonWS = Math.max(start.ch, line.text.search(/\S/)); + var inWS = pos.line == start.line && pos.ch <= firstNonWS && pos.ch; + return Pos(start.line, inWS ? 0 : firstNonWS, start.sticky) + } + return start + } + + // Run a handler that was bound to a key. + function doHandleBinding(cm, bound, dropShift) { + if (typeof bound == "string") { + bound = commands[bound]; + if (!bound) { return false } + } + // Ensure previous input has been read, so that the handler sees a + // consistent view of the document + cm.display.input.ensurePolled(); + var prevShift = cm.display.shift, done = false; + try { + if (cm.isReadOnly()) { cm.state.suppressEdits = true; } + if (dropShift) { cm.display.shift = false; } + done = bound(cm) != Pass; + } finally { + cm.display.shift = prevShift; + cm.state.suppressEdits = false; + } + return done + } + + function lookupKeyForEditor(cm, name, handle) { + for (var i = 0; i < cm.state.keyMaps.length; i++) { + var result = lookupKey(name, cm.state.keyMaps[i], handle, cm); + if (result) { return result } + } + return (cm.options.extraKeys && lookupKey(name, cm.options.extraKeys, handle, cm)) + || lookupKey(name, cm.options.keyMap, handle, cm) + } + + // Note that, despite the name, this function is also used to check + // for bound mouse clicks. + + var stopSeq = new Delayed; + + function dispatchKey(cm, name, e, handle) { + var seq = cm.state.keySeq; + if (seq) { + if (isModifierKey(name)) { return "handled" } + if (/\'$/.test(name)) + { cm.state.keySeq = null; } + else + { stopSeq.set(50, function () { + if (cm.state.keySeq == seq) { + cm.state.keySeq = null; + cm.display.input.reset(); + } + }); } + if (dispatchKeyInner(cm, seq + " " + name, e, handle)) { return true } + } + return dispatchKeyInner(cm, name, e, handle) + } + + function dispatchKeyInner(cm, name, e, handle) { + var result = lookupKeyForEditor(cm, name, handle); + + if (result == "multi") + { cm.state.keySeq = name; } + if (result == "handled") + { signalLater(cm, "keyHandled", cm, name, e); } + + if (result == "handled" || result == "multi") { + e_preventDefault(e); + restartBlink(cm); + } + + return !!result + } + + // Handle a key from the keydown event. + function handleKeyBinding(cm, e) { + var name = keyName(e, true); + if (!name) { return false } + + if (e.shiftKey && !cm.state.keySeq) { + // First try to resolve full name (including 'Shift-'). Failing + // that, see if there is a cursor-motion command (starting with + // 'go') bound to the keyname without 'Shift-'. + return dispatchKey(cm, "Shift-" + name, e, function (b) { return doHandleBinding(cm, b, true); }) + || dispatchKey(cm, name, e, function (b) { + if (typeof b == "string" ? /^go[A-Z]/.test(b) : b.motion) + { return doHandleBinding(cm, b) } + }) + } else { + return dispatchKey(cm, name, e, function (b) { return doHandleBinding(cm, b); }) + } + } + + // Handle a key from the keypress event + function handleCharBinding(cm, e, ch) { + return dispatchKey(cm, "'" + ch + "'", e, function (b) { return doHandleBinding(cm, b, true); }) + } + + var lastStoppedKey = null; + function onKeyDown(e) { + var cm = this; + if (e.target && e.target != cm.display.input.getField()) { return } + cm.curOp.focus = activeElt(doc(cm)); + if (signalDOMEvent(cm, e)) { return } + // IE does strange things with escape. + if (ie && ie_version < 11 && e.keyCode == 27) { e.returnValue = false; } + var code = e.keyCode; + cm.display.shift = code == 16 || e.shiftKey; + var handled = handleKeyBinding(cm, e); + if (presto) { + lastStoppedKey = handled ? code : null; + // Opera has no cut event... we try to at least catch the key combo + if (!handled && code == 88 && !hasCopyEvent && (mac ? e.metaKey : e.ctrlKey)) + { cm.replaceSelection("", null, "cut"); } + } + if (gecko && !mac && !handled && code == 46 && e.shiftKey && !e.ctrlKey && document.execCommand) + { document.execCommand("cut"); } + + // Turn mouse into crosshair when Alt is held on Mac. + if (code == 18 && !/\bCodeMirror-crosshair\b/.test(cm.display.lineDiv.className)) + { showCrossHair(cm); } + } + + function showCrossHair(cm) { + var lineDiv = cm.display.lineDiv; + addClass(lineDiv, "CodeMirror-crosshair"); + + function up(e) { + if (e.keyCode == 18 || !e.altKey) { + rmClass(lineDiv, "CodeMirror-crosshair"); + off(document, "keyup", up); + off(document, "mouseover", up); + } + } + on(document, "keyup", up); + on(document, "mouseover", up); + } + + function onKeyUp(e) { + if (e.keyCode == 16) { this.doc.sel.shift = false; } + signalDOMEvent(this, e); + } + + function onKeyPress(e) { + var cm = this; + if (e.target && e.target != cm.display.input.getField()) { return } + if (eventInWidget(cm.display, e) || signalDOMEvent(cm, e) || e.ctrlKey && !e.altKey || mac && e.metaKey) { return } + var keyCode = e.keyCode, charCode = e.charCode; + if (presto && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return} + if ((presto && (!e.which || e.which < 10)) && handleKeyBinding(cm, e)) { return } + var ch = String.fromCharCode(charCode == null ? keyCode : charCode); + // Some browsers fire keypress events for backspace + if (ch == "\x08") { return } + if (handleCharBinding(cm, e, ch)) { return } + cm.display.input.onKeyPress(e); + } + + var DOUBLECLICK_DELAY = 400; + + var PastClick = function(time, pos, button) { + this.time = time; + this.pos = pos; + this.button = button; + }; + + PastClick.prototype.compare = function (time, pos, button) { + return this.time + DOUBLECLICK_DELAY > time && + cmp(pos, this.pos) == 0 && button == this.button + }; + + var lastClick, lastDoubleClick; + function clickRepeat(pos, button) { + var now = +new Date; + if (lastDoubleClick && lastDoubleClick.compare(now, pos, button)) { + lastClick = lastDoubleClick = null; + return "triple" + } else if (lastClick && lastClick.compare(now, pos, button)) { + lastDoubleClick = new PastClick(now, pos, button); + lastClick = null; + return "double" + } else { + lastClick = new PastClick(now, pos, button); + lastDoubleClick = null; + return "single" + } + } + + // A mouse down can be a single click, double click, triple click, + // start of selection drag, start of text drag, new cursor + // (ctrl-click), rectangle drag (alt-drag), or xwin + // middle-click-paste. Or it might be a click on something we should + // not interfere with, such as a scrollbar or widget. + function onMouseDown(e) { + var cm = this, display = cm.display; + if (signalDOMEvent(cm, e) || display.activeTouch && display.input.supportsTouch()) { return } + display.input.ensurePolled(); + display.shift = e.shiftKey; + + if (eventInWidget(display, e)) { + if (!webkit) { + // Briefly turn off draggability, to allow widgets to do + // normal dragging things. + display.scroller.draggable = false; + setTimeout(function () { return display.scroller.draggable = true; }, 100); + } + return + } + if (clickInGutter(cm, e)) { return } + var pos = posFromMouse(cm, e), button = e_button(e), repeat = pos ? clickRepeat(pos, button) : "single"; + win(cm).focus(); + + // #3261: make sure, that we're not starting a second selection + if (button == 1 && cm.state.selectingText) + { cm.state.selectingText(e); } + + if (pos && handleMappedButton(cm, button, pos, repeat, e)) { return } + + if (button == 1) { + if (pos) { leftButtonDown(cm, pos, repeat, e); } + else if (e_target(e) == display.scroller) { e_preventDefault(e); } + } else if (button == 2) { + if (pos) { extendSelection(cm.doc, pos); } + setTimeout(function () { return display.input.focus(); }, 20); + } else if (button == 3) { + if (captureRightClick) { cm.display.input.onContextMenu(e); } + else { delayBlurEvent(cm); } + } + } + + function handleMappedButton(cm, button, pos, repeat, event) { + var name = "Click"; + if (repeat == "double") { name = "Double" + name; } + else if (repeat == "triple") { name = "Triple" + name; } + name = (button == 1 ? "Left" : button == 2 ? "Middle" : "Right") + name; + + return dispatchKey(cm, addModifierNames(name, event), event, function (bound) { + if (typeof bound == "string") { bound = commands[bound]; } + if (!bound) { return false } + var done = false; + try { + if (cm.isReadOnly()) { cm.state.suppressEdits = true; } + done = bound(cm, pos) != Pass; + } finally { + cm.state.suppressEdits = false; + } + return done + }) + } + + function configureMouse(cm, repeat, event) { + var option = cm.getOption("configureMouse"); + var value = option ? option(cm, repeat, event) : {}; + if (value.unit == null) { + var rect = chromeOS ? event.shiftKey && event.metaKey : event.altKey; + value.unit = rect ? "rectangle" : repeat == "single" ? "char" : repeat == "double" ? "word" : "line"; + } + if (value.extend == null || cm.doc.extend) { value.extend = cm.doc.extend || event.shiftKey; } + if (value.addNew == null) { value.addNew = mac ? event.metaKey : event.ctrlKey; } + if (value.moveOnDrag == null) { value.moveOnDrag = !(mac ? event.altKey : event.ctrlKey); } + return value + } + + function leftButtonDown(cm, pos, repeat, event) { + if (ie) { setTimeout(bind(ensureFocus, cm), 0); } + else { cm.curOp.focus = activeElt(doc(cm)); } + + var behavior = configureMouse(cm, repeat, event); + + var sel = cm.doc.sel, contained; + if (cm.options.dragDrop && dragAndDrop && !cm.isReadOnly() && + repeat == "single" && (contained = sel.contains(pos)) > -1 && + (cmp((contained = sel.ranges[contained]).from(), pos) < 0 || pos.xRel > 0) && + (cmp(contained.to(), pos) > 0 || pos.xRel < 0)) + { leftButtonStartDrag(cm, event, pos, behavior); } + else + { leftButtonSelect(cm, event, pos, behavior); } + } + + // Start a text drag. When it ends, see if any dragging actually + // happen, and treat as a click if it didn't. + function leftButtonStartDrag(cm, event, pos, behavior) { + var display = cm.display, moved = false; + var dragEnd = operation(cm, function (e) { + if (webkit) { display.scroller.draggable = false; } + cm.state.draggingText = false; + if (cm.state.delayingBlurEvent) { + if (cm.hasFocus()) { cm.state.delayingBlurEvent = false; } + else { delayBlurEvent(cm); } + } + off(display.wrapper.ownerDocument, "mouseup", dragEnd); + off(display.wrapper.ownerDocument, "mousemove", mouseMove); + off(display.scroller, "dragstart", dragStart); + off(display.scroller, "drop", dragEnd); + if (!moved) { + e_preventDefault(e); + if (!behavior.addNew) + { extendSelection(cm.doc, pos, null, null, behavior.extend); } + // Work around unexplainable focus problem in IE9 (#2127) and Chrome (#3081) + if ((webkit && !safari) || ie && ie_version == 9) + { setTimeout(function () {display.wrapper.ownerDocument.body.focus({preventScroll: true}); display.input.focus();}, 20); } + else + { display.input.focus(); } + } + }); + var mouseMove = function(e2) { + moved = moved || Math.abs(event.clientX - e2.clientX) + Math.abs(event.clientY - e2.clientY) >= 10; + }; + var dragStart = function () { return moved = true; }; + // Let the drag handler handle this. + if (webkit) { display.scroller.draggable = true; } + cm.state.draggingText = dragEnd; + dragEnd.copy = !behavior.moveOnDrag; + on(display.wrapper.ownerDocument, "mouseup", dragEnd); + on(display.wrapper.ownerDocument, "mousemove", mouseMove); + on(display.scroller, "dragstart", dragStart); + on(display.scroller, "drop", dragEnd); + + cm.state.delayingBlurEvent = true; + setTimeout(function () { return display.input.focus(); }, 20); + // IE's approach to draggable + if (display.scroller.dragDrop) { display.scroller.dragDrop(); } + } + + function rangeForUnit(cm, pos, unit) { + if (unit == "char") { return new Range(pos, pos) } + if (unit == "word") { return cm.findWordAt(pos) } + if (unit == "line") { return new Range(Pos(pos.line, 0), clipPos(cm.doc, Pos(pos.line + 1, 0))) } + var result = unit(cm, pos); + return new Range(result.from, result.to) + } + + // Normal selection, as opposed to text dragging. + function leftButtonSelect(cm, event, start, behavior) { + if (ie) { delayBlurEvent(cm); } + var display = cm.display, doc$1 = cm.doc; + e_preventDefault(event); + + var ourRange, ourIndex, startSel = doc$1.sel, ranges = startSel.ranges; + if (behavior.addNew && !behavior.extend) { + ourIndex = doc$1.sel.contains(start); + if (ourIndex > -1) + { ourRange = ranges[ourIndex]; } + else + { ourRange = new Range(start, start); } + } else { + ourRange = doc$1.sel.primary(); + ourIndex = doc$1.sel.primIndex; + } + + if (behavior.unit == "rectangle") { + if (!behavior.addNew) { ourRange = new Range(start, start); } + start = posFromMouse(cm, event, true, true); + ourIndex = -1; + } else { + var range = rangeForUnit(cm, start, behavior.unit); + if (behavior.extend) + { ourRange = extendRange(ourRange, range.anchor, range.head, behavior.extend); } + else + { ourRange = range; } + } + + if (!behavior.addNew) { + ourIndex = 0; + setSelection(doc$1, new Selection([ourRange], 0), sel_mouse); + startSel = doc$1.sel; + } else if (ourIndex == -1) { + ourIndex = ranges.length; + setSelection(doc$1, normalizeSelection(cm, ranges.concat([ourRange]), ourIndex), + {scroll: false, origin: "*mouse"}); + } else if (ranges.length > 1 && ranges[ourIndex].empty() && behavior.unit == "char" && !behavior.extend) { + setSelection(doc$1, normalizeSelection(cm, ranges.slice(0, ourIndex).concat(ranges.slice(ourIndex + 1)), 0), + {scroll: false, origin: "*mouse"}); + startSel = doc$1.sel; + } else { + replaceOneSelection(doc$1, ourIndex, ourRange, sel_mouse); + } + + var lastPos = start; + function extendTo(pos) { + if (cmp(lastPos, pos) == 0) { return } + lastPos = pos; + + if (behavior.unit == "rectangle") { + var ranges = [], tabSize = cm.options.tabSize; + var startCol = countColumn(getLine(doc$1, start.line).text, start.ch, tabSize); + var posCol = countColumn(getLine(doc$1, pos.line).text, pos.ch, tabSize); + var left = Math.min(startCol, posCol), right = Math.max(startCol, posCol); + for (var line = Math.min(start.line, pos.line), end = Math.min(cm.lastLine(), Math.max(start.line, pos.line)); + line <= end; line++) { + var text = getLine(doc$1, line).text, leftPos = findColumn(text, left, tabSize); + if (left == right) + { ranges.push(new Range(Pos(line, leftPos), Pos(line, leftPos))); } + else if (text.length > leftPos) + { ranges.push(new Range(Pos(line, leftPos), Pos(line, findColumn(text, right, tabSize)))); } + } + if (!ranges.length) { ranges.push(new Range(start, start)); } + setSelection(doc$1, normalizeSelection(cm, startSel.ranges.slice(0, ourIndex).concat(ranges), ourIndex), + {origin: "*mouse", scroll: false}); + cm.scrollIntoView(pos); + } else { + var oldRange = ourRange; + var range = rangeForUnit(cm, pos, behavior.unit); + var anchor = oldRange.anchor, head; + if (cmp(range.anchor, anchor) > 0) { + head = range.head; + anchor = minPos(oldRange.from(), range.anchor); + } else { + head = range.anchor; + anchor = maxPos(oldRange.to(), range.head); + } + var ranges$1 = startSel.ranges.slice(0); + ranges$1[ourIndex] = bidiSimplify(cm, new Range(clipPos(doc$1, anchor), head)); + setSelection(doc$1, normalizeSelection(cm, ranges$1, ourIndex), sel_mouse); + } + } + + var editorSize = display.wrapper.getBoundingClientRect(); + // Used to ensure timeout re-tries don't fire when another extend + // happened in the meantime (clearTimeout isn't reliable -- at + // least on Chrome, the timeouts still happen even when cleared, + // if the clear happens after their scheduled firing time). + var counter = 0; + + function extend(e) { + var curCount = ++counter; + var cur = posFromMouse(cm, e, true, behavior.unit == "rectangle"); + if (!cur) { return } + if (cmp(cur, lastPos) != 0) { + cm.curOp.focus = activeElt(doc(cm)); + extendTo(cur); + var visible = visibleLines(display, doc$1); + if (cur.line >= visible.to || cur.line < visible.from) + { setTimeout(operation(cm, function () {if (counter == curCount) { extend(e); }}), 150); } + } else { + var outside = e.clientY < editorSize.top ? -20 : e.clientY > editorSize.bottom ? 20 : 0; + if (outside) { setTimeout(operation(cm, function () { + if (counter != curCount) { return } + display.scroller.scrollTop += outside; + extend(e); + }), 50); } + } + } + + function done(e) { + cm.state.selectingText = false; + counter = Infinity; + // If e is null or undefined we interpret this as someone trying + // to explicitly cancel the selection rather than the user + // letting go of the mouse button. + if (e) { + e_preventDefault(e); + display.input.focus(); + } + off(display.wrapper.ownerDocument, "mousemove", move); + off(display.wrapper.ownerDocument, "mouseup", up); + doc$1.history.lastSelOrigin = null; + } + + var move = operation(cm, function (e) { + if (e.buttons === 0 || !e_button(e)) { done(e); } + else { extend(e); } + }); + var up = operation(cm, done); + cm.state.selectingText = up; + on(display.wrapper.ownerDocument, "mousemove", move); + on(display.wrapper.ownerDocument, "mouseup", up); + } + + // Used when mouse-selecting to adjust the anchor to the proper side + // of a bidi jump depending on the visual position of the head. + function bidiSimplify(cm, range) { + var anchor = range.anchor; + var head = range.head; + var anchorLine = getLine(cm.doc, anchor.line); + if (cmp(anchor, head) == 0 && anchor.sticky == head.sticky) { return range } + var order = getOrder(anchorLine); + if (!order) { return range } + var index = getBidiPartAt(order, anchor.ch, anchor.sticky), part = order[index]; + if (part.from != anchor.ch && part.to != anchor.ch) { return range } + var boundary = index + ((part.from == anchor.ch) == (part.level != 1) ? 0 : 1); + if (boundary == 0 || boundary == order.length) { return range } + + // Compute the relative visual position of the head compared to the + // anchor (<0 is to the left, >0 to the right) + var leftSide; + if (head.line != anchor.line) { + leftSide = (head.line - anchor.line) * (cm.doc.direction == "ltr" ? 1 : -1) > 0; + } else { + var headIndex = getBidiPartAt(order, head.ch, head.sticky); + var dir = headIndex - index || (head.ch - anchor.ch) * (part.level == 1 ? -1 : 1); + if (headIndex == boundary - 1 || headIndex == boundary) + { leftSide = dir < 0; } + else + { leftSide = dir > 0; } + } + + var usePart = order[boundary + (leftSide ? -1 : 0)]; + var from = leftSide == (usePart.level == 1); + var ch = from ? usePart.from : usePart.to, sticky = from ? "after" : "before"; + return anchor.ch == ch && anchor.sticky == sticky ? range : new Range(new Pos(anchor.line, ch, sticky), head) + } + + + // Determines whether an event happened in the gutter, and fires the + // handlers for the corresponding event. + function gutterEvent(cm, e, type, prevent) { + var mX, mY; + if (e.touches) { + mX = e.touches[0].clientX; + mY = e.touches[0].clientY; + } else { + try { mX = e.clientX; mY = e.clientY; } + catch(e$1) { return false } + } + if (mX >= Math.floor(cm.display.gutters.getBoundingClientRect().right)) { return false } + if (prevent) { e_preventDefault(e); } + + var display = cm.display; + var lineBox = display.lineDiv.getBoundingClientRect(); + + if (mY > lineBox.bottom || !hasHandler(cm, type)) { return e_defaultPrevented(e) } + mY -= lineBox.top - display.viewOffset; + + for (var i = 0; i < cm.display.gutterSpecs.length; ++i) { + var g = display.gutters.childNodes[i]; + if (g && g.getBoundingClientRect().right >= mX) { + var line = lineAtHeight(cm.doc, mY); + var gutter = cm.display.gutterSpecs[i]; + signal(cm, type, cm, line, gutter.className, e); + return e_defaultPrevented(e) + } + } + } + + function clickInGutter(cm, e) { + return gutterEvent(cm, e, "gutterClick", true) + } + + // CONTEXT MENU HANDLING + + // To make the context menu work, we need to briefly unhide the + // textarea (making it as unobtrusive as possible) to let the + // right-click take effect on it. + function onContextMenu(cm, e) { + if (eventInWidget(cm.display, e) || contextMenuInGutter(cm, e)) { return } + if (signalDOMEvent(cm, e, "contextmenu")) { return } + if (!captureRightClick) { cm.display.input.onContextMenu(e); } + } + + function contextMenuInGutter(cm, e) { + if (!hasHandler(cm, "gutterContextMenu")) { return false } + return gutterEvent(cm, e, "gutterContextMenu", false) + } + + function themeChanged(cm) { + cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-s-\S+/g, "") + + cm.options.theme.replace(/(^|\s)\s*/g, " cm-s-"); + clearCaches(cm); + } + + var Init = {toString: function(){return "CodeMirror.Init"}}; + + var defaults = {}; + var optionHandlers = {}; + + function defineOptions(CodeMirror) { + var optionHandlers = CodeMirror.optionHandlers; + + function option(name, deflt, handle, notOnInit) { + CodeMirror.defaults[name] = deflt; + if (handle) { optionHandlers[name] = + notOnInit ? function (cm, val, old) {if (old != Init) { handle(cm, val, old); }} : handle; } + } + + CodeMirror.defineOption = option; + + // Passed to option handlers when there is no old value. + CodeMirror.Init = Init; + + // These two are, on init, called from the constructor because they + // have to be initialized before the editor can start at all. + option("value", "", function (cm, val) { return cm.setValue(val); }, true); + option("mode", null, function (cm, val) { + cm.doc.modeOption = val; + loadMode(cm); + }, true); + + option("indentUnit", 2, loadMode, true); + option("indentWithTabs", false); + option("smartIndent", true); + option("tabSize", 4, function (cm) { + resetModeState(cm); + clearCaches(cm); + regChange(cm); + }, true); + + option("lineSeparator", null, function (cm, val) { + cm.doc.lineSep = val; + if (!val) { return } + var newBreaks = [], lineNo = cm.doc.first; + cm.doc.iter(function (line) { + for (var pos = 0;;) { + var found = line.text.indexOf(val, pos); + if (found == -1) { break } + pos = found + val.length; + newBreaks.push(Pos(lineNo, found)); + } + lineNo++; + }); + for (var i = newBreaks.length - 1; i >= 0; i--) + { replaceRange(cm.doc, val, newBreaks[i], Pos(newBreaks[i].line, newBreaks[i].ch + val.length)); } + }); + option("specialChars", /[\u0000-\u001f\u007f-\u009f\u00ad\u061c\u200b\u200e\u200f\u2028\u2029\u202d\u202e\u2066\u2067\u2069\ufeff\ufff9-\ufffc]/g, function (cm, val, old) { + cm.state.specialChars = new RegExp(val.source + (val.test("\t") ? "" : "|\t"), "g"); + if (old != Init) { cm.refresh(); } + }); + option("specialCharPlaceholder", defaultSpecialCharPlaceholder, function (cm) { return cm.refresh(); }, true); + option("electricChars", true); + option("inputStyle", mobile ? "contenteditable" : "textarea", function () { + throw new Error("inputStyle can not (yet) be changed in a running editor") // FIXME + }, true); + option("spellcheck", false, function (cm, val) { return cm.getInputField().spellcheck = val; }, true); + option("autocorrect", false, function (cm, val) { return cm.getInputField().autocorrect = val; }, true); + option("autocapitalize", false, function (cm, val) { return cm.getInputField().autocapitalize = val; }, true); + option("rtlMoveVisually", !windows); + option("wholeLineUpdateBefore", true); + + option("theme", "default", function (cm) { + themeChanged(cm); + updateGutters(cm); + }, true); + option("keyMap", "default", function (cm, val, old) { + var next = getKeyMap(val); + var prev = old != Init && getKeyMap(old); + if (prev && prev.detach) { prev.detach(cm, next); } + if (next.attach) { next.attach(cm, prev || null); } + }); + option("extraKeys", null); + option("configureMouse", null); + + option("lineWrapping", false, wrappingChanged, true); + option("gutters", [], function (cm, val) { + cm.display.gutterSpecs = getGutters(val, cm.options.lineNumbers); + updateGutters(cm); + }, true); + option("fixedGutter", true, function (cm, val) { + cm.display.gutters.style.left = val ? compensateForHScroll(cm.display) + "px" : "0"; + cm.refresh(); + }, true); + option("coverGutterNextToScrollbar", false, function (cm) { return updateScrollbars(cm); }, true); + option("scrollbarStyle", "native", function (cm) { + initScrollbars(cm); + updateScrollbars(cm); + cm.display.scrollbars.setScrollTop(cm.doc.scrollTop); + cm.display.scrollbars.setScrollLeft(cm.doc.scrollLeft); + }, true); + option("lineNumbers", false, function (cm, val) { + cm.display.gutterSpecs = getGutters(cm.options.gutters, val); + updateGutters(cm); + }, true); + option("firstLineNumber", 1, updateGutters, true); + option("lineNumberFormatter", function (integer) { return integer; }, updateGutters, true); + option("showCursorWhenSelecting", false, updateSelection, true); + + option("resetSelectionOnContextMenu", true); + option("lineWiseCopyCut", true); + option("pasteLinesPerSelection", true); + option("selectionsMayTouch", false); + + option("readOnly", false, function (cm, val) { + if (val == "nocursor") { + onBlur(cm); + cm.display.input.blur(); + } + cm.display.input.readOnlyChanged(val); + }); + + option("screenReaderLabel", null, function (cm, val) { + val = (val === '') ? null : val; + cm.display.input.screenReaderLabelChanged(val); + }); + + option("disableInput", false, function (cm, val) {if (!val) { cm.display.input.reset(); }}, true); + option("dragDrop", true, dragDropChanged); + option("allowDropFileTypes", null); + + option("cursorBlinkRate", 530); + option("cursorScrollMargin", 0); + option("cursorHeight", 1, updateSelection, true); + option("singleCursorHeightPerLine", true, updateSelection, true); + option("workTime", 100); + option("workDelay", 100); + option("flattenSpans", true, resetModeState, true); + option("addModeClass", false, resetModeState, true); + option("pollInterval", 100); + option("undoDepth", 200, function (cm, val) { return cm.doc.history.undoDepth = val; }); + option("historyEventDelay", 1250); + option("viewportMargin", 10, function (cm) { return cm.refresh(); }, true); + option("maxHighlightLength", 10000, resetModeState, true); + option("moveInputWithCursor", true, function (cm, val) { + if (!val) { cm.display.input.resetPosition(); } + }); + + option("tabindex", null, function (cm, val) { return cm.display.input.getField().tabIndex = val || ""; }); + option("autofocus", null); + option("direction", "ltr", function (cm, val) { return cm.doc.setDirection(val); }, true); + option("phrases", null); + } + + function dragDropChanged(cm, value, old) { + var wasOn = old && old != Init; + if (!value != !wasOn) { + var funcs = cm.display.dragFunctions; + var toggle = value ? on : off; + toggle(cm.display.scroller, "dragstart", funcs.start); + toggle(cm.display.scroller, "dragenter", funcs.enter); + toggle(cm.display.scroller, "dragover", funcs.over); + toggle(cm.display.scroller, "dragleave", funcs.leave); + toggle(cm.display.scroller, "drop", funcs.drop); + } + } + + function wrappingChanged(cm) { + if (cm.options.lineWrapping) { + addClass(cm.display.wrapper, "CodeMirror-wrap"); + cm.display.sizer.style.minWidth = ""; + cm.display.sizerWidth = null; + } else { + rmClass(cm.display.wrapper, "CodeMirror-wrap"); + findMaxLine(cm); + } + estimateLineHeights(cm); + regChange(cm); + clearCaches(cm); + setTimeout(function () { return updateScrollbars(cm); }, 100); + } + + // A CodeMirror instance represents an editor. This is the object + // that user code is usually dealing with. + + function CodeMirror(place, options) { + var this$1 = this; + + if (!(this instanceof CodeMirror)) { return new CodeMirror(place, options) } + + this.options = options = options ? copyObj(options) : {}; + // Determine effective options based on given values and defaults. + copyObj(defaults, options, false); + + var doc = options.value; + if (typeof doc == "string") { doc = new Doc(doc, options.mode, null, options.lineSeparator, options.direction); } + else if (options.mode) { doc.modeOption = options.mode; } + this.doc = doc; + + var input = new CodeMirror.inputStyles[options.inputStyle](this); + var display = this.display = new Display(place, doc, input, options); + display.wrapper.CodeMirror = this; + themeChanged(this); + if (options.lineWrapping) + { this.display.wrapper.className += " CodeMirror-wrap"; } + initScrollbars(this); + + this.state = { + keyMaps: [], // stores maps added by addKeyMap + overlays: [], // highlighting overlays, as added by addOverlay + modeGen: 0, // bumped when mode/overlay changes, used to invalidate highlighting info + overwrite: false, + delayingBlurEvent: false, + focused: false, + suppressEdits: false, // used to disable editing during key handlers when in readOnly mode + pasteIncoming: -1, cutIncoming: -1, // help recognize paste/cut edits in input.poll + selectingText: false, + draggingText: false, + highlight: new Delayed(), // stores highlight worker timeout + keySeq: null, // Unfinished key sequence + specialChars: null + }; + + if (options.autofocus && !mobile) { display.input.focus(); } + + // Override magic textarea content restore that IE sometimes does + // on our hidden textarea on reload + if (ie && ie_version < 11) { setTimeout(function () { return this$1.display.input.reset(true); }, 20); } + + registerEventHandlers(this); + ensureGlobalHandlers(); + + startOperation(this); + this.curOp.forceUpdate = true; + attachDoc(this, doc); + + if ((options.autofocus && !mobile) || this.hasFocus()) + { setTimeout(function () { + if (this$1.hasFocus() && !this$1.state.focused) { onFocus(this$1); } + }, 20); } + else + { onBlur(this); } + + for (var opt in optionHandlers) { if (optionHandlers.hasOwnProperty(opt)) + { optionHandlers[opt](this, options[opt], Init); } } + maybeUpdateLineNumberWidth(this); + if (options.finishInit) { options.finishInit(this); } + for (var i = 0; i < initHooks.length; ++i) { initHooks[i](this); } + endOperation(this); + // Suppress optimizelegibility in Webkit, since it breaks text + // measuring on line wrapping boundaries. + if (webkit && options.lineWrapping && + getComputedStyle(display.lineDiv).textRendering == "optimizelegibility") + { display.lineDiv.style.textRendering = "auto"; } + } + + // The default configuration options. + CodeMirror.defaults = defaults; + // Functions to run when options are changed. + CodeMirror.optionHandlers = optionHandlers; + + // Attach the necessary event handlers when initializing the editor + function registerEventHandlers(cm) { + var d = cm.display; + on(d.scroller, "mousedown", operation(cm, onMouseDown)); + // Older IE's will not fire a second mousedown for a double click + if (ie && ie_version < 11) + { on(d.scroller, "dblclick", operation(cm, function (e) { + if (signalDOMEvent(cm, e)) { return } + var pos = posFromMouse(cm, e); + if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) { return } + e_preventDefault(e); + var word = cm.findWordAt(pos); + extendSelection(cm.doc, word.anchor, word.head); + })); } + else + { on(d.scroller, "dblclick", function (e) { return signalDOMEvent(cm, e) || e_preventDefault(e); }); } + // Some browsers fire contextmenu *after* opening the menu, at + // which point we can't mess with it anymore. Context menu is + // handled in onMouseDown for these browsers. + on(d.scroller, "contextmenu", function (e) { return onContextMenu(cm, e); }); + on(d.input.getField(), "contextmenu", function (e) { + if (!d.scroller.contains(e.target)) { onContextMenu(cm, e); } + }); + + // Used to suppress mouse event handling when a touch happens + var touchFinished, prevTouch = {end: 0}; + function finishTouch() { + if (d.activeTouch) { + touchFinished = setTimeout(function () { return d.activeTouch = null; }, 1000); + prevTouch = d.activeTouch; + prevTouch.end = +new Date; + } + } + function isMouseLikeTouchEvent(e) { + if (e.touches.length != 1) { return false } + var touch = e.touches[0]; + return touch.radiusX <= 1 && touch.radiusY <= 1 + } + function farAway(touch, other) { + if (other.left == null) { return true } + var dx = other.left - touch.left, dy = other.top - touch.top; + return dx * dx + dy * dy > 20 * 20 + } + on(d.scroller, "touchstart", function (e) { + if (!signalDOMEvent(cm, e) && !isMouseLikeTouchEvent(e) && !clickInGutter(cm, e)) { + d.input.ensurePolled(); + clearTimeout(touchFinished); + var now = +new Date; + d.activeTouch = {start: now, moved: false, + prev: now - prevTouch.end <= 300 ? prevTouch : null}; + if (e.touches.length == 1) { + d.activeTouch.left = e.touches[0].pageX; + d.activeTouch.top = e.touches[0].pageY; + } + } + }); + on(d.scroller, "touchmove", function () { + if (d.activeTouch) { d.activeTouch.moved = true; } + }); + on(d.scroller, "touchend", function (e) { + var touch = d.activeTouch; + if (touch && !eventInWidget(d, e) && touch.left != null && + !touch.moved && new Date - touch.start < 300) { + var pos = cm.coordsChar(d.activeTouch, "page"), range; + if (!touch.prev || farAway(touch, touch.prev)) // Single tap + { range = new Range(pos, pos); } + else if (!touch.prev.prev || farAway(touch, touch.prev.prev)) // Double tap + { range = cm.findWordAt(pos); } + else // Triple tap + { range = new Range(Pos(pos.line, 0), clipPos(cm.doc, Pos(pos.line + 1, 0))); } + cm.setSelection(range.anchor, range.head); + cm.focus(); + e_preventDefault(e); + } + finishTouch(); + }); + on(d.scroller, "touchcancel", finishTouch); + + // Sync scrolling between fake scrollbars and real scrollable + // area, ensure viewport is updated when scrolling. + on(d.scroller, "scroll", function () { + if (d.scroller.clientHeight) { + updateScrollTop(cm, d.scroller.scrollTop); + setScrollLeft(cm, d.scroller.scrollLeft, true); + signal(cm, "scroll", cm); + } + }); + + // Listen to wheel events in order to try and update the viewport on time. + on(d.scroller, "mousewheel", function (e) { return onScrollWheel(cm, e); }); + on(d.scroller, "DOMMouseScroll", function (e) { return onScrollWheel(cm, e); }); + + // Prevent wrapper from ever scrolling + on(d.wrapper, "scroll", function () { return d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; }); + + d.dragFunctions = { + enter: function (e) {if (!signalDOMEvent(cm, e)) { e_stop(e); }}, + over: function (e) {if (!signalDOMEvent(cm, e)) { onDragOver(cm, e); e_stop(e); }}, + start: function (e) { return onDragStart(cm, e); }, + drop: operation(cm, onDrop), + leave: function (e) {if (!signalDOMEvent(cm, e)) { clearDragCursor(cm); }} + }; + + var inp = d.input.getField(); + on(inp, "keyup", function (e) { return onKeyUp.call(cm, e); }); + on(inp, "keydown", operation(cm, onKeyDown)); + on(inp, "keypress", operation(cm, onKeyPress)); + on(inp, "focus", function (e) { return onFocus(cm, e); }); + on(inp, "blur", function (e) { return onBlur(cm, e); }); + } + + var initHooks = []; + CodeMirror.defineInitHook = function (f) { return initHooks.push(f); }; + + // Indent the given line. The how parameter can be "smart", + // "add"/null, "subtract", or "prev". When aggressive is false + // (typically set to true for forced single-line indents), empty + // lines are not indented, and places where the mode returns Pass + // are left alone. + function indentLine(cm, n, how, aggressive) { + var doc = cm.doc, state; + if (how == null) { how = "add"; } + if (how == "smart") { + // Fall back to "prev" when the mode doesn't have an indentation + // method. + if (!doc.mode.indent) { how = "prev"; } + else { state = getContextBefore(cm, n).state; } + } + + var tabSize = cm.options.tabSize; + var line = getLine(doc, n), curSpace = countColumn(line.text, null, tabSize); + if (line.stateAfter) { line.stateAfter = null; } + var curSpaceString = line.text.match(/^\s*/)[0], indentation; + if (!aggressive && !/\S/.test(line.text)) { + indentation = 0; + how = "not"; + } else if (how == "smart") { + indentation = doc.mode.indent(state, line.text.slice(curSpaceString.length), line.text); + if (indentation == Pass || indentation > 150) { + if (!aggressive) { return } + how = "prev"; + } + } + if (how == "prev") { + if (n > doc.first) { indentation = countColumn(getLine(doc, n-1).text, null, tabSize); } + else { indentation = 0; } + } else if (how == "add") { + indentation = curSpace + cm.options.indentUnit; + } else if (how == "subtract") { + indentation = curSpace - cm.options.indentUnit; + } else if (typeof how == "number") { + indentation = curSpace + how; + } + indentation = Math.max(0, indentation); + + var indentString = "", pos = 0; + if (cm.options.indentWithTabs) + { for (var i = Math.floor(indentation / tabSize); i; --i) {pos += tabSize; indentString += "\t";} } + if (pos < indentation) { indentString += spaceStr(indentation - pos); } + + if (indentString != curSpaceString) { + replaceRange(doc, indentString, Pos(n, 0), Pos(n, curSpaceString.length), "+input"); + line.stateAfter = null; + return true + } else { + // Ensure that, if the cursor was in the whitespace at the start + // of the line, it is moved to the end of that space. + for (var i$1 = 0; i$1 < doc.sel.ranges.length; i$1++) { + var range = doc.sel.ranges[i$1]; + if (range.head.line == n && range.head.ch < curSpaceString.length) { + var pos$1 = Pos(n, curSpaceString.length); + replaceOneSelection(doc, i$1, new Range(pos$1, pos$1)); + break + } + } + } + } + + // This will be set to a {lineWise: bool, text: [string]} object, so + // that, when pasting, we know what kind of selections the copied + // text was made out of. + var lastCopied = null; + + function setLastCopied(newLastCopied) { + lastCopied = newLastCopied; + } + + function applyTextInput(cm, inserted, deleted, sel, origin) { + var doc = cm.doc; + cm.display.shift = false; + if (!sel) { sel = doc.sel; } + + var recent = +new Date - 200; + var paste = origin == "paste" || cm.state.pasteIncoming > recent; + var textLines = splitLinesAuto(inserted), multiPaste = null; + // When pasting N lines into N selections, insert one line per selection + if (paste && sel.ranges.length > 1) { + if (lastCopied && lastCopied.text.join("\n") == inserted) { + if (sel.ranges.length % lastCopied.text.length == 0) { + multiPaste = []; + for (var i = 0; i < lastCopied.text.length; i++) + { multiPaste.push(doc.splitLines(lastCopied.text[i])); } + } + } else if (textLines.length == sel.ranges.length && cm.options.pasteLinesPerSelection) { + multiPaste = map(textLines, function (l) { return [l]; }); + } + } + + var updateInput = cm.curOp.updateInput; + // Normal behavior is to insert the new text into every selection + for (var i$1 = sel.ranges.length - 1; i$1 >= 0; i$1--) { + var range = sel.ranges[i$1]; + var from = range.from(), to = range.to(); + if (range.empty()) { + if (deleted && deleted > 0) // Handle deletion + { from = Pos(from.line, from.ch - deleted); } + else if (cm.state.overwrite && !paste) // Handle overwrite + { to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + lst(textLines).length)); } + else if (paste && lastCopied && lastCopied.lineWise && lastCopied.text.join("\n") == textLines.join("\n")) + { from = to = Pos(from.line, 0); } + } + var changeEvent = {from: from, to: to, text: multiPaste ? multiPaste[i$1 % multiPaste.length] : textLines, + origin: origin || (paste ? "paste" : cm.state.cutIncoming > recent ? "cut" : "+input")}; + makeChange(cm.doc, changeEvent); + signalLater(cm, "inputRead", cm, changeEvent); + } + if (inserted && !paste) + { triggerElectric(cm, inserted); } + + ensureCursorVisible(cm); + if (cm.curOp.updateInput < 2) { cm.curOp.updateInput = updateInput; } + cm.curOp.typing = true; + cm.state.pasteIncoming = cm.state.cutIncoming = -1; + } + + function handlePaste(e, cm) { + var pasted = e.clipboardData && e.clipboardData.getData("Text"); + if (pasted) { + e.preventDefault(); + if (!cm.isReadOnly() && !cm.options.disableInput && cm.hasFocus()) + { runInOp(cm, function () { return applyTextInput(cm, pasted, 0, null, "paste"); }); } + return true + } + } + + function triggerElectric(cm, inserted) { + // When an 'electric' character is inserted, immediately trigger a reindent + if (!cm.options.electricChars || !cm.options.smartIndent) { return } + var sel = cm.doc.sel; + + for (var i = sel.ranges.length - 1; i >= 0; i--) { + var range = sel.ranges[i]; + if (range.head.ch > 100 || (i && sel.ranges[i - 1].head.line == range.head.line)) { continue } + var mode = cm.getModeAt(range.head); + var indented = false; + if (mode.electricChars) { + for (var j = 0; j < mode.electricChars.length; j++) + { if (inserted.indexOf(mode.electricChars.charAt(j)) > -1) { + indented = indentLine(cm, range.head.line, "smart"); + break + } } + } else if (mode.electricInput) { + if (mode.electricInput.test(getLine(cm.doc, range.head.line).text.slice(0, range.head.ch))) + { indented = indentLine(cm, range.head.line, "smart"); } + } + if (indented) { signalLater(cm, "electricInput", cm, range.head.line); } + } + } + + function copyableRanges(cm) { + var text = [], ranges = []; + for (var i = 0; i < cm.doc.sel.ranges.length; i++) { + var line = cm.doc.sel.ranges[i].head.line; + var lineRange = {anchor: Pos(line, 0), head: Pos(line + 1, 0)}; + ranges.push(lineRange); + text.push(cm.getRange(lineRange.anchor, lineRange.head)); + } + return {text: text, ranges: ranges} + } + + function disableBrowserMagic(field, spellcheck, autocorrect, autocapitalize) { + field.setAttribute("autocorrect", autocorrect ? "on" : "off"); + field.setAttribute("autocapitalize", autocapitalize ? "on" : "off"); + field.setAttribute("spellcheck", !!spellcheck); + } + + function hiddenTextarea() { + var te = elt("textarea", null, null, "position: absolute; bottom: -1em; padding: 0; width: 1px; height: 1em; min-height: 1em; outline: none"); + var div = elt("div", [te], null, "overflow: hidden; position: relative; width: 3px; height: 0px;"); + // The textarea is kept positioned near the cursor to prevent the + // fact that it'll be scrolled into view on input from scrolling + // our fake cursor out of view. On webkit, when wrap=off, paste is + // very slow. So make the area wide instead. + if (webkit) { te.style.width = "1000px"; } + else { te.setAttribute("wrap", "off"); } + // If border: 0; -- iOS fails to open keyboard (issue #1287) + if (ios) { te.style.border = "1px solid black"; } + return div + } + + // The publicly visible API. Note that methodOp(f) means + // 'wrap f in an operation, performed on its `this` parameter'. + + // This is not the complete set of editor methods. Most of the + // methods defined on the Doc type are also injected into + // CodeMirror.prototype, for backwards compatibility and + // convenience. + + function addEditorMethods(CodeMirror) { + var optionHandlers = CodeMirror.optionHandlers; + + var helpers = CodeMirror.helpers = {}; + + CodeMirror.prototype = { + constructor: CodeMirror, + focus: function(){win(this).focus(); this.display.input.focus();}, + + setOption: function(option, value) { + var options = this.options, old = options[option]; + if (options[option] == value && option != "mode") { return } + options[option] = value; + if (optionHandlers.hasOwnProperty(option)) + { operation(this, optionHandlers[option])(this, value, old); } + signal(this, "optionChange", this, option); + }, + + getOption: function(option) {return this.options[option]}, + getDoc: function() {return this.doc}, + + addKeyMap: function(map, bottom) { + this.state.keyMaps[bottom ? "push" : "unshift"](getKeyMap(map)); + }, + removeKeyMap: function(map) { + var maps = this.state.keyMaps; + for (var i = 0; i < maps.length; ++i) + { if (maps[i] == map || maps[i].name == map) { + maps.splice(i, 1); + return true + } } + }, + + addOverlay: methodOp(function(spec, options) { + var mode = spec.token ? spec : CodeMirror.getMode(this.options, spec); + if (mode.startState) { throw new Error("Overlays may not be stateful.") } + insertSorted(this.state.overlays, + {mode: mode, modeSpec: spec, opaque: options && options.opaque, + priority: (options && options.priority) || 0}, + function (overlay) { return overlay.priority; }); + this.state.modeGen++; + regChange(this); + }), + removeOverlay: methodOp(function(spec) { + var overlays = this.state.overlays; + for (var i = 0; i < overlays.length; ++i) { + var cur = overlays[i].modeSpec; + if (cur == spec || typeof spec == "string" && cur.name == spec) { + overlays.splice(i, 1); + this.state.modeGen++; + regChange(this); + return + } + } + }), + + indentLine: methodOp(function(n, dir, aggressive) { + if (typeof dir != "string" && typeof dir != "number") { + if (dir == null) { dir = this.options.smartIndent ? "smart" : "prev"; } + else { dir = dir ? "add" : "subtract"; } + } + if (isLine(this.doc, n)) { indentLine(this, n, dir, aggressive); } + }), + indentSelection: methodOp(function(how) { + var ranges = this.doc.sel.ranges, end = -1; + for (var i = 0; i < ranges.length; i++) { + var range = ranges[i]; + if (!range.empty()) { + var from = range.from(), to = range.to(); + var start = Math.max(end, from.line); + end = Math.min(this.lastLine(), to.line - (to.ch ? 0 : 1)) + 1; + for (var j = start; j < end; ++j) + { indentLine(this, j, how); } + var newRanges = this.doc.sel.ranges; + if (from.ch == 0 && ranges.length == newRanges.length && newRanges[i].from().ch > 0) + { replaceOneSelection(this.doc, i, new Range(from, newRanges[i].to()), sel_dontScroll); } + } else if (range.head.line > end) { + indentLine(this, range.head.line, how, true); + end = range.head.line; + if (i == this.doc.sel.primIndex) { ensureCursorVisible(this); } + } + } + }), + + // Fetch the parser token for a given character. Useful for hacks + // that want to inspect the mode state (say, for completion). + getTokenAt: function(pos, precise) { + return takeToken(this, pos, precise) + }, + + getLineTokens: function(line, precise) { + return takeToken(this, Pos(line), precise, true) + }, + + getTokenTypeAt: function(pos) { + pos = clipPos(this.doc, pos); + var styles = getLineStyles(this, getLine(this.doc, pos.line)); + var before = 0, after = (styles.length - 1) / 2, ch = pos.ch; + var type; + if (ch == 0) { type = styles[2]; } + else { for (;;) { + var mid = (before + after) >> 1; + if ((mid ? styles[mid * 2 - 1] : 0) >= ch) { after = mid; } + else if (styles[mid * 2 + 1] < ch) { before = mid + 1; } + else { type = styles[mid * 2 + 2]; break } + } } + var cut = type ? type.indexOf("overlay ") : -1; + return cut < 0 ? type : cut == 0 ? null : type.slice(0, cut - 1) + }, + + getModeAt: function(pos) { + var mode = this.doc.mode; + if (!mode.innerMode) { return mode } + return CodeMirror.innerMode(mode, this.getTokenAt(pos).state).mode + }, + + getHelper: function(pos, type) { + return this.getHelpers(pos, type)[0] + }, + + getHelpers: function(pos, type) { + var found = []; + if (!helpers.hasOwnProperty(type)) { return found } + var help = helpers[type], mode = this.getModeAt(pos); + if (typeof mode[type] == "string") { + if (help[mode[type]]) { found.push(help[mode[type]]); } + } else if (mode[type]) { + for (var i = 0; i < mode[type].length; i++) { + var val = help[mode[type][i]]; + if (val) { found.push(val); } + } + } else if (mode.helperType && help[mode.helperType]) { + found.push(help[mode.helperType]); + } else if (help[mode.name]) { + found.push(help[mode.name]); + } + for (var i$1 = 0; i$1 < help._global.length; i$1++) { + var cur = help._global[i$1]; + if (cur.pred(mode, this) && indexOf(found, cur.val) == -1) + { found.push(cur.val); } + } + return found + }, + + getStateAfter: function(line, precise) { + var doc = this.doc; + line = clipLine(doc, line == null ? doc.first + doc.size - 1: line); + return getContextBefore(this, line + 1, precise).state + }, + + cursorCoords: function(start, mode) { + var pos, range = this.doc.sel.primary(); + if (start == null) { pos = range.head; } + else if (typeof start == "object") { pos = clipPos(this.doc, start); } + else { pos = start ? range.from() : range.to(); } + return cursorCoords(this, pos, mode || "page") + }, + + charCoords: function(pos, mode) { + return charCoords(this, clipPos(this.doc, pos), mode || "page") + }, + + coordsChar: function(coords, mode) { + coords = fromCoordSystem(this, coords, mode || "page"); + return coordsChar(this, coords.left, coords.top) + }, + + lineAtHeight: function(height, mode) { + height = fromCoordSystem(this, {top: height, left: 0}, mode || "page").top; + return lineAtHeight(this.doc, height + this.display.viewOffset) + }, + heightAtLine: function(line, mode, includeWidgets) { + var end = false, lineObj; + if (typeof line == "number") { + var last = this.doc.first + this.doc.size - 1; + if (line < this.doc.first) { line = this.doc.first; } + else if (line > last) { line = last; end = true; } + lineObj = getLine(this.doc, line); + } else { + lineObj = line; + } + return intoCoordSystem(this, lineObj, {top: 0, left: 0}, mode || "page", includeWidgets || end).top + + (end ? this.doc.height - heightAtLine(lineObj) : 0) + }, + + defaultTextHeight: function() { return textHeight(this.display) }, + defaultCharWidth: function() { return charWidth(this.display) }, + + getViewport: function() { return {from: this.display.viewFrom, to: this.display.viewTo}}, + + addWidget: function(pos, node, scroll, vert, horiz) { + var display = this.display; + pos = cursorCoords(this, clipPos(this.doc, pos)); + var top = pos.bottom, left = pos.left; + node.style.position = "absolute"; + node.setAttribute("cm-ignore-events", "true"); + this.display.input.setUneditable(node); + display.sizer.appendChild(node); + if (vert == "over") { + top = pos.top; + } else if (vert == "above" || vert == "near") { + var vspace = Math.max(display.wrapper.clientHeight, this.doc.height), + hspace = Math.max(display.sizer.clientWidth, display.lineSpace.clientWidth); + // Default to positioning above (if specified and possible); otherwise default to positioning below + if ((vert == 'above' || pos.bottom + node.offsetHeight > vspace) && pos.top > node.offsetHeight) + { top = pos.top - node.offsetHeight; } + else if (pos.bottom + node.offsetHeight <= vspace) + { top = pos.bottom; } + if (left + node.offsetWidth > hspace) + { left = hspace - node.offsetWidth; } + } + node.style.top = top + "px"; + node.style.left = node.style.right = ""; + if (horiz == "right") { + left = display.sizer.clientWidth - node.offsetWidth; + node.style.right = "0px"; + } else { + if (horiz == "left") { left = 0; } + else if (horiz == "middle") { left = (display.sizer.clientWidth - node.offsetWidth) / 2; } + node.style.left = left + "px"; + } + if (scroll) + { scrollIntoView(this, {left: left, top: top, right: left + node.offsetWidth, bottom: top + node.offsetHeight}); } + }, + + triggerOnKeyDown: methodOp(onKeyDown), + triggerOnKeyPress: methodOp(onKeyPress), + triggerOnKeyUp: onKeyUp, + triggerOnMouseDown: methodOp(onMouseDown), + + execCommand: function(cmd) { + if (commands.hasOwnProperty(cmd)) + { return commands[cmd].call(null, this) } + }, + + triggerElectric: methodOp(function(text) { triggerElectric(this, text); }), + + findPosH: function(from, amount, unit, visually) { + var dir = 1; + if (amount < 0) { dir = -1; amount = -amount; } + var cur = clipPos(this.doc, from); + for (var i = 0; i < amount; ++i) { + cur = findPosH(this.doc, cur, dir, unit, visually); + if (cur.hitSide) { break } + } + return cur + }, + + moveH: methodOp(function(dir, unit) { + var this$1 = this; + + this.extendSelectionsBy(function (range) { + if (this$1.display.shift || this$1.doc.extend || range.empty()) + { return findPosH(this$1.doc, range.head, dir, unit, this$1.options.rtlMoveVisually) } + else + { return dir < 0 ? range.from() : range.to() } + }, sel_move); + }), + + deleteH: methodOp(function(dir, unit) { + var sel = this.doc.sel, doc = this.doc; + if (sel.somethingSelected()) + { doc.replaceSelection("", null, "+delete"); } + else + { deleteNearSelection(this, function (range) { + var other = findPosH(doc, range.head, dir, unit, false); + return dir < 0 ? {from: other, to: range.head} : {from: range.head, to: other} + }); } + }), + + findPosV: function(from, amount, unit, goalColumn) { + var dir = 1, x = goalColumn; + if (amount < 0) { dir = -1; amount = -amount; } + var cur = clipPos(this.doc, from); + for (var i = 0; i < amount; ++i) { + var coords = cursorCoords(this, cur, "div"); + if (x == null) { x = coords.left; } + else { coords.left = x; } + cur = findPosV(this, coords, dir, unit); + if (cur.hitSide) { break } + } + return cur + }, + + moveV: methodOp(function(dir, unit) { + var this$1 = this; + + var doc = this.doc, goals = []; + var collapse = !this.display.shift && !doc.extend && doc.sel.somethingSelected(); + doc.extendSelectionsBy(function (range) { + if (collapse) + { return dir < 0 ? range.from() : range.to() } + var headPos = cursorCoords(this$1, range.head, "div"); + if (range.goalColumn != null) { headPos.left = range.goalColumn; } + goals.push(headPos.left); + var pos = findPosV(this$1, headPos, dir, unit); + if (unit == "page" && range == doc.sel.primary()) + { addToScrollTop(this$1, charCoords(this$1, pos, "div").top - headPos.top); } + return pos + }, sel_move); + if (goals.length) { for (var i = 0; i < doc.sel.ranges.length; i++) + { doc.sel.ranges[i].goalColumn = goals[i]; } } + }), + + // Find the word at the given position (as returned by coordsChar). + findWordAt: function(pos) { + var doc = this.doc, line = getLine(doc, pos.line).text; + var start = pos.ch, end = pos.ch; + if (line) { + var helper = this.getHelper(pos, "wordChars"); + if ((pos.sticky == "before" || end == line.length) && start) { --start; } else { ++end; } + var startChar = line.charAt(start); + var check = isWordChar(startChar, helper) + ? function (ch) { return isWordChar(ch, helper); } + : /\s/.test(startChar) ? function (ch) { return /\s/.test(ch); } + : function (ch) { return (!/\s/.test(ch) && !isWordChar(ch)); }; + while (start > 0 && check(line.charAt(start - 1))) { --start; } + while (end < line.length && check(line.charAt(end))) { ++end; } + } + return new Range(Pos(pos.line, start), Pos(pos.line, end)) + }, + + toggleOverwrite: function(value) { + if (value != null && value == this.state.overwrite) { return } + if (this.state.overwrite = !this.state.overwrite) + { addClass(this.display.cursorDiv, "CodeMirror-overwrite"); } + else + { rmClass(this.display.cursorDiv, "CodeMirror-overwrite"); } + + signal(this, "overwriteToggle", this, this.state.overwrite); + }, + hasFocus: function() { return this.display.input.getField() == activeElt(doc(this)) }, + isReadOnly: function() { return !!(this.options.readOnly || this.doc.cantEdit) }, + + scrollTo: methodOp(function (x, y) { scrollToCoords(this, x, y); }), + getScrollInfo: function() { + var scroller = this.display.scroller; + return {left: scroller.scrollLeft, top: scroller.scrollTop, + height: scroller.scrollHeight - scrollGap(this) - this.display.barHeight, + width: scroller.scrollWidth - scrollGap(this) - this.display.barWidth, + clientHeight: displayHeight(this), clientWidth: displayWidth(this)} + }, + + scrollIntoView: methodOp(function(range, margin) { + if (range == null) { + range = {from: this.doc.sel.primary().head, to: null}; + if (margin == null) { margin = this.options.cursorScrollMargin; } + } else if (typeof range == "number") { + range = {from: Pos(range, 0), to: null}; + } else if (range.from == null) { + range = {from: range, to: null}; + } + if (!range.to) { range.to = range.from; } + range.margin = margin || 0; + + if (range.from.line != null) { + scrollToRange(this, range); + } else { + scrollToCoordsRange(this, range.from, range.to, range.margin); + } + }), + + setSize: methodOp(function(width, height) { + var this$1 = this; + + var interpret = function (val) { return typeof val == "number" || /^\d+$/.test(String(val)) ? val + "px" : val; }; + if (width != null) { this.display.wrapper.style.width = interpret(width); } + if (height != null) { this.display.wrapper.style.height = interpret(height); } + if (this.options.lineWrapping) { clearLineMeasurementCache(this); } + var lineNo = this.display.viewFrom; + this.doc.iter(lineNo, this.display.viewTo, function (line) { + if (line.widgets) { for (var i = 0; i < line.widgets.length; i++) + { if (line.widgets[i].noHScroll) { regLineChange(this$1, lineNo, "widget"); break } } } + ++lineNo; + }); + this.curOp.forceUpdate = true; + signal(this, "refresh", this); + }), + + operation: function(f){return runInOp(this, f)}, + startOperation: function(){return startOperation(this)}, + endOperation: function(){return endOperation(this)}, + + refresh: methodOp(function() { + var oldHeight = this.display.cachedTextHeight; + regChange(this); + this.curOp.forceUpdate = true; + clearCaches(this); + scrollToCoords(this, this.doc.scrollLeft, this.doc.scrollTop); + updateGutterSpace(this.display); + if (oldHeight == null || Math.abs(oldHeight - textHeight(this.display)) > .5 || this.options.lineWrapping) + { estimateLineHeights(this); } + signal(this, "refresh", this); + }), + + swapDoc: methodOp(function(doc) { + var old = this.doc; + old.cm = null; + // Cancel the current text selection if any (#5821) + if (this.state.selectingText) { this.state.selectingText(); } + attachDoc(this, doc); + clearCaches(this); + this.display.input.reset(); + scrollToCoords(this, doc.scrollLeft, doc.scrollTop); + this.curOp.forceScroll = true; + signalLater(this, "swapDoc", this, old); + return old + }), + + phrase: function(phraseText) { + var phrases = this.options.phrases; + return phrases && Object.prototype.hasOwnProperty.call(phrases, phraseText) ? phrases[phraseText] : phraseText + }, + + getInputField: function(){return this.display.input.getField()}, + getWrapperElement: function(){return this.display.wrapper}, + getScrollerElement: function(){return this.display.scroller}, + getGutterElement: function(){return this.display.gutters} + }; + eventMixin(CodeMirror); + + CodeMirror.registerHelper = function(type, name, value) { + if (!helpers.hasOwnProperty(type)) { helpers[type] = CodeMirror[type] = {_global: []}; } + helpers[type][name] = value; + }; + CodeMirror.registerGlobalHelper = function(type, name, predicate, value) { + CodeMirror.registerHelper(type, name, value); + helpers[type]._global.push({pred: predicate, val: value}); + }; + } + + // Used for horizontal relative motion. Dir is -1 or 1 (left or + // right), unit can be "codepoint", "char", "column" (like char, but + // doesn't cross line boundaries), "word" (across next word), or + // "group" (to the start of next group of word or + // non-word-non-whitespace chars). The visually param controls + // whether, in right-to-left text, direction 1 means to move towards + // the next index in the string, or towards the character to the right + // of the current position. The resulting position will have a + // hitSide=true property if it reached the end of the document. + function findPosH(doc, pos, dir, unit, visually) { + var oldPos = pos; + var origDir = dir; + var lineObj = getLine(doc, pos.line); + var lineDir = visually && doc.direction == "rtl" ? -dir : dir; + function findNextLine() { + var l = pos.line + lineDir; + if (l < doc.first || l >= doc.first + doc.size) { return false } + pos = new Pos(l, pos.ch, pos.sticky); + return lineObj = getLine(doc, l) + } + function moveOnce(boundToLine) { + var next; + if (unit == "codepoint") { + var ch = lineObj.text.charCodeAt(pos.ch + (dir > 0 ? 0 : -1)); + if (isNaN(ch)) { + next = null; + } else { + var astral = dir > 0 ? ch >= 0xD800 && ch < 0xDC00 : ch >= 0xDC00 && ch < 0xDFFF; + next = new Pos(pos.line, Math.max(0, Math.min(lineObj.text.length, pos.ch + dir * (astral ? 2 : 1))), -dir); + } + } else if (visually) { + next = moveVisually(doc.cm, lineObj, pos, dir); + } else { + next = moveLogically(lineObj, pos, dir); + } + if (next == null) { + if (!boundToLine && findNextLine()) + { pos = endOfLine(visually, doc.cm, lineObj, pos.line, lineDir); } + else + { return false } + } else { + pos = next; + } + return true + } + + if (unit == "char" || unit == "codepoint") { + moveOnce(); + } else if (unit == "column") { + moveOnce(true); + } else if (unit == "word" || unit == "group") { + var sawType = null, group = unit == "group"; + var helper = doc.cm && doc.cm.getHelper(pos, "wordChars"); + for (var first = true;; first = false) { + if (dir < 0 && !moveOnce(!first)) { break } + var cur = lineObj.text.charAt(pos.ch) || "\n"; + var type = isWordChar(cur, helper) ? "w" + : group && cur == "\n" ? "n" + : !group || /\s/.test(cur) ? null + : "p"; + if (group && !first && !type) { type = "s"; } + if (sawType && sawType != type) { + if (dir < 0) {dir = 1; moveOnce(); pos.sticky = "after";} + break + } + + if (type) { sawType = type; } + if (dir > 0 && !moveOnce(!first)) { break } + } + } + var result = skipAtomic(doc, pos, oldPos, origDir, true); + if (equalCursorPos(oldPos, result)) { result.hitSide = true; } + return result + } + + // For relative vertical movement. Dir may be -1 or 1. Unit can be + // "page" or "line". The resulting position will have a hitSide=true + // property if it reached the end of the document. + function findPosV(cm, pos, dir, unit) { + var doc = cm.doc, x = pos.left, y; + if (unit == "page") { + var pageSize = Math.min(cm.display.wrapper.clientHeight, win(cm).innerHeight || doc(cm).documentElement.clientHeight); + var moveAmount = Math.max(pageSize - .5 * textHeight(cm.display), 3); + y = (dir > 0 ? pos.bottom : pos.top) + dir * moveAmount; + + } else if (unit == "line") { + y = dir > 0 ? pos.bottom + 3 : pos.top - 3; + } + var target; + for (;;) { + target = coordsChar(cm, x, y); + if (!target.outside) { break } + if (dir < 0 ? y <= 0 : y >= doc.height) { target.hitSide = true; break } + y += dir * 5; + } + return target + } + + // CONTENTEDITABLE INPUT STYLE + + var ContentEditableInput = function(cm) { + this.cm = cm; + this.lastAnchorNode = this.lastAnchorOffset = this.lastFocusNode = this.lastFocusOffset = null; + this.polling = new Delayed(); + this.composing = null; + this.gracePeriod = false; + this.readDOMTimeout = null; + }; + + ContentEditableInput.prototype.init = function (display) { + var this$1 = this; + + var input = this, cm = input.cm; + var div = input.div = display.lineDiv; + div.contentEditable = true; + disableBrowserMagic(div, cm.options.spellcheck, cm.options.autocorrect, cm.options.autocapitalize); + + function belongsToInput(e) { + for (var t = e.target; t; t = t.parentNode) { + if (t == div) { return true } + if (/\bCodeMirror-(?:line)?widget\b/.test(t.className)) { break } + } + return false + } + + on(div, "paste", function (e) { + if (!belongsToInput(e) || signalDOMEvent(cm, e) || handlePaste(e, cm)) { return } + // IE doesn't fire input events, so we schedule a read for the pasted content in this way + if (ie_version <= 11) { setTimeout(operation(cm, function () { return this$1.updateFromDOM(); }), 20); } + }); + + on(div, "compositionstart", function (e) { + this$1.composing = {data: e.data, done: false}; + }); + on(div, "compositionupdate", function (e) { + if (!this$1.composing) { this$1.composing = {data: e.data, done: false}; } + }); + on(div, "compositionend", function (e) { + if (this$1.composing) { + if (e.data != this$1.composing.data) { this$1.readFromDOMSoon(); } + this$1.composing.done = true; + } + }); + + on(div, "touchstart", function () { return input.forceCompositionEnd(); }); + + on(div, "input", function () { + if (!this$1.composing) { this$1.readFromDOMSoon(); } + }); + + function onCopyCut(e) { + if (!belongsToInput(e) || signalDOMEvent(cm, e)) { return } + if (cm.somethingSelected()) { + setLastCopied({lineWise: false, text: cm.getSelections()}); + if (e.type == "cut") { cm.replaceSelection("", null, "cut"); } + } else if (!cm.options.lineWiseCopyCut) { + return + } else { + var ranges = copyableRanges(cm); + setLastCopied({lineWise: true, text: ranges.text}); + if (e.type == "cut") { + cm.operation(function () { + cm.setSelections(ranges.ranges, 0, sel_dontScroll); + cm.replaceSelection("", null, "cut"); + }); + } + } + if (e.clipboardData) { + e.clipboardData.clearData(); + var content = lastCopied.text.join("\n"); + // iOS exposes the clipboard API, but seems to discard content inserted into it + e.clipboardData.setData("Text", content); + if (e.clipboardData.getData("Text") == content) { + e.preventDefault(); + return + } + } + // Old-fashioned briefly-focus-a-textarea hack + var kludge = hiddenTextarea(), te = kludge.firstChild; + disableBrowserMagic(te); + cm.display.lineSpace.insertBefore(kludge, cm.display.lineSpace.firstChild); + te.value = lastCopied.text.join("\n"); + var hadFocus = activeElt(div.ownerDocument); + selectInput(te); + setTimeout(function () { + cm.display.lineSpace.removeChild(kludge); + hadFocus.focus(); + if (hadFocus == div) { input.showPrimarySelection(); } + }, 50); + } + on(div, "copy", onCopyCut); + on(div, "cut", onCopyCut); + }; + + ContentEditableInput.prototype.screenReaderLabelChanged = function (label) { + // Label for screenreaders, accessibility + if(label) { + this.div.setAttribute('aria-label', label); + } else { + this.div.removeAttribute('aria-label'); + } + }; + + ContentEditableInput.prototype.prepareSelection = function () { + var result = prepareSelection(this.cm, false); + result.focus = activeElt(this.div.ownerDocument) == this.div; + return result + }; + + ContentEditableInput.prototype.showSelection = function (info, takeFocus) { + if (!info || !this.cm.display.view.length) { return } + if (info.focus || takeFocus) { this.showPrimarySelection(); } + this.showMultipleSelections(info); + }; + + ContentEditableInput.prototype.getSelection = function () { + return this.cm.display.wrapper.ownerDocument.getSelection() + }; + + ContentEditableInput.prototype.showPrimarySelection = function () { + var sel = this.getSelection(), cm = this.cm, prim = cm.doc.sel.primary(); + var from = prim.from(), to = prim.to(); + + if (cm.display.viewTo == cm.display.viewFrom || from.line >= cm.display.viewTo || to.line < cm.display.viewFrom) { + sel.removeAllRanges(); + return + } + + var curAnchor = domToPos(cm, sel.anchorNode, sel.anchorOffset); + var curFocus = domToPos(cm, sel.focusNode, sel.focusOffset); + if (curAnchor && !curAnchor.bad && curFocus && !curFocus.bad && + cmp(minPos(curAnchor, curFocus), from) == 0 && + cmp(maxPos(curAnchor, curFocus), to) == 0) + { return } + + var view = cm.display.view; + var start = (from.line >= cm.display.viewFrom && posToDOM(cm, from)) || + {node: view[0].measure.map[2], offset: 0}; + var end = to.line < cm.display.viewTo && posToDOM(cm, to); + if (!end) { + var measure = view[view.length - 1].measure; + var map = measure.maps ? measure.maps[measure.maps.length - 1] : measure.map; + end = {node: map[map.length - 1], offset: map[map.length - 2] - map[map.length - 3]}; + } + + if (!start || !end) { + sel.removeAllRanges(); + return + } + + var old = sel.rangeCount && sel.getRangeAt(0), rng; + try { rng = range(start.node, start.offset, end.offset, end.node); } + catch(e) {} // Our model of the DOM might be outdated, in which case the range we try to set can be impossible + if (rng) { + if (!gecko && cm.state.focused) { + sel.collapse(start.node, start.offset); + if (!rng.collapsed) { + sel.removeAllRanges(); + sel.addRange(rng); + } + } else { + sel.removeAllRanges(); + sel.addRange(rng); + } + if (old && sel.anchorNode == null) { sel.addRange(old); } + else if (gecko) { this.startGracePeriod(); } + } + this.rememberSelection(); + }; + + ContentEditableInput.prototype.startGracePeriod = function () { + var this$1 = this; + + clearTimeout(this.gracePeriod); + this.gracePeriod = setTimeout(function () { + this$1.gracePeriod = false; + if (this$1.selectionChanged()) + { this$1.cm.operation(function () { return this$1.cm.curOp.selectionChanged = true; }); } + }, 20); + }; + + ContentEditableInput.prototype.showMultipleSelections = function (info) { + removeChildrenAndAdd(this.cm.display.cursorDiv, info.cursors); + removeChildrenAndAdd(this.cm.display.selectionDiv, info.selection); + }; + + ContentEditableInput.prototype.rememberSelection = function () { + var sel = this.getSelection(); + this.lastAnchorNode = sel.anchorNode; this.lastAnchorOffset = sel.anchorOffset; + this.lastFocusNode = sel.focusNode; this.lastFocusOffset = sel.focusOffset; + }; + + ContentEditableInput.prototype.selectionInEditor = function () { + var sel = this.getSelection(); + if (!sel.rangeCount) { return false } + var node = sel.getRangeAt(0).commonAncestorContainer; + return contains(this.div, node) + }; + + ContentEditableInput.prototype.focus = function () { + if (this.cm.options.readOnly != "nocursor") { + if (!this.selectionInEditor() || activeElt(this.div.ownerDocument) != this.div) + { this.showSelection(this.prepareSelection(), true); } + this.div.focus(); + } + }; + ContentEditableInput.prototype.blur = function () { this.div.blur(); }; + ContentEditableInput.prototype.getField = function () { return this.div }; + + ContentEditableInput.prototype.supportsTouch = function () { return true }; + + ContentEditableInput.prototype.receivedFocus = function () { + var this$1 = this; + + var input = this; + if (this.selectionInEditor()) + { setTimeout(function () { return this$1.pollSelection(); }, 20); } + else + { runInOp(this.cm, function () { return input.cm.curOp.selectionChanged = true; }); } + + function poll() { + if (input.cm.state.focused) { + input.pollSelection(); + input.polling.set(input.cm.options.pollInterval, poll); + } + } + this.polling.set(this.cm.options.pollInterval, poll); + }; + + ContentEditableInput.prototype.selectionChanged = function () { + var sel = this.getSelection(); + return sel.anchorNode != this.lastAnchorNode || sel.anchorOffset != this.lastAnchorOffset || + sel.focusNode != this.lastFocusNode || sel.focusOffset != this.lastFocusOffset + }; + + ContentEditableInput.prototype.pollSelection = function () { + if (this.readDOMTimeout != null || this.gracePeriod || !this.selectionChanged()) { return } + var sel = this.getSelection(), cm = this.cm; + // On Android Chrome (version 56, at least), backspacing into an + // uneditable block element will put the cursor in that element, + // and then, because it's not editable, hide the virtual keyboard. + // Because Android doesn't allow us to actually detect backspace + // presses in a sane way, this code checks for when that happens + // and simulates a backspace press in this case. + if (android && chrome && this.cm.display.gutterSpecs.length && isInGutter(sel.anchorNode)) { + this.cm.triggerOnKeyDown({type: "keydown", keyCode: 8, preventDefault: Math.abs}); + this.blur(); + this.focus(); + return + } + if (this.composing) { return } + this.rememberSelection(); + var anchor = domToPos(cm, sel.anchorNode, sel.anchorOffset); + var head = domToPos(cm, sel.focusNode, sel.focusOffset); + if (anchor && head) { runInOp(cm, function () { + setSelection(cm.doc, simpleSelection(anchor, head), sel_dontScroll); + if (anchor.bad || head.bad) { cm.curOp.selectionChanged = true; } + }); } + }; + + ContentEditableInput.prototype.pollContent = function () { + if (this.readDOMTimeout != null) { + clearTimeout(this.readDOMTimeout); + this.readDOMTimeout = null; + } + + var cm = this.cm, display = cm.display, sel = cm.doc.sel.primary(); + var from = sel.from(), to = sel.to(); + if (from.ch == 0 && from.line > cm.firstLine()) + { from = Pos(from.line - 1, getLine(cm.doc, from.line - 1).length); } + if (to.ch == getLine(cm.doc, to.line).text.length && to.line < cm.lastLine()) + { to = Pos(to.line + 1, 0); } + if (from.line < display.viewFrom || to.line > display.viewTo - 1) { return false } + + var fromIndex, fromLine, fromNode; + if (from.line == display.viewFrom || (fromIndex = findViewIndex(cm, from.line)) == 0) { + fromLine = lineNo(display.view[0].line); + fromNode = display.view[0].node; + } else { + fromLine = lineNo(display.view[fromIndex].line); + fromNode = display.view[fromIndex - 1].node.nextSibling; + } + var toIndex = findViewIndex(cm, to.line); + var toLine, toNode; + if (toIndex == display.view.length - 1) { + toLine = display.viewTo - 1; + toNode = display.lineDiv.lastChild; + } else { + toLine = lineNo(display.view[toIndex + 1].line) - 1; + toNode = display.view[toIndex + 1].node.previousSibling; + } + + if (!fromNode) { return false } + var newText = cm.doc.splitLines(domTextBetween(cm, fromNode, toNode, fromLine, toLine)); + var oldText = getBetween(cm.doc, Pos(fromLine, 0), Pos(toLine, getLine(cm.doc, toLine).text.length)); + while (newText.length > 1 && oldText.length > 1) { + if (lst(newText) == lst(oldText)) { newText.pop(); oldText.pop(); toLine--; } + else if (newText[0] == oldText[0]) { newText.shift(); oldText.shift(); fromLine++; } + else { break } + } + + var cutFront = 0, cutEnd = 0; + var newTop = newText[0], oldTop = oldText[0], maxCutFront = Math.min(newTop.length, oldTop.length); + while (cutFront < maxCutFront && newTop.charCodeAt(cutFront) == oldTop.charCodeAt(cutFront)) + { ++cutFront; } + var newBot = lst(newText), oldBot = lst(oldText); + var maxCutEnd = Math.min(newBot.length - (newText.length == 1 ? cutFront : 0), + oldBot.length - (oldText.length == 1 ? cutFront : 0)); + while (cutEnd < maxCutEnd && + newBot.charCodeAt(newBot.length - cutEnd - 1) == oldBot.charCodeAt(oldBot.length - cutEnd - 1)) + { ++cutEnd; } + // Try to move start of change to start of selection if ambiguous + if (newText.length == 1 && oldText.length == 1 && fromLine == from.line) { + while (cutFront && cutFront > from.ch && + newBot.charCodeAt(newBot.length - cutEnd - 1) == oldBot.charCodeAt(oldBot.length - cutEnd - 1)) { + cutFront--; + cutEnd++; + } + } + + newText[newText.length - 1] = newBot.slice(0, newBot.length - cutEnd).replace(/^\u200b+/, ""); + newText[0] = newText[0].slice(cutFront).replace(/\u200b+$/, ""); + + var chFrom = Pos(fromLine, cutFront); + var chTo = Pos(toLine, oldText.length ? lst(oldText).length - cutEnd : 0); + if (newText.length > 1 || newText[0] || cmp(chFrom, chTo)) { + replaceRange(cm.doc, newText, chFrom, chTo, "+input"); + return true + } + }; + + ContentEditableInput.prototype.ensurePolled = function () { + this.forceCompositionEnd(); + }; + ContentEditableInput.prototype.reset = function () { + this.forceCompositionEnd(); + }; + ContentEditableInput.prototype.forceCompositionEnd = function () { + if (!this.composing) { return } + clearTimeout(this.readDOMTimeout); + this.composing = null; + this.updateFromDOM(); + this.div.blur(); + this.div.focus(); + }; + ContentEditableInput.prototype.readFromDOMSoon = function () { + var this$1 = this; + + if (this.readDOMTimeout != null) { return } + this.readDOMTimeout = setTimeout(function () { + this$1.readDOMTimeout = null; + if (this$1.composing) { + if (this$1.composing.done) { this$1.composing = null; } + else { return } + } + this$1.updateFromDOM(); + }, 80); + }; + + ContentEditableInput.prototype.updateFromDOM = function () { + var this$1 = this; + + if (this.cm.isReadOnly() || !this.pollContent()) + { runInOp(this.cm, function () { return regChange(this$1.cm); }); } + }; + + ContentEditableInput.prototype.setUneditable = function (node) { + node.contentEditable = "false"; + }; + + ContentEditableInput.prototype.onKeyPress = function (e) { + if (e.charCode == 0 || this.composing) { return } + e.preventDefault(); + if (!this.cm.isReadOnly()) + { operation(this.cm, applyTextInput)(this.cm, String.fromCharCode(e.charCode == null ? e.keyCode : e.charCode), 0); } + }; + + ContentEditableInput.prototype.readOnlyChanged = function (val) { + this.div.contentEditable = String(val != "nocursor"); + }; + + ContentEditableInput.prototype.onContextMenu = function () {}; + ContentEditableInput.prototype.resetPosition = function () {}; + + ContentEditableInput.prototype.needsContentAttribute = true; + + function posToDOM(cm, pos) { + var view = findViewForLine(cm, pos.line); + if (!view || view.hidden) { return null } + var line = getLine(cm.doc, pos.line); + var info = mapFromLineView(view, line, pos.line); + + var order = getOrder(line, cm.doc.direction), side = "left"; + if (order) { + var partPos = getBidiPartAt(order, pos.ch); + side = partPos % 2 ? "right" : "left"; + } + var result = nodeAndOffsetInLineMap(info.map, pos.ch, side); + result.offset = result.collapse == "right" ? result.end : result.start; + return result + } + + function isInGutter(node) { + for (var scan = node; scan; scan = scan.parentNode) + { if (/CodeMirror-gutter-wrapper/.test(scan.className)) { return true } } + return false + } + + function badPos(pos, bad) { if (bad) { pos.bad = true; } return pos } + + function domTextBetween(cm, from, to, fromLine, toLine) { + var text = "", closing = false, lineSep = cm.doc.lineSeparator(), extraLinebreak = false; + function recognizeMarker(id) { return function (marker) { return marker.id == id; } } + function close() { + if (closing) { + text += lineSep; + if (extraLinebreak) { text += lineSep; } + closing = extraLinebreak = false; + } + } + function addText(str) { + if (str) { + close(); + text += str; + } + } + function walk(node) { + if (node.nodeType == 1) { + var cmText = node.getAttribute("cm-text"); + if (cmText) { + addText(cmText); + return + } + var markerID = node.getAttribute("cm-marker"), range; + if (markerID) { + var found = cm.findMarks(Pos(fromLine, 0), Pos(toLine + 1, 0), recognizeMarker(+markerID)); + if (found.length && (range = found[0].find(0))) + { addText(getBetween(cm.doc, range.from, range.to).join(lineSep)); } + return + } + if (node.getAttribute("contenteditable") == "false") { return } + var isBlock = /^(pre|div|p|li|table|br)$/i.test(node.nodeName); + if (!/^br$/i.test(node.nodeName) && node.textContent.length == 0) { return } + + if (isBlock) { close(); } + for (var i = 0; i < node.childNodes.length; i++) + { walk(node.childNodes[i]); } + + if (/^(pre|p)$/i.test(node.nodeName)) { extraLinebreak = true; } + if (isBlock) { closing = true; } + } else if (node.nodeType == 3) { + addText(node.nodeValue.replace(/\u200b/g, "").replace(/\u00a0/g, " ")); + } + } + for (;;) { + walk(from); + if (from == to) { break } + from = from.nextSibling; + extraLinebreak = false; + } + return text + } + + function domToPos(cm, node, offset) { + var lineNode; + if (node == cm.display.lineDiv) { + lineNode = cm.display.lineDiv.childNodes[offset]; + if (!lineNode) { return badPos(cm.clipPos(Pos(cm.display.viewTo - 1)), true) } + node = null; offset = 0; + } else { + for (lineNode = node;; lineNode = lineNode.parentNode) { + if (!lineNode || lineNode == cm.display.lineDiv) { return null } + if (lineNode.parentNode && lineNode.parentNode == cm.display.lineDiv) { break } + } + } + for (var i = 0; i < cm.display.view.length; i++) { + var lineView = cm.display.view[i]; + if (lineView.node == lineNode) + { return locateNodeInLineView(lineView, node, offset) } + } + } + + function locateNodeInLineView(lineView, node, offset) { + var wrapper = lineView.text.firstChild, bad = false; + if (!node || !contains(wrapper, node)) { return badPos(Pos(lineNo(lineView.line), 0), true) } + if (node == wrapper) { + bad = true; + node = wrapper.childNodes[offset]; + offset = 0; + if (!node) { + var line = lineView.rest ? lst(lineView.rest) : lineView.line; + return badPos(Pos(lineNo(line), line.text.length), bad) + } + } + + var textNode = node.nodeType == 3 ? node : null, topNode = node; + if (!textNode && node.childNodes.length == 1 && node.firstChild.nodeType == 3) { + textNode = node.firstChild; + if (offset) { offset = textNode.nodeValue.length; } + } + while (topNode.parentNode != wrapper) { topNode = topNode.parentNode; } + var measure = lineView.measure, maps = measure.maps; + + function find(textNode, topNode, offset) { + for (var i = -1; i < (maps ? maps.length : 0); i++) { + var map = i < 0 ? measure.map : maps[i]; + for (var j = 0; j < map.length; j += 3) { + var curNode = map[j + 2]; + if (curNode == textNode || curNode == topNode) { + var line = lineNo(i < 0 ? lineView.line : lineView.rest[i]); + var ch = map[j] + offset; + if (offset < 0 || curNode != textNode) { ch = map[j + (offset ? 1 : 0)]; } + return Pos(line, ch) + } + } + } + } + var found = find(textNode, topNode, offset); + if (found) { return badPos(found, bad) } + + // FIXME this is all really shaky. might handle the few cases it needs to handle, but likely to cause problems + for (var after = topNode.nextSibling, dist = textNode ? textNode.nodeValue.length - offset : 0; after; after = after.nextSibling) { + found = find(after, after.firstChild, 0); + if (found) + { return badPos(Pos(found.line, found.ch - dist), bad) } + else + { dist += after.textContent.length; } + } + for (var before = topNode.previousSibling, dist$1 = offset; before; before = before.previousSibling) { + found = find(before, before.firstChild, -1); + if (found) + { return badPos(Pos(found.line, found.ch + dist$1), bad) } + else + { dist$1 += before.textContent.length; } + } + } + + // TEXTAREA INPUT STYLE + + var TextareaInput = function(cm) { + this.cm = cm; + // See input.poll and input.reset + this.prevInput = ""; + + // Flag that indicates whether we expect input to appear real soon + // now (after some event like 'keypress' or 'input') and are + // polling intensively. + this.pollingFast = false; + // Self-resetting timeout for the poller + this.polling = new Delayed(); + // Used to work around IE issue with selection being forgotten when focus moves away from textarea + this.hasSelection = false; + this.composing = null; + this.resetting = false; + }; + + TextareaInput.prototype.init = function (display) { + var this$1 = this; + + var input = this, cm = this.cm; + this.createField(display); + var te = this.textarea; + + display.wrapper.insertBefore(this.wrapper, display.wrapper.firstChild); + + // Needed to hide big blue blinking cursor on Mobile Safari (doesn't seem to work in iOS 8 anymore) + if (ios) { te.style.width = "0px"; } + + on(te, "input", function () { + if (ie && ie_version >= 9 && this$1.hasSelection) { this$1.hasSelection = null; } + input.poll(); + }); + + on(te, "paste", function (e) { + if (signalDOMEvent(cm, e) || handlePaste(e, cm)) { return } + + cm.state.pasteIncoming = +new Date; + input.fastPoll(); + }); + + function prepareCopyCut(e) { + if (signalDOMEvent(cm, e)) { return } + if (cm.somethingSelected()) { + setLastCopied({lineWise: false, text: cm.getSelections()}); + } else if (!cm.options.lineWiseCopyCut) { + return + } else { + var ranges = copyableRanges(cm); + setLastCopied({lineWise: true, text: ranges.text}); + if (e.type == "cut") { + cm.setSelections(ranges.ranges, null, sel_dontScroll); + } else { + input.prevInput = ""; + te.value = ranges.text.join("\n"); + selectInput(te); + } + } + if (e.type == "cut") { cm.state.cutIncoming = +new Date; } + } + on(te, "cut", prepareCopyCut); + on(te, "copy", prepareCopyCut); + + on(display.scroller, "paste", function (e) { + if (eventInWidget(display, e) || signalDOMEvent(cm, e)) { return } + if (!te.dispatchEvent) { + cm.state.pasteIncoming = +new Date; + input.focus(); + return + } + + // Pass the `paste` event to the textarea so it's handled by its event listener. + var event = new Event("paste"); + event.clipboardData = e.clipboardData; + te.dispatchEvent(event); + }); + + // Prevent normal selection in the editor (we handle our own) + on(display.lineSpace, "selectstart", function (e) { + if (!eventInWidget(display, e)) { e_preventDefault(e); } + }); + + on(te, "compositionstart", function () { + var start = cm.getCursor("from"); + if (input.composing) { input.composing.range.clear(); } + input.composing = { + start: start, + range: cm.markText(start, cm.getCursor("to"), {className: "CodeMirror-composing"}) + }; + }); + on(te, "compositionend", function () { + if (input.composing) { + input.poll(); + input.composing.range.clear(); + input.composing = null; + } + }); + }; + + TextareaInput.prototype.createField = function (_display) { + // Wraps and hides input textarea + this.wrapper = hiddenTextarea(); + // The semihidden textarea that is focused when the editor is + // focused, and receives input. + this.textarea = this.wrapper.firstChild; + var opts = this.cm.options; + disableBrowserMagic(this.textarea, opts.spellcheck, opts.autocorrect, opts.autocapitalize); + }; + + TextareaInput.prototype.screenReaderLabelChanged = function (label) { + // Label for screenreaders, accessibility + if(label) { + this.textarea.setAttribute('aria-label', label); + } else { + this.textarea.removeAttribute('aria-label'); + } + }; + + TextareaInput.prototype.prepareSelection = function () { + // Redraw the selection and/or cursor + var cm = this.cm, display = cm.display, doc = cm.doc; + var result = prepareSelection(cm); + + // Move the hidden textarea near the cursor to prevent scrolling artifacts + if (cm.options.moveInputWithCursor) { + var headPos = cursorCoords(cm, doc.sel.primary().head, "div"); + var wrapOff = display.wrapper.getBoundingClientRect(), lineOff = display.lineDiv.getBoundingClientRect(); + result.teTop = Math.max(0, Math.min(display.wrapper.clientHeight - 10, + headPos.top + lineOff.top - wrapOff.top)); + result.teLeft = Math.max(0, Math.min(display.wrapper.clientWidth - 10, + headPos.left + lineOff.left - wrapOff.left)); + } + + return result + }; + + TextareaInput.prototype.showSelection = function (drawn) { + var cm = this.cm, display = cm.display; + removeChildrenAndAdd(display.cursorDiv, drawn.cursors); + removeChildrenAndAdd(display.selectionDiv, drawn.selection); + if (drawn.teTop != null) { + this.wrapper.style.top = drawn.teTop + "px"; + this.wrapper.style.left = drawn.teLeft + "px"; + } + }; + + // Reset the input to correspond to the selection (or to be empty, + // when not typing and nothing is selected) + TextareaInput.prototype.reset = function (typing) { + if (this.contextMenuPending || this.composing && typing) { return } + var cm = this.cm; + this.resetting = true; + if (cm.somethingSelected()) { + this.prevInput = ""; + var content = cm.getSelection(); + this.textarea.value = content; + if (cm.state.focused) { selectInput(this.textarea); } + if (ie && ie_version >= 9) { this.hasSelection = content; } + } else if (!typing) { + this.prevInput = this.textarea.value = ""; + if (ie && ie_version >= 9) { this.hasSelection = null; } + } + this.resetting = false; + }; + + TextareaInput.prototype.getField = function () { return this.textarea }; + + TextareaInput.prototype.supportsTouch = function () { return false }; + + TextareaInput.prototype.focus = function () { + if (this.cm.options.readOnly != "nocursor" && (!mobile || activeElt(this.textarea.ownerDocument) != this.textarea)) { + try { this.textarea.focus(); } + catch (e) {} // IE8 will throw if the textarea is display: none or not in DOM + } + }; + + TextareaInput.prototype.blur = function () { this.textarea.blur(); }; + + TextareaInput.prototype.resetPosition = function () { + this.wrapper.style.top = this.wrapper.style.left = 0; + }; + + TextareaInput.prototype.receivedFocus = function () { this.slowPoll(); }; + + // Poll for input changes, using the normal rate of polling. This + // runs as long as the editor is focused. + TextareaInput.prototype.slowPoll = function () { + var this$1 = this; + + if (this.pollingFast) { return } + this.polling.set(this.cm.options.pollInterval, function () { + this$1.poll(); + if (this$1.cm.state.focused) { this$1.slowPoll(); } + }); + }; + + // When an event has just come in that is likely to add or change + // something in the input textarea, we poll faster, to ensure that + // the change appears on the screen quickly. + TextareaInput.prototype.fastPoll = function () { + var missed = false, input = this; + input.pollingFast = true; + function p() { + var changed = input.poll(); + if (!changed && !missed) {missed = true; input.polling.set(60, p);} + else {input.pollingFast = false; input.slowPoll();} + } + input.polling.set(20, p); + }; + + // Read input from the textarea, and update the document to match. + // When something is selected, it is present in the textarea, and + // selected (unless it is huge, in which case a placeholder is + // used). When nothing is selected, the cursor sits after previously + // seen text (can be empty), which is stored in prevInput (we must + // not reset the textarea when typing, because that breaks IME). + TextareaInput.prototype.poll = function () { + var this$1 = this; + + var cm = this.cm, input = this.textarea, prevInput = this.prevInput; + // Since this is called a *lot*, try to bail out as cheaply as + // possible when it is clear that nothing happened. hasSelection + // will be the case when there is a lot of text in the textarea, + // in which case reading its value would be expensive. + if (this.contextMenuPending || this.resetting || !cm.state.focused || + (hasSelection(input) && !prevInput && !this.composing) || + cm.isReadOnly() || cm.options.disableInput || cm.state.keySeq) + { return false } + + var text = input.value; + // If nothing changed, bail. + if (text == prevInput && !cm.somethingSelected()) { return false } + // Work around nonsensical selection resetting in IE9/10, and + // inexplicable appearance of private area unicode characters on + // some key combos in Mac (#2689). + if (ie && ie_version >= 9 && this.hasSelection === text || + mac && /[\uf700-\uf7ff]/.test(text)) { + cm.display.input.reset(); + return false + } + + if (cm.doc.sel == cm.display.selForContextMenu) { + var first = text.charCodeAt(0); + if (first == 0x200b && !prevInput) { prevInput = "\u200b"; } + if (first == 0x21da) { this.reset(); return this.cm.execCommand("undo") } + } + // Find the part of the input that is actually new + var same = 0, l = Math.min(prevInput.length, text.length); + while (same < l && prevInput.charCodeAt(same) == text.charCodeAt(same)) { ++same; } + + runInOp(cm, function () { + applyTextInput(cm, text.slice(same), prevInput.length - same, + null, this$1.composing ? "*compose" : null); + + // Don't leave long text in the textarea, since it makes further polling slow + if (text.length > 1000 || text.indexOf("\n") > -1) { input.value = this$1.prevInput = ""; } + else { this$1.prevInput = text; } + + if (this$1.composing) { + this$1.composing.range.clear(); + this$1.composing.range = cm.markText(this$1.composing.start, cm.getCursor("to"), + {className: "CodeMirror-composing"}); + } + }); + return true + }; + + TextareaInput.prototype.ensurePolled = function () { + if (this.pollingFast && this.poll()) { this.pollingFast = false; } + }; + + TextareaInput.prototype.onKeyPress = function () { + if (ie && ie_version >= 9) { this.hasSelection = null; } + this.fastPoll(); + }; + + TextareaInput.prototype.onContextMenu = function (e) { + var input = this, cm = input.cm, display = cm.display, te = input.textarea; + if (input.contextMenuPending) { input.contextMenuPending(); } + var pos = posFromMouse(cm, e), scrollPos = display.scroller.scrollTop; + if (!pos || presto) { return } // Opera is difficult. + + // Reset the current text selection only if the click is done outside of the selection + // and 'resetSelectionOnContextMenu' option is true. + var reset = cm.options.resetSelectionOnContextMenu; + if (reset && cm.doc.sel.contains(pos) == -1) + { operation(cm, setSelection)(cm.doc, simpleSelection(pos), sel_dontScroll); } + + var oldCSS = te.style.cssText, oldWrapperCSS = input.wrapper.style.cssText; + var wrapperBox = input.wrapper.offsetParent.getBoundingClientRect(); + input.wrapper.style.cssText = "position: static"; + te.style.cssText = "position: absolute; width: 30px; height: 30px;\n top: " + (e.clientY - wrapperBox.top - 5) + "px; left: " + (e.clientX - wrapperBox.left - 5) + "px;\n z-index: 1000; background: " + (ie ? "rgba(255, 255, 255, .05)" : "transparent") + ";\n outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);"; + var oldScrollY; + if (webkit) { oldScrollY = te.ownerDocument.defaultView.scrollY; } // Work around Chrome issue (#2712) + display.input.focus(); + if (webkit) { te.ownerDocument.defaultView.scrollTo(null, oldScrollY); } + display.input.reset(); + // Adds "Select all" to context menu in FF + if (!cm.somethingSelected()) { te.value = input.prevInput = " "; } + input.contextMenuPending = rehide; + display.selForContextMenu = cm.doc.sel; + clearTimeout(display.detectingSelectAll); + + // Select-all will be greyed out if there's nothing to select, so + // this adds a zero-width space so that we can later check whether + // it got selected. + function prepareSelectAllHack() { + if (te.selectionStart != null) { + var selected = cm.somethingSelected(); + var extval = "\u200b" + (selected ? te.value : ""); + te.value = "\u21da"; // Used to catch context-menu undo + te.value = extval; + input.prevInput = selected ? "" : "\u200b"; + te.selectionStart = 1; te.selectionEnd = extval.length; + // Re-set this, in case some other handler touched the + // selection in the meantime. + display.selForContextMenu = cm.doc.sel; + } + } + function rehide() { + if (input.contextMenuPending != rehide) { return } + input.contextMenuPending = false; + input.wrapper.style.cssText = oldWrapperCSS; + te.style.cssText = oldCSS; + if (ie && ie_version < 9) { display.scrollbars.setScrollTop(display.scroller.scrollTop = scrollPos); } + + // Try to detect the user choosing select-all + if (te.selectionStart != null) { + if (!ie || (ie && ie_version < 9)) { prepareSelectAllHack(); } + var i = 0, poll = function () { + if (display.selForContextMenu == cm.doc.sel && te.selectionStart == 0 && + te.selectionEnd > 0 && input.prevInput == "\u200b") { + operation(cm, selectAll)(cm); + } else if (i++ < 10) { + display.detectingSelectAll = setTimeout(poll, 500); + } else { + display.selForContextMenu = null; + display.input.reset(); + } + }; + display.detectingSelectAll = setTimeout(poll, 200); + } + } + + if (ie && ie_version >= 9) { prepareSelectAllHack(); } + if (captureRightClick) { + e_stop(e); + var mouseup = function () { + off(window, "mouseup", mouseup); + setTimeout(rehide, 20); + }; + on(window, "mouseup", mouseup); + } else { + setTimeout(rehide, 50); + } + }; + + TextareaInput.prototype.readOnlyChanged = function (val) { + if (!val) { this.reset(); } + this.textarea.disabled = val == "nocursor"; + this.textarea.readOnly = !!val; + }; + + TextareaInput.prototype.setUneditable = function () {}; + + TextareaInput.prototype.needsContentAttribute = false; + + function fromTextArea(textarea, options) { + options = options ? copyObj(options) : {}; + options.value = textarea.value; + if (!options.tabindex && textarea.tabIndex) + { options.tabindex = textarea.tabIndex; } + if (!options.placeholder && textarea.placeholder) + { options.placeholder = textarea.placeholder; } + // Set autofocus to true if this textarea is focused, or if it has + // autofocus and no other element is focused. + if (options.autofocus == null) { + var hasFocus = activeElt(textarea.ownerDocument); + options.autofocus = hasFocus == textarea || + textarea.getAttribute("autofocus") != null && hasFocus == document.body; + } + + function save() {textarea.value = cm.getValue();} + + var realSubmit; + if (textarea.form) { + on(textarea.form, "submit", save); + // Deplorable hack to make the submit method do the right thing. + if (!options.leaveSubmitMethodAlone) { + var form = textarea.form; + realSubmit = form.submit; + try { + var wrappedSubmit = form.submit = function () { + save(); + form.submit = realSubmit; + form.submit(); + form.submit = wrappedSubmit; + }; + } catch(e) {} + } + } + + options.finishInit = function (cm) { + cm.save = save; + cm.getTextArea = function () { return textarea; }; + cm.toTextArea = function () { + cm.toTextArea = isNaN; // Prevent this from being ran twice + save(); + textarea.parentNode.removeChild(cm.getWrapperElement()); + textarea.style.display = ""; + if (textarea.form) { + off(textarea.form, "submit", save); + if (!options.leaveSubmitMethodAlone && typeof textarea.form.submit == "function") + { textarea.form.submit = realSubmit; } + } + }; + }; + + textarea.style.display = "none"; + var cm = CodeMirror(function (node) { return textarea.parentNode.insertBefore(node, textarea.nextSibling); }, + options); + return cm + } + + function addLegacyProps(CodeMirror) { + CodeMirror.off = off; + CodeMirror.on = on; + CodeMirror.wheelEventPixels = wheelEventPixels; + CodeMirror.Doc = Doc; + CodeMirror.splitLines = splitLinesAuto; + CodeMirror.countColumn = countColumn; + CodeMirror.findColumn = findColumn; + CodeMirror.isWordChar = isWordCharBasic; + CodeMirror.Pass = Pass; + CodeMirror.signal = signal; + CodeMirror.Line = Line; + CodeMirror.changeEnd = changeEnd; + CodeMirror.scrollbarModel = scrollbarModel; + CodeMirror.Pos = Pos; + CodeMirror.cmpPos = cmp; + CodeMirror.modes = modes; + CodeMirror.mimeModes = mimeModes; + CodeMirror.resolveMode = resolveMode; + CodeMirror.getMode = getMode; + CodeMirror.modeExtensions = modeExtensions; + CodeMirror.extendMode = extendMode; + CodeMirror.copyState = copyState; + CodeMirror.startState = startState; + CodeMirror.innerMode = innerMode; + CodeMirror.commands = commands; + CodeMirror.keyMap = keyMap; + CodeMirror.keyName = keyName; + CodeMirror.isModifierKey = isModifierKey; + CodeMirror.lookupKey = lookupKey; + CodeMirror.normalizeKeyMap = normalizeKeyMap; + CodeMirror.StringStream = StringStream; + CodeMirror.SharedTextMarker = SharedTextMarker; + CodeMirror.TextMarker = TextMarker; + CodeMirror.LineWidget = LineWidget; + CodeMirror.e_preventDefault = e_preventDefault; + CodeMirror.e_stopPropagation = e_stopPropagation; + CodeMirror.e_stop = e_stop; + CodeMirror.addClass = addClass; + CodeMirror.contains = contains; + CodeMirror.rmClass = rmClass; + CodeMirror.keyNames = keyNames; + } + + // EDITOR CONSTRUCTOR + + defineOptions(CodeMirror); + + addEditorMethods(CodeMirror); + + // Set up methods on CodeMirror's prototype to redirect to the editor's document. + var dontDelegate = "iter insert remove copy getEditor constructor".split(" "); + for (var prop in Doc.prototype) { if (Doc.prototype.hasOwnProperty(prop) && indexOf(dontDelegate, prop) < 0) + { CodeMirror.prototype[prop] = (function(method) { + return function() {return method.apply(this.doc, arguments)} + })(Doc.prototype[prop]); } } + + eventMixin(Doc); + CodeMirror.inputStyles = {"textarea": TextareaInput, "contenteditable": ContentEditableInput}; + + // Extra arguments are stored as the mode's dependencies, which is + // used by (legacy) mechanisms like loadmode.js to automatically + // load a mode. (Preferred mechanism is the require/define calls.) + CodeMirror.defineMode = function(name/*, mode, …*/) { + if (!CodeMirror.defaults.mode && name != "null") { CodeMirror.defaults.mode = name; } + defineMode.apply(this, arguments); + }; + + CodeMirror.defineMIME = defineMIME; + + // Minimal default mode. + CodeMirror.defineMode("null", function () { return ({token: function (stream) { return stream.skipToEnd(); }}); }); + CodeMirror.defineMIME("text/plain", "null"); + + // EXTENSIONS + + CodeMirror.defineExtension = function (name, func) { + CodeMirror.prototype[name] = func; + }; + CodeMirror.defineDocExtension = function (name, func) { + Doc.prototype[name] = func; + }; + + CodeMirror.fromTextArea = fromTextArea; + + addLegacyProps(CodeMirror); + + CodeMirror.version = "5.65.11"; + + return CodeMirror; + +}))); diff --git a/ui/html/editor/toml.js b/ui/html/editor/toml.js new file mode 100644 index 0000000..ee0c239 --- /dev/null +++ b/ui/html/editor/toml.js @@ -0,0 +1,88 @@ +// CodeMirror, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: https://codemirror.net/5/LICENSE + +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { +"use strict"; + +CodeMirror.defineMode("toml", function () { + return { + startState: function () { + return { + inString: false, + stringType: "", + lhs: true, + inArray: 0 + }; + }, + token: function (stream, state) { + //check for state changes + if (!state.inString && ((stream.peek() == '"') || (stream.peek() == "'"))) { + state.stringType = stream.peek(); + stream.next(); // Skip quote + state.inString = true; // Update state + } + if (stream.sol() && state.inArray === 0) { + state.lhs = true; + } + //return state + if (state.inString) { + while (state.inString && !stream.eol()) { + if (stream.peek() === state.stringType) { + stream.next(); // Skip quote + state.inString = false; // Clear flag + } else if (stream.peek() === '\\') { + stream.next(); + stream.next(); + } else { + stream.match(/^.[^\\\"\']*/); + } + } + return state.lhs ? "property string" : "string"; // Token style + } else if (state.inArray && stream.peek() === ']') { + stream.next(); + state.inArray--; + return 'bracket'; + } else if (state.lhs && stream.peek() === '[' && stream.skipTo(']')) { + stream.next();//skip closing ] + // array of objects has an extra open & close [] + if (stream.peek() === ']') stream.next(); + return "atom"; + } else if (stream.peek() === "#") { + stream.skipToEnd(); + return "comment"; + } else if (stream.eatSpace()) { + return null; + } else if (state.lhs && stream.eatWhile(function (c) { return c != '=' && c != ' '; })) { + return "property"; + } else if (state.lhs && stream.peek() === "=") { + stream.next(); + state.lhs = false; + return null; + } else if (!state.lhs && stream.match(/^\d\d\d\d[\d\-\:\.T]*Z/)) { + return 'atom'; //date + } else if (!state.lhs && (stream.match('true') || stream.match('false'))) { + return 'atom'; + } else if (!state.lhs && stream.peek() === '[') { + state.inArray++; + stream.next(); + return 'bracket'; + } else if (!state.lhs && stream.match(/^\-?\d+(?:\.\d+)?/)) { + return 'number'; + } else if (!stream.eatSpace()) { + stream.next(); + } + return null; + } + }; +}); + +CodeMirror.defineMIME('text/x-toml', 'toml'); + +}); diff --git a/ui/html/index.html b/ui/html/index.html new file mode 100644 index 0000000..346de32 --- /dev/null +++ b/ui/html/index.html @@ -0,0 +1,22 @@ + + + + + +RustDesk Server + + + + + + + + + + +
+ + +
+ + diff --git a/ui/html/main.js b/ui/html/main.js new file mode 100644 index 0000000..5f3b5a5 --- /dev/null +++ b/ui/html/main.js @@ -0,0 +1,153 @@ +const { event, fs, path, tauri } = window.__TAURI__; + +class View { + constructor() { + Object.assign(this, { + content: '', + action_time: 0, + is_auto_scroll: true, + is_edit_mode: false, + is_file_changed: false, + is_form_changed: false, + is_content_changed: false + }, ...arguments); + addEventListener('DOMContentLoaded', this.init.bind(this)); + } + async init() { + this.editor = this.renderEditor(); + this.editor.on('scroll', this.editorScroll.bind(this)); + this.editor.on('keypress', this.editorSave.bind(this)); + this.form = this.renderForm(); + this.form.addEventListener('change', this.formChange.bind(this)); + event.listen('__update__', this.appAction.bind(this)); + event.emit('__action__', '__init__'); + while (true) { + try { + await this.update(); + this.render(); + } catch (e) { + console.error(e); + } + await new Promise(r => setTimeout(r, 100)); + } + } + async update() { + if (this.is_file_changed) { + this.is_file_changed = false; + let now = Date.now(), + file = await path.resolveResource(this.file); + if (await fs.exists(file)) { + let content = await fs.readTextFile(file); + if (this.action_time < now) { + this.content = content; + this.is_content_changed = true; + } + } else { + if (now >= this.action_time) { + if (this.is_edit_mode) { + this.content = `# https://github.com/rustdesk/rustdesk-server#env-variables +RUST_LOG=info +`; + } + this.is_content_changed = true; + } + console.warn(`${this.file} file is missing`); + } + } + } + async editorSave(editor, e) { + if (e.ctrlKey && e.keyCode === 19 && this.is_edit_mode && !this.locked) { + this.locked = true; + try { + let now = Date.now(), + content = this.editor.doc.getValue(), + file = await path.resolveResource(this.file); + await fs.writeTextFile(file, content); + event.emit('__action__', 'restart'); + } catch (e) { + console.error(e); + } finally { + this.locked = false; + } + } + } + editorScroll(e) { + let info = this.editor.getScrollInfo(), + distance = info.height - info.top - info.clientHeight, + is_end = distance < 1; + if (this.is_auto_scroll !== is_end) { + this.is_auto_scroll = is_end; + this.is_form_changed = true; + } + } + formChange(e) { + switch (e.target.tagName.toLowerCase()) { + case 'input': + this.is_auto_scroll = e.target.checked; + break; + } + } + appAction(e) { + let [action, data] = e.payload; + switch (action) { + case 'file': + if (data === '.env') { + this.is_edit_mode = true; + this.file = `bin/${data}`; + } else { + this.is_edit_mode = false; + this.file = `logs/${data}`; + } + this.action_time = Date.now(); + this.is_file_changed = true; + this.is_form_changed = true; + break; + } + } + render() { + if (this.is_form_changed) { + this.is_form_changed = false; + this.renderForm(); + } + if (this.is_content_changed) { + this.is_content_changed = false; + this.renderEditor(); + } + if (this.is_auto_scroll && !this.is_edit_mode) { + this.renderScrollbar(); + } + } + renderForm() { + let form = this.form || document.querySelector('form'), + label = form.querySelectorAll('label'), + input = form.querySelector('input'); + input.checked = this.is_auto_scroll; + if (this.is_edit_mode) { + label[0].style.display = 'none'; + label[1].style.display = 'inline'; + } else { + label[0].style.display = 'inline'; + label[1].style.display = 'none'; + } + return form; + } + renderEditor() { + let editor = this.editor || CodeMirror.fromTextArea(document.querySelector('textarea'), { + mode: { name: 'toml' }, + lineNumbers: true, + autofocus: true + }); + editor.setOption('readOnly', !this.is_edit_mode); + editor.doc.setValue(this.content); + editor.doc.clearHistory(); + this.content = ''; + editor.focus(); + return editor; + } + renderScrollbar() { + let info = this.editor.getScrollInfo(); + this.editor.scrollTo(info.left, info.height); + } +} + +new View(); \ No newline at end of file diff --git a/ui/html/style.css b/ui/html/style.css new file mode 100644 index 0000000..6e59bab --- /dev/null +++ b/ui/html/style.css @@ -0,0 +1,34 @@ +body { + margin: 0; + background: #fff; +} + +.CodeMirror { + height: calc(100vh - 20px); +} + +form { + height: 20px; + position: fixed; + right: 0; + bottom: 0; + left: 5px; + font-size: 13px; + background: #fff; +} + +form>label { + display: none; + vertical-align: middle; +} + +form>label>input, +form>label>p { + height: 19px; + padding: 0; + display: inline-block; + margin: 0; + vertical-align: middle; + cursor: pointer; + user-select: none; +} \ No newline at end of file diff --git a/ui/icons/128x128.png b/ui/icons/128x128.png new file mode 100644 index 0000000000000000000000000000000000000000..6b709ba1d0fc8a55dfb70d228d319a9231382237 GIT binary patch literal 8097 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 literal 0 HcmV?d00001 diff --git a/ui/icons/128x128@2x.png b/ui/icons/128x128@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..e92ffe8d91365cf4ad21ed69e411ed002ea53475 GIT binary patch literal 17636 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 WDY#zwt5|&i0000=XeraN=*ckcPl_cIEB z;?$VEcom*{WfS7})x)+OSp3!Ef0nv)6WT>bdn;+hY#6!Y|$z#dt(a*`ZRpchmvEDvk$Tlrv3|7H{~HQ zs4)NOg}89`jE&`Q?m}@{JTz{Pwbl*|`o4ztWctC?51;d)yyK6@f|eE9LUqjy2Nl!n zkxGcaZSE{*8?i!jQ_DQ^60TT5Sy=&U%Zo6j*dbqp7P$kyXSEBK*384wzbbi%Za2zr2VNUHNY=5Q>bK|91>kV!MhaN726W0du{P!2pK}IYB z_s56~C)#Dia4Ze?ri<0{?#74DJ{agn-VKd~w}F#%078C~edkOrMomc!9XFD&2|$Zx zMj;_D07LuDBwlTpo@HD_=7(2XjS?OlO-DO$a27pKoSFOr21Gu3ITMg*F*Xp=tIs zY;CAU3&q*^ZJTjLjt&iga7q%;14+E_a24iOPmE|68*;zkKV7c7nHK_k3BTRZuw3pAv%eEdzO=T%s{_0_2DS%7=tzY~AnqQiUpV@HiV^(Y@2!|cg zO!f&&sgs#iB~d`Ba4#9_4z>ei&Mp>Vk1U`oKg(%IEZYiFFlPacCz-?7k=AW1AI4Zi zd~Ss$Tdrb$!@)K*vph?6bOXPP-;ntHrwGDf;z%+g=08$pj7ve%lAweoWOqU7dwC}o z=HJ)%|BdD&mtivlO3etr4aRRsg821Kt(QgT>BC=0`)pGqRFq=VQDS<95P>A1)~;J< z+IJ2=ob93Uf*_Gu`K>4{+oQ+&nlbJW$1ws{vO`+UDmSlY5-M1jhL1kF>G-97?EJM8 zyMDi7`UR&nO}iTPD@$SNCn+WXXIv0+LN=(9WF}83MjgAKO6CS>%ez^8+8Ba8lK+Ji z8kSzri;S!MAe43;+~{bLCLv}~GnO4F z-GsEI@~3U>dvMsrbe?Nv?=;wp=?j*_Pb%Yh`EnU$_+hOQf!buk5~DJm;AA3DUyl_h zDljf6iY6$0@yBYT>~_P<)cqZP@_iO~Q6002ovPDHLkV1htL BHSYib literal 0 HcmV?d00001 diff --git a/ui/icons/Square107x107Logo.png b/ui/icons/Square107x107Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..126e7faa38ef927dd0e06f2762566ac375d80d07 GIT binary patch literal 6955 zcmV+`8`R{9P)3=GV|uquMUum}i2)JXDTToMh5A(|J7Mw9o>NluK(i^(}rv#5Bo zd0tM=@o94MUQS$yifi08MBH~}6%a;N6$AzbW|+NedEa-dZgq7}cTZJybx-S=tIhOs z`*zj+)%V?Rx%ZZWTt(GlFb&;(J!SrU%v!tzQ%?R28YWIhMO7WWTMk80pg48tY4W-A zkCOIW){}L-&-=AeYW332FVkn4>zVZE!?B}>uy^-XY+3sfUj5e-SpV7@w|}*m217Tp z;ZQQa%Ri*rpokY1U2q9b`|9^GZtAIsS12%vA2YPf>>xgtz`Vy9vR#6Pl$8N7 zdi3^K*s=LFJa*SDc>JDwpeOiq>UZj3%klwBQ56A!P+;cb#rX17w_w7wIY{&Zi5>=I zKxIi%S(=mq5AKr$EVtzNtH=Fnldzzw8Y+hY6_vpD%^Pv^bywh(RWGwnqt7gYmO@NR z1EmrSyTS!Oy#Y(FxgC{Njp%CENt!G=Ak}_IP@V(Iq$ZF77;*qZh7KN-dKn<+f-+zm zDgEGF=-iL=I?-pKv%^H~=&?Be;_qNswSqUEdrt6FnMYE@v^0q#+VuQC{&*J_UHAiZ z9x+K3nqutY#>0U4qya+&z*6c_ziOI_M8ZICH*nhLKZg@%O~rGMJ_N&H=~JXi)RL`P z_O~y+X$9t<`%SdBB*cIxA>{*N2w3iVQmfJb=pZdNd*M8sICDByJ@_DjQe-_F7E6vr z1J#nBT#wVg{zCyO7B7ob)eQmjQ%@l&)6mhDz^nyxX$S&dfA)D{bPyknKxw4v3^bjw z7#IBP4x##3qTn$ehJY0l7=&8v>aeizv!BD3b*r&w`)+2U3Q%mGpZ}vd89Z=l$9!Rz2@=`lvTx8w1v3nil%V`o8jpTZNfV{+B8$E%@>> zjF~zIy^J3?*pw7vXt}+tbr;138;vOPLF-3&TvXBx;lW{;M$It1nrn>&6 z_?~Hb&Nbz{(~l`zJ@0Y)sHXt_`#7l!DY^lSo75CTc~w1x26WOKB?ycidyX9&RL9h* zn+?kufa&ux4Ha<}HSrim#5I(YHxi@w`HXrAVkgyaOPJ`OXpYfq*lqLoGlY&zgdOTt8( zG;sa=Su6k0e}Htz0QFdcSdw(6L;-1($8d6E6_%VZ5??rO1Ws-kh6+tZzC|bao7;Nv z-2M*y%ss*&wtt>hVj1N#6J(t=jH<+K zUz~#TCy#PFh9P>d?qV1IWiO~QI+nXWJpu2K75UELZm4CdV=WfnN>n2X>HCUIh{-+l zZ=$mgXHTm`^MB40pjeV@%Y1O8DO=&=>2s!}eB<~U7I{1JJxGxbHIn$%K)@`xCuxvG z{p2&pVb#}Xk^vEOrAaL%N@D1oryyP5%DAGYq=HKU zwQj!+sv;)FTT4mn)HDzpkeVk$VSvS4F^mWpU%fhwQS~D$ao>eA+|G>xmK`5dQet`U zQo3VZOBc3~!}AqOcj<+9*M7!GcLf%PNH(%nvbyjwKUb2 zMb*hDl0mseW;4Y4J%pD_N)~;X;_AGipYZN9nUk4>zNY{wkW1 zG*0parVeOw`ZU*hN&{%TxRydm3@YKIH^QntnY;QQQcX>NU5`~;4^d~vM2A|IEpetZ zQO0jwtzUX0BMxnsFA4KJVp zk1tC-*pp*)r#;C62%r7H+|MUoACEH_o9r90-?4{%O428z%td#*m0?#eoGf)Hc+yz z7-#9TpU$jLM(QH~rUvrDGn}Y6I2!Cn(pB`G1!G0kFlM@CCHXZh5 z%ZdO*NMMTdT!5mB@#?wRLCGSm)^Cy3*+_;ACt2N*D-U35wyVi6Fad^6WEov;wUuSA z?-E$5oFDu4W6gMGa|_}mQGJFPEr<}ngw@Q(#HS|`sKx<7d8MnG+=WX|7%41Q&g119 zno>i>xjYRRoco{w^|JZ4RD}U0()jenKa(+W`)ju96QEMmK=FZT&is(2(`s?;Jb$2M zamQVfE}q_|yT(g+U~2A4xq+$9Rd*6Ogr`g#;htd7af*$R?QEVuwH+WsLN^Nx!goFU z#bs0L+_(Imo$C0sb4FF*l=@+gbOr3=^#0B#k}OD*wX>wD-j$HB<;tga!06J2V{KVQ zFeZG}v;Rm7FR0d#uE3Wk4j195E&~$)w#Ml=*h6UczSy)p5A;= zgn9H7^*6Y{#Q9JsKly%JO859JGOBX!xZ$FoT(=`6Fx4;B^m@XSrR;AbiTQj|gI+xy z^kjbb(g!Jdo8qdv?Da&lkzA1#+YaLpja{+imK45KA(xY=kB%E2hviPV2?tCKB8J|2 z;z#>T%o$saYMuaT1+xMTCuRQjzGHY{N2>@SrA812ADD2)NiDav_u|2wN8RK0eK9)q z%jrbt*H)yd!jQvG7+|)FFtK2~ZCC^yu4I#UZ#*a*YE9-UN@+o#JWe{c2X-6@r9I^7 zET9w(WUwIQu%m{vOyHVEvnk~ev~UwL9Q70jXL;3z>BliFJ}}eHa^j5x9XQyn+g4tH z3sbV4O*u8!)e31Rs9^>=;a`a!*D$4SSjs{9yV~q_woqPb>p^?+ziDL;5)URYxoG}a zX9DXFb=g`3K~$mLF_S48;~E)3g(7qW!%=}2slYgmGh=Ar^d6L-B9C|7M;#*i5%VV6 zN)VXnBr*;*IRpPs=%CM z*xuF~{3M-@sUc7`Wtx4lTmFP1okge!hGH*l5_24em8l3yOIF?8+HJoY$T1ycVDhc~ zU5UUdUzQ3|fgCGLvBUxb%PWEr=hcB)@FSNe+sY^J4!R`_%z546%=HMO^1aFGVVaUW zm*Pb*?AMx-bZo4Pt`zSSFGQm2Nq^fCDg>(Et1j}x0_pv^arO*`reH={$Lp~=xyy>H3 z2wIpG#{wHERJD+^sN}z>$OlB>fZ3rY1LyI?7X;6S%fs4oq+4VuQnJMXfrXxfAw-$J zz3%6ehZOdR<_tk{2eIH7#A?g(BYwhD;r-|FE5` zLPN}z3u4mBi8U9^9gPvBUU=rJqLdae5pW=*;LJ%iIGM&Pd+vU)@k(>{++54BG*5P+ zm~$|MU=gg3C=$Kl!*)kn0vH+2EZc^vI4DX#wkSz(UW#kSTAaJchNqj$qvf?XHy<1QeG$-`ZCo5aECc2_UJu1OTQY=Y-0E8xwv5IeaVL*lQo8=?|3YtZ4lG zv%ByR?=w*uOHFwX3NTBou}Y9nbonXc@LgxhbeQE!@}gbY+zP!jk(|bs>34ksQ;{N? z!GVbmChz|51nXFjoKZV4C{~#_t=@&J@7*Gz1D2V?t1l9;xT>O$K%FzI0k@q$)w!BO ztcZau@1EI(pWV9| zD(^99d5n`m045gMbNK97FV3D>kEg#e%ax8W={kA-_rKSQ?FT!>>iy(|pzy%bA{Yn- zOz2`tcl`Iic8c{>G4DFs44{6qYA3E)xk-SsEKg2s5P%8wM3+5pu=4FwCt%gG+3w`b zuzO2ML+kf%?@O+__v?t~0G1(w5geFU2|}>;yx)dfpWh?iP8i9-%d(Q7e*MoK_&G}y z`B!dgEa#Z0h;fns#^gpLc>|N}D)x9n&g!4P)`Y(;nd(YZ*nKc(k<}-~8)(JaOeh#AC_**MCJ2Z+vJgR7yB< zUGY`fDQWG=dsLfUI+iRLgUc3?f}A`h zHuI+}fw3yB9EY=~jB+I+iak4cp2ZC`cJHDwoEHTq>@&jd-*^-G&@ z-MLdzI^+;Z*#jF7;C^z%-=r{C2d5rb<;vY z*rXu;y$>bqjT8f%d&dUnTs)hfgxK^sy^j@q<3Vd+5CMUa6!11V_BK6y>j+isg_N?} zN;)vu_gWLGkAN({a0Y%!pbSR}6_1*cJGDt6;4=624cJJ>#Cvua?ovr55?}=D0m~nVV8D2O zxa#bqBsL52o{`cYm<@^`clKfVMKfJcYWnVFR&u#e7-=ZPUhz_@zDHK>UtZsfvg$HB zgck9Q3o`7H8_gJIiXEk`)C0;;PyS);Wsqbn|GEcMh8;h-uH4F7-toXf|7*ZIHanV7 z0E&7WayFoNJpJGG2Lvc>SS)qMm!Gl8=NQ(1bI1sRCG}VKdUDe$gT|ia|2``xC}aSa z)5MOJOTW@bP~rq?_3k!&_lfsJB*zW61vMso)Juk&e4Fcj>-lhWopUm!M18?OsKG80 z)LOFozCeB>9PLoZ#p`N{t|&4vPByaD_e-++e)+`{KX#zjALzv574L|BtF)9XaBvWQ z>Zv&^6%ZJ!FLp{lO+nM;OQyLgg;L*@nhggA^&&-U7TvZUU33m&3vt8BTXF`frw&-D zK)}RMlQ8jBXJbVpb2+IL+h4H{M>oSRs)-Jg z+=`sbZ(n*JGjDkdZ|*uG;(hK?rve%ind&K6dao7OyYBZ{evuB7BH-gFR`=@*nsE7P z6Ox_ATYjs>xo3%tjCh^qhu=Mft0_mfjc*!5u|*L^v!aho_^qeltM^)=8jBE^*tMGD zh-7fgonD8l$uYi&QWkQYkelvD9VU`@TM+m4@<4ioAl*dL^eRccxKU??z0t8N?Kw9g zE*vl$R@lZOmN0(k6tU+h`jq2G;xdx5ix-Z=iD`FJmGjLNcy4E*WDi&*C&4DwYx->p zKcWcAgPRWGFK_O{Cf-{Hah!`HpwAT!pwc|k=;kS@%)aX_{WwOtlr*=PTo49Oe0A4++f2R zs85OuOu<)Hnr^nQM1ZA88ei7D2#uo~l(?KRrW*5)8$pj6oHTAYPN=Iy1HE5G#!9vr zEzia0odNb7>A_|S53Qk;${Nary+aWQzNMk~ZQe3GritBSTuB;~yUb?oV~b(&@`lO? z8jBp5Oh&5C9T5aLUg{~GP`-ySB{XZR$}p1tR#E1-k{;z^HW4#6(cY`$2t^qfR&S3X zmhXrk;Qc$q-M$qu2iJ6GvWEdt6kt6u^mQCU`G|@3ga}8%!bFG*6s_luG@O~NLIFq# zQtWwoytDH`l9+>>>i63FvIAAcp0L5`e*(m}uYfZS2{%F9@WpdH1-_*sf=A))fN6JI zOAH!@WFzl+Z@H4k66RjmX;SN*Mj)(8!|E^Dk$@-=FbIcK zLCc5DDq5RgqBLzX-jlCW*YC3erB|GK;v?r)7p8OP1MkCh9N2z~0y4EXNOS9R))P0L zq_pGC4KJwJ|MnAPdhsQpC4cDS1uW8fr3OqGmt2@QMygv0aWKV1o#Z&0YmD(sqyh z@d_9ef>Slk*;R<);#fd+_(Hkuyc-LGPCAs#Qx^KS06(4gsG@)VqjvJqtDbKU|XWz2xhzV{;g=K$WZ{oV|m4_%UW1(U0nF5rV(Cu$1>JYGqfw940@>bqt zOjJ}Uc>a#-aQ}_}^|wpFbgFMEcvN0>)n+)sGB*Tti>;p0kRlXjnh#+oNt^}POYesrwBfI62`lU^`g7| x5RUBKh7UKtL{ju9_N-s;_Ai;|Z1rWs@&D>Q;+m-!X`cW9002ovPDHLkV1k8*Zejoc literal 0 HcmV?d00001 diff --git a/ui/icons/Square142x142Logo.png b/ui/icons/Square142x142Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..9f2f06803a708e9d36542d2bcc1be42106addecd GIT binary patch literal 9445 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 literal 0 HcmV?d00001 diff --git a/ui/icons/Square150x150Logo.png b/ui/icons/Square150x150Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..72e5983f34b4f3cb0993d15c04ab6f3040f49bc7 GIT binary patch literal 10013 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 n+vqsb<@{PG1-)-6>wM$f z`_6lV(SI0w*Ip%SuButJqCcw2W1^9wy?OHnQ&B-iP% zd%<%q@B2|mE6aB4i$p)Vy76aeTa2GJe_rVL3ZSh%C)6+5!*X<=D)A{LNrpr$=Q?o$i ztyVwk(wVO4DbbiA4dF0Ki3^$?B2Yjw>bsAd*r4`?k+h@TP+44VUjzs`=wq{T`k;2v zL@OijE+;qdm-SP?V&{Xequ(A^#q&|J&q>Qk)WB{RN_4Gl|IS;gl-3kNK|icM?KACO{Z#^{j|_C6_w;zCKHBe;b9rSe zl?^bIkgKJ5dCoFb-!VmzT8EMYEFK~L^|=xWuNeJ&8inpbl%!$`#+0YOlNCH;hIJu6ZdjKTN$Wm^PHJ@&!xYJ2{0A0)2FMki(Fp!~=?eu*rYs?)a+W3ir*>^e8T(Y>na+&}y# zjDbB)HO?yu`v)WA8XPbL)9@re`Z5knV{1QB*wTb7qPLBuIiuF)ESEr#*(ii;x-&CcP{0 z+&ZOP|3Vq~Km;%6UO}Xeh77jai2tfYIFRCNaV}u;%4D5;&wlOwflQ@&v!^s)llni4 z*`olTD0AiP42XA@gH<>-!d|Zmu+8^V;WTJycoAda!&Pe05MWlCvCQvxy`3xFz6@$5 zO8hHiSxyc4GP3fv1Ny&Yp#r}X7flh{+N07Eu7z+s_s#h{h3JNJ_bAE2dF6aue+_;9 zJKq(%bE#$=>)`yr5`i>G%m0pkQRdy;jm0?=R7*ilveY#rGZf5lTtBt-zOfB6&EysL z3vKoG10(-*3unmC7!mLRF4D|`w4$T`;@9h~U4`En04mgbdg5b_wpUhw21En;4!?)u zFFNP(0-E~V+gBl`DEmeMqK9NyJ4-`(w2NQ9NWaI1`XGb9sAzs7&ucx&<2vg#*I99)+(d%AOJDb!5rVLJT4iD;DLF4XQ$`6wc>WTghcUoe23E<$V8S~u!AX>8Y0MQ zWTPAKhth3XxHEd4b~hZ&A$-N*l04x5I%zP!5A%j85kLRW&6ew$AX; z^=|~%FV%5oczrA44_w)IFK6FN`*5}<^$Wjr@M}rJ_6;`7Mer*pS=9P?Ge0_w5n|Im zMb%ag)%@jf_#)3D^cePG1e07P0cFw1Yi7>pDDpG7v+y{w3sZY}(rz6#a$Sut1`ZIqZs?1~GFK^1^__o>SGv@_hu!RT{NS=7dK=wMUkL6~Ccs@gLT_(1a&jo=>(F z=Uonayzlmf?(zRmcvPxX4@+BR0!g#lE-t)T2S?Q?m1^k9ELF=Yc=5Vd#BbPI?JUA0 znW=TF%94pl_&R>J$7LE5uxmQZu()b?@wdhGsl57?3)1K(X=#*d`Mswr(QtXmx~ka* zZ1i?>Ns}iR9~;CGkrW?j8OzxL!$)Vomh@?sZ^0qd6R}HA)(+Kdh3D`#Zd>7^vK}xA z3`S+qut9%2bkS&p#8{y#{{LT2DzPvaBR)o`dOc6G^BZWZN*{r!z=IW1tTt870)!bR z#N;gxclb02kd<=7)Fex#V1NbtCJsojejj2=&a
HTzKWm-Zvp2WJTa1xQsl;^p| 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 literal 0 HcmV?d00001 diff --git a/ui/icons/Square30x30Logo.png b/ui/icons/Square30x30Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..ae3f813fdb79fc8c7517d5efe06f1ae26e3968cf GIT binary patch literal 1712 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 U>p|)P=sVHF2io@wR80N<2hey;y#N3J literal 0 HcmV?d00001 diff --git a/ui/icons/Square44x44Logo.png b/ui/icons/Square44x44Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..144307bc706688b83cf8f380874d333508c548b7 GIT binary patch literal 2772 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 BY@+}G literal 0 HcmV?d00001 diff --git a/ui/icons/StoreLogo.png b/ui/icons/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..92b0cc1a57122d3d850ae64a40b3f9d001e76c48 GIT binary patch literal 3184 zcmV-$43G1PP)P`75?7RvobR+biudnQ%p6;0oszVF`i zoqLw=oYxxo(scv2ZOL)nvQ=nU^Ax7lHK4e(5*l=98qJ{>ziUVxd*31W`)qSl?&HtC zv3IXG*G7L&7tS^w!Jl@#h(mjJE7=W_-LfkB@)Snow+0)3}+VW!(uZQ0)f$vQJQ2O5kqcc z(KO-T$3`A|I^VOI#iGF61$Ub$D5->HDV3!Om=73}{!h@HL@XhNtSm3Wf-%LIUs;UF zBMLCG(2y~sJ8q%1KaOTH?K8JxxYjo)mj-=r60igV$B@BjNRaF$Wur~foUXn^pti%n zQ1qrh6M()1jM4}`SvwZ%=8eYEsxm2jwyP&@<7j6;cD#EFzkjbA(SA}wk-;`WI}8XHb4 zy0{8;q=+vZX@_25z`_vB%rQw5uI5B;r#5N9MDHLTsvn0}*33hMKF8@hj!>qqA>WH< z8jeO|bble;yL4Qs+FB|WNp0r>!(+;mrur@yasr_-h&a|Rsm6|n=Xj?O2?4Eo{c;(R=4}_8C18noG zaTi=`&mfw+2GBwN#G!R;aRl>570H)h0V{T2#6F5%5%Lvjru3Z^vyy&E`OX_>0TXOm zzOh5mu>FyFD4;yS+DtzQ|KE0<>%!*7D>!_)4>8Uyygm!U^o_!D?dTFbIe#=3k1fTw z-@1&0@7-1)$etp!etaN-k4~$=^LJHa-<3Xm^~7Z-++_!2A}kTn*o{!@mrllqrj$#K zMM6Nd(Fv^k^LZS&*yRarL{x5I2jP&)w%>HM7vH$j>t%VP&_q08BSL${DHK02a};*p zKSQovKeC7tXcWI}xdD^RE|J9zbmf(fV@WepW46x(ZNPT>?6RrK%rpdoIDM@TwZAxt z1LtlaQe={FhExqxl>|x8FPFCHB(TXK$z%)~OP?T+62$b89*CIoczm;N9MLI5%AyG` ziloRY*Y)^S8W<@wExx8^EM^kjaGlui6AYq*PU7C}r_oLC1;wmgA%&Ct$#&Lr{m>RN zyh>maoRA#Nim^Enh?O&w(TvTQ-lr04c$BOGgGA0DG61+^-2;#YMhZgLx`h+G*q@pU z)L+*A@hooNj7qHyChSy&h%_+i``AgrzOzW} z)U^B?sZC^PrlYK%FanjdfDEmge*^WtnUk32@Tx#<=LX|u@~thMDj)cQiRMhJpwqsC z!Zw9AC7TE}E&ryDRtWukmo|vhjLn*AB|3hDm@C&7wq<8Ao$O#F5K4eeHwMr`CYrgQ z`cTWH)Kb$$`Lr2YIMKiILNk!LO8VU$lc(m{Y!23(jr6(AkR4 zT>(Qb+fK7pybmx^5y+rDDRm5d`yqgt2T~NrytD?l(dqLVMP$acql;5=l>cH9 z>iMsanY-%-QWW8Y#1`g6KH>eby=HtVYB;Kqlj^{baz|?XSB~C573U;sR`^SCbvo)p zvl|HfNzu1oAVrZOk;3Ykwr<=cn!>{SOYnrFmGz6OITa`Ecc@_aFokmTjSI)8gj?5G znJV?t9*x)gB|_Uy&+7h!n6?R@2p2b96x$D9yqURyGrW6hg({mvh+K9sLY5lLu9wfM z#G2WaQ2I;db9}u?q5dkdVBK(hQe=YB1G$fIG)1<%<5+u2*kz&@acJ;!yDub>4G~NM zo$?^n9u?(<*zwTpz<}Z^>?Q87P^b^f>cOVvjG3K+9B>yEKbPoaSW_{k^^V3?{_HL6 z|Myj*0We~jQWje9nF_4I^WC|%e z^f3DsPOTBA#JB17^K$V*Q;LWOHXp~H;~j{Mh^TskPl~i_kv}CUy4cZ#m$6xB(*Y@% zy7L_BGA^fPUi0S{p`HRpP}ONU$MJ&`9q8{Kl3Y;oEJr(O`#QZu)Pha%-zKuhiYcO^ z>%%if;m50In_U9pDGlb5|PSN zN``#OvOFb$S1hW+-Y+gr5vGNz#*ENlr)7b`r6k(ZooG--X*w zqp_n01}VUDGiAsFB!{AeCot9|gV9NQTzB)B>jExQ+3frvxPhQ)%C?y~yX-ktP~nSC znIPQjGgSXK{`VHl(gImgDtW>ZEPS2D9AGT>6om@S7B!xiFBp%#8<%86Grz#T?bVaK zwBE1ZoLm$8%D#8;Yw|$_!eI`%TDd7CEGM;4W49Q3;qh8IlcSj%2>c8npDrrvG2v6f z`q$23>#+_P6i6h9JgJY4pe8|%8e3Pp<6jrLyl9qinh64V2=APrTQW0<7RuaLYw47# zh!roGRE|1&ZZeqwmQ(2DhoC+5eJk;$CTfG8y4-^{>I+M$>3fse0k@!r@USUOK022N zw_HQPh_RACa99~C7$+pNHf1LG?xtwm&n0Iy$y7{Y1M;032kvK1Zn~+-?YIppgcx24 zAR`9zqXOVk(_!KW(Oa0bbS?1+=Q+Ed0u1j*1IZ4l@PeW{X2FGjjr4u;+S3=jO)3Un zd;ZHht{i^@?MHT^pn?pQ9=H#q$reWB0$WY_%+0wc(}=+sN-GUC?%#>G5A0Uq<=Uy& zG49SsP&TOwi2+N-In6cD;h#*nwuk+54z^=ukL6<`Xl-i3ufDb#iNQEOz%YoS#?W?f zD@w-CMaA?w=u9^`K>Hg^X#j=`#=CbYbDc4VzetfT&8hLPJF)HSs}b$(=bvgh8YeKq z`Qh1wC95#)V^5)Sb^|?1s-y@p?9iOw&zka{Yh$pl3mq+oapKh%arV$2#f8-G&He|c WVOV)qwbrcw0000KmLe)!t0l5$XQTy%sZ`Qp$yUj}GX^0^rBc~qR3ceRCEHjd>nJ2y z#@NOZGmK@1VgA=Wo}TJ?pLhBH-uL74==sc;d#?Ms&iS72`JQv`%XY3_Fcy2*WjiG$ z7>u0|eay^|hifYr3!J!*=wL@e zx&NlrKnH=r#m<^{VrOWbgCUPfyac`-G7OUSbqf~ZSeV|>qh>F6C6HTI&1JuFfatd( zW)m(yq_o46D`!PxPRkL>Zwo~6b^Blav_~$;j+=c+6^V_yZx>t0_nI$bmHV{%$abX{ ziuCcw_wEa~ZjZQ48+cgisJh0!{ld$$gt@+8zf{%9hbBKM8;Y&J_Gr^L1D}@l9GluF z?;W{O;W91fB=X9@%e+Zvc4OX|{g#$YSDIoJpMTx%7@3+LMP`wi<1JwlI}{dinC;@d zRaTeNU0<|&aZCuovb<_%_J{*4(|2Xn&nz6<{iVa==}aEyi}ZW=XHt0lnMIiIyZOQP znBZL}tM;r5we#L~r#ge^jp{t>E~+$bYc{p(YDfmJ*U)pzNgh|$C~^64fiCtL+M@8M z{fFh47wd1Vm-^;V>n_K$m=V)Sp010+>TMn~?B}^1SriuM4KqN+1rto<51SgV7gN7q zz^NbOczFAE1=xY*mR(jZ38@a}4~|AzoV&eIT-4N1+kMy*e({4+y20WWNmq{0mS^u- zahUr2EA8{1fn%Si52|%9f0g6V}CVnE5v3Vb}Xyf9sy3q``6rn5DaSU23x&tcvxtKtQe0 zjgs+XuS?WIkw^hy9>awj0rd5N6n$5BB+NI-L7Wf-Q9L!_Z)~ zYMZ}XK)Q@=+WZ7ePh){k@L`J4(nmHi6KuQVDXGLu#h$Y3=VAH>PAN4uBpG&PmBEG^ zTb!k(XLetAc%5(N$0B&&ZuX%>D{b4wLGC&_h8%qSM&s*71CF=Pm1cJHB?rJaK6xF% zj7#qd)e`#qcbl(yhL1OM_p? zD@_z;exwZB!84{9Yh}}HRi1duv+UMxIfFDl^Nq`R&O)cd0`fA4o2x%B%kJ3FsMdAH z7`wPzIZ8~%AZzL=1toM}==7U6y!NWfO{R9WfQGPLDTH)qD^bq+~8 zS=mfWEX#A z?_Ez~*csnF))%pY**TsymObn`SHRZPd%Brw(XuJHCI}$=UM$ylF~GP zy%O{3*9XqF>`~8m+_>jV!u43al5xs&)OXrjfl^e(#U-{(RnyX~^Rh>6$E9Q>VNU1y zJq^@e+_#rR$Q%|cMIRYuzuZ)6iTt+tn(lpiq~O*^R&6o2vT55M_=@$8UHXvz&CpVc zidy9p_!P0hgtOG&Dqm?w-aPO2BR;B<+Z~UqJQ9=ci+J;VHq&J)$o=aF?^I_8qUzU} zaqdSoh&@C8RL?CA6x-a5Vc+blH$GEN8L;1R%sO_H)E-57>6?<$$eGr|A}hj(hI+n1 zFQFukz-GSeTS)JPvZ)QS>u(Wp@3utwsrRs-Ud%f1-h;aS$dC$uvWA14&}vs3O^0{| z9+{8pyRkDU>BBrT9(JRymhYBJ!TArz(Jv$OF>&6`F7nl`aErIWsJR}-_yR0Eka{3vl0 zgyd8mQa41s$@R8LhD`D4(#DVv39Yo%5B4=1=`P|I)>Ka z?zm~)!6#EQ$VN4kdp-BA!QHg)homgcx}+Ko7?R`o>?j^Zm+O>#hMlb`c6RuwGn5Zi z1=3|ayb(BU!BrE&GKbTuZbI>V`HF4dfmzzJ>IM`ghS*+cF}-QK%uw{*e%7!|IQ^TX z*rzYXD*b}@c|5JA&)e9u4ZOwFIU+) z)e+oN!d29gtab>U^B}k_nllvq9NPh}Nn=6HhOLM9*hmOe z4(dq95H^4>B`Gl}&kog-!!oY*j7*l0vPpIWJzKYym|?#bTu9#st~?$Z&_a-@Q@=XiYaJN?2MX8rcrE}ZCRyEsI=`g}EMbBL|KB08yDAO@^k zWY9m~(wU?+i=^Ts;H12D5}nVZV*~BXG8z?SqGCDQ98r&qHEFBbpIiukT`rs4k+-34 zDyhUH1qzR?k!Du>^6SRhOT2sfc9=!6!7Rx2*4ozQw(&S_sTK3U6aM;3qlP7Dv#Zti zv1Z8IR7-Ykp5gfZ=)5GfZ5tDus(&5rQV`2&<01aw19=_N1O_&H3)RvjlrlB;m5DAS z&qXVg??Fc0@Ums9d`|mh@#Q*4Pj-#r)I+?5a1;l+zTr)5+!pY;w~1(n6TB64Gw&Yi ziX4|_T|H|h>&Hkma&wIZQ_P9I1DR?}PdD~%!_tdLaUt!6?|P*N51xU&2+ELJ3AFTg zFIU!)MsLTFvnLNqnJjP-WNU0VP!`)I^=Ex;m@9#~#o_AHgax+M3@RZ_LeyPm`+8CDuu;)I4rhWV#7$ z=gIBBAQ1ns!)e=7{7qnf(Bj{QqGLGQeEbA#S2C-Y7BBZbik-YlykV4E&8(j?o9B$> z;!9AMPFTVh3{||tKp!)K)l;AQJd0+;6)72yUahar7i#e5kB-|SsUJy02}SN1wqu@az$(i`p2UHLJK)oMF10EA0j1D6ch#^atWc-$Q$**f(Ta}l{tfpq0PHG?l}Y;orx4N! zfkE%R@`mjPxvaNHjsW!i)(jo5f=Q^}5AXh%C2))LuJ;f3wg8sXKQT>mLRnyYX-`PL zM|OFgfsIL3gtWwsAXa=R7CP|uMqn{jNQceeD~Wq*S&jPdod0*nn`;tkXN^)QTiJb~ zWTbFMBJjXRv<3@{iH{xV>)J!H5!z4c8=4(3%D_<|@P$Cg8rsTbOF_?DzzWMWSa8>V zqEOE*g3D(({5*_=IvVe~nql;^0Crchyab-&Z%8?@RK-inGcXAqp8ELq-*`$_JL}l6 zK7~pgOH8Iej%WJ{z_*8n-zR+K%7iZ7Nw`kJWYGRPXPW^E9%Ha+R*7k87>b+1lKN=K zWkiSUn0G0(Ru%!nt|OhQe0q|bqBazeJX}N1U}r~}#6PB7*pLm^R2pe?j=y3*IE6<~ zI8|3XLSxenyE!g^J0v}y3m2nYh)jSr^xSinD!K9t1JIKU{Sa_W2)h%U+(5fd)5rX5 zPQ_r6TTNtK)++&A1|cZw(5(>E#&|fTF}pe?i+q+oKh7)Zp}O1Z#gigtFHd3Vy*hx1YzIFxBu!-Gv=G2}EkK%wlI zD>DNg-LrNUuvtpg?qZ?X1(?&%#k*?nQYK=}Mn|Wt%S~9SqN-Ee_DZRMXk|$Oczx<4 z6d(SRqrWd3G9h%CUu4@L!bFQY>Bf7x>z-dDH|qEWw<)L6xCNE*;|u%28A%|Y`@as8 zD27hS%`h)z>?L&zyBN52drCL^aso_%ke9n8vfD{gj%iCIf)1fn5 zI}g#G9jFVYp@}^e_l0Sm=d3rjwX%i6-v<^l(*^L)LR{y}o_-HcJuj)dLTcCPu0-tn z8im#w8%Y8dZR-`)O8N!&dn$=RYY0YFcY8T1TcaTa0CqjY1RDo9s`heS&u?=OAs%n~ zjERSptu$fVANXCMq+v}~!&A#Ij;`!1bt_LjC$=(ETr@$|dWDi#KwwPEIpFu*%oQm2 zkja5qQ%uLouhuF__~Vc*gi4(J0g#1kPz%zWjirsBzLwPaosxiBtGBR!XWq)(mWW3 z`>5W@jk)LclCO98=#1<~tM6eFuf&YOTYcaxVbD9m$ep;85~|4(2OnpCCf%O*Optg` zxhOiCJi!KinuGMvR!8DhPraMrex!AFHI{zP`u$>j$5a0+2SC8yoz!Mn%|Q*gWZIb5 zSt;Db`Y~K$UPG(0C?GMk)3PWRidpcP5t&!@O0+>M@uAIdPwf+=Vo4YhTL?%-Q-SoR zN{dHR$8LI<*wSJz)rOR(dJZORO&wK$l}%+Q4 z;lY%KaH~9ky<%#9W9xt68x=e>495x-zR@A%j4K%BTXuK=PnAVmus!KItLpm{X-HkW z8sB{yEmko9`p(#{2f}8nZvoSgD!fRUusi-@>UX~JYd|uxdK~6fh0y!Kj$G=?Y|(Q8NOo)MriSnLvcY8h&4x z={dd)*WNIjnfK|`qTYTUQx#!Y|ICQGaU6QRL}g?>M!313y&jllj~#tlX6a>;+PrSr zHGn$dcK5&W zw5Jf3$UNsMoHSN>Bnz&CdT9gBQTyt2+ZN2Y#&x&R9stg<&~McTAvtjm@1d`VvV@?d zwA>#6pgTi3{EQ#-!B=`k!?)k}K_%au_=OUxR85lpo%$8F&^rtCg#t1$G9|>!@p1E& z8ViXS14bTpay!n^qjDmr7i8XmpC1~pA{{*|=yl7jP$TY&hbpxzO99@LE{e(#;>Fzu z$?>tZkS^HBr1}`fyWCJ#%Z+t7E%5O0q5pu5S9n7_cD9>>^6>}QRd1X49yVFLaNK-$R%diG`&X2 z=Nm%?gW3fd$xf=;d}=Z>Yq|JCt-7nBC@uq&_xrn6D%4cGjzdk+%lMk#jO%F5;(+W2 zf4vEvE|GTR9zRTJ3@r70Q&0YCIEh~IL@pm+@ab^L={#l+QyAsEK-zjt7WvZ-OpEW= z-X|&ytbDt`jl1tg*7E@Y>uJ=KvC88NB&)wez@JOyc!(0!cGGSgC|&e~ z6|D~~vJQ5j)YES#R`^_hn4Gss)Cc#H;A{drP|hJCu+0gC8G@wsMoE2eC;j0d_kV1L z?4;G2U1I(Rr{)!?Oa+;LtQK~@P8HplLe#Ygqu(P1wKiw>S;G8#IxDuU-org^a@H8l z8>r3QCAPfyeyRAeBm`BxVBMeX~PjHMDXgjavO`7h#3VKZTe z?=oddI)OOOF&7!MYI3LcHd|;>Fx8@lUa_+X+}ZN+#oRzl9jjtT5MTwKqYUr@NK!ik zVO9c6lk754?l@~#Z~h3G9jMv7$TiHt3tnThRw8Jcz=BX2X2^p8ta_>a*ol`xc@J1- zPA-;BO~glpbc8%4Qt!zQygpNGy!0x);@EkPwxzeK@(=_JCczHPn5M)E&A7a)8RbpE zLkSN!J!wn}+2{bZUdwU|HLFgEMDTmcVn}UNyb~#*of_p9AbxVm<9peZbht#BalGpa zcc;cYh&es+3S9IXXg;{eTfKx_iGvUXOjQ0A0>1bCe?q{A_>5`=tEWybs|i<^E)FJtMPsQE02~gu#ylMt(R3*vGr!FP7=*_A-$SKuX`wp#T9T^DX z1x9$yZ8-BW_Du?8;9sYPik=-?jZV^;B`!HCrYAkO0{6v^S%?i$qD!0k!(JyIB86u#>K$ zCW(5!BOp)xP^(la7153fqMzS)v|I>A%cqqg>ATy}J(qSC!lO8kF;$?=+cxjz zpsw$NzOG*~k`(R{z=HksTne>+pOLN*tRFe=$TJ~=cXDp$Q+w$0`qTV2ndP*d@qaPG zo>r{t7y?teH2eQS#djuc)wPb#4?4Ihb15Enp4t+*b-mu!)l*-@SB5@L?Aukpnvg{I zdNscxma7Y-ZEog7#(8l=_}=dor{IImFhLIaLa;H}Sd_ImK%geMQy$F&T(6r+VEYGH zgt!jcQBN2!aMOF_20QDZ$>G>w4O-bO)o-2~#==2YrqLt&@^|0Mu|A-j+#Mo6xKGr} z!o6%gtr(DQ^WVAl-vcCI;cJP~B{jIG&ZBETGbrnYp#X}mU$UoO%|50F8h;qCG-lBx z7~hYx_%L(Qp?~%{nyY9a|ADb{A#Lg+VlZr+W7nGuW{OhyMv4$p=Is|&>y-+f3iD2Eb(-?@Z5+h)a5wdcj@ko}yGA==uDdb7Arv>b)ym3f>ATSSm0 z>13;;JAhqwQGW9*U3Kb-#mkMq2j|p$&L}ra;=VXH(O64T?!<^9PWG;ZMsrb?F!IA= z!p2Em%H>h7={}($m{o!xf(Fa~P>#e*{P) zyTebjg1jun@Je%hyt`=Atj^cdAPlXe)oNcy-$y%&4r%;Iv1k};fqq|<1o?#;gM>B2 z!T0$b3=c=N?Uq7W?9S+A3-vo+ZZK43ig%hU)HP~U{Ce_T!}S(tjU&n4@0$^1dlq=7 zjRa~oE#4Vu6j3c=S~Xb3u~0N}TMbt2s~bxNaeoD*s1R^vSxF4mtBO@#<9mhH-glqv@& zDbL*Q*-&4Ul`ji17l{UNmJEFDGQoK0I9B~F{mM+l9!enunhzsSXjz2YxmiTdoIKsX z^ju;+on2zeZDdzXq0Ps*OL)Cw~lNIsnggguaaG_Hx)2c*_R^&yZ|a!`A)NeetF)tC z(-u`Sgx#=IdY)Yzy&FFI3O@b#oaM9}FxBJpoO~y6w1lN%?U?v5xS!L^KNu>iH||a} z!0f-z`8CClR;hn!vPB(Z#(5eMDKP<%NG$8{ zf#cwrthH#VX9X2OA#S*2>r^94?nJRl`dhm2a zG_A;HK}`cSIgbqft~MAe)Ld@*QsJhAInD>Jt0RIDuHs9ogQ5Twwb>xKhFIJXUxF}~ z#CT{A0_gD>0YsCL7F>gDa51St{Z73c>tMk{NWhOTGeSkGMU$io3d7$ z8jAq($X$>Q>OU2*R!6~8zP_YRJQL{kMLqJk8bkHj$CTbQpR*TTn0`(wgk=C79_AiH zf1kvt#psKG<*e;6P^*$~oVS2m9z+ws)nMQUBul@lVz$h~+UOXNs7Mm2>DT-wE11bm z<0`x8Y@x~dsApvZIUN>WfWyHTefE9OFVhaq{u@2)>%Y>&{+Vy!`+f#tx796Mi;44% znyItR+7)F7qa=yzh`zUT-YPfc-qHmyF7ZOi+Q7N7F?P!XAjHd}j;(`-xoO3ABq%80 zH6D!w6yze4LHRk_Z#^73w5a*n6s=vVssyzXdfYfQq3xT4Y1;*f8{ev13~>I?v1N4jY_GrjSnqy z`P8TLNaDiwXRBWIo&Ep!b9R*CTMP51cVpeMi+iGmonZc}ZimfQm6!%60hhO8U+qm{ zV`Kw&z;SA%R9an^T(M`|yQ99EM$Zb1cU?rBUEROn~I2}nXF1xgeG#Lb|H ze%BF5kDyusRT7DI;*p$pFN(%J%0IBR&9cOP^1_4)bu+BJj~>wgm()kD^rn1hssxzC zC=Gvvl8@fudfo8^kY@g;d;6O7R^Pl|K|0Dm7*}(3(YpVdqc@Q16`8($j0bl(t82^r z<{rrPnc*{cfT^=yez%it&8N^bz0uwtOV&%?R+!@R2bKP)MN^X@|;r$E~69|l^1Nuj)4!-{Z5wd);q zy=3Udda~LpLhNP5u_orRc38p^btsN5Co8q(wCgAX-dza@xsG2nnXfTY^8D{9ovOQ~oEFgIoAj4r5#t2Oh z6PdUcnE%zmw-YI}pmLF92Z+10=zy9EJVS4cx|}hB?Xy&b?0Fax>Ro4tQoT(8s!x-3 zkhaW%Rp7OjQ9I^!0^7KMrV!yj`R8fcrmfso+3On$VEo?ihT}&=N*C2MN?fXD@?-lB z(>`4*E;61!p8T8&Cy2r`Fq5c2e>J4SH3`+*|30Dm8A|__kT>YW7AF3YibD`Sh5VdM z`#>V6J46N;SHRpyIu&^7A!ol=B%eOEtBGOlWJ+ocEg>-5?8U~3AQWPaB#jLBAoVe9U5#YzMYFW zquCHi)NGE;;tO2GT&8*f!7_s(V*Z(iyT>Vf$hQf~5C|dq?wT>3_aP)tut1eeE2tO> z!W3%QUycoTMj?v2pA(6-{mDqL`*HkPxcEq|L^LR;b|QS_S2G*5t0g2Jy#3-}9IG46 zmLU-u`{g7I?g+T|wS3C{?KD=*xXuYXOj*RxnMZ`GcZ`NVseUEe1Dfj4=6WjB3+P5x zW&?S3-78WYAix5Y;O1xF7>e33rO!v6-M>U$bLL(8#-l7YgHd-(SG^`9vSS}I+COr@ zqG5naZv!PJaBo?w5SssoQ2gl>@$$vS2?v-jH!O@EJ`u=M^F6nAAJfZ$`VPOpsAHF{ z1o}_?tatu3i9-{dtMTW)1hou{)Y}RDMWt274qY8pInQA95Q`ohHBSnBC^xu!wf3P! z%2OHQ7t+9-eKz{reM0Vewgy?r;$M8}E$X{6t}-(J;L2x5^+<_|Ay8T>WRwSSqXDcK zhOiFu<90LOWos6_TFg%^jeWVMQQA#}r&hR~UG3du zpT`MxP$y*aM7Se)XT6;a<)_g36YJJCl2LQdfRB4I z4K!xAuA_&n&Jp%EZ`>)V&qGm~zp&U|QwYe%I)TdCAL%tgvSRUaHK1iT7_^L0MBDPS z&H+4dt^w3j4MCdS?t_^(>pJC^vi(3aH!NGYHbI zKNLOOGT5DemMr`V&zcJ>GDFPzG_C4~*8MLUqL)Xa3~{}i&RFK0_s)I%B8W{x=ANv@ zDboK9qK*G4L>p@abwz|+OD&{Uy$HFZ4wI}$KWpuzyI9;&WV%utn?)=^i>LB{?ydxw z(Nty7hkP4CekCOrcDI+sKQiP3Y2V%|LZ9^u0FpN1-3$50WOdkH55a z6#t-UsPFz??*B_gvUH9}U538XQ&%f-L;FVfaD)3`pA?96 zj}Hb()UT&)E9i;-lr-SfnKV%Ebzz{X5Gii_?au!f~XpwR#GfD;KGYCjaijsRCROlsDRg9ESoj7{r7nOmOpKX5cf ztg1`v4DE}P#pO$+~wD8r6)$X6Q*O-|Wcux{Ads-fA$ByFvI#mm_f0Upw zifb)c=`<1UrB7Xwg)kO1C{}}LK&agDc>Fh2f?0n(jU1-juID`q&4;k)VZQY`7e@U! z#=0*xJ$&|Ylc0Gpe63^X7k0Y_9zWRaU%{hgwEm9M-d}1wKcSD2GWvOxZ7^*uf<2X7 zQh`5ca-Q86@(h^tPuL6EKuf#KDD5V7MfiaXWvxEIK$G8^bg*3!HAOjqBq2nxl7A7G z*SM^^DU@XdVZBo2Par_|O7rS5`4oR}MEgeTJI?tSJUoUY2VI2PmOh64kxQEXLoOLB zhCMs`vjyibX&b!N_zdj*>`OL09gAMo=`t(Z1)z4;ZlZKLGs+3{%kxWyM*r+JLJ`{| zqGLJv8TlY+A2tb9rdWm1Ds3Tr`9bmER*UJRch0T2a+u;M`8Oi z9%F3)J=9USJ;CjVRu`UJyjpwcgYO`S9vydoXm9_(?idbY5<136VIUg*pz3E47v%P6 z5Tub(=6wn*W996XKdzS`VeZz+dCDLdON{0OBxf53gXAz`rX904LqbYh2VMiU6<;0a zhQE_Mt61-P=tv}hW~yiGm2-qgvcmPwL9ToMTYyG=_QwzmLhIwV=apS4mV6tu+89}4 zVH3Bp*i&#<{uyc4k=j$JX0A5^vM)r6KmE>Vk zL#fyDSgSg#+$K0TSU_Tt2|4i{d8m$@BFtnWf99p^7l|>XM=xx1*On2#|9am)q!N%k zu_@Xyni$x?qzCylZ^>!?(cUYqF6YZMi|PVv8V}+B;=dR6k0!xLJGHAkpxW!7kP9TP zpM)Be(IH0qFAfHu1WQs+MNc%(J9#3Rwv8cGT-gpRfa4+N6TW!K2>{*O|cNBxJe$?@e*nmV8F)z0B_!;5Tm?ME%GpL%nJu8%#}60`2UVIw5(!o zSk-ZsO2-j)sE-B`Uix1Oyo^{%#R)J(OkR*wK_VuDE&nEB{!_-(ej1~`xEp3w@U|by zz!-=ONLkm)9O)`ZpQ~9FK~?%k6@nPdfZL}GxMhqlvHz@Ug5Y9F^%90<@W7s*E3W!s zzOmmArVqq_23=Sn&irh+gUH=q#i4&1K68gA$4X&kgJ_QG9)aF5PaeNO}IVMB!h=`ds|-fp30`lGb4rj!PmLn^?idC_%a?xw!n_=Qptf zKhg+iNw|kja%ItPOdr4Jx3l}n(!g1f{LPV=Wz9*RJflYgd0(cWir{w!G?0tyxA zMR_%3c@*;sbWnnFd}~(3Rnut)WoS3#HOjyAbbGI2)v)-@-2bqAK%Kg73 z1eMn$E@dlFn>KA~=eh>i!De~M(AjZT+5akxt0snYz%)u=cQ3N-2O+q*kw>x;>FNed zR@!qBv{U{Rk$Q(0^%$(?6QlZ23Fbtk!+(~@cA3Cftj|t2kz+Be+iDmK{QA7*f3=kY zRP(a~QGRLwS=`tP2~A_0SV3o4POlAfGhyKikSXS-qd0AT)xiFpcWppgbF*W)vUXlq1I#nU!yb6ve$0m{JAOgF?2MyQnaxIb|#@4EcPh z=W3LTlorS8eLT}`iWO!3G^qKnbK}_IS`#9{=_VXu9lJj8tRPBH-5g&}IhnQ-Uq92+ zx|rc@?>YL8Jb#b0aEySH%=ETVZVMwxXcuwROTEn`vlOqcs$uO8t*$KNn<_!`_F8RF z{}J|?N74OLQd?0AGswNvBVC-=(ZPD{a;u(*3Nn=#0Y{>S4@*y_zc0!`$7LP5(uB}y zs#2eB_AN!vH>B^QCB$(exdEkT#x)~03wAwp)0Q#P;ajL*tf5lAu^l+8t@XkOU;pjX zlV?Ts6;`DK6hcaL@P$ID^MV>08|3-D^{Nkr1>*-R`$-F*UU}&1s69!El6t$+c91e( zJLf_e!h{cPp|3uQdtEI~M^T{uY=vY2>o`c%ay)TGDb?>f)H4bX_7Xt7q=F%4ee221 zFz%ewc^B0|kY@()i)w_Vh3llf=&J*=fdy^@)u3X;40n(UoV>rm#Y#tK#p5F7m96iI z3ewmv_~WnnT=1m(BQ-4T5|<0zT6a{j;ICEoEyqSk43%Vil@dSBbwx>Lo}jNpat=sW z#O_xBbAbNhmM-sRqWL;+(=9)4hIY7Qdq{ zw~fj1_HL5r?ZxDK1-+lE59#NK9Vj9CI2o2Xjtc=i{6kZ{Cy^QV`x+j_DjoT zrDZDF9N~MFJ(y%pDqQb7QC+0@RfUu*B_>b)Wv;=6vqI$++;8MXD<|CStd`0roTvBe zic4+6S%$m__L80FS>MmUBH6i7Hpp}JmMq?N4f=jVTwKH=V}DT#pQG6Knxf%Fr7@or z++vzFG}=RU>p$7Tpq2~!u-6QARu%{gAIb5Zbo(p!zA;A0yp)IRPm3`oxGwBt65xkxrTiq%SGk~ z(Bzlj1CV6sfVRm$`|Gu4!pp^2Y!H<0*B!DJuSA?Rzc!T%^!cJ1tJEa*4^Vz-Int_= zAR$vQNc%v~km*J?ynP6M&OYSm*H1;dBljHb7w;JdI}y&j->jH13G8&T8e1VD&u?PJ zwh))1tW`yN=n7;(ptFEc!zAGZm@0OnnJ5RNEf9Dc$cDX|iD%Q_F{XQ==I2xOf3|8q z0275iF>}MDp_y!Lv6VsT+XgN8UjiE6kOtNis9A>VSd?_!Pd>Rd#~%0=Dnk7==e>?|y<$^AaIa=P#?&HG4@!}nX2FcE4Rf1LwlMB0Ov6L@ z?K(+)7AoVIs@9IFM}bRDY+?SfK>T=da{Pp4@}o;VpEqn6JTa}Un3pZypO1wj_0d6> ztl#S^-g7xFx1jN;ZzhVf4GGKv!UHx&6%ovrzQkkIVTw#!>%cwK|8Wnr8_$nZb|=FK zxm!EQ@8sIa)y8!58hLt}ThQz6>8r(dxO<6gVNnZ{Uihb#&!Xx&L&&@E98d)q)TIV~ z90MOF6Ssm4%zOEsM3$t`a@QQZGC`yQrFXF=Lb1=pIc+So8rD=>m5BxGh z%T1Fq&LQ6JB%zg-4NUq~YY!hNI96hn@A&+KBY9G1*ufk`4Mm0n43+_lBGy);z3Q_V z!*W6Xggh&aK0MK630-3Q>iXEMz|)$zFwERXreMkQ>nL+9%icq&2m0W5eO{kB3r1>y zA-Vp=koMBwGqolBx&AK;aa&R-OEbcJ)WC&km9rs+M7XWe1(d=4*~+S!@yO8DYn37J z_trtN-u<>|gv!_dL*>(qh3d@UG`7EW*p*H zFUU@Ssx4Jm2aRmM96}ddI-{VgH6HS0 zZ0)Z@$2Ui?n_-FCRWfUFsvw&4t_pkvJXauXI}N2(1*zNh6*>XqH>^A+j+A@%cn|Q`ChrnN~G^~yli;}!AbuIx04Pc-ANX!ff3W`v;wv>%L33|YI0R57FU|Zrp>S&m{F!GQOp(8D zB03$Hwq6xw(I1x-0WS_^KE4XuOJpPzDFVH{aJ%52AJrHYk+th5H#ww{l^!p+uR%h5kbAH=N zzhclparaS0p!czSZ7-j%Q`WgE#R(GIbDOK8WrF80^>cnj#8fN6O4dt?z)TFlj8aSC z(#$iS(9@4i_Ckf)%7*4dfWx7Qa4;u1{m5bIRY4E^sY}zo;hwx!aIdL7i(;RGTzj4` zUXNkY=Jm7M0VRf^oG{$=A4AA1GXw>geah9Z>q}e=q%e}S2XVL0&baU{tOvzd3U3nZ zoKWo8Z9-1!G{x<#j-0`|=q5lwWBcd{tE2Dwme5fPQJE<_lGHijHyD>brh>VYx-TaH zWb8=!ON$L1J0QyjlS`0Ej$wjFva;ve33;DX5NGxntTRq7U6lBQ>&F;|_${01A}_rj zHuFbphdeHYlEip`2^j9(BLZLD4YQQ`qP?9C*rE;O&15?$Nq+rI$MSCV;aK zWne^4T#wa6zYjt8do8;LPlVO0It1-#(&~o%0kpw`r!9nzTFxU874yZRaakidf}mY2 zG|tim;pn2q1c*?Mb(u}MRmhhsdBccxGID&PqFvT~B}YTHpuSI^mj$h5;86%bA3aZL zh*CnHa%E0XV3u}3Lq-R{=QViv2tV+m6w^?r)b}P8l=p7~KfT*Dn1qVB`}%VLM_9;v zyQ0;(QL&O>+!Bbk2C%WRK{a3`eF4lrI6$6U9IWgd!>On`Fy5J& z%cZ?K>0Om{Xh+1|m!CBqf(KXY=cI7BEQMyw!)**l`?)el=3OE%1`+zedTBF!#GV5H z4e-R5rlF^HvMi00yT+YbFJ$w?TtB#OyHBG}XVDG*GLWieNBT@6|g3A zZVZUi&^ey+RrY!qLLD7h!r9i-$4zLQ+xHqdZBHW$U2|KReug)wJh%vVyzt-y!%RU7 z1~-FDRGWs1vuyj&c>H_aS>AU_3`)^m4JZX*PqOsxo>;{Js)e){GT!2{W1d* z#NKB`NaFFn(h!{$``FP_GYt5JnCi_TKM@!}4vJ6}K)M0@(@PD_n^wKvwR+Rgjo<E zg;FihN=UJ|%Bj7I=ugkQdL979_P)e*j(HnMLAcZ*I~bxL4EjoUS?!BGzr+^4bk~BxGqtY-uRjZ|v1h^M*Lx zB#RH^<;UJO%yXa~k{0kt0`Nk2<+lUpSl1u{FI8AVDv}rbBoQeIMpPooT zXdlm%v)%@dWn{!zn|FezOYeoqqPW(QSds;V(2#*#rPT8P&(@szBe=*d##tuP>T@k$ z(EX@tx&gYvl$`*2l((c7(s8+^bJ|_-m*pvb>p|EA*!ri@HpiU!Z3$ZHQu1P7BqGG< z7U);s0=srb@SnKqE1KHo7D70_GBs5y*jBa&?WQ>n1z-S!v7_Bc7J$iSNRVvUFuN-^ zP1&E`71B_Uj|-TUT&ZT8d}{+C&E2JurM{@S>&_BwMZULp({@4o4*CW|7m{Eq?4gB> zN8yC-p{Q{Lu>(-vON9sYpDmxtlDaZ4&A5}2Os~<^C~e=#uKXbTZ|lQSEOe9K;KsRbZM`gYT)_n*#(^;RmicKo z*am$mae=g8$&N(|KLU#Uw}?gW~Efsugc>P@z#IrTU7F zV^vb0qOI*F!3>&9-H_z(b!DiBJysRg5xUlOy$NJu8m`Qb-+Lb<1}vyuc;!>PZhM5P zigh>Y7`Ajmd`bkp<`Ka7&zZt1EPot9HLH6E>*jTE)Ks*H4|%fHX%;vo57xX(uEQd= z(9~JjTYh3ISqCyA(2lFLHd^Z|Svj*uml#?`}VlnweUB?U_uv$_Ze+szwW!Kg-T2Eu)UNP5Kx}PXA5Jg{?3Yzb`SxL!j z&((Qx4dnVsiLi6=ypu8cT1O=Ut7Og=xdZZS@KNQ9{O2HrZ~k-H34{QXP#UA#E&;Zi z{A_Z?cdfG+^cG)X_U`{o%;C!20hN2eiB!S&BA4eF-Hc!te#)4T+MWxH~^B z;N&Idt7mm`uo#-j3eL%;b8MS175MbV6hFAfv(|G;p8xQrrQl0_812m9OKq6TMsxNp z^-p5k9nL)h=D$wK;p5_5SmxtxAxkoVrl|fgjNd@BVgcXI3X0I8Yt5-nC@ldSDk*ez z>OnLq)#)FZ-gNIa@QcGPDG4$*8 zCkyRh)PE99v8S9xjn{gvyt-n^9x}`R8;AY?~_l4A$kiA;)18BOAX{M=qAV2E0A?B zpCR`D?MF_58hKkLr=sBMcOpEvFfX8`TkA5F8Cb&hfZ^fYHG%zgyM=y!mpWB%&9z>F z&i#*-aIel6nE7Xf@gn(e>0#;h(DxZ9qV-%x9up)?LO=g;cagKfP=tUYI%qIfuOLrZ z2M->;u=tJaJ)IP}1K7>YkA+>sunNn)%HItHH+dYh&5+-(U>i{$t_H^AM<$YRfwN{>?c1k$|!FpoSW?h4!f zY7jF%-izhjW&+z8qM@U*(y~cvJX}F%(+G4@kPeaMmZr&k)HHG~7X?Q2s zwFt-oSwK}0q!TYW3obVlwXqaF5i9vCIfEHC@?|+OwKdUmg zjQyGumL9nYm`QrNoWuf83aPs%-AwHV11YDVzBg`4p=_Ov1Z!xM78q#m4pPC1{8to|QeUmh3Z`u;y9I&)AM^oJ^8Bv*nR1-- z`Tk!0@qL|-@AJ(4T=#Wf>-&1&elf2W+M)m={$vDAIWpH$&~ak>KSn}>N$7%GqxO{SjS%!japaqZS_CrvSk_Wq23nvtoY~zS{G4aplGzH5~xv z{qh33ynt;3^2XarqH>iX(RrQY6VS6<Z)KP}sKCoRM(c=AH|? ziyHmxY?X+#=8sde(z;CI`=ebwFg0y6AC&dMpDrub_n)s!OeS_mKCf!ILUs?@?OtmY z0Xu(cHizT4=bKUe}KBH@Z+kR)oSY&KpN9q~-F6LUkp49f+GZYAX zk4yl^tpwI(=UP%+c@NKBTD3@R68atISDKM!6~P^)>7+#;d}X3EXB-r=d?90=fddw| zERmx%+#~g0vcB`^{8|?L(1fr)sS*Fkmh~R*ZfzSjDtfHxPV$1n=p$&q(cijA!nu0B zY4^SIe#O!s_W~Y_2T|r;dc!NJ8SVMbaj)z-_>gg&G~PPdco>0H_qFr$L`p1n*R3D+ z4;h%FYowyLl8giVyOaJU!wbCcUiXkB(BESJOzI&sYj(4pi6r*{5_{wgeNOlLVx99| zKmYly5Iv3+=h9S})4l=;_t-H5x4@QhllRR==VzXfsW{kL-RZEAJwJ)W4EQAws*pBh z`9c=B+c?WVQCI)6f@xyql-ztm3IbWK)3DKRec2FZyQm37tCFg6qUo zs3E3|*TE7}rcD7MevTK{U;FOCmCkyc@~__#&<20~)wy*YQ^s!IKe2zuYH9w`+ zPW|Jt!h6pw-^>U1J1q^;y%`WkPoV;@=I|n?AD6$AaoQaoJk^s5D-6+g#By)iQ!7lS zM@2>oH#EuSfPi~w7xWe2;c|1rZ%;%0;HC536yc}77oPPY==q0DFDWdFm-`p2+8x+v ze*4)7Dw+N3XAj96(LnKJpP2zAuWp!R(5?1sf3laq7xteyvPZ9Y={r|L>`nE z2t9^3v1|gV?%uU419_UJ8$YNl7V3b6-iWKyG(JO}Y*&M9)TRMgJ|_dH89LJ3k&R^J zXlIvO?Ri`ZyT5QcRQ^y6;Em+M#(@-7uVU)oBK%QcDn;AiTCULDH==IYf0OE-E&R|= zCcD4dpy)4KZKg}@U2GtFW1}T57{)0hG=Bn|M}_<=?ZbMSttCw=vAJI=Ei;(@*M1Z- z$NLBiAYb9KrDdO(cCs1QiyS3%pwi3%Ai_Bq$wO3J2EytwSY z|NRvqiX1&QNe?$JP;k~W@_#Aq8l3=X+8;*`9@fVArB|a>Ie>Kmpd(uyg&70O<;1;4 zJ+hONcoDmE;=@3F*que>12qg}$(IxuV#%%eXD>dfhyc#!44Q!E5$!FrJ~!Xfi-=nX zVwtOUoGZpZW%0gftn%NV0)omI`IId`W7(e9O(kv5Wf?4Jkhr1Kjnc>2{9UH2SHGVD zt`3M(#&Vd59|Z*sX4g<rj4ch&-^_N7$%;p1Mj*J@h`dQfg&u0JUAM zczlrqXS#wG;K3?#pp11a3R`x_%n1f3jNOP79;GWAZ4gJUCEMoUqtLpezpLb(qPxLopk@u_FDpl3_3a&t- zgzMWtN3MRULU+4N1sTLRn;$!GHp#QRjy`oQIz_8QSnQdt_=Kqxc09RI|O>44%xcfC@M}Lb|r}9tJ7J zboGAZ!I#fl#uT#2cS-F?k6#y{fFbd#LU)bKpkym-YtqiXSHIeSa0T~B&AkKoM-@FC zEA=>7aS6!?WaVR~4%T_{33)-6OyBp*CvGS0&*t}QGL3gQJ+YsQG+?tqrO>M45|p_Y z%l!cQN+^UJf+rBs82XRINu)ZSz4zlqoL6?pa)f@a5SD%cHn-n@!twV9+(~uTde!k& zF>FiO1CmJ0@|pWRlMlWl`*|dpSeN-r$lJ{s+}LN^>E6PXvd=ixNip!aCyQKsHMRvp zZsZe1V2P0KTjOUwTUgwP9pSQX;Kc&4 z52d5ppmjAPiCE{vQ*e+EM-sk_mr+>X6ju4<$@>c)IN^tK3n;&CXRaSQP+fS*fd7?Er>}2_}R|`-C@Y5FzpQWt4u~=?c_fJvTS+Z4~ z(3e|8_Bl@zwdx?BdCG*xI@NVdYIN%9a3(lm9}F;t6SAnWvQTGbBq1s+xP?MF^$e;8txw3QpV<_` z?9Qo5sXxly9RxR?lE#5C)qDYiu(3;eP8faaeqO3Gzu9l72~)a( zUA!@6#Zjl-)tmnkcRe$;(!SNZ@Uy)1iY4Via8}##iEB35X^hk9_ab|);~RVK@w%X? z92hEAR4y^^*EC!_QTknLj^38}^*&E@9NKdcj|#(M*j-0)%x9NLV3~Vhns^xzKwbD^h6Va61k}LS6*cw{uFZ3r=0Zipj;bS z>qN=d+?%ZDlDhszX;)T#0c%!<8&9i7#k0rdyUAg4%T|-GZJQsz-4G)#shd^S{9u;h zLV*39$UEX~WSq6w)mQM;vG5}GyW6Tqvw43SVeG*H#Zdmam;w{OzL^biX-g2XAv^u! zb5r5UzKC4Q7j;fQo%R~*1(Ts)h)pzza9!FS=5qZ)FS!r0SOb*B#+w){u8rt`9)QMp zvW7vT%lTM3y(;|S+3>USpmtG&qr$ON3IJCU$65!son0~3W3@n-p0r_wVT=BeQdfO^ z8I=`6t8^K{OqNzc{GYEs4ItLY6TQELEwlQuN>WWVRp-P4Kq>Og3FJF{^oDCHZSTfkS^vi=eRW4H(@4qE zYLGotb|$qP3-9{jx9%fK004z`sTpBl!l0E}TK#%Yso{Y~D;NH(`J;E!n?X&?b?SHH zw+a`@h@@h!2#5;efD&JAR2<{hEJR*tb5j0|@W#iC-p|Q1173%fd~fz|j>#JOs-8J; zDU*MM|8?CJoF>%cppnWnYGwW$0IN*emvQvcZnue*Um!M20Dcan$dFoeAhwTd4PF$5 zGUr)K-9f{B_!9 z_bmuk?EZ)uJ%=iJMdNjrSsq>pZfTrvMvqf$V(9J#ppLcaG|_4aS3UFHB}~J={rad+ zj70$tY?kMG*fbx`=)+zr`e_7SrPC2mW~o{MG*b_e zft>HiI66yif7bPI0*Y>bzUI-SkA}YKoS3W?ACunoY19zc)~j_bG$OM^N*l3l$8gb& z^Bigj9_O90z)nGM2C~k3$sb-mZK_fVj}VjN`$L2NR}nWv5}@xF6}p$LtB>$-FS8Y1 zA8P;8zutp;X~K42!RLXOysu2YpvQ>*GaaO^{VDT@n^uKdmQujb-VbwR?jqPu2 zxiM)JeyX%eUvrDM+ES?mnq7?_T-CTAI4@lH9NRGF#c}Wb89(3ejBEE)|GbAgXP2c^ z3iv@__mvoi6Po%O#uM7Fsl074e)tPsCgS+*YWsULfqPy3i24wQAw#IrRlX-Kj?; zE&ErsYJQoNv-Kz|>zFxZyvjlLb5RIuB8|58^;|$vje*GMPvPFFOc56c@S&)6X&-s8 z&8`1lxi!dQpJ$LoOBTm(Cok(%=E<&ci^~^nLGj1MI%Q#ueX3)Gy-G|&tY)p!iVk@u zFN5Xw5>woAsQwiJ_$r7Pl0fWU3lJJbiYGYUCa3wvg$nUl6V8@hbw*SdbjVp1FE9EXiV9T4*EmyhShrc=+ zMcvXZa7MtEE&rm>vJw!MYR&v|B2WTVDG16wlzvGn-KV=|Q%}UW;2Nvibe)btm#T!W zAIXI!`a7(K;98$+@BtHYB-f!I9#(3bRFIs)p3?pPYk<8t!f4=Sr{b1y_t_kE#4S{Q zO086L9IwHtbk74!J?Pl(pm9521+(;w+1TeajZa;(NDrja-8w*SW=;sSU>t%z75dA* z=->RRDWlDUdj(qDgX$4qI2UT9WMSpn47S@8EWPk039X?_6KhosYYBT-Sbimk8)#@h zzb+|QtxTELtaO6B{1Mgg({uWWIjHe+tL+^SHLbRLTN;dX8Rhc|t50%XF?RekV zLvKj}7$1~Hjj{L#IYSTnD%%DUn3XegDn5NEHhSmKn#S%adqYXMvw3504bBjwUQj^q zsDg47nJON#=}71s{H~hTo|eO9%tV{=AQomgR~?lvo<{IDiFhcSb(_BQ9Op%7#QH6b z?54f81DRpRCu+^c+-u+Qf^$w{iY`Cy_LMBy;|oANh>M7neBy_8C?)%xx z(SG%OvnImHP;IH{>T~1$bmv0Lh0Ci+BL8W0 zGnVCNMZ{Az=t_;MPtY?tn%D0kzsM#nvD=}wtnsF)>-R-j?H4wBe2B>@GH!V>FOI|` zkf)2PR9rr*TJ4*sa=M{5$F~{#@jyLL$4w~d#H1*p`3PgMut9KD!9LT7z47~{)^xG_ zKI+fy6W8<>vVT0=!4p)U%jo(fd2Ed*4KwJ{hTXw!*UDYyyxwxfjpmbGrC}0BXE_Ad zYFbLug0CfDU|ntA^7`el`bRn~8?EfM!cKp12=w^I?W!E5STI%~`rxXubw~uXy1*;c z-wufC0%a9~)F_qnzR_(wA}d700BPzSSc|Z|pA{CPwPq7N;?H0vJ<}s0McgLII9j!* zNJj*Y6881Irn*|0TTWhM!ihcc3CWZvI>{C;V~i(R_Obm03kr!{fSvj=^>SXTAeOSE#?N&D=+^IApUg;i&QHv zoIhvta=%%U%D4;UE(@>zH0U*Ci3&W*yVlkhglnu?9Fwa47jmu}dKIY@xPA#^f)`%I z)ddXj=hE5-J&)oTZ1y-VP&w1#Zjo@pX7mM^xM7Uh<7?)oRnV?e#bM~>aXb^UYa~tF zqq^>o&9RqU;|A~Ycz+m4`K>8g(P_O&w)pO4pQ5$O?&zpl*zBc^VW$f(`4%=iI9|7?CJ(&x*AthPBG`UoN#^N-F3pH=V@$|TT(5rROnf?a?Tgs zv-IOe$J=IgS$21}0RzVT5c(VGPtt8DU(a@^r8js+4|-L#zQjC4#f@zKD(l=+`hM;6 zey-Zh?>zpbEi3Y0WQG4Fv<*xmOzz2zwm=gDQ{#Vfl`m-0u}SuP zt4-C^rZfJATpqJ3nAWCL^OD;wo^rg@UHnM&x--M%&x=Omr?sP-LH@aWB0783Z*#xr zD*KE=G3>Rw+kI{9xv)HS$#b7iu9|duIme1frz3hD)<q)OR>=qx}lc$<_d2 z+!A#u=X>Z)^K{JF1Daa7i};;JPps)bSDJLL<&yirEcc{8v_PIiYb=td7x{#cix&!)RW)+HQKddMv5{0gc58;)+D6SJ*b4OLdq_68d?58o^mXCpa8Hp0U<3{ zEzDcfSnkXc8qcdg&yQb1UDn(UK0I)^x&?&5(8iiXf7Qo%Scn~`b@ksebS!j*qz>gU zle3x7s^@0nJXPEDSwlauVv>IAO$2Z+F5OihfZgHSGs%MLQPX4Z_^D|~&TNnsJe+gG z78rgqfzL1)__$1N!`_XOXg33Pq1%>r+ zh?wC8aB0G8@Y17uI-7UUmgwprm*CN$y8`oyO<%9OL2>;b5u3SX-n{X_E&Xgskg0e1 zeP=J+l*DbI7TzP(K>iWFgU2FfH?oZ|{w39i9O(qKlQaY(@-b~vc`lQOHS3AM_V%?F zl|_cD141I)7xj7-2C@?LsY3w7UA{o9_RU;+|8$d2`-_8zW)!g5kL-!TK$R#)eYJw%6#kWcFuRJM&!^(CAS~U| zy|dO-$CR{-V*914{YI1wuVz(fP`t-^hM=O|>pA%okr~NRBSDw4w2{1WYamtfwxO~K ztkomy;s&@h@Q0E)G~bbmmjwrII*Bc`$6wMB-f9{q9j z*dRa{mBrsb`sO5bmA#!6dYQ6%5M`kVoDR3mz#jixCbSA8XSn*81hXx&4#F#kYqz`< z{)b@^sAArROd;>hU~I^%W;cFEMFdY6WJ)VYiEzpFe0JaPfcwvO;O83)LRhLv+HdJE zF=t#~t&JTm_p#0X@Ge-ai4NYc)mAHXyCKNo@|zqgDbB3|Tc~bvHRN_vS?*0*y_;8S zuQDewP+9F#*W`6iW|UuI&XQs6(7j!7Z0E!l0?xFxp-QD&@coN!GaLw6gGe0V%T7gd zTPysyTyFPOr8Y0Unwe{=Z%28meL0W0W=T7uls{qx>Cy72eE}r&5Sl`bzxWZeR$+fH zhf*?L)fnS6JB~JyKJ=YqJYpv%bM&5o=_=bsTV}z~)vI~@VAi>r@fO0bCo=ov>EaX? z+o7YSr>t+(-_d7%qW1thoVtwp6<%K(G}EwtS6}-vdDoX1wKr&N<KG(?;5d2 zK&yxPBI81Dl!N@8XU;pxqDG6E@e3hIIKvUVGx6n4z zHxx}#gmM+JU&&^3soVQkc{xLm%6Cr|2%_3BE(R{q zQ^ya1fPOoNA-WvBWL!Y3@7mdW+o!hAaY~s8Xhsi67<_n=Al6Wwsbl-P(%OSy9bX_4 z7xplLb44VKSoo%y{Z(x9nviwaP$Y9Rnk`I!;)^)mfO&^ms=&&??w;x;= z`KwAAonn{$y_B7XdUArSzRKI(NaVnWgPP9_nh?S(d`D}bY2hi{?2c`||D4|)ut-vN zZK&OaJiDp-(rrio(o@g^8zZ9w1ncCoaU!a7H$@Pl3o)nID}$5`weCanPwX>3-V(s= z0d+5cwga+#Whxw|OetBaAoF7??TW3^&@tSYtiXXrzQ1*qard4x(MRTd+34}ECAaEd z-cf47_*RJRs9ZE@o(|isWcn3LZ;fE~BU9PNAQlFij>?a0-=8)HfJM;AqmoKY(z^l>fEOC5SC z>&N62H0qbyFT?5=boA&~=zvskm08GPzL6bOe^43x#c%jS8~fkU(>E&`S&RC928~jN z%N|gq1hLfh*jVD?8lh7!R8Re zti}Z(kG-uOKiR_be*G7$YEmA(R)Whn;WVE8&0uq4!C14833Uv4aZf`%eFm4;Kj@g+O2cPFxB4 z^_emgQV~UPNxxGi4Q+1B7R1L4yydmJdGY?1$l52*(DgLr8@O}nTq*ZZ2XmJmi-eCzVAyAg&iKNZwWN&3QJnIZ%3bZ% zr457Nk>HQ96#6K{HBRE@V0ysvHszJh#@ZpspDN_YM8LXlP=+lId>}n7enk zu+3|qxgB3)B`HwtPY&cKN&iQ#L7t$r=S)NCioFlZt(}FbntcM@z6QE@D*AW?RuIWP z9!{oH@&l1on5}gumZGlqzPx@>7w9e_Fe*e3~!%<)=Yd%=T zzS=TY(f>i)x&mWqk4PDP@k?l>o67`w(1PJ{C2-(zU*+WqVdWA1klOLPj80R@UeECU z{0!ie#eIkPb_9A~F__-0!T6@4T4L}w9)91iN$gIzY>5*g`{KMv0=cj8+VuX04d(*B zkkc-NVhLH;7?am@<3P*Q1?_%8=u*kuBinylN`>{l>t(50y`Y0dT;%>6dhP!?3{cCNK)zl|xEjkP_@V;ItukEfSmwXxn ze(LJ4a2_B&(t@j_2%(sEQ`lj>F&Bw-8f+k3N9gU1)1j4;3O#|zxuviz15U@M!h3l2 z#C?-IrMzmtJxg@vjwqaB8#VC-17NX4rjn&FJCS<)jJ>g_df^(i z!rYy4Dv~~njKMShL=l{?Xn~=O&<8)_11sgGdcB|n^6KM$fdCV?>OKH?=d≪ZSMo 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

W>1fCjlf>J5;-Y#i&yZNMR>j!jh-pJ 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 z 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 z zMsLxWttfF`&EBqhx!TxI3+!WL?fJp+eETSycqS z6VdD(gjwD!%suTLwi$(FtpqD4WW}F#9`VquYLPI8Kn{+R3W?7@_(pQVj|!L0`>eg9 z1u1d;Tlh8Mfe{O5;pvK|Z_?>O_c_{&$iX4U<&wLNr-(%6_9hI&f&!Mb1i&XT<*k(Fdx>*;@zjkrmY{Q?#fC1M9QmTw}4XLIp`LqqMfB0NC>(- zHI}dP^eX4L(pz#B&zx2MxAp60p!UCV?!&8<_30msnU#ZIp;b0thKaHgwANQS5P_YK z1i#8U@lkc1%y*E^KaOiVdfRD78v4~v#p|(*9h2d1XIwv@Tp@+Xq3DmF-f7kHd(jYa zq#H&i=J3+dqGos$Nd+rma2F^`(Yt^&&$I8-qmWu%T)V^z9$=ATHp2X-^mSEmD!?xSx(wN4d0U;Sw4axg+^Q^u`+pKdg^>9ksQ z>+n{5J=KfiwB#tj*N^=9dKb7{e@egT^Exp+)!Sx<{0^L1T+BD59ElnQIL+Sl0fe&v z*{XERnzf_0X?c9@sMuWxk@}nKp@V|O^E%3Z3NLJ54H*Z;%3>#A=!@dzjtAJDy&Oaw z?+==?#vpj&uiM|M)91+fndDCBy}~N2LHb?RpAiXSNT!5Hv0H~a1oytig-Fhb4|C>= z`3_QB*VwGtkCTw07a2bNdU~8zretulb9Lo#NkK%!q#)^FE8%WDS~)e5V3}#O=b2{} zEcMKr*@=|nv6w7O$98@Doqnl?BAT|T#tulYpdMxPqp#;+6u3x<` zDK+WyL0d%!zhVfJRn-ykb*iKfE!>+i9~iS6vn`EM<4wSrPoQy~Rw=tkycm3WdlzqJ z_?v!pekqcC$rp8AIQhfc@N@e-Z}g%Jbg$z!eY@bG6%8%_KSQPvNjKq>L6t%%QX$*% zb-{&CQ7%ckUpbiZue;}xDBg~ZV^yy?zkN+kmk zQ?NOTGvY-0@RK;*jwDiDtdtCSt1UhXN%*U&RU@vIbl{5X0kVjKnkq8#%<)tdtg-K> zKVs*_n0)UbMqa9a;a!Zcg& z2EL!L34iITXKItgt_m9Vl}Df66wAl3>_e&LIoh+ zLv8LueT)9)_L!e{rX{BWQ1qpj4K@Nv{ioj9uHSiszun%R75uxf@soAn!s;j!c~P~W z(C%8U%1(~f9Q)sr41h|n|5?5xv+vSu50AXhP>g_nDwF_ek@~^}H0LGWZ6k1`2hCso zEO|ZY*n3&|A9G6xGdAs)WN&}#hSpf|!M?!n$UuK1aIVZfdkVFTId~K4TV<64(H!v; z(NcC-#aCzSFSL-odzod9z7yt{PhF XxIS3qHa!Y(2>e!k78K04XNxBlt_>PUA! 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 z zOq9zDrd%Ue?+x;Q#oQ6(KfgXM5=})kE~0HB@1Tds-@MM|v`;#P925sX_3WsM9_#h#5{@c_L32}!#ihhx_=MJ83EOT_O zB$ztyJy94NXIk}?KgS~e+afB;Z{sQLL+SfIDpMQe(V7A;l1!A=#%0p(@JFr_c=;jq zOA{F2P4>+l@gB1_BGVYr@_ri9Ewi)Y;7yf+oYIbQk}(w_z8ELz$S(ZM@uxmAs&cFB z$85u%mOMgCTN7;}`yVU=10WHoBsWh4c58R)o5_y$P2R}kx^fu$rC;mloHa{~q~j^& zJlISRQq0U9Qw3tzs?{DgiMjBh)_`oHcjrk87=+BP=iHYDO!fRcIvSmFQlk3%H%flL zmu=00Qrw5c$BwQe*VJ#w{f#*N!MPHec=zzAs+5zh(G`5Mb?q}4(ErbI)2vD<%*o(cdCNk}Fp3CA@a}sOHY^OT)Y*^-(K$qB{p4TOS+)zI@`sDgX?}mM;v0cw+ zMt8JTVKBL)z5@b?3;dTnrnSM%1!vi!gc?`SdsV-zWFljPD?X9|LpzF2NxQMbA>~-| zg^$kZ`cqBk=K2e#)e=*k;& z`&E7%9~X7RsY|AG`^m`uAMFM=0Iq{@Q394E0jKcr@&zHzGq&$u%kjY7qN@mMAo>CR z>0(z^a)?pbY~V3*-30QhCL4jbzZ;|nx%;^hP}xC%(($VLd_I#f4wyMi|H$oIed&&c z`D03%=D--^kn z+ZQYFWiyB5;WSFLDj9>^=kyU~K!_?hw0T%UjQCgwrJ$q?ky}=Ulva{-5Cen7XQ}&J z4DmJEL%6e8JcIkfzmkYz9Sos=2Cqwj!=;Hkt~LgQK(9;w*{uE>^$4K?>AHYSB?n3m zqaMwDbH~vxw6F_QAQcgT|C|KOKH%H?^x#~CO0UDW1mMS^1Fk>JIR~hy}c;0m6--UJ<=@p+I`;EMA;OusL;zxld!FPtU9hld;$@ zwWr7+-JuQ;?75EkXIFw_B*35=KNcIqjaKI0NTlReR`UEFx@T9pdDgHH-f7-0gd9j^ zxp4aUoC5#0DaNU?k2lcTE4FRToq3KBqFR&)G9_Eld7}-f9#cjK<#hR ze{966s4m)Vr(TQm0OrPW8pF%O!m{*Rx52XL!~gW#Y|sxxeyBJ`XtJ?Lso&TE=DyKK zDQURj%iedwAa3XB`acnZvIZan?VVdF{uGxt*g@sT{NMg$F@Uhqk9T%Qz+meCje5fF zsi+~&0r*g-xh&Br1&34sDC<^y_194TuLCI)!e8d9@&EjB0Lt;e4GJmRKWXlcx=`4* zllEd^|EQ}uTqT%S&i@k}%m51iE6CH}Tq~sEtxI)4r_;KpC^1#IP~g0)Ws-?GWJw00 zh&cX--2bTnm0`fpOSG)03<+>uw3WnAkgYxOQTrx+MAsD}YG+(xai!xc^-ifV_|efto+{qNmgtJ1od@$o=-8 z00i?uf2ZG_AbdD0t}6cSx~eALI+SWqJ{#lV>;C}x5YBsMvC5v)cW&FTC{3w&I2Fg<=JfP=abrHc~YlcGmSrdH{`&s ztAO0%GqX%5GK)&0n#Yg-=-RWo6Wfn1ICz>@&bq4gBOb;#?ew(b-6*I(5IOz3uhW{~ zbg~KF1yWmKEGh3f;4iP&v(z!!NMM;vOh$&5RlSVchfU2SUzh0rQ2yaQu_w)AI5qyJ zW}!cM`nRv;*VIP~+fs$JT`wyFx+oX<6;FeXYTqw9e#|7FSnKRHoOzd3Y~QiZ!2+oPFLHiRZ~bz@ffSO@+`Z_f9(r@p?hK4yo89uLI8vrEZkWrsGLgX;>#E}P+<}$R?e4Hu zI%fQh3j56V^fOkYx5Ytg9dF6EztBFoPU4jj=o=i)cA=f^6=&$v$yL5e>h^D*9(0Mp zS4x~-LLdM5+Y}$+p`lE_u={B>5UVV9u`$f6`rmE_yv_`2{d;F+Z{X~^kLWs0QV(xk z(06#A;<<{szB?JzXC(!aDx;M6pgyuB?}6L8RNHm(3*WCeoN^i^GWD2_Oc)$gJRQEU z?c$nx^jVm#{=(o&*;0bndV_C*FmUgK8B?I)y<-l0o@Z&j60=V`2RRvgkdrSj2-9fJ zo#34AAYZce9%x-fFf(i@9UFUQ1=ZipT`rg+Sa8kYetDZ!N5fe}* z@ApVX^YdW39Dm4c+);T3?=#Ekh`6Iv=dB?7R|d*Dqrd2=fG0Gx`%-HB9Q(LffuMSx zz;BNl8%6)RII?MRveDDNRS(yiFg5xGWn5nVLj7UlF0tt%ic$@Rc-pIW8N5L0KtL5} zl(j#R;UXqZHLC{+#+UU9(b%oW6+Z{5%`jKrBh5yp-{`Kqo?DVimeiN@S;M}FkWUBa4UZD@= z2$2%z;!gW!mGuEkv9gM&aG*M79Lzk&*mZp^*i}7;W2)6G&l>O9wJ=BAR1srRZ5kz$ z@KzH^*!L2}p{>WIOKXcWsK=&Cbx?;2OA#tk>2+FSl3-=Ax!p4hkC)pam^%VLAldd&&53&P)A2Vmx9hyDX=WS^iz#+{ zty694Rxm`1-(t;>vCKa@&~iWRV3kpAj%5M!k8iVjpVj1?O% z0(#bDpv@50m|u!0j=Y)5v$_V4wc?aP|7%f6q3#7qp)sNpbd&2vp5rVj{VctDOQdo? zPCEIwO_R3?z1M+mxqM4zn+M{rfHLlMb-|B+iUebXm zA{Yo8Mj);LdLCq#2swKgq+1D8P}lo@F_SUEF1ttld(yl8!!F7ZNJd6iO{!PId-%W$ z7WWfPvsLK=XnZG@U;*-zQ^h<)llppyDOMeEW!?3Tw*e@@RdPtW0;=Ib85D8(HOPqM z4ub|HsEJ>;a~eGLn?KHEym7JSEI%?aOoFpNICp#5PQn_&(U&mo>g~U@+8Z6h{Ie1| z>$k?m!SofneAar#*Unlx-x~(j8gIag$dZqX84xUg+xU_4I?4uQE`tnE*OrFr*+8w^ z>)w;^K3A_FOG#QOxIc3-nzXWzGrr-1Z3_O739Z^>d&uRuc*rfBaWQ64G|}@e>;ATe zBFJ_W5r*(+RzUC@7)6m54p)886c8D0!of=nsWqY#JL$t^`nkx!*<9g%@o*~4OO^OY z3cf0aXnF=;RaB#v1bcHl+Z)5X#Md+5wNMjS-*6!4%-y%C5zDXP1^oY@Z-WS0msG!f ztdfhgHAZjMi?48=)FEr*;>x@1wbK>P?*mnP+sqU zNo)l~e6BA%9{RbryG#H3=_6Kl`NGOrx$MSH9`T)+m81FgM9kC9`Jl(w(K3077yy*W z2n)?;o?S#7ywUu8-*mhVOW7pYmzrtR(cUw zY}@r$=ZO5?OFl_Tf1_&GRAa;tG%qq{ z47)n)swv1w47U@Fj=_8vfNDN4r9>(%W2|0R&aD`*1?HQfp}uzSf0)bt8Pu}1{8)wN zVBhKF@6oM?)_o@XLQBAy(Zp6TAA`D4v4J@2{L<#GH}tcW3uw z^$mxHn~mioV%u>qRZ`b^7PBPTLGVcP@+y0MF1dn~s(I8~_Yk_<&#d`)AS_4T@s1p~ zGtMUCB05k$;%=wdlSO%Vdw%L|yFlBVC?9pu<@8h?Mn=x-J&*|+dKpB_3kQo;wA=YC zl?NWTct^GBh)(JknqhpY7w>11B>G4%9Rqf6(t4TTz~s*v*|2k)N8fjdm5D}VfTF|$ za){uP{95i^Bz~_g=D2AiQk&XLbEXB{_oMil1{bOHVxiGT1bBT#Wfm^;v{)iO#jO-pE;;94KxETr=CTkifRy^$dR~)2A?Q@3m|t=jy>31Y9H@5dPlazw0CKSFZMnH zm-hUP>7AC0RK!Cw?r2 z&5XP3INnoL{Ua9sL?v#Jl+8}T%^$ggCl3k$MkzNscd^Ojtf_Q0xY@cF493?Fw{!Xh z?IQ70^&%qv{50WTxy4-$pcifvHYizdbOtsp#aM_t?)pW7jgnUP8;?VapOkA9eyE^3 zf714QCGsF!DTHz^@_3M#jDJ}(Xbr_&BZpjGO@u*xL|X`5m3k#qLW0;1aFmgGp|*hZ6WRLZN@gktQ0h9S5J<SLGL)rU| z+SILee17#uHB-O;8E((5Gm_iqwDnBHSmVdF+YFB2pa((}fx7fMlSmQJc7Ugm9*0i8 zv@3CJkICPiSQe!d<_8_r^P?j>L+@x95xvLu+sPr9_%mxlVXrM-f5|xWZ5jxbLvZLF ze$J@z)mLG2TSoD8CnD82R8nB1nseItE*2v7mvw3B5 z`bvS#IjopVE24}x*_TG?q0J+manXMqe16nv-q~qb{FYH1(UW>NKjX3to-$z1tjb}? z9rrZy*Z^$oir8^+xv+s|1`YPb8AomTx@sZYo$c+(6Cqd7#TkSW_o6CEC6RUkD7I@b z$cxjLvt4dx_2mq}zrD^q{)11t84qwV*-xJUQTbpsK0uEqG?S^M$Ot3%LCR z?anC^+;TebQosE93R0o@MAeyabkIDu^fNt3Dwfmmi&zmoZCaD3Acbs|XAZL zGb_mAa>2Z^&YSgFe^NmOEd8JD({>_WiA9D*r9^O=`91$d+xN2kSHit~P^1pxTbT_x zzwtC~u11M68}JNZgI$u?LkZjF)U{wgykM5F=@kL77BhbFpz7;qXPkxg8P-Me7Ff1` zYb*MMgT~T(qy_8v5=V5_@%hZswQ3>Az36V0{6xHoW@f*jZA~&->?{(DfV<$YRxG-9 zk_ppOh@hG64TmtF%%`85PdGE%j;zAKqey3`7Cy@_aez6moeEq`Jq^j~bg1J7dS=r_|<5)`?()@6L`MJ|>gX{O5e6DagS8|Mn zm9UX8CEUSD@O*uH_j$}c|Jj3w&STBwv^C_BCm-S3tg_r(=4>cqX|PSxO%0jpyeh}o za=E>$&ESS<(a5=X%{)xTlP+Uz zbb?2(*b{CK{gn!OBUr&r@c6TKKyUy3)7Vk+w(r3D%-%M8R05WlXHbX(v-a5o)rGp2 zvDK(pFaFDZ1`TZwPGo#p?Z&q_cz2nZ1>S$LtQmZmgx@|(K<2;3-F+C!IxZaWeo^qN zd$>-vTsx@Gk8W2RZ#-GL5cfzWb;-&m@2JR(&rk)HYXH;sMD8kn{|oYhFi}Q@hOkv^ zVy6jSUiG^>T2Y|I)46(ONv6qLUT?;w(|2M^PxxXBS-_er)9=?f97%2nJwaNxNp~-U zAl69(P?$GB%u(vM5-)Wczg3#O`-wBLTYnxn(Zu6~Y`FJupC+{?sP9@(A4as7s7ikG zbLtHbL90Gnu$pS>%c9z~TA1c$e-d`wk*b5Ydi>*u#{7v4GHRYl5fmg7Ck~vU^BJF#kd=NoLeN<#BKR(!CF_IdVuD5AA2OF0y5i^4s79lon7?SodxS@!OKZY5lNYCk_FL8W1Sy2DpV_25~1$dT@iI8EfNA=}4iGUP;# zbY{{OZ}+X_#~*LZ3h6Ellp7>6P4k{O+}GqEWiGkeCx?d?Hhs(-zuQ|@$R*W`v$1X)1OXK z9%at#TT{8&WM~PV&>eVvNTrNS2=tb7RCJsR8WG9fTMdnFaQIjm#zY-Czbnh@;S6@} zPBM>IU6_5Q48&9upev<2NY42VbqO36r4>yZ0yyQPGv#tCXkZ@AuU=FbmC1&n= zRpz+xhdQY&jdG=DyZNh&Oh5ks#n0?Xx*=)l=s(zAv^CLf_6v@$vt)W3$UM+Mn#;_J1VElILxm}=?$uxxLguaEBb1MMnY{qlFT9lH)Pdz zderk@CEIHYzzkFpiKp zkEHL>K~d2_ba%CcJT$DT&Pwej%i>aI0FyW=MBK zrLZ>j!cjdLy{PKuiq{#`y1BNmMHfF|?;NbFh~QO*mJ%Vj!SR_~Ibv9tp=lhtDybY8 zt>0r_R?`^4vNp4!xy^1BY;uOp9}2xa-V9QzcCnSGrh4F2r95=e(`#EL&$h|F&-Y_p zb=qlhEM~~6&31B5NWYtr??OiuD&=Ilu-Z{aV&=66r|C6Rny9q6=4Y0rUj;sT2BooTyVh{HeHD>rIG%Ht(Va~N{Mu6DmUgjt4!biC5J{g=bn zXsSx<-PNBiXN!4FU%$sMuo%aFzL*TgnG7-Ue@-Gu?2(Qnqx5>b`-fjsKl99bCwsVf zjVZ0D=GU)5*-0{|gYUl8P8Rai9SIF}(F=h#6gdt&^@pD}ai8Vj(S|Qp;bll%sYVtr zt;F$Do?AP=mwi1(f5|0rKO~(P(jFE0Ihxv45g6W_^X{Lxn1|5RhP}1<8d3F$}2g7Rm=} zF8#Lv1BNqdF>YImaa%gJ3_D!=MTUR;^0vVS&776+pZ0|5mK2vTjOMJ`yMo&RV3Q)1 z9s1!QZ!|r?ba${{mNh^rmWpiFeMzIvYFVSpCXDYF%T+nqw8<;0FPqP5gLX$`Zd;&3 z0ObtnmDEkPY+>TuqwwptB^cjpmJ8casbLJ$LZJtm1I!nHwkFF_|43J7#W&c?H|%5O z++0+jOT177)-ORX_^iK{*aqwBbR|^E@^dC`u6Y_A%Q#fmfNs~3QL+I zh90EaNQhpT$CGOVHP~_{I&Q934K(X>6IGHQy`G{I#IUaB_Q;ek-Ao=i6Ob+In;?7u&WAYPhdNcG-#j_ESH%$_sc^1`peL{&ss@u7o;_7zpcI=Hv`Fd7~5NyM>+CQOeHp#A&jE%_D*ic3$R>#-ubjVbSSlW6Es# z%8~e<`>_`9le9G&tnO))ta99-6C|~`T~zImujWfd3;i_Ae}4ZDUMa(JWr@x6=4a!C zW$2JDTXaFVjjn-ObDX9mwpgx&p61o1odpc8QNm~sbGOm=V~O1C*`NtL?a?Ki_SnE@ z4QatqpI89p9{TMdpV2ih7h&~7qrXG8<7xCL8*}TE=6U?b4r}>SHr@m>LP{-bHHevrXT9z;354AM3%_M_33I=2nqB zI8$H0m7P5x;B3w}F7ik+UTTw;t$*+xNye4Q%X8+Ezs)DrF0hhbadfP;Q7|DX5Nw*W5I1~ z#oBhv6B4bO7rf6FAU8E+v%sR6g9q|;_tp~!ryQFsqwemC=F#spQ9`E}%bLgV}sG`y2u*y+X%R@bw^t;7%e zMk%A`5-6?Lq_DSmuYdL3>{qYGuRIi4u&B6OH_?E<@Y8mUuj;QmQDps`#Z}eqD-peH zk)~33C)S*v?H{uGuWAHzf+5lj+5#DnuN#4b7>guYXMWOtCu1 z1H>DD^%J3k$C?I4wi4Ycu43pt`)M6N_)`vFAtuWl)g{$w?S|f8rS>@}NoMAZXu8;= z5|pm{IKm*~idj*ECojYw^QOTfK@}=8Jh#0cIGy)9jtmLpErhWE789I>3)YA3LQa7D!WWLM4Th@q9k<^NbNp!-7 z6JIPY*5GSQN{}nK2SPwczQI|tis{zam-^%5HOk>zLAVwP+20K;Onxuv3}%k$X7=;l z#=aphzCX+zW$5l+HYZe#Ah#9%Q*4V<}&4@Gpwb!&e#`O-|ro%RTB z&X~nR9FXR|tHmUAMEX10)2gpo?8!#l_LuED^{nk@j#NcPWva`cUT_!{^&V08cuk9r z1g8@?^pwB~`f9~*vrZ#r{Bl4|-n7PVnMiQ90w$t#jZG2psJ>uLW`VojWB66wa{TzE z%$WW>+n+*McWSML(hbu_etVxwXBIbgHlngBS!jmOTYq9g#MNppIMpF=4Bc;E<2DQ% zmTCFb)#`T%I3^bahz^0V@w~vG=DAKMHZCkKADvt$lcxV`Xza|d$n0=UeqObAF5B%i zW>MmSsLR9n#?xz)gb|mt+wioK=5ulddZ?m5FnxG^ zA6%R71}blj@*ckNC#B=>4;;mloWZA5tqXoeTJPfeIA<$q9ZrWS$Ao!+()VUI?j_fS zT@(>8u&finTwK9_$2j2zTrVObrH>7GCIo6pEIDVA;M#7mzR|2J;2o-k+s%v*zC)vT zL>#Dmk;4y6No4ibf|M2|H`Z5n>Q!IoHu)@F_cgLT3jn1Lcxl6sAI@(K-IIjA?Ry>R zyrjW4Gg>s`@2?pG_BtD?)lf!d&DPE^ZQl3?KX&O_n>v_2AuwIe)10 zEa8VL6_khLDR12JL9;r}K7W$BfgvbR`T;1g2yvg5M*3d4MbXC{x$V;4qeDc@?BA{i z%e_q;FD{gHB@ie++|F>n%ZkGmw9W*k?G@*Z7bV6|>{HU%=}w;pwNi=>u;?g#VtjoD zdK(Z>Ap9*AT^-kJIP}Co3ePpzevry{@@c~*COEb^3NKASh1{t$~)6) z+ilMg`oZ%aI+rFtES|g_S9KC2Q5S$lTZmrh?4teK>-L|eduMy`1uC-Dk4LbX2bVaSI%>r7b7P&q^r5|Y6PbwvWb;Ah*~U2y%Tn-JR?6rdq8#|&>osIEujJm zLjkB?`+G-8cv`AuEPZdzcC?)D{vVzm5T@(on4trN3SEyLs<$QIHi2Yj+)KtU)&@CY zqEcHaYlHRixFH{T!jz^5JS_OWjN!~;2EMd&{I#*~vQiUzu9}rj~A!z*I*M`-DgC`pgqfS?L$)!{g7(NAp zR-CitSyn`81fddHgIAv@=U!4|JSTgSD5bFGuTShly5jVQ_(&n zf?1=2nD!tsQb@a>I)IT>>1O#aTJUgQ$xufZ2XLI76RLq6LU%@{L|Cl2ig|x?z0lJQ(?yxQe#NA3y#Kt^T$T<6EXw6lbAjC`)-QXqq44q0nF%`UL-~u zY3G&Q7*(*Uq*^;_K6*6|3y#^Xb_WS0kp==rr|wtmlIqHtie;Q*jcsn?%xDLt@K%T6 zb8e$|qC&|hJHdf3>8A1xj_=^4*bqFrJH>SZHKQ=rK4=R*8G zS%$}j{eC@{+}^9-nT=O6@%?Cb_4&mYCQB4A-lCt7wZpAT*1x4937xhw1r+sZ>NTDq z_c}k4i2_R}+zgvQsi9`-bmZP|LhvQaQbbo_$svKiKX(URPa^dP^s9NW_!;_@%&P8Q z+kSl9i@yycR99#Hro%keV<5_tJZ@9H;Ku>nX+~UJ!zY~FN$7sD9%gVgOr6{+hVoj6QE({GZDcClY4eoa&cfoj!ps zvq4Jlr^S(8ZPhvkH3k2Ny6j2!VY$^aW``;CD_>KoPjN9XzPI9)CP{a5s_X&f9ptTdX9zVTHB_J;o#3_0>LH`j)-=uWy#R`XX; zSafd@dsT^}W-tp@m4y`_V^5cowKprz(o$Q5)QM!tV1azM=Oy$V15j&FNVdGp>OjNm zsXs@1Q4%$Kqsu(^SC1QRn~0(ByOHbF*u=r32f^NcC>2Y+<2nqwUx0Kll2sMQm5m=4 zKmVwbr^~;M>-KszEAdV(Y-_`TYx#u+45kBWoHWqvnRfX*NP*u!zvjL86edjZ;``0H z+SqP2ArnR5?`&q^Mz^)T7PTU&ByC2y%v2Pr5^Qe-SO_zs( zh6OvBU_>e})f(#2&A1F*H>t~&xtVdfTa=xo=9QC#rCUYr3FN{wBMOef9=+u7J#;$% z(pdj(3^}V6+elbh>|yp)SNVd*%GvhxEfliGfs!jz;F82S7K0-otK58lCsU==kKhY3 zJYT}o+O%3scDwGw;6pT&>U+fW&}ckIclxMxuCJ&ZuT3sbp2v`CNAM1g&_XE$ z8j`$RCKxrTxDYz|)%PcBAMa#muH?SpI~~wCI>MJdzWr>l=&AUC*%rAUf%CPYfKl7A zH|~Y2L_%ZxwR_Dc$&&X_ACgwD9r)gZU1frHSwE5FRzh7lb%{Gz5b{&BXul| z0)K(Pd5fJ==te1v+fnjsz_b%3yn-+nlCc5jL=O77(pFg$065hxacwiKiHjDTy0mS^e5VT!jyCa$wYM#T|NQ0W@XE<*@*_+fr%C!Aa3i|Cg=grmc|RWJA+PhfPn;N; zmLioyq9+HFY5tki)rdMWP}TX?+*u~lt;}Qu258Vo{1s0 zh6K6OxL_S})Cl^EnhabB@kg}j0#c&WtOlM+_*+=BBx`d_RB)BWbfv56WUD-lO6yR3|mUyR~@0oQw@?>~{9#`wL>FHu~4@W4dXl_lv`|mudr`JK; zi@8=Dx%jsSrt)|13)qkVP-42Wd^)IeK?e=QQkO~dG8dq0fj4sukoZQ{;uV;aLu&kQh5$^a&7{7?1f_TBx;>g-|-=UsV#1co3x+aE#`5{9q%a~nU#gTgy%%>Zq zqQh~u0l<<}H&^|4auqe3wXWAmb-9z*^ym;xmY5nkqf?qc3t%G!{1!#q7N#clnmuf> za`UatXC-Kd?f0SODPW~*b7v3;G$jJ(F{31iINwpEot#}C!O@x#l+xl`!e>vzgsn2)wuG{u}V zmn*;4K)#!Q4Qe);xkQjAZ*ez1pXX!Hd=HOiJ}VY|7xt)2qek7j=D{G=ZR2pU|G}Ba z<2o{FpZ|QCbk)@1L^il#4=dM4A$n%>WO(vj%(PHOeUYj)HFdqa zCM#|)Dv7Qhv-I_@QE4!0BIYmdz!PU+i0U0!@gb*sJYM*R>n7eE?EaM)V9utH6P@wr zA69@xqT^YK@Rjyw$2iK<;ak*{NwcoxUxQGV94~o@mkj4sp#PQwAiv&|zZ*S4O5>Zm zc3Svmy

    |h&_FN&6_aV@)Gb}gQulQJX=_gqn>N@V58kNfkQwbkzAYdOnzw>k@cFa z%QJ%L(e0X4Q6tHwz>k#BA%KG?a&(xsRlqsiMg(sb@-r?aJPG^sl*>M@FikWFdl|ga zK6A_f7vcm70lYEoyDn%|UXa+4kbhyq`Q0LnZ^I_dEWPv zALO3BXYQFZC$8%{sUk!7;(}uQlm+2Aln{I3w(j+2-x0QR=7==J=>n_LIBE4{)ZK?2emiT-4-v!Z3n$EdSnDCEvBcfCSeNp{5=P z(OaeaRb(f@1mj09dqA>#H@2$CtM5JsyZAm~yc~ZL*hBhz5f)RlEnh=13eSEN)(x+W zfMWF1!3oPPEASAWtL6wI9GM0q5 zF9HN@(fm(I$Fa_1=uX0o`}bwnIbM6^G9i`AiPQwl0U83Lk_dM7elT&8km?X_j3b3J zrch0Nr^g@L5b`&bv4_ z>R(r`(|fIHz!R}*r#l~8JHy4!mO9xjMa9O>mbVN=MSPlCo_LowFN}4@;l2>jGb9FD zGw8ZK0A>WdRL(Vc&LpaFb(5;E%}*wHP*|VuwWg|C1Rdn(js8$abLv=%DD}-qA`rto z+?-E+T#A4^5*sFlEa2S|=i~Y=;i9q=hS>ln>THUH(Oxy%(^c3rL-;F}4K^Ahcw#+N z22`kfT%ic4p@eXDBK$Ipr2mwBxn_fwZ^J>IFWp*VLhP5;*nqZCw0pI5fLMUP1mj?(j?c6{fY*!UxALiYnif6T# ze)lp4fseeToofi0_;CB`e<=SU6l6c2L$2J~97eu=MeC*ivxF>SN@KYUhZ``R3c`i+ z0+XEJ?L6YtZNr~zpLD&Q+TDLoRsh4g_-8^&^9|mK781q$k&tz`jWW$niHisDMW1!Z z65cHyFKx)b2oK>3=e-RebWS!bk7F52?viq^>gSe4yyC>-@S<~kyvOomoVGafF5s1J zrM^A$bHOgh0-&lq9~Jq=0fg;|@FfZ>ZzV-3wy2Mj%t;hFQIp;N&IuAWBD7jn%aoA$ ziypd{Ah$>bCr2#K3w+&yidu`PZI0SsbmNhLcX!7F9*Yn7j z@>!_jAc@5q{vXFY^ z;_Up$ta|Hd>!7fa&GK=t|HR~dds)e>#>7{b63;?x9T31>Wvky_Vj$nRqOZ=mMn?Zk zy2ne&Q+=ZtxYUL{-Db^!kbDEI2D8)!9pla()h^KqslU+<0nSR21D(V1p#aLecIgYi z8))1{Z+{yhNUBiDM?Nnq0A`nR&N*5QnxpK?L!`O* zH|3AeBXd?0f`dRaDB;DWSWXl&@`yL%X(Q8RMg4)zgsZNiio7p_f2r*1&abHNy4ko8 z$IX9EZVig5yWKZdI~WQ1`C46lVcse-RJCGx1KDw?!{X8k`;Q}`lWQt|?w#6lCIm&q z0x9|)J+YSz36n9R2&KQV|IDh|iKOm4NPgIC6A$ME8Q+BG?4fPD%S-!MVf3Znl$YXW z7VgY?8P?VF4Vc*gSqy@6Dp-5;Lq8Mx@WPgL%#iyJzRQ#-k1mbtGPf1|YYj&m#B66` z$)Go?xoRFg9JG1C2+@L3>-fq;Wy{SH4fX0 zFt~Armq4Fg7?&8_-bz8Qpw3z0X{@PaxKZU7;H*K?@>=edLeozBOx*i6neR6xCNea+ zQNr#KxUuJ8)PkgtM^g$B0kCx7NNAB{jzTLtdU0SDUl;>1&+^3oV~M@ow{;`B6GLXoki17L1dp=7{p9PUb+<~QjsMSBwPzbh ze60Mj@S=>X6>L9&n_{VHq%npJtTryzt|z%6YOkp zlRK(#U+WM`RI>7FTvxIZgE$%Z@Af^xdJ#X!wCu!)=D^X3A18g}h-t%@ z((WFQ`~Rqp1M4GGz?<& z`~4p20*&EmYN;OowY;gWN5C{|Y9rzcDAH8ng;fLhAoPh82@pCJsM$pFLan7u zmpBBM%&AgG3JeT7Y3Mp(6m!JS3D=X+S_H&GwtCs9(?%-r>vL)skmeykBX+zu#ca(t z0X~Gx1R1qlpC}Fm?$$@+Q2vS+s^=g}bUNnM8KtB@=Kx%+!ud*>vo5=0pA0`I6>#` zLiDinwtd9_V2h&}hRYux|EK$`-N9M=EW zY$Q{%ISE^8#}+b5_j4xtY#rZkr?QM!~b@?NykLHFeA-#we7paE3SYLzY}WFXmF@VQ}_ zqv8TDGxyg|@U!i}b9~ft`m~W9GACl#pL+@7PLgKGn+Gx@qtsfQv;}!5l@-n$X*J?E zckv@O^SAq7aKi&Z+6q9x=y97=F0Hr#z8~&m-!d6ClBA!Q#7}-RnGt<3qqS`%`arR| zB!MS0W@jX2FG7g3@V zeg5Ed5)oQi%vHfO%zr zRZ!wm?e_lP8Pl)DS4Ti7h+K^=!mnO{ z8ae%bIx}cEbAs+nkpzFP+HuuX-zNM_Jnf8v=kE>n`i;3G&Y;oE{DDZv-Q%y9_iV7V zT3DI_UfJXx=#SSuNY%2V{Hwd)0pj53j~(#71{vWzs@H7sa<1=ujMA3Nk**8PAJRcS zb1-S&L~>uR@_VpdH5aP>%}@OGYV}<1{``N+1ZNvhTN|NsUu;`)zw9NX{&~CGm{mD@ z47m3fB8hbRf^^A)Rueee<|3#dJBBI*c61s{ey9q^wGUQYKe65N8VoAoE*Rn)P zKO74n1?7Uw2}Qf=iQ}Ujv8+%vbnrPEw^49=IsnetNeH~s_9CiIUjbHcgOYM$o;c68 z89bsd&JK?c*Oe^ed+ap)opHK|9HNB!rkrVS^Cl-hgr|ORX}-+;3>bMvsR1d+$wC&0 z(q&a8QgH#8`P@a@#Tp2KmSIVw6;3kjGgqW3%+>bj^6fJL z1-Cnp!Rl<@C)Y+HQIOY~WQyYNg-Nat5U#aZ8m*(Cr0H!g2piOD^dX$>ZHP4--F*S7 z3__|N66mB1@uU8s*B-sM6NjI0V35w^TDHjM^K0NyOOS;lF<2;#8HN1(P8}TyDUr^Y zY`1oNz$0?M=%4U|O&|n-Q)}F4Ju5=qCBE9r4vn>SrAT`fpTDT1<&6jQLUAF+3g<@t z$IAC!3lg_l9;53Fdyq2wZ+)$+*D8|5E~+E*WHH0I$z@ik>2^AOF`-Sowy-P`8H@!y9P#b8O7E(xA}kYA{7qU9^-R zNp@AxDorFDb+>T(NN|B~q3L9_BpY9H1Bj=AI@*BzWj0f35hH%4U#rTHqs|VKZ^E!? zWo9=A4TRccd$MVe?tCK+C5p(OgiY|frfwDogu^%CmvbnE&Mi51^QzmZ;f3}Vk{L|3 z6s68B>s*MU5_6C5w&88XC!B64G+Hl649ILbq2`-EGgqAMbvfcn=Q&_MuQ3v_+1&%h zY{D1-b?*A)ubkV5kj!Jbs05F0%WA86zF#K_Q@~AcPhHsKOYWpAa3m^nGly9Uk)5Zu z^5#QvDouXZ{r&iDVsgOQQkZ2^Ocxr9m1tsHZ=xEq28ze5PWiSYJSJ{$f;e8vk2Je6 zXqB$5U5Ux(JoheAxg^m{GhuA#HK$FP&n0O1^poB?zz_h6FM^*yhA@kUvQ&4$!+WZG z1!+#Xk~2#-BHtw{EYW^^uICbTVee)#30;8~3HK~nIr+QOmOF4Y38yV#x>zrY$fT*O z**e`5=I{SEIYpGjrJ}Hn-w3V5fzQ7edh8^AXok3V9Lzjg5uH0{7O)Tm(am?ycAI&a zg&YtE4DnR$y6}P`zbM4^2J)OHDTSau2G(_Wguqm zx<7uG5>i-8*}13t>;^(GsnGe}aJ77b(;tbqcNrXE%d$x?uWQgzZj090j$90B+{w85 zMf!g2zc2VxjUuh;*IUo7P&etKWKIaJec?q-64!g3pz5!KfXDY3N`6_^tLzXhb~Be1 z;)Yyc^Q269@u*ONBhB<4!IdD8TEk&bQ`}U;ahT8GlnWvJk7z82lPl54Ebrogv$29v zj3uuw=@~%G-TUumLLU=W+oH=Yu20cU^`WNydo?1E1WYz70~T8a1sO6Ix1DLc3Symu z)M_s|Q`chC@~-dix(|ie*%no7+~~AiybF2L{`d<=gv&#mBR1Bu%pP~0j23&RNU+oo z+5@w9mZ9-O=-4%rTAO;3_CEgkB~}QZinb@$`140tHX(zQjh*cor|u_E(gMkg7w6oI z{QD5k8nVWq?SG}88Wyg|Cyd&>2Zsen$K;VhWATnJ!_|`Zb6<+m;{-AvnQgGPsdaZS zgAm$kqWz*TPhze!$#5P;3_`4Snh2$QyU(uBR7f{S4C@i|98{G5w@xpJp<8XIbWU>; zEb>iw#!{xNMOB?+%W1$~+W|ILyY%<_uOc&oCykD$7&Kr&7O z{an%8a37*(3sFO~XQcLnOxE8$+pm=)t=Il~SsWG_wSJWj(0n6g<}=4v7_BvZmL~wo z%FbJ;)iS}>c@ComISJqFIo{h7MAPRci0U=R*cL%HXigiKZ_%n;+~AF;=#_PJN$L;W)1XfPOGXi z%xbWKNOd3l!mM+5_wc!a;JlbP5=sQT#T5=cOoM z1c>n+PSVOdgE%2HlrM@`~HqRQL z7nEetF7?Q^mSCRzpoOo^?mlGPpjUnjC}#v^3G!eFR`${QeN3@E6K_TOp+LL4(AOHrh`ZW7?$)-VeoT6Ux}_z#?3s!D2=dv66uql`+9_r~4Sr!jq;BhnhnvcZ z#!A7=RRFNZby<^EYuQ^)=qC}QEM$7gib)Lbc5j`1{ z{~Bw`UR@AR>VSrVujgKkR?YDrsT;4~$0ZT+X#X3zGYHZaW;rXMZL%aVub!bZupZ3v zu&JmEgT8ML-tsK93Wm&x0|aFy$O$p`_7X4FmI17(xj&`f-?gi@N-eJ!tIzbY zo;oP2-`(_X!ga>37RsfQ)7`XQN7KhB^YD@aNg(nyrU%!lGEOYn||RYXRWc3A&?XH`i7#apz8dDzYO;m}V{HlovlfS5M`%>a<* zz5!j4&&d4}=U@G%zj0xr>nR&?W%vtYNgu@)_b*iW@3|Q{osShJ&1S1ztynPOb?l_` zB-iH8m>2!j<+C1L^0S{I$YJ%Cj_u4DO&J0Gv2WXKCPk)V2RD;^8j5C^qH2kcV7dWO z`}*t)`UB|?FyaHJ^Q=sy*%Y<5eVl)Xx1;GdOp%KGZby$7#V&2W>9cKnJHouPzI1p# z=RZ+5_$oiTYfF#2x9NhLOpT$E;iph!|0K1LG z>-xw;bry)Tcp)asN2C2i$Gr=X?MwtXErAdXM#N7`++okNrp3O;bNsV1={y7BSjQ>x z5a|7p?-~P-8FW7UHfVN5T?UiJq1Y9&)d={nJRI0IiIXhpASG9(mB z-0D0WW=dUu4LT=ga@!pW2-cLsoOPKVb5*{s+N!w6QtrqZ^G%l z`vq@7@h`T8_qC#Ei0ZDqE&2Kjf4B}@d-l5=xE7|%^8;+VKPE5hfjXCeFW>rfVumw-OMMqT_jz(D8~W@= z*n?3P%6?ey*yKiI6{1*h`pnjegPHcWa296ZOpHCnvEBjbicYXGtu;CRDrDN zhIyLUZN&yKAa*Vb2~0u-b`nw{kJkPI<%@ZaVjG~wPcPh||M0SQ?)lj#Js%8_y8TIn zrHNb1ETl_+@2ihoqslGo5zVAiz4?2}_c1)`xK&j|`K-p)zl*#o-s5$kcGlCiRHtNf5ym*A+U_hZsr3Syq$XX%Szzm-Ke#)?u z><8)N$Vs*-;32rK^z3Lmp3rJt_m-2JFH9Mqrx8rWUW~DjJ2qFScB4l}FTWS>VpRV; zeOB{cA&2cbqxjKK zC43$ZfK41X`rAthW?dn2c{aUP(M`8G3OCNa=SuCeMMAh$_MuSk`qWU#I(M9fq@_j0 z@Jgx}>b+*g0e-%Vcu<}5MOsnXDwR9HgpTYzp9TJM=TKhJN4BBpS1y=?gb7>HgY)s< z$5TzrK-x01hm=DP#k1X;Wk#fmw1VSlz_hEAMHNmKab<=BNWOzvl=dp z&s5+%UG?+)-g4J9(Ep9_@%rAC# z3kV#}WogfR$Tbif{f%H5b*6}P+(_-bBwjpncjjjW_K3lLLM%{CU3iEPJ3f;{2oCNR z{KZ$EeE+y)7v}s8PZGZ&<`SN4-gEC>#%0)zmBsEgGt-R@&B(^W!C<0vycu_tU$19)V>}qhwP&%!uuGVKl4tlIk`78-CDs6FHyYxQzeV zYav_q6dtVhRoc)PPX+4)Md_`$I3L$=Gs*d-+Rv}}F(+S5Y%wb~%v5Y6$LL#N(_<4-y7+h3&|DYK1I9@M7=$d5;;5@ z)C3Hw_fRKl^%XXQ1ePf_77rOc?xM47JnmZ7aggvF$zvs?vHzSjva{V_#D=#zj}*IY zW7Q+o))Mqne)v1Rok+JwUNy$6_DmmMV^6bJc)Eb!an&wxALy2yu9~Gybf0i}c z@L|`}W!W>enP0mz5t+E_x%+_`7#N*56l|%pf4rEo1vZ-sr)mI8_E75dG|p*s1b=%F zM^2_y-zl*tz@Ele%Md~3)ZKWU4mQZfmQN{Lw@tC(x2*VN#2rwtt>yR1@Vi`&NNdY@KnF**^7T3a9O|gFov(jdS=OuVW^?| zEsLLJK*?8X&t``3A;nB*xb$N|p)ZW$nggZ}Yy9hC>>5UZrWfBU=JR1Uazv|_qxT0v z4nBtnp>tT~75ntC^zU!ag4VSIp6sLiwB=xbiQ4|iMbF3_iy;wX{9-jYiBI-yT+T+< zpUM2jM+tkVmdF2kRhj>&Wuhsx=*V4k9W!sPP>79i#`ST@;9Zk}5K18G%579lVGEYI z;@8z=+`2(QYiELk{kEBf2u7cJ%B)(OraJl%M*?&zfq)tL_ZL8|hNV|p!} z`)jnCmoU7x-gD@uhmn6{4bDHDRp4& zR%T!2eqpc|`B)M^?0b4)96xTVux6I;k0X5c+rNCoki=Ob(-T~_IHyOyvKw*kxQ}AP zPLF>)6%95k7&gJfHj?IA&Y2)@E8eU%H0Cy)3X0iXp}hc&7;dJS`hg^EwT#fN40pJ& zDA2q3-bpUvba-Rm7N@tlNKQDtx!yxpOvZ;DI9xs7v>&4_S~M0gc~(`zdnWf^{+UvE z6_R)`oF4_qbqclY^%wb)U!#Fe^4xG2Mck0>%sfBQQ3q>{3-rnl^)wHhr4VBw?qJqS zCvc-C8EvcxaKZ@aJ}HzEU50d0g&)=&NNKktUq6E-#3fs;6VCRgFsqSpUekadRzrES$w?RR;g_^q64Da&k<=w*3IvD=88#8eSof*3|koipO+ebj#8-mL8eZCXP* z7?fQ5PvuflEIih;GG!VQ0cboiE$n1iL@S>UWKp7soee?LY zh!5Oveu+a9k@GfHMC8Abb*hUmVirx3sH9p{ZlQn@!ZuPNLe*^Cj2nx&1$O0!oHtim zwEfk6xq>B91&MZ5;!lPZhShNslDe9yDFc3q=+dzqB1 zY2Qi4Xz0j68lRgOcZp_`Dq028nkc9H1Fr)L2PeSSv)O_YvQYqPVjEt0jCLJU5p&k6 zRfW21J~Quj!)bq0U`s}ND^(JkpuNIgvh zZ~r5Vy#0hiZq?m4GHXs?c(Btq&c0(GIrMw0MVazeGZ$0;iiye^b08!N;v zRx7*)b->PTfNuKlHwwPVhB4x&l&H6_Z7Z+_aS0G%pUmWAyn!cg*HmnYPlI4asqw7Vk*8R$i#g{pQ!T}>Ath*7&$^w3c z1iW3)GIOXgc0J(ez|Z&r%RBF)Z@mhBQK>bH1n6ntS8@~tZ@|3c*;0!g35%OOIAjVl z#J%(HK73;tVRkwtE*gsWa*eyfF`?CcY|IOaTy-w&^?VqhO5L)$tBCTw(oD2fCL>{i zcgA*8rkRBhtH=UUQ81Gjl5ju^fVCLte(Q699RcfSaF?@mbZ!e#?M? z_F*^uQOBk%xY~ewxN$aa0K4L^A_%J1M`g=8nj}hpl?Mg1P*ktEG$7?xWbhA8k5_jI zaKpyI)jDi&RUC7)orfiv{C4hDuaiiv*5fz(xu=gETYQmTSr)55uo*{_Zaz>-sAj1j z2Rw}y@Vt;HLXDz%Aj;M1Pwvk1*WIwH-OJ5An+jx8Rqp4c({29BXRj89V`n*K%)30agQMlV?jRH&5nSi9 zsg&G7*;3jigoJL*Eh4K~%7n2G#%1QD@QV_MoTK-@`s4mdnK$m)Dk(^XO$Fw&6yQA@ zgk^n(u2;IZbSv>9gE37K3?m-=T+AO)tmZyMf$KQX0`Ay)+LXz=|tfN^sjs6ZzPypnwpWhutuKl@p zYkkHAM53L)swc;hVh84I3z`H|molg!xJN}WNB z*`#>9;jX~ak(>QPv08L`qjwjY_J#pp9?y>V(ssxEjhD=Py4X@aZCwPfHOrmvR1zd! ztv9|7liKDF4?~neXkGoyUhUfHQSHp1A4hRvu`^2BHA_BYJD*-A1hr8UYG-USG&bURe4n@yTqr3#?Q9N1~=HuEf z80c*l^5_cqRqgCkx$JxT7?6^s4n;`)UF5re(*)KT+*0-FPRyT5AS|o;#JO4QJ)3#R zi}&Z&d}*F=KKq>HP9FGG+s6iIPE?_4Iw#m>WZEhBw8EiG5Uaq#iW9q6|*gJv`wt7(~EvUk@g9_w&J-A?k>&m3x(Au3_l8->Smp4)KH5L zF^QRJD7T2jaB|>;7s|WR(jJuCD4EU;ztb9hgm$7nbdU|i``D1PjJPAVZUCJ?Q>47}>(SfNn-AO)zgv9nZIeUW z(Z~6nUa*gyC2NmLUbk68m(DsRtD$_QMlO2?-a+nf?`|EdleL|zyK@(5^BAd6W9OY|q&~rxBhTV*X1CU#@*}pUM>I^}&OVPZt#8NFdjNz|dSBH23qNS(^OU zmlT4byV~(@@)UeIV)x3pS#Ii{yY#N6p1aApiuUUI@ZVRMY3-DT5GLMavA6SnCc?4IcaOt zdJ4g`g3qg2WZN2u_A14x?A#iwhsvnscMJ}dJC#32`)kTG?)0xw zZ^jQP_|sxJOl-I$aGdZoQ#Lj#$O9mu+U`g6@J=cyUYC9m+B+zl5h*l&mDg+bmVrY# zO%r|bg;mds7sh3SpJdT?2s3IfT$pOPPxv1t9tmVK?>`KwW+qlWT)Y0%%xiV7i&^;2XIwKT{p}599V0Gac?@wQfv{C&;fQC}F zvUV zN27m}A_ECcuT=x)W)1#ZOC=EZk#xN8*<0K_pW}a6;|@W4KjHT0W@)Yrxke8n*&!`0 zRv9^V#d5!p3ya7-i`vT5+3Y9&+IH!hNDocQIPpWg-XI*=t+rBMHzo)S}XjTC^@=nQ8zR-oWZQThz@EM<4I2L(0S!6ng z<%dT+S3xM|vjbh(|LxOKVjSRiEROVmal45?u*O(cm9GGUHbbfBH79>I} z)-+!MXalg(&ye zv>YS(j5+>@`l6C7{m=Udy61h}q9_QFZvGL?Ub{H=_bdS|-(XY`X>4Epe4fp$@C@du zr-pLHUw`Rff3%Rs8=Pkd&!26MJ*1ATQx6P#;=x>`_cK zQP*F~n8}Asp^MD0skDUGMvK z(CZfKd_u=M`9^|8j5O}sQWK^ic2Ib?Z0|JO`U>PGzQ=nUM8qpSA4azXrm%Mq2u9e& z8g&3tX$N8*Kb%muOC>TEocBu-bJ<_^oUifw@pB?0>UU74@Tq{7881Td?JoLIJJ(>h z&$`Oxa{_H^tXO8XI8*ZkBiT%`1Cf`-CQoa#a66B7Gm+%=w_g16RL{?2KOJ|aRZ*m| zuFlmRt^{o!>D>5K$AcHYpQqq|E1P7st1m&_d+>;4lxZR-vJ4w6hSl&hQ2J4D`3F*6 ziD|v&l37VU@JTK}Ss>H|jqMG_v@0j~Bxj6Po8CayF$VlJ7I+2H!iCf>_qS}!=jV1D zI81i`{Jtey=Ld;=o7%T_MFkCqjYR3B)V*6d;-tK`YNGMNAlbVW^^Uk2fe`Gky0yd} zwa=axoE;(0{`AHUmusCcO_{eTw-)8~TwS^svwDro0(94Ntp+X`EblQ+xo4omIm%wV zMqndD_985<+`K4c{z^5bEs^#4o+h}KnD#lGyOQj6gkDi^g^o4|+NXkh0z?($$@ ze^l)Q*IuV@z5*oz|1<_;IqtD>!iBL^hfg1Fe^$KoZc~-i+)CPkbD1H&G4Lxlhl@tX zET%e?=+lW>j0uymMmKe@|NJ*HCaG#>)xP!S4$%Em5KZbPox!k}!5svod$Pl?9{T2}DeG>#S|})qRwD@b2BK1qzF)j?#J= zZqp+XdIe)*lCLfiw-(hRZ!2FMRK?1FR`Fz_{`LCqea6(mGS@LD%xC78JH1&uY90Lh zmmMgrn(i9L`Zab4tT?nhiLN%|k|%9mbiSXVV5{{eXQU#-c<`hofrZA!_VU$HcM-DwO6JBZ+s&{r)K>R+h}LjVvq+RqsFO6-4p^l z41X6jqVqt%AgumKylC6@N<+k+#@irKnKZHT<;4};dVnN8uFpq1+rEB9-@6%2;AgTa z(0%RsgP&i)N@(`%?+b;QTdwdbc%oc!oI*4Q=)*qSf$72rS*d2c9WhyVUgerJF{*L@ zMUG}<4cBW8_VPMZfyTXsGZK&wHpOqJ9xfc2n2<-bY)>Yc>M!%~+G<|987t)B4_Z|$ z6(4pDxox2A{ck>y;U;t;f_!`p8R|neJFQPm_bRl1zje#ig1&SAu# zH;&h%9!E#T$u!RS4J1{)z?@EFC7kNZu^GB1IAL)OTo46Nu%x&kTbWL1k3zVHx#2v1 zMhbWzs5N zoXmOTl=U+}6#ZA270X+(mM zAF}-{0D(Q0D~^>fv12%WNLflWEJIMt#3QyT3g3X9YK<#kO>~&z(@c}mi=4| zMky&EfvzGy^}y~U-*vDrr`kLkZHGCrcRAsrT=2@}>!@$w;1I^|E6`kCB+OcGVsH1w zK=7TTJ?5mL$K+Zn_y@NYn{J`d(Fw>iU1I*ducJx|`1x9b5+))mwXp0|WjliLcV3&J zrrxK=$J+EDSn~y_F)AP> z2}oJyztLy2erDx&PXUiM?*V^aezoEVx$5-WvT4IYNoi@ygXCo}0J6ZLHZEtwHxBq< zG1vlsWJ4lQ9CT2>2!P6#752?00xa!v{bsl0am4IwzJA*vlm)uAAkIEHA-uZ?K{u2_ zL;kgE`t{>Lzk^BsqlOF_^A}24tw#cXLYEal7`qx400KIop9z#N`m+yrvw_0tZ6Sug zai8&p3UyRwbxx$+2M8wBg6l1zD`yXozJZkNojvezINN>yl6O zF#9jaUXCs$F~OR-pLm;KBW&!zW)KA_ezLvYV6*%H<_eM16NBzE8I^}b{}d($RiG+jTe8v_A#0($LuZ`jmb zx;I8Zzf+_gzF`QDY;*bZ`sO&cW1#q%3L{v2eQWhV>|tbXBHnQsW1RnRku~vbhvmQt zKT0^V3Vy&J6fCzCC%ARYNPlVIyysb{5Wd7pf(OnH$S2g~r8X7Z>FE6*wK2`AHYo+x zegq@zrXBC$RCNq;%2QUqcU`I5Kc?x3#LVnK1#edB?^rhw_~tXr@&po!d%?rJlYcboFFrJLke zJ)*J+eQ4}=xJxiXJo-+wb!TTsv^EzT_82|H&_dj2G&kY3hZQwy(UkT&w(saegUH)p zV(a~y$E;Z03s=Mi0?URB9{*2IoX52A#z~C0mYFzF9-W7e1dAPB)JU0sLwk{Ty-A|( z9lF+m^IguD6tOmk%zv4lpp~A#z_b&(iW`(+;{$f}dmkX_M3)fZD!hN(Ez$nbHq}c{ z`({*;f5`Iq(|@0fTu*HwPLW0J;dSx=2LDhNJO<#JIyt5| zBb_^3SHfcl9$G3$<-{IgslfGThS|6()hezr($m+mPj(I1?FZ+gn|D6MhzNJd4wJpx zlhyrt!pAsVJ6SmS`!Q>gh2H*U*t=x!vWI*g%4)9Wd?|mf?m|S3To$ecVI)|tv{e@( zDI*SR*eyCIu6SKFG-y-CnGokJc&Vd%qmj%~3 zpaoO&PW`RCr>eTzaVi-!RzUl#O-&lVYBnAj14@T1W8;x(s$nZro3xLqG;jgYzzD5! zUydSBX}}C$B6OfIN~o91;nv`k=#_jn^^GaKfv0_=F|v*}AVWxL)T++Rqxkwzs5&Rm z+BIXPpy>FM_GHGF&<5f8Wr7LEVzS{sB?#K z`yXB($M@f&+=;v`Z>+^JV-}j|`@>rWcID>f=~F2YuQL;6&8CPGFtef$pCu-D(Cd<< zXA6&gzEk{@=v1Sb88gDq=zKiXH&g#Ja~N&*t;^~u!AhvrI@xUeyBA(ThUD(n)cfyj zd3>7^NjG&Czm8H-kN0JnqvA{rCsxi}l{e6;Wl%VemB!5IBe0FpAVovo%dXzK>#LX0#nUex^i zx={Z0YU*gdY4A==?MIRD-$$`b8&lUeu;h3TInW#i$6c}4^xp4O)9Tf9>C*^6DX)`a ztFJdMcp;)f);=uR1(4y&>wAs|;j5;pv*ULLstF#U(~Y*M>%r&->uu!B#5LY%{?th^L%*1 zS~i$nD{w`Hb*tc#o>^{W_vb@{3y`Ca#-NY~xtQ^KWW{-D{(92k}-nL2;rmHH*SLQwi{9 zW&r-(NWkp9%Lu(QU&J}ms;xsO*~Djqs~RlOuS;uQ58a&1$8EWs6%q^yZ2J*<1p z3fge=gtE77X?IT=e4rWt6sVciY;O1wL}%lylY}d~B5tJu&?Qkv$>p}zfas+ck2ko`G`QEfbNc5s!ab@NJfAUS{j4R#A9s@}&aNP8#J z8J7y=%yDat*6|ZV>A$Jq&n%K^SbH)}Zyb`o!MB{2|1E!UI=Iezy4xirAUt|>rg8Oo zZ-5B)0GjsX-!)GP4OVczC%XWla_Rmw9HbzH7xaDXyWp<<3e_PFE4^XpJuCmbqRtm$ z=JQNu;}KGE5+$gdVm9eto^&eS_n6S?2y|qTkcV5r6kGl|i?pyk173>wQs{O9r{Xl# zq5w^5lVC-)os}=^^aQR1ojhp5K znjJ)Ey_A53lBP&Q%S&+xJ~ic*_t<#gyElIIk$m1A2Tm!)U<*w$9wpueCWXL4X7oEj z?8=YY&TR#DH;k*ap5ZJp=9O=MiqvhzXn^+n6OA&5j}cs?3;p2(n@mMz&9U^%%5u z1CVu#+lr2moO&=Kq5KoHWUX$mj$w(cCV~HCX;{_oYe_YAroSoYp_OieVu}5DA8Pb{ z83U~AfWSIy3tqmM6cn@>tD84>&X*YRy%_i+iTkD{xm*Y6E?+?k<{b2Vff@^O+Kx>8 zS<}pibg&w;dGp(*;jFGq(CxOBChzT(0lFEJY<{&&;>_Y-=59$f8G}4Aj;t<-?a*=?snbi6@%~Rt|dyMGVm!zqN8ECU^oEP<4azrxVea&d)}u zk(d4rZ|iL#?lpR+9+AR1xtgLTvGc^BaY4|DesWO7?+%r?qqmC!PBrj&bIMCCTq*Q7 zf+JSKHPv{hsP^t5Ke$ssL@-Jrcn+dBdTW936Kt}GsB2BwYnUJBt-RTu{9U?Q>veja zbn75yarRHpM5x0Ha#)O@U_Kw?T!%He<8oUW2O8N_<@cw~X|Ounh#$EYIya)*^m?ipp7Vd{aBgAFp4v|CS!ro+5AP>G=}r(Uz2RU=J~e1mYS5`%?B6g z&3#@4i>~htFd{q0aW6pFW6-zJkjQ)oM$%II^GPGM1@0>?cEs_hu7-eU6)_?OMVW}-p!$Bcy@7M2D|6p%M#s% zUjIT=xsU(^{sND^$BUsA;1+0$$O9H=JdquZ?>l&LY(130YNDr=j zViC9U;3!eA#AV~H{N4*C-MYI6*L2t#mK1@OBfkXHJV8#<^zuuLF*vP<0xb1+3im9n zp7rZq$ad=3V1MGqEmdJgb#_Vo>tm%21b*4PK-RDpe3hYOAH`tYL_9fBV`w*!KPQby z4poO=tT|a4d9=`{5pRD5aZv@)Dc(2ZQ|49=6vL14JkA3;yHVJGU?vtB@z0 zLWMue2Hq&#;DTk%f|CJKDH_}e!L2O2@y@d=7fjFZ7Rr?0B;@(YM1#APB9ohsHmTO5 z!Hjg+BGcp>k+{BkOr}cU=tHH3ZLNX5P?S#8^U;y6D|Hw-;|h%n1_B$*l>Rra_0;g0QunpWpb`lpFx9qB4iebi`bf?G<@4 zh%S>TIh0iAoy+E1ZyAA|*D@Uqh>6=X?|A3&(MhYqisxCm+N*<(g3Yw~sar(C;bGq= ze9bRvuQN3^abzM3+vf|XWJrAY797|fi1u%*4vM*86Xjh^o4SMk(eRcb(8~}js%Ik4 z0;XX+_GhiS05vffHK%Y%sueYpO_F&SI&y*SnM35?tr2DtxE5$n8q?f2OY3e?4hc$2 zAQ?Jb+SJO0N^me~NS%B&@+%jtE00GM+q2TQU71-MUSn!4sSe)Si(p@)k5_yw-uq$x z2D87?@10BNE|#6rNr5>QLN2E9_wYHmLu zZ(JLydC~Xwaho7VKTjbOQxhpiGCn=$SK*k*w`8nMvHfk2t`DpXQk0?*p{GR+-pg&3Vq z&fK;CqwtpQ;9U-;*5d@=7%1b`uVch%LcDuTRrD@5NjAxNRiyn#5fOU_ucVKK6d7Qo zi4%H=0<;U309YiDpmSxn3FCZjB~7z)n3cYpey)5#aM*p9-t~;u!rQ0VYbfk#VArt{cx%47kKvasL!W9H*Do70=C4i6! zg7or%0wP5aK~SVflahc)?;RBDGcgxm!|} zBwX;nMB;~mAi3nf-aXUb|3_4SLqcg%96Tes)v5mwcaH0+*Hs|aNAM{*%Z!IZI8mcd zXRK*2f(W~Lnr~m>(H%q&$L#goxxF+hItM!Q$DC^__bz!yWc^&tUnK0LR79awE$iZ4 zmBn>dB@Bcbu)CU`HC?`DJUS|ev+c^vu^q-tga>m==7vw_xL7sCn-6bzT2;C;UC^|S z){uJs*;xO02!cQ7Fsow{T7Oce5m?ewI;iR8ml23YrhTcyE+sSj$aKQOq#CU`TTspo z(^$NPVsT)7mUMBAhV8e))x2$a9&Oy=l5@Vi!?ts)L@R8I7kXIaEnwA+xa2%CUmPpM zb`$%b%1lN5r#Nap=n8c->bz0U1ClQ^`e8?~CWx%GJK#F#hNwSpHY$@uFU)wqn@|D&&oF z!bD^(4WRCUcr+MY-{6}Kc^Qq$K^E$-TABP0-&j@Rhlj+`$UZ!1OY!kPWlQlr>JeX}!+aY~JjT>JWK3~^Z0JGHQTogLvul>B&t80V`3 zE7-pU07>LLX!1RPN9=^2UW6{8!CDWr-rgw&&uc3f`!G7beg4^9$RG72{}PQAQ4f(gRu`?`FH`F1aB9$^|@4fJ2Uns;;y( zw?BoIx5~(nnV!ddkLu&Ab)aN2#dEMk!BS^{Vo_xNT^liI+vUz&H%xf`h}~1@^l|Rd zXmQxE*xh@gXWd(X&^HP#D`nJAn8jITq1Rzp;irTa@vOvXHBgDL%gm45G{4h8S_?%S z0LAyegd#;xWuSw=>QAxd36KUx+>%a%B=o21birS`x^Vn&j z5SR6I3z4>a(TMf0{9chz5aSj-=hjv$fnMuP8H3V15bgB;hDjD$-Be`&)4WWSwtwKo z*lD_r_>qJe3503C({X*6{s$(oyz zzU${eo6|9Dh7s}@;u1V$SVD*9=66QQVAOP01H|BD-EcBXOlY8O3=K>qIATtW>E{dm zgCm@soRDmN0%%twC?f(i#_fdCKk2Afil;iTEg}D7HATeG`ZolYrWD>p&$`VQYs0cY zexMrzh|g?Zsbo8GNk(I{L?2RJeCK78(Retezhr9#a8CjyDuBt#j1T8KzPA5sACqAo zxYU`Tfn^~<+CejJZvIZF6lC0WRn{5O#oN^vCQd40Z2o(>rA>P>>4r(c#x~iRes15K z&N!WRftNR2>3m;{3zFK;Rh((?mo}Z5#ALD?ASa;3`~RL4dbol{Br7%w7W9)tVIj*Y zZ)o)nSZkN0#M=1mF0)kHd67K~Myp-T3d8o8qE2kx)tg2Z;45EPI^I2vKe~fgWW2O_Oor zGZr;lKUzo(_4rxH>E5AuGERUU{qH(e7^rP>?EFD$%s^uxqwc7k6^pOC=@xso=9q=^ zB?qr?2sx-qq6vf2Bi<9m*zm6z)`!p8l@i`_yU#3eJgg+6xG+pCmtT@A$6;=DQ*U-i z#@i!$adwBdP}0ADUK(Gvil-q&V`9u>hQ`SHVopdJoUc*bvU6EDjsb zTKsm*!rtz=kUrgKeM>^_Ig{8R;EaQ=8L7QoP&(WnDiT=Cc?&cyDkyMo_Pr~aU=@Id zlub+?P;>&&Adl+TMu{x$ByNGPySIQ!ko;pwyb$lGQ`L5i%q0cvp8vkx zX687z2O_7b#l#yzuN5Qd2mELkh!tu6@g36q&AMl1KEQ+7^d7Qgi_v@Cj*Ftq^Myau zv;psw9k6LJf`a2#KRN2{&gCPwAH|$PG)#0$c0fRzIiPU1#trdZyIwgG>XrL=Ti+IQ z9NBmL|C*m*9k)4p88WuH;8?nw8Pwsp^nqZ|$pW$lHxDP)?X2PKy%xXXw_7~dNJQ=tO(yeOI;RMhD2ww$3%XYTawLx_<}P!mT)*+FK$d5SeAiHu z%zI+jBfUe|)zv$dHwGQ1u2t;l@h?xUlil?Nkb2%az+2xU-&b3sRQQ_w!)M7=^}8$q zxy(Cxhml@*;NHQF8ZUgDTW(Qr^VcKIc+yc5&U6`D%D7EDuS}i22M@40ZjvIME$!Dt z_=mqM1p^-M#7r_DsPkLLbErhr?VT7hW`7%ikGu#|Q$$F)6MN7HvAc`_VMY`LH0pa* z0;5d|m^pCKj2Iagnd3UPCMya+cmPcy*+v5)?m0?)W5PSws%n^@)sc{EkY4k)rR@8o zZbyzNg*1kQp?=bwhPUL8khF_f;oIP19u>su48|KY2>!m3#%!yCS^*TaA+5ZF3TE>j zp~{B`aag%GUuDA?{c`-kwt6LC_JPqwiORq;cS+q@jhV^c2r7m7*7Oe9 zd~%oIInOSOcYRwy5|Yi!OfG%-UUlz-jSaKV*$>9!??)0rL+02v^3|sEI*7-Le0BZ^ zUm#yUKRO3e7~woapRm1UzPvsjh9jg-#Vt|l;6;o*uu)=`cY0PyXR3HWlgd9d?0yMDOp{_fQZ(V%(dMACtaK|Ex%19@U z4h4nDY(Cgb*r(-t)ogO{|B0pYk-S9zVoVI>2Gnoo^~rWj2UXIazuKz^c4bEa{?}>y z+2eV!uS+184FoLsc*Rmk{4h}j^vY=wf>O~MKi`Mvq29gZ(_gi&-7L=k*^vw($l@1# zNS+4Lrvx#q$T1nnRQV~jC$0IL^Q66?>u5<{Ld|!jLxZXg5K6@)&4{(MoIif@MP_uZ zOfHVE8OU}^CC??YiMC2Ny+#Im@)FSN>;l%lwYW^TsMjRNux*mW!ynVqQ@42ud6tVH z3~yMQ$qI?zcq%UKT9$e&A+iil$+ycjiX!uzu z2!j(iuMLL$LE}3Wa`kh1XhaZ=tL4oLWENX;ciJj$_)svl&J~mgF-KT31G&_Oo==Az z@!1QXvb|UE4xrw&1DUjL04Fi2WAk&EmUJ21$IFi+8R#NvUAgFhbpfR4YHJb6dl!I= zZKq5t|MrG3i%lY7BR9)oPR~(#ebpL_&!|s})P; z->UYNdvgU{YoIBW(W$VN$Jm9^Q{K`hl<0}Y&kMhtozts^$=ykWake|@Z`+S-axu2L2foEg(O@st7dyJU8Od~RslY!JU{ zNSuYt$NG8w*<&Qr=b|jj*b-!!88--o_Cp8w|$%RCuhvo+fJz^=sfk9baS z5wjr1$391v?LMtx@)Q7;oQO%YS0+yH3>Ll3t8RT*x{EOMU z_Nf<}+vots5%n*encML%W{>m2SixFecJz*LUFotXT(mYsdX5Yk_QYK|YABbrzSb>m z>OYu8z%f85K<{;s2+(0}`p0G0wfHLA_NsijJX+APSwy_**4(#mO|%S4QX^(ki&=I; zR4Di#3m7d9J-^y9?|ES5eFZ;>Ln_RP{0s@03r+`V_#6lK_!fOTmX?EL4Z{heGk5}$(_?`Vi z2#0*gyGePQ7pDMu2Ur4xa2*FI6+3LNt;?~cBS3zH<=c~+FKJmhI~PEjar`&CG`pRl zpiKtD(~0liLe`jVaod{Ot?OJ40tXV!tvO}7YBUM(Gk|db%AJt|fKG7es3=sqP!#=f zcCUxGHJarZ5=`iYwInGCgv>u58T(u?A?Ph9!tth>lW4y6>VfCb1Ul?h&$jgCb1b(i zPnEnMpvtr2L!E-8vr(BmQ0Jvl6oUfa41AjkN*e@tXzV2>;aqHAe5pc@+%fa$BbUj8 zsT9*V&C?Y?t+$;7l#$4i?J4S<;`M0s3dFVSz z+0|G}nz^~cvVTU9b>%{GFs1FeDG#R}3LwrT1e;Q&K2Wx6> zEZS;=lW18;tJEgb<$m#Kr<4Ba>NFssAs=L0yP%-kh|H8Z@vn>0O9k;c^*A#sDyA{^LY-%$ zvC^k#m>!}_86?@rmggjah&;fof|zZ|LS%!>g?y}paBu0DG>tDozy(*sBc&cptEj26 z0>^s9X)Zl-Pt{Qxdf5J+N89|~8dJn$Ok`@{0I%-DnNyE{Y8V-5J&Z5%<(ZpPmcHa~ zW`y3#zCw5Y#E+p(Ui-;8y}Oxy_lLu=PYyGUOLeW$dG~J)DLqRJMPe#B-7)o8H1k9j zmO*u6ZFr0zt71}{__X5-4Gn6c++>?Jq5!q?D;UN|4`J+4quDkNPDtsDauWn)N@vxWH0C$s@s< z3p@@#tNF-{Xa>lQOc7+m_ttRI-z&ol4LjI~Jd^KfLFcmKT;B-sI<;j&A`M0)2cV8p zm`RJJ2mJ?}A_Kl0Dh~WYIbb&lv+MwNF6SM)vlliEbs3pjjbU6C9TyE$o&n`qg7Jm_ zptK??aC;8|ND&(7?7Ua6Iry>QOHo1t6Ry)eP_k(@ekb1UsYfn?q#2SQ>?hvx>1eA9 zUn^4wcYaakS!1VC!BdXDr`Qb={5kaA)>cB+HZt11La$_f?!bP^Gu3}*EA`2GX+%7K z{Hx4wx<9gwCiyPau{Tg;W8>1no~-A}RY@r;()doEhi${AIgZ{Rv! ztP#Fnz09hqnk{Z>e-0D_O)mNyiFfnSn+RF1RJ1nB%@DkSgTRuuSzPn`)+)QfqzN{s zDKT4HRYi@`v*|ER)JU;%3(Ww!@AhmESLHAE!J!rL2@NCcU9UZbjKX}e_SNu8g&}jSb(1^1}AHegW5vPn^gYV97zBT$?$^X&ldPxtCeoek> zM*m5^r^$EhOJCFpqc6pg*_t-b;nMC3mo2dK-qy+-V;rM2ZG!`UPDyS&55Il*`7*xQ zdj3Y%2z>FM{jGI^Q~1BUaRm9+Dg{}V7390{#YF9@a;LV2KbAVR$|VXHAOF>Vro&09 zivK|8Tz1?5|ISEVeRB$V6Q8o$#kPX((tklvb;b=>U75O4(_Xn4Ic)pq@Vyz|CI7-; z$Qi1bwxtFcLA1k;ymgkQWwy8? zI;1>oRwFIb8IG7oH89!JK{3i~33SzV@^c6Ot#ePE1rTXRSKLU2+{sDt{L6qivg3nY z7ii60$)n==3RMJYohmJ0r5)UTOy^0fB~4)QBeQSrx}~Sg(rUMW;s#J0X)>0DE>9TC zLkqIYLjj~#w!fD?HMcC}F`61)<7Vt|2r%vJDkzGx8M+Sc5o9;iGO5N7=Jk zJeO@pH}t}h{+vD)#OgtQ{KKJjnm?Lob;DZp4v>X1TYPozrbmN0{)l-Ua+?<}>3~{l zcH4Iyt=evYvdlJD0^L15s`~*knUBTIQ9^vc*qTj+s(aJO)|Yj*pygF)YE@>F69|1V zqe(*pD7(PR|z*O?$~UdSIcUqyatETFlVzvhL4QTXd)t1+lsRt5!@Wo`dcNU3yvh5kohWf1o+C+ju^*R( zLfP3=i+KbbF*l4CQhZVKG5k^;>?w5c7Nkjo{~OG(8tg7f)iD=Ry!2gg?nAY_uNdr66tii9i`5)&InJWScLlNCg z7S-8=oLnRX!)k%^Uk@nGpS`DhOzxo&ax^Gs$hcJV{_6cWXnL45ndcsN<0N3JF=n~r z;Fcu1vzKb!qlw>``D-i0#g>%kk19wC7%+p`!hkbXm0(0kMgty&|7QYt$4Ek+ z7g`D|1O-#lW`Uu70wyljz+VE&1GERX)!K#DJ^gtVOL9;XKilk+7@U(72Zeg z!bp18znq9c$}4ClZL8SRo=?w20Z+vI%{ZaN9W`IVFD2xQ3PS!C(u9WRW{QyKE*iB& zNbs(oWXy5JA_?;c=m+omaY<*{OZw%g7&Y&(I?B5~;zEuQcE=*Q1v8v6GsPSjBA}j^ z*%FFor<+$0|ALS^W?qJ0OKLj>yy}+1XOzQ~N9X7iH*aetDQ@uJEq&B{MOS7fM=LEo z0@bhR0{dN&xH%^-&Hy!kj_ z1JflDa|M1G`!k1~sq-wx0(&Sb>2dRo8A`ev^-&b>HWU`ox~@({t9eNWJ!7GdqFH-j zMk?gH=^QoQ`}eohfuMBIyMA8iXb4QD(XihYjYZ4@698umIkJq^=G39q4KGGajl=+b z(jlx(M9p%fB#ix5pTKg(%s-C-?FUlvxcLlzMa)`@Mtw9%{5{fy#2x37L=Q;hkfu0o zfq~*j&AU(#Gy&kZ@v9k9EM*#X7r}g2zyu>^yA8(5FUohmA`JCJ8-h7cC<-;Lhp6Lm ze7>Rq8Fj8ux;$So7e7TzqwtSD%vVgsa|_z&H}o+oB}(O4t?o3TIxPt-N|9T8-QBIYts0(n4g3b`$r<$#o)oY@AS^)YBxG7kV% zI)O*cD0_d4AAM69(;uc~y;l`!3snQ6&iQ`CoFb(Hxiz6mBw|pmK?96w>|ylu>&8rW zpRv2Pv-TCh_D89n=;a3V^0JV>DH(}0=HCDge+<8q!A4^;`!~N!Dx0;PPte*)eu;cQ zP$DR;HRa!sVT*uctlm^o5#$W7B8RJCVWb)O*DH2RK(!|ZtUDqZ?%m80CC%)pEUilp z`KUn?V$dpoB-*#CtE8%6>^OA*k_WBY(NK!DRB@$a9DUI`O3;ccJVj!SIqI%*$ zRQFT6w9Orp2PeFr>b+zpc_;FFH@z43(@U!#!Sx}r zPaU-Sh<>n_N}6K)Y{2MG!lV7vE@eFQm;+FMRR`DO4$e#luIuV6YNbd!7-Sl_?%-l7 zie=M$WMB2g+pD9F9~5s{-@3hIgbF!an$H-t?%;UgKMWf$Cv5}M?CeK2oTX|}F=+K6 z)#8}a>PPleKiGS9)(NH6kISuns>gNnveMplacH9>7BicSxbtpCC8pBX( z56K>|?%;|kNuA}0glb@o;2UJ`!Fr@$)`GEBS|4vKehnnkGx#5NwL#Y{(8irDfzzkUT z6DajC>xxnjv+jxH)iCRx@+sI- zW>-Ig-3vRFS_bG+5;)&i(}tm{i&76CyD0VWtBX<(SiPWDGRXz|{jubcNGx9XP-^($-Dv65=&Wfk7}1hd3h6x0Fh4nA^?8MN*v z6Y>F357|>^B_TG-L^!z87V#+LF_{7W5GwkY+QjQ_Rlv3l_ zek%?>?nq}1h;;C}(o@5%i^#DijV*Q)skb8mgQ}G{&jaH9Wa2$w^&!Pu9J2wd4=JBj zcEkJatRbt5cn^quNa97j2dq9Mb}>qJ^7> z>?6cuNZA&}9I*P3WXBz!>ZLlQ3%K4A5sM6^Tf(ty>6#4ZXlVD+J}LqRwW3|B!0tUI`Z zU{8rQFy6uI3cH4hSA=}Px1X6t)`*3D9pLKx>0 zOdm?B{VQP{SqU9x-80x(L)0yaw)K(|Z2B9rZb_`HSKaWZsLSox1JnG8v_ssgQW%A9 z8q)mA64ihl8&bezrD^!pMLPzpJ|yv?9RpS$l6diOhFu+F2MybB#}3x*?G6hh1l;<% z;=LqIq-8+7gHHiMl(Yfs4vzP%Pf=I8X_$Di-+9?a+q}`o;=LDqS3>wE87nTtUIK5h-TTO*0NVp2<}m`C*5;0~cEh+X%H zE*m^XDndTYy27pj>kh7%5(6K&?oe_fIx=AOA?F<;H|>LTO=Rv*%*6)7FC`X`W5@_rb@hYZ;R)*W10WV{|`U18TS>xz^PTz4ob<+kW2 z2CP10Pl;X+SbeCT>JT9xu=O*1|9T~9t5ZL#3h>rAET@ERz>Tw)Y;MRpE z?#GGaq``#b%#BX)+&t-pd>&7;%}V~5nAA2#nEZ%(a&L6-DWaZEG%r#=YRvQ0kMqoF z>c>T9HGX8agaKld`SK2dgfap`N!(%6qR?cdOB0(eM3E+W3Es? zW|}wShr%&ifxd=0ew*k+>S>Is{yp_{wD}+EN9D#5#NVc#PEmz!QctIVNrfu;l6snKZdE^yH=kBNPBR}{BqC(QgCa(D}e@D|#q@ZeSP z@c9`nndvjrRZlR?L1M;tm*>8R-#GN;M3$C5=v_b8DG!HcrhZ#&4-fCT6G<(pHRda- zcru44Do@7IA|B<9nEN2kJf+*HA67&iV-baeUtLYc={$=W&$-TrgOGm>wd|wn>Ek1M z_%*b}%@3TPSg^acTkK*ZU&;PgMyAy#)ae6k7mr)N%2Wg~hh; z5E@VGyKw^n4mGySn5}u+ehMbw3{i-5CX9Sb<`x{0`Y<)gIzQZ!Id5jlo7oC3ou{S$ z#>ezk42_jf$MLCDEpl+)59cq99v-X8r;bhFND(M@<)QgtT%jvTShp|U?c^z>LJ13U z%4gxTF&%8l-0IYFUv_%izl5WQ=tlpN=7o#9*q=#9#GESk3b?y)=F6JrK!JIK~xZX7Q9}+*W`Lez0N&UTsS z?9ocjqb)#E+;}Xs6yJLOHVn26p+)TA3Lk(c8xUg)Byk?B2DNZ@thN(_u`5QF@zxwd3DU!jq;Od8p7FQgiWWXDQroN;p@3#Sp)894NU zn?-S!&Y0}MFPvPCF;l~MBBC)3*I?vvmNAlu6cd99Jq57Iyvj5GuuHV1z4MlGWdfEg zgv9q2_Z`u=jTQX%fo{Q^0_K?t^RrR3QrEE5mwy9dd#S>V9>WQvII!CpQCW4-=G$SPx$@yeT)skN4jWhegas5p;1FXFYM+)Vv_+>cS8G+T@o;nJcBbgrW zE#oqqUDz98=`f>h>=T_D$};9IUC!FLdUA^cV0uNr?fP%RJF^YaxSpt(rl3H};< z`_aI9(1klpJSY_4@l7OGLL_{6u53jmd#GuJN2$_9Bo*b`&rM@z5Oshm4aKIf&<5j`BP%OGa>Rwt^+SzuMENdyy5(zmCLpQd{>S0lZ=<1y3KZY9j^1 zR-rYdceg<4jOczTQc4fXtuskZ-1{rsf{=iX0`9n8F5urVCM!~Q8Dm*0u8$N5Z$$FD zj0%aXfzkSN_$aRXi;XLn=XYPcmB9@vmJ{wTijhu=2i@ffKkZ-1xMSz;a+{I zW~{vnJ)6CopY#&_a%ws^+ZoZ{g9`(-wYzJy{boC#cIk;3~>(2}1cg zssBEQ^v5T-%D`gY;RU`~q@9qnz^b#~I!ngQD_-EIy00amXiyy2_X&1fQ3U-?%~H_w z=L7oP{x+u;ll&s|<000S`svd6sCk22P~stdpg|M*jEWtF?$k#~Ut7R0G{!PZ@wD9u zCov)gifun09b2iNEzo18zX+Z46V>_>;G?D81>k~L7t(W1WJPrrfKJ+d#@^Oz1$e|< ze~7aMA-w?HqHhcr8mq z;cYt(07L`Dpoqpo3m^n zXN9oredyOJ;VqBW>66ZcSr(A1Q=mg#nK0}VYXVztzqjV-;Z@#8a36M~j@Q_dQJ&Jd93 zxY2qI`hM?w(2}~Il=XBbp27-iSttF9*Nw@PQw}nm`c5%KV^Qli>U;ewI}B_w(f z9O<5?Fj-&#pmtAI6t1o-9ZfWHY^4%XJrqnN;Xy&WU;6!ia!mIC8iXuV5Uu!!Ck|4bdVa3mTNZxeq!is%UvWx|4RBVlCXNv5_oU>9TZrxHpaHP=ToDNyiLj{qxWu-7PIITeT+1I0(x;# zP_ia!`ud~y?jmb==hIU!iJVfqj>3Q`BNU~E^}sZp}@=k7aOpol;fq= zB$xAG@*K_G?Z#KEF=2lBGE(bweZ_duJoZIR8`VzYM%_)~c%@Qs`OAt% zLCZ$y6-8nXyzJf3nR(lhZRb5a9s6O7<-!@`pXTupr;fidK|;I}`1p4|qPAw1@$r2= zN*MD4%1#CS|6Fc0Ji_P`A0W>hi&D9}*B~LLa-aB+$p?z1+t(s9^27lqza`0U3y@X; z@=qo|TS$g1FfK<rkF(g^7?`a)kUK;PQF6m=Xj z#jxfSEHGZ=A=|DaGuwU@J{8DZZW(?@pWrOROhLeMcVCYLbPVSjPq>-9Sme&VZXZ&J z2aX2aLyQb1GYyU#-nJ_tfa-e9+`RK$(bDS}d0k%G7)v0ziyV=-z$kjIyg9N`pC+On zGe7@V5p~9Mb9Y|%_bZq)o4K*2a#UlSr+%~-}@51saPy9dg=t5&HV zcvD9Y+)L*7>VeAuCvMJ=`hn(!eY>DWvX7Q*+|nxZXE3SGV$yh_0+(pY{1+MZRz?p* zId1;pdeInUE7lA9PGAwR?=>m1QHuB#1cCIBz^PN%sM2i#8ONqy&gc78+GePPW{9TQ|)%g3d z^+$f3J`?p)<1?lsRo?Lqn$y+swtPOtPu>@~2)_MN&D&N6w9H z*k&HfwG?>6MvuB4?+MPplldtxMgb^d))2-v1;bun>J5sJC>X}gu1u#3t?_}@_G<`M zZhv09L_eJ8a!H}Zh$LN)a#b+Amml0pe5o_^^T1@&!G_EWRY&xF;4PO8Fj&JN|C(F~ zAedXt@J;s#Ab45Ky3J3@M9fuE#?LaWq=yOb7k|#@fhi2@Xlw=RJY!vMw-!ZGL%!lE zMBPEcsTK)i0kkS+-iiYYEUvC=)-jz*dN8ih_dr^}n8x`Js<}DQLLa`)lBLhhxLtBl zA=n1_!S!BPkNR4-d|;xT^EM?8Olw^w*=AEi+XHx^B4}v;C&=y#P&N{^NCp;*5xc+&qr}oujS+Ed=v+@nUBZv zk=~-kz7j4-D({Z9$RzU+@a6@Q3G;6fp!DzkJv3FPJ9#AgjooOEKVs$D?3Z<-%4nnc z-wHwrU+8<5uze*#TPv7FFpATvsBpUbO5J*5_xA;NB>jrVXDRI6Sh=)=^A;mRj@1pg z9$qd~9Rn6YMHViBd{QKvYj?;vWQ@fX4G z5Agjhe19K*Kf_-DGOKy;&*3cN7yh|Ml=EvO{@ncG@r?3}=GPb+X6ql;=j@9|u?h=y zoZHCw_Plr^(=*?@>L*}W>gwM-=JGi z>WX)e-Tf8-EnRW5`!~>o^efi%aWDEpR>D)A!l5w}#c>wnuz%eaIKy@Oy=~*M#mVrr zGcaw;Gyx1N%Lq>RA7@H(G=lv}2cW?I??YyG8td(S6LTyv1*tUD-`l|4%6K7l#s+vvn)%{87&4}Dl?B7*gXD1jb&1+TfVq-@i8+jPw|B#rSo#MjErnFf z-{p|^z$US?va&u9AY?Q~}${W7L+ zx6{k)bP-S5Ji=^XnIEY#R@3@zlyjg){Tmx~)&HqRF|Nr*Nqo}-tF4dY2Y+Fp`~U(4 z^PB(&^x4FFdM~`#Pt-5!vVlmc6y=D z^vjw4&)->n@3Q++zk=z1w9`k}>FDD!-RfifcIbaYOC<86qCr-$YF%lN%GhnzpDY8V zPrn=DA@M1wDQ_IaW!tyTFzA3`wC@oI4B{S1mc`6d|Az+BkD;r94R2*lXe8=|>$ZZi z{^i>2X3UYB-gZrC2u+3e>Mw)6 z&KzdPG~9B6NbEWV_({l;Hsy8ie{Vh&ut^Y5HRw(_Ib1mBe?Za$QS+|fy6J5n73F&t zO;*=gt56nG7`ua#+fg!E$h9I&FoLum`bA`N>u*cts2}|YExw&SptuUW2t<-2ME_yl zZT-Ivl$$dk^ORQx%kmYpF)B1x>?KCwV)bSx!VK}=6-548I5d-6RbWa72U6d}4@PT-XWf|nd>bO3aJXro_DG#{5QZjYu+y3&t z?f{`O#4LK!zhV>MD z2@y)`#0seW2jT;(n5ASfE-2m4dXmDBAbJA(MW><9^h>1u|4Z(3=i8C(SN$JGo}~bz z`U(Ih?P$M6A7f;SKJgGydmbFGg>boU$81))T$z1UO>yt~RA?$AHT4Po2XF*IP#fgX zFfsehE(>|ES>a@R1Lu_AV9TF=8c1zwG7k%}*lDP?GE{XL)51_^ZZA0-?oaY8sK8|I z9O6O6tF2k+v(Pup*}P)QKrh@V`f#Y@VVyDj=&!UxZ!MOFNvb!d?Et8VI9*L_zn;9g-0Rew!-hW=NG9m>iK4G}(XTNMJ@$_bL*!5hsu zfXi>E`n`7qim<-!ZT|;?8wqjq)GinZGF?Qtea7i(-^pw2ucQMe!}2y;&(~6Z@sD!% z1lrK|%1P>;XjIU5%H7F57*R=tSST+kw~8Apu(3`_k5#*LI|K|XU7g&WBrXv`WVJ47E)e_ zT9p>yvUIM=z5?0q^O{R`m+dZTdWHH8RC+ykWQbiz`6~rIYs4z9TmfKJ#5_2U%;CrnCtEFhVYZKL z7>%WzHtyj<(wKX=kmPOK38t4i3m7{HK%`HMij1OEeKonZMpK71nnJ{0!=PBt0DdJr z!FQ;1Pz1IA?QDfhl;-=ySG)bh%_lxzw>j;?GOAnxs(&6T%~jdc-eAK$wR_C9letQM z>$ze*u>SSDc`WS4iK|HVi9+_6&FKk^5rD1K85yud=t47&nsvLEZ?)b&!G7x97_N|k zO8N;0R&fWLBYnC(u0oNd!D^J2GBQ#lT@BA{t8ph+!BiD{2#-oWG)IASrcbx(*$_E^ zgGOR4jLaOrEjhf0>u6S$n8YXG3Mg2v^ci*y8yJUps|hyc62wpvY^>tCn_VX&InWUW z&7D5Ru3|$|PJku2T${7U$B54HTGXpBV2kc@{jHDg8uxG!P6l@Dc$IOL&P)Xd!rYy* z3@3pVXfe&A+Rc_*#U(Qp6G3~JA)DZG_i*_wCXoy<X?aEv2%8tJ z8@Xtvr5e?;SFwy*VN=~HBcQ`xQ)723fDUVmp7gLRn*oCwC7G1j$kjG2Ju0)2i*H)$ zXnWwb=qMd{@8oKnO$1)WCdOq~W@Ab~9A&KH;+)+Oyf93fu*+D*CK`8gwXkkex)KUK zI@9AyjmY#k)8lwNBXh`=Iwo_-nd19JeEK3$nYie(=lYcKeXdm@{g%Sgmer(^r7dJPi{mR+EZ%7T^$gpJRVoWsvMASN zUMVR3-KW8^sh1VUn7!C2y$`#FiGD95mf1*RwAAFxM$(DVicXQ(W}2 zPIL24G2q75UK>iIz~ClOzre)HnxI_-`X+$Fx?=y6xBX6}@KrfHvXaavBtBRTUCWl4 z`yPd9Ul5wAPO4yl$hjtPC@4LvlKKqBj36rJ{G<3H#cFIQe+>0d+Bhcj(QPR#U^kk7 zcu5f)*N;;Kk5>evmu2;n5M^M&_{4K5*87NRJ0IK+b$;*ze)RC;V}59O%h!W0e(-%? z31G!rFYm*sWE5bqWT(?iI{(sLLLE#e(=m#9&)A1a~EZn zT+y|T_|SLQ;d;Fk?yw3IF$#~9!fv%tbVZj@A>{@5HfwT;AF2F$#e}AIhDDKYg=Y60{AuBos@^Z#amvX1? zB8ujsxc$N;Y~)H#<~*bd)Ao>g%nwD9xG;aq>3Y>~xZ&A45B1WEBJ$858L}B*<*P&Q z`Uz{y?Sd_3?79&wu0l-TaVnFs{FMr@2AoIDuJHw{2KP>Q+pfaUuKNX%8=vYOPRYqp zbL~2TAf%inq)0KFoN$pGDwz#@gay0_9TY^|{yRbkR(B73+xV7abmvHD=`y@kQGXk~ z7uS1ZJ^DzjEM{YU?u7yq*q=7mJAbU008R%QEzHN2VE#GE0&_Vqr?O>wM?Z+y{osh^ zvY3rHT0~5_vJp?R5n~HCUxdge|G0{f*yPl47SiR}a`b|VinG(+`jMiSU4x)+0o=Bd zbV|F8=D)3U^!WnR!7NV{%)G}+A241|iHlI;=Hd8`#c4!Wl9Tab)9*`zDQNIhmX?az zRXY@yMbMgol#%=?f-B5-K3>k(@_EqIe>(*R6Q_0HQp!<}kye@E&=c%M&%LGey!w1U z^nC9j(jV@E;c#Ooa>XK^AA(LC+`Z(OPAr^+&97M{ENbL^m<)NzVG$X2JecW2CIWb& z9$vhguXxrPd{W2a`gII`7$$Zg37eu)Bk}uX{N_6oaTdj%F(2Aa(p=ch_!*a+!>qDs zYqz6%~;>pb9d z01n+_7^}SN=X<>C1mR7)jpp}J%vcjzif0%U>CewT$Ym$CLI&&(9<(#h zL1M8z5hOJl_W_Ip!zvbAxw6P1sxp$rK&)C;`(BgG?~`Rs$&nm(I-Y$#Mx1d$Pig)Xmu0do6>pMTizT=*W{|hXBmT!n;arh3z2J;miLV@?rgHS#T zI9QSb4xY+w-;?6IA?MX~d2fFWCDNm3K={44Z^v)6LEcu`fbMzf%g(;fLG@oU;K=;i`!r+;vu5F5#-`u9;EUr)e zUs%mX{S+l`Pe}0~u!pIXL11UI_g3;P`sAm^ElIn!~@MEEVkMmg`Rlg*Du3n zVtoR<3xa}5G#h6^BgSmJcMq~37H*`^Q}p8OZ2sER`784OhjArUvmzfrWw_`s=DR%z zP5&H)cil72?!@U^L$%;D=( z?iGjGi1bK{{!-HAusY};ZPA~3DX$22lHj;`?=v9yQWsvHOq!!Hy;c$2iH1N7YlYc8JW!8-|2qkXg<0g9O}5vy3dHV?H4;hl`trcazOKU8B)3f_jd9ZOVr19f#~ zx)X5xscK_>(1?e|Jm+n@87g19-FUg|wTYM<)Xfih*IbRH+eX#JgWlUe&)hxmV^>D- zt95zh($U^_ZYsdWy-Aec1nFH$Yu|J5tz+^B-@1sYpvosUBU1KOV>AxBrkeGNCcs)V z2Go=-gXqPpGuVxyZF2%5IN%aJ#oHzC3tiUQt9@?ZHJH}GrQ_x}PnA-OcT&?QHAwo_xsD!f)fQ7E~nbgJ2T|h$!qKs`J z9nh6N0+6NJzuQ7UK^f^sp=x%H$C%?Y=6mp_?+D&PjQJhj16w7>i~QL+veju0S_N(} z?&WuYD^oV1^ZdqdF09+_z5P+J!+4=~&lqq$y}a(D^kgbxBVWo*c0zSWo7kM?Y>4e zihVVS&5Dc3h}on3Ec72p?FS461_1KAq~E$v?n8nRw-A9k$QhTnp@|ya0=_16IW!d8 z2X~mA-xH&Y$IY(N4VRomz?@=Ct18wvXEEE8%|8kacASc?3Z0eSv(7Nk4M3&$eON4a$zkS z51@DhiOp~(V_ciq6tdQ+B-=arobUZ!sDPSv&F~T4oW&(%wp+o zF?HVq*E>dVMWc(OnFqU}zr7l}xi>I?2B0k&gz+1VmDLEF8Fy6i^V=bOLJ+8LNr&Yn zW@k@_r*c|>roU}eG!^{7pb!QAiO?n zSZ`Z99x@vwx|X|xU#Xj-+h*4z6_AKAH@iM}M+1Q=+%bF;50tJdrjQ|p*kaKfzDMAg zN!*!xpq?oz#$qlN|E4OtGK@s9X0lPHj3^c2(t0RF_vmesNxYd2ET*NeOqM}9wOms@ z59&f9s;PjJUq+{+9>5gu`nYq0)$2T1p!@dV<7k(-+>Zln0IhtNr`v+Jb!SeA=R(haY-Te^A;b)N{(WxXTuYs{X}6S`gs| zWOEtLO+ZJDJ4lEjL>b7&IRy%ZYHP$Se_u-3qG19_K{Wn|hs*|PLGBKIdD~t=62v2n zuY!1lb9XEv*rIq4qa_~X1#*a&;z0&0@mRnVOFS+RQw{OB9Es@H@x8<&%n-QrdS(L) zXz8nM!3dWKh7yTzfvL-%DrM@&v|g4-{7~2}Oa(MBb(NxmtYjhEtB#{Y`5u%CH+W|Orw`o*1xn(LlT zjgZ@XB8f(G+FjH-&%xctbS?=ie;fLb9dzmP4s?Si_8GGy#8-dFnJK)Ptizb(UGKDN zW!`p{2H!xUTmXS##GP}6U^&g7V-AFYq0kIuxs1*6-1UY1XKvZLy&YS(x9;p|PMzvq z@0rz-IkYG>0iS24JlGwW?ylY5lJ(5$f`2p$TXbg~J~!V`4wKMbgc7hI|1Fh(D*^%qVgWj{&u2UG4Ixis?H)Kl2!hK$ zJqV9B85FmyCc1j^Sj0+K!|BD}H2j@|zt7@t`qqZfj1l>Y1WDgYVk*G^F|wbGoS-)a|bv2V5@h1mjIQuSRcGM zwb|XRwuaMfIR=dhU;@Vdo^jhYX^70bv;rV0bQMi<=byeMYgX(y)N12cR%*R9<6UWG>2 zi~#Mm?_oX#dLYVWIsGb78H7CsE9}EkbQ?kR8%vC57IRa3z18WsKZ24An7mS@*D7y% zR7V(~F--AtFK8Q1nBwGN?e^LOaOgLsj^TNQIifgnm@#@c7IU|qxC@K8dpV;87I#-> zpWj@4D>kEOi0GLA$g*355%V_^d2`{11fAR}dyiy8TA#GDpH$iA)fno{2o3;1sz)ZT zGv`A+X&NdsA32)h3GW@Ra_YA%RBg<5<6fEy%)F*h_KaNG9nXFJa01t%{X&%m zw(^MiUntM3kIe7c5WYtU<@!9K?4$yOB4tkVI=k$3EIUr0E|eX@{IG8;%FGMxvKK1K zs)Vu^`YG!&kFv`irDzBU4eJVJkFmKU5i`?_T8%a#bRfemWT^Wv$jsW-nN(*j?QiNh z083+DB(o^==6Xu0#cA^^R}u_v^;$TZ#`8|^e){Q#IHWcQHlwbBV7TPr2| zyO&yIzx!P{Z;g3e(sWHd2znN6;VGTWp|bSxHmE?|ZgSxu!6|$;XdN3$3;zXUk>irp|O7P<#J zu?&?OVcvsb7_LFZRHgCfz()IP4@6)L`lJ;tY>M5TK~F zoy@T?_J_|+d>DQE!S}-dSPio9{ZsJ!3ix=PQQF7#I_v_FY10u@oYsqq%)aX4_*g{~ zq&B)47X|7XLgCb;B?6nPC{-BOzQpl&OLdoVnLCcjoW!uO;0(6Ng7f7@!X49FpdeFv>-D^6o5YO8{fpIFxp>3RpKUk;%VZe!Ep(Wg62MjF!&J89i`{WflF_qfiMFBTGYU)Lo@WR&;6D z#D*&nYPVwsa{ngKa&hMOBXIYfqUai{u+@JYN8G@`8?P$ru?K|q1V!DP8vE+T;r^qz z3wH}`foOB`>r3Q!jhf@u;hv$*$w}%F$BgN(E!pfYN}@uL*;m<=zy&4hnI+L0+m>;mBA3BtEUMcemW8OtHfUre|X|(1TL^CwB3;Go}YzvfX2sp!6FnS3?gX`fBKC+}tpm)jg2e5gR#k2Db_~ zo!au}Aozzli+2;Nj%pj>RaUfuu zW4xb~@;*xl4*(90NOzOo3D(Gg{+!}YB(6_ZvU`*it+b1tM*UEO$g~8+< zK?{3=olX;O1s{0VQ1P1GcDo)&FjDiFl=tub3wXv$-58mnH8OwQE+Pe?_D2$s)JkTW z&)*_;(qmcTz28Q)Ch#SIQ<6Vb7hi!>$6DM6A0I_6+B#er*l2DOUiyH-j~xJC6IiL) z5)a^NQUJlot4e^ZkuC%*0Rj@RWY%cjZULdAk}#(#f;yFGOaw64i8p&%#}zj%D5Xz>gI*(e`}5On7o1maJax~ z*dy8TQmfBHwqC^#D<5V`0{1xiPga2JVx~tj zFo^An#ReSwv1&j<|A!*}WMMK_K44Zgl%26CPz|eDsc&*@Hp;BK!!h`I7!E4zo}9$EioH8CTSgBhqCX5_N?1ypEjRB`a2JD~ zGDQzfS)5xSaLPE2Agz8P^UvGo7VSxmLIAmYucR_AB z3xJ|X6#81lu7XQ~MKd;tw=Aa6IF2>wXdX;2SslxKguZND9-6A9zQ%nKXZ=Vdjt7U~ zDqB6dNKvyGeg$E}ZNPP-SbW5(W6X#i1z~kiweN+HUwPTQMKLf-I#aAm_;EH6=fbn5yji+||&YtN2n1fb(@7@$4Am0VB z!f~jn((N>Y(naF`_d%O@OS4BQ;w=Z>(o6dbByzFT4XC`=9RwzOMX-_QqV{@Vu0?NQ zu6bK+f0&o{#eApm(K4xuL6A?fM`Sc0a|q0*cqhA>6q0>3v6T4)ER0AM1FxeB@|ij8 zOnV^&L0qY5_hqs5Z~m~4X&9quKoH@u6Bi4^Bkep~?5-X3#BtH@a?J6LYu}R|0|NZn z0N^gfM34>lwePuUl6q;vXoTW%Ksn{ik3^K_hIb8b*>>KeWy_bS8MGtogjE>RoE>S! z0=h6Y-g8s9wzCQGpmSS{>iI3%>gj+vUrQekm^cj%$Nb!<$3l*oW1Nd6f~UDE!lw)H zQ1|=|TNgJARd&Z&-;}P*J`bA_*hWRr(2B8WMP)XCM$r8x-ep*$-E-4;zF%PZY;7!> z;9wK}7O(A0U>>sa5md}wa+n)}H&E|#mzE=P6v#E<4s@)q{}UTa{A&G0>Zg|yj&pSS zas)j>H(m!7^0j2n9h;s@dRj6wMyJoKd;iAq#`9BNH2&W5{*S<5-e4Wb0|Eas%b>kn z(3rPayF@-wvHFs^nRlI;zdGmVM`fTo&M;!)b26KqurPj-!%c8shj_AV#^E$ZaYKCH z4oG2=RE`c9i!DlOI1nbV3#Qb*;$7cxDUR~>j7@z8pQACZme=N6vh^5Hjq_Tvu5*Fz z0VXf6z;FPgAKI8LV~OMNE zSG^^!7FsT@R@B@kd2*dRojzpiCjBjI$oc9INHT6~0tzAobzxA4J8|&P1@wM==lr3c z(ydJ`W{?B^BitEr9)f+GEyVO~Ui|I>#S3(Tr{HXjIuhF}Hy5yB8!kN(c*DTiikK9} zvF@K*gc+_7XnUwwdIx%n2F!(8QFEi%@?H`WZN!dL%>TvNk#KtM0dDMQOqS&y;ogoW zET669_KryI4t0WRHQ1AY1+0gvO*N;y%qE1u^>ctnwzgPTE=ASQzYQ@63Y2`B^FSMf zv>@wObXiEbiJ%ci`w{NjXaaWGx&frJmqNA!6p{Ywr6N-B0)s)oLTa67v5|sDn9aQ* zS9S_gCcyu&kaCG$kaB^(iMs)?f1xb0Vk=kZ<2ski1*ti^fRMNK*~sF(TPWttOcs$@ z&XiJ3b)+J*uf`T$I4bC!dg|kJTD-Y3$jsG010ljKR(EX@f432wuEcfdrW5l)zLLR% z(Pfg1E_k^P3=2B^mp75AHC<5J0Exi2--mBZi4(Q2v|#gLCHqDOM2=QmYr{h|_t|p9 zV!ZVx7su7%1NS)%_{qW{;E2p>O9APouMp5uZk3FqfpXr|xRb|LjhDylRIlI>gB`{DgfIwG zCOXs0p#^?pb56%~YsEGDXE3Yf{0iH$VA-xBCfgZGVJn$!h?>5u43U(ur&z7ulc5U^ zuU}@-CB8AI3L{j5q$Ln!^nB`gn3;lm!S&{1YZPjTx{bWsg%yqa~TxXtz0TPr}7wzR7k5dXdS4r)i9-*>tHwt`FJLW|eobU6rF}?>4If_x7zUZB}_6RoOlz zJppI()`%8dsBV@mcBmv5&OE1Ba+#F;Oy81{Og1b7LCPA;m6Ct`TOT2jWR|?XP_jx& zKGV0PB(o$pe=3-ol>A=bl9Eh1WrLj1`HraNSNfKeWWwZGXN&-9EVC#~!#M%JGA_CRj=hL7{owRC|Att<0X=z4r>Nr(6D z&ZLIB0U5#wMAhN2l|^45Vc!29SyTx=gb)s=Q)0)sijdPq$QWjPeEFmn(+?w-lzW8k zL6f)#2{T%Ng|k9Ag{D#Rbe!#P#cby?uu&>981)5!g=5T-5fB{_{Z9y?=N_To&?J5X z-aoj{qAopJUar?pqiI35w`K9pQ5?v+hM!C1PL6=Qb1!|q0OSQOSYAN`N6sXIo3M?% zQNZ)WKcnSOeoLgpYQBUp_Wl{p2xznl;?@9C|4k{#B^CT9EB~05+#D5`AYnGzw0heo zf%h#laL~ZpHU>X)kMKeaI3#*g%v^>bDSHt2fWX7laU6Y$f?g}oeYRsho9>Xd_cv@X z7T)QV&P9Nz*M=@{+mpyP@G78dO;of6HTx*RQt+_o8cLU>-MHcb58GVyMv$_ za0~<4)v<`2xOov+ly`I)x;6|eY(o+x|oPhh5m$ zv0q_@g=rDSbjrwUWtnN9@ zXTB+&4ruiD#l$Ae8WCV00C5LNr3UR;y^{OtyGL%7Z}dA@6pV_YO_*At{G{4W^mk>- zmwiM>`RpUyJg%C{Us>7UjmnSE0ypV2vk7yPNDL17I#MI8Zf6mi-X@*)HDNx`e-YZ; zCY^>gVSc^;A~d#5IxT9#y!^-_xx3`N5bgkh`rx`$sEBd83!k}_a-C5AHJobD#6VM4 zalE%t$D25*FW*>8)?puqn2TJSI(U?SP5j-x|3!gcBWcn6YxOF_1p_I71AZX@YB?a1mwH{fAh9Bgr)@B+ z#vBvXaCgyhu!W-3DgT9;`umxy)3;BEx1eks}pgL_`YYtnz1Q^8(c@@BYif4nv1(SsFU4iGTo7S z59!?j{w`1bi3xAwTp*rYsa<^9m3cN_hZ%MH=*+gWSL8oH)!Qb3Jf6~2Skr4zWXa;L zcA&Z+e?P_Fdi;IUdM+JON!^NlT%ZJ#JVFOwsmn0b8VN&v3&*ifVw)pXfd-WWdo!ZUs-G;ke!Z-X0fuIC;%GSPzBZ~-Ns{7#tgKU>Y2v0k) zEffOq6Yr9hlrfueH|+9#!F;MB7thaFurHKG6n0;zdtBxjN9GOe=i3*;Uof-Pk=do) z{1^}&4&U%!xrS@Y$~wzBBS|;#R2Jro5{_OIss;j3k;jslKkLA9Tcvl+Pr>fn+}LMv z`}gt7*fjA|v%?u#gG-Os@s}6t9JXGx~*7l2S?z-Q4S6+!}O&8M8Wd1=PUXz6qHvGp=yvE^w;ttuTQes@R6P@lyu2Bf<=z5nOYcAQ_2YQ2{rv|1GcIN2mBe;P&g`o4hY61J| zEQc0sbuDSS$mEKBLGY{S>vK1NrI6eF)~PtkQSRS)w+4s|?mg@reZ!Ty|h~-+`TG1(QqzM2?-a(&898H@tT{ zmJy6KiuL{jM#J42RuHhIM7`t^`}=MtOSkv|3DMx9ftLd)!i6BXu$S)`?uE&?D^!o} zB%5RL?(yhdK7t`WCUIlc1F|Q|59GAhDq?It4)eTX3&jq?7{w0NAUdT<)=0rL?uNkH zEcT|#gc}p}o`3hYuVRB?U$Du!&w3~qZzrHF?5EXsXLZjYAJG?l$unSqi{UtydrKms zY9c+hT})(2We&L&&PG4_BHH>Mj7E{%3v#TXl zHLKQ&eH?&``o(60QDg@Pa7&|V4?qv9pWgjP*;F5>!_7jS(C?NRpY^t_$B*O)bD}x} z!2zspYx-Du505$8M*1Pzk=eo>p?eoWZ@lZh>aBjzQ=hS|rS3&<+g1pxcm4J`I0ZHZ z<39M)J)#8{#Es&4vCMQWebBppu9FYA7vwkG?Z6HGh+pPV5rT}}MO^8C=X*WKw1V_p z&4L>?&30j*&RBvcWfq~J*%G(-`PF5VGN0_b*!wHA3LWal1*`xeS_8iv^CWb?9zi|X z8t!dh&yJ@~6?$)%VZzz=K}D7m%O<18H)WbT#A{sa?}LgqPJ}? zkWiF>0rxQ%;A7n`B>UH{cjR2>&^B{Mw-|d$e*(B=zr*-QE^@4)#9bd@vyunPIP#4YVe()W(*2cB(l;QLHyDy6)lHKuxK=lH@%$D6zp59z zse2L#Lv*co>tupf1DUjpxrtG6#TME)r|bf3f$=@nvlbmuNA!xRt|E|Sy#Gtt?!Qr@;&N)LC;M6}fDYmIUEHCMxo z<{^>%e7P|RRU|w8cRXDbu!^K#&6GQha!OcHZ`4bbxXZ3u|Cl=erfp2H&F<$sr$)Bi zBkb}a6bTvUax_{H;yJCOjB!RHfKV`8;xDLUe|s}1f)}A4+hkl9@UEXNOF!4aAD)sP zd0-QEsC8d(V3Q+NZ#)C>?Dalc01b+K-t2IkXN=Fe&d1#5^SCI<4amrx3IQ#9i(aq< z6jS4<-oK( zBLQj+2Yx!Qm-M9Fuqhr6OsK^@R2ZLeLv%$z1UOX&kCGCic7JcYMTSL>8Wyo1C5-sY zySGw?)h4a39Z?J{eq0+Qe(e=q82$Z##KE5yn$`sW;YNyG3Z@MHJ>V#@TU#c1(5bLP zQnnqQsxSK!`fe&eWFYwaWmeDqR*?HBd~zivn{T-Vf(1=oXq1B)+z@dZkYMwNvZX99|H1~8hawt3yV41R8vmXpZ584BkanUW!^TN znUeQLeU1FE`heaD77Ml^OUx(TV*FRu*A@FEvO!N}=>%E4W_n_?^qN1T6ZRK+LZ5H- zM59pY!wvv+1=iJJ1GYIZHsd6t+_AFF2^%60U=F$nJM-g$9368q_sx!G?`(5G`;WNl zM$O>6=qoNy{XJrS7Mr-xr>y3z6i7Y0g;Q=Aj>VnQoEjoWDeS|%` z*37ZbgoztJ=zAyu#`Q3;XQ1$JG<$_$IY@+Aw`?HFTv$nUiYHRHM9h!Q69S;6*CQP^ zpk#!i_8a?i%g=F^YA>0KyCqTMH2r#VcM(5C&PUr+e<;m@g;H+;1kOuvm0qo}} z1o_OK&5&B(8xTN0?k7+etUl2SvY%w1WLI-dIJ=swq}kP6H++Ii@!MK?G=Mu*wzV>j z9h6^Ov}WIB*K!RyyOs;O+giCcOKX{3%f-%Ztz5U1=hY0aZfmtenAz0~Rc2SOkxvF6 zdvQFj`*8fPkHHqDuSD095ydwqI?P-DT~vYh87lEt_q*}3`~#rHSm^@&karry;s$K- zVW6hFjFlebqdSi`?(p#!yyLB!{epPOX?T54?Wjve>`>+3_Rv2vd(hI?J#Fjl(3rX?2SAev{H zo?VN3A0Wf|R*GsBHcQ{)g>|mnAmWIPh(XG7H75Htuo4I?$+_t`hGU*etjS&H#6VC* z;V{*G9gM@fbJvySZaLh2ksPLun~yw2Xv`Tcp>gI-kwevS^FQpo^aMFl9XDI;l+>7~ z2^iZzVSo^pThj$C$2+J0>7+B}y(7vYAAxQo>aIPodQoU1cSy~cJU56K$I=dd8M{Gz zr7Q%{@s80pDn0eB#?T$$D&a4MvRIEG#Jpt z5DkU|R6-LX86pL2)i_P9Qk((W5=fi`86F31tFG>=dRUCiq(H@B8Y%-K;l+i3oI=Desc6F0axQ zsLPYq2Y``^ylQ`pU)|Q(xU7k&Wh%_XqVM@0F1?$v#zsWkG1qkgPUJUz?_*8ldwe zE2yH$icJG*=6f0;ZOp+vmKYW|f*0t@bfzT*CRFQHIG_KdboXz|?C#zX(A_Q39Ko?Q z^?vnF59^#LL7Qkp8PU5nu5~+t#f@+x1vcW@LSDMgwbIY3PKjC-&-EsqD>L$-G0iB< zWO>!oA{;F_;TE>s7*kZLl-I!QLqa^?4thuxDRmkk;Q>I3)+`rYm^t4U7;OM+JZ5c} z#nRSrGQy?W$ECWb(c+z9M;RDK18B0=8JQhp7xl_w&$jim{#3&8yO9EJR1aPznA$4r zzD>Al7BRN8rb~9E4N-bX1H}EOHXYU7V~f3m;6{#|)W9^YMv@V&i|)hjDL4`Y)LV>u z=Fmm3RMVgx*@J?oN-+Fh{@cf9dtKJ6o(FbcUGxfMe^P_&z$vht>m#d-{vdJQ6xE!R z+jXEXW%taKLq)Hwels%b%;dq+xn`tH8?W#m65iqE1Si!dkP}(&=ga8_-5L;Zpg~$| z74MMj{1~%TL@#f=ey!BX)afB>Z{%ArbO{$xR4F6(l>;ZNp2*xOoJPi473ZA_iXh5; zQN%plFr8-R9GmHN1ttjmpB)Kmur#(xlFr^ST)(-$A00`w482^yCW7zHE+y@>)nQ2? z2E#-b45dSg1f#^P9XBBd1~5u0D153%Hi8e*f(m*vjP3FG-=W%jB?GATD$kazu8GEq zoWG<8K~Ei#^Du{?i5~Gb?;~X=XuziSzUMD$IJA<<@}_ji#lqIhDi2iJ0Nx(MeQLewGD^tSw@ToWHyL9 zt>}>5zW7@Hxe!m}A+R*ZkV#p+&^pkX1%pC0@%*u#gy6}DvY6p>zW*E{1b57|>vV&u z(?C%g-W~RPjenxVo~dJJSE|W6wmY#Gr%J5--3B4496CRzY>e|VJ{XNg3J+cs7nWBC z&KC9b<+n>aZJ!97!y{t&O?T+FFZr^3=qzp|vy}y&ZH<}#Da4?q?=TBj&oeW2v_7q` zkLc@t`np(M^bW%Gd2Bx?Jv!i2S8Zo z9HD(vX=gXhZEfq3cHXbAetn&zuNnHPbUXJZ+W9MzZ0EO=UkAT^{C>ypb$(KWv479- zsm&)rQ+=kjYyxm18-Krk928VMdnLr>vnu`WKSPIlDJ#Bt<=OA(jzU=L@cFy>fXZ-0 zjd~3j>XFufHQSd{HJenz^~ZgONe(ZJruU<)RcTY?``c2zyfbW(zGa`CxG}lbq-=^w z)Sy1fV{i^O+~PO0{lsf&872R1-}=X1WL{=%cO>l+VI};SNH5kDH^V{n3E{`I1=3?T z6I#H|*T5Bc>Aj4ntl(vvT-jGUsw+3Sxm8xOcSN5jCcYu$5Fzn;@Qd377&)D=lS$Du zNfpSkHaN4Sgl(6#Pqp2RPA?Dgux$DZdUFg5a^De4YCCL!U+AYy6rheG%4F-k&}Zo@@JuSHT~x3-zVi$A zqaJ@*;VU&Ng?34Vq+m|rE=jzCQ(ho(EZqwH^Mq~HZt>+6@I)RI;T7F?4psRc zvG2uB62qd%u3myvt;inse>mNUxxUJ<&lww=EpqRJ8kidenD}ni-A_hPLqWNCaTk-D zl;>;eRNSz6mD67!x>;m_Qx(lzysR$N3{y^rwM`4t#{y^8$B3IbB$CsP#MCK9K-w8n z4ja-{ROX#MIdNTsjFHfh+Xnj6FWRD2){D}ut5~#h4ORD4=kE5g{aq`*A>fw4??u+*?oP_M``I(7^$MKkF-5W%R zd^;&R(%28!Npe4Lie;l4T9NvK+zd>UcF6!r`sGtx?crs^SB95?FEzS;5I)^3o=XZT zZ%`c;N*&H4Ok>6@!3@9X+h#@X$+?G&G=f$7&ovnK8^55*9BZQtMcKJ7u!o}TM6y;8d(@mU(LK?3U|5~whf1G z5Th7JbhJDP8xj@mzDs(yu5ec}-*DnAx8Uh|BpX@MmLjXK(9K+c7kI3|3U`V0iVOT- ziukJawF}hRNp>SWEnCU6aF;02IA3CysMVrgR2tciz_6W1am&SM$f7T@D%A}aNg}O; zjF9LB5k5k@L?(1-K_rmOniCR;wNd2zY9HR4h2s*8%C^ZwjD6+tH8sf;Pw+2(nIVm@ zQk;H^F0j(C7uC8hw*mg^Itg}*X8;kEme4VxrOv8SnFBSv2^5qPzAFC({?ue9+h2Uu zH@iWBvryF0GQ-bdzASE#-qLa_t1iJ1LaRvCj6S((Zw5dtqcSe<;ciOZ@PV$U$s+$? zXqR+yk}$5G`*(BxauxDO_TOaI6nW?R zC(tVO_+>VjEFIY;U`mUFsYWf(0=sj-`$3#vXgVS$L~)YXtj!VG4KOjV=amXT@Lsi}tdPmfpZuexQJK(Nj@D3{p- zxrnueSg2@;rzzG*^;b^vY`eGluO%V^FXP7XHel+Q)>(3Mx8}$#wbjX}GQtGfE%vk3 zs26`vMUd8IrPITNAyP!7G)4Oz5(6DcVKr-OsRbf(Ir)xG%xiGanj-O`0I}DbVsfxX z(3u~Ljz9z9Wr6cS3Kaqs31If_eqDEjoV@)y>#@k->YAgJjcg1UuoKEPkQbZ38Jx2q zeRXu2-B<5{uGCR;4!~7xxS%vb5~o6*ZP@yh>zf+%OhM`+y=6%srZS__e?6p2U4Na7 zdsxWm^Vr<_)bFvGl%k3KLOiw{&1Yh-ikBT`7LVSg6&9hGGx&9YFpWmj4!u}NTh5k& z#QGM^v6T%yq!IOLThBbkS*5zeE(&&|pvteUNiyU4U#R1Hd(I}N_ycp<5SC1VG%nb* zmk^^dvQ+GirY~$re`I`lI0Cl=MKMGZI6v`f0?xWKsozAOdY7$B&>juy`Km46T(oDE zJ@>)jFHkSvXrSR!zt-EF0NnsEPB(R=J!^=J55ooOkwpBv;_-FIX;2sC+Z{Jol)QT~ zn!Y$6GT><`B6TR1ifKj+<2&F)BRU!bgwl@%9cke5LI6ia8qGb)}|;&uOr5iWTyS|M6&vW(3Wd z2~fyVqztpxT)or)K7L|C2*Aq3-YN@Kqz!AwdSPwr9@gIFREh4t?13`z2x#<;<)%=> zGBf-VY@{c$PS{6EmBRp|m)cxwaQM5bBFz_OAu|e~MqHncKJt^~)z7QRmpo+vVFgyHrk;}T zebYZJaokF${fzr1{6ajxz)xg*N9zCDpK}npz1;dZERd>WQXiOe9ue&iHsf2k+uhN* zZjbaz=Q@#IlLELh5jR;95#pFZ>ZU!CQAhnOCRW&tN>xgrcHKFtss^ShPi6?{j4Y1j z@SDVMvf8DmO;Lwk4*eE6>WHzw{m;b)JL{8c)DFFAB70DQn=eZg=!?L}p}mV}?X}PU zgy#JtxSXRrzoQZMS?$Xc>L8BBuB>PMlNkQnXxWWtWz=(;o34 zbj=Y+3GEgCZk&&#h0h1|_I~=wv#p((iF)C}5r}Ccg$x#dpdCvM>5$GGw@A0K(x?0A zucnV?ew~e8BE_l?e+*PM%8F{0dXBbhfgzhXz7^tr-x^YyQAz%wVI*;{V6bu7k(v$o3<0jwA|DDDD5(u3$no2 zU(E7he-*^WDz-PNdZ~>2T(h@rR*s9UFZ!92Xb9&x1(jjC)JW`8oJj0RssyO$(Z46d z$;1e;OlE)!y zXFk@y9Ks7}RXb>Zd3?q^XQAmle~K`Pzq`mT^I6@e?)ZZ1BD0_<9=~eTMm+_{P)Bgl zQkT(l4~ndX05p|nNv7Y|nS$20oSG>FR?FXCq3>d6U-@Uigk@ckv1j@GeQ#8_nBq%o%hKt&8q5SYYi>SL0++TUx` zdR3%0{T|wrRnKvX*qZd0I4DFkm@xHu2K6Tk-71Sh@R6Cevs$;Da@xezgT|85OKB01k&@EiC(L4EXs|Q%<@7opmPk4 zH=!B~3y^V4Sz*>MDC`YU!<(OHJ0<}o|7e_W2*b{q75N(0~6VthQy1O&{c|i!rt2L@bCt#WkzO|G? zE`Y}zQ0@a=t+}`g-{jO~+DIx5%)u|@aZ~1>7D#DXC`FADaUg>y6B$@zMIp{^3OzS4 z4ouQ5Boz!p5}8zmt3UjeC_?VZX#}95J(Hv|RAg}?AFWVlo}&iY)S%yF^9{)c8vscB zB;-hX>k_gdz3O83fFMYfszJ$f-`!u7IQsb&1IQMBaatz#YM=Vn?}^>Ve&M&cqlJ`V z`?i+myp}6rfZ#LgvH9xENm9uSF*q9KtFKd6d|wK6u|UTH-ueD#gmck0T-u_o;Cy0h z{g;N9SKJC1YeB2Zxqvf8ZTkl8K}b`^O10wxhhqn_trWwK$d8KNTC*f>zfEItM6*7! zFmXOkV!b%G<3Qg`c6w$+0%=LB-$3G<)O1qJ8CGQblairkPn~Di<)5zCRTi^MDP~c} zb8?dnk82hHw@fSJVI28z1kW{&!Pb17zk@X&rsne__uQc!7pY>ZN|mzbfXFEy7aeLC z^=vj-)rIfZ5z1s;H)HkB;|`MS#%>qx#xI@)YShaBs79qegw(5ka)PVXtH#q4U@~TJ z7`YDCM$3AX+Hr_}>XmacJlU;3qc5L-F1 zS_;Vk*Fg2c38GF9csf%>yPw3Mm3 zb|$nI2|~~BUFou#*`*_=1B}5dC*j9L89lJF6Mjs{S6DCZK-ly=Cv$vJM{wZK#)2xT zDW;zvnQ6j5U*5ekOsIN&681(54g-@1g-waeS#Dp`Zjr=nW%}Ud%1^$u3uHpYdHxori77PK!3BRfy z>C>_7w!ZwbKRe1tHTD4sW+D$}`m=OMN+Kjpc6}t7J<=VrV&P`Rf|Uy6k8xoCgt1O7 zCy&%6;grR=oi7$kf{6Pv;j%eIY`~aa%*(z0JPMj0y?B9*Xf>6}lM~0V>1fjJRN6KR z>Z9XV8N=486YZhLRtnvBOW5qNxC3oCsKT*h36i9j$A!P*JEsLO+HvY1xXlvDr4IV% z#R#?)*+Vzp(_)cYlLWpHodMW-6xlpQ0UO~QziZ6O7&|=Pcf1nB0N$k$_?k(%_`HKnXy#YT4efoi=-G* z8T)*c2=moNy1@8}Ut$m87JCR%LKm4$1p@4_z<3e;Z5n62TpJ$8b&|E4bDxG-7h@Z< z6gD9Zd;e4|b_hOXv0s8R#YS!xnYOrh|CXbf2|48!nqUIb2K~{5)o15%8&El?oZF4t#u5s=n`~o=i zeJx34(NkyWGMEP?117+)lWWr+Cogh7iHmviVrFcyetgfVj*aOJw z%os90#7w6e{r^)`5?wOg>S?}2NFn_pXbv+x(MqSG7@OL(nyFh@;;w9IP)1La#5xwZ zA>K#T;u2Zxu}GRH#;mzMbS>74z~Um3%3=RVt6)0Jj45_^JD_m9NTwihi2@QNU&`B9y|n( zL%YVwuqcgJ=VGd}NurTT8`0wXTHDW_6OVBz^0wvNDx6li&N}!9>MgitSKOz|)D<5` zg|qN+lX;)r0|94z-B1eu(*7H_u9@C~BQE%0wUB|pe&dTcP!OlYhpq*pj66*lYW(hG zj(lsJU_49PjT}auJ%53E2bP1OWUP~Osc)9)?MYSY@^kIp z4vrD?2HGL{cj?e+vXoXL!TDxOyZR41JVD9L1Lx~#2jP>oXM|z8XG5Htqc^9Nh&edF zNkyM~nq?`u@N7?WGj}Sk&zO^qcSBqf1xJ7yz)q{^tjpC$Opmmv+8Xa)D6^C5kHi6Z zmF3YWS)~^4vcm$?)eHuK;vak7S<9*W|*pRaQl3uM7;$(=`Si<%{* z%{#xUQi@ZLJtvunNR);FG(-xt%%ZolsX`7_m}E`Sv+G~2&(G~W_e9ZOgDwHx-GIz` zW5k<5x7BN%uu&_Uj5Fs~<-aXi=cv+n*1@j>7S7s`^T)H*hN`9bDqY)Yk*4Yy`WEkh;YJ#`3-WPhJnOfN3u49 zE71cIos=1nVVb7QHc+mKJ4ySx2K!*hQb6@kC0IQP#3?Rui4~V`v->eoZ!2)Rz_iVWvzd&?;aDqlXNiJe5 z9nG|R;62@XFDE71H3e910V2+YE0N?bd0a}@Qz=D=!vvkTpv;go(m0&UtE+V9i#lkA zI(MV)-JHbGSQ9VxTa-%QOrtfz;z@14oTIReZzN8S6r>Pz0tIt8kwta3#_{?LKG8_C z%|?!u9aJ%iEMP29<$u#))Vn}(>_XpMVsSE%fOK#NR!Q%9>Af_8iQbQzg*#nOb0#yc zMc`O)qY!5UFBK9th3(k1O?pjp zxHbt}HO_9zO+!k752P$Q0x-DnC$F)5FV%2si9>iLee_Az`~|WAl_P%5C(E!=XFj59 zO9C*WvVYlWNCS5##Z?TAE)oZcYXdd1c%qc3u?tpJy@|xq5#4nJlx`V zjN8#P!oy7_&HxW5GzynmZwID9nCjvM2F?e(S@G$UI{!d$Z$+iLex}B~OpSZd@){L_ zWB`ZkN|=;?dsOP{J$`8EnH&t(eR5F=O&^+1zT|UprE-&xJq>5Zr{QPD*iHG#)$)JW0G@fo-{seSx(XE4(%g35PIEwI)L%&4a76LmMK4cn=xvqd08Pl&P2`d%r< z%|<;L>I7yXHr%NLT?CSKLOeuX$Y zB`pINr%wy=kNK<~d^~xY-OxVI_BMMzzHEFCB$Zn2vRwmws$vA02AI^mI}(+*Zi)tlp6+?BGR`C6k7+?h=0In?YO8X*Nv(BW*d6@YrpzS*MQfHo4R;8!Jd zP(}3nAn3~bU}(#Gwy35wxH*}IW54I~6Q>y3?$)@)2$sj^uiJ~IB53lA{|m3(!|7M) z`jMM>AUkzW%RqvesJj`GihHANXd_RG(55i z%EY~cRK99{WN!IMj!WT_3>i`1$b_44YJB|l!8lU<&&Ef6&;Og_gOTRKzm=Y^XJ#a z^iD%-P!@l#+ai!NDrMAbBQ^UMKcRMzvKIQ$>TCo9jzLf3YMkc5`b_Jd92XHzRcivN zQ9XCFaBv zv@Wbn&lvcuX`iNlr@}+zBWZn_m4{kA**XqyJLq5IB3c$37de>CNE&-CAB>C3hugTg zxKM)KM$e7jY8;FG;nlk0w8*toOW8|01~lN(4SX^Dl#pL{r8@L0Frb&V4(R#k$q>bJ z3A~aI9eMeOI!mg0%9(JO1`PFoVER8GTli&WnyD8GiUu{1gMdzH|`r%w|Wc=a&5)wdStRx{G%^OxG=`ik~w9zM~Y723wz^$)bikFj)#N{*NOk?sZ& zfNVCE@}0EV9N+~yWtp54N_oypLyYiZYfc(KEEUeK#>l^OR?Y~=b7HCwm@TN*dWoq?m<~y{4%M(jCGy!xW5|I=I~0njp|kyxhfn?Z`*yDfj3;C3J?-u;IuqgK ze8~zkGHJ@?E*ppwbyLK@fuUGbOithQI9;cOD-n1&7s4D9lu60rwR$tfAeaV;=y5U#0-@%%@ADgRT_Gm_Zq=UK9t zv*?&k;>QLKjQ6j=$5p@l^7zUcGQK|elZNI$fRBR01M5?^s?5_|!9Xf}PV`Ohkx?b4F;@|1e7XOGIavsz2|5B}~bjvtxc`DK6 zfl{sAlhEI7l|sBre8J$R7K zIDG1T-Kk3!Ej0vb=z47eKfWW3CQDtO=9_q0;CCOv1Hn%CeTTYXh0cM&w_>N4kJZOt z6w^CT^Pl)iDJ)Q`ZLE>nGelsHRg?%WCLb5a(QsCt)Gf{n{uRz&H{}mgCDj?iyn);QmM{}_q#H65j- zQe81P%9?krQNAia=M$EwDe+7)2ggWIa`QlqTrCF;za)L3cL!2u=NzBxa$m@%{=OWX z0_U{!aDAMWL))pKLTWl63wZ` zr5|1*{e?SO1eFdZ-RRrcJ3U6OiXWQ*9QbA%0zaWq0(-$5?|dxz9P_QpOgXSNvnqCw zf;wX79cEQ5cAnDLBl_B}uMUi0V&^@rpP$m#`}Fl5eO<4w&HB1pUsrK$?asN{(Xpwm z@@h7VWh{Y>OmAh0-4RVI>TF22IycJ~aS&g@I$Le+=I2YUhA;%rs(03er^`1rZODhz z`ZE?T>Bv90L-LKLZj$(6cXFsbJG9%`bmGPfu6C^cbN$IB#ONi4&)VJImx^ld@v9(# zpM^d=yZys7%b6|;Kvz*`0RADE9G*(@tD8<#o=4)}YQ9%_Sln(bo`L0*Bao^NQHR)c zDN9`?)xo*K0_#YP6?EzL74KZ7i1CPD6D@F_yh+7k8Mnvb8#%w!#%UkwLBvW9&4#lKcNo^hlYUTOA8##Dd;f z(9PPKIxZ~Fp3Fg}J{sX^i4Rz~tqQNz;Ii7S11X(FCs(+N`aE|%!GLKxA(O-MvqQ!A z(+iwv=Bo*P=m~w`DLT1iY0!lW=bqEClRU2FqTtx}p5)LUQ$i(e)sC#|2Iw4pqi zeAmxT4t1u4x^(U@Cvs=ZB;x8=Nh~SgTvqDvuZdXqnK+!pAT{htlCSF%U&-S)l-bJf zX?|PyJ1-a!E8Zt3OrPXRp9H9j?As*9ea$>?;kTdPhVqni z53HY^0-rBgf1;uH>p@vd-Rw96ef6=N46NZiDCT{G;?V+HX!qI2DWOlKXFYe-#A2~Q zDabpA3QguWjo%D@v-r*BcRjyb`2lOTDBjEd=Zze_a4!q!8#$QbUN*CD^m0eA+K2Tqc2GaiHsYADA$=Do7&X>k zI?LTcBX3gIvoSr)^fBkQ@F;7JKRnNAjVc;hnFm8S+8TM=C6LlN%Yy0Z6L#{1)0lvY zQkPxK$8j>}B)+@UO^m*9xs%XiCCie78KF7Lk|`u9I^1%RbBR+vV#vy_d|eF|+^Z27 zI7hlL==C(e0&-f5T}AH(C#uE^ktO7>%fYInL%Dc|M`j@?wzlU9iP+%gK!P`+E0Ky` zbw1%%S#RO8jNnzC?J2BG%v?T<>kTVYpkJQty`Jr?_YDawEuB3(R^eqiBXD&cl2&mY z+V76&Ws$PpO0r-ZO_3~i^qTkdO6BC8IdV|C;gT*@(!J!_zSpz8Gq=65p`YXCt%|ewzPJgZiK7oWbkbDBkZULxAqL)bE!0;n}|5v%NiccXV{k03BY5R7{Hymph6^%9IyO z{-&YxqGcW=Q(;~F$99)R(tLJmLu%U>6ju8Lt7lt9vvTk zK+Y_3Vxjo0{I(4+l+A6yaZR6Tsy!-BwNrau0gyiHMCdc;@~Ow)3ca5aaOWOapDv`3 z^DmBBd)vERDeZFea(f9P&cF<$efo1U9&Y0OS>jQ^QW2J%9rbR1WipfM!5OlV57fv% zhM)Zh+VG}7K~28^OAU=h8pLYn`5L$gZ_#T_Ur5Bjo8bnxPkp;D7OM>h`+aH~wPYbT zm}#aiUu=OZTy_{8m$<|T?aAsY>ldYhLOsLCJgokO;0`7@^)Hfz>2^RZQ=d$F{vEU7 zrm9In$J#TgIPBzXrNtS+Y;`ZSV!5Qc+D7>CiCXr&NC`48`m6@AM9wMtl=w?eiT~kw z@mBTxnD|{~N0=fV;h+i!yPGIAcGZeuU1gX?$JV0ncV0zX@Uays>ozT{qkxJ=Cs!~bDb_py%*s32#5v0H&+|gU6esLUWK!N8J-@cFmtHQ<5 z4vaBNs(}%8MajXmnKQ4xI;sfrY#*N6K8UGmJW+Dz*v1ptccyus-2G~IhqXVyt?~V{ zU;QI)z48y5;?0_K(1lm?#r;5ajDVYMj6FYq)mo97-&Pk+1Mh$|BPn|B(C)gEciPi4 zgSeUyA5o8DLui#9k^KlC(eA>98NoSZxgyJ|fd440^KA3hg~t_S2F{*YULLOKFRJh^ zKU}c5kM1lx8oF`W7gkw+&q-1a32X0(62xe#LBVDf-*%8aWW!?1oUu1qm2TNB-?Xk8 zm*Ro3Y8KV%a$tx6Eui{6KjaAnU<8HB`dL)GU_)B0qW_AHz*&)sBc5$-tPHqk3tl5O zrIr_*6*#B7aB+X|Ey~N)W0wX&HLD57)TDEEyKOyi2D4v^iXC|nRf*|gqKy=*xD7tlt>4$E=6vgt#jmGuwM4jC*qNj8L4y`C5^ObEHr+xV-Gzps_tuH!ee_;^Srj^ppAyt+u-6Nvm2I+9uKgGNUxlzQiwfCm8th=VK1 z;Q~-USM_EOMg3L0gZc%Fj|%4Y3g$9sL`s322i&2CjO5iXam`t~r^d7Wat0T2Ks1%d z*|Q^MisLWZCjW&x9M!rbdNC11u|~n(;5m3_BZ@a$_}+u{mNl-EECKn>l}?}#pj7BqRXwupv9io0LsSC*tUng@5RzQ)Sjc>z(#Z&? z_s|bW&&h{C%JIehjSWYID>MBBg;^Ts%R%jNI>n|hgS}H{WA);XQL)&55YLY2KlBM1>fA^_*1wlmv<2^wJMXDd)P6gv zWXJxeSgkI98C31%dY5{dg?i3Ta;aBF%7d#-mE#&S1cvL9C8$?WLfHOT8>j6XeZ*yR>k^Ec7{^<`)5EctQ!!8_K*t6&+8g!R_$0h?zrd`csnq zFA-a6ITx(q5X)t&V$-)s;KMqwHynH?+;AB7EcCIH=c41weJaQ&c5Hpb%eAq~)E&Hv zFEMW6wAh<=rnNfM&TK9(^kreg;b3ZES$ANRmca(s8mD~vkT+JOJCUCyolO2JxKZmQ*$<)*7(P!#+Q=TpBBAfXy{#yFC|A+<2RgZqaz2tG@jGgB3z)TF)3nk z$MHjFww>o_b2w6^XzNS==!`I?Bh^G5bC`oE<4-cpt#%cqK7>wf`AC&M@aZ{3uoJ0~84<1Y z>@^^>Jf2;1r#eILbDCFWpcC9kIl++;%VQWlkcKGYip4)q8_!CN_07-uu#R} zSRB{nUBsrFX&+*fOP!FcOqWql)B;*~TO}PYf3{fUNVF)LVwHHI7WHob(*meBP(Fz4 z$1wr}vR|PtTQmqp_G=eIcFloDuM^qNt%XF9{aikE$DgURmi?ZcLgfxc%Dk1r_xaRw zBN%`Pf7NORrF@0(_ZY#t6^}_CQm6e=r>k|HSP~7o;?n59Q3KN!Q=>};YP3|1!ycwS zdr?XU2l1$LBrBUd`hi^0IP%aCi|FO^=GOvQZH3c;?0i>WgR9@b7_XE zf_UgiF7>g<0Z1$) zHPmpJeVCPM#ODb9mvV_-jBH@JtYP7bcd)?tW+}}8iEmL>**k;c|K&5{pGJJUM-ZFU zw%7D zH^VkOT?TJty?BI;=5>}h9U)h&vm|wRc$KTOB*)QNa^CRHlJj{j=q$mgqOHUlDe0Qp zB?W5$FV__|aE#z^y38uuFL?`-U=>6bqL?fK^LOcpCs!w1C%ekJiROqdlKQB3dDenc zjaAVdacfc$P6}yik{!8E*XW`_H45G6ax~tU(-^N(=*9x7XX zRmwC&@JYxNx*=tKxzqnR=6;cKjF0AnsZx1Q^FCS>D|bc)j9mmXWk? zjCI087MVbtFUfK{Qou{H8fY_ql8H?3dimx(os&o||8QO%r{rbl^nbv9>Lit#Tv+A~ z{DU=XH@QJ&^JK`pBMd_j3$j2kRD2JJlM*b&6UgaK;3yQMM%B&Z5i|yV!aOJ$F+J9&EDbkw7ZuAwWP{H--u^+dUU5w6EX)kdvK+@s+#zh8)rp0~ z7eq^ml^qVnGFDI0(JW`05NvZckPeAWOH*IS9BURXv(jcqA3K%W57)IyQkM(Cuz4ZP z2$j37y^Zgu9mrXI+`w$1t1hW8=b|LJ{$%b)(EA?xL=s$0~O> zw|&nO>i!~J?#9pJJa;y$-b+ass&fJdy*b6kIo%z>VK^HFxV6zsY7~Znn%IivW%TUh zEIpJ^ENX_~6ojQT<t3 z*Aod*hz3N&`E+4HV2KUT8k+GAE*ffU^ABDfUeIsD@@WpsIo2KuTvE8e6+Ep{T`M&c zpq~ZMqo)@(xPlqS+LNU}SQXcwf+@qG=MDYJMM>q+W=^ILcH15CbdCB?T}Vf~1HcLp z%9RAQLgp=dM>Wz0I9>G%KENC#sk0?tKqbTKg@ug8(2T!556hYqJc}cZT6qc=Xo3*S z3w33xe=i}OPy}~*=w#07gADhj>>bI`F@*s9#fsr0OHPie*(IszNhr^l&>C2>ksR{o zQ~Udw!_Eh}I$cdC4^4u&zN2F<)iT;Ji5cXusaFTSe;_`N?bYSjv==2?Oj9UAvs@2J z-`sSb^v!HK2QBsl87e3}Un@XhI!jH&r=Auy)$YGY7l09wX}ZE}!f;w$(c9}Y)gq=u z7#cJz9<>pw+~sfsA{taxKU_|q)Ptw+EDmrKn(b4Y;79}z!SOzIQqro0iBycZ=!o!@ z(R82slYENzMx4?7JV!cVxSC|c-mII~L`>7f!NM38&*h_LJ5E#ESnjBeT{d*7oz1HF z(bqn4!)0!UMD3Qlg5%YJQ3)PbhQ;1kk8JkeQW6-cw&_n3X-xD_D88Ao#)X$Sx3B_q zH(}Uku!$)=iXla2q3%yYdy{!424v%Bvfm~+S;gMf9GmRUP@n4OlA_+=NQkI9<3=Dt zh0|+P=TaUSSTde{p5{i$o%OjZBXg2ie4Ce<+jmXT=dA6mnShNVNsGR&hc+6MXhmpm zHl@nY{GL_emKpX;nPJCS?V;|otpn|!rM7pcr8pmusSu~Rt3ZZhCC=;s`wyzCtJI}S z9FB8$vwk4M=sZf@P~lqdijD(0e33GjF7D+;@!|>_`f+z^;1qSi?CVJpV_sV?0yQi_ zx3h{pkY|w8r5=`+)$WKfch(iPWA8SK?PQ#T87DTqQH%@7$Q!G0E270hSH^0|0cm{g z2k|Ma=}3SH!B}#?sMSOmI4#D-1`IyhpZr)PvIV>ex9peeqle|XvsGXF^z}7;J*uzo z=<6PRJ;YT#2?;3NDM^F*ssk+c@n`sapSq5Bq>jd&&+uJNJ8XHH2hkY{rtCqbhxznA z&-QWn-P+mBr|`}r`ue3VKgV5}TK+43l#LlKGZ>iJ>f z+1b;Qcuwm19?wlWj-Y8zJ+H%dN|K(XJl2IiyC^t0)ZsMUU@htoKPq)$<4feKL@v(b zI(a>@{`gsM^9Qjzmo=L30nvj|q@PZt*{9L(Ro)&Gr zyF0r}qnc!7Fx;R_Noc3;uE^GY3ezTD;jO(qhFfGvcp~?adzbE-G{KxBydKxcnJ18I z*-N0wDZA%+o(H~R1+Nh<+tMY#o(EH35O9GG$8-+agV0Ti^fbGWZsGAqY`S?WQ*w(0 zhMtsqI4oT$+<|Y*CeDVmW`u}wJQ*Tl7L~S7HnUYAsk}U@;_fyy0c8;=ysS_Z*LNLZm^OyDN*jC1se>g|Fh#|qOQ$1P!%lqyx<5&1TKNm59jV4K#rayY2lMnVMh;c@*IOeSgA(m0-2s}f=FHY-?zkV)9rytg0wBa=9>XWV^@n1M(W@Qe8V0e z05iJ4%1=~TeSnTavM1V=-$ZVldK@KQ2~`U*9Uu1O2)dy~ew&3su?Z1AtCYcUah zYT;j5OVA`9()>Kt0?b~!8#K0{NFQ!8mgLeOu5io!M6^o#!z~Z-VE2A(tI%%GuHCV% zGK5U0RmOB*Ms$iA^cp2#vKr53)> z;@8&Jg?0+iZw+QKEC$7zBeB}!u^O+O5R|NlBJ`D+NyYeiTCi%cewV* z+1EC*lFHMf&%#cO_du4(x5U6Ikmh-zv_IOS-G_ma9z?m%v z*N$J!lFOZ^9X}L0=s5oSffn0E-ba7^-s%ft6<|ZQ!955^&IoCOeOyzyq4;8Tjpzub zoulX8$kxvp2WC2o>1n#9ZEc#w2u!i`7DUp`d7t@2<($~(Uyprf;nhyFCbkNe& zaA3ekhkZ>BLJp*rlpxK2nyWt_=raX`b_%Tl{eoAx{Y_YRG zH=4#ttr_*%@m}rH03edX(sR9~kvaF>+()H%O;5Ok<6~R*^BU1Zxf-R^e`=Q@?$}m| zWofR=e2hc{SJY3?aht?07J|%^GdS8;U7u&-sm&&b(9T1|cLaki$JTt;+9`A{yj2E3 zEF#w-WH(N4AK?Rj74E8`H!!Gak*;WITXSJ-t9&tYshLXEC`w7$DG|)Da@4N<*JxHK zBGf4s9b=$hV^`_VsIqHq#&31DUFpD=+TO$3Bm#SA=ksL3hK|@)c~JX5CiqDmR%;oy zaXYk0TEXUgjz^EkRBvgv*V^CnAT?9{G6c2ZRDK&rcvV*RTuSg)aIuDnvZ#xj+*cN< zr{9Xj_H|$^*>~+s$M5H0SbEJ&$G7-xi?B8~&!Hla_yIPZ zIRw&xE9AM6mUnoPT{J(YfJlpkhg&9r(vg-tnJG}wwoK+B+|n)Ah!`-0A2=k}M_-fc z*8Otb`7+nKdmiZ1x5yEFdvve9wd~QiC)@Px7teEhB!71SuZw$r4cUtWH-BG| z^A(Z!17l`}PE1+;m&lxtLMKjJIjVl-LSXKEJL*cf++N9L z#f@CnEaStigsr`Uu(c}*Tf25yWLqO(kGvq)Yl53C%53Pj{?o2TR=D9P)sQu-#cr$P zVQVh}X#PvNFNNOs$n9aPFaNV#Ec`ukvku@%>spIt>feUmUmLDaMSls5$^Ap(eDTNMhXXr;B-i-}gstGNfl3y!25%6%)mxYr6Eu^M`b@aYpoj8+%@E;t>N$96A^ zA8|+==39j;g#c17IE)yZTXwi|ewD)8oLxfnjCf=(!gx>er%z%Q`F@Jd)S@NQ#G}$g zRHCh-nb{|9PEdW;c_y`E^(S~3Jy(`0u-z$!7vd1_;t6s~;em=9aCX(BNSQyCuZtCJ4_EZ+ok#>N zAWh$*<7HyW;S7vYU#Cf6E4D->BAQ}`p&lk^vl#SKlPOOy_5%|`${83RQX>QIIl6+a zPFS*zRt_=b>V$XbXgy7yMS*7Z`q`U;8Y)tr1=(Hox*VW_VXW02<{-5-uJ9Un`}^Jz z?U6O!pa1;lJLZ74^csnv9-dpmu;PJ@13B2x-DQQE7i?DgJk<>t-=|~np z8z4&6zDSE=O{X%pf|Kj+VSv6M>4ek#oR;Rdt#3{h>(G*-uH{EJw0um|&K3#CZf*-) z9C`E;0zBLHdbXt$?Oi!8x4on?a{oyAUY|W*ZGBC5d+COhQtW3Bp@m-IhC3$-rE#o* z&WP1Jmd&5@QP|tngcAz=@g+X{NK~yJfgFVP%(5duh6W<|9Zdf^(n=jEN1%33nG|!Z zJt;7%ac>SM(giM6L3Xcoz42eAx+&CtuavSYB@|kKcU9? z`!3Ya)&mj}X&xo1Quaq~$PRse`bu}>+){E#5|VOTo#5Zt-dw@DkR&t4Xo5L$biBQV}t>1RW^3tpi2 z9U(@Ys-MUm^&?dZE;;n708zrh!$s4zCHrM89-P5)$o+;IdzwxPq6E;Y{S({IYd1-x z@NB=OW0Q=i_YpO&V+1)I(T!H{Fa_+@E5Mp6hOlp^d&Fd@Wk0lV!c&m!(8-g*v$|5{ z5m2C0eT0k(7WW6rY^(9;jL^w1f};mVd59>{w?ilU#a5^nL;8V_(LItD+onEkJ=vMC zY&w!X2w!a*2%ox{K7qm=W5FBC^HElZ+D>m`y7nlQpg#_gjqz7rFG>g@j*AGzO z!K-Du{(&=mr@L^0@~rElh{lGG$^LgdMS`Df7}dPb)4ZD(&$e;~%f6m}<#|vx8_CA1 zI7~L*-j~N>K;&2JrIUh(qZhH^fpNz1UsocCM*&&)hQW)>krA{@P z6l58$c12UdcVZ2tNtU5hKM+b4-BLJRaKzIhX2|FXWejNcstQzM5MF{l#XCRH{2ME3XYN@mE{LGAd$k z9xGp#>}mNk$&RJU$mC?JKk&lnXvX-!48Kz6=I3djRqEQ@rtj{}d${9Z9Hi?@ZSdAv zb4xK6c9%U(a7k3@FU3N$8%A!Jo0+wKy??TN=rJE;G&Ml6GKIpdU%zaMeER^yH##g) z?J;^JCo2A|03tj=qEyG;jE`nO#42uTEYSk>M)Vmmp8tz!E z7`j!AGv$yrNOC^rT7_381qXt&EwT{T6mA?!Wfi=z{{zAevOsKD#IjSxIncFRx;zAS)=ge$ZCnBHprB>O8SH; zuU5vs)y4MMHkoTPosgMTXwTJTxHGHQ%(dmq;M3MH*Ji1)61?m-d%|4{2PPA)MGBIu z9|>^~UNlmEn^i2E%G9?glus=$Rb#e?atqB6m*sI}n0)4-;6O^oo=4E-Qtf-%{MO&6eGQTszi0Q%2faCV;T z$QK*5F@J#Y^|HKtEN}&I*5I3dR6r_{J|Gn=l9Q8Ol;Kkw8+)UGbDlGX9vMrA+eu!_ zHb3SXfFeFWMLtn$DM**&s`sj!4iZPc)VusQ3gpj$98%|&W1eQ=fUNQy3V|4&Bbiy{ zlg*pdjJIj#E!DiuFmJ~-e_LK+-g?a2Ec5oZd7ES2UNLW9FP5&9LY|iZz}4H$T}G(2 z#t*ePLz+O-fV!tCW+pwKx>q8{M=WB8^wM@oNEn?<+S^Ebu1|dmpI=*~2YMi*DW-{v z8~-pt7UpAOR1(kREK=2|%Ozj61P)q8fbPC^?-A4?&u;a7^GpwZ8A1OOMhNQxA-GGZ zf;C;R(f=}72+j4k$$j$?`j3}q^oxunUY^n~(zCHQLd6n;v@)PJ%K!?D3l&R5oWh2R zB@!A+K#{Xa#^h%CvPs5KSE?lReUtM%G?M7FW+-pA$DF5GW>GVMnI?o4evSY&o`Dsc zF3Hsx*gz9O*HoqGcPUkuq=9M1^=6HUe*(BnxVkX)JcvNo-r~RRW(JtLPG<^se<-g*uv>)nboC>`@$_p;#I5M$9M)cTC)E|Q$)Wk5 zX&8(n+ar#shdU^$;)qq1fo<`tL0kp6B6D7-3!OOK-i_N9{YFizFho{w9j38M?z}Kk zb_9u57|$)DxsXjUp6z8W%#z3_EMR2km@_Hb5&JG`xc>Si9Qa4jHgWt8Db-!@86i3D zNhd;qU)Dc(H&t9FGP=dhuFIh$Bb{;`>yYb&{>!*d?~`lsQLc6OjLqgl-8~~S^ld_~ z4op3wZ|5m}n{t@jBlo6e62&TWY4cJtPi z>fky|RE4Qd{nb`5gtZQF)6Ex98LdP#s>98dM1o57&xG+qC!n>6{zIU$(IH~KO9Tgl zCP^KVIDW}{h!Sz1QN%fgu8IoIjS8;L^GRFOWjoNi5B-^F-DZ2`k}a1!xs=F7G;FhP zl*_WXZf*Zy#hO=>Yu8Zy8A|~(#GS)|&>z=^7aT2mDKI+sCHC9h3EGD^9i8cS!BMvL zmZhNe+KsMAEV%pFSoZ0^^DTPu@%Lc;!VSIJu-mHWm0;9qr1GZh&E1a^$ttx*=cN^K zGz=w}(MUo+YSb?f5-Zi;W(czkg0EK3JV(K8*_h9;rxN4zC-l3R)7+TfRuW6~VvL0i zjW)cQhniuyH<|wlG|t$>#RxNb4%m zIb9iEl8FfqK0A_66Rv-0$s*gV&FBRhFm1U&EKkG^j(h{B*QiD4cAM(l`W(u-Ob5nV zp*okN7T(0)T|d)tb8I@J0RI9xUd~tdM)>7+bE3T#@~4*d=f7APzD32*1eW#N6c%u@ zGwJ5dlCA^b-5f?%1QJVOSblmY9A z`~VxDlYx=eJZH-9^4$fhqn*J%591}5dH+B1UWNkzXPu{IoQ&}bZ)AZASNB_sFrilA ziX)-VPX?Bhmki{~kehf4zG^wR+b;;V<=r-`f!^VZ* zHa4)Nkz=I|twM=ig&JLjD^#AY!co&otn!XZtE2lso2J5>?)*-7@WN2>eJC6qIIxqu z+MFTe11cZzSPK|H977=Cf}j`_{e;TEhZHV!2S)o1L|(P_s-K!*ls4fx?o+Gui#7w5 zc$FTNciK3|MeC-M@>yX(3ai~HOn9)f{f(;NQ%@Elx-X8+c9$SV^jdEPE)T7BIf7Gx zY*Jb@56b}Lp-QVu{RXmLS}OKV!3=esSoRlO#HRDB`1CZNYOzCftlggwP);?1vMr#{ zKZp$!`|~1^XQ1=OHX!_{EDwcSp3+xYDmG>{W=R|3q(h$8S6L@hkMCqcIu@L+cB3>K zvT~&65TZ?>+K8x4pkys7ZUXf?lz6gjBRE>!O~iry9yQSyJ=-x=kQFgwl@Q)41`pw_ zTjUx!%oQgGp5_2K)F!vYyHl@)-!q5c$jpRgRJ&(euYaI7Kj)fG~rt)Rn7-*h3N!j zI9?E2sX1aRH7&O@fMfbVhF;`e$Jb$7C3?@@JQ}M5XU`83&q+OZ@N5>A8^Pk98zsd9 zI>iDWnN%+d=GsOYrng=rHzvZ!WrBczRTyhozy{|2iZy4IZDi)?R=7kV<%N5c2Xq+c2bY<$zChxsVBmvE_Bsx!P8Pc zvx6atJu3({0P*(JC!Vu=mhf!0vtAZFy)LvC3#rkeu0a-3Ju`HM*hcBkmzvLdsXexq znoTgDv5K4>9f`PPK*0ih4QtrSyxGH>; zVb{}2MBRMMqVke?Zr;iDOJ-5KF^k%bS=4S%%Mn=MP-ooQTqrqIc4|k#4%=3V|X%T z#h67s4rugj{AIH!#j1`ri|VER0Hyf>skcg}GoY6OrA}h}J-aA_|Bp~bv5VTvJ<{?F zSL~wX*4eU;Yr-x{z9;OWUb~EP#KE`NMF~awuk50(rVfLK2Ghp>z%J?wlqGSys84ww zVi)xppsMY8N1}*b)G^S2^BcHoyQr6RICfDYkBVK?cf>9#N83gHl5fT)pfS8vsNz@J zLp2c&xu?6XgQ2!`fi0OHZ^64u@?MRgdT(gWwdKD4C8gAeP*nh_Q((oW|Js3Y#c_ z;s1v=Q7OB>$|g!i*Z<5WN_zDlwu#z9WMexdHc=2TBicQq*Q|XPbvWe2Q(Ttn=>~{k;QIhL_X%qFvQO4j`*+dOA zPul)EdD8aK&MlIm*hI;LdVU|lPwKE*OEZj?=6K;QSRmEI3NIL}t?upF1at~Dw}@6~ zr_BH9o|Z}i8+U$*p*_VK>Zi{bo1Ib1W;)VtXQ`LpkNLgFFUoJ~9WxzyeAE6(oyXfD z!ZhJ>$=E=m<7m25S`^gps;|?#nekJw_V(HRrh4+$~ zII1|$(I{)SgZ!P@rb%cgP~^xyjD+)wIs_N2&hzd}M{yKm_XaOl+=+9HwvftO+_A$e z+N1+@MY}zr`ra|gm7-toae_?Ut4rX6+c6}01vorkHG=Ppss@2F$#&;It_ zpl{d6w+{xsbqxA8MW;h3x6}RGpl_$ix5`n8Z`Po1!VK-$AOE)e&UiikKzOLVQs=gO z@v|4PH%dTymnf`vlrTk@FQxJL;*?=WHwToN@Z5O#13I5P6FTjgQV$sd19&VppUzsaW)kD?L`3GA>!b+=bC#c(JR!!Q~P|1u#?ZKdMye zuvMBd9lfCpTfFsUed`yW=q&q8oUZ2YTfexkv+RUpCOL^CsCaFwB4vG4mas}SS!Nqi zLk7JCWrH09MKh$bwB2?@Q_&m3Jz!idSyhD??vlNLdgFId))&iIr3egTV_knJHh%fX zTs)zbw4**n^#BldD<*lGr? zR0=^N`F+|z(giPAU zuSw^SGNW`T9tT$252xvv^d#ekC7)k5e7n%N@VU z7&DFoTOcxQCu4x~RGV9-lg>*%YOwJcbBD0OSlQ9iQt(*SyqeZ(2Ug!Sa2V!dSE3I= zfi$}_(k~38(gb&uR+yW7_(zZ#)rAGV@pEPU_F&GN8tZEMCw^3q?U;GuRVT z-j9Qn8LgDNQDdjOC4;&7&!$C>(_WCD0``h-uZ>q1C(F4)JDjN}YYwY9iTr1?1WSI-gvE8c4bKdv zG$NJ1{U;dQ!Irq#K-0zBe)0Fe6ne>a`kpzSia&$?W4Yo z2s0KeNTr&Vrs-EBT4SJd27FyBb{@mUqg>?R_ta3@kVbvbu|0vND03j$K6b2zj<*`8 zUPL9ot`?K3sM`)8V6@&g+HCkJca`oG)wqr$PW1Otq)^&YLhGwEWKWnQ2h(g6^y8^y zr7Uo_mX2M;!9E|pCmJdR$W}8$aRb_ALWVh9V;NH@f7Yg1q^vB$2)&$}lH%(f+Q0Cf zxIkl^+il}LW$)5@SL$5tnXFwJ!R~@*7q9u zzG>_?t?zpI9zM3g`d%&H1IONDeSclPdylOE{`*Utw@%348d7yZgZ{Uc zM;8uj^j!+LfRbU2{tW#_CY#NZv^ZIqeY3?ZKH_k7$qM<&>NQEBc3W4v1nE z%nD|l$8jYG!tdzm!cMF;tKP??GN^4yNp9PWrowQ4B+D^ia>Rwt#X6TOnTsggs@ys< zc3vpc;wqM7V1g4%xL9i2U#zlOG-4KVh^WBk(vF`M>XU;oTrnhWCO(bwUrr6789_}- z6%fA8T!)SblXs1!^|>Yf{>D(FuWpW+s9Yx;fd=&D_<4!>G{sc|M(?L|zpHx1$>E^c5E z4rM2PqcG~@|2PM4q0>Y$Zl<$io$J1P*S~b!j=fnk0sIe3;NpivLgT6}?aqETzCDVqC zQE@Ckk}C_O(!T>HwsN`-M>zG+zx%vsqa~J8quP)WC4L9s*Gfam9&ObqHIsLBU}=Jb zb0*Ug$GT&_+27Y^>|il^kG)ikZez8y??(A!^t+DB+66gxyma+9WX60AO7{ynzPcYS$uf&LU;@E|J-J^5@@xK6cxS?AzuZ$P)cY^2&& zXT!*qaxb0#X~r4}KtG?(bl`G%)mWgrBjyoWYLtFNp^y@rvQ^m7r7IS=TwXOv`GZEo zGoSVb?Tp|Bp~E}6i6@Rd@pWf1G?3|X2Crw+-lhHvKuF%j1=;sEmS38d7TQ}F?$_pE zA(V?Nxj4>v0tb$|($eNLJv)XQNp>?m|TZG;6S%r#Sn19{>H{k%5hosDC^>b@0JToJ7yu0rL zRx0%bJ;ua^wbgufQ%5(mS6dD$J;Z%K^h;f-FL9D+LR+`?ijm%0eu2?ZT1uId&soav zzz)lThdEp2HtgP{WQxmw+%Wz=YC00q;1S*0XoVWmtU32Dh9IY17y?9au5u8 zC0feew9RrLlbLe^A0?>e3IT76+MSeJ@ZyvY(w=*cR!Ljx4qvbOt-kKZ_H34=FX6fQ z(j}v(CWVH-HQC?N)+a-9ZL_iPPRzBqB{$RB1#i9JWgbb+Y))=YJ?8KB!c-`Sd)9yI z=XMxQlJD6ZRLdETy&1eg0+>@IeY&{PEGZVh_bxfddys%!sW&W#;U$-H4Ag#domv-{ zuR9sQ>8k(oLp*K;b)V#JqZE^+-GP%$@!!~lj^}b(wFj;PV?`)(JkC>xS$8>5cQjkQ z#LYjJf?<=0iLRx;Hz~~}31J7a^RO9|^TAlfnu}&gXR|M*RMdpPc5Xdsj+{^R2U*MS zA6_0eCne?y!twQye$@Ld$`7qGzw6L{KtSha4XG`LD5HpLi^810^cz9b6R@*R-!bZo zQW4B5+7=WQ$!)2xEgoLpG?U|k52t3vUA!fYTMG{Cu>8njC+scZn_7of^zSA6|2!uy zbU27akNF)OVxZ2%LNH6ptV6mc8}SITBanO+qvZZIggIA)NzYg!5n?3HF8CrShh`s4 zeb09u&gkqnejtIyrM~Ac&ZpI29@r%^5ADY?J7uhr2&X9TJEr6jUtfbP*kvcj+)1~` zi1wjOUgcb;I5=?92QA!+_g)Im7i-|KTjnWR7;@CtT9M8?K4@Ga``&V(&gY-w>(DEd zu}~qQ*nm~|OR;(eD>KsZ_21+}wRx42tmBIS7fFCbIahxU3nJVk+GOoV69ba$p%c7>A0T zEo{djy=S|K^!F)l$TTYsvVybzMJSkQbq%9NM{#13vi@~SIlcC`G^$rL`70tvuMNbC zj(fOB{7Sz`pJE{SN{zG%-=R1;l>ugA^37~AGGBk;A1WZE$CgZ(7RF!d;wl9X^j`MZ-LC zT!le7S<^kRC6U5C+}}cn)eS>E`n{l$c|1uaD+&?^^;g+U$mj|ESh6fyD#j(&S z8)kD|q1&8nMRMdE3Et|ID+&0W?qVMkY{@}Uwoqrc1m2Gd&OQ=fPmfd^#?rLeEsZCf zL(ix8kJuy#qF(;tEZ2%7r$HVrY^pIK_pKIXsr`CZ~c^ zJiQ&irj9@uvS^6g8!80bCC6{!e+s`Yep9Eo{BzeKuC+PwCmYxDB0{{pZbiJt7P^;} zSoekDr+a_(uB4msY)1Ef;j0u<0%Emc6*~F;wM1;+hYf2K-`x|a%Y(7Oj3m~)H@7ja z@G0(_)~c%1=wgO?two{O??OH*)zUPr@lWxNthnc78YXud`(2c~@?z5N?s2J44$3tg z1COkgBsJ(_dopXhfsmC@w`{!T?;e=zJgICreXGsymE2n$*Y>8eYO9vZOl&72GORCZ zEvdKY0X)mgzOyO)oS6x+9?=`JJ%Cv1L3fN{)xNmTghFcukVzV)Q?= z<wZ=nn4EUx8vRc{#Yd>PPr>$W_D@HH@^An1&wAN<%^f-6a>Ac8CjI`7y`FDqA zplB^IvT>tfYFseO8BBLI+`@}1nC=Xed_P0&_V~^BMPJrU7{6}k$;LHXNUF6{#&a6t zQm0ZevgC)yULWjng|?baPFjUrQ?CTU-A-(rm%c~n55uNWqFvbdVSMQ2P9@rr(9~8M zGm}ye%e7&lLBX5^`ke81&w#O`TPfx;d0}Yu)A)N*d86oQJnp0nYzZ8{d2wv{&4n@` zSL94Ba{0#_uA*fV)D9i~iw3fkq0rh~tABB!adwZmJ7vK?=L6 z&d^=1;4$f*b;HoAN(9 zAz0`NPIgL(GTFs%YN5+tur9kBrN{+Riga@Z+T67R>Q-DJrO0cx@}Yl2#)gd0Yhkx? zOK6zdsqk2%n8w=5=W_4>l4-~o(He9Gv!hxm-)6AMJt{b^HJCA?McvRsyKEE^jBk*m z2`S63V*YJPRB&=@!>nYE5J+e|>6}9Cfkoh?iqf2;Z0(4zuahYITgBOOKsc#W+bfil zQlY#`wc(4k+TIHxGFzA9qHjmS6I9G5v8OtDU} zi8V7J=m=)?Yo#%6SMbD5ssPAwQ6xEHq^JorUKsdOGZi%2nLCNDW`4nno`F}}_I(`4 zY2kJk)GqLHTk_F;A4)adOO<D*qX@1Wa|DJJ$1kTuFxey z_%t|gf%BICws2hFKUfzW@!5>e>rJ2CJGi}7(~OTk`bOrqLi-8F9P#ch%?N!o-O$3& z_?5K5rP34GSZ%Ix(@@j}ZtWL%abJio?LYC8QPLm#s;LMc{U zdbe>A$GvM1KI;;~f0fea)SREaAtSl%vRB#EZV-lOxx0vRbJxWBU6h+SM?!hWouMAX zX!jg8^^fenk~Ym8X3N&dUf|Fz&eU66{#oQDm4jAX5qeEBIJXdvLK}m#Ke}wz+KeD@ zGTxso+ev1-2KNkKL+&xq)~hPfz#iQHWIR6nJwXC>@MNdiP-r0>SLjY>aG8?;Lw8ES z5Wj|jcM2p+GjDMPL6{~8!D%j&uQ`Th_B`2$R<1=$S6o)NqNnEXsZ@_#^GWyAP((>v zyDwjxA&mx5dPNkp`+rEAtKl~Wt5cd(qiEm9-M>ab#sEjpV2@z-d6MZV3;oTGy^^o7 z8bP)`66)QsEGl?Y{VxASsh3DSi@0fPsm20}KQ9+6DOQ87hH=h_l1t(3qVDC0Upfl| z^iSvvt8Sh#ey%T(A*pSNJ-3F(9p&Uu-`Dc>@BWBU$k2X$!sRkUJYu74y;w9vIvujG zG6qU0^MnCZyFEPm%|Da|{K^5G&!H+0HAeZE^s0KvY8`G0U>1pMLI_=s&fmfHQxybh zgl_aVkI+vvM>*r*AqfWlU;j#wu_tZ2n@#E0M`UT|S zbv;8W)?80^ya%I6!FmZS6zkX#Sjv%Neb#wKuAOmYZO%XBwD|JqhRh?L@MIQsdi3@0 zka~=vjt(_Qn8S8EauO)3Q+LLH{ZR;mTc3tKz2EMP;Ls2aw6K2p7fyDgwkbx!7neun z8b}`fFD&n|a2mjol?~-F4LL_-w^@S_;%cm?L@uUp&gYl-swv1>cwilYimivit0SIJ zy(DEwLwv?M0ukI*poLV>p$1VTM`OxUBA{TsC|CUYKDY;-m-uVOjhO8;WnD~!==RJb zy*d!y;}DNRDk^^cYkaiT3;i}l_mFgv$1sCECfYwZ{+VP(Is+#Wbt8L66f@DmrzCzx zGMk9g+mxODqrqs*{8S~$`1(=_M-h!S`Se}IQBt0ua@X(dfSjuMkeC_VFr1R2!i!&h zoY9g)SK=P(z3u{o%e8s&BSXD|8S$eI^~QmLQd9s{Mn7K^Wi@i4N(eNr{$=81Y8Ur- ze%*~1E(}nb6lxGb1RfP#(}pSCXsFNPgZt)cQ$pVo*EW?@>&{QF`>Y376Dw(L*LtNH ziopRu#>=Ybg-9FQ5;=!vzd>afr}8w^UxPg(x{9umOCrfUPVp-kQA$?aQ@4J!vXh{P zshDtMTKsA`Tx360sDCQV#Z!CgZC8!q-&1EFzuU=OAtixG{BBit!iOz> zH%t7|a8VIjE+`GBL`3pw*73HsIg&hMjJObqsHX(e@v4dn=aoqu9NVK*eldQDfn&Q7 zgU2ZLYFVG6u;&>NV`2b zLtBS!_cW}zK|FVrfqij~rzBNV-@R*hIL_ErZfHI>vy6;w#NNozDvf&}gYeCS(I8%@ zu|}=!DJibnk}QQ`(pw2L@TlZMbV0IANBV*1#ZL2A1fEwozH7^4=A@_`%GNK>e@oq{ zCLCw-8cYh`Z06osd~zM3nJ-j%pT?N5(!jb=7pcDU5IsTpAAl(Ie!K?UY6>YXq!<~d zl&I)7S_#R&o1^aussm^eN_R?iJx3}HV?y&{{lG7jU%e62yz|HGyi$?xXuoD?u>MOB zIEmuB?RZ9&K3M#-0Bo0W_0WKhR}b}Uzk29JkA4-ii0X&{$5D0lP+t+NaY4oK7NNp! z!-L_z`i<>D=r^fAySjzw-R-m(q;{+osxrW>^bc{O1+(OkJ5IJK1&v0$(eNAqZG@u^Yy~Z9@ZzZ3awAIs&oB4O>HAq zGW9BRt^M_dgb~U)$f}S}F36|7qu(ZrqF!SM z{|^6o`e!VoG?Fp2BlL&xE$WibRuoufW?q3Ue1dp^!5Q^%ca9jwPht2qbq7nxsTw)P zJaYrdROjY`PlhQu%19kyYj9K`=K$^6ChHC$od$`F|>7E+K?f4jfsw5qZ7S+eLo0zR)k(L-W8!OyxR#qaT-D_+4+GYbdQZtz(#0E zCqfHOAta3wu7%=Gi_9bCF&>$M)Gw#>R9zjPEOIAlW-~**qIqRf+Z5;0^Fy)gvd11- z>k9Rbe>y5X*gM=C8IC=|d1#M3M08Yqc1}!P(Y$<*ES3+u0~4Glm-Y(v=3_oLD#b>J zd&ydAJRD#>Hb*#F=YgfKk>c2xSlt;#qdaCkT{_x!vZh9+X-OQFBotSl`ufQIu?eFF zs#_Y7NJrx=S5C`SYb=1}aDnFX zsE(n<*9%hk*GeqXGqP%oH;l~NalK_eo9z>OZt)LgQ$zyqammbnnit6)W>@xBu9HpR z{Lt-UI`)Pq@;(b2xdxppX7?W2`_A4E_wMhx%YWq9r=e!Kd=`w1AqmGmaO|z=oeJI( zS515>xQn|_8HU5fc|$legEtp%amU`~VClED(95BHp|>QQIb2v9xV)NCAvyb!lqGc# z`T5+xuxivF|H%9@%g#RdHYw4bEfXVM+1z~28VemxxnzS30*uPdmD@Q=@8@QSQdvyG zTIW(#(fC}!v4RrrV-)LwmZkn4J7UC2iWlyrU3qCJhf_TgCUK9mD=l@m|7c(r8k0Dz zkz0ThS45?8jrbg3H1Jznl3D?um(Ca}O3P$Co!HzdrNWG3eKPts&!P*I12i(~=AH zUG(5X+tAnnJJ?Vo#iK``FJ&rL-FIjrBZk~LsZ^@aBPq;Ht+@$;Y<@pt6y|aW31LZ3 z?R`QH-5@f_mD_D0x{ z+_rOPrQxNyxp3rn=H`ZD4MqeJ$-0fEFBNybamXKj^`FxhlSQD13RTiDiP%g&GEygz zGqO4)l{8KAS*FK;%14yKY8YfN{!%mD@oU~8hPj-0nJBGXNjKdGD$~x$oHTfYbXEdI z+PE45l}5x?$Q(WN48B*64YV{Z8AUP~iP~2`LU|Wzx`DOo5UfcXb6gTEA_C{#>P?%tUNmqNWrcH}v^iB7Z z^^Dwp9Knv3g)~g|=c~NV!k)QSHorj-!y|3kygYj5W@Q8A2;zexUdOa4tz`8O_-fBRYa_a~CXV^*~_v(#zHNPFJxg`#xMyFWf~N*c4& z#aGtgyxCLEuyt^SO5p+t5_OW?OGuQ7=ZS)0%Q{ktE(xBi?~;*kv^?zRMouz^VjlG# zkTTmA6Ove8!hs-CBdgBQ#8gsopeS_$O3h+KR`L7*1XdYu>qi!()ryMQG{QfCqt-+z zT5#ncwY+;pBX%@+KWb0@22#3x*Akqo<>f4mrPydaWH|kHRPq+S4We(9FRpwCrA!S~p ze@mH3dV?}Y>h;PTps!HoDBZ8jG5R9Rz_zru#cBHO$|^&@Rhe1(bY*7iw^weq@My{?zn=hUkd%K8)P^?rGMRJ}eRuisOz56bI3>UE>Mu2HX# z$m=ro`k1^{@*3E7jnyJH62*5zC^j`lo$X0EFc}oiadW1|j2XcyEo@Sh&0^b=!HNl1;!GHpJ+ThUESjmb7`{$$wnOO5fEHm?~r1GwhVw0YjJ zai_-2G;MyOY!(kmyA@x(gb8Wxy+o3(9F7i3YP4!cQ`#xURdu@+#6Grd$Ii~tQ$nX zX?s-sX6KOFkGZ;Ro7>vWpk^~@{?K?)Y$c@3j`N>y1|+%EijS*feC}lu!-&uC#jA7e z!0^kQJ;kYJ^13&$B9R3E{`hr0*1FQh5v74dDcryP(>0a*({mF2AB*Scwf%@~Nc?b_ zVrE>qXYH)mwwZ^PqNQsG>UR^AC4$vP>rO3JN8Y<5{FMq;MBaygVDXn^$-6)D-n%Y# zZ8S388j*2-{aRZ9jh2kZ=x(W9gM!x8Egql=^bm-k?8ccY## zIz8IoAItMb7d!k3%WcfT}=eSHh^IkrFWL44}TIYk^RS2X)jcjA0(hl)-g&dm?}*}rEpOL^!;4%?!Hx8Lz zJ27hAglOolofsY1?g;Eq)L&_*j$XFoDy*o$_UOQlXyM_9?N}QOoWS-d;c!QkxUOw? zg~mICxf9p|JPSMlJO*q89soiacOML9+;b39$J8-D!u$xc8M7Jl2<8#Y7R(k*Rt4PC z+TfH4OwG~kXfeeRYLiH}0O1O2;5=z^#w~%xauh6p6N_w9t>HW8jwD4x)MAGWx=)fl`71r7?H`wrq0Wmbw>|;mZ6G_?l)%j#q zn-6G@grPA&29OQp0keP-Uf03HK=BebownczSIwzN>+#MYJ$#0?z7u0z^cnGN&o%G*$zDri~HV-&Q9 z8zxXhwwJUFHki$s`|gnDRzL2(=_lRAJ-4uUU-NZOPiJZVrwpnMdnwCk}$*$GBWVlNuM+I?~8{wj9lC>>z4_ko*dp5_z$P%e?=WF&uQfPyUZT^N=h&J zXyzmQM9DoeV=UbmT5ww->pYh3WWGUrR+VzegvTyVSMpB%$(lAg=B52)*<5u(TXmv- z6FNgDWVXT~8o}sirNrSZMvB_dRc&_+XuG3d+Z{voJ|-f&RA%HC_{}nh0LV-YZW|FFRhS;bmvPOI+7yNeD0JYrf>GM7U)}<$CouAfw2$L znPAa%d_DUawbBhy?6K|hh-wDQ39VNnDf5KZH8^oXtMsuGvGwS^ps~X_#3%Nfg-qL< z9=+vJWjR+_ZZs|5H!L%hS12%2xA zM^7Y7He~a~O*P&4U_`BjwfEPsH)N>lLiBIQX_;0oCz>+->uLJ~#AAJ1Bm z>`W!~%nkzMzA{$(>hghsp_#M6t6+lTnq`#@cV;;C`@aD- zc75vOmdT6Kug(`i9gV4@Q5u!cCZ8Vqwim$DANwtnxSal7-dF!IuZ0E*Lr%uba1)~% z|LR+y{2Wo?1borL~qb3oiFS8JAPZRaJVW^(7Nhw%e-8Ij&7Ei(`m)%JrvtYpP*}K?EhvZIoXcH`vZ-_+3b5*GEmQD$WJv2jfsx~-%{x= zD^n=}q+Q5sRnakNf4T~Yp?fs@hx0Y}p^ zxbv9A)j%ze;`Hrf+wsE;lW#!29+r1zlb%F3SnS%v7>qDRa`N?wxSl$bRJfg~B#n$3 zSD>#TvW2L)k!O^iXNjKgU|S7UqRf0;tY?Zu-0XkHj7&>PIn`+@X#faJB}KR684_K` z6b0RYvzeB>PvT>nBw}ZXOW#e&E9;LqaP~)#GFf1ala*Oy;#O8J<-@g_2vTA(GJ*)2 z4&Y+}-@wOQzKf)1AH7PQ6?=?Ddu#z@**Is=PHtc_tsig8{G z<4W0hAtlw4m|luH_eejS-!P+jIx{3kJk#3xcobD%gG_Olv&pL$%23FT7zsvd)A0LB z@yv_1KcYa0T(sR^FJ&mr6dxBzE6xv%#hbcnd$Mx8REYeE3k5Hfd+Ft(ZD~q%x@a30 zskL&;qq%eYww_yA^lja?eeXOHTaF0kw(WZL-hSKm;|EDcw3I=enerOBZ95=A7`JUl zo40Kb+s(d%`Znvj?N^#ahnSRZ4Nozy+dedwDu|WDXMf#x9~R`xk;gAFiQ9hP_O%l3 zY$l2Ng)foCQLVJ6;zB2s)$CS1uRYup?%nPw_ih^r-YvBCa+#-!T)d6qm=i@TQTc#ALAUuT4i0!WPkurlp7K8;>;K5YpZ+5Gwf z$&E6l6kjjHDWremuLxW2^Im)-9q@QU>RFJRuRl|!#H8N^4P%~1_wgDsr+bX4AXPcy zYXoBu*QoKe@=M!8|09D#gs!HK&>q5Vk#lAbE#iGG8`~u|Z0HhQQ#c5r9j8C<4LNbs zatrcNYeuniSrN^-M21%5F_D3T`1(2GCC5d_{P|#1_*YiexHG;!0~gk+uOYq+M8|)< z2veffRH~wNXe!@Izh(BxYV}e=ELUx_#P)fcxJV8zkCn_*>ZHv=Q_7NA&nXT0|KeSVojx?W zc0Qe%*%GpxmEO58GeUK5;YhMhBJ;xrP%aQ+-3OS$r)$vQXSFgV{sagAx~5 z{!98~7aD!Cj95RBGDH|Co6jSE`EpH#fj`6 z<*pk@Q=wsHRNz-K;~ll~Lb=W${%P(9@#sS(_i$P|o30Z=_wK|U2aYcr7if}M-6$g;)XR|gds29z^18b2L=ssjGqDFG z!z0&q8?)5cYs^e#rCAY@jLH*L@X}BkcBA(w$fiOYyfZzCs@r;#kYfeo;F#X%_epRcl)~9vhZM z&!qd~*sd0Nvp}6R9VPZY$FbQR51M0VUbr8LuW*t&rLEeprg9%c)$QH5l$f2|;omm`hF6>-m`|MJ$S-7*GtMUR8)y7{hTwDmGZZWv}9 z{nwh<(eE#bj{acu4&Ju%wtaLHZT3S^{=Lb&MmPDo|4I_LCi>W0p~l-}6tH9Q^h(3H zw%fK^M^csyVMJmb;~=@A{f$j723yQ=WR`FDkTKxhzSq|5@=Y@bm%}~x7lgJpzMqia zbAPDEi*k-71H8wQcQYD!JaD*8jaD&$SRKGB7OOYH-=0%s@H~zIVpt#dxnZ=5 z(RTSvWNwe*Ce6+0K(CSfZhnLx*0T3X8qCN3A^aTRXDdv6_55Fv!1BJ)S_N<`Fafv` z7zo4yANPsY_5(YC{{|ie)&V}C1jqx@fDwQj=nXU{Mr&^XzX5&>d=FR+)Bv{vX~5M$ zZ=mG@!T{a{UI(@SPXG@CYk_JY56A$90|S9r;BI)6=ivE<`F5{p?L#2CceIuOTndZ? z(tzo}T%a1L10DpP1@-_R04+d|c>DmPf$2awupGD#_%ZMT@Fws9pe4WuFbePhuM+OI z{?Xc#!1sZ>fz`lbpahr>qyb5Q8;AowV@czOz#G6e;A!B8z|vi#Zn<1q=lq zBb@EP24FQ%4a@|xfib{vU;q#YXu#j&qO~Sq5AYk{VPFGL2UGxaf$2a7a3e4fhy#xH zjMfeUdw{2b2Z7bVd>|hf2aEs`fulX5wLb%|051TK0~>+$KpjvGv=Wy;1ABnCNw;R; zB#^-OKp+Xo2Fihzz&hYz;Mc%5;C$jP&u`2$p90NMfIKgg{!apr0IPv&;C5gNFdDc5 z=nFW3qvs)WU_Y=8coKL7xDQwjR0FpI(}8ioHNXJC1$;(2ACR;Lo&_EQz75<7Y=E}) zH1AHgUbWSir)x6`(zPq+q-%#)rfb{25pgSdnN?v|M83t-6fIA4Yc%mRA4}J&v>L69 zw`JNaT)ez3QFaTpT)t|w#kkJn?M(i%@i9*;)+$c%V|Q7m)k58?ErM3AHc89Cyd1k( z>Q}>MDI2tlwMwmo_Yz#0Ma5mXsKkB|Z$*5UnQp`JDUbYCU|)=@a8U_2mDmaY9pfO} zEKsh~p|XJ3`@p+Rg+Cja2saYXT>f%+Gx!tJ3q_Gcjq)v=R4Tvo_^w8FMW?|i(r$-0 zk_8D&euV-Je}Prw>nLZ28sj9g(^l9&1z#YE)b+kghyq z;7@eHjX9rRiQOXJYw+vFM&3I56^vT`is8?z-2{zF^(`r@pmcnlL1tOR(|r?pCSfR&;6itMd<(v&@T$Qz^tqClm+>VUrYSua%0^x@bX|1cZs*2_X!3mg)sP~^gk7d= zG+ZKjUd)$Z`oWb{wDO9CBb*42k~b?%O)_#+Bwve!CA}A8S~@CeA*F)#eYG|m*QG!z zi-(7k0>X{)J`dj#gW-U<$>QSCDld)ZP4bWtKTAi7_^u#@E!vZ63%nH-lPjy1ROXg} zI=;qR?DKZCE5^@a!mNg?WNieY2#pFwzo2-bcYIZ4Ntv&#sxrU0rmXn(3MsF0E4<$7 zQyj+Uil=m+uXtW5jCz@VMnJH<>?T`FP9=l!T8!Ju6W9LBPcAxMto-GW0-{-(%2Pg7mRa$&)|6L>u$g(M*jO0Dl}ob16-h|!MgJxs zCE>-Q9+By(Zc?r;P|`B;qMh?1s2HwB-Yp__rDn`ZOzOFmR2jrLQ=87;RG>)9B6X)= zn~kkJ7S2>{2G}0;+ZoHknS{@-G0->Ctr}|f(!*|Nl^~+oBao#$qKDV2vQBC#jjtr_ zdfcwX9K~-kU-C>;X*ZtuF5=IqKeLgeXtO0p1IN%Yzml*e=_#fz8JLD9NKO-NFzjkb zB`H%Ro$O_Wge@+H-WhJzyJbrKAlzH!iTLSQCW*f)aEuVe-6*eo&^GdjQ3^`_sl-ll zh*5qTZ38P@p-`j368};w%VW?o>@O$YQsXUDI#!`{UCP&5utn$OiMUlOzNFrF{DrdH&O>#rJB`-v)WEY(;19Mq*j~1$YrUQ;4UbVfMUbXwG!ptlT~h zU6#C2OSx;b$0Ibl#_QT$^wuaPN}$y>&QxM5S}UcZ6<>Q8Rt~iL7a4WV>(aV4@?OWV zy233`;gvvRNqd-G;hj!aMpz;*pIJg#G8CCvC0+(Gk`{`T3x<0-?S=U&Y|-e5y$8;v z6(YZOdugdioFpF_?f!@iyUIIOIGsxYPR26p&LZ;MbiSlkmE2!QJ|9o5%4Q(`G;JK^ zLN=}i*iTVdIk;u>b!LC(f}2h#Q?-0TI=3*g;CLb$`9-`)2`4<~fuEy7IWzCM;7o^~ zNk~F?%HS;*3ge)W$(KB*;z;Rjv`LC^&EtK#Dowk_6$uwAYDK(Bn`J5?o!Q^%@%-q8 z^jeH|X{3adbY4JC5?wLs&FPpCjg&V3JizE*T4v|kC0*%TnX2t1?vXx?QMX79ZSTuu zqA4?whQz0%B#rpx;VQZnDPyG-5~^GAN;%XOzv3RLFYPHJJ;AR1SaCd4`bZAS zB$ne<8RJp;P*U%U!mB0aqy(%+c1EAf2l-vcdO*>9FGW{uFLRf=;7PKWa;{GE=b6_2x_6{#ss#qP|jMOWe^F;AkMDE<3UnDQ9qqg9%?)wkq# zd5oS-XN|GSRLhT{L6X*%E=9^*84)w|z$*7FQ|Jp`q&Ms)Jgenr?-O`YZ(`f)LtFkq{mjQXj<`-F*A|PeC(xvE~R=Tj}>7r zb%v22MLNQdRqLdKFC$^ar?mPcu2Q!cedh)6ZIvlq;R?5cDdR9k45e1Gm(Wt*MQSgC zR5AQwKOJK){yOVYB;Tf!`z4sg8YihQ z?Rgou&M!IHvgnhHL!8~Hs?ndZ z`-_YSo_UnDt1!D7ZS9C>jKiHfZ-&1w$D85zi+Phge|DU8jFb2~Th8qA7JprFHNL7Q zb7`5+Q&Tn1TT3%{kZZ zB?AY!2VZ*Gkjt;Qa_Ci854+~t;nyWyKO%YL4L5#mRLbboF=KDKIW2wM_>9a66SF4W zGC4bE%2dy^>A89A?3r13>us}U&ncQ)eEYl-@B9U&W#tPi7FAYN-%(TR^DkbqblIK% zv3$kKyR^*8c~vD|PgPl^&nqoed)_m~_+^|oTe63i;q8b!p`vy|jh8X!irQSSFTc3L zuihux-qR~8s^%%rH;&V00yX|hU)dtB+gnppRpVxAoCZo>_SD>5!$v-}+(}a=+CH_6 zsX6JBrr2$0)7+SpJhE4h^h$Seb#+DAykeQxaF-U>x)&9fc-_U=`+VL-)jqec%3V=a zT;leXdfnsQR`?ZVx7QTcEOVC;|C$=_JYU7K;XOPR-r`!XdtOx~6Ce1*hmHD`weDJf zb#+w@F5cor?)gMuQB{o>8oVx291K?xAP&M`a<3lOx|u|=*ziL;CwEdd0l?z?nyN(v zQC90NuC4Vhy1inVyTo5pR=L1k38}@x23Td4%-9rHl-;Sw_sA3cGNy5euos{1+x-jp zb}y^)*VuU-?w;gxgSx1y*5|G$Tj+(lM5o4E>#y*+tLD4s6<1V9U`R@Mx^`aGqUy2= zZ;5;8b@M7}u5!=!SI$#1ReTmln5wMx)%fT6h&=zwF{7d)r?{+A#a-e(LgHOn<#T&0 ztNaT}-L=)l^N26#C_`~Y2Z7n;b$us!wa49SB;NEqL*Bkpn69dv=N*3b@{n+ZwDG0~g|hP%{TTy1a*oe^Iz= zgZQiVqiu`JYJC3Uibw)UN~!>aFY?4`WM5QO>7_)v4#mN6`y`6(d|jU+{vz?Ns`ge& zK9HF|cZqj#**qJrDI@RFYVr*lBa*S_PWZT9$;VHKCe9+%uFO};tYwL4!NSh?rn83C_&S%ourYNHTh- zL*1i1GrPI8uO%fFc)GE*(ydr?%`KhFqiIX4m-4v4(7I_Z7lw;J`TXiZ0`61(hSJ|O z{!Vo})h3ISIn&=7?bN@H_^Y(YUzB!se|8G1wa6c96VK|;^6&mi2Tnh7DegGa`;uN18eHP{*AT4b)oeQci*$&-uu3J|F^#Vod>@Az5jghq3{1-!C&=5ABI2r+sB_YAO8ENNB(j2 zSj+LxPPBf0vQ7JEJ4~nV5S>+r>3=)^|J&jJ)AIkK4(sXNRfqL|JN{W&qZch2Ej@b1 zB6+TH=kU1YWf_l_lXG23$#uN&cvv2r4$yC=f2X?F+LWrr?eA0RMTvE;x0*hpfspQB z;ICz1^A>-FqHzmtXrYx}T~j9GmpR2X^GY!%cyF)q(}5MYTZ${yE8z%z4Z1>8gO<<% zD)F~WXo!FDD}J=xVxPaJ1P7s4Q>NbXO8qsprd@%zq|$4Cm1e)ijQ2sX%_p$ zuZBMjd<{Io5qBZ0#n#n*y>3+<4Kv5r>%P9aE-@yCmRWs$Jq^gDq&iRCT3T5{uN>tm zsH5FQVS}Up8E%!L3xL{mxGAQ7IkW z_jGc}0OUEHfA_5&-8=K~@$8Q7cKSkh zPVt%DH_nUj{&U;=ew#dn&h6d^UZw55b9giF>KLA#PR~{8+8{t4E53I3*|-&Va^KR4 zk7w6(^lwkMton4V2(Z)d%wLYVufqzzvwOewXZHW+hK}y`@Fm=d_jGjcOn=XRc69IT zziIQC-5Ve2=-yc$ihkJ9y)*r(&!5@7bW6InQLf`MpAz=&Jn?#z_GGt+T?PASw(W`1 z9=GA`XJ5^4zlQlGc7mf4U3P5Xheol$v*zsl#$m0|c=Y;&`+3(`H4hL==SXdgtGEh070 z$B8}BS&ZhYX&r5;xQ%CCz|Sb^6vhYf`;c-srgbih#@%dzi7#eQqr|7RW8}xmzn|%q zN(*gLiMG+8s)m-$2A6h0)P%B%3e(?IzmE{dmloGB3FECP(9S#6m06XVvfJT{W21$O zTwh66ab<~YQ+dh3WRyuNugq5=T=&)##};FnD=KqoHTap4aoJo5RxUt1d&R%a!P+cS zpiNe>vpKc8R^wIE{vrNzs!IG7UIgJaWt|l@LCq_f z?NQ=UDRGsyZH9M#F(c~P#gz*tv8?0U6eyczRzpBru}fsaQ* zHH1e9M{zGMneMG+LTMh-9EI#F+rKlH7HETQsh&Q6zRZv;%PFp1sA>PDQno{SYey74 zbKn{JZp(LiNePot^rNzsRIQ=u24_J{nNLYU`<;;zB~#~%P&Dm5`IguA>B_rINs48G zmZLOb8PfoZ@|a`P`Z{vxZ5eI}qC;M>&a29eplH)HQSjm#g{FLs*Tz>=)p|{Jy4o4R z&a1L$NEL@j<tn*32@ zYp)S6iDr(s(m#ppMM)&sM%EBZtu-prYo5gXw4_&o)@HLUU=OjeYcYcf?WzS9mWOhF z5uC-}%Aim4Q*MzEhetbL|om*P9#NyB$4H@4wf0@tZLfeQAGwoir%tZMw zEu)NCb>FTHZKfb`p6(q#ePVBAm2;J{sZOpYzWMogY zbn&UE?Aqcf)ar~-)#g<}#Au#8BlfB|t76T^GF2k^*bkfQzdhaWE3G1nGd5Kd714Rw zEIU=jp{!(52}M=e{4#G%1leP{WqT_Z_)4cUjg0D|@zYIvJLU0J%qwek$dtO2KxH59 zqr#EYra4~Lf-KX1Cg0grRSW&q5;LUr9kEeWil+TC;)?HD?IKn838DMNg*q{P-aH9q zdf9?fU#<3iu@y0@Qn#ZUYr3VL%JtUB?7UU;WGlW6JJFGf;$^0U|9}oz<((?DbB!uK z7(Lx9i&~T&DZYYlqXe>HVSgv_7X6=5Stct}v~hxG6s@XhLH%p!eO}cM~} z(r6Q{*1%&$woT%YGo}3x!?%$T_#N0G3@Xa`WfTIFkr+)lD-kVgRw8y`KcYYz&;=E& zwKvT=&g4z|wdCqf@tH|Wr;;*+3Q%bb$3u6JeSx;ZET2sT=&lk;sT$I>lLRuWc9DI0 zMm`-0E7x8al}nSMB6F#C9xZcm&&|rrwknv5967QEWZW_zO|XKp60fxIH770c$TB%S z(k3!8oAw8huBzph(Hu%q^`9t=zgiki>Do=y;)sxzKOLWW45U-FgH9!^X?>)IKCScK zXv#(}>!(Ou4^2^N#@r^MjrRy?Z3{IgWMr|57pszNtfHb!YGb?*_e?btV9i081q zUCsAXr?2P9bh*`Km4-lDB}`jy=?AJmH(q5Z?x=F+8>@>He|Zj-FFf8F)^5?bg$6}&9kVOZPGiPR&wW6wd;TuP_Z?Z7>T65W&0+&w0+Z~ zCRF%q>C{$u$NA^ar#R8HKSgJgBdd*`7x8}I{*A_tH8e!}a(QSB7-=1Cz|kcn)kRXR zcW~}=O!rmHs9Zu+ z{~6pKcsE^(QXCmStfJALfL@Y|;~4R0cN2`X?%bcyle2c-OJ{B;^2nN+jlJL{K3#k8 z3~mQ;b4I+Ww`xbamPS05cM;x(gmkU>Jmi7f>HMvQW@NO|Aa2R!kxvYNc6Teh3e!#I zT&%}(8)>@LSq_+%Tf#f14=?TvH1~XL@M4dLMe_mEt*h`_-#&eK)uz8L<8X%XTK{J7 z(p7j{4xC=rnwbs^3%rt=rypxbd&g5Zcki9ez=(Y zfSaYamfJ?`69#anjBe06vM)mO3G6oxr2OcDW;JdbfRZlUv_ZJJxud2FH}_!TaA~@* zciLx5+BoGVW|YOK*d(0lMdD*e>5L)nR-8M#ef9m71iF&Iln>IL`$hj3Gc333nCBK9 zV;ZupPBtI>6OW~0&W}~8Ch$&$+V5aCS!gK@GzyN@5hvHS@A^g+{~01`vK&`>a+pf8YGxgem+z0!Vm20tD|FK;rZ&Antzv#JwLv5%~y+T>iaJ!f78P zT=!|8e=lGEQ`Aqth|u8R^o!X3r#SrghjUsLFl+MDs(}07&)ffC2>(ArkOflt%5i!mR;lsa)a=0MC@n1e7|{tl0rTQCP>?mV2%X#$!y6jM$`NW^3q zUvpyKiFu@%`yw%$F@^Ca%(<*{IvYTZRC___N}MDw!98DNq5F0wus)U=}bF$OAk;Hjo8m0BOJ&U?eaUa0C4S!A}5O zfCe0COV>UEnt(TeJ-{o#7T|GUBhcL$(E&;0;rJYh4m`khZ(js=nUCm96#m4onARim z5}mM~IvO_O-h9~58BcDW<@BXYPsTszezq@0;DXQ51$T~m)c|-?Ofm;F5 zhwlJS0dD}G0_PFYBwz}#2(bLf39W^|65!jwlfXXU??3{0*8w>|1@NzWNMfE?wZ=D% zW~8)_Ns2mY>osHc#&kt#b)wI1Ov#6%Ffr6)_;;$b^I$J&T8b&@TZbv`51fMEo6|8E z)5CrN=6=jlOcbK73}Yx}Ii?45A?8v{X$Nn_ly>k=%u38=%qq-&4o%cYOT)YavlLU> z#~UzfF}b6%4nsW#zfp?crY`KgV7Z)KoSD(gS3DIC* zGf*5VZ*Jft4%i4J08aqcW4s!8Tlf&XJ%Hdf0oG%@8hFio2%d%#2ws9HgZbF;+}I0V zl8Kjg8a$7QH`m0gJ`G--iMPST+t>x3uSil3DbJ4_{w*hiRUr#=AH(x+Qh3f@iugUC+WY@#CyWT+j1JbJtkh0iPwA@JgImj z9toHd4>zXuSn-f>lT5rc6Hm6MT91JjrSxj{V_%2;h6T}DDMSt$gtV50a$bJq zd*gDxFOPg@JzU7OlB#_$^Tm?G2mz zD-H*%JtFkh#5%NFD3mSwd%8QcS8VPN#yPZ~*}k*m9U4Kl<7c1m&|a{8$Mtb&kK4YV zz0jc@uzlZuk%QUch=0!|4poO);m;lD&_>(%eQ=ONyTbOp&F#>BY)ilD!4B;d`~sf8G#>_HEnuN0)c}UUQ{Gd)wxJ?ofvs>#+Dsy2_#b+2)>jwL?pzGPm6G z9(HJ>7)-Ig*C#u*ncs+fAN;jboyBjt4|&e1J!q51mgk)v^kXPtsX7)jN^|r3g^yIR zGDJhJQq8MNF=gn6Shqj&F3nMCPRnqR{gK=}1egg(HR%DQIW2UpNBmw7j02>JZF>?Y za3bR;nsz@;<-)(w`YpoI9zOKDrEpi63>`^zEm7?BTnt~|k*4-+K$?iwBc%xOnf!ZA zD?iNpO5iHXv7@|oN5 zhRH(dPD`Jf_Z!qZt1NAH;@5Bc9xjOI@QiQw%Zmy}Oe7L?lh0kn^a$}^b1I{@F z4yqBp5&z``{9Th~Q3slQfNR8Ccrs+>#}xQigfFreSsJvg_#5Fy(!lzT@KS^o-cwbf9U`7g@-=J^hV1itIbe!|sQs(K*In z^i}eJUH2u7h~61AD-}N$Pllb9{#+!gc(u~*?Bg%~&IFRd;@4Y^seI{VNCa}4p3d@pge%9kR7=CeJ{5nZ(NWZ+n7U{9BG z;oye$a3l00X<*q|;aX{J*hk9lhz=DA<7fR?bkAfO>0!yZV>)!@@2mq?h-X*-Mbg45 zFGWUO*PG`We%EoZ%3aZYd)gYhZ@07iH}cE5aA3tp((TOkU*~Y-+en*^{>~-zNSR^D z(<(!)_zPc#oQ?20=aEzWeYx-@oQU2>(z}RYBW1Lu|91Dz{?0A@uFJAW{b$A3(tqna zq7xnY6Iq?hGaP&=gCrkx1feVCoaJtPTc%~-+26T@{uS<568OI$0rJc#PixHM?|uG{ z58FP!aAVu&eg87(^FE{6KL5u(KWL4e`(j(`!JAKBzyHP0T~piI{_1B+5?08l0(Wbq)%e%P$Gmk}IXj$~WEKT9JJ8%IY^W`$WET)VP_AyQQzQ}x+ zF-OJ>|EV~L93)JkB_QL05|1zQ#NtVK7j+y3q?vFtrhxT5mUkH+lrcmZBmA=Ai9g|4 z#@ep{1_Ls7FLC-Zj|)#CTSf&n#!9tfpaNJ7EHh1+VrQI`E2U$qog#-}ALk(bEtT;(skOIRW+ zN!Qx}k&DPo=2t|YzQmJoBhv{vjAKv4v(OPeDF)U958?J>)GG*ik-Zx@4-h`!M_wf< z&IE#^@`~gckrU}0A0Rwva}2F9?tT@fq|29h5}sooh4$3tz%{@qU;;1|$OELUKLY4q z2yxLh(NmN6FXF$Qckv@SPH`W*fc6_B)&pMQThewm@Xzo+ANeg|r5AAZADK^r*ZDvx zkntC?>(42YzDZF;*isBhktD2~N#^1vybGSnC-Imv?~un7#RrHT+L!F(`#xX}@K5lM z@Al`sOG#d6&jzxAm=!n`0q`z5FH;+dz}d)M@h*8p%Bmqiwx(VAvZj3xx{m+@-^32N z{44o~ns(KzOl3ho`CUF10W*PXfSzZ^f4kh#F_kB!Y@uA}_Y+O~26T4-KePB3`Tvvp z1BDKc`vqg%;Of0tmjR@?N_+Cx*~nk`SNT=)xF{U+TNl9RVt9TY_&xAb;s15q8UQKp z{zdu&C9VHM=qU6D|CSH(n!4)7q< z-O&6UuoHOT|FQSoQB8E~-bqM+gx-F?0D#}$@~3d8JkPJ3Oc{hjz+b~b z{saD62l}Ac48?W|0gR@A38KNXS%DG->~m&=_RawR0{(|V|I7)0^iSb01n@Wf|6=nL ze`N#!HcVMxV)70A`WLwV^&hAJ(s>O$CuJ2og+E^h5QeJdouo+d;bCdUp7zi zR}hze*%$B=h4+;2>VE5-5^pGL76Jgcqd*&qUjYB$GzGa49Ap0%@>c}?|5yC~gTL|t zUV5NLdIo_cfa^K{D0V~f*BAi4JaC>;KTzTlcwP?RPn7=u9sDWoNl8n8>#uA$@Tvni zH3Lw%|LL!az+Zo@8KTs06gvYO8{n_-Z{+`rJDfrUKnbYT9|Ca!{z}QOf6rfkwWG9$ z0)UMb@Tbg={yX$fDQEst56b|51wLss^Lt$n#oj4CTM6*j{z~!tKe@-2deNZ?PYczy3PE^45TLRe96CzIJgg`_y_rw1?1NYz+Wl(mBO83^A7=xi6Fm% zIQrNAN{O@oiT|-b_~(O@ZUB}5Aou;hzQ2Pj|HDS9pDFtJ3x6=)zvfmHfcZEBvj_RL z1e~YXJEgXH25=7KS5^uaii1<^4Enp4rf{c}(to|NngKO{Ykt+Ym%y1*0RO}MDgFQA z?*jU!j4ws6K&lQvAO+wYMduXVQ{p`(?sLb2^FjbffWP7X_xS(HzlEUfzli^@`Ulv_ zuRnot0TMu{_IGVS(K!Kt;_xYtc^jH2^l07|US2hf=U=YdcBdhvq)eeQp&e-7YR z+TdEwN8mbd0BZn{Oa7mvXtK5!U-3E=;B1O5G~ z2WWt#)WP7UJU4->g8mNx|56_RZ6_3a9{^|vpyVjNe9)E>Qz<(82R2XPPkF9iIUCs4 zuebz!gfH>;yd*c6xBNAK7yu+1fHJR3;X!Fjx$d9YC~YZz#|Iz*0OmV*@_x@B+D?GK zcmZ6W15kXGqW5F~#ct4!GTsz|pr&L4f}&%}?%(1UcS=m6G!g;;*Gcz+cnkUwcn9`# z0d4?L=77`y1OX_WP@dzTc?Me0juNv0?_ck^cA)=0@cW9O|5N~qkCp;Z;ys1C(LBfj z`k*Zb00IEq}e;|kjSInMtLcM9!a{3*JZ126&r zbCFtWzsFZ;4D1I3_ybVls4W0RHxxUd_yVxY|8}E{6Xm6x(!UlM)4JbtpA`LI0ImXf z0Z{ybJsPy3j1|Qm{t52C_)~$li~xcFhrqC<{q|ia&>#9I2wTU&ah*S)0i*%|F91ca z|AhWot^?Zz@t!>jq>$;~YbH*EzU=@U{*Wd>@)UypD1<1_3-t0|*$k!GUjXcqIRxAT z#7zEz-}8DWK!22bm;%VQgYXOV!X5+ELdk&?yQKKzAGQfT{g)dH=tC4h0ze)>89)Vq zlD{Z(aFp*Ycqo2G@pH;}0-aEN^&k1`UwDHyzdm0BaT4?)3_!WhK>%3*IRF^|NdR#G zE&x`FeNo1XqIU}ZiH-R%xR1eq1`9a$Cn(+gCtm;TG4PF{q!^rOg)ef%F1yYhP<`iG?YE%#`C%bhO)jJROy*VV)!!*NFd}h z-lY2Uz0Fkbpz72qow3O6QG5T?y4yF4cST7I3?ni#{#cH@IrHa!oO@-BVJ#A*>+cCn zaKZ@9a%RlNB21!(4ePY1J-c-I>}LGe?BuAGSV&r=xC?aeI!E|9Msu9z5f)H1Z3~xkfo4$2cbZr4_j+8tKgc^$(5O_$p>qm) z>)`n5Oc65(PWvJC^kdOnwWxlt$T*x0qy~GLJXAuu!%zM$a~p1zYKW@U$_n*ud%oL^ zI%tFmaN#-#Mc0-O*2}ZJFy<9!2kd}C zQ>SDawgsZKL`fUoLAxq5Jf+1Cx9`0n5X4*}E^#AWRj<>ZCvZ!a(T&!u zYjN!^KGm+jHNP7+jN<2Qw@v!|{j-2WwDYSEx2&p9R7aTc=y>Tsm9a+m;%8-)r>dNe z@7zN38rz)jX@oXuk`g#W{pfPKIDC?1S-zME`A6s*QHvS|xW0JS7ykXByw}5h&+(|R zB8G?rpAS7Q_vG+_Y>?s^R;9 z5*CeiaFp^Kzi^@TUO+x=VbK~@1LH6$OZ_t1=bZ;E>vpRUHn3yo(@Z>Svc9bt=5=9u zA>^b(w69nDwtT0;r`Hkv*^Gqm4C>9h`b%$u=;Ap%$>$~Td#ZnZbroLba43P zoj2@FR9SJYLJ-WvXZ7#XJ#3W>b_$|B*Q;+n*&RwGtXW6Z(f`J!hjm7;5sXupx0WU*bQyX%%of(iDAHJ~|~Qij@w~?E?SGv-y7M zg_ zgy9u$>sViM!j~L_S1)%@zJEh1rz6$f^O{KZ#(pp(sAo7lm1d#OQz6XaXJ)3e(yv^Y zE1_xZN;hiLmt&i65+(NttrSLj({b#)L_J}f5?h+MFmBzOzNT~=VnsaYa_y=~2bBco ztj!iq?ir-+G*|M}l&;2VlP^zeAr*~AW!vXCvp}l%{2Mr1D zWe3G%oZgM&p$kqdJke>1)o=$YdFZ9-!+q`B*f$M9xa$rR$t+Rpy6@9MkW3|qk;>RN z<)2Ox6ESL)g6eQSY9}}!d_5(O_U1Bnfd|jM_#mbwWSV5oohwmB!{&w3nu}sIx7u z(ps|wPLI~pGh9n^X!?W-{VKAU5yQLQ-XD#@octL}ef?SUTlU3RdOe0S(n)6;ias@$ zBP3^t3MQI~H$Ma+XHc^tb1!*{4U_bBzl{0!N=iWC}4Z^hOUEO*Xe* z_YB3dJTv*+hH{9xXH0x^B12r}?40Y-AM7>9h4gai_Z`jBN*bIZ4jqvfc=^aLSce&V zbmht^5oR@Wy7qP9`L$|U8AVN+lco4p{>l*9=arS++C`MUFKe5VdsP!?$^UexRLo4y!LIz^NV*0tm*g4hEcN}E) zS1Ii{ymGkknTT~Qf=2s!sJo>zF9!EvDh(5WRxtCpT-NcS1mnu;lZmyIW3?|KSl3-O z@0t+w!yjnC9LSNl2d@#3VhD|_$$xX{Z(n8{ZE#13I(<&)~IbECHkEh)jfs)r1%rY;^VoH>zM*V;=0rv<7V;5$EHKW+JbaAFRW%QbD|Lf8$R zw^#Ixf@6$>{Wf#Nt3BsK$5_0iw_+jwCo97C#0OZkCgOzbtr|PObB0zg2J`IsE9{WX zGe$D`_(bjf77>TGpYE_#*CpM3WTnI=xqeA7+AoR3{DdQ~t#OM_xjg!|@+?#mYR~1C z8-sA)APgf-_z4g2%9ShE$xXIFFSRp94D0GQ0^n)n^vE|pwANEoA|D09Zr_E!$R36> z5751coltu3Tsa|+Wzy(AmbE{MusJhEcd;#7lF9!$)jM&UNg8Kyc;09DYa__hMz}T? zeuhy>g4a3L+A;2AN&uC=cy~fnO9Ry|{b!i_?dZ~i@`Wh!Uh9_2TK-LWWmx=rr={sp z(eHV3ryT=JdYGCaM;TAnIOwNqfElP~>Q@O#flxj9k|8;N+5R*Zw2ln~cOiU?F6M?^ z-mX#qwHGL637_5$9j6#y4M_a8)LSf4&)}gtJX?~XT5V3AQ%Y4dcjWM8Gt<_lGUzyn zi3G!Cy1dej#~oEmF=1)j`F=;%a6)E~H$`{6&p38)rhfA{pqn9a**$&Qmy>Ak_NhfV zeD^Dk4o7}$ZDK4G11bMROGG$yrW+|hqcp(3mPR=1F?&OOkXs3m(2FT|6BNQb%e|+U zg)WS6R$hhfZ5ahEKu@JQq@r(JNK}SBzuvMW3UM6$+4M9p!kVtvAxcNmSE(+t*N|v9 z|5z3|yZ!XJjEmp{1FP+Eo$g_%F!F#AyP3;Fr1NvwNrm=zxLSf9oFF2OP4gs;?r_n$ z$lG2t<=7RkJ`Mj8Au}%;dUfDYfgmmVn%n(@Z~TummC-quLJr6{QClf=K2~UFa$uq< z5`Mi%XHRad`*{CSgv~x%D{CE#jQ0SI!o3otuTT423CVCrOV8c}J=T3zE-G9yl6tPR zn`>OY?D6Y^!AngsK5tGn2iuf|Ai*-WFXcclCU8299RgH+a`}f00YK zPt|L;EtY4SU<)BepwCX&jRn5UO?g=I)Ct?Bh4Q^C)KttI*eh%E5Qb-9`{-I(qA;oFJ1GgpdX==>mGOKF0(Wd~29jPc|jiLH= zbs0^{64K=$Z@*+AdoUcmz5eOF@AZ^Er~Z?0qW+wIQ$kJ3(bUEv)|Mx+Dp-(529GvZ zWjZ+Ac|Vqef6U~rL_2}WMC3iw?yhBJRd1x#*@f@aJl}XL9t#(mBA0kj1)wd{D>f#I zX{(?QE>+*rQ|n0PP!~TU=>>l*4t-+M;4Nn|k8{c;$+|(qoZ!3WkbC`*+j=uk?lzar zslaYJL>tc#e~7Eg_daA)98T(!Ce2Yr-SjZdfs}qK>@n~dW^E3JPGVTXb4#U)Wv<#s z^r@~E#5rF(MW}osl_B^1 z(kL6Y4BnLzzgM)~@YI~GW9ra?#8o~nHN4S^3MolH(0jT4F%^4Hi|XKsFJHxj-iu^6 zpf;FkS%Wznv^PzcN=7H!ddu;_c^XttsNUcQWV8EwuS*S%vF==*f4|_8^L?CZ$H#u^ ze9_L`;Byk*vZG#}FuD^#d8X2g51wl>3@dgU(U`*WMq@}>&XM#QF1De{eLrC>V!^u-KqMx8rmi6WcK{wAwZ z>a5sGlekME8H%aPv}x(n2UuWoNV06?7ry6l5^T;D&Ph4W79m{dthUxZWDzzka>&m| zLY9G9H+IPV)qz+R*+OI$N8a1y71tJ378~T-8KM66N9NtP`zd zS^2#jTTx2&RUv*9Kd()?ge7;oA1fC3OPuNdyjE%8G`yXjKuIrpf4-(4Y~w5 z6OfTs4p)*nXuA1=P95Q%a7Js$@2vj!NGE$U*Kxm4zTtPvuO8lNK?WTR-4G_5pE5%i z*ffdSd_vLceac|k^*X?QD|fBh_tni;@*Qn9wY{k3`+Q^g<}CW+p5ghXTF)It2q!kL zo3#O^R1P7S1E4bu`C4&vU#z_%mAY?~g5tFl&C>Nrk* z`6f2{WeEIFR{?<+x!5{K3DoF*m6x+lhn;G$4#&E9(^v_3lHI8~S&g}CwTB+hc#S+% zE!KjvXV&9nZj~!YUCgU}{1TQyB@q2hr~UIryWbR5g-3hF@k6Qf4^`c}_cH2u!>*L& zyBf+l$hHrv1T7bmZd*;R-p#qRX6x?GO6Yso%`r@-;PERhttgq5z{ZiQv3o{XJcRC>gZ%yQfx&`Fb!0elw66bV{j%rXzE=N9Sn#L8$ z)ny*@FMO|}@A2m8k&4p(0262NCivUVJF3(DG9QJ6ypSPp}uovuq@7NC}UWB^?(HEtEA&h+&rKh>+-zsprL!OMRd#&sh|3S8P&bgMG#v3zt@;MWIJ%`Zko)rZX?7 zix}j+nYhGK{D%H6heZgi*e>&(wFWwguMYuz=V{|m&%OeQ2VAI6`T`j$q$ z;GM)A+@M&+vAIG@Z(-C$NEt#(Pn`7Sai-b%u_>Tw=LXB7y~>!edo+|Rrrbw#T5dGa zxDWZ5m#cIu&wa$=lIDX~EiQYC81_fb^WRYZQ$@$M=dR>SH9QDL7rz|YtvkLH*v-gv zH>{~_9IIrFXGU-E6B;%y-LInp)GS=aN0g$*G?C=;i(-dR@JFrIL4rk%UtGuXFW zgzwn#ct+H~2AkdJmkB7p^mxp9YvR!3X)5;PJOh0O<); zCU9(jH&Sum6(Wlju`exl`(l%f$TR=2Wv|4SYX?my?wxG!5`^V+JdAS`;n;!;d*Uy# z%%Vj+5hgf-j{}atLi|c{>?soF7h}&>9z3b5ceV`DRPmOx{%b_4Ml=1%u_G-*{ED3D z**d-YGjxNKFh~TG#gOM^I=m4)*a#LXCNvbzW)lX}zAoA9CE5I{?&$V9$K~TnyVg8~ z*(EX+?6^9ZTjmRK7TZTzggsI?lq`;UjcnfyI~&_hxR5@5Z~-|>!W+TN) zI#R{4Ovc3&%@%pFFu|=Qw;X*afFb;ojL!hBuQpcufwCKKz{e|sk@s$)MixHiOqnkZ zz$4p!jD^+eFF8VreNc9%<;7r}&G*k5A}>ucNPfqU&k%PvbXSxyERvifI|LqvXJ>AS zv8SU468Q14)RQn{->CX&16?g=H1$EH3zMEWLSO@ID~MyespxDV=E4;6IiyiQmde`E zgLc=i)|2@c-Kq0Ti&DfdQQ_i)}NN6z)E1FVOGMgR*kv}(V|^=oBJ3D1bChdI)OSb zqBjLib@=Z7k)Zu>^4AB72QxJT({}{5WzeY*5B_QxWB=KMZCl4;P4&0xziOO~8?3v} zuE+U6TY!gw;7-hCEiY8pQr$5%)1TYaSD z7EH+pDzQ_9$=vb=Z8P-uCjG!5i*9rmjaV@DIM0?WmGb4{?iQI!h$ij<(qkB5i8ZVT z$q*!YaxnR63w8-McCqPP!m$?U@VC-9wLs|iP34`h%AsvOLns zC$~hQYXS?oErPx8I`!QUy0#u_mrX>^yvjdcLMr0t>F3NFf(%{=P1=28m%k1dDlVWJ zS!q%c)Pb&&p8c%7_hsgOM*hxW(r|8c*0m1LRcv$4k=bVlYY_w?O(mk=v6m>Ekgzz) z{9R|ra(q3GDSCN9DE}$#b8PF+Hu{tN!uIO}DNv%0gS=*z7IrRV z>JRDpS}TBi2E+cKnPy_dCm&Ro4aN&pmt*66+|EI7$mgv=cm;)KOmPI=#vjnGa(vmz z3scH99<5f}ruxDeaoLCW*H-u}$G$Dp`T);jK^FI$^~}Q3Ys;Bihzmc(gjNuZZ1MLo z-;+oSkMlOUeYQv{16AKdLIz&ZxUX~=Ap;M@dxhdpG??m}UUcO>Xw&qzLp$d6yJu~l zUv216)d517cPguFyYZ2Aki;Fmu-oiAQhSp%^S{ghwn4s8Teq3tY5canGc{7+@P}$Y8TWu|6 z?RZ;A3*HKgGqqW>bIwwc7Bew9mEb6vsl6jRzG6#$5#8{jApMH0aKC}@JyV`G1v`QS z*9R*+T;A+P^L4V+@ppL5YwCqAT(={FU&}6z8TYi78R>2Y282%M9?T6nG*^D!O3n8s9+fj=NKb|d8? z=a6m^RkCdZtzlzdo?2+T1v8pO4>9FAy|5g1!imYE|G6V;h9>k{D6%(~TAuhQ+f;;w zKjYKkD*a&W@{&P{g&XVe0Mm5i9#?0HFIJ6sQe;3pvT+`&?eI9Uo}te~c=Lu3EBb`x zL!!pTF>8`%KSVkOf7ao#PKa74+Mqp2{jlyMrubD_UO|gN@=}3edsbw6XV!X0iOC9* z^CIg&TZNAPu0!P6pi#!nt$D+CagRHZV%Vp&?CXtk5I^rH=eH(c!x;X(an|fzzR+1+ zB68ep){qH&1tJ$oeO-h$Ir0Nl;HODte=Ye3Bj8;O=F9UMlsyc^qr~k<_|aK*mi=Id zb`95JB;+T;%QS!3bMEWCIq?^@^>Z(0uphaIkr8n^;W4Y;`YAppgD*r_D}%A#I~tGk z-kRKf+o1;Qa@peC7;?S-9+YoGBF`!fKU`fgk8=rn8^KL-#XD6w(c$B*(KGGJ)n}q& zYSy%=Z)!2@W7L}cPZ^?)oxg{1J#arNl&O>|R^v+{LO(T*k+_rMHbAiNZRe*Cy69Rv z$B$ag)~w`~hS74kgSUjW(fq2PF>oQlgBevr%kg&>%|s9nrUsqlmk0@^V+hTnaYUo@=`QdJuD)IDvsR#dA>H#AHgwhzh&t zH?LMbDofu&P3*MejY!57g}yyyNs=cMI@K*ntaJ7zi-f$rTS{8^jaI1hss2L60KUmA zII@S7xACqsfItPCh18^4LQZRErcygH-GF1KP&Ory;(BkymUNqxyC`BtzH>J>{*KNu zEB3)B@uBxl^JFbQ6g8|6R_K;(&WakovoN(JZc^-Q;>wZpb947TGxY;V+$5sX#@97H zY`-LL1>?kicdm27d|Nj3XA-IUV9>4Jxw7eyVRWb8apLLK7vdQ&4y6RIU@R|AtFHQ9 zoPJ8n@OzqMT2hGUt_2&HMr~$HN zE}aC!gnsxI#)yefZZdm)HB|uO>Um73@P)O#MLac1e+lLlL$dbwo)WqD{p&}^z%3Go zLlJR2ow&=Sw}KpBb=@ss;q8zvW)&3jK}(rPU0)#$CQS#P#NlqUmo60L4}404*e>rIHoW}P|6whL0?|!`z^EYsS-Qlx~_;- z3J%X-A`%XPY!DUG9E@%==Rw^)Uk=@VZARm|w#T-H_J`7|7ATjH+Zl)t3D=cBP#Lhl zeNOcZGcQjjvp4Iug@_D8y*3Cg-McHZR2Qms zmza_G=-Rtpvzmt6T4Ky^4+e2+Usq`M(qKV6-2Px{6y}57D=kEbZz8{}5Cbrd&BuA{ zt|qy0?$Jks*zuHg* z*0&-f+|cW0pWplP!1iUjB~xm}I8Mk$Uekg5^(?%Kfh+qCDm}v_>reGWEKaZP84p5K zxeXn4O}J(u3i6zY3tOadBzbMyQ7_rYyq)u_t{zS)5r=kvm1iy@0=)0D1OtC`u5y8k zw>^;w6*sg$ocbep_blF6SK1r(h+1N4B!7(d$ zDG?cAXac)Kl%QAp90(8Hx9PjBn+x)m_oq-==mnOof%~$4G%HPE<4&Fiun{!-=AL$p z^yZb>qu*7N4BD%Vr#Ck6EHWrmk>&PrA5D?G;lMNKZ*(`LihpLcoIlX}?zxGsmNYXv zVr_qdv{>>pv<{_Z1F1FihpIx)^6NXFNJ;Z+c3{t@y0{$AlpC{>a+)N)X`<_FeYS|k zoeO=Eht(1zII;TaeLa3#VjweG*V1BNBByp@5~ck1{1XeGTAxL213H&z%Ob>?$j8Gg zE$&5Q7t>u9#X|j=##IrinO-^bBC00E`djixC+OTy{bXQzEdn#7W0dPq(5BZh4==|$ zREM$fC`6gJQ6ul!_+F^Du)ii`2jPY1-Vj@;O^iDHvLNpZb4CmO(o*miCcHL4@ z?ZZB7{5se8QRMz4_56ZuWb5qFG8%Sd)F>+Bl-gZ5Dr}iG+w>9B%&CNY1KrKCa5`3= zIBH*D{cJ3!5`tB(UE)KcwX57;#YVvP76sJR5fwvXkj-T1b`wK@PnXx2p_U1Fy;Z+vAL_X&3ZIQ(~J4Ik8)|)A$osSmI;f+>fGZEq&_Xk%(rRbp90+| zOZIUqdO7G#e1E|!9oX^b#lsASnGl4$S`r5X%|!UU;|1Y@Qq5IRSo@h?$?NBhN% z*geMyvI??W%fH(WI`H)I6)~X#qR38%D5>sYsPv&tYb!N7@I7_&uxIjz1D(<^RU=|? z_}8>JrPMCJDdpiOThT3vQSdr51Kp{y_!&FQx^}~7sC$m^gTs{u;na6_XKI`+)6SfU z(M@2#%XRB5zDktjv*Rn6X14J_N}ZnD3PyXM9DKAnd7^e&YJO8+EN|lgt5hiB`Azz9 zCbK)Aji~(@q0YsX;YMebPz#1vQBLu1gh{MqwRlHH=mQh6!vXCVS*2wPtHT!BE8U^` z3o!OIsdc_S>mf0gRcV+NN6ST09Nk!QbH8m6QJy?;nf!y_&9I%HY)tJHJy?$Ildcl0 zJ$B!w2BA}v{Z2TKDh59X9TPz@2J17qx+5Wp_E%i?jTjjrFRidUE*yuhJhEY5WNlx; zEYA@8B#1OiZ*_&?f=H}0Q{`S8zi@_?S`EEyhqs)1#6z)oyq#hDE!k{Wp;%W5?9+gk zjNEr^i|-MVI4q1{SG^=o!bDIPztLyMMl|yJ+>i0Cst`)|J^@oTM~A;pj0$e^GGmP7 za4>Hd&+zHk7Kl<)xZtez=zOYlQq%(f0g|mkXN;>j)`_>g;zz|yux`xT(SpS92}|iL zM-SYx7ZQ)MbXjB}7i#(R;;&?#q92%?m`uvxXbmASnA$_HHlMgQK*%>FKddM^0uOzD zq-nb2=UC+x24}@m3g85~(3aMdc}{A2`Z4$6p)+%@FgJaQ^1jS?CVMxXL*C4enHopx z973wy&?MlILCgXIF|sV=II6A>Rg6AvdAHsOEL*SgCc+I|*jT%1H|5krVA^$DlRnRoOG2Ku;HT)H z7x(d3_D8YGmx>_T>c3v4-SL(F#*7OoE}*$PjZnW%W%~+w?`7UOZX`rnbrLUy?i-%t zs8h1KLbZ6}o!c7ZfPlk`8_}RTNh1AlBo(F>T@E!ek%_+p*Kl)$E-9HrS6g9iXtukX zSBYKsNwfD-_+VM$C?h(d0xtGB$bue+XI?k`5H2S~LOk+pfDLV)CyR+{{y}o@L5EIn z;tS2O;?Okg_?=sSotvL{8J7C!=i`i*_DoweJBgFnQ@1XMdzC*L@A z-f#`Zh)P>maJ0C%;aTytid*VCbLqrKmxCU1B7|#c;o2-k=`RYd-aaO#)H0&a2%Xw@ z{vt9LmUXWB19vjy=xk5Vl)(s!e*h+(c+Sv|+9!)I~$|()5yrXg9ZISr9MzyWOE; zA7jkhmzQF%nM+$@xGsyJ>Un#ZlDGy5$v3$@)>P zOS(p45UPo7$@dqTlpVL0PUxQf@X;8S?-!Pl&nqtruROl)%#U~ls`3rI;P(b}AF ziA5E-u#`vl`ialb(}_Ug%-pcmmvFCxUWh3nOTsJKn_7s7FebjtDC;C~7q%PZl%(>n z-ugd3igE77zP}8D56;510b|G>eu4XV45;qCmVGx6<`ZXPj(>ED$1m<>lDg3n$=!vd z`0a7<=_MI%Ylh#uEfGgZG72robK^31h&)e6y4`i!lCZ#dhQ;tum;Q)P|20j;noY>- zyvA$J6}}s5{u8wwlBebZOf*Sy$fD056a?>C-+m|e+(4x52eWeSi?7T$>)RjQ`6Gv@ zuAXM;nPK3zPQu}Z8;`)9u2D57E63x-IQ(e6Fy{qq&V$0_%v0IAA2ahKYy|Z>1joyn z&zuQS!X+*eB{Z|i&?Uy3j?rDMkhT`O$?qXwx!L3C-e_%tnMxj)38-rk=gurDJ3?SD zO@K9Ne%pqLy6&sw4LCEpv+01wOK;yn%$WnBQPvgu=Zx3~!SrB{9*7{{pVMg{LR6$H zYik%m!0gJ{g@Qa^`=qFzF$-V&I6pt2$9IC0FABCY-N`6F?h_I11U761DeU}Yj3X9U zi^z|JsIvx#*yKy)pqYokt;RY>D^}Q?6pp zpZoRR2KetXYzTcVZ#27uI0s_JvVe#r--^%QgxgvYz+{M6QSK$%Kvx!cEIjZNiYVc5 zu3r?xE8j#iA6V?Tnt42MTKZPRh+`C}Jrbp(&y1=#J#F$6RfbNuyn*9IywMR|lf#FO zb;cS;_IqN!CHUA zNr_UKnzzpx22Dki(yYS2xv0hCpAi~bN87Y(#3-?C0hMt_ILYN*Tdk!}Q~*M+E3q7U z#1eDlqqis`x`4>o(b6`#-s1DNeCaB#Tn6LL65cPy`R*&TlxU>4%FGr-UmWI9+OJmA z5+?UBHNm5G$5u)Bvm! zBx@$O7EAJ~DCKR?4R+)28|sqo(1SQO)s4^Cl$A)3teTxGcu_EOMGQ;R*t|C5tuQW! z7K1SP$8x`U)nt=AW`9yIeAj4mo0IpD5_89KC-%WRk1f~-lcOvg+3$vYFpGUruzZp= z$&RT=29*;ZCk|b@y&Bum^pfI-c>!D>lHYku-K$JXhVDL}Z9IJDzP1DR!D2_~U@PMu zOJw!kbJcA^RmB1Vi-}P)`Bw_J>gA5urttWi<@xS>T+%DXoShz{u2{ICUAs(VL#)jx zSz0I@*18eJbkNeGEoyvE;tQ|6)G^Fmue*8Sh)rRl5mB8_le#|DTrfvM2!*Pd6BLQm zHL8IeBbZp%Z7e^T_Km$>2}a7_*OLXY9C>GPUYC9KNr|Bq_Qb&<&vX6H=C9Qp{Jipm znjcilhIP&S1*aa{UaMLT-e0>-KeFr&n>|aJZef*QWJ9R<`<6OFcWrsv`uK6lk&m)e z$g>WSQpFMP)7DIW#fR!m&1xM;5D}0c*7K_T{MHYzyzQrZl@~8KsU45SpsEe zhEI$N+{ztK7vsD)*C`h?A+q!M(sW;UBb5xkxYf2~k13j2eHCtT25)y)n!I&?q1%f2 zRj^^Z$hC`y4RuS{M*6YR@{vW{z8z!tNjF##;{6uAFy`*{JbNe@6K$KU)?}S8&*;@2 zhI@$}DZK|*oLa!OJ$}cEShC|O@+s0*syqTebFP0Q7b|Fa1YwM=3pn)UzV-%&nFW~# zd3yDD>9@}YbuqN6s4Nww%H)E)lSMJ}(;aDffhl2Q1d&kE8EKR%mSbVVlg^!+)`i;; zf9%3jL%bsrik0=F>6+Gk4z z@k*b<(AXZbWb078NljmZu&{gd=u-8l#lx-sI|X?a!%X}#)zpg{>_g!CRfrt3ha-Mt z^iYUzlj$0kGxQp7?@>eqQg+m4`gUXa_^{A<8>A4;)D5gLP35i0joM>vA5Olg%t?-X z$BYmzrJ416osu}ZZ#f=$D9DUgAcXq+R6H*)`w2Z+9&aSQ5~w6x;JUfmHtx_>d(mN= zKERS8*qPL{zk!&wh}!1@ukQyfv7318!L#_vD>2_nsyL<`VUm>Dm!+K z382dC7&XxC5he(MiasH#H5nRKVfCI=wJKK0bbAt}(FsHG*mJ@I%+GzAye~ESkG+`635rrakD6u@LD!kaGkWpYJo!?C%n2Q=ZVgbnWr*pXpI;bWhN#R#_;QRAIL=fGRl4uaR?E15UMoJPuX z$FQqDNqtL~{V3f&22B0&IF(&moSmu^?i99EG=Tr)-@I}~*y=+ab7UXK0Rwt*=weih z>LWD+>Q^YKBx+d$9ee7Q6zt-An+hqi(0CQo-f%Bg%3YE{HwV7BYqJt@w#@q7Uft*= zS!|>VEG`8Sh#x+i`TZmQLodJl(=*FM;Ej{Rsl=JLEiXM8I)bspuybo6+p3s+a-&SI z(5&LJ6~spDyjypFI)*V!d|uf7ISCbxjP%~6KM1AuYM<|GEXl?AnR#7eZ9HC9^{#+8 zqN2|K`XKE`q~^M|{1)h{(saLteWtpZFOC&?@4POocNVTIlO-0o4c4##xzL7TX_B{_?1Kq6Cr0m{z0Ihn6R#* z7^4w`3)XVbV=erNtmtN^@P6CvrAA4wXHqugb=PilB;&n`$vQji;vF75?t0XKS4sIt+t{nHmeJYX3yyDPRI^Dgn@ zt(tW^IE_%8-`MY_if^4fNynJ!y`^0@( zv)k&0MSM!rtGq4RFdwsCfLvFU` zD6yTi2Y-6?eRT=Fg{#jw!_rEP*cCy2kF@_PF4*XG!A9|}G1^{ObiUbjcGs0mi;X7P z<+{g=)_IWB6~CrLjZph`B9+!2=AIzmGRVCVwSNt@7cFprROQz#&U~}DHjsseL*E#} zKn~V?FXQ%2#boMm{g^l+c|zFi3PJPc>k$u25|W&%plM0Emtxv&POQ{w#Tz?yp2~|h z$8g@dLJqdP8Mfanw<9Lb&4#}l(pSV;829q5tYM}Aaiz0tYI)4MfaY!LTR!+Vfw(Dc z=u9rYC1};-YQc-mv8k%c3p(@&O@Fu|a!UHZr7$)V#qAh~#KcwHQ7G96J`^6ku=!K9 z5X9E)=?#J7A_#?PZaow9V@UlAQSP)HXGLW=_?r$I;s~6NBfooVr@Blh>EIED#b{oV z@m(V|Azh|VPWdWCdsY)(r&ldRV-pv~j3zL{9IF!qW|$j}t2&IRh6^I`B=%1hmm#90 zFeN8heXQ^yllpJSY*-NYZSC(&qIb%%9jb{@=kX(mh7~%D|LBdVQx+xjTdKL(-6dUx zw~-PM`=F+2@2!AAVLE*IH6kq$a&tK@tD=L>jjhX_m3YW~JY}%tDMy%A*F5$FJHiIGlyA@f4lAMynG~geo;pO4eScfr-GRn;6lwfWX_f_IyG`o~H-@~&hr3Wa>1+Gl z4WMe2Y7C!Mqk-B>q2yB^v1Lj2Q(-^GPhT^~Z+7)0Mroj>zHrjh#YI6F@oxplMEUF^ z73W{6cy$hnLKCR*^n8j<5#FT^=dh{_!*^L@CV1 z7-eTk_{Pb{DI%2=w-jOFUZmaS}Z-PZ8JaMqh(W^LVwBIIy6{(~0j*6D_y!xj816V5c&xMz4< zqS#TL1y!yqd?E>ETq$9v*3*o)1gMN5PZc+AwMR_RL{u}~UTRfUvVjqJk>uWur77dv@X&O==hR$T7>Xd9SX+sm*&*GZ!4d-nQxrUO}b$^X-5SPqK*MuSm|%JI^{OuWb{FHDKj| zvipWDD=v&j7?z!X%Dlb*G-rpkh$6XPS(v>2pQ_KunMp+*LOdEL)K z{=o-~7O&k+#!k|F*tcdA6LWSHv3Dyp!+d{3vTvGxkgE9P660-2=eyNhp9K6_!3`nq z$5ZZ;hG3*8>#8Qs+uL=P+rc}QI}B6d*Z8atJu+$Hzf3w8|2h~kBc+OAU0XRAQS)wC z%;+H@oqi1$fURhczs+GwwH_j14XLI&Qivb9(6BE+PSPTEiqOvAe%T0#{tnhiLPv6% z6QlUr1rNipyOwVLD{KzBZsos|O)=pBs3fldvN6R}FfX~gzhDF( z;|E`i?oIosYapf`nL-AX(uF&8joVn!RPN;9prf84=G`&F6YVB0-fib+cIQ2NmbYG2 zt!<3C^%QiWvHQ8UatPc4fJ_BgLZo4QJA0>twLrTuc7nk ziDT3nMlQJi3OIx?o1vuONyaVZ2Yjym(U|{|i_5|Q5>@w6vbT9TgrCbcl-BwXS9h?Q zhLQO2qokcr8go=*VyKIykqVs^i?Pm`$5tVZ$Nka8pFI+S+!AM1qnKt|A7SVP-<2Nf>x{1som?brVE-VO5xmkfU8^7H=mh2Plq zhmSpYz=da@_S+Zz=lK_`c<8TR@T+T%c)`O*Z~VyI2mk!AU5DTP`1I?yKJ%VezUeJL zb?Vihf7t;~f4*HSaOmkD_~iSZdF_ff{nL?W{M5I`KK8NM@4M)c*FW^u-(Na%@2>B! zebv@~UGdM`4qo!UzkAN@FBzC|(DPsT{__t1z_xoX{_q>$cgZi^IcLF}o_)aCUpn*` zUv}VEjvIQz3-4HV;V19=t)Kb3hi884a|{3IBOko=Pha)w_bz`HJg)=OXdqj$V~(?Ku2an_!JPapOBFMnW;?Y({d8L#=$MK{hn z?10~Wq4itdde>ubzu~w~|BWS`x8A<+?f-V|ukQKp#Z}kdcKZ82bl@ciobk*r{%HCw zZ~OFvOMddNPXF=^A6fC)^M7^qA07HPKm8AvulzveD|`fVp} zd+UpT@uHu6?QsuYa?WAjdD#IcKJ6zHz~pzxl+UUU<#vA2{=pyMF1AWgk5F zk`spqzk5dUl7lWg{4K|R`V&w8>Uqcg#WgS3`HL?-=ym_|f!}z;`ui4N`^;tMJo55s z5B=5buiyPMFaNc#p1As|8=m`v@13#mv2R~L|Hcpf-DAfd{M#@1yH9`OT_?Qp?zcSl zi+6qJw}1bVpLpHfAG!I=S-=nPe?a&L4`}?yVu+`IFf5WGK<;&0g{bzjez}F32`oXP@AaLf*hduK6`^PRg?$)<{<}Vif;I8-F`mYxpanw=Y`~9~aeDL#L z`LW+z`>&7xf1kS3P9ON~89)Ebzklm%|LFG)yy+)Dx#fmSuiW+Ye|-PHowMjG9~+kppx;iCq=xpVoR7rp0}#doc{*=`i@1?~&5?717i`aiC` zp%GuHyvC2)H5#m+joBDwxx^SH{)RsVePAD;27bAI}QBQ8Atv46b#Y4d;ezn#DJwMYEHe?0fqe|GrJT~GUmCGY>p z>L35kgSY=;9I}`_ow{ro6q>ruYL7T-!}Ko2fq8!|NPyLzy3FFI_c3HZaL)-58Uyi z&%S2bYcII@n>X$FtB?QBgKjXC7~OdFV{hNGYR!k<`p1vG@q6WJnUH?dDpDJyz26s-gMiQZ(dS7>si0>$Y)Qv;tP+y@QJzk!6`ra z_|JaouYdD{OSb(ocLpn#j;t8|qcbnLaddE3ao;3z+z zZvPLRc2Tis#+cotaJ${8f3-c-W5{ksw%JD9X73yA#&#!^C+NrY&UshZ4bx_o_rtic zGj>q4*+$u9^Km<^qS#s7P@c1>xZK7*r1j~&ZGu_Arihon2UI2AT5IYUQiUUW#x`)G{2->Av_Ih6!hwPd#jYy3=k=8>6JM!OQ%gFkzP6 zmT&$fG2!Jl*LgNqU_$t8&gYof+E)7ySKICX)OoD)eT&huY=ZBYZ$pV?y?n%F@HCUb zVI5pdefOZmu8>{syDzc1FX&4Sxj(HmIiTZx@gwKIs&_`dsMF(VL5k$CUo-U+66#l4XZCvAQvocL#pd7Lx3nCD|p zo!^+Sr%;xuuT=TZeWm|A;;%dM>=og<+kMNtD>w zk-ukl8c|qvXmNOP@ft3K3_t3GVEwtc4g-@lddalYZb z-IBQc=i|>V7EO#lW}~k*WZF^2FY>qzWei)>L9FXKGb_K)+ymv@#msu1{IK1|mbs_d zcRS0Ot8<@_@HS{Ot+#o}#mVQlH_Wx5xZC*r#sr_EgHNtLhD;Y^98@*APDV{9@0k*v ztSt7Jjm$UiTx)ajbC1o4mbTf?^%K!KbTVp3G55af1bbtaO~pf|5oI$~J{J^!^aSc8 za)*u?cVc=!elm4Bp?1SdsNFyYdCGwOc6C|nZmHSs)agWiLY*Z)+0ZaoyH1`yCAc+g zbAuEcjQi~sJUQHIC$F`K?TGCq!mYN7eZah=sn!O+@aqE;4Dnp;PHUk;ZZZDPb)Edu}OGsacyz1jrYcq z+rXWvlINbj}zGd5(AF*Bh%`w&xi2 z8}_qokrCFqzKpaTb4_sLeLW;8?QFjdrB^c;F~qqt*5~mQ7EKoAmQ%&c=A7jd5r>#-N?O(T=>v&WdbK zbq!ilpOJBiUSux=b}V(*<@OtKbh|wYm?O7p8bd{=b-*5cFspb*InTHqj~!HLlh(Xf z_)2>m@*kTGJk!p(p);Q2*YnHB?RY~xr5|vO&AiR%&^Yhy^c-Jlk43OV!hM~`86Sy-{`r9_EN`=|N`?Y3~M7ZF)S;rSy{&cIwyuHqK$f5vrJT>ef@>EvC@b~}n>&G9z z(R{-F8e41j?6e+zvVD88c?D~qpf#CAtRkaNkEi76zhZVgv&?&z!l=DhM(v zJZy8B?dPaUmbcbyL}(Wh8YuhA%t_`Qbmnu)n2p@F>729dyX)+nr!|~& zO_{BW&uUemEPk8$AS=P*Ahl)k^lK)37~bKO98%RoRc_?9)EPl1)z8K{1Y zb`IQ7#=%=GzyE3T?Wa%V<$Nnl{X?7og%k5bJsAoTb*bsN=NAi$*G(L^cXVEAT&=hN z;8IR$O6zI%0J1}hSq-%QnbB~>1Pzy(KFHNX=Tyfew~1H@a_d-AY8xJ0LSa{j7oRZt z!j9D|ktM^kEKAx;#~~jCugM@iq7g5YCsL7M-5z7YBUItk>5#3;zDLYfE-Up)cU`hq z@33xL%1Z0>VK3pYHyT}Aj8FLjeJkuGueQ9hsrm!fOFSZ1*FU$f`NcaYbQ|`yuJoC; zb_ViqqnoTxIebDEp(tLXL}y(0$~iU3}!Ttv<4@#NcB(oVZWnE5Ej1 zd0B7r*iv#8oP-a3)H2#OANpTL+fPi;MqP^!?MV2DntiJBJNZ%?)3GxurHBt{lu!K$ zIm(~NZ>at0WT+EMuPhxybypr8)|HWgY%-0UpoU_KS8b>;=FQ^+>-)qmYWbK?O80Y! z4{tMCJwC)a-Y=I06J65Yk)$$Uy#{p(h<8HatCIZ+ZeZanY0QYZzzM3>oYDb{ryGjz z+o$Yuq1Q!sNp&hCyASMLoY>GI&S}fzME|s5(~9NIw6)vx{*MdK@2s2BmlJC4Fgd5u z+BoTmS7G#xZS(92}YOPxI4 zpp$>GaqBvnD(rQ8Weu0LZEP@fHP?2q*6rA%nE1wy$z`N#Y(ka`a=SHp52m^<48GyR z8!e}4vv0H)xxgO#iyc~c6c)}bxhx;(V&4x>+P>4ZZ20kiz3rTiuIFjgDOe}j5AVJC zmTkg0vugdG^T=Pc&h61cIf`;ZGGLM%&v3RY|ANyzoe~QK#pMT#t#~KA zR!vLhp*TpEf(;+kvEld>?{CVIs<{2OF1CAXhTBzrDhtc)p`H)j+r@tWxrhBeV@i76 zW0lAy1M-{`o23tFkL|Sn>{+EAz!k6_Eof!JqvO2tq2n4sw(({=Ki2lfO*5bm^;xpE z-{~Q|zk|PzG{mw$Z^7T76EvGue7mG`tfZ3;?Rj?n#l=R|GVAY+S%&VBofT6sm1ym` zipS$O+fn_~{4-_z{az!@0}b&vtpVm61+$9plr)bTE!eWte2zUteyK%Krs)mDeDz#0mGS)IeG|6YOn+D` z)GPBM(@Hy1?5XmcA-5JfDE`m+n%^g1>OD5u|G!&br8{2>?aGQKo0j!JJGE_U*G}pF zudq9 zRdkk3#nq;1Wk8p9Pyoxi_plo#*3Q3K992wD`tT`F-!#9R(OC=0*K5e$F0-+z zI*FKAJ)OGh{H$Jag(f{8`Xkix^vj7?8|)fLyjwM?`|{MtV^xiBFi(|M(21wItoB|m z_5Odid9Vj`0zG>=GDL!NjS{Yy0PU($B9o<7q1sF3DalQ>Ev2&4%#t0uYgyev*W{l1 zH+fs4$4j0CN7N(K78kfq1>H?0qov^uea~l+KiUSm*(A`+hPl`uZrX7rt*{h;Iaen)66XnD}K)UG>04JzR}t5@K3G~ z;|v;dunxv*b23gbt;F@;v111fyPsWRxAwEv<51Ju=74QfomD)iJWrLSRvYlFv|@AO zA}5G7+aVj{T+@np8$9S&IyC)kalY+8Il{(%LwS1G`2Ns==ZO92VNZh|F4_w{OpKH0 z0eMOfcJ32v|38UpsPxr>B!uqn{%!9dUEyR{jq-Z zvb#YqV|$^OiE&!=LNA1Pq!qPXEAmy@d$Uf!BJE103qxkDnANXN$ArI&4?K9s^t-bc1zi^(i1zB~TE7+4~4GV6l zV8PVzHe~ZcRh2I~>`+8!ikt%Og4*q-J#rg9b&h<0IM-`z=wz}S!M`VtpL1;Xs7!+| zMM_zma|Y*heX(bcjnV?21h=jmk<3?hxYy>d!2e}Q9N$%ye@gU^*m-4 zi+Fv@em~gWdEK(Guxl5JMbEa^g42uQh4#+t`b9-C$KH7@87zvq_Wojf-8Ebk3+$cO zvL!`vvc2=V&whV+MzNFEu}cfYz1x02U}mxNY4*DO6@^{jRqW(-k6na&h`k?b zuj`i;b{$5slh;wUUGaJL&g*OT`wQ%Sw!N;mX!jy}=XLF?i{d5rKF?mCv)_-icV4&u zd{LZa@4ODVq$qwct=Pru&P#2s>BTNy->~2J%qVt!(_U-W6xO3GcJbP6@cw;!f6QL* zy{xeH%wiX>53Dz3%q(_Ix0gA#?WZVq@p^QF-P^|A546{{R}^;bNwJI9BX(n$BkcVr z?6uWE`T6$#Q}+7WYl`A1d*^kBnfcN7&g*OT`+R%nb(38{bG*HuXs?s(VulN!K5gQz zJg1qBfh<_z<`OyVk#lCfYi!Lp&?5Istc|Pp*4tUzibJh8u&Vqm?rky0#uzC0d2HvM zqsTJ+Dph8q=gGA`3vJ%Gg6|CbdG@EeAN$hYn4M+ zWD+ZciD#8P;?p|g4A>~?|DY%zLG*+dlQ;U+i)R!$Rn;@K;*!hHuRc;&Up~IMAV1XZ zeW!QwbS^Z$)4765q^xz{eV4EH_(P?lNxxF{^Pr`TPVB@rOh=j+O%2N~86q1wRE(34 zLe7lU=(EyfmY%W_o=+egT-CEk`hNt~C zH&oNzVgKDa^Q>NSKx+Gwo>bfI{tOj#TSWPQt*Wuo)7v}ZJZuL{$?YY)!?hx0$R~LQ8hDcC-0j*1{+t`M!*SJf@Bs`j)EU+9lhID|)2t zJJ9-V_i+k4YMRyZYt3FkN9AW){S|hx@7Vhe)Gy!@nH`wMOY1<|XB9E5Nvrcq@3kz# zym@No3|y_-kk7Vtiss7gzJ0#;+I&;*l_}Qel(g%&$pedGiP1M=aRw_PHevr{2Ob-9 z#9>EOnmZjip~Gt{<7f}@Hj7qmBh4=JtJ#IdP{qOVV>W+OheJk@a*OrWvp&X9Q+XLy z&%f)RfO$`_naKsKvom*2?SS3kfg@)dmF^pOpX^`wzoGOJj;i9EBr#$g2Vy;40`3W^ z6-kZ8S>k-zBj@_d*g6IGz$zjTGBa zE_w20c0BnroRjAe)!IfHwsExU8k=NSD=Q~NQEVi3utv9g)W(F~pk=L%k=iypyxC6? znO|<*I&)~^sC5jg%~GUH;kX-x>i{ubR0>beHc zy`_b2ENY9@ZtUYC5PH9eDx)TTo^SJjoO#t5<7z)P(VXfY4{}6nt`Hp&h>hLH zRU{#PP}6c9iM$L9YnCZ9r>)}_*LKWD?=2=(2+W7p0CyYr}>N~A0p4F&R0bPzZ+NRw?3mE(=^AUHb-g$ zV6o@LT>B{7mDQ4EvC|O$h+0(fw3pS1s_{<7Q00QopR&Uk7m1RqveQPnmF|dyS4$(T z^5b9K@tG{Unqe2lLz8T^kKXU>=yKaz*Auf3Fss(H6jmL4G z^nA9RB`nYF27Au0R@W|lyqB8O^A=?@)jSic0^={WqoGf`frwYSR*cT7d%k)Jsh>be zij`rv@`pOkL9Kg`XATxzkJ;7X0hrdVSn{mPBq$7*`wb)pK6xlXoGEr9Pt`;Py3Z& z_uAMq%Kk=MRHF_10O7dzf@*tNCUkl=vUWnF4@^`1Q$GZI(7ZXmcyBG=WrNo^ZhE$< ztjTBAiU_?MVUD_d@&?Cn{D-?;@J?O7+N?X>%ahNd@#Tq%kobT;^)+hrkmZo)@!8$kX>qt%rK{n zHoYx`e4JQ^6zScaYnmprlDym-gp=Oumi2+3iiAjnnLrP>5*?!~$gf6nE!|}EHT6W= zdJFYv>iDl3U*p!h3aa3nkg%||nr0fJ2L&(ULbG^ODeNBB!~pDH{yc1&!guK{fx5(} z==dn3U?lH}5|{9eyr#;rmkzReBGG@!Ef1UunutsFG0|kbS4m98GW!`B?5~eYu9V+D zo3XG|q}GkjlWe@@B}TBCullH(Q8?$$9p@~yW7CYM*E!H#oku9n$_e`dkbycjO?eqR z)sIQ!du#&@ZMj?%z3c%)F3SC@9NPYmhVhBde&37Ozu;1_a}4X!crI_lSIOp-eM!Pi zUDyjvqT>^>L)J_tB)kN#=`^pkqm=1@)?C$3EKn8ls`41ETj*HFCeBrMRP7Ao1JZ+I zqcUM;QuiQoNxJJkl41{YbDTzCeE4<4~mV%NX#_{VO8 zYjMS1eqx}IO_J42AhP=2&PQOpJ=nc?RdKp?dj_rNdanKD$k(oC$rX)nF5?uMcTIzr zbjosl3osn3z@M9Y@ZtENYmVap`_oxgIy&;@Mf92?VxQkT5J|?^xD>Yu&f~w|G)`lG@yXI z6gz|lU(aL=@*8}No)P=Gt}AUl(7@NPJ-2YHYol_7t#OQ(GZJINHld}x7sAYN59X+D z5FJ#&AS+k^szGm^XU>#O2p`j;m|4lKA(a;o>5v|c6eut%`yf3sds4;YBB4Q=gDLF6qKEb2rS$r1i ztj^9XO4-0WGQ%^;5P~|}=WAmxvCmmyOFx%igCDA0H`{O8ahb~=y&$Ki?-=7un~!RO zJI=R_foG}V#bksBOKyVAmM-!F=W)kzJnQl?d}!qa+F_rfHX20NsZ_Xg;Nteu&S(`5yfvv!p(d?FWZ&LM{V#r`6hB`>dz#_rsRYL{}9JgpTk( zA^UVFuebyPibxPUw;krcR;}KVKWY2-5 zAqxfFR26x*!;hD?^2j5(;{9Nn?_qUaE6%DSLW)s|a@WHX3=5qm>CQch&KiF9tOvsGn)Y0PTB&YhSBhF)2Emg~A9mU^nvpZuX$)igf8A5HYLcj`Zn?-7ptge5SmP?#&(cogy-^Uo|5b z;Z|VRvlu1|jU!6a7m932cs0kmuk`v(u%E6g{2(eNzCF>tRkWC6UhK0_-@Vd4M`Io# zK+%YxJ~9*|eRVVIxFss&y<}agur#L6Rumt$`BvIU)o#9@;iy}u|M-qCD@x@Vnq~!e zVke0zJ7g_>VxOQSrE@%rBIY?pg4xuWLTz99hN7^NqPTOv(bS~R z@I0&z3Y7^Xv)5!6|43h1=R&&KY{1Bpc)dCq_y+ZuN|Zhgl7B>y`YdXr^qQ;`#`cG%Qjth!x(Ht z-bi&JjnZ41V{3unxPCunBG%k$e%UM5kRx!lhsS~DSmabyrLGthXd7I?dmt^*yC`mN zpl8%F?BS9J@Iv-hrJ+h=oCD_ej+2VS=rF86e&G?IDDE)YR+=0lPP(k!BhY%??vQ}n zP5pkkE>(>YSWi|MaRJK0eucm~gV+@`UfYVZ9E~k&6&(K)0?7iAAGHCNn$~sIIkl^6 ztsRMv#JumG#Jub$#=r3$EYc(LjRUd>q?`I4hWc5wd7n<^oXeX-Nz-* zUh<>E!whI6mEUbv3y#>QXaOIs;(~0kPLrdjV@HmM-7=!oCY!7_G@na)?~ob4rDLxu z)iD68ZbDhvI_O12P{(SsRg~1TNGNi-h>x;Gs!C!=Kl=`mPJK=Ngo$4H{boBtFUFJy za(vk9iAISk4dE;6z{=XO9qEued4?W@$nJYp3v=XFo+^%3*htiAx;lcpE-=62pkj5~ zyy2f4XGHzV(d=Vk_Xm9p?fb`%usre8He!wrv46zZt%bFU1x;3!RwR-S{T`x#Ji-wb ziL2uYUDR(vX8L+Ae^rz9ops0tnIqlE9Y7bM@SthN&+_?PFXxrA@q5PB{jH7xSexz; zfb=wTRJY0`bOi;r!FH}B_WB-- zpr(on${)y&rVia^_8D)WHC+`7?PxEp@?pwzNVC-Y^nRH}yMMS4g{8UjuF(T|kyoHs>$N8T5^YtusmQotRFRwShTv_rP z2qTF#d0ai;uKI#sheU{(fCx+2bK z23ctpRVCl{@rjetDdT|qUJ0>7Ms?Z)HdnLWh&K3wES@aGsSQ0UOL8RktFV+?DAr2` zktb?iwC7$*+g?b<_fMWUk?Y;vu?-(x-33;9;YAWt zY**}1X3<-QD~vLb9Sqe~&{ezk%qi8F$8$0TG9ShA@Br_0s9sK`GF5aBmhq5$!J~c5 zF63v;2g~wZB$AVNHL=HCtu~^S-iUZj@mChm-LK$0=<45NPc)f!9~t@|+;8zgQk~ii zTydIRc|91}D z9<@{KYQo8U_oL^~zLy0Q6CLFF?Vf*p=Xx*f7p#P<$YCWt{3awy-WjOiQD10@_fhW< zsqs5#pt?w}f5Oj3?6{`&J7g&&#^*Sjxa)}4&IK_|c<1!AX>qyjMqOrHF10*kthm6= z^9&<+a$cHyAM}pWd>NXF(5w_X`dn7ZkXYjOO1BEzZs&mx2O3yx=Mu+;O5XhrrtML| zI{=sONB@UIR^z!F0K3BRSP(Sry?GSyXt~|iem9s6=qN>oyi4fP^6ZrNru|O%|Gs$Y zpviut(Ls%_s2W~^r#f%BWy=bx-dGe5by-_akqVDVS1^&8Rzvb`uUG$AyXdUeo>;}X zCU@;&QzyPEZPrzF_PBAxjt``(?#pOtjow3$B`Ieob0*e9tFPaYn?xT1y)iR338v8L z(6{OfR6EUqVm2V=y=C(_jj(7?px}G5nMq?ml;V!FQBc*QSB-| zS$Y#Hfc1XmSJQK6s%tfFH=GsSUU>3uE)s}+itWhpe}Wa*H6}@n{lCo);#oe;R^W(V z{Z{L|x+}J?i*PLR1C7aU{{Lz*7j|m*9W9l`Dw6;`PS5)kM@}!-l-sUW^=^yzT4Eht zc+-7HxcULghVa_xPb$KWnO4%Z1Vzz^+R8qa*|5T!Vx00rbWCjo29S$upI^l9B^Co$ z+IdyF^DIg0xBc@HIhXd5kVi-u}i&t-%}8Ao#JMT1xD>Ato5%(j~9Z`FN~YYTIwktW$R&5eYple%XDl4_n8 zQIT&i1}!5tJ+9uwCZ^ayG??XPSy^v(bx}%YM;Cn5Gon2OZ(KDyBLRX-TGgW17S$@?7 zmV;E7&+`V}xmUrs+2%aUiBGY=)LX!&sFJ+q0v{M5-Jj#RrQhG8x9y@e{14r1E9F6@ z!(7|UepUCRIk}{uYDqrKiYP~_e#Iw6C)MSpr9^~Oy7DEb7w$a=0&PTzbVTN>?}WL5 zp-#_yJA&&T{2EMk$)hI-wqiHX1c$M<0e|S8niL~KG(GBd4kJW)j8MP;gkMp)r+wf&&RiQOa z?bzF9*_BbyF^o&etr7 z0h6eD8tGL4^sSjodzJkPci93lP3zB~lJ}p|yRLYTM7cnFf5koCo=eg~KUti5Y;}+I zRmCN?^LCkCO?zS4gYh-V$S=lQ#%4t7kKSFs>RN>E{n;e%$zV)<)b?>%!NtziTdT_= z?^4!BX8&drz4=|-d z`CWDEtKND2FqKpl1+`WaU16X3?CKJut$cN*dQ?;a(R&9KiLSEy{-t@s#EMz?)y@{W ztD}-#^h=w^-?~2Q6bw(x@pbCf)$3OUlfRKIfz9qKBW5@C^}I1ddh!tLlHM(M%$sAl z|0;Wp+xg2aCY){m$IH)W*ZR7-e&9)CdHiL?jXPB!A#x~1306V4=Z&td4P9f1+E zKP+&itpzW&>Q8qo;_8iyEmjZO=YwXWBc-jbEG9XFIODa8&c%}2>L?$x7bQ?Y&Y|6OC($2ZAW7piGv1$Jva_~KS^>y_$Rx)4Q zNy@z#3kiJiD#ZElYIeZ#j<&l=4VynS^+m=_&gzf0XGNYp5)0GZPgPdFp0D~6E?5oi ze=UE|IP|>%L)qEwba_Vg#R^@rpjbH|QftMRO4?%}Rk=qF&Dgdcge@_q>TPkz-%(8| zcNRX5mG+zS;MG>1v-jq#DDJ87M$JJ*mxexZs!)w=MAwLaFkSrd~_`^@T4 zxLv5%EL@@@l!k{Z^RBZyyo6n~OUAPxa^I8>w1V|J{ffVMkav;jAAv*s?RTZ{-b>0I z`v(W?KQ>skPT{%yAn(#d{E6y`eR9;zss6^3NZrn*qeW4?*UoQ>ciJ_D#>5|cJ)-j` zo#9c`e6ERh%N6QgW*X3$)K7kv%ZSlVny{ynJ6((qx6mhjs0ypD3Do=l^fLPGOrsa= zrjBd=`|nJ15632XI=!+R#a#9iAzh)B=T}6IT-x3Gtg`l%b`HpleQLEqH5h$d?#h+Q z7>z|&F}Je%E)R9=RFAmNR`sloXkPD$uGBI|jW+njD!mgyx2!0>(W2vaiQs2#c^G4+ z-BET8L@xvis`sZu2C4T(CpP4yE{0d?c*SNrCpxvR2XzNh6zz{!AGyif+PQTKa{Y>y z$;rU)y~*kTc7%m`zt}rC)Fytt>v<-{UOm~i=LbJRn zcMQezgP&*5_nl$S`Q`PX{qD~XzTckj>(39q;}!Az;5$|n6VDI6#h&Bq&kz3L%6NY8 zvFF9}gYUB6{rSPCo*&N-zR!O5=Lg^Os(60z?e^SXe}3>S7sm60@3}ahAAI*E$@7C( z$Mb_nH^uXVKWxAI^Mmi-8qW_tbz3|?c%waw*PkD}%YOIg2ajJJ&kz3GYvcLBcfKy3 zAAHE`&C%?6zSHe>zy0pd51zX-o*#UV{qD~XKIEo&e(?Ekj^_t|@h$QE;Nf42=Lg?x zzx(rpcia-s58n7Td!EWH?xi(m|Cg7Zzs$UcYftI6IAYOh)}D5)PgT8}{O&wEg3OQ= zWc~)N*vm&1q0Wu!816Z)y=q_~5t{oIs#Cnm{*wO-C+CzS@sln9@8HLnRp(@q?2c03 zluWtz(}&e<;>@P!5RXpK>k*2YA9~>6=wgpmGFn4M21l3ND(;gJr07moRh5u3v4iaM z{C`l6^kO_c;S}uKWECPKUToh&4S5%Rx_DM`P@az=+Ue_7so`((E%da;=Fna0bca0G z`Q#~HXybIFmnVrfuRi&ccB@xYO@*HJnDoFxkG*@R9r8Lxfrsu~Vxb3FP4Cw4^S5iG zx1{mLe&&X{SUY*h&LK*>bcrJ5>+>3q@u%kI_Q`sr`<7=(y(F-2RB*QH`E@0JO!m3P z-LX|ln`9Xg zlx{-0-o7Qw)jsrI)M)l@9zxE^bp`u65cWmp{kKNZw@MT2$s!>gVvNp8XX?6Tfc z;;H^R+TudfI)i%eKmAh3-FkdZWHmLZ5yA(J?s> zcbe`pnj(TtZjAm=B8@BijtJ*Y$*OOyd%h$a0b=MRRl@>2rsM`Y1bYH7paUh;6rrFOiZm{pkJ{y|#&ZjcXZO@gy z#puRAuq*iX{5Rx+Egfy&ftS=B>NYk-1Jw}e75v?BksUYmc49}4P{!*H?P-`= zTHK=2u~m0ywO#h2yZ$N%lqG|k&_(}5e5?0P?7tfO8P+g(EWS}$aJ=9O!eT4NMuL|Lg8q0YN-(gKf z_m1Hn;!7v~8nsX9bj8zRcGT>8cPRt;+BTcFmxqbFv>P^7(&&~JJu%gvMZp@p>>wf; z_PEUC;`iD2os`g#TkdT8girSvCwt1@^+aIyI_ht*37pWKFR^`e?dYsnn)|YNMyK?_ z>HcU>W?uE|J+;jgxm_$M<$>hFxwk+SS9u z#;|83;7^zi8^KrUSj*}-L%5HuL|OeQRV$3fSglj{&$X(4dpliNx++Qbm@{i?$xdHb zJ+Y@ZjY}(|c6%E3=eo!Z8C`AmgYLu2s5%@es9<$R6DTJOL#umd6RCVhjDvh9&!FiY z`vrq{*t+fhdOr5`CXZ%6@cb*c|J)DV@3sCzE-+SV)ctQfIr4bq_N#9=KK8S6EOuS(t5vZjqN2E4S&lMnKk*`bWR=ah(KM6x z`rQLqR}-$)y9hCIbG$|0vChvb8Y4k*TFvvf_^Z#rcljtf-?M+!a^!m4Go~Lpk)f&u zJeBOgvx4?ch~!ojU{pVIK%qWc2%~yMylO%+CAmBl94p; zbY0#jUF1aA7Gs3eQ(fpgQM1P|LwA_+d5Cejeebr>WUm{IdUkWbOCU*Iqp8iLxX3v< z=W(RZe{IYB-iZZ?Co_Lj->*JvQQTznrk>9nc?Qw$x8P}aDRig8BRu=V`mw$4qvcr! zno_(~3YQM!VI5APav*R%?W`)N+*W+O^oV$BEs?Y8*(pL$Dfu|q zYBevAr$F(J&Kk6GAncHw)$i&hWNEXk$d&8#q|~H7(l0f(hBU3+U*O#%N!^|lh4+-c zMYI+dNSz!QO!Z8-UmtRA>RtwK(x{IOGGZxYDrB6pb*Z*y$up7tL?)vgE1Lc}V?Z>9rE40cafL);{*9Fm=xXn-H?9$PweG>Z+)LRSc>r`{q zV(++EovR&B06_symnp6jOKUdYr&{d)ja{aC3-))!Sp@San^C)hpOW|dP>+gD0-R#PnoCD@4H z@nE3DJVitFPNs$53fC^PSsgiVH$CNXRl60ibx`=a2`bPB-!W>M31XL6D74q34WG6n zNK?cJyW`1Rb&jOaj8L~`=6c1ieA!~~5l?9vW$zaOtg;3vM$amo?=FEWVg zbyqHxRdzgUHahmTb{zT>Mv5nOjo95J1lHIdv2uBG54`G=>w8I5wv1(jjEZ9IG<=Fr z^BL3~t!gFjV#+Qe;^N6f#pb9_G{SqaqI53)u4cya4rRNJEN10*ENoBdKSUlrmE9@BhQ3ES*2zdt1NmoL++hsHr1wvk8V)_e z%1*h8zFTe-wx|3^oj~_PVmf`{Ep|mZGmMoI=Ncv7Y3bb;-IJ;to$Nr`Q_|>}iFY00 zHgIs*_)YuST%(NS=}t4RM{&CEMBP1|s)|vtRPV72+IPqWxkr|W#NAFq7^Iuq*zn)F)EoVh>s*SzE zq$}$|X4q(S^r^Hqml!IKbD1pcab6u?{LI3x9%6l_IXhPzN@vtwW^5bJzpS(?e2o2Z zF(!PpkJ(Pmv3B0LjqI4wexzhIY<}mlCZ1v0jHgcB=cYZ?)}w}u3*G$!tA~5;r0Bg3 zya-FcmdSKkj|26tu-~u;Rb|38?Un@l$cI%qt}4A1gj7W5H|0w^40QvaciZP!8#o)4 z8rf31a;Iy~jx9Z&V?Em9V|cu313n##1*ST^~`j7Dm^K3F& z6~(+hbfngOo0oMeAMk}NP5VT>8&Q{^dlqtnR*zE9izMjqf78Cv-)VJMjjBV2)gyL| z!0DYU^hWF+4J#+&2);RNQuJ(v*>ufxvz?}XbgP})8{5;^lVhxGe$;qCzNxmQm3bzs zjm9l9zoNhb(4wNNs&sZ`(NNY#M+$58-GzKA>tJT@DtYc5u~9i= z6HnwR%_}7JYAEM{o<}#CK5;zgTA$!#LuubGxq7^eyz%Ec5%=~ky!alL-nB9K!|Kik zvk=zXK^(dW?zeU8@%pNpwLD}v+fB|?C(>YdzK=9|1}x%J^MXz5?72nr3<<#x?8viz zuX6B)$T6G?^+Z8Catn2)&@|txgTlB%6tXQ4AW)exnOQj~o*Y-4tSk4Kht*K2w9x`W zlKlz+0-Kf_e=7_%Mhr>FrRLfZAXr@eOl;XiOd?m;XUn$dkEQq!fPauWUG zp1+CPI!oTjtm;oGLsq69nv%4%8tLde*KBaG)TGw#BXVuG%zVK_Zg`X(x6-JU^yr@{ zMx{rwCt$p!0nK`~k>_ve@k{LZrN#w3$_|i#P$NGJo!7HI&s(9bnTO!u1$NAsjS|+C ze+R~sPlBi^jRSVxknyB=L`~1{aV~RnuEz(rj_MfozHyB4ypn!w6bp~f$*0ow7U6EX z;u6OmVaJXX#~F|D8F}1FqZhs+ACax(@=d9=YjVo5(ksr1qi*jpzU1DtiV(*Pmpn8b z!!94}-|r-r=A?V9Vu>-(-SX1!s0ueG-xOvql0PV*4h}ma;@m~{{YpD4_cWn2k_5x5 zmLF#qrrWe$AtUm6seMF7m)_p6f=0YJ{@D3(E+mYlrj9e zs!v_1!gchFM7FlhaCViQp?n}63%!lo_f#g>l#n!+D>k{r=0S7o5_ysjDdtf(Q|IhyxDk$`X7zq=_D>kD9(?T(Cej$>hd`)-#P(VnI6JyDf$-vrp==*y9RWWV%X6 zbkVcc*4S^ZkF?j(+$ZwvSP1J#4W?}<5j3xcp@=aR0U7aJ!v}qZ*tcLV>9q z6TKO5DeVF1-lA~EifG!2WwqKXzoK|xAN2`ENU&b>3t7<%l!8ROM@JZ*wK79&R^D-( zjfE}aiHu7$lE%H}BPKMj7cqLSTaD?o<@pO4fb_|Z4e3+&G}&7AMHD;H{VJmkuLRwd z86Z#5R_#G54m8U`ktDYWmrlAag}1>4iIW`|6QUgP(tjob#PpwUuv{#8jsrCVjn1@?HNUCW=+QP(a~ zlzzQuCFDu1xj)`h&!2id&z!#RdR8yEtvle|0L4Y$S(?UURSif?Jqxg@Z8XO{);B%t zaTLSL_T3tw!`Fbq5@aF0>Dz5IDAIbS09ABQK;2&6hlk)3R2o7K&|kKMzc}~8Y&u%X zbc7e$;kwz5bGvPqq`d)X{h#njg zi~7|^snZ;HwA@{x0ZpJOaiUq8&!^J%{yqHWxoX-MNXO(zp70XA3-Rdp&B6zq$8-$u zBVYlHAlw!D5G|u(%WF>bF5GXP2Tk|Z@ddd&kEhx4*S|tD#*x{FA+W2Q{lD`-D&;eoi=fmTCd%^ z;YsJCy9L6PY!|E%$MA=wv2VT)-B&p$Q$=RsuMa%w{I*-Ns=46S{iVv)p2Q9xdJ6NC zdYkf5UBx48L~|fH`z;^Ek{fd+P-A=J=H=dmVMMs$>7x9; z+g_d*q_m_NX}azneGK&@hs#`JP1zp}6aaytsLn4LLcZQ6t;qs7zRnv_(c?RO<=qO; z_e9TVC#H$Z=6<(g1d;>2@d0H9LTTv1`ckc`G9x~E?@8SG+-_&7%?Rt$iZjJYX|vtR zrI|U!$wm!P8vi22x*97VlovN;J<`0>2k%fuhM68cudGS6FEcdT zY=yeJx1Knqalwv=+^3iHpIGLsV96s!|KNm9ea}pP_wQpcBgSHd4)ecHO-ywH9d`#IN%*vkKdk2t7_J4 z^vJMus^7Y$SEH9(hhJHxYmz(?w&yACTTKy3`60f_Q)!vOdjWXjYNJg%u{bxS$GJg| zv4<_?g4{@Z1F%^3yAunQt?_qr%wrbc%iTS1;{46!I3R^AWT@P8(ciTq%*55u@Jl@M z-DvjwQ^U3Jba)cxNW!Y@;e-7Rsu$dPuv*ZFd_+|O(JqZO{ng=q$I?+7g(#3-L(j~T zC_ZyVNjq~z|4cboPND2g^tm@}o#B`Qf4&kU4QZ8!U1YMl_R*vgHre zldzoq+|x)MXVbZkksLO!^)&5X1*h;+ z?^Ve@Q>)d=3dg8A(ynl>okl7rm7k{8oZ3pRT~;8#N;-VfG?v$0=Ps9Amtayej!Wjm z*YphUH^2p17_kA3_}n_H8XNVukW85@E3?RNgZ)(GuAbvLo{%wJQ&(nsd$`uZBka(lgXl64ljQ{LnKC-n9<+q|~Mo zbA(s^=4g&3kCn6#Ye9I)=sNQimm_=EWfRSa5Ju~8B_p39!%kgN* zGdM=AAQXWXWbbqGyUV?)n#4D-87gp&>}?gE3lAC^L@mPIqTGjlojWX^x|@uYyYr^m zvT~zTuH-WtjgHi3<;U)Yst1XrkLv+;yi??GTabmH8un=0+RHVG?l z%9XGT#)|cn@M)gO&@G5j zvt6+9UgLelxIyab?RXS%YgKNi8IUkM`(Ew*7}+qMDbMZ42Bd?<<^0vB{B)1rUWM3w z3HB22ntV&P1V%OAV-Y*#$}jGksJ#z-;yt_ShK{ZibDUu(? zn$ih&w9in_Ih*Hf+dH$uW{cg^saKy^&JtJ2vtxyP!0-5?o$ldv0%hQnd#xyNc*OpL-4SIF2tZ<*%3!xEFiDl_}C8 z%PTA&OR|)O3CUuW3(cgfIL+5K(AyBt&6!J3m1bJxA}V0>rCQ`7v2r5 zuG07lH8$va(td`fE35v?HmGAZl<`tn{#5b*X4^Q&D#WFBt=NBAMyv!lY81sK7H7uH zr*@d{q!pLvWvk57s7bv7RopqEHA0JvdsI` zGxf}Dw5b$W~co@C_ui*5wG)@+bu8K+pLLPHLsMLWRhl()e1zl z1d`W|C~B7Q&y!|&4ou&~uXw~N=moh%H9#`kX` zIXX}0TKrjTSHc}{J66db_*^x(EY))w&y0z%SYuQg;ZMq?r4u2N{22T8dWS1v@QU~b zo_%E$`=S!0>gOn~5#);NGcAW&UUn75dDIk=qbfhgW7WTx+Du;Oi5m447?H8-J1yxe zB18BSg`x)f>wG({+Be6wv^qLn=R3jX;!N$s(wuZ&Sgj)J3$dYy{;=tP%y14m*Nj+xQ0?nI>h8?r#}DyCgfsAgnkNqfplY;Wx)%}K?3b5)#6Tpd~=iFhOW zOJj(uRsN~39gC$m{)Bk0)yTzNqKEgaT0#ZCKA&|Yf4sWgQ%=w9A~oruOA z#Xog8LmJpO84EjX6rbDBMu@TAMvPrzlYe%p^g3qR0IheFyvMZzL-xrwqjT8kp@s(^ zuypLadq*Ok>rE^kGSsN{rae!}*VXrqD|JqUG;xO=&`$S&lcj+h`Q4-fCy3=BC;p(A z-~NoYh!1;j>vV@xTR)-jtNpJvd5xCZNOzftE@dS3*yW3YIU z7h|!EwXMabxyJ|dAen7e$H>RqJ7aFq^!k<>x*^-#c13BL`zRjtzw#vd@fMB6`AD9K zTwOWmI*43f$RnM-cjiUBTV~@6dAMUH`I`4SRY{SXfu$a?Se=XYd}$t?dpC5bq*$4R zcOlWF?gH8_U$6bJ|C}$`SMOeGul*rQidP!9%Zm%kE~pScI-WcBdftAcOm$7QF#Bxd zb&p9j&*f4-+xr=df@_{eY;3nHG)SHo2&0u$uF=9n=*i>N;kC>TZJxvF%%jbY(q2Hd zqpGnSDfXTN?7o}-)z{FKeR!@79rX5)CzLBArJlt`$@9qm;1|rn^Mb$Xb=}RfQ{6*m z*NjrC6sq>8YtfokogxDks(@QhCHh&bPW^Vbao@fI0)}vXfg`Z=(X5ShkBH(} ztT7Tto9wqA9h@++XV$TYJhRQV()G~LKpVwW8f%QUoYLO$xK7iZ7MHa)&wT5dV{+4g_D{Cu{J$+)1SUq92Ne~$6m+j~4jq(CxX{h_w2-xotz+Z;<>UV#pt zK^4X4y4VlrO%|Kj$AG`H9{6P864wv3`$Rh~MO_2sb4~gwFUQztPX@{s#j+VWPIc3D zJ;M}slQ&I$<|Hq#=g>nP8z7tQC!>mfw0BX{Jd*pQtt`E2rLBQ2wfoYovL4zp`)%0% z9<|?fujG-^|5lcIB9eK}sauQ}wty0OJeALC?*bJ~z?bb(Uo2r**sL7p?M zG(DbW8msO<^Zg3sHFy~ERVJc*0py&TJ4EXq{%OpYFP&xc?xe0%wf|bt4$ls>fn4`c^6R6PuoV*%I1J+^$gRS);B$~_pGvMALnj6S~=31(k4Mf ztw2cXUU7MzLcT`crh8|451h!FX3_jjhNZh0Ms?q$mHIA1ukh2n$E$kX4>pzacoNT> zrQ>pNFE5I3n4H^liS$`F+QsKGBBFo?X$A*6A~j(IcIELQU#n3Uqj$#Zcp-$&GtBDQ z)p=QcbZ$@XVA`Wycy(k?cjbwLwtSpACtb}UD&_G2v`^Q;t2EOM?Y^$5JXQ#k=NbL4 zPTI3Fr?u<27vHR0U21%gFK#v6l9`h!ro6y8QliU9Rl?DVJMyPo`%PWK6qS^7P0qfk zH;G8zAAS42Wnqtz)k0$(FTB23l>SradC|+XMAbf9HvFQ8unl-&B9<%p@rx%OvKcpxQwfBqd_0SP^ z4cClf5wDX@D~j*h`=j={#eV;xz5mEwcb`!dkJ~%1S!Wi-jG4tEUU%E?2irTZ_YM`s zVfOxPd)+i#6fd-QUe_-viaGYqYwc27ceD2w+v~n%_6$6G=Qa17qBz;!dEI5dKRlz@ z$!o#NqWHGG^V(&&Mk^V?EO%C-Mp$Oo@wvAcD|}8o@ej8 zMlZ1EeA@eLdkwt0C|+dmymqfM8QJ?hdo8=HD2}stUJExA#Yy(g>%J?B;s?`;UA%T~ zvbm-gyLdfdzwen*?E0p?F5g@f-?4XIH@~JRzHjf3+3WgkMe$>M=XL*fQ^w3<*K~U= z++n}kJFi=>E{dny`+@d4>YAc>hQ0He`&zsAsJ;J$y}ogMQ9R$?f687*?KIox-Cp`pbs!q6 zv&z0n;UHG4HBH&zs`7mAFXJb3O8e#~_`y4vcCNi|Dd#13=jzIVVxeIGl@WdhvXFhf z+CHW4x4!&Fez2kZM%U0@RE~C#RVIqHtcZgn?&I1Cp*16R+j6fCy4?8l2Kz~^Ojn9( zd71sZz&<(KJ{z&`LKd&JW1$wx53+Ca|G@$E16YYfkS5gYN^60l=>Z#AYF(7j2swdP)~FrHHr%GvRoPz}qn7JMKit*na~>B{Y5vRJdyEC?IkH;jQ(_Ti8tO%`E9!MR4m zDzoI&n)jEr=G1ocIqw6JSJB_kW!>z9`-^H}ID2RM!HI63A}`ywQDoahm8qeKYC~(H z-SpAhO~zYp@}jT%e=~G&Z}C~b8oauk6w|F^JLHhpV0H`VfFr3<=xXI`Z9aJTOO{hQm(1d*{1K^H+dH>wcWgbb8onCa0*b5k|L3n;t z9Qga_q-m(@E@suU=9iY4KA9A&p|S~fe1J&m{ChV8E;xI@)|6QLz-o0r75X+H4ONa? z;^ju`S@t=YR;-?Q`+)X#P-%%Otwza96-#DYRj1CL ztc!jrvP)|R#-44TpcO?X=}pxl$U^VOKg0Lw;8Ro5l|d$G)uYO-#=F}D{7o%Q)LPVg zy{HLYEHHYO8GWlQ>qAPLO<%0E5leLqvbt#QskfB$=X;hEU)`SYOQ9{FQzx^|>^i`f zo8%*kLg%-tjEC)QshF-f5bS*WxP#4B%>x?h3r*3sc(X?O9 zWh8HpOhS?ZN8I~a-NDDE#%@!&ju;o*jT5`WM%G!COzdK%30qxhv#vK!WrebduZ0t~ zqHD}2b2fIL`#jxA=x{Gl%xucEn&YJ7fmXvnnj8%0_SG-@^KuPo0WE@vT9th1U7OC}d+(#=}q2c)g`9O6m59zoN% z$$DY+EFwxAv!T=1B0lyr2XS_t*$+KFqOHrrGi6qLh=w_xfk)T&=@?mI#vNTp--*aA1 z4Yr6Dlp{p0T9;c`4LmjbNgU%+W)E`J7n#qWPfzzpzKKMux{C28J7?;V8o%yQ`#z&b zT3eSiKJg>00Zq7s_LV2)_{fX8N8^UZV}A5HnB_F84Tyip+C8M3k8;1o0s9~0exHM_x53q7$!7{Am^rQ4euyMqk<|4IK0*hykx8m! z5xJ9VC-+^BcKL|5rREn+_$jU8TiePzV6zrU9z-6>r_}AlKE)epX~<+o1nM3=s9LHO z3s_i{b;_aB9F@ytrCb=*U^=n_VUXBv<6LVjjY`YM}DN& z?o|$m7|fw{ey^hx@9;A?B=dx87UGWfjBp8MAus zm~#}-rYO!g8pcWrn{h$)9WyJ#Q8j^gYyDq4^}?52ci>MAdck7xXwaan5hkkra?>P0=OmCf6 z^X`6ijxDtzvd0&$AN!8UBKH%x5K{1tq*EKc%VNwjs}%jop{l=jmzGawB=C=MBxlDW zRp}8o0xQTJ)frKDg>#wN?`rJbUitv!ZNv`FNbl4D4Mcvw&j+)CJRHyO^h!93xxfo~ zelsuB-HKLt6FPt*)v8bh<+7D}J%QGRvYeCi?&yYOkTEE9to^QYKxyqn(q~-VtGe9x z<7u}m5u%xUr#ko}{}`UurZaX?QyHW=Fk?q7aa+l=d)LcY<$O_`Mlj^>cr2Nzp45(9 zX=HY>z;(avQa`7wY1C;!S9q(X+?P+c{{XLtvU4M`NTju+Z-FQ zAA9lmu+jVpsnT_k9m~4hN3bt-usBN5M%IsviA%B@u-oApuR>`d^Wn%%Tz*kPB#g}Utr(h)~SjRtjx(_S!rGUla^ zz`c$lmb$Mrc~y+8-fc>|BvRcilUCCl(KPDn2}z%1^sX@ZHRX56ovR@DiL_lir*=8V zc}ZpF=M8scljezj<%Q1z!XagJ;nItlZBJI?81-3$L+yJG9?6l=J$4e<%$)U6Li+GL zTJ(MrN8h^WTQaeC(pES^y^GEp1IX0!)db8I%i)j|5i3O!%Cjh+oQZp10cP_+v*szS%A`AqsutLpC6 zoisaA`e{?o7A(zsA@Cw!;+pR*rV0LgKZRQO$>XCau!o!*mlv_P%FWMB(2ZTU(cOO? z*3BN=9s>u+I@;{v?rH7xklkVvXrh;u4w%=V!N|=d4{~2Tj|?1dVI01Zl{(rfOTvTk zZO!F*GG{B^rkE&ei@cs}IX|Dd$nTo1x=Bl(lQCmz*(+@QZAGcUdf#eGnY+WcpOH(- zu}R$)IslAL1SSsqvGOKXfZ(6_r3{&I^9t2HV6NHGpm7}6NO`2$U^(i7340r`UH7b4aQ{{!Y ztsVzYu*rEns^pb82F|NWSIRd2{@&}<`(jWLq#DKEdTc3D$Ob-n0d zCuS=zN55F#T%({{NBEe8YTJu%b1kAM#s)I(6e*f$R31f# zCuHJLq_Eweb>DIBpbCC{26f{iN8dF?Iz;M7hIgMU^Z*J7DMO2%<1}?Iktfn3A~7Od zDAwX9=#ii5u_+4~u-#hRUs~Rd#}Qd#MOf=J&G`-1QNs$FW#T>I*&tf_ly>FOGE|+H&@CAY@FDK9SI36gK$5>?KI!mMN zu{H|+qO0VYiH?*kUi~}nU_^zvy3`Na*B+?m*{hURZ2~&_w+bi_&ckis1AlRs6462z zvm2V%GX|H2B6$;<_p_IYW13~--fY(w8kP&YBRe|ZJ{#=ha?%o=X0BiNEAhbv^8RMK z(e?L=A?aPcZ?kd9Psk+rHqTfUhrA+-xZ|^GJYI#w=$uNh6M zQP7gSUpPx18F`(wOl+%bOVUBZ)r>OdkgCG@Vr*5n?R+UKi90&t1%Aakm>7LKtzIyC z8rz*m?`NisDYANxix>diSQ{__B7+ z=MmPVHIw87c90jw%vhhtb?w=5q>?tGeo5{2i%$xz-EApW8nGYYpXV;viAyr&%VTcJ z+q<6>-W*-dMz5Z$!W8iX4A~4CGbo z?Z5gme5$@%;3W}MykNmtwpQb@cKW(RNMTyN4q{aR7EFhg_`M8?Vc`3BBBVg~qu>G#!tXP@!U7C)-bGnqw>C zVXGfDe**ow#a_|2(J~i~V+_rusNs=IV-pQ>D(iYs&H(jwyKdqFoJOzwd#De3tM}$4 zzPcs%!-Z28cld-WEXG%(dgmD@+Ohbu&cfD_gG(;AxA5K2OH=;g6_7gI-rYj({YV_k zm1kg;N-IAeV2)%0}O`H`yYsN}FjS=BpomPCyxg^H4`KoM0 zd$93wtn6x=RlbQu#(ma;dTEZR2M4P7$c*qhuMQ$Yf-|b>QmTsLo+pGZ?>pe1^cU2f zA+Ls?D%Ei`(R#NX(Mc%TTlmJb z`g%B6ukq;yusedY!dswBR*8kiHxVNu#yEl_+sS!L9lz?j*w?rfy*|8>(X_7Ps0>F! zlIRyhg~uoOm!#Aysb&jJsOntMagwh{7eiJ>W1Lwd6n5${ z1YR|2pfsPkzH@KmbG|*#eyTpd#wqG- z8J3I~b$GE`S#_U%_(N*RInR;ZV2MOCIIbVlWKnqD6NQ~ircEWk^s=J2(WGNV*mkZx zr>y%K*b{aKO5-2(T@Qh<{w%8fAA#&%b5^5k&l~tDTNg&j`t!9Gp&dA&yjM2vc|?6D zrF*I@k6fB6Fvgd?W3hM@a`CYogFM2@0)_6(@8|`>;cdi3JW}>2uc_~9!=k03pn=s4 ztsSv9jr&cU9-!$O^_xI=Zv8)=rVj zb(UMW?ATE(9=lfzDJG?e=TXN|HkJMCa;IzLQnNcVQE%R2_@Wt+L+UNvJtMDyyxOOZ zLFyi{JTCNyb=Mm$D@_krUlTHcZdx$?Y7q}l}z*! z`|TdPR;jM@s3!dI+z=a&U3eweSXS;kT%&x?CSK$O?K^3g3)uoAitH(BS*wnu)c0~>UvWR z!_oaCPBZGIogKH5HdI5CZFP-nkh*_z_Ns0UmF=IV`K}8q4b~B z`(R$TWT8u%&-xkNP!{ByeBGvMSA8|FQrDH$O6t$jc(-UTU92*`7;(4B(X$*ZMll|A z6E3(7$)3sQbpHcnfNkRSV4}3|*ToS_4>4UYoj?~j_B|RzXC&w7>~mu2P!*c(CPlxh zM}3B+MwdG9`?uHWvJPCsBNYv(N|0J`>URHt`TDSZ?%8L(vn5GZ_fL3)lT_NJK}O+} zff{XAP=Ce<)}4BJUis$zJI_0d0)9qJQ|)z_XvIR5(~$`Yk)rleXMjGC@)-B$c0RjT zUW-es@*b6s+bxoMkLvop#wF~azxn_TW8dJo^rK#n>rGzhh$4;4ue73(?)}EUwcA@G zX>TQQLg#mrV70Djvz4e1=pR&fdRIA#s==)ve&r=(T5uUi6Iad`#n-y*J&HKkmLmui zJvyqJBJT6`9K0gW_|TinQGU9@X!N=u5Z2MneOGggmq?}9!br_ebc&9Qa8t1yeDf}( z?}*ClLd6&GLfs8%HIFSso%D+7h$>+X${9p4ehBjRSO2o=i_GMsX(vV24sN*Ray7kV zNq$nday}D6y1deQ20xW`cs=09#~zK)kLm{OoX7>%e!qOr<%p7k_n<7-`?j9t&hImYIW6&C2pBQP=l z&S`s_-}R59`QER#j1zBHEt&Q)WCNk4h)7L(7y6`oGmkcz>$zz<6H8V0lCMwB?yQq| z*PCZW&9-CRW4guY9CyczkG3qWnv)61Jr~28>uV^Ukrc&4PpGbt)RU_#tuTS>szSBy z!`%wbvmN#qn}(KI1wLkZ4Vuz!7;xm8Qs-EKRwL92>W(H)B|U%b|2jQ;C6MYFe|1ft zQ|{Rx@90_4CVi$Q`LnXr_N$1VTE4u|;!88GtJ6BtK`kSLwnz|NhGS@L529J48x6iZtouh&27@DcITEZOr8yi^s0_Am#= zU1+wiv5B!-&-Uu5H}$d^y6jc#_A3zBwGYqA1vIbbBW7cNWPFU%ZGPo`+PRhQDC2yx z30(`Mj0}8FXR7Bbl3HXf-knM_7V;=Xu5Oh1dWA=plagLJ>-uf=J^qtte9FO?5zCQu zuoQA2KG6(yois_BeP8OZF; zRx3WzFObnQhELW1(8og{a)&PZbZMn~}He>3y{Zxvq?&MwJCO%XL zIHzH$-VsQzI*Kg1DDJjeksS#6S_fPszcx>3%C^q6igvMGD{{Q;kCZ)n{*T>8<&jp| zyA5A3(|$;c&TOW%r&q498J*qg4Q(4cJ4=vYpk9b;%*Kg zpS(zw7Z?(IGw2a0y5$`4nP~8pZ!%@CLu6xGTMSBs5?F&v3uzMr=pKP|(9gFy4YFFa z6YEu2M80CD$e{a;)Na4o`+B|QtvWWx}OY7*x0$! zTWh5r7rNE7@hs8@yTl>k3H>wGg4_=TeG4ygO1RFJ96@*3+18Qus8N@C9MV<47fbif z1vB{0Xt-n!MJSF}9^leu2ZZAvu^rEHY)IEU_ugh$;|ni#o4KirobX54KDxp8!~wi$ z#|CurnS8-B3cS1jNL-lJwAqL3%(ETVMVqW-NvWZ=W-ol}R+uAZ^d-VZ=)bh(D$WbM z!nx<1%zzx)B8#tq4w)4o742=}EG&kx+SdG<{kBR+`^N<17xiZeO!jI_VIR4S_9E}5B;$XD<($OY;S%R`3A-B*%8bDWykkxBw>XP4kE*vMRTcrg( z7p%>ua#^_^K;e{jVs9Juy(7{I6J8uNZJajQI&W(C(kwOmVh|?u?Zq;a}^`yXIOCV~+hFD_&);IBiYYIrKGiNq<+1wKqY!(1_%^?XW}a25r>G9E_d9&YaeeoR zM<3Ne!Yb{!N@bPa?YZ~;HZQao*__8Vbpppt3aZiisW$Jmu}2JTJi~W1gb$F9Iy!c^ z6QRIC$8pdZ>+pDtHMDiDB=crI22E$+E;dB<5uO)EY9UTq_UPq()Io(JoL47 z*Kn+Uk}M9R7MLyKQbxGiL!8`hH z<6WKEkbv@{JoGaw~9IjFi1Ox)uG%fx4pE-qQMSvH1)3s}ViZ%5zUu(9Kn$ zTVc0ez_8`vad%4iOSP(*=b5avUNvAHRGt+|mVAu8H_sb+9x;0F?H{`ZQui}U-^(|D2e?{&U+-- zecpq2zJ0yVEu(uEgL**w6`C^7e2jF4lP2=_lP7A5-6of|+@+3cUL}#M_P-jXj&$53 zh_iDloAoR03AaYe=;1YR|0_|{CzIvR*W0jC=nQJ>9lyFxyRWN=r)6dnbn0atb%ad& z{>qi;ov*iZw8G&1)U?j4%Mj~OhSJ5nZf7F*C2lZ+Gjgscg=$%%Y_w{k4yR%k^zTQ1K)4(~dVC4f zbjcjiLhhoXzjd9$FlT0Q*kQcez3FC_?*sbl1NQ0kV!?vWUvr9L2Jl@T`QkGRJ8yLG z_UR|tC#$R?zu10Kk?=eW?isC`WU>9uzdxP%@Q*q3c{buJ>~DY9h>XRz`M>Yj2V6C! z&OKcK*Z5N7oSeESK2sjE!0z$0pm>?RPO>|$8o_pt^26+0vI^EJRPAiH&v}X{*O;AV z_a8paMqy=Rlj)5$$K%TH2kbnbXV}hkYuRe&=^l=DnAKFC<&(Y6v!htIyt1@Zuptlt zoD@RG%1lwbxHur0XO$hJl^sUoAGUOYal^kGjWRkr%FQ>HTy3?rSFl{qMJ)^oc!H%? z2HA-T-(01&xp=wFt~(vm%Vb4hY3CbyX4o5Es{71uwr@```7N+c7f+;FVBKQTaB6Xg z(IDifC&3k7E9`7!%fA(-r!lKG2kgwa!(?Gxz-NA5mD`lpWj5Bd&b}VkLTJ0Nt3?j6 zBgTzhtbe<4ERS)y9XRvDGY_%XVfI?Mdi(Zun=ajW-N3b*Hg4X2`s}N=Z9Z-Ln#g}86Uw!=SflaG7Z@6sT_8qI%ZQH(K%jVN(A3uM= z>@yBMXkcLBj%`Hy=p_hV3@`C~mdUhkF{R-9{f4o^}C_0gf&%o__8T5m3f(nul", + ] + .join(" & "), + ); + self.check(); + } + fn stop(&mut self) { + call( + [ + "echo.", + "%nssm% stop hbbr", + "%nssm% remove hbbr confirm", + "echo.", + "%nssm% stop hbbs", + "%nssm% remove hbbs confirm", + "echo.", + "@ping 127.1 -n 3 >nul", + ] + .join(" & "), + ); + self.check(); + } + fn restart(&mut self) { + nssm(["restart", "hbbs"].map(|x| x.to_owned())); + nssm(["restart", "hbbr"].map(|x| x.to_owned())); + self.check(); + } + fn pause(&mut self) { + call( + [ + "echo.", + "%nssm% stop hbbr", + "echo.", + "%nssm% stop hbbs", + "echo.", + "@ping 127.1 -n 3 >nul", + ] + .join(" & "), + ); + self.check(); + } + fn check(&mut self) -> DesktopServiceState { + self.state = match service_status("hbbs").as_str() { + "Running" => DesktopServiceState::Started, + // "Stopped" => DeskServerServiceState::Paused, + _ => DesktopServiceState::Stopped, + }; + self.state.to_owned() + } +} + +fn call(cmd: String) { + Command::new("cmd") + .current_dir(&path()) + .env("nssm", "service\\nssm.exe") + .arg("/c") + .arg("start") + .arg("cmd") + .arg("/c") + .arg(cmd) + .output() + .expect("cmd exec error!"); +} + +fn exec(program: S, args: I) -> String +where + I: IntoIterator, + S: AsRef, +{ + match Command::new(program).args(args).output() { + Ok(out) => String::from_utf8(out.stdout).unwrap_or("".to_owned()), + Err(e) => e.to_string(), + } +} + +fn nssm(args: I) -> String +where + I: IntoIterator, +{ + exec( + format!("{}\\service\\nssm.exe", path().to_str().unwrap_or_default()), + args, + ) + .replace("\0", "") + .trim() + .to_owned() +} + +fn service_status(name: &str) -> String { + match ServiceManager::local_computer(None::<&OsStr>, ServiceManagerAccess::CONNECT) { + Ok(manager) => match manager.open_service(name, ServiceAccess::QUERY_STATUS) { + Ok(service) => match service.query_status() { + Ok(status) => format!("{:?}", status.current_state), + Err(e) => e.to_string(), + }, + Err(e) => e.to_string(), + }, + Err(e) => e.to_string(), + } +} diff --git a/ui/src/adapter/view/desktop.rs b/ui/src/adapter/view/desktop.rs new file mode 100644 index 0000000..328d587 --- /dev/null +++ b/ui/src/adapter/view/desktop.rs @@ -0,0 +1,220 @@ +use std::{ + process::exit, + time::{Duration, Instant}, +}; + +use crate::{ + path, + usecase::{view::Event, DesktopServiceState}, + BUFFER, +}; +use async_std::task::sleep; +use crossbeam_channel::{Receiver, Sender}; +use tauri::{ + CustomMenuItem, Manager, Menu, MenuItem, Submenu, SystemTray, SystemTrayEvent, SystemTrayMenu, + SystemTrayMenuItem, WindowEvent, +}; + +pub async fn run(sender: Sender, receiver: Receiver) { + let setup_sender = sender.clone(); + let menu_sender = sender.clone(); + let tray_sender = sender.clone(); + let menu = Menu::new() + .add_submenu(Submenu::new( + "Service", + Menu::new() + .add_item(CustomMenuItem::new("restart", "Restart")) + .add_native_item(MenuItem::Separator) + .add_item(CustomMenuItem::new("start", "Start")) + .add_item(CustomMenuItem::new("stop", "Stop")), + )) + .add_submenu(Submenu::new( + "Logs", + Menu::new() + .add_item(CustomMenuItem::new("hbbs.out", "hbbs.out")) + .add_item(CustomMenuItem::new("hbbs.err", "hbbs.err")) + .add_native_item(MenuItem::Separator) + .add_item(CustomMenuItem::new("hbbr.out", "hbbr.out")) + .add_item(CustomMenuItem::new("hbbr.err", "hbbr.err")), + )) + .add_submenu(Submenu::new( + "Configuration", + Menu::new().add_item(CustomMenuItem::new(".env", ".env")), + )); + let tray = SystemTray::new().with_menu( + SystemTrayMenu::new() + .add_item(CustomMenuItem::new("restart", "Restart")) + .add_native_item(SystemTrayMenuItem::Separator) + .add_item(CustomMenuItem::new("start", "Start")) + .add_item(CustomMenuItem::new("stop", "Stop")) + .add_native_item(SystemTrayMenuItem::Separator) + .add_item(CustomMenuItem::new("exit", "Exit GUI")), + ); + let mut app = tauri::Builder::default() + .on_window_event(|event| match event.event() { + // WindowEvent::Resized(size) => { + // if size.width == 0 && size.height == 0 { + // event.window().hide().unwrap(); + // } + // } + WindowEvent::CloseRequested { api, .. } => { + api.prevent_close(); + event.window().hide().unwrap(); + } + _ => {} + }) + .menu(menu) + .on_menu_event(move |event| { + // println!( + // "send {}: {}", + // std::time::SystemTime::now() + // .duration_since(std::time::UNIX_EPOCH) + // .unwrap_or_default() + // .as_millis(), + // event.menu_item_id() + // ); + menu_sender + .send(Event::ViewAction(event.menu_item_id().to_owned())) + .unwrap_or_default() + }) + .system_tray(tray) + .on_system_tray_event(move |app, event| match event { + SystemTrayEvent::LeftClick { .. } => { + let main = app.get_window("main").unwrap(); + if main.is_visible().unwrap() { + main.hide().unwrap(); + } else { + main.show().unwrap(); + main.unminimize().unwrap(); + main.set_focus().unwrap(); + } + } + SystemTrayEvent::MenuItemClick { id, .. } => { + tray_sender.send(Event::ViewAction(id)).unwrap_or_default(); + } + _ => {} + }) + .setup(move |app| { + setup_sender.send(Event::ViewInit).unwrap_or_default(); + app.listen_global("__action__", move |msg| { + match msg.payload().unwrap_or_default() { + r#""__init__""# => setup_sender.send(Event::BroswerInit).unwrap_or_default(), + r#""restart""# => setup_sender + .send(Event::BrowserAction("restart".to_owned())) + .unwrap_or_default(), + _ => (), + } + }); + Ok(()) + }) + .invoke_handler(tauri::generate_handler![root]) + .build(tauri::generate_context!()) + .expect("error while running tauri application"); + let mut now = Instant::now(); + let mut blink = false; + let mut span = 0; + let mut title = "".to_owned(); + let product = "RustDesk Server"; + let buffer = BUFFER.get().unwrap().to_owned(); + loop { + for _ in 1..buffer { + match receiver.recv_timeout(Duration::from_nanos(1)) { + Ok(event) => { + let main = app.get_window("main").unwrap(); + let menu = main.menu_handle(); + let tray = app.tray_handle(); + match event { + Event::BrowserUpdate((action, data)) => match action.as_str() { + "file" => { + let list = ["hbbs.out", "hbbs.err", "hbbr.out", "hbbr.err", ".env"]; + let id = data.as_str(); + if list.contains(&id) { + for file in list { + menu.get_item(file) + .set_selected(file == id) + .unwrap_or_default(); + } + // println!( + // "emit {}: {}", + // std::time::SystemTime::now() + // .duration_since(std::time::UNIX_EPOCH) + // .unwrap_or_default() + // .as_millis(), + // data + // ); + app.emit_all("__update__", (action, data)) + .unwrap_or_default(); + } + } + _ => (), + }, + Event::ViewRenderAppExit => exit(0), + Event::ViewRenderServiceState(state) => { + let enabled = |id, enabled| { + menu.get_item(id).set_enabled(enabled).unwrap_or_default(); + tray.get_item(id).set_enabled(enabled).unwrap_or_default(); + }; + title = format!("{} {:?}", product, state); + main.set_title(title.as_str()).unwrap_or_default(); + match state { + DesktopServiceState::Started => { + enabled("start", false); + enabled("stop", true); + enabled("restart", true); + blink = false; + } + DesktopServiceState::Stopped => { + enabled("start", true); + enabled("stop", false); + enabled("restart", false); + blink = true; + } + _ => { + enabled("start", false); + enabled("stop", false); + enabled("restart", false); + blink = true; + } + } + } + _ => (), + } + } + Err(_) => break, + } + } + let elapsed = now.elapsed().as_micros(); + if elapsed > 16666 { + now = Instant::now(); + // println!("{}ms", elapsed as f64 * 0.001); + let iteration = app.run_iteration(); + if iteration.window_count == 0 { + break; + } + if blink { + if span > 1000000 { + span = 0; + app.get_window("main") + .unwrap() + .set_title(title.as_str()) + .unwrap_or_default(); + } else { + span += elapsed; + if span > 500000 { + app.get_window("main") + .unwrap() + .set_title(product) + .unwrap_or_default(); + } + } + } + } else { + sleep(Duration::from_micros(999)).await; + } + } +} + +#[tauri::command] +fn root() -> String { + path().to_str().unwrap_or_default().to_owned() +} diff --git a/ui/src/adapter/view/mod.rs b/ui/src/adapter/view/mod.rs new file mode 100644 index 0000000..8569296 --- /dev/null +++ b/ui/src/adapter/view/mod.rs @@ -0,0 +1,3 @@ +pub mod desktop; + +pub use desktop::*; diff --git a/ui/src/lib.rs b/ui/src/lib.rs new file mode 100644 index 0000000..cdfb4f6 --- /dev/null +++ b/ui/src/lib.rs @@ -0,0 +1,17 @@ +use std::{env::current_exe, path::PathBuf}; + +use once_cell::sync::OnceCell; + +pub mod adapter; +pub mod usecase; + +pub static BUFFER: OnceCell = OnceCell::new(); + +pub fn path() -> PathBuf { + current_exe() + .unwrap_or_default() + .as_path() + .parent() + .unwrap() + .to_owned() +} diff --git a/ui/src/main.rs b/ui/src/main.rs new file mode 100644 index 0000000..b551470 --- /dev/null +++ b/ui/src/main.rs @@ -0,0 +1,25 @@ +#![cfg_attr( + all(not(debug_assertions), target_os = "windows"), + windows_subsystem = "windows" +)] + +use async_std::{ + prelude::FutureExt, + task::{spawn, spawn_local}, +}; +use crossbeam_channel::bounded; +use rustdesk_server::{ + usecase::{presenter, view, watcher}, + BUFFER, +}; + +#[async_std::main] +async fn main() { + let buffer = BUFFER.get_or_init(|| 10).to_owned(); + let (view_sender, presenter_receiver) = bounded(buffer); + let (presenter_sender, view_receiver) = bounded(buffer); + spawn_local(view::create(presenter_sender.clone(), presenter_receiver)) + .join(spawn(presenter::create(view_sender, view_receiver))) + .join(spawn(watcher::create(presenter_sender))) + .await; +} diff --git a/ui/src/usecase/mod.rs b/ui/src/usecase/mod.rs new file mode 100644 index 0000000..7ca5fcb --- /dev/null +++ b/ui/src/usecase/mod.rs @@ -0,0 +1,9 @@ +pub mod presenter; +pub mod service; +pub mod view; +pub mod watcher; + +pub use presenter::*; +pub use service::*; +pub use view::*; +pub use watcher::*; diff --git a/ui/src/usecase/presenter.rs b/ui/src/usecase/presenter.rs new file mode 100644 index 0000000..335d16d --- /dev/null +++ b/ui/src/usecase/presenter.rs @@ -0,0 +1,59 @@ +use std::time::{Duration, Instant}; + +use super::{service, DesktopServiceState, Event}; +use crate::BUFFER; +use async_std::task::sleep; +use crossbeam_channel::{Receiver, Sender}; + +pub async fn create(sender: Sender, receiver: Receiver) { + let mut now = Instant::now(); + let buffer = BUFFER.get().unwrap().to_owned(); + let send = |event| sender.send(event).unwrap_or_default(); + if let Some(mut service) = service::create() { + let mut service_state = DesktopServiceState::Unknown; + let mut file = "hbbs.out".to_owned(); + send(Event::ViewRenderServiceState(service_state.to_owned())); + loop { + for _ in 1..buffer { + match receiver.recv_timeout(Duration::from_nanos(1)) { + Ok(event) => match event { + Event::BroswerInit => { + send(Event::BrowserUpdate(("file".to_owned(), file.to_owned()))); + } + Event::BrowserAction(action) => match action.as_str() { + "restart" => service.restart(), + _ => (), + }, + Event::FileChange(path) => { + if path == file { + send(Event::BrowserUpdate(("file".to_owned(), file.to_owned()))); + } + } + Event::ViewAction(action) => match action.as_str() { + "start" => service.start(), + "stop" => service.stop(), + "restart" => service.restart(), + "pause" => service.pause(), + "exit" => send(Event::ViewRenderAppExit), + _ => { + file = action; + send(Event::BrowserUpdate(("file".to_owned(), file.to_owned()))); + } + }, + _ => (), + }, + Err(_) => break, + } + } + sleep(Duration::from_micros(999)).await; + if now.elapsed().as_millis() > 999 { + let state = service.check(); + if state != service_state { + service_state = state.to_owned(); + send(Event::ViewRenderServiceState(state)); + } + now = Instant::now(); + } + } + } +} diff --git a/ui/src/usecase/service.rs b/ui/src/usecase/service.rs new file mode 100644 index 0000000..4d992c1 --- /dev/null +++ b/ui/src/usecase/service.rs @@ -0,0 +1,24 @@ +use crate::adapter; + +pub fn create() -> Option> { + if cfg!(target_os = "windows") { + return Some(Box::new(adapter::WindowsDesktopService::new())); + } + None +} + +#[derive(Debug, Clone, PartialEq)] +pub enum DesktopServiceState { + Paused, + Started, + Stopped, + Unknown, +} + +pub trait IDesktopService { + fn start(&mut self); + fn stop(&mut self); + fn restart(&mut self); + fn pause(&mut self); + fn check(&mut self) -> DesktopServiceState; +} diff --git a/ui/src/usecase/view.rs b/ui/src/usecase/view.rs new file mode 100644 index 0000000..882769b --- /dev/null +++ b/ui/src/usecase/view.rs @@ -0,0 +1,22 @@ +use super::DesktopServiceState; +use crate::adapter::desktop; +use crossbeam_channel::{Receiver, Sender}; + +pub async fn create(sender: Sender, receiver: Receiver) { + desktop::run(sender, receiver).await; +} + +#[derive(Debug, Clone, PartialEq)] +pub enum Event { + BrowserAction(String), + BroswerInit, + BrowserUpdate((String, String)), + BrowserRender(String), + FileChange(String), + ViewAction(String), + ViewInit, + ViewUpdate(String), + ViewRender(String), + ViewRenderAppExit, + ViewRenderServiceState(DesktopServiceState), +} diff --git a/ui/src/usecase/watcher.rs b/ui/src/usecase/watcher.rs new file mode 100644 index 0000000..883ba68 --- /dev/null +++ b/ui/src/usecase/watcher.rs @@ -0,0 +1,46 @@ +use std::{path::Path, time::Duration}; + +use super::Event; +use crate::path; +use async_std::task::{sleep, spawn_blocking}; +use crossbeam_channel::{bounded, Sender}; +use notify::{Config, RecommendedWatcher, RecursiveMode, Result, Watcher}; + +pub async fn create(sender: Sender) { + loop { + let watch_sender = sender.clone(); + match spawn_blocking(|| { + watch( + format!("{}/logs/", path().to_str().unwrap_or_default()), + watch_sender, + ) + }) + .await + { + Ok(_) => (), + Err(e) => println!("error: {e}"), + } + sleep(Duration::from_secs(1)).await; + } +} + +fn watch>(path: P, sender: Sender) -> Result<()> { + let (tx, rx) = bounded(10); + let mut watcher = RecommendedWatcher::new(tx, Config::default())?; + watcher.watch(path.as_ref(), RecursiveMode::Recursive)?; + for res in rx { + let event = res?; + for p in event.paths { + let path = p + .file_name() + .unwrap_or_default() + .to_str() + .unwrap_or_default() + .to_owned(); + if path.len() > 0 { + sender.send(Event::FileChange(path)).unwrap_or_default(); + } + } + } + Ok(()) +} diff --git a/ui/tauri.conf.json b/ui/tauri.conf.json new file mode 100644 index 0000000..0afeda1 --- /dev/null +++ b/ui/tauri.conf.json @@ -0,0 +1,89 @@ +{ + "build": { + "beforeDevCommand": "", + "beforeBuildCommand": "", + "devPath": "html", + "distDir": "html", + "withGlobalTauri": true + }, + "package": { + "productName": "rustdesk_server", + "version": "0.1.1" + }, + "tauri": { + "allowlist": { + "all": false, + "fs": { + "scope": [ + "$RESOURCE/bin/.env", + "$RESOURCE/logs/*" + ], + "all": false, + "exists": true, + "readDir": true, + "readFile": true, + "writeFile": true + }, + "path": { + "all": true + }, + "shell": { + "all": false, + "open": true + } + }, + "bundle": { + "active": true, + "category": "DeveloperTool", + "copyright": "", + "deb": { + "depends": [] + }, + "externalBin": [], + "icon": [ + "icons/32x32.png", + "icons/128x128.png", + "icons/128x128@2x.png", + "icons/icon.icns", + "icons/icon.ico" + ], + "identifier": "rustdesk_server", + "longDescription": "", + "macOS": { + "entitlements": null, + "exceptionDomain": "", + "frameworks": [], + "providerShortName": null, + "signingIdentity": null + }, + "resources": [], + "shortDescription": "", + "targets": "all", + "windows": { + "certificateThumbprint": null, + "digestAlgorithm": "sha256", + "timestampUrl": "" + } + }, + "security": { + "csp": null + }, + "systemTray": { + "iconPath": "icons/icon.ico", + "iconAsTemplate": true + }, + "updater": { + "active": false + }, + "windows": [ + { + "center": true, + "fullscreen": false, + "height": 600, + "resizable": true, + "title": "RustDesk Server", + "width": 980 + } + ] + } +}