pax_global_header00006660000000000000000000000064151066015700014513gustar00rootroot0000000000000052 comment=74b46e665f68d0356148c80721508eb376ac6f97 qman-1.5.1/000077500000000000000000000000001510660157000124535ustar00rootroot00000000000000qman-1.5.1/.gitignore000066400000000000000000000007471510660157000144530ustar00rootroot00000000000000# Prerequisites *.d # Object files *.o *.ko *.obj *.elf # Linker output *.ilk *.map *.exp # Precompiled Headers *.gch *.pch # Libraries *.lib *.a *.la *.lo # Shared objects (inc. Windows DLLs) *.dll *.so *.so.* *.dylib # Executables *.exe *.out *.app *.i*86 *.x86_64 *.hex # Debug files *.dSYM/ *.su *.idb *.pdb # Kernel Module Compile Results *.mod* *.cmd .tmp_versions/ modules.order Module.symvers Mkfile.old dkms.conf # Tooling junk build/ .cache/ .ccls-cache/ __pycache__/ qman-1.5.1/LICENSE000066400000000000000000000024541510660157000134650ustar00rootroot00000000000000BSD 2-Clause License Copyright (c) 2023-2025, Pantelis Panayiotou and others Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. qman-1.5.1/README.md000066400000000000000000000101731510660157000137340ustar00rootroot00000000000000# Qman A more modern manual page viewer for our terminals Version 1.5.1 -- [see what's new](#new-in-this-version) ![Screenhot -- Viewing a Manual Page](/screenshots/qman_man.png) ## Get started - [Generic build instructions](doc/BUILDING.md) (works for most Linux distros) - [O/S specific instructions](doc/OS_SPECIFIC.md) - [Manual](man/qman.1.md) - [Troubleshooting](doc/TROUBLESHOOTING.md) - [Packages](doc/PACKAGES.md) - [Configuration and themes](config/) - [Contributing](doc/CONTRIBUTING.md) ## Rationale Unix manual pages are lovely. They are concise, well-written, complete, and downright useful. However, the standard way of accessing them from the command-line hasn't changed since the early days. Qman aims to change that. It's a modern, full-featured manual page viewer featuring hyperlinks, web browser like navigation, a table of contents for each page, incremental search, on-line help, and more. It also strives to be fast and tiny, so that it can be used everywhere. For this reason, it's been written in plain C and has only minimal dependencies. ## Features - Index page that displays all manual pages available on the system, sorted alphabetically and organised by section - Pages for apropos and whatis results - Hyperlinks to other manual pages - Hyperlinks for URLs and email addresses - Hyperlinks to files or directories in the local filesystem - In-page hyperlinks - A table of contents for each manual page - Incremental search for manual pages - Incremental free page text search - Command-line options similar to those of `man` (most importantly, `-k` and `-f`) - Keyboard mappings similar to those of `less` - Mouse support - Navigation history - On-line help - Fully configurable using INI-style config files - Manual page ## Project status All basic functionality has been completed. The software has been in use since late 2023 and is considered stable. Bugs, of course, still happen. If you think you have found one, please open an [issue](https://github.com/plp13/qman/issues). ## New in this version Version 1.5.0 introduces the following: - Support for several different manual page systems. Historically Qman only supported `mandb`, but this is no longer the case. The program now supports the following manual page systems: - **[mandb](https://gitlab.com/man-db/man-db)** - most Linux distributions - **[mandoc](https://mandoc.bsd.lv/)** - Void Linux, Haiku, others? - **[freebsd](https://www.freebsd.org/)** - FreeBSD - **[darwin](https://www.apple.com/macos/)** - macOS - Hyperlinks to files or directories in the local filesystem (new config option `viewer_path` can be used to specify the program for opening them) - New `[capabilities]` config file section enables users to disable several non- core program features - Three new themes: - `adwaita`, designed to match the colors of dark Adwaita desktops - `adwaita-light`, designed to match the colors of light Adwaita desktops - `modernity-light`, a generic light theme to complement `modernity` - Re-organized and extended documentation - Improved error messages, especially when it comes to errors caused by misconfiguration or a missing manual pages database - Miscellaneous other bug fixes and minor features Version 1.5.1 fixes an issue with reporting errors in configruation files, and introduces a few updates to Qman's documentation. > **:bulb: Note** > > Users using custom config files may need to update them after a new release. > For more information, please refer to Qman's manual page and the documentation > in [config/README.md](config/README.md). > > In version 1.5.0, config options `sections_on_top`, `hyphenate` and `justify` > have been moved to section `[capabilities]`. ## More screenshots Index page: ![Index Page](/screenshots/qman_index.png) Opening a manual page using a pop-up: ![Screenshot -- Opening a Manual Page](/screenshots/qman_open.png) Using the table of contents: ![Using the Table of Contents](/screenshots/qman_toc.png) Searching incrementally: ![Searching incrementally](/screenshots/qman_search.png) Performing apropos: ![Performing Apropos](/screenshots/qman_apropos.png) Online help: ![Online Help](/screenshots/qman_help.png) qman-1.5.1/bump.sh000077500000000000000000000016631510660157000137630ustar00rootroot00000000000000#!/usr/bin/env bash # Bump version to ${1} exit_on_error() { if [ "X${1}" != "X0" ] then echo "Command failed" exit ${1} fi } if [ "X${1}" = "X" ] then echo "Usage: ${0} " exit -1 else echo "Setting version to ${1}" cd "$( dirname "${BASH_SOURCE[0]}" )" exit_on_error $? echo "- meson.build" sed -i "s/version: '[a-zA-Z0-9][\.\a-zA-Z0-9]*'/version: '${1}'/g" meson.build exit_on_error $? echo "- src/config_def.py" sed -i "s/\"program_version\": ((\"wstring\",), (\"Qman [a-zA-Z0-9][\.\a-zA-Z0-9]*\",)/\"program_version\": ((\"wstring\",), (\"Qman ${1}\",)/g" src/config_def.py exit_on_error $? echo "- README.md" sed -i "s/Version [a-zA-Z0-9][\.\a-zA-Z0-9]* --/Version ${1} --/g" README.md exit_on_error $? echo "- man/qman.1.md" sed -i "s/footer: Qman [a-zA-Z0-9][\.\a-zA-Z0-9]*/footer: Qman ${1}/g" man/qman.1.md exit_on_error $? cd man ./build_man.sh exit_on_error $? fi qman-1.5.1/config/000077500000000000000000000000001510660157000137205ustar00rootroot00000000000000qman-1.5.1/config/README.md000066400000000000000000000023121510660157000151750ustar00rootroot00000000000000# Configuration files `qman.conf` is a basic configuration file that should be sufficient for most users. It's automatically installed at `/etc/xdg/qman/qman.conf`. Alternatively, and in order to configure Qman on a per-user basis, it can be copied to `${HOME}/.config/qman/qman.conf`. A complete reference on configuration files can be found in [Qman's manual page](../man/qman.1.md). ## Themes A number of different themes for Qman can be found in the `themes` subfolder. These can be included into your main configuration file with the `include` directive, for example: ``` include themes/modernity.conf ``` > **:bulb: Note** > > Include paths are relative to the location of the configuration file that > contains the `include` directive. For example, if the above line of code is in > `/home/user/.config/qman/qman.conf`, Qman will expect to find `modernity.conf` > in `/home/user/.config/qman/themes/`. When in doubt, use absolute paths. > **:bulb: Note** > > Each theme has its own requirements and may not work with all terminal > emulators. For example, a theme may require support for 8-bit or 24-bit color, > or a specific Unicode font. These requirements are generally documented in > the theme's comments. qman-1.5.1/config/meson.build000066400000000000000000000014541510660157000160660ustar00rootroot00000000000000# Configuration build file # Main configuration file if get_option('config').enabled() or get_option('config').auto() install_data( ['qman.conf'], install_dir: get_option('configdir'), install_tag: 'config' ) endif # Configuration files for themes if get_option('config').enabled() or get_option('config').auto() install_data( [ 'themes/modernity.conf', 'themes/modernity-light.conf', 'themes/adwaita.conf', 'themes/adwaita-light.conf', 'themes/catppuccin_latte.conf' ], install_dir: get_option('configdir') + '/themes', install_tag: 'config' ) endif # README.md if get_option('docs').enabled() or get_option('docs').auto() install_data( ['README.md'], install_dir: get_option('docdir') + '/config', install_tag: 'doc' ) endif qman-1.5.1/config/qman.conf000066400000000000000000000013001510660157000155150ustar00rootroot00000000000000; qman.conf ; Qman config ; description: Barebones configuration file for Qman ; Change this to a theme of your choice include themes/modernity.conf [mouse] ; Mouse support in some terminal emulators is incomplete and/or buggy. Set this ; to false if you are having mouse trouble. enable= true [misc] ; If using a graphical web browser, uncomment this to suppress an annoying ; flicker after opening an HTTP link ; reset_after_http= false ; If using a graphical email client, uncomment this to suppress an annoying ; flicker after opening an email link ; reset_after_email= false [layout] ; Change this to suit your terminal window size lmargin= 5 rmargin= 5 qman-1.5.1/config/themes/000077500000000000000000000000001510660157000152055ustar00rootroot00000000000000qman-1.5.1/config/themes/adwaita-light.conf000066400000000000000000000036541510660157000206030ustar00rootroot00000000000000; adwaita.conf ; Qman theme ; description: A theme designed to match Adwaita's look (light version) ; tags: rgb, unicode, light ; TERM: xterm-256color ; based on: ; author: plp13 [chars] sbar_top= ▖ sbar_vline= ▌ sbar_bottom= ▘ sbar_block= ▌ trans_mode_name= 🭬 trans_name_loc= 🭬 box_hline= ─ box_vline= │ box_tl= ╭ box_tr= ╮ box_bl= ╰ box_br= ╯ arrow_up= ⇡ arrow_down= ⇣ arrow_lr= ⇄ [colours] text= #241F31 #F6F5F4 false search= #F6F5F4 #241F31 true mark= #241F31 #1A5FB4 true link_man= #26A269 #F6F5F4 false link_man_f= #F6F5F4 #26A269 false link_http= #613583 #F6F5F4 false link_http_f= #F6F5F4 #613583 false link_email= #613583 #F6F5F4 false link_email_f= #F6F5F4 #613583 false link_file= #1A5FB4 #F6F5F4 false link_file_f= #F6F5F4 #1A5FB4 false link_ls= #E66100 #F6F5F4 false link_ls_f= #F6F5F4 #E66100 true sb_line= #DEDDDA #F6F5F4 true sb_block= #77767B #F6F5F4 true stat_indic_mode= #F6F5F4 #1A5FB4 true stat_indic_name= #F6F5F4 #3584E4 false stat_indic_loc= #A51D2D #99C1F1 false stat_input_prompt= #241F31 #F6F5F4 false stat_input_help= #E66100 #F6F5F4 true stat_input_em= #A51D2D #F6F5F4 true imm_border= #9A9996 #F6F5F4 true imm_title= #F6F5F4 #1A5FB4 false sp_input= #241F31 #F6F5F4 true sp_text= #77767B #F6F5F4 false sp_text_f= #1C71D8 #F6F5F4 true help_text= #3D3846 #F6F5F4 false help_text_f= #1C71D8 #F6F5F4 true history_text= #3D3846 #F6F5F4 false history_text_f= #1C71D8 #F6F5F4 true toc_text= #3D3846 #F6F5F4 false toc_text_f= #1C71D8 #F6F5F4 true [layout] lmargin= 5 rmargin= 6 qman-1.5.1/config/themes/adwaita.conf000066400000000000000000000036521510660157000174740ustar00rootroot00000000000000; adwaita.conf ; Qman theme ; description: A theme designed to match Adwaita's look (dark version) ; tags: rgb, unicode, dark ; TERM: xterm-256color ; based on: ; author: plp13 [chars] sbar_top= ▖ sbar_vline= ▌ sbar_bottom= ▘ sbar_block= ▌ trans_mode_name= 🭬 trans_name_loc= 🭬 box_hline= ─ box_vline= │ box_tl= ╭ box_tr= ╮ box_bl= ╰ box_br= ╯ arrow_up= ⇡ arrow_down= ⇣ arrow_lr= ⇄ [colours] text= #F6F5F4 #241F31 false search= #241F31 #F6F5F4 true mark= #F6F5F4 #1A5FB4 true link_man= #2EC27E #241F31 false link_man_f= #241F31 #2EC27E false link_http= #9141AC #241F31 false link_http_f= #241F31 #9141AC false link_email= #9141AC #241F31 false link_email_f= #241F31 #9141AC false link_file= #1C71D8 #241F31 false link_file_f= #241F31 #1C71D8 false link_ls= #F5C211 #241F31 false link_ls_f= #241F31 #F5C211 true sb_line= #3D3846 #241F31 true sb_block= #9A9996 #241F31 true stat_indic_mode= #F6F5F4 #1A5FB4 true stat_indic_name= #F6F5F4 #3584E4 false stat_indic_loc= #A51D2D #99C1F1 false stat_input_prompt= #F6F5F4 #241F31 false stat_input_help= #F5C211 #241F31 true stat_input_em= #A51D2D #241F31 true imm_border= #9A9996 #241F31 true imm_title= #F6F5F4 #1A5FB4 false sp_input= #F6F5F4 #241F31 true sp_text= #77767B #241F31 false sp_text_f= #1C71D8 #241F31 true help_text= #DEDDDA #241F31 false help_text_f= #1C71D8 #241F31 true history_text= #DEDDDA #241F31 false history_text_f= #1C71D8 #241F31 true toc_text= #DEDDDA #241F31 false toc_text_f= #1C71D8 #241F31 true [layout] lmargin= 5 rmargin= 6 qman-1.5.1/config/themes/catppuccin_latte.conf000066400000000000000000000041761510660157000214060ustar00rootroot00000000000000; latte.conf ; Qman theme ; description: catppuccin-latte: a light theme for Qman ; tags: rgb, unicode, light ; TERM: xterm-kitty ; based on: https://github.com/catppuccin/kitty/blob/main/themes/latte.conf ; author: mazunki [chars] sbar_top= ┳ sbar_vline= ┃ sbar_bottom= ┻ sbar_block= █ trans_mode_name= ┇ trans_name_loc= ┇ box_hline= ─ box_vline= │ box_tl= ╭ box_tr= ╮ box_bl= ╰ box_br= ╯ arrow_up= ⇡ arrow_down= ⇣ arrow_lr= ⇄ [colours] ; fg bg bold text= #4c4f69 #eff1f5 false search= #0c0f69 #f5e0dc false mark= #4c4f69 #f5e0dc true link_man= #1e66f5 #d9e0ee true link_man_f= #1e66f5 #c6cedd true link_http= #179299 #cad3e5 false link_http_f= #179299 #b2bacd true link_email= #df8e1d #d9e0ee false link_email_f= #df8e1d #c6cedd true link_file= #121997 #cad3e5 false link_file_f= #121997 #b2bacd true link_ls= #40a02b #eff1f5 true link_ls_f= #40a02b #b2bacd true sb_line= #d889ff #eff1f5 true sb_block= #8839ef #8839ef true stat_indic_mode= #4c4f69 #d889ff true stat_indic_name= #4c4f69 #d889ff true stat_indic_loc= #4c4f69 #d889ff true stat_input_prompt= #4c4f69 #eff1f5 true stat_input_help= #4c4f69 #eff1f5 true stat_input_em= #4c4f69 #eff1f5 true imm_border= #4c4f69 #eff1f5 true imm_title= #4c4f69 #eff1f5 true sp_input= #4c4f69 #eff1f5 true sp_text= #4c4f69 #eff1f5 false sp_text_f= #4c4f69 #eff1f5 true help_text= #4c4f69 #eff1f5 false help_text_f= #4c4f69 #eff1f5 true history_text= #4c4f69 #eff1f5 false history_text_f= #4c4f69 #eff1f5 true toc_text= #4c4f69 #eff1f5 false toc_text_f= #4c4f69 #eff1f5 true [layout] lmargin= 3 rmargin= 5 qman-1.5.1/config/themes/modernity-light.conf000066400000000000000000000036511510660157000212000ustar00rootroot00000000000000; modernity-light.conf ; Qman theme ; description: A modern theme for Qman (light version) ; tags: 256color, unicode, light ; TERM: xterm-256color ; based on: ; author: plp13 [chars] sbar_top= ┳ sbar_vline= ┃ sbar_bottom= ┻ sbar_block= █ trans_mode_name= ┇ trans_name_loc= ┇ box_hline= ─ box_vline= │ box_tl= ╭ box_tr= ╮ box_bl= ╰ box_br= ╯ arrow_up= ⇡ arrow_down= ⇣ arrow_lr= ⇄ [colours] text= 234 254 false search= 236 250 true mark= 236 75 true link_man= 28 254 false link_man_f= 28 250 false link_http= 161 254 false link_http_f= 161 250 false link_email= 161 254 false link_email_f= 161 250 false link_file= 27 254 false link_file_f= 27 250 false link_ls= 172 254 false link_ls_f= 172 250 false sb_line= 68 254 true sb_block= 68 254 true stat_indic_mode= 234 68 true stat_indic_name= 254 242 false stat_indic_loc= 88 248 false stat_input_prompt= 68 254 false stat_input_help= 172 254 true stat_input_em= 124 254 true imm_border= 68 254 true imm_title= 234 68 true sp_input= 234 254 false sp_text= 68 254 false sp_text_f= 234 254 false help_text= 234 254 false help_text_f= 255 236 true history_text= 234 254 false history_text_f= 255 236 true toc_text= 234 254 false toc_text_f= 255 236 true [layout] lmargin= 5 rmargin= 6 qman-1.5.1/config/themes/modernity.conf000066400000000000000000000036401510660157000200710ustar00rootroot00000000000000; modernity.conf ; Qman theme ; description: A modern theme for Qman (dark version) ; tags: 256color, unicode, dark ; TERM: xterm-256color ; based on: ; author: plp13 [chars] sbar_top= ┳ sbar_vline= ┃ sbar_bottom= ┻ sbar_block= █ trans_mode_name= ┇ trans_name_loc= ┇ box_hline= ─ box_vline= │ box_tl= ╭ box_tr= ╮ box_bl= ╰ box_br= ╯ arrow_up= ⇡ arrow_down= ⇣ arrow_lr= ⇄ [colours] text= 252 232 false search= 236 250 true mark= 75 236 true link_man= 34 232 false link_man_f= 234 34 false link_http= 162 232 false link_http_f= 234 162 false link_email= 162 232 false link_email_f= 234 162 false link_file= 27 232 false link_file_f= 234 27 false link_ls= 178 232 false link_ls_f= 234 178 false sb_line= 75 232 true sb_block= 75 232 true stat_indic_mode= 234 75 true stat_indic_name= 254 242 false stat_indic_loc= 88 248 false stat_input_prompt= 75 232 false stat_input_help= 178 232 true stat_input_em= 124 232 true imm_border= 75 232 true imm_title= 234 75 true sp_input= 252 232 false sp_text= 240 232 false sp_text_f= 252 232 false help_text= 252 232 false help_text_f= 255 236 true history_text= 252 232 false history_text_f= 255 236 true toc_text= 252 232 false toc_text_f= 255 236 true [layout] lmargin= 5 rmargin= 6 qman-1.5.1/doc/000077500000000000000000000000001510660157000132205ustar00rootroot00000000000000qman-1.5.1/doc/BUILDING.md000066400000000000000000000071331510660157000147430ustar00rootroot00000000000000# Building, Installing and Configuring Qman These generic instructions should work with most Linux distributions. For other operating systems, see [OS_SPECIFIC.md](OS_SPECIFIC.md). ## Downloading Clone the [main](https://github.com/plp13/qman/tree/main) branch, which contains Qman's latest stable version: ``` $ git clone -b main https://github.com/plp13/qman qman ``` [Tagged releases](https://github.com/plp13/qman/tags) with tarballs are also available, starting with version 1.2.1. ## Dependencies Qman was designed to be portable. Because of this, it was written in plain C and only has the following minimal dependencies: Runtime dependencies: - A Unix O/S that provides the standard `man`, `apropos` and `whatis` commands - `ncursesw` - For best results, use the [official version](https://invisible-island.net/ncurses/) by Thomas E. Dickey. Most Linux distributions provide this by default. - `groff` Build dependencies: - `gcc` or `clang` - `meson` - On some O/S you may need to manually install additional support packages for `meson`, such as `cmake`, `ninja` and `pkg-config` - `cogapp`, [a code generator written in Python](https://pypi.org/project/cogapp/) - If your O/S doesn't provide a package for `cogapp`, you can install it using `pip` or `pipx` Optional dependencies: - `libbsd`: required by Linux systems with older versions of `glibc` - `zlib`: support for manual pages compressed with `gzip` - `bzip2`: support for manual pages compressed with `bzip2` - `liblzma`: support for manual pages compressed with `xz` - `cunit`: used for unit testing ## Building and installing Make sure that all runtime and build dependencies are installed, and do the following: ``` $ meson setup build/ $ cd build/ $ meson compile $ sudo meson install ``` > **:bulb: Note** > > If using an older version of `meson`, you may need to substitute the > aforementioned `meson compile` command with `ninja` > **:bulb: Note** > > Qman uses certain BSD functions such as `wcslcpy()` and `wcslcat()` that, on > certain Linux systems, are provided by `libbsd` rather than by `libc`. This > causes compilation to fail due to undefined references to the functions. > > This problem can be solved by installing `libbsd` and adding > `-Dlibbsd=enabled` to `meson setup build/` > **:bulb: Note** > > If you opted not to install one or more optional dependencies, you must append > the [corresponding options](#meson-options) to `meson setup build/` Build instructions might differ for certain operating systems. See [OS_SPECIFIC.md](OS_SPECIFIC.md). ### Meson options The following optional arguments can be passed to `meson setup`: - `-Dman-pages=disabled`: do not install the manual page - `-Ddocs=disabled`: do not install any documentation - `-Dconfig=disabled`: do not install any configuration files - `-Dgzip=disabled`: disable support for manual pages compressed with `gzip` - `-Dbzip2=disabled`: disable support for manual pages compressed with `bzip2` - `-Dlzma=disabled`: disable support for manual pages compressed with `xz` - `-Dtests=enabled`: enable unit testing - `-Dconfigdir=...`: where to install configuration files - `-Ddocdir=...`: where to install documentation ## Configuration Qman should work without additional configuration on most Linux distributions. However, for some operating systems and Linux distros you may need to add extra directives to Qman's config file. See [OS_SPECIFIC.md](OS_SPECIFIC.md). The config file is located at `~/.config/qman/qman.conf` (user-specific) or `/etc/xdg/qman/qman.conf` (system-wide). All configuration directives are documented in Qman's manual page: ``` $ qman qman ``` qman-1.5.1/doc/CONTRIBUTING.md000066400000000000000000000004561510660157000154560ustar00rootroot00000000000000## Contributing All contributions are very welcome! Please use the [devel](https://github.com/plp13/qman/tree/devel) branch for contributing new code: ``` $ git clone -b devel https://github.com/plp13/qman qman ``` Also make sure you read [DEBUGGING.md](DEBUGGING.md) and [TESTING.md](TESTING.md). qman-1.5.1/doc/DEBUGGING.md000066400000000000000000000030511510660157000150340ustar00rootroot00000000000000# Debugging How to debug and profile Qman. ## Debugger Use `gdb` (standalone or integrated with your editor/IDE). To make sure the program gets fully rebuilt between debug sessions, use: ``` meson compile --clean && meson compile ``` ## Memory leaks Test for memory leaks using: ``` valgrind --leak-check=full --show-leak-kinds=all --show-reachable=no --track-origins=yes --log-file=valgrind.out ./qman ``` Then, examine `valgrind.out`. Reports of lost memory that has been allocated by `initscr()` and `doupdate_sp()` can safely be ignored. They are caused by `ncurses`, which has a [tendency](https://invisible-island.net/ncurses/ncurses.faq.html#config_leaks) not to fully deallocate its own memory. For more granularity, we may want to pass `--show-reachable=yes` to `valgrind`. This, however, will result in even more spurious errors caused by `ncurses`. ## Profiling Use the following command: ``` valgrind --tool=callgrind --dump-instr=yes --simulate-cache=yes --collect-jumps=yes ./qman ``` This will produce a file named `callgrind.out.` where `` is the process ID assigned to `valgrind` by the O/S. Use `kcachegrind` to open this file for further examination. ## Debug logging Developers can use function `loggit()` or macro `logprintf()`, both in [util.h](../src/util.h), to print messages to `./qman.log` during development. All calls to `loggit()` and `logprintf()` must be removed before committing to either [main](https://github.com/plp13/qman/tree/main) or [devel](https://github.com/plp13/qman/tree/devel). qman-1.5.1/doc/OS_SPECIFIC.md000066400000000000000000000073241510660157000153360ustar00rootroot00000000000000# O/S specific instructions Unless otherwise specified, instructions are for the latest version of the respective O/S. ## Linux The instructions in [BUILDING.md](BUILDING.md) should be sufficient for most Linux distributions. (Please pay attention to the note about `libbsd`.) ### Red Hat Enterprise Linux 8 / Rocky Linux 8 / AlmaLinux 8 The `mandb` system provided by these Linux distributions cannot parse arguments in the `(
)` format (e.g. `ls(1)`). This prevents Qman from performing certain actions, such as opening links to other man pages. To work around this problem, add the following to your [config file](BUILDING.md#configuration): ``` [misc] system_type=freebsd ``` ### Void Linux Void uses `mandoc`, therefore you must add the following to your [config file](BUILDING.md#configuration): ``` [misc] system_type=mandoc ``` ## macOS Install all [dependencies](BUILDING.md#dependencies) using `brew`. Then, run the following to build and install Qman: ``` $ meson setup build/ -Dpkg_config_path=/opt/homebrew/opt/ncurses/lib/pkgconfig $ cd build/ $ meson compile $ sudo meson install ``` > **:bulb: Note** > > On Intel-based macs, use: > > ``` > -Dpkg_config_path=/usr/local/opt/ncurses/lib/pkgconfig > ``` Then add the following to your [config file](BUILDING.md#configuration): ``` [misc] system_type=darwin groff_path=/usr/local/bin/groff ``` ### Improving performance Performance issues with the `whatis` and `apropos` commands in macOS can cause Qman to lag. One way to fix this is to create a set of scripts that emulate these commands for Qman: /usr/local/bin/mkfakewhatis.sh ``` #!/usr/bin/env bash DB=/usr/local/share/fakewhatis.txt apropos "." > "${DB}" exit $? ``` /usr/local/bin/fakewhatis.sh ``` #!/usr/bin/env bash DB=/usr/local/share/fakewhatis.txt if [ $# -eq 1 ] then grep -e " ${1}[ \t\(,-].*-.*" "${DB}" exit $? else exit -1 fi ``` /usr/local/bin/fakeapropos.sh ``` #!/usr/bin/env bash DB=/usr/local/share/fakewhatis.txt if [ $# -eq 1 ] then if [ "X${1}" -eq "X." ] then cat "${DB}" exit $? else grep "${1}" "${DB}" exit $? fi else exit -1 fi ``` Then, change the `[misc]` section of your config file as follows: ``` [misc] system_type=darwin groff_path=/usr/local/bin/groff apropos_path=/usr/local/bin/fakeapropos.sh whatis_path=/usr/local/bin/fakewhatis.sh ``` And, finally, run `mkfakewhatis.sh` as root: ``` # mkfakewhatis.sh ``` This command must be executed regularly, to ensure that `/usr/local/share/fakewhatis.txt` is kept up-to-date. Qman should now be lag-free! ## FreeBSD Install all [dependencies](BUILDING.md#dependencies) using `pkg`. Then use the [standard instructions](BUILDING.md#building-and-installing) to build and install Qman. FreeBSD-supplied `ncursesw` is known to cause compiler warnings, but otherwise works. You can also use the [Linux version](https://invisible-island.net/ncurses/) of `ncursesw`, which can be installed using `pkg install ncurses`. Finally, the following must be added to your [config file](BUILDING.md#configuration): ``` [misc] system_type=freebsd groff_path=/usr/local/bin/groff ``` ## Haiku Haiku doesn't provide optional dependency `cunit`. Install all other [dependencies](BUILDING.md#dependencies) using `pkgman`, and then build and install Qman using: ``` $ meson setup build/ -D $ cd build/ $ meson compile $ sudo meson install ``` Then, add the following to your [config file](BUILDING.md#configuration): ``` [misc] system_type=mandoc man_path=/bin/man whatis_path=/bin/whatis apropos_path=/bin/apropos groff_path=/bin/groff ``` An unidentified bug can cause Qman to crash on Haiku. If this happens, comment out the line that contains `free(wline)` in function `src/program.c:aprowhat_exec()` and re-compile. qman-1.5.1/doc/PACKAGES.md000066400000000000000000000015221510660157000147200ustar00rootroot00000000000000# Packages Known Qman packages: - Alpine Linux - [qman](https://pkgs.alpinelinux.org/package/edge/testing/armv7/qman): latest release - Arch Linux - [qman](https://aur.archlinux.org/packages/qman) (AUR): latest release - [qman-git](https://aur.archlinux.org/packages/qman-git) (AUR): [devel](https://github.com/plp13/qman/tree/devel) branch - Darwin / macOS - [qman](https://formulae.brew.sh/formula/qman) (Homebrew): latest release - FreeBSD ports - [misc/qman](https://github.com/freebsd/freebsd-ports/tree/main/misc/qman): latest release - Gentoo Linux - [app-misc/qman](https://gitweb.gentoo.org/repo/proj/guru.git/tree/app-misc/qman) (GURU): latest release Packagers for other operating systems are always welcome. If you've created a package, open an [issue](https://github.com/plp13/qman/issues) to add it to this list. qman-1.5.1/doc/TESTING.md000066400000000000000000000014661510660157000146660ustar00rootroot00000000000000# Testing How to test Qman before creating a new release. ## Preliminaries Thoroughly debug the program and make sure there are no memory leaks, using the methodology described in [DEBUGGING.md](DEBUGGING.md). ## Operating systems Test against the latest stable versions of these popular Linux distributions: - Arch Linux - Debian - Rocky Linux - Ubuntu (non-LTS) Also test against: - macOS - FreeBSD ## Terminal emulators Test against the following terminal emulators: - console - xterm - urxvt - gnome-terminal - konsole - terminator - guake - tilix - tilda - edex-ui - cool-retro-term - alacritty - kitty - st - ghostty ## Configuration files Test using the following configurations: - [provided configuration](../config) - empty configuration file - custom configuration file, depending on the test case qman-1.5.1/doc/TROUBLESHOOTING.md000066400000000000000000000073231510660157000160360ustar00rootroot00000000000000# Troubleshooting 1. Always make sure you are up-to-date with the [main](https://github.com/plp13/qman/tree/main) branch. 2. Read [BUILDING.md](BUILDING.md) and [OS_SPECIFIC.md](OS_SPECIFIC.md). 3. And, of course, [RTFM](../man/qman.1.md): ``` $ qman qman ``` --- > **:question: Calling `qman` without any parameters fails with message > `'apropos .' failed; did you run mandb/makewhatis?`** Most probably, your manual pages database hasn't been initialized. For most Linux users this can be fixed by running (as root): ``` # mandb ``` Users of other operating systems may need to run the following instead: ``` # makewhatis ``` On some operating systems, this error may also be caused by Qman not having been correctly configured. See [OS_SPECIFIC.md](OS_SPECIFIC.md). --- > **:question:: Some manual pages don't show up, or manual pages of software > that I have uninstalled still do show up** Again, this is probably a manual pages database issue. Qman uses your operating system's `apropos` command to discover manual pages. If the database is out of date, `apropos` (and therefore Qman) will produce inaccurate results. The database must be updated by running `mandb` or `makewhatis` every time manual pages are installed or uninstalled. Regrettably, some O/S fail to do this automatically. If that's the case, you have to be doing it manually or create your own automation. --- > **:question: I'm unable to copy text to the clipboard using the mouse, and/or > my mouse behaves erratically** Mouse support is experimental, and depends on features that are not fully implemented by all terminals. If you are having trouble with the mouse, you can disable mouse support by commenting out the following lines in your [config file](BUILDING.md#configuration): ``` ; [mouse] ; enable=true ``` --- > **:question: Links to HTTP URLs, e-mail addresses, or files/directories won't > open** By default, Qman uses standard commands such as `xdg-open` and `xdg-email` to open such links. On desktop Linux systems, this is sufficient to open them using the default GUI application. On other systems you may need to specify different handlers in your [config file](BUILDING.md#configuration). For example, the following directives will cause Qman to open HTTP links with `/usr/bin/links`, e-mail links with `/usr/bin/mutt`, and files/directories with `/usr/bin/vim`: ``` [misc] browser_path=/usr/bin/links mailer_path=/usr/bin/mutt viewer_path=/usr/bin/vim ``` You can also disable these kinds of links using the following: ``` [capabilities] http_links=false ; disable links to HTTP URLs email_links=false ; disable links to e-mail addresses file_links=false ; disable links to files or directories ``` --- > **:question: I don't like the way Qman looks** Use a different one of the supplied [themes](../config/themes). Or build your own theme (and open a pull request to to add it to the repository). For instructions on how to use themes, refer to Qman's manual page or look inside [config/qman.conf](../config/qman.conf) --- > **:question: I modified my config file to include a theme, but Qman's colors > still don't look right** All provided themes require a terminal that supports 256 colors. Some themes, such as `adwaita`, `adwaita-light` and `catpuccin_latte`, also require a terminal that can re-define colors from RGB values. Qman autodetects the terminal's capabilities, and will disable certain features if it detects a terminal that doesn't support them. This can be overridden using the options in the config file's `[tcap]` section, which are documented in the program's manual. Feel free to play with these, and also to [report an issue](https://github.com/plp13/qman/issues) if it looks like your terminal's capabilities are being misidentified. qman-1.5.1/doc/meson.build000066400000000000000000000005671510660157000153720ustar00rootroot00000000000000# Documentation build file # Documentation if get_option('docs').enabled() or get_option('docs').auto() install_data( [ 'BUILDING.md', 'CONTRIBUTING.md', 'DEBUGGING.md', 'OS_SPECIFIC.md', 'PACKAGES.md', 'TESTING.md', 'TROUBLESHOOTING.md' ], install_dir: get_option('docdir') + '/doc', install_tag: 'doc' ) endif qman-1.5.1/git-hooks/000077500000000000000000000000001510660157000143575ustar00rootroot00000000000000qman-1.5.1/git-hooks/README.md000066400000000000000000000004041510660157000156340ustar00rootroot00000000000000# Git hooks These scripts add the following functionality to `git`: - Call `bump.sh` upon commit, to set the program version ## Installation instructions ``` $ cp pre-commit post-commit ../.git/hooks $ cd ../.git/hooks $ chmod +x pre-commit post-commit ``` qman-1.5.1/git-hooks/post-commit000077500000000000000000000003131510660157000165550ustar00rootroot00000000000000#!/bin/bash # Add the files modified by pre-commit into HEAD if [ -e /tmp/qman-commit ] then rm /tmp/qman-commit git commit --amend -C HEAD --no-verify echo "Version changes committed" fi exit 0 qman-1.5.1/git-hooks/pre-commit000077500000000000000000000004321510660157000163600ustar00rootroot00000000000000#!/bin/bash # Call bump.sh to set program version VERSION=$(git describe --tags) VERSION=${VERSION#v} if [ "X${VERSION}" = "X" ] then VERSION="null" fi ./bump.sh ${VERSION} git add meson.build src/config_def.py README.md man/qman.1.md man/qman.1 touch /tmp/qman-commit exit 0 qman-1.5.1/man/000077500000000000000000000000001510660157000132265ustar00rootroot00000000000000qman-1.5.1/man/build_man.sh000077500000000000000000000007251510660157000155230ustar00rootroot00000000000000#!/usr/bin/env bash # Build the manual page from its Markdown source, using pandoc MD_FILE="qman.1.md" MAN_FILE="qman.1" exit_on_error() { if [ "X${1}" != "X0" ] then echo "Command failed" exit ${1} fi } cd "$( dirname "${BASH_SOURCE[0]}" )" exit_on_error $? echo "Removing old '${MAN_FILE}'" rm -f ${MAN_FILE} exit_on_error $? echo "Generating new '${MAN_FILE}' from '${MD_FILE}'" pandoc ${MD_FILE} -s -t man -o ${MAN_FILE} exit_on_error $? exit 0 qman-1.5.1/man/meson.build000066400000000000000000000002151510660157000153660ustar00rootroot00000000000000# Manual page build file # Manual page if get_option('man-pages').enabled() or get_option('man-pages').auto() install_man('qman.1') endif qman-1.5.1/man/qman.1000066400000000000000000000621611510660157000142520ustar00rootroot00000000000000'\" t .\" Automatically generated by Pandoc 3.4 .\" .TH "QMAN" "1" "December 15, 2023" "Qman 1.5.1" "General Commands Manual" .SH NAME \f[B]Qman\f[R] \- A more modern manual page viewer for our terminals .SH SYNOPSIS \f[B]qman\f[R] [\f[I]options\f[R]] .PD 0 .P .PD \f[B]qman\f[R] [\f[I]options\f[R]] \f[B]\-n\f[R] .PD 0 .P .PD \f[B]qman\f[R] [\f[I]options\f[R]] [[\f[I]section\f[R]] \f[I]page\f[R]] .PD 0 .P .PD \f[B]qman\f[R] [\f[I]options\f[R]] \f[B]\-k\f[R] \f[I]regexp\f[R] \&... .PD 0 .P .PD \f[B]qman\f[R] [\f[I]options\f[R]] \f[B]\-f\f[R] \f[I]page\f[R] \&... .SH DESCRIPTION \f[B]Qman\f[R] is a modern, interactive manual page viewer for our terminals. It strives to be easy to use for anyone familiar with the \f[B]man(1)\f[R] command, and also to be fast and tiny, so that it can be used everywhere. .SH EXAMPLES .TP \f[B]qman\f[R] or \f[B]qman \-n\f[R] Show the index (home) page, a collection of all manual pages available on the system .TP \f[B]qman ls\f[R] Show the manual page for \f[B]ls\f[R] .TP \f[B]qman 1 ls\f[R] or \f[B]qman `ls(1)'\f[R] Show the manual page for \f[B]ls\f[R] from manual section \f[B]1\f[R] .TP \f[B]qman \-f open\f[R] Show all manual pages named \f[B]open\f[R] across all sections (whatis) .TP \f[B]qman \-k open\f[R] Show all manual pages whose short description matches the term \f[B]open\f[R] (apropos) .SH USER INTERFACE \f[B]Qman\f[R]\[cq]s reactions to user input are similar to what one would expect from a pager such as \f[B]less(1)\f[R], or from an ncurses\-based browser such as \f[B]links(1)\f[R]. Manual, apropos, and whatis pages are adorned with links to other pages, HTTP locations, e\-mail addresses, files in the local filesystem, or (sub)sections within the current page. These links can be selected and opened. .PP The program provides a scrollbar, a status line, incremental search facilities for locating manual pages, and facilities for searching through the text of the page currently being displayed. A table of contents is generated for each page, allowing for easy navigation to its sections, sub\-sections, and paragraphs. Navigation history and on\-line help are also available. .PP The table below summarizes the program\[cq]s actions and their default associated keyboard mappings: .PP .TS tab(@); lw(15.7n) lw(35.9n) lw(18.4n). T{ Action name T}@T{ Description T}@T{ Key mappings T} _ T{ UP T}@T{ Scroll up one line and/or focus on the previous link T}@T{ \f[B]UP\f[R], \f[B]y\f[R], \f[B]k\f[R] T} T{ DOWN T}@T{ Scroll down one line and/or focus on the next link T}@T{ \f[B]DOWN\f[R], \f[B]e\f[R], \f[B]j\f[R] T} T{ LEFT T}@T{ Scroll left one tab stop T}@T{ \f[B]LEFT\f[R], \f[B]<\f[R] T} T{ RIGHT T}@T{ Scroll right one tab stop T}@T{ \f[B]RIGHT\f[R], \f[B]>\f[R] T} T{ PGUP T}@T{ Scroll up one page T}@T{ \f[B]PGUP\f[R], \f[B]b\f[R] T} T{ PGDN T}@T{ Scroll down one page T}@T{ \f[B]PGDN\f[R], \f[B]f\f[R] T} T{ HOME T}@T{ Go to page top T}@T{ \f[B]HOME\f[R], \f[B]g\f[R] T} T{ END T}@T{ Go to page bottom T}@T{ \f[B]END\f[R], \f[B]G\f[R] T} T{ OPEN T}@T{ Open focused link T}@T{ \f[B]ENTER\f[R], \f[B]o\f[R] T} T{ OPEN_APROPOS T}@T{ Perform apropos on focused link T}@T{ \f[B]a\f[R] T} T{ OPEN_WHATIS T}@T{ Perform whatis on focused link T}@T{ \f[B]w\f[R] T} T{ SP_OPEN T}@T{ Open a manual page using a dialog T}@T{ \f[B]O\f[R] T} T{ SP_APROPOS T}@T{ Perform apropos using a dialog T}@T{ \f[B]A\f[R] T} T{ SP_WHATIS T}@T{ Perform whatis using a dialog T}@T{ \f[B]W\f[R] T} T{ INDEX T}@T{ Go to index (home) page T}@T{ \f[B]i\f[R], \f[B]I\f[R] T} T{ BACK T}@T{ Go back one step in history T}@T{ \f[B]BACKSPACE\f[R], \f[B][\f[R] T} T{ FWRD T}@T{ Go forward one step in history T}@T{ \f[B]]\f[R] T} T{ HISTORY T}@T{ Show history menu T}@T{ \f[B]s\f[R], \f[B]S\f[R] T} T{ TOC T}@T{ Show table of contents T}@T{ \f[B]t\f[R], \f[B]T\f[R] T} T{ SEARCH T}@T{ Forward search in current page text T}@T{ \f[B]/\f[R] T} T{ SEARCH_BACK T}@T{ Backward search in current page text T}@T{ \f[B]?\f[R] T} T{ SEARCH_NEXT T}@T{ Go to next search result T}@T{ \f[B]n\f[R] T} T{ SEARCH_PREV T}@T{ Go to previous search result T}@T{ \f[B]N\f[R] T} T{ HELP T}@T{ Show the help dialog T}@T{ \f[B]h\f[R], \f[B]H\f[R] T} T{ QUIT T}@T{ Exit the program T}@T{ \f[B]q\f[R], \f[B]Q\f[R] T} .TE .PP All of the aforementioned keyboard mappings are customizable. For more information, see \f[B]CONFIGURATION\f[R]. .SH MOUSE SUPPORT Mouse input is supported but is considered experimental and is disabled by default. The \f[B]CONFIGURATION\f[R] section contains instructions on how to enable it. Many terminal emulators still provide basic mouse support when mouse input is disabled. .PP When mouse input is enabled: .IP \[bu] 2 The scroll wheel can be used as an alternative way for scrolling, invoking the UP and DOWN program actions .IP \[bu] 2 Pressing and dragging the left mouse button over page text causes it to be selected and copied to the clipboard (see \f[B]NOTES 1 & 2\f[R]) .IP \[bu] 2 Pressing and dragging the left mouse button over the scrollbar allows for scrolling through the page (see \f[B]NOTE 2\f[R]) .IP \[bu] 2 Clicking the left mouse button on a link causes the link under the cursor to be selected (see \f[B]NOTE 2\f[R]) .IP \[bu] 2 Clicking the middle button (the scroll wheel for most mice) invokes the OPEN action, opening the currently selected link .IP \[bu] 2 Clicking the right button invokes the HELP action .IP \[bu] 2 When inputting a search query or selecting from a menu, the middle button acts as a substitute for the ENTER key, and the right button as a substitute for CTRL\-C .IP \[bu] 2 When selecting from a menu, clicking the left button causes the menu entry under the cursor to be selected .PP The above behavior can be customized. For more information, see \f[B]CONFIGURATION\f[R]. .TP \f[B]NOTE 1\f[R] There is no reliable method for terminal clients to copy data to the clipboard. An escape code (OSC 52) does exist but is supported reliably only by \f[B]kitty(1)\f[R] and \f[B]ghostty(1)\f[R]. For all other terminals, \f[B]Qman\f[R] will default to using commands such as \f[B]xclip(1)\f[R], \f[B]wl\-clipboard(1)\f[R], or \f[B]pbcopy(1)\f[R]. However, these will only work when running locally and within a desktop environment (not when using SSH). .TP \f[B]NOTE 2\f[R] Some terminals may report mouse cursor position inaccurately, causing difficulties with clicking and dragging. .SH OPTIONS The program accepts the following non\-argument options: .TP \f[B]\-n, \-\-index\f[R] Show a list of all manual pages on the system, together with their sections and short descriptions. (This is the default behavior when the program is launched with no command\-line options and no arguments.) .TP \f[B]\-k, \-\-apropos\f[R] \f[I]regexp\f[R] \&... Interactive equivalent to \f[B]apropos(1)\f[R]. Search for manual pages whose names and/or short descriptions match any of the \f[I]regexp\f[R] arguments, and display their names, sections, and short descriptions. .TP \f[B]\-f, \-\-whatis\f[R] \f[I]page\f[R] \&... Interactive equivalent to \f[B]whatis(1)\f[R]. Display the name, section, and short description of each of the manual \f[I]page\f[R] argument. .TP \f[B]\-l, \-\-local\-file\f[R] \f[I]file\f[R] \&... Activate \[lq]local\[rq] mode. Format and display each local manual \f[I]file\f[R], rather than searching through the system\[cq]s manual pages. Each \f[I]file\f[R] is interpreted as the nroff source file of a manual page. .TP \f[B]\-K \-\-global\-apropos\f[R] \f[I]regexp\f[R] \&... Show the contents of all manual pages whose names and/or short descriptions match any of the \f[I]regexp\f[R] arguments. Beware that this option might cause long execution times. If not used in conjunction with \f[B]\-T\f[R], it is ignored. .TP \f[B]\-a \-\-all\f[R] \f[I]page\f[R] \&... Show the contents of all manual pages whose names match any of the \f[I]page\f[R] arguments. Beware that this option might cause long execution times. If not used in conjunction with \f[B]\-T\f[R], it is ignored. .TP \f[B]\-T, \-\-cli\f[R] Suppress the text user interface and output directly to the terminal. This option can be used to redirect the program\[cq]s formatted output to a text file or to another command. .TP \f[B]\-z, \-\-cli\-force\-color\f[R] Produce colorful output using terminal escape codes, even when not running inside a terminal. This must be used in conjunction with \f[B]\-T\f[R] and otherwise will be ignored. .TP \f[B]\-A, \-\-action\f[R] \f[I]action_name\f[R] Automatically perform program action \f[I]action_name\f[R] upon startup. The list of valid action names can be found under \f[B]USER INTERFACE\f[R]. .TP \f[B]\-C, \-\-config\-path\f[R] \f[I]file\f[R] Use \f[I]file\f[R] as the configuration file for \f[B]Qman\f[R]. .TP \f[B]\-v, \-\-version\f[R] Print program version and exit. .TP \f[B]\-h, \-\-help\f[R] Print a help message and exit. .SH CONFIGURATION \f[B]Qman\f[R] expects to find its configuration file in the standard locations defined by the \c .UR https://specifications.freedesktop.org/basedir-spec/latest/ XDG Base Directory Specification .UE \c \&. The following locations are searched in sequence: .IP \[bu] 2 Any file specified using \f[B]\-C\f[R] or \f[B]\-\-config\-path\f[R] .IP \[bu] 2 \f[I]${XDG_CONFIG_HOME}/qman/qman.conf\f[R] .IP \[bu] 2 \f[I]${HOME}/.config/qman/qman.conf\f[R] .IP \[bu] 2 \f[I]/qman/qman.conf\f[R] where \f[I]\f[R] is an entry in \f[I]${XDG_CONFIG_DIRS}\f[R] .IP \[bu] 2 \f[I]/qman.conf\f[R] where \f[I]\f[R] is a compile\-time option .IP \[bu] 2 \f[I]/etc/xdg/qman/qman.conf\f[R] .IP \[bu] 2 \f[I]/etc/qman/qman.conf\f[R] .PP The process stops once a configuration file has been found. .PP \f[B]Qman\f[R]\[cq]s configuration file uses the basic \c .UR https://en.wikipedia.org/wiki/INI_file INI file format .UE \c , extended with an \f[B]include\f[R] directive to allow for the configuration to be spread across multiple files. .PP Different configuration options are grouped into sections. The paragraphs below summarize the sections and configuration options that are available: .SS Section [chars] Options in this section specify what characters will be used to draw the text user interface: .PP .TS tab(@); lw(17.3n) lw(52.7n). T{ Option T}@T{ Description T} _ T{ sbar_top T}@T{ scrollbar top end T} T{ sbar_vline T}@T{ scrollbar track line T} T{ sbar_bottom T}@T{ scrollbar bottom end T} T{ sbar_block T}@T{ scrollbar knob T} T{ trans_mode_name T}@T{ transition between the mode and name sections of the status bar T} T{ trans_name_loc T}@T{ transition between the name and location sections of the status bar T} T{ trans_prompt_help T}@T{ transition between the prompt and help sections of the status bar T} T{ trans_prompt_em T}@T{ transition between the prompt and error message sections of the status bar T} T{ box_hline T}@T{ dialog box horizontal line T} T{ box_vline T}@T{ dialog box vertical line T} T{ box_tl T}@T{ dialog box top left corner T} T{ box_tr T}@T{ dialog box top right corner T} T{ box_bl T}@T{ dialog box bottom left corner T} T{ box_br T}@T{ dialog box bottom right corner T} T{ arrow_up T}@T{ up arrow T} T{ arrow_down T}@T{ down arrow T} T{ arrow_lr T}@T{ left/right arrow / equivalence sign T} .TE .PP Each configuration option value must consist of a single Unicode character. .PP The default values for this section have been chosen to allow \f[B]Qman\f[R] to work correctly with virtually all terminals, including the venerable \f[B]xterm(1)\f[R] and the Linux console, and with all fonts. Depending on the terminal\[cq]s capabilities, \f[B]Qman\f[R] may choose to revert to said defaults, and ignore any options you have specified in this section. This behavior can be overridden by adding \f[B]unicode=true\f[R] to the \f[B][tcap]\f[R] section. .SS Section [colours] Options in this section specify the user interface colors: .PP .TS tab(@); lw(17.3n) lw(52.7n). T{ Option T}@T{ Description T} _ T{ text T}@T{ page text T} T{ search T}@T{ matched search terms in page text T} T{ link_man T}@T{ links to manual pages T} T{ link_man_f T}@T{ links to manual pages (focused) T} T{ link_http T}@T{ HTTP links T} T{ link_http_f T}@T{ HTTP links (focused) T} T{ link_email T}@T{ e\-mail links T} T{ link_email_f T}@T{ e\-mail links (focused) T} T{ link_file T}@T{ links to files in the local filesystem T} T{ link_file_f T}@T{ links to files in the local filesystem (focused) T} T{ link_ls T}@T{ in\-page links T} T{ link_ls_f T}@T{ in\-page links (focused) T} T{ sb_line T}@T{ scrollbar track line T} T{ sb_block T}@T{ scrollbar knob T} T{ stat_indic_mode T}@T{ status bar mode section T} T{ stat_indic_name T}@T{ status bar name section T} T{ stat_indic_loc T}@T{ status bar location section T} T{ stat_input_prompt T}@T{ status bar input prompt T} T{ stat_input_help T}@T{ status bar help section T} T{ stat_input_em T}@T{ status bar error message section T} T{ imm_border T}@T{ pop\-up dialogs border T} T{ imm_title T}@T{ pop\-up dialogs title T} T{ sp_input T}@T{ input dialog prompt T} T{ sp_text T}@T{ input dialog incremental search text T} T{ sp_text_f T}@T{ input dialog incremental search text (focused) T} T{ help_text T}@T{ help dialog entries text T} T{ help_text_f T}@T{ help dialog entries text (focused) T} T{ history_text T}@T{ history dialog entries text T} T{ history_text_f T}@T{ history dialog entries text (focused) T} T{ toc_text T}@T{ table of contents dialog entries text T} T{ toc_text_f T}@T{ table of contents dialog entries text (focused) T} .TE .PP Each color is defined using three words separated by whitespace: .PP \f[I]foreground\f[R] \f[I]background\f[R] \f[I]bold\f[R] .PP \f[I]foreground\f[R] and \f[I]background\f[R] can be one of \f[B]black\f[R], \f[B]red\f[R], \f[B]green\f[R], \f[B]yellow\f[R], \f[B]blue\f[R], \f[B]magenta\f[R], \f[B]cyan\f[R], or \f[B]white\f[R]. Alternatively, they can be a number between 0 and 255, or a hexadecimal RGB value using the #RRGGBB notation. .PP \f[I]bold\f[R] is a boolean that signifies whether the foreground color will have a high (true) or low (false) intensity. .PP The default values for this section have been chosen to allow \f[B]Qman\f[R] to work correctly with virtually all terminals, including the venerable \f[B]xterm(1)\f[R] and the Linux console. Depending on the terminal\[cq]s capabilities, \f[B]Qman\f[R] may choose to revert to said defaults, and ignore any options you have specified in this section. This behavior can be overridden by adding \f[B]colors=256\f[R] and/or \f[B]rgb=true\f[R] to the \f[B][tcap]\f[R] section. .SS Section [keys] Options in this section specify which keys are mapped to each program action. .PP The section contains 25 configuration options, each corresponding to one of the program actions described in the \f[B]USER INTERFACE\f[R] section of this manual page. Their value is a tuple of up to 8 key definitions, separated by whitespace: .PP \f[I]key_1\f[R] \f[I]key_2\f[R] \f[I]key_3\f[R] \f[I]key_4\f[R] \f[I]key_5\f[R] \f[I]key_6\f[R] \f[I]key_7\f[R] \f[I]key_8\f[R] .PP The value of each \f[I]key_i\f[R] can take one of the following values: .IP \[bu] 2 Any character, surch as \f[B]a\f[R], \f[B]b\f[R], \f[B]c\f[R], etc. .IP \[bu] 2 Any ncurses(3x) keycode, such as \f[B]KEY_UP\f[R] or \f[B]KEY_HOME\f[R] .IP \[bu] 2 \f[B]F1\f[R] to \f[B]F12\f[R] (for the function keys) .IP \[bu] 2 \f[B]ESC\f[R] (for the ESC key) .IP \[bu] 2 \f[B]EXT\f[R] (for CTRL\-C) .IP \[bu] 2 \f[B]LF\f[R] (for the ENTER key) .IP \[bu] 2 \f[B]BS\f[R] (for the BACKSPACE key) .IP \[bu] 2 \f[B]HT\f[R] (for the TAB key) .IP \[bu] 2 \f[B]SPACE\f[R] (for the spacebar) .PP For reasons of compatibility with various terminals, mapping the ENTER key requires specifying both \f[B]KEY_ENTER\f[R] and \f[B]LF\f[R]. Similarly, mapping CTRL\-C requires specifying both \f[B]KEY_BREAK\f[R] and \f[B]ETX\f[R], and mapping BACKSPACE requires specifying both \f[B]KEY_BACKSPACE\f[R] and \f[B]BS\f[R]. .SS Section [mouse] This section contains the following options that pertain to mouse support: .PP .TS tab(@); lw(9.3n) lw(13.1n) lw(11.2n) lw(36.4n). T{ Option T}@T{ Type T}@T{ Def. value T}@T{ Description T} _ T{ enable T}@T{ boolean T}@T{ false T}@T{ Enables mouse support T} T{ left_handed T}@T{ boolean T}@T{ false T}@T{ Swaps the left and right mouse buttons T} T{ left_click_open T}@T{ boolean T}@T{ false T}@T{ Causes the left mouse button to invoke the OPEN action and/or act as the ENTER key T} .TE .SS Section [layout] This section contains various options that concern the layout of the text user interface: .PP .TS tab(@); lw(9.3n) lw(13.1n) lw(11.2n) lw(36.4n). T{ Option T}@T{ Type T}@T{ Def. value T}@T{ Description T} _ T{ sbar T}@T{ boolean T}@T{ true T}@T{ Indicates whether the scrollbar will be displayed T} T{ beep T}@T{ boolean T}@T{ true T}@T{ Indicates whether to beep the terminal on error T} T{ lmargin T}@T{ unsigned int T}@T{ 2 T}@T{ Size of margin between the left side of the screen, and the page text T} T{ rmargin T}@T{ unsigned int T}@T{ 2 T}@T{ Size of margin between the page text and the scroll bar and/or the right side of the screen T} T{ tabstop T}@T{ unsigned int T}@T{ 8 T}@T{ Number of characters in a tab stop (used by actions LEFT and RIGHT) T} .TE .SS Section [tcap] Normally, \f[B]Qman\f[R] detects the terminal\[cq]s capabilities automatically. Options in this section provide the ability to specify them explicitly, overriding this behavior: .PP .TS tab(@); lw(9.3n) lw(13.1n) lw(11.2n) lw(36.4n). T{ Option T}@T{ Type T}@T{ Def. value T}@T{ Description T} _ T{ colours T}@T{ int T}@T{ \-1 T}@T{ Number of colors supported by the terminal, or \-1 to auto\-detect T} T{ rgb T}@T{ ternary T}@T{ auto T}@T{ True if terminal can re\-define colors, false if not, auto to auto\-detect T} T{ unicode T}@T{ ternary T}@T{ auto T}@T{ True if terminal supports Unicode, false if not, auto to auto\-detect T} T{ clipboard T}@T{ ternary T}@T{ auto T}@T{ True if terminal supports clipboard operations (OSC 52), false if not, auto to auto\-detect T} T{ escdelay T}@T{ int T}@T{ 60 T}@T{ Number of miliseconds to wait after receving ESC from the keyboard before interpreting it as the escape key. Users with historical terminals or very unreliable network connections may want to increase this. T} .TE .PP Beware that \f[B]Qman\f[R] uses these capabilities to decide whether to either honor or ignore various configuration options specified elsewhere, particularly in the \f[B][chars]\f[R] and \f[B][colours]\f[R] sections mentioned above. Auto\-detection should work correctly in most cases; it\[cq]s therefore recommended to not modify any of the options in this section, except when discovering or reporting bugs. .SS Section [capabilities] This section allows the user to disable various non\-essential features of Qman: .PP .TS tab(@); lw(13.1n) lw(13.1n) lw(11.2n) lw(32.7n). T{ Option T}@T{ Type T}@T{ Def. value T}@T{ Description T} _ T{ sections_on_top T}@T{ boolean T}@T{ true T}@T{ Show a list of (links to the page\[cq]s) sections at the top of each page T} T{ http_links T}@T{ boolean T}@T{ true T}@T{ Generate hyperlinks to HTTP URLs T} T{ email_links T}@T{ boolean T}@T{ true T}@T{ Generate hyperlinks to email addresses T} T{ file_links T}@T{ boolean T}@T{ true T}@T{ Generate hyperlinks to local files and directories T} T{ hyphenate T}@T{ boolean T}@T{ true T}@T{ Hyphenate long words in manual pages T} T{ justify T}@T{ boolean T}@T{ true T}@T{ Justify text in manual pages T} T{ icase_search T}@T{ boolean T}@T{ true T}@T{ Ignore case when performing page text search T} T{ sp_substrings T}@T{ boolean T}@T{ true T}@T{ Include substring matches when performing incremental search of manual pages T} .TE .PP All features are enabled by default. .PP On slow machines, performance can be improved by disabling some features. Also, disabling \f[I]hyphenate\f[R] and/or \f[I]justify\f[R] can improve legibility in narrow terminal windows. .SS Section [misc] This section contains various miscellaneous options: .PP .TS tab(@); lw(13.1n) lw(13.1n) lw(11.2n) lw(32.7n). T{ Option T}@T{ Type T}@T{ Def. value T}@T{ Description T} _ T{ system_type T}@T{ string T}@T{ mandb T}@T{ Manual system type T} T{ man_path T}@T{ string T}@T{ /usr/bin/man T}@T{ Path to the \f[B]man(1)\f[R] command T} T{ groff_path T}@T{ string T}@T{ /usr/bin/groff T}@T{ Path to the \f[B]groff(1)\f[R] command T} T{ whatis_path T}@T{ string T}@T{ /usr/bin/whatis T}@T{ Path to the \f[B]whatis(1)\f[R] command T} T{ apropos_path T}@T{ string T}@T{ /usr/bin/apropos T}@T{ Path to the \f[B]apropos(1)\f[R] command T} T{ browser_path T}@T{ string T}@T{ /usr/bin/xdg\-open T}@T{ Path to the command that will be used to open HTTP links (i.e.\ your web browser) T} T{ mailer_path T}@T{ string T}@T{ /usr/bin/xdg\-email T}@T{ Path to the command that will be used to open e\-mail links (i.e.\ your e\-mail software) T} T{ viewer_path T}@T{ string T}@T{ /usr/bin/xdg\-open T}@T{ Path to the command that will be used to open links to files in the local filesystem T} T{ reset_after_http T}@T{ boolean T}@T{ true T}@T{ Re\-initialize curses after opening an http(s) link T} T{ reset_after_email T}@T{ boolean T}@T{ true T}@T{ Re\-initialize curses after opening an e\-mail link T} T{ reset_after_viewer T}@T{ boolean T}@T{ true T}@T{ Re\-initialize curses after opening a link to a local filesystem file T} T{ terminfo_reset T}@T{ boolean T}@T{ false T}@T{ Reset the terminal using the strings provided by \f[B]terminfo(5)\f[R] on shutdown T} T{ history_size T}@T{ unsigned int T}@T{ 256k T}@T{ Maximum number of history entries T} .TE .PP \f[I]system_type\f[R] must match the Unix manual system used by your O/S: .IP \[bu] 2 \f[B]\c .UR https://gitlab.com/man-db/man-db mandb .UE \c \f[R] \- most Linux distributions .IP \[bu] 2 \f[B]\c .UR https://mandoc.bsd.lv/ mandoc .UE \c \f[R] \- Void Linux, Haiku, others? .IP \[bu] 2 \f[B]\c .UR https://www.freebsd.org/ freebsd .UE \c \f[R] \- FreeBSD .IP \[bu] 2 \f[B]\c .UR https://www.apple.com/macos/ darwin .UE \c \f[R] \- macOS .PP To avoid an annoying screen redraw, options \f[I]reset_after_http\f[R], \f[I]reset_after_email\f[R], or \f[I]reset_after_viewer\f[R] can be set to \f[B]false\f[R] whenever \f[I]browser_path\f[R], \f[I]mailer_path\f[R], or \f[I]viewer_path\f[R] point to a GUI program respectively. .PP Setting \f[I]terminfo_reset\f[R] to \f[B]true\f[R] will initiate a full terminal reset, using the strings provided by \f[B]terminfo(5)\f[R], upon program shutdown. This may be necessary if your ncurses implementation doesn\[cq]t completely restore terminal settings (e.g.\ colors) upon exit, but will also clear the screen and erase your scroll history as a side effect. .PP When using a horizontally narrow terminal, setting \f[I]hyphenate\f[R] to \f[B]true\f[R] and/or \f[I]justify\f[R] to \f[B]false\f[R] can improve the program\[cq]s output. .PP Setting \f[I]sp_substrings\f[R] to \f[B]false\f[R] causes incremental search results to only include pages whose names start with the user\[cq]s input. Setting it to \f[B]true\f[R] (the default) will also include pages whose names contain the input as a substring, provided there is enough space left in the window. .SS Include directive Supplemental configuration files can be included using: .PP \f[B]include\f[R] \f[I]path\f[R] .PP Where \f[I]path\f[R] is either an absolute path to the supplemental, or a path relative to the directory component of the configuration file that performs the inclusion. .SS Notes on syntax Include paths and option values may optionally be placed inside single or double quotes. They can also include the following escape sequences: .IP \[bu] 2 \f[B]\[rs]a\f[R], \f[B]\[rs]b\f[R], \f[B]\[rs]t\f[R], \f[B]\[rs]n\f[R], \f[B]\[rs]v\f[R], \f[B]\[rs]f\f[R], and \f[B]\[rs]r\f[R] \[en] interpreted according to the ASCII standard .IP \[bu] 2 \f[B]\[rs]e\f[R] \[en] interpreted as an escape (0x1b) character .IP \[bu] 2 \f[B]\[rs]\[rs]\f[R] \[en] interpreted as a backslash .IP \[bu] 2 \f[B]\[rs]\[cq]\f[R] and \f[B]\[rs]\[lq]\f[R] \[en] interpreted as a single and a double quote respectively .PP All text following a \f[B];\f[R] until the end of the line is considered a comment and is discarded. .SH ENVIRONMENT Users should take care setting their \f[B]TERM\f[R] environment variable to match their virtual terminal. .PP When invoked using \f[B]\-T\f[R], the program tries to set its page width to the value of the \f[B]MANWIDTH\f[R] environment variable. If \f[B]MANWIDTH\f[R] hasn\[cq]t been set, it tries to set it to the value of \f[B]COLUMNS\f[R]. Failing that, it tries to auto\-detect the terminal\[cq]s size using an \f[B]ioctl(2)\f[R] and, if that also fails, it sets it to the default value of 80. .SH SIGNALS Upon receiving \f[B]SIGUSR1\f[R], the program interrupts its operation and attempts to re\-parse its configuration file, using the process outlined in \f[B]CONFIGURATION\f[R]. .PP This feature can be useful for people who wish to automatically switch themes depending on the time of day. It should be noted that it is experimental and has issues with certain terminals. .SH EXIT STATUS .PP .TS tab(@); lw(6.4n) lw(63.6n). T{ Value T}@T{ Description T} _ T{ 0 T}@T{ Successful program execution T} T{ 1 T}@T{ Usage or syntax error T} T{ 2 T}@T{ Operational error T} T{ 3 T}@T{ A child process returned a non\-zero exit status T} T{ 4 T}@T{ Configuration file error T} T{ 16 T}@T{ No manual page(s) found matching the user\[cq]s request T} .TE .PP The above are similar to the exit values of \f[B]man(1)\f[R]. .SH SEE ALSO \f[B]man(1)\f[R], \f[B]apropos(1)\f[R], \f[B]whatis(1)\f[R], \f[B]pinfo(1)\f[R] .SH AUTHOR Written by Pantelis Panayiotou / plp13 on GitHub .SH BUGS Please report bugs at https://github.com/plp13/qman/issues qman-1.5.1/man/qman.1.md000066400000000000000000000623541510660157000146550ustar00rootroot00000000000000--- title: QMAN section: 1 header: General Commands Manual footer: Qman 1.5.1 date: December 15, 2023 --- # NAME **Qman** - A more modern manual page viewer for our terminals # SYNOPSIS **qman** [_options_] **qman** [_options_] **-n** **qman** [_options_] [[_section_] _page_] **qman** [_options_] **-k** _regexp_ ... **qman** [_options_] **-f** _page_ ... # DESCRIPTION **Qman** is a modern, interactive manual page viewer for our terminals. It strives to be easy to use for anyone familiar with the **man(1)** command, and also to be fast and tiny, so that it can be used everywhere. # EXAMPLES **qman** or **qman -n** : Show the index (home) page, a collection of all manual pages available on the system **qman ls** : Show the manual page for **ls** **qman 1 ls** or **qman 'ls(1)'** : Show the manual page for **ls** from manual section **1** **qman -f open** : Show all manual pages named **open** across all sections (whatis) **qman -k open** : Show all manual pages whose short description matches the term **open** (apropos) # USER INTERFACE **Qman**'s reactions to user input are similar to what one would expect from a pager such as **less(1)**, or from an ncurses-based browser such as **links(1)**. Manual, apropos, and whatis pages are adorned with links to other pages, HTTP locations, e-mail addresses, files in the local filesystem, or (sub)sections within the current page. These links can be selected and opened. The program provides a scrollbar, a status line, incremental search facilities for locating manual pages, and facilities for searching through the text of the page currently being displayed. A table of contents is generated for each page, allowing for easy navigation to its sections, sub-sections, and paragraphs. Navigation history and on-line help are also available. The table below summarizes the program's actions and their default associated keyboard mappings: | Action name | Description | Key mappings | |-----------------|---------------------------------------|--------------------| | UP | Scroll up one line and/or focus on the previous link | **UP**, **y**, **k** | | DOWN | Scroll down one line and/or focus on the next link | **DOWN**, **e**, **j** | | LEFT | Scroll left one tab stop | **LEFT**, **<** | | RIGHT | Scroll right one tab stop | **RIGHT**, **>** | | PGUP | Scroll up one page | **PGUP**, **b** | | PGDN | Scroll down one page | **PGDN**, **f** | | HOME | Go to page top | **HOME**, **g** | | END | Go to page bottom | **END**, **G** | | OPEN | Open focused link | **ENTER**, **o** | | OPEN_APROPOS | Perform apropos on focused link | **a** | | OPEN_WHATIS | Perform whatis on focused link | **w** | | SP_OPEN | Open a manual page using a dialog | **O** | | SP_APROPOS | Perform apropos using a dialog | **A** | | SP_WHATIS | Perform whatis using a dialog | **W** | | INDEX | Go to index (home) page | **i**, **I** | | BACK | Go back one step in history | **BACKSPACE**, **[** | | FWRD | Go forward one step in history | **]** | | HISTORY | Show history menu | **s**, **S** | | TOC | Show table of contents | **t**, **T** | | SEARCH | Forward search in current page text | **/** | | SEARCH_BACK | Backward search in current page text | **?** | | SEARCH_NEXT | Go to next search result | **n** | | SEARCH_PREV | Go to previous search result | **N** | | HELP | Show the help dialog | **h**, **H** | | QUIT | Exit the program | **q**, **Q** | All of the aforementioned keyboard mappings are customizable. For more information, see **CONFIGURATION**. # MOUSE SUPPORT Mouse input is supported but is considered experimental and is disabled by default. The **CONFIGURATION** section contains instructions on how to enable it. Many terminal emulators still provide basic mouse support when mouse input is disabled. When mouse input is enabled: - The scroll wheel can be used as an alternative way for scrolling, invoking the UP and DOWN program actions - Pressing and dragging the left mouse button over page text causes it to be selected and copied to the clipboard (see **NOTES 1 & 2**) - Pressing and dragging the left mouse button over the scrollbar allows for scrolling through the page (see **NOTE 2**) - Clicking the left mouse button on a link causes the link under the cursor to be selected (see **NOTE 2**) - Clicking the middle button (the scroll wheel for most mice) invokes the OPEN action, opening the currently selected link - Clicking the right button invokes the HELP action - When inputting a search query or selecting from a menu, the middle button acts as a substitute for the ENTER key, and the right button as a substitute for CTRL-C - When selecting from a menu, clicking the left button causes the menu entry under the cursor to be selected The above behavior can be customized. For more information, see **CONFIGURATION**. **NOTE 1** : There is no reliable method for terminal clients to copy data to the clipboard. An escape code (OSC 52) does exist but is supported reliably only by **kitty(1)** and **ghostty(1)**. For all other terminals, **Qman** will default to using commands such as **xclip(1)**, **wl-clipboard(1)**, or **pbcopy(1)**. However, these will only work when running locally and within a desktop environment (not when using SSH). **NOTE 2** : Some terminals may report mouse cursor position inaccurately, causing difficulties with clicking and dragging. # OPTIONS The program accepts the following non-argument options: **-n, \-\-index** : Show a list of all manual pages on the system, together with their sections and short descriptions. (This is the default behavior when the program is launched with no command-line options and no arguments.) **-k, \-\-apropos** _regexp_ ... : Interactive equivalent to **apropos(1)**. Search for manual pages whose names and/or short descriptions match any of the _regexp_ arguments, and display their names, sections, and short descriptions. **-f, \-\-whatis** _page_ ... : Interactive equivalent to **whatis(1)**. Display the name, section, and short description of each of the manual _page_ argument. **-l, \-\-local\-file** _file_ ... : Activate "local" mode. Format and display each local manual _file_, rather than searching through the system's manual pages. Each _file_ is interpreted as the nroff source file of a manual page. **-K \-\-global\-apropos** _regexp_ ... : Show the contents of all manual pages whose names and/or short descriptions match any of the _regexp_ arguments. Beware that this option might cause long execution times. If not used in conjunction with **-T**, it is ignored. **-a \-\-all** _page_ ... : Show the contents of all manual pages whose names match any of the _page_ arguments. Beware that this option might cause long execution times. If not used in conjunction with **-T**, it is ignored. **-T, \-\-cli** : Suppress the text user interface and output directly to the terminal. This option can be used to redirect the program's formatted output to a text file or to another command. **-z, \-\-cli\-force\-color** : Produce colorful output using terminal escape codes, even when not running inside a terminal. This must be used in conjunction with **-T** and otherwise will be ignored. **-A, \-\-action** _action_name_ : Automatically perform program action _action_name_ upon startup. The list of valid action names can be found under **USER INTERFACE**. **-C, \-\-config\-path** _file_ : Use _file_ as the configuration file for **Qman**. **-v, \-\-version** : Print program version and exit. **-h, \-\-help** : Print a help message and exit. # CONFIGURATION **Qman** expects to find its configuration file in the standard locations defined by the [XDG Base Directory Specification](https://specifications.freedesktop.org/basedir-spec/latest/). The following locations are searched in sequence: - Any file specified using **-C** or **\-\-config\-path** - _\${XDG_CONFIG_HOME}/qman/qman.conf_ - _\${HOME}/.config/qman/qman.conf_ - _\/qman/qman.conf_ where _\_ is an entry in _\${XDG_CONFIG_DIRS}_ - _\/qman.conf_ where _\_ is a compile-time option - _/etc/xdg/qman/qman.conf_ - _/etc/qman/qman.conf_ The process stops once a configuration file has been found. **Qman**'s configuration file uses the basic [INI file format](https://en.wikipedia.org/wiki/INI_file), extended with an **include** directive to allow for the configuration to be spread across multiple files. Different configuration options are grouped into sections. The paragraphs below summarize the sections and configuration options that are available: ## Section [chars] Options in this section specify what characters will be used to draw the text user interface: | Option | Description | |-------------------|----------------------------------------------------------| | sbar_top | scrollbar top end | | sbar_vline | scrollbar track line | | sbar_bottom | scrollbar bottom end | | sbar_block | scrollbar knob | | trans_mode_name | transition between the mode and name sections of the status bar | | trans_name_loc | transition between the name and location sections of the status bar | | trans_prompt_help | transition between the prompt and help sections of the status bar | | trans_prompt_em | transition between the prompt and error message sections of the status bar| | box_hline | dialog box horizontal line | | box_vline | dialog box vertical line | | box_tl | dialog box top left corner | | box_tr | dialog box top right corner | | box_bl | dialog box bottom left corner | | box_br | dialog box bottom right corner | | arrow_up | up arrow | | arrow_down | down arrow | | arrow_lr | left/right arrow / equivalence sign | Each configuration option value must consist of a single Unicode character. The default values for this section have been chosen to allow **Qman** to work correctly with virtually all terminals, including the venerable **xterm(1)** and the Linux console, and with all fonts. Depending on the terminal's capabilities, **Qman** may choose to revert to said defaults, and ignore any options you have specified in this section. This behavior can be overridden by adding **unicode=true** to the **[tcap]** section. ## Section [colours] Options in this section specify the user interface colors: | Option | Description | |-------------------|----------------------------------------------------------| | text | page text | | search | matched search terms in page text | | link_man | links to manual pages | | link_man_f | links to manual pages (focused) | | link_http | HTTP links | | link_http_f | HTTP links (focused) | | link_email | e-mail links | | link_email_f | e-mail links (focused) | | link_file | links to files in the local filesystem | | link_file_f | links to files in the local filesystem (focused) | | link_ls | in-page links | | link_ls_f | in-page links (focused) | | sb_line | scrollbar track line | | sb_block | scrollbar knob | | stat_indic_mode | status bar mode section | | stat_indic_name | status bar name section | | stat_indic_loc | status bar location section | | stat_input_prompt | status bar input prompt | | stat_input_help | status bar help section | | stat_input_em | status bar error message section | | imm_border | pop-up dialogs border | | imm_title | pop-up dialogs title | | sp_input | input dialog prompt | | sp_text | input dialog incremental search text | | sp_text_f | input dialog incremental search text (focused) | | help_text | help dialog entries text | | help_text_f | help dialog entries text (focused) | | history_text | history dialog entries text | | history_text_f | history dialog entries text (focused) | | toc_text | table of contents dialog entries text | | toc_text_f | table of contents dialog entries text (focused) | Each color is defined using three words separated by whitespace: _foreground_ _background_ _bold_ _foreground_ and _background_ can be one of **black**, **red**, **green**, **yellow**, **blue**, **magenta**, **cyan**, or **white**. Alternatively, they can be a number between 0 and 255, or a hexadecimal RGB value using the #RRGGBB notation. _bold_ is a boolean that signifies whether the foreground color will have a high (true) or low (false) intensity. The default values for this section have been chosen to allow **Qman** to work correctly with virtually all terminals, including the venerable **xterm(1)** and the Linux console. Depending on the terminal's capabilities, **Qman** may choose to revert to said defaults, and ignore any options you have specified in this section. This behavior can be overridden by adding **colors=256** and/or **rgb=true** to the **[tcap]** section. ## Section [keys] Options in this section specify which keys are mapped to each program action. The section contains 25 configuration options, each corresponding to one of the program actions described in the **USER INTERFACE** section of this manual page. Their value is a tuple of up to 8 key definitions, separated by whitespace: _key_1_ _key_2_ _key_3_ _key_4_ _key_5_ _key_6_ _key_7_ _key_8_ The value of each _key_i_ can take one of the following values: - Any character, surch as **a**, **b**, **c**, etc. - Any ncurses(3x) keycode, such as **KEY_UP** or **KEY_HOME** - **F1** to **F12** (for the function keys) - **ESC** (for the ESC key) - **EXT** (for CTRL-C) - **LF** (for the ENTER key) - **BS** (for the BACKSPACE key) - **HT** (for the TAB key) - **SPACE** (for the spacebar) For reasons of compatibility with various terminals, mapping the ENTER key requires specifying both **KEY_ENTER** and **LF**. Similarly, mapping CTRL-C requires specifying both **KEY_BREAK** and **ETX**, and mapping BACKSPACE requires specifying both **KEY_BACKSPACE** and **BS**. ## Section [mouse] This section contains the following options that pertain to mouse support: | Option | Type | Def. value | Description | |----------|--------------|------------|---------------------------------------| | enable | boolean | false | Enables mouse support | | left_handed | boolean | false | Swaps the left and right mouse buttons | | left_click_open | boolean | false | Causes the left mouse button to invoke the OPEN action and/or act as the ENTER key | ## Section [layout] This section contains various options that concern the layout of the text user interface: | Option | Type | Def. value | Description | |----------|--------------|------------|---------------------------------------| | sbar | boolean | true | Indicates whether the scrollbar will be displayed | | beep | boolean | true | Indicates whether to beep the terminal on error | | lmargin | unsigned int | 2 | Size of margin between the left side of the screen, and the page text | | rmargin | unsigned int | 2 | Size of margin between the page text and the scroll bar and/or the right side of the screen | | tabstop | unsigned int | 8 | Number of characters in a tab stop (used by actions LEFT and RIGHT) | ## Section [tcap] Normally, **Qman** detects the terminal's capabilities automatically. Options in this section provide the ability to specify them explicitly, overriding this behavior: | Option | Type | Def. value | Description | |----------|--------------|------------|---------------------------------------| | colours | int | -1 | Number of colors supported by the terminal, or -1 to auto-detect | | rgb | ternary | auto | True if terminal can re-define colors, false if not, auto to auto-detect | | unicode | ternary | auto | True if terminal supports Unicode, false if not, auto to auto-detect | | clipboard| ternary | auto | True if terminal supports clipboard operations (OSC 52), false if not, auto to auto-detect | | escdelay | int | 60 | Number of miliseconds to wait after receving ESC from the keyboard before interpreting it as the escape key. Users with historical terminals or very unreliable network connections may want to increase this. | Beware that **Qman** uses these capabilities to decide whether to either honor or ignore various configuration options specified elsewhere, particularly in the **[chars]** and **[colours]** sections mentioned above. Auto-detection should work correctly in most cases; it's therefore recommended to not modify any of the options in this section, except when discovering or reporting bugs. ## Section [capabilities] This section allows the user to disable various non-essential features of Qman: | Option | Type | Def. value | Description | |--------------|--------------|------------|-----------------------------------| | sections_on_top | boolean | true | Show a list of (links to the page's) sections at the top of each page | | http_links | boolean | true | Generate hyperlinks to HTTP URLs | | email_links | boolean | true | Generate hyperlinks to email addresses | | file_links | boolean | true | Generate hyperlinks to local files and directories | | hyphenate | boolean | true | Hyphenate long words in manual pages | | justify | boolean | true | Justify text in manual pages | | icase_search | boolean | true | Ignore case when performing page text search | | sp_substrings | boolean | true | Include substring matches when performing incremental search of manual pages | All features are enabled by default. On slow machines, performance can be improved by disabling some features. Also, disabling _hyphenate_ and/or _justify_ can improve legibility in narrow terminal windows. ## Section [misc] This section contains various miscellaneous options: | Option | Type | Def. value | Description | |--------------|--------------|------------|-----------------------------------| | system_type | string | mandb | Manual system type | | man_path | string | /usr/bin/man | Path to the **man(1)** command | | groff_path | string | /usr/bin/groff | Path to the **groff(1)** command | | whatis_path | string | /usr/bin/whatis | Path to the **whatis(1)** command | | apropos_path | string | /usr/bin/apropos | Path to the **apropos(1)** command | | browser_path | string | /usr/bin/xdg-open | Path to the command that will be used to open HTTP links (i.e. your web browser) | | mailer_path | string | /usr/bin/xdg-email | Path to the command that will be used to open e-mail links (i.e. your e-mail software) | | viewer_path | string | /usr/bin/xdg-open | Path to the command that will be used to open links to files in the local filesystem | | reset_after_http | boolean | true | Re-initialize curses after opening an http(s) link | | reset_after_email| boolean | true | Re-initialize curses after opening an e-mail link | | reset_after_viewer | boolean | true | Re-initialize curses after opening a link to a local filesystem file | | terminfo_reset | boolean | false | Reset the terminal using the strings provided by **terminfo(5)** on shutdown | | history_size | unsigned int | 256k | Maximum number of history entries | _system_type_ must match the Unix manual system used by your O/S: - **[mandb](https://gitlab.com/man-db/man-db)** - most Linux distributions - **[mandoc](https://mandoc.bsd.lv/)** - Void Linux, Haiku, others? - **[freebsd](https://www.freebsd.org/)** - FreeBSD - **[darwin](https://www.apple.com/macos/)** - macOS To avoid an annoying screen redraw, options _reset_after_http_, _reset_after_email_, or _reset_after_viewer_ can be set to **false** whenever _browser_path_, _mailer_path_, or _viewer_path_ point to a GUI program respectively. Setting _terminfo_reset_ to **true** will initiate a full terminal reset, using the strings provided by **terminfo(5)**, upon program shutdown. This may be necessary if your ncurses implementation doesn't completely restore terminal settings (e.g. colors) upon exit, but will also clear the screen and erase your scroll history as a side effect. When using a horizontally narrow terminal, setting _hyphenate_ to **true** and/or _justify_ to **false** can improve the program's output. Setting _sp_substrings_ to **false** causes incremental search results to only include pages whose names start with the user's input. Setting it to **true** (the default) will also include pages whose names contain the input as a substring, provided there is enough space left in the window. ## Include directive Supplemental configuration files can be included using: **include** _path_ Where _path_ is either an absolute path to the supplemental, or a path relative to the directory component of the configuration file that performs the inclusion. ## Notes on syntax Include paths and option values may optionally be placed inside single or double quotes. They can also include the following escape sequences: - **\\a**, **\\b**, **\\t**, **\\n**, **\\v**, **\\f**, and **\\r** -- interpreted according to the ASCII standard - **\\e** -- interpreted as an escape (0x1b) character - **\\\\** -- interpreted as a backslash - **\\'** and **\\"** -- interpreted as a single and a double quote respectively All text following a **;** until the end of the line is considered a comment and is discarded. # ENVIRONMENT Users should take care setting their **TERM** environment variable to match their virtual terminal. When invoked using **-T**, the program tries to set its page width to the value of the **MANWIDTH** environment variable. If **MANWIDTH** hasn't been set, it tries to set it to the value of **COLUMNS**. Failing that, it tries to auto-detect the terminal's size using an **ioctl(2)** and, if that also fails, it sets it to the default value of 80. # SIGNALS Upon receiving **SIGUSR1**, the program interrupts its operation and attempts to re-parse its configuration file, using the process outlined in **CONFIGURATION**. This feature can be useful for people who wish to automatically switch themes depending on the time of day. It should be noted that it is experimental and has issues with certain terminals. # EXIT STATUS | Value | Description | |-------|----------------------------------------------------------------------| | 0 | Successful program execution | | 1 | Usage or syntax error | | 2 | Operational error | | 3 | A child process returned a non-zero exit status | | 4 | Configuration file error | | 16 | No manual page(s) found matching the user's request | The above are similar to the exit values of **man(1)**. # SEE ALSO **man(1)**, **apropos(1)**, **whatis(1)**, **pinfo(1)** # AUTHOR Written by Pantelis Panayiotou / plp13 on GitHub # BUGS Please report bugs at https://github.com/plp13/qman/issues qman-1.5.1/meson.build000066400000000000000000000006361510660157000146220ustar00rootroot00000000000000# Master build file # Project declaration project('qman', 'c', license: 'BSD-2-Clause', version: '1.5.1' ) # Executable subdir('src') # Cofiguration subdir('config') # Manual page subdir('man') # Documentation subdir('doc') # README.md if get_option('docs').enabled() or get_option('docs').auto() install_data( ['README.md'], install_dir: get_option('docdir'), install_tag: 'doc' ) endif qman-1.5.1/meson_options.txt000066400000000000000000000020701510660157000161070ustar00rootroot00000000000000# Meson options option('docdir', type: 'string', value: 'share/doc/qman', description: 'Where to install additional documentation' ) option('configdir', type: 'string', value: '/etc/xdg/qman', description: 'Where to install the configuration files' ) option('man-pages', type: 'feature', value: 'auto', description: 'Install manual page' ) option('docs', type: 'feature', value: 'auto', description: 'Install additional documentation' ) option('config', type: 'feature', value: 'auto', description: 'Install the configuration files' ) option('libbsd', type: 'feature', value: 'disabled', description: 'Use libbsd-overlay' ) option('gzip', type: 'feature', value: 'auto', description: 'Support gzip-compressed manual pages' ) option('bzip2', type: 'feature', value: 'auto', description: 'Support bzip2-compressed manual pages' ) option('lzma', type: 'feature', value: 'auto', description: 'Support xz-compressed manual pages' ) option('tests', type: 'feature', value: 'auto', description: 'Enable unit tests' ) qman-1.5.1/screenshots/000077500000000000000000000000001510660157000150135ustar00rootroot00000000000000qman-1.5.1/screenshots/qman_apropos.png000066400000000000000000005057531510660157000202370ustar00rootroot00000000000000PNG  IHDRS׫iCCPICC profile(}=H@_[A;8dNvQjP! :\MGbYWWAqvpRtZxp܏wwT#eq!]0 Ab>'Ix{zY}JdO 1ݰ77->q%xܠ ?r]vsa? /)#qRX/^Tkk8 9VTTȑ#z7ƴg>gclCmzZ/^bw},O~$Iuuu*))?{o$]FF>}>?Iw%$4ut]r%ay )L:s$oWVV֜+k{޽)Iߗ) 6υ|}VkX.qyH@X,*))$޽[O誫<m&Ix@K,ч~_4k:t[nFeffѣzano|?s-X@===z嗵o߾?JΞ=~f޾otyW??|~-ZH===%K'ԛo-[(D}I}_^^/}Kꪫ?IxLVnnW? /_/Y{jd^|N<ɏ@Reff&iy^(<477رcڶmz{{%Iv]OZfMBy )nP^{5-_\_җtwFZxZJ555ZdoVR8{뭷|׾ 6_uUzO}J<ȸYxA/.ӆ oo?nnd-X`TPP:I͛˿4޽tG엓>@_׵pB}Ւ%K;DlFjծ]"+ԢEF7MUTTꫵ~z䨲RteEvko[<ψ/~@eff&3͛7k=裺uIJmTPP҈v<7tn&j'PZZ~m[N=Μ9/ ^SO;ԦM{СC :z^vmf?^_^?Ocnsmݦ\Ik[n[wy;&){d1:NguP(wd'Pww.]{N>/_{|N$ EdffHLo[R쀠q|Q=S p w~;w}wLL/߯>-_\$IuuuO577SR|Q;C7f> UQQQ7;Cg}VW}nFYVAxڶmn$iŊ?Oԧ>zFzekNgeP(bOy}=fxٲe=#=07|$I?|Q8q{F`ݭkF]v٘ӱZfzFzߗ]vOꩧ5\m۶iͪR{{ihb7|s<:cqK ګȇj>͛ `p:0 DL߯ }&# E|%KhժUq߿+̿??$l`qNN$cN' Wi%p_R_sϩG_~yqXm4 =~$I`PEEE#{u-hŊ +p z1vEcbYSŋ.]SNԩSs=7b@R@VVlmmM7ݤ";wNbNiUPPK$)s~_k``@EUUUr\zuߎ+$v׾5IRWWdZURR"ͦ_~Y/^cXGIƍOZ---~FiiZZZo>eddo)I'>͛7tr3$̙3k׮UffZ[[Vyk7llX$|wСK3d|HN:G}T>N:%Kh tM̔Y}Nk֬^+w}wT__zHvn67|S/)[t饗M04|rm۶-s~;`0;vN^{z{{ww~FqqҴzj9sx/Y˖-߯_RxJ;S400 m۶M'NѣG/K_:sMdIjmmo#Gܹs?^}U9sF`ϩYkTC0󺿓kVOQ=ھ}/_p@ 0F1--->:jGjŊ믿ݻw)={?w-áӧOСC~s}ܑTQQ[@:~^x۵tj:}ǜqFmذA+Wڪ]vFZz|M:ujϝ;_6l-ܢ+B}}}oUWW롇?qn߾]o:v֭[}M'`={V'NЯk~MBP`5kyPh333?Ԇ &u] rwoo$I_O0,X@ ,Hg9s&bkHgƜ!juY0<tPH>O`0|㞮y.)L*ݮq7888\#L`0^9sfL#XCΜ9ޤ^Z `JXVeddh޼yJKK ty $-:N50Ο?ϓIS@@ )0"@ )"Ӕ$͟?ܹs "@ )0"@ )0"@ )""l*wZڏ"@ )")$Iϧ4`ݾ븲JN47ܹs }6# EAR`H EAR`H EX$$i$ώ{O^I(=F@ )0")D婼\NSv]Ԥ;wR8%;va4*--4rfSsss>O~_ڷo#/))QUUU:;;uAy<X^^"9IqDhzC-//W^^Wggta~*sNv-IzzsnnF}$fSo˖-555r Uϋy0˜'|6jOgyFSSS#áE}#^+//צMvuq+//W~~|>lbݻwTqOgn񨮮.Tyy9 p%''G6U>e F"ǣ6I2{׌GggCnti3Xލs]]]ą]MMMSX$+gL)sΨ+4]LbLA( `?W>OMϸ0 "{a5}dSCCE˥rٳ'wv֭[FIIIT@͛<]*|&^IIId65+>׉xt*,,Ӷ999zcMMMZ,P7n mٴi&ҜVow㉪cF0dRx*i\`L1Гa)qKcS]]]FCX Dhzf].vޭC6 >> ^F0t}].W)<1UiGJoUWW$?W>yHJx7.6.K999qOgx^k߾}#^(u~Mb\(Gh>I\߄1.6TYYRUTTaFbƺl17޽x9~֭[ vSy^ܹsׯJFyCT|78Q߸q#CU>EbLU6i8 ڹsvޭM6D1$ME6z=_'#:s=4`NG07<#5ZPs꿲)m0(--hO:n{ԠqݣlݻFl66uEm6*++F9UD<00#qMn;fH555*--U]]كgϞ=˓R}}:::dMMMbɐhzCUUU󩺺 }d[[6mڤR|>3;::̞PWW+VrQuM4p8iӦgFQ5=zMM~RH2tww|)--5n50xt}r[oiΝQep8vU__ gL뗟ݻwGoǎPNNb*hfHqz#$0.>4ox̩˵g׫\EEE C?яzqI4vm޼Yn[+V0|P{{&e:<vgT.K^W'K~_[lQyyn\.y4jr;"Ub IDATL4&|>9N9sI NuyND{{go]֭SEEddz0[lQee5j>|X%%%fk$qJKK5ՌNp(//o9h}sERHϟOip8nݺi8 &ώ{O^I(=F#!--- PXXH!B@^uay<80޼ycWRR"-).++ǣ۵ttth$ͦQ|*..zfTEEEr8$׫jjjvYF~wyy6m$ISCCÄR`LVMMMkv]v].Kn[999Qʉlxpp(???fu*ˣQ.3JKK\nq0Fl6$] ƎE[[[Hסb>+޾ʈEvsĀlQQј:#aEEEf@iݺu6w:*//sIyyyD`u߾}ڳgODÃG*??_R8;t~ľctFLcsDreeJKK2RrtZ6:5tdigggDxZMMMIKJQÃ%//ELGo>om,EEE38`f" ttDD;O<#txBNw^^ތCp84u\r:38`"}o(Ӆ N8XEÃ999iNvgqE sjllTIIIT%%%NִMMM.K7nxtj޽Z.Cv=,***̿}>ߨyL q8RUU:::p89)йqƸk644DР"s*㊊ ny^lNqlTYYi{n~_;w41GVUUvG寡aL8|&8`#||QX_l٢Z3d74}>_DXv)in3;z<1~D@yf?H1:vkŊr8|hӆ{~zvtvvvΈQ~_֭Syy9W mjjyMMMqu0X$$iLwWVRIҩFf}Qۜ;w.϶R@ )0"@ )0ALWwבZU4#陭:\w R0H0Y!x{rC:~¢VϣP45ʑҢRWEOXTJ:Nҗԗs3AvMa@r-X_zΓV5NSsK?*P_@}ԗvӡOP_0=_Ņ;-nXA#RoUB!4 if3 G)uX 7 T\د^LׁÜ@}ۃYHezxukrY(`uP z|W& /2N_hA%P_0tX~`U@l0;?a1V. v?u0]8cZ=_yzWukpW$<4cVy{xIS~ZE|XSг[T\TA: /9c4F]a V($F~clJA/@oS+S4XVM%/ӣ$%ͼ61ZP_@}- wz,`ѕ ‘p홌F\(*0eőTYQ@k>mAx;oEͭiQY r G}={MV. ɵ4^siCRxxY![;hs,I3uh^<= 0eBוY_[t p_<SSzޯEY֣tB$Ҡ- +>hMa@(+|hnƜ}0urc0 e #ZЉ՗kׄɊ1pp[ hCMb4{ԋF&7;[ QU;=lMA_|~WE_Gň]:LWxhErK;{ځ$Vj"wIz¹PU5/e'P)gz}Iz;cѮjnFՕg1AU}=09%ڟW/E}u%0KKZ_eZY h岐ZZsRi 3= :Z#vL.Zj&h}1֮i=j Hٸa 9OX_ *s==Vi}Ix#Ͻ0^QkToVw j=5zҴ4F5 ieQxZ &=]K_IzpÙ\_z;yhPŅT; =&C/w/snG= d{PQzvq^IE¿}dH쐞F0/,juU\wO]U^S Lf}1!aN%^T{!\u4>ae h`w>0L ~DrC:b2)$>1xxvdc>%SI_IڭWkueײx]Y&{7'8ZQءe>a/Ev~ܼI>ϹS_Y!sߧ^LסrC~p\ׄt*_} =LFx0 DBj=JS_h OiWV4)5-T̩˔/G <3Hn-[rӇ/٭f0ov4G@=@TdMa@l}d1B{^Z6ރiI~]EQ+X0:FX{јmBFU=@k Zh4z,#)`udc=+dg&{XFa'` YP_`U0C=+'0G:S&28 =Qԗ GNSAigNYQ_TOzlWog0?^k 򕁨j /|HR`֭'td_\.$s`j0/_<eٞI/1XFD[VH?9s #1]zfƎ|}-ȭݟ.ҠV. ]:~"‹M ; ^뱑=i*s?c}I\3ѓԼt2uo_F jsԗC-ֈ SBw/S/5*. `yy{,f>X9K"ףcij=P=z1]K1x09֣VmgPeqԗD+ɸlnIZ,Www˜YőTiߕ8iރiZ_г[yt-i}I@K. H)}R3#~ {¡!ZYo6)3+|cЩQ &6ERHϟOI0KrC fN]ǕTtQu_6ΝKyBAR`H ES>kΣQ )0"@H01 iۛ'G rd VRoUSODcuRnvH]=z$'haOXd_(\eLP_}"<r-ijnI O+7;FOIғhpF`87;- 2(,00fGvP'${VH+$I#z8YYo2"lQxGP='zgo>aF)s$I |Y1x(5N#+ 0WeÌQ*z7ZYOA Ȟ=+$޾eDL0cuai-i'#"ki+iL FcgT*Ѩu,T*H ?4Mßɟt`rrҚ"LVgF4Ϸ6??d29pُ~)_n8Nׄ\] U,GjK+K6]ʚ= f PR×ꥉ3Rv^`WXeI'>z1?{/>"ts,_fqO$PUձ/YaVA+TiV\dYlnnZ/0ǬEbn褝WӴϯ<TUձOE`vva9z1?{/{ 7GTj5'۷q\riH$j񈈈d3 *ߗPӴ YeiHBZi;A:s~Y@U+++uO&sRTE( EX]]Xwb~:/CrZy*Bm,n?/`/5 `rD.iVf (-Z<(M+pKANhgᅬX,V`;=1F^rM,IpΝz1?/'5lݽ?""""""""""n`L)m@N _P0?V}N0~DDDDDDDDDDDsU!NWgEʹ\ZV)BuiS|>_ßUrǭϓ/{C,r.}>_lnQ0+efff*+[ V?/ɊVYBNV"HW_eܽ{pfIp8\Al6?ORK t~?ܹ.EQh4jYӴp7Ǐ[4\y[oL&c-!Jc "DQ 4AIJǩv|>k׮qXYYtii l|%.ϝH$*$I077gG|[ u |x 'qH$h4 YjԯqrHRVdYi_vws{n5LCDDDDDDDDDaL=Ul@ A7W>~ c{jV8V=I㰵y,,,XS/ƠqUS=~j4UMZ Ovaffg'x<o=STpƯ])7 tcL=U^IjV,VV BHRǾo2<6IRPUH 4MC>G&j2jiL&k׮YK@KQd2yl* Ue\|:iֱı_f$K>op8 Y/h\.HmB$R5t2ZǏ[\ 8s {EÍ5߷nv/`LDDDDDDDDDDDDDtJ0&""""""""""""":% N DDDDDDDDDDDDDD`"""""""""""""S.~ov2 霒Go(1at{ ^8IDD5ݺu kkk2 7}ޝ;wpMd2Sw~'Q$A,C6o돈ZtƘ0& `~QGQ.½n+5 sc€ FGZ׽((\/]'Jt $I(2 ! ڵk`H~d|l~v;~wA ͛71;; Adǭ@"@"9^dYy^{ ~d^ D"V[ #a}}TK'׭w"""""":SNJ/q0^kƄQ}h vmұR=8YU׶ /\8\ZYWK\8p{R]t3yn; ]_mр XXX(Ji$ X X|RUU*$IB4,˘ [EGUUf!"BBdYQP(d$IB$|OS 7h@ Yuvoaa:,|fbd2rwRXsb^_쌻ylw܉tcL't+f d6ʽz{:- (-(p59s۝gNO'ǝN>.McrbyaߕB]cA6=x_*(a\2J?o枺mϠ|%"$/g/˗/(Zwܩ3 ( ~E[5/PRvvvҟT;j^ZoFԼd2H$@ w" Ncss8uivθl+8o7Z{SGYGc'0Rֵ9Z}2>c~h@W"3 Q\?7lJ!i>*֖Y9j:^r^.]XN^󘚚B4$dYVUxܪukγn_G\~0VcFC!g־E »;n?++BDD4hʃAխm+֭[{m?_YYyn뭭-qq~rY$,--'?IE%Ip~Ӹ0uYl;{>^j/P/pׄ?wz\svc̰DDDvy+feouT&$+Vig?pu.C"kאf>iO""""""rS!S8YfV6;}fjL}6m׶7Ktٴöì3lvP(7[v:xfnN:rj^wlnnvO""""""\ #{`yTtQZ8~~^]*`iiNa,..V<``Vua?f.+b/g;;iZЩy׉H$p8\`IDDDDDD40uĽлC8zE\,-ռwVhۈgÏ 0.8ԳCwWC0^4_)k +={PX P.T /" sge_b~J&PsssFVl2vvvbyysss58??yFsm7K{ ׶u]'uWt7 1\~>TZfe;`{ """""""""""z0&|>'"""""""""""zD`0ٲ>;Ȇ3ϰkXLDDDDDDDDDDDDDtJ0&""""""""""""":%ſ~C__0p]`GFH&{Gos;5N^M=16{c2{G666ju9eA@>o;w ͛d2/uD"b1dY:󅈈$cL4(^(B?[~+-X}pV'm=7^yi;?܁sa{GuQ0dY(PUbmm Tt $I(2 ! ڵk|pѳ0рx @j" /}eߝg9A%_˷wcx |$pZ$ ~%IB(B( gff?/,,@evdI( TUeg84_4MbbL4yppKT;ڪ=w1}ܽܽsdW&jfYg?C.~ 1==N[[[DDDDDDD48.y+OZ~͹{pYcvk?؇kׅ@ #@4TdVZ `ryAB?څiVkׅ^熯=yG`\ /a}'c? RZ8_W`;uV㟌VUn|?mXi_/- ?n{5elj$wn~[j:1zca0\./^L#/Fa##>cw66cxyonvr~ IDAT^4|^(|XW8ydYF0$I$ !!J[:;; EQpMd2D"(Rx㥅F+$  ' "(Ƕ烢(eWUU;>/vK _'< 󅈈Y: rG;{ qM]ױ`Y;?og6VGux{!pjt rs_>d:w ׮1?loǯWЉ=ϗ%|(`hy6ɘ/~ɍ`$7VK\9wFr#{x{1ױNvr~bch  ȿwKKFwKNA75&zώ[l~h,cjj&R WUUE6(Ų,W3[(X\\D(X`=Mfߖ?f>`0h4jK ,unv" baa(Z4 $!Acvns~N$""""""g `'ɍ3U++8yrC;Bȋy?:V9}B⛫TFGڹ{0*$!g1xvkb秏/7Whվwbz5v/[sܽsx 55}"<~8l{ܸebOb{~_׻3@[{p c\. ?nDb8>t4dYX `vvX^^F*j~? qDQTRpؑ|ZߏVj4ŭ[|XYY$I9?id2劾D"VS XZZ{~vg9󅈈Y=#f7W8/ﷴfr T6mG\._pګZ_sѯ_\w>>3Sρ'ׯ8ؾ+R_3pYkvhj5=DҸU }9Ts\ca{~_;{'G1v}>wcVj֓?A* (hxU,kJ$H$5U\`U56j z୭-$IN]h("N#̛D"ho=?BDDDDDD,bL'Ϟ Yyp{p;)qku/A}v9󅈈Yl*8V MMN\4|vJǧߡP'q\. 56 gums+wF7UA'W~^gPLtՊA v4|duӋezYNtng ѳ0lyn/vmj5i%@2+"Obr:=k~8l[5qb;)g2$I]4WWW'[ڭ[*<5̍<zٝ^""""""gץ$PQl5:R5f;{*`P~ڛx?;P=}Tj*A{n2_?8{n<1'm^wr~N__kf{/Q ֐f!"k~?ܹs{d23[RͱA@8b``V [Zr=ىUhP(ٚeHđR-AӴd~:џ<_E:#Lwd-}݁  xcsca12 ׮no0pC_Ux~7x{AP* q( ro-e}C|5}g1Wֱǰ}0~}; <[џ'a^wr~N_+]FpY콲1ڊ/**Uek 5733E@UUhIZ USnܸ@ wZKnnn"W<ې$ ,WKņLtPKKK5u($I~K&PsssFVUp2Tv[[[E(5aN̗j˘yGu2?A/DDDDDDD" ^fԺ6 Upy/Q; jުVOƃ^M6C8{,sIBO '~F|.vCFk!O^y`B ҥKe=r?;T*A "TUůk׿c&+\tO?u2?$""""""AG cz DTnccp8̎qrfgg޽z!ccc \Hy%BKϻs666 O}sΝ; DDDDDm`LcћG8|p/\p}vB>!C(p5xA˯{vp8Kff4ҧ8(HRrx=kmm "xv `vv+++ """""r]@c@Q.µj [>|} 뤴NR%^{F:1a/yP ?.`WC"̌煅ȲNCrhzzH$xzh*Dpg?$I(PUiPU[[[ """"6ڢ_ԡ÷l O=P&""~Pl֭C4(*`:]yvQQ[r@EG*wOc븮]ܟq"h(*#@ELNNC%# 0.ys'" ?nx½]{Jwm})O(Nc԰^OK<~b2,2& 쿷_g30ʶs~N(^)wQKr7=>CCIQZwp?pýw8y\<{PZ(UtM/ίv}1VZDkOӕ4 ~\JH{>85W~g*`Ji3:>@e"LUU#L";zWUl(" ! A?E|I I#;Aggv^'@ @ P(tIvY~kHe~`kMڞX{fY(`0bӜ+KKK-GYbƍESSSa>s91.!@UUܼy CcYN/p̱2/_[{*RQWb1qGyoIRVN.gy;33S7urmmmA4ҝ^Xb/HIGkkk~@Uc\EѶpPȚS }<4  A{d0(u+_z1_:9^'.0+|eY‚Ud*`0XѧvK4U\~D"5~{GDDDOəY岿mϧYeh/cw4>Njy-xyfg;zy~ƘaU񖇣@iUs,+:1{ *=XU ɨ9.P :9?'̥>|7/FNsggcx+__c/ !BE銀ƔH$( (}ǡiZr~H$5H.*XU ÉvNωqhuҳjjd2ևvi.dꎽǴS^yμV%YŜ+N;_VYjoѸomm!LZ堨^v:ul;,//W/XtJ>C׉~|ix XǬ~뷓N+~\DDDD əTgf+ .UyiiV&zyNe?ǡQiE;KZUM9gVo:u~v묥wJok˸dTN޷(u=]/jtyprN*_Qa~i>t*vAV_g.ii՞rfHv@_|gK_6jgYF7֭׆nʼngo7~K'z̚a{b[&뵳n WDz8yf.0uZ~7+:N/ż_+ 8/v.MW hLլFwQc̰§A_'婨N`ر_*(Kmoy|jvz~viu*j+t IyPqi胟 ͽn X!R/QsZIpΝ1?HA(_V*tZ}|;˫$Ij3L" ݻd2Hڼ$l&UU!b~iw^s ^Uig'~o{_'Ev:ul^F^NH4f埫։~|s<.fUtҟ_F^_DDDD`ꁆQd8GlEf|fƿ_chO~d-avٹ\j6Sm׍0O=.|m]QZDEWtKm֭FhSv@D@y1?E|?7@<`he^Tc|"vyLMM!brr,[Wܙs2kTɼnTlrY;;'$AUUP({/ IDATlXtkI7n>d2eb/F?_z=_=lN9{} m}V3:~wxg־E VTݚ??|iu=[YJH&_/_KzU?0P{?++BD'[g:b mU oݺU󕕕Iigǯ_LCz|q*n޼|>w" ! wM[~jΉ':{^5b-%]ovۥկƘty":YX/<3v4KR5ߕa'^3?nb͖ܵ+!HڵkR͖;s 5fymV`/N?s ZNYN.S>QuOR@?IrR]d{iWwO<#""OϩҴ3.uOK'[;Y}(sBF;c/!cSMVk`}kՓfscK^$c8fFcBӬR`.j:vJkf%"`qPU'u<%Ij;p \W":=0??(EQ*4M$IET 7n@ ݻwM޾}$AeXEaQ&A:F(RMnݺh4 IϲNtu3~˗/#G6hce'$ X sssu$J9B&''V5+sssF4 @@*syyٱyDZY T*մvvr=؝/N?ycee'V3'sB2(|ܩY R1:sss5}3??_X&^'J?]Ћy%N#AQf5w/vﻧy`bL}vcx~/0& ][-#׼ ū5ҒxCC*UQ鸘(=n|<~gTnU"p kibJvNZJ W (ʥc=/ܥvO_^o5׮ԧ?.%jc/&ؚcRqɀaٳ|:ƌ֖boxzbi^?ss_S(`jj h` @D"R@033YACF籾p8 Ii,2LJD"(b-ydH$ I`_N:v^XȲ@ `@ǔL&itWîT*~ۺn[]R7#N#Zm]__r;055X,`0I*4_vڽ:/N?r9"baa׮]թyf>N;^ޏ xAeHdBNqϙLOO[`~y/33Fņ|9$^ =:ܾ}LXs-J!H8{igDDD4x\ Klibl7bd5{5 tcV8@p*$ȴx4l`D؝]K͇4֬2-CL=|6Et9UFDoڋI Pt|,*"%b[8|z ~UZlA D/>jpn\`2٬;fYlllȲ,ݺuk*3qqoi2MS7nܘJ/>O]|EO>xγgzmPFBOB/N9d۶2T~|,kj˒lp]%%c9s徇]z -|![4Z__yhѨG3gʊZxǤ^,/{? P;7LzʠH=aڍ;0^arYBQm,] JN~]b}JIqmmmy_ cL.۷[|2ղP圗~8>>n]&j-ԱR˿O,aYj]VVVZ~u޽mo5lFK[,//{?;30f+ۄ,-JZ[[l6+0dvwwU,F}RrUD"/*_~assS^޽{WGGGT*C/sy\.R&45 9A s0 `0'h }srA xY5yOŪ?vYZZښ שtxx؝;wFK&Q6e,1^pJţ#ݼys.t}7n\.dRLFx\aH677rFUThQN R_ոؐ$5.7K+uլ‡oJ]T/$7!-|0TxpRM|QL$Lݻm[ׯ_^,F%Iiz`qݽ{Wd۶l~qN4U6U2|ޫr2^`pg罟_|BkS_Ey˴~?{;$$=iݍk bY?êL$H޸߾}yccCe1 x8l1t:-it:M?xC B+u߭+MhJ YP:s_lqUaWU?fմfqR)ٶͲlpsoP,$J  ӧf$5ABOByg`{W3%k_ې%4`K:3A5.6TaBo?*ak.ُ\f~U nYyQUS{Rrlc>_г_>.Io}V5|8;f醿7p1T}#_ETVo.}nݺRL&t:-48677.UiYelVPP.SRx~,eYJ&2MBX,'5ٙJ[{)HS<W&Q<ԜasϠqp4U:LΙ$eHӲ,޶m(wk>fiiIkkkrG7nz~\GsVܺݺuKF*JFrr\`Fd2Jr z2F{R.ӗ_~)0tڵqÖ͛Cqqs{~D"!qtpp&gZvbzAkڗvqʊ[3M }8'y4u;zu|tRzvsR*ҝ;wzýBYF /\ = IO_?۸d#Wԥ_uM7D&>$&$]W^m?9߳][~Pmȗz~S \y:HoB}`۶dRLʿm۲m[ijyyYeƍiC?a(J)Jɲ\XL2 ;4Mݽ{٬.DBe)wm 疻_0FD"!I^R/J&ؐa^8#4fFx$ڳaqezQYfYbH$fU*T.z_Cn{όs$׃;Fl6+4{@PI<::~vuL~8 IDATK^?=]NL&JҖn}c!N>ޣݾ___߃q[ka~I/{ݎAY]f}=EI}g0&R]q9ƹ~uÈOAh흚"[z3p}0wMTNM/?z_W;fWᰞJvǷNM/_= yz_z'a驤KͲQ0 ݸq%tXZZ:{ò,HhTlVtZT*mooP(|ǵT*2 677lڸteٖoiZ\\ZYzt˗H$d۶nݺpԲ,ž3#F/b^dLƛYYg7]qezQYqg33 qdƭR8Ǎ{=,--)Jycѭ_2옡yZ}qbT qsRt&Y;h{0 wN>a^5<>NݕmgßI/sݎAY]f}=Ţ$)J)vCɤ/Kp`"UÏ=x[kLٿ]|cϒ˅EFf>Kl%@<(R զ޽*]j֠s7 T"hX4fw?RhssS,rC\.kooOo}8{{SNg}Y?޿f!qR ÎI,//0 Ŏq)ٿ'ўn癤]&(QP7lr??Ts_T*uqzp뷽RRs9Y^\4YT2/lIge,wy?Qq!ufqݎ.۞Jś ٿgeH s?i݂q7o ꘥,ޟqRņv \vO'+ Mwn0`P@C|7p;GIj =$y{u 5 Zru[]0M~ܐw:q[D"a$fʬI0o2NF~ý_p_}~{s=n!zu[}}(øn]*1 :KN>(5C(qtttq,wy?Qq!u'~)hˬ[n_r|[`c0[~(oKj~޽q?8tZ2T:V<W4ZnpЭ܃fWcru[FӧS_:?cǚs\L;,YY_<oSY]&(QP圕/{ Z{ye2% ݿ_RIbQ=/7}qmѾ7iY^]=&m0WNJK&O8Y~"K\CPf}=L۸2$Y,8N2Y{g0&6U{k_{:cQjU{le'9.>gOm,ܭQ/'/Kv\|ܫS8`gݏnܽ-?RXzrkŤf_oqdFߙ"ܗ}׳4Mٶ-۶J۷o.Ӭ_ ԯRƍZ^^,`۶677hqIOgyݎr=۞xqz F}wA_$0roIJ%YղtVXIXO:9կU՜rB:땚#W?ns9з!oIhwy 7Wg]BA';LfR }:ȗZi{{{#ǽPΝ;Yvww{ׇA81n9'mI귴$4Z^=_ljq}l֭[TTt}R)e2_]}iﻮcmnnjssSxܛk޽˿:Smƽ-{73?Gmiro#5~Ve'~i~U9QeI7b`;.|t[؝.mjj(^/;!nUņ^ ucۿqjw&רK Ko`=vA'8n9'mI.m~hkOZtJ}H5=f=OR\*~Kl׺.g4^tuo)aIf_{O:^Fm ]G*tvix4L?̺gmY?'mBв sX.n`zk]fռٿ'fb׻ܛn֩q۸z^m(?[8MRH+pK$]?I&orkY%4uttu9v a0^kKKKc[Az\BA|^.g4x9kkqz/\渳2>g=m ttRˆneo6߿"M=vfI8mzCPY?mlO5ewo%8M1UUAeׁ;ÈBOBj\m4ѧ:$oqO}з!/2NMVu ǪT@UjjY }ڠp_~u;_?p*$Iw02jiiI[[[-$ɖbѨVWWYŢ$iuuC㚴~~$?7[]]m'L*H'iooϛ6RC8eY4>Me۶VWWir_we2---u'Lznw[:~&F,|Z>kr{r/ ڞAHR-uFZYY}?Jwd2GLfe\+++2MSivNƹރh Ӽ}?q 9KAKYiot߾ 4a`Lq5U\mz}‡aEjKf~;4E#Ն7[7s܅TRWjC/>y ηpy-,~?񋟵)DHso9_;5/(n\l = 53-~pZ4MY]ٶ}RIbQTJw1MSaΝ;Z^^ib-˖mnnjwwWe)LʶmBlI9qL&H$dvow~[DB5-//{3!O۞* -urC\۶|>L�ٶh4*0l6;7 L+>DZĬ/As [q%,۳T*ob~ N)I d]k6~VxRϚg } |R3hn\~KaneH"RC| i-=_q6j↑]ª_f`|iַ站:_~MZ J?ccEQ~oF_|NZ/so&˅ T*ӟT/}{z曖* ζm?U\֟=>q˙N|G_|EW^eY~aӸ[]]ii)/^xGGzw~vvv/:>>VPЅ F`m׿֯kxbXuhtoz}OTX~{OT|]iq7u4I9/rя~J_5_|~'qs]Mr=|:w_T*rr^~T}7=zիWex_IqsW%077mgq_h}}k  ]rEhT.\P\giq5A b<}TdR.\$?{zgoǏ4O~iv~},/erN.A?gٞizy~ fYV/6*翎ۯtO]|EO>xγgzmĽiK5ګxլ^ÑB)וC- [~.k~*&F,b,zR4eӊ'~:>_T䫈-9]/Ωn]܇a&&{l++++:88h`=+Hj M*0h Ix\a FIDEsޫ IRd?w߳fT[5,~j˯[ 568 OSaDzJZ^^8m[a4MIۙH{ibVWWJtf:kKsL*"JY0f^J F#OD~un*Nؽ 5ېRBZ_ :wN .իoF~=8TJe?  _CI_GW:SVz퐤$[4L_|x$鷇|gϞl s0 `0'`N 9A s0 `0'`N 9A s0 `0'`N 9A s0 `0'`NUg&[{RHɤ޽ζm]~5ڟ:~,2٬$i{{[\Nt=%][[[JR|>͉^#ݼysjǑmz JR~h4L&d2)4%IJERI|^ry`9uVGycs;>> B FOO8~L<>Qe~p---ɲ,q!۶e۶ {'_+i۶|KN\+++Z^^$hTTJb2Mkr|>ZX?XaX,N4#F`Ray2nN?t:f<)a0 % iigg'%Imll0󚦩t:=T< ˲ѳ~e)l< c$%jkkR4MT*5`^et%Ji}}_F϶-E7oq_7 0L& Ösoh%[^^VT:;pbם~~F㏻ w2βl/IϠe~p} jOAjKYbK,R\?q厶O*J^70&8 BD7pZy?' i&-mnnXǵ MZՖm_*5w跳3T-..zrG7n+~JevBsgP2l?HeAcx<Jϴ=x<޲;wɫJ^]X,*˵\˱XLޘXZZ"70&3M۟Rs7=zHR3t1MSX%eqqqM<)rYR bb-loowMrYn dgLrQruES'.nx*5C\.Oua8Nr{{{^//wQŮmx\tc胃{*pvid2J2MSmkgggHݭJErYb/v̵0M !J*~Դ/M&L~gyqLF^٬VWW٬D>kkkw^/UeYijccM&]qv*0ΒK&^2h?|9::fJ;sX70^arYBQm۞ hgvww3< f1>g.3J}㤴vz͒ŵk׮ڵkc;vGXV*:::H$~tZm'2uttqn BK]wv?Ic h  ͬuGbQTJS~rX,&˲ZBPh^ |>Mn(u]$b|.CiƵf2E:KVVVZnq}}ǵreY->ߺu;&xeY#oyp^h4rqFw)vWVVݥM `\.q/=::t[տe-.. :UY*^Hk۶=zs qo{h4:;;;nWT}q}ެT*X,6=G1D GS9 RxJ?| ^WLaq݂۠>&+2w / IDAT b,Klcyr@+f#0yn޼7aD 2DG G圥Mk}}];;;=qg7#P(h}}}fax=KܞÌϳ.~Nw9H?^ÊoP=v&nQ\E.~ݺuK*2 t`̜?8rGb?aCr-UkI(1(?7rS? B}KNU3>JN~]b}JIqmmmy03b c1g.۷uΝS?4 }q¿_d7[\\lgYV@(rK?.LeZZZXbviiߧiaYj]VVVZ~u޽mo5lFK[,//{?;3>qbw{{{吏[ufxZשTZwhvZm`T+++])O>~v~b`̜?thT&X<88ZgYo/]EEіqmn)OPL$/Rg677ݻwuttJ2R+++=r-e2MSkkkZ[[cfrzDQvm'*P۠9 e~rZ\\eY%۶;rB][[eYvi8{ ۗ[Ύ޽+I޽}ܴBA~vwz},-//qo߾Տ=jF߿/۶q޾D:`T>?H$F-YTZnqP rYckcc{n_ͺvTW*4>2no֖w9H: Y߰3_ YnR*l6wܴ[__ݻw{gXvu5 tG;;;=+m+o%01S̳vSE|߀P(ȶme2/rGJERI{{{= RIׯ_6MSax3N|xX,T˲o{q;W.%6h|vT*y󦖖dYewf(7dٿRs6t>Ir*JJu>f{3I{d2ݫvnɤLSHRCz-Z/>O]|EO>xγgz0 0 `0'`N 9@xSKլˤ }bUW-'FUTވ.--immMBAt;si L&de$)kssq>}z_=g|&]mSas֯Uj +uվ_{&n i7>Fկ<0Fߤ9^t}j\k~C]ņ^'}8R~M -! g/Z̓mڋ7~;koT?ê7P'4Ma Ze2IW۷o{?ollȲ,N%u8L0qs-"Wz/ոˏ^*ᮡhr34췬lod?߼Tl = 5GqͲeMڞz/KR0ZfׯU}X7 }(o흚.*1|_7pwJ YM_6gpೱ"~PUͪ\)+JɶmF$IR3uf]zu [Xᯛñn]r9RܯεGo.|VjCgMڞSkO_mafqX?9uouڜT:t##~!vqgFTWD|̠f)]\Wm Gz{yI9knjgwo ?ܷYscȿWԜ?̲Α";rooL&t:-4e۶rKk׮u=β,---)0 ٶB\.Jܕ-//;kxuuUtZnRTjnmnnNeYٶ13Q$ey}{OZ^^ioVIփ:wv $/g4U&)IJErY* AFS\BÈ֥aݹO;$wi7.z e#@wbpe_i\lW_ WuCO$= o[˾jA# OW6C~Y%COBe6o~y|׾ؿٷsj#v=oqAf0J$IGGG2 ClVi0ʴm[m4M-//˲,ݸq%ܱm[GGG޿wN N^0 R)R)Yղg٬WD"!˲;'5]!q6{[~h4VK[D"D"T*1 nT*%4 ɤ6661e۶ǑifF ,SjyL&u@7ĸ*J˽-i۞ %`8y/xSP t%3\tQf~ݳ~;Uuح#oU_j -(02\94~9&iÈO_p7#q0o{[uBD .#]}~\R;$sv_W{~P//b]Lvn?^ݖe^8^Es>K}O&̗%R)9۷o\.Kju3VVVdYlw\4U6U:jK͈ݕmۺyWTBqmll(JiiiLl6;wxw^4qp mnnz;;tX^Ir=fH$d۶nݺ [-RX;?aq׏rv6|^-dAg|1^f՞emoo{cL&[Y'&{0 LmYR="wLEJ]/eO{e^/U W?w ~PճϞu륟Vo\"Xj/_/O^4^ZO5K ؿ?J-_.5ܧ:g󅮳ݺ,uÈ~0- ? {mjo]~f }7M ^n JReѨw?ԑiYr9rYrY{{{N=<=>>ŝc({7 ۗ.J^(8(xN$(5&gaX,vOAd|N:^f՞@Rڱ[[yO2N{J|.J] z?zϛ}\/~֜}ҹO:0we5tvRsީuk2wn tOeX=ǵBe|/5V>˿~Y??]``=;5o܅_vnͨ~3/46z6˝DŽ~z~اǓ)g_4M{͚/[+ru{=zHPn˩Kb=Bnԍ'8]_-{"v~29xU{RI0 oLR7>eW~3%YOS"G}O[ug66T\o=˝}zoFϠXz, {wh~ƪ9aDÈߩn|3ðꪽSlugʫKe7.{,gKCF>݃6;ޅ4Ѧ"RmeW~\0a,:}պ]׷dmOۓ0~"g='sގ64VԞX <ڼ%B]N&pnnnuX,3Ϟ=k+X.,/"W*:^Da?/A- pc]sb_{ ŜdUUK9B!Ba `2tyBq{.6 eAoܐJ"ZtGa{5c]{Y.ɘ~>^^j;: Ї=KD kr<ӄADmWT륾()hb8ji ^ƋVyڭScviё#֫_:ԗnU?'}ݻw^B!B,N ^ky|UHSvGxM7Ռm#4 ի] B\p_gL絡E¸#~v:N|=`Ú!d|iLWvBΎ."L%z_E-ԫxu^DxTUޞ4"B8^15(#}&J@w̯_mLDHZ)FyN\gög7'B!2|(#=!:yk;k4o7q"&lr*NȎΞ6M.W rIHg4n/_=Tv?-v5ZV*9b@o5no{wtu7nMB}u:Ecl6oM@.k4ͩE{#˗/["0R^xѶ_D;!įD"$a8ѨA=88@\4+++]>=wttB\QdK$d2Mkkb7!7.s޶3G\wR$dvBqhrIb?@2mx7!f{{!Lbcc{{{D"PUB+ MӰjZ'OfBRW* 2$^|QUUD"<{ lbnn.|4 DjX,K$V([__Ǎ7׿iiVWWt:t:ݲ݄b#NOQKer9ij5q^K~7sbxQSUUr9wUUxxlnnbyy5w?913ы ۞BNarD,kz-9i;.&籰)2!<'hOB!B! 2|۽"aQ*.@i%N#͢VZ"8ux * D '!B!(_B!r5\~gy_E2f;" ?<'xB!Baz=㷿Gu_זXw"$B!B!B!Ao3y?J?﷼׵ B!B!B!B !B!B!B!@B!B!B!B !1S'N`Λ4FX3VmE'N/4P*Z~R sp8}o߾ETB"x=Jbkd2J%} = IDAT ?/mD"/^o?+++]QܷB!0 7SMb9osVBqr$J%"0G=PCkgeMcgc4.gҡd “5ci;SM֌=/ _[hjZJQ*2{.w'(M2=~/~φٷƜp-zRlPGݎ^}Cޕeણ@Ќ !WMCR!Bw`닌?}\2!^"P/vd1\#S])e.^3N2̨z^JP>(N~jpiǑ~s߃yo'5> SqG*AޕG!B""%pV1!B0 l=O ]op+XqXj: Hޕa~~2q*)0RFShsweFCO;;Qa~~8B.=/ C3:x6&ELX_W~S5s^d%;M䶨5}kv;лP(ekƂ~[s |aG?7]#j5:k;sӆ_UNiscZbggBGGGiRb"*"\iH$PUVabcd 4=zJL&t:t|>wjŇ"6*JRkxU$ d2b1vzj~ux-8=zaT*yg-`kk [[[x}qj5`}}.}ooӟb?#b _CUUX\\D6?ڟ_)g;Q&A.C\nJWpLYC8::>vvvP,Gpt* k ѰϳQ\yt<ߑOommo"&?>8sssN]dA BLj 1Kęy~W٢McJQwH-?+D2G;ؤUVkvT9)~6>q&C;7}'3##LbuuQӘTUE$8ϣQgäsϣ}L&:9OunnD"NgUUˎB!dL#lMw"jƁᴿyvB1OD_ r5()=p±UGTvvYxՀ?>ޠC}P1kjwS_Qл4݉nDg(%L]br=!fZ[Dܟ[ZNv՝|8rsn L&DÇi*VWW/#!Ncee:bӍX,5$IRD$2R@nH7b@Z)0ٳguč@UU2?K? "|5Mښ\ThD"VnK\#DK])r/~weY;ލdZ~CJDl,sR8*=zԲBpbbr9 1R4&<::j۷oDի>Fu ~Υ^>ľM&jX^^vog(ao>],eB!LI9osϱ&jS 5.V_煋9~2qԳ"t(y<Ξ Nޝ)%^s j? l`t}m&w `>wL[C5WʮЯJ(7G>薪ZD(DE_䁜-n5K?B,na4n?qa۳?~b? i85pCt!|+G7tWv[ۉGV=V9/mD:ps~0q~>r~KjEcZv{'CA\n"H8777{:fLZ;a-BR8Fnw/.b"HO祿a$!D[!@)| b߸gS\Lz<P-|<z< Μ}QOUsL3@!04 (cQA(l46c9E$[0f˰ \{ayszVkƮ#jhήkRTؒJK2MU՞ٰ{ahgg9v$o[3#6θ[rZϭmJQ~N}SȻ EM*Y~p8t0z oߺG muD"t:X,4v 5x u|3֮Z"@Uվ7{Ցn~kwZ~LN-dMa(H@UUT@Q(d{T*e|m?:zEKj68<}uj5'?~Vq-!*DB! I L?fD}#e@]-cE^nzҐʐ%XQ榼#f?;Nk2\0qpsvFk )wGllukiDU0LXo#k?9~6>Iqպ]׷dmOӃ>>/"='sބy~pÊs!Sl%X8 >qjss±X̹ٳo_qM lmIA{7H? _&r9$IgE ]Trpp|>|>X,D©/_cS?1N>E$gW`;3V_;*FB!W&c8u:;jQ0s޼ꤞ_sPn'yN̙9nUAIٷ^|Q; gOrI{>s/5; ||µ{AaXΜGvȹ4""_Xlo_{en"]btlIA{znDI\u+r#rA-ܽ{I%{9?av5b}[a(ϳ~"ׯBMI*F!w5ء|Ņ}qMvږ| *A34ӵa:qU[C\\w_絽Ea0nkLϿa_?qW{9B_(CU(C;!37qvڹ8$D t^ct6ND3ʥ;blGI5?yU,>)ϣ iv?-`@O<4?ЛDz~CPg$] Z_}9>kҰDVC2J 'MӐd:^Cܰ4 #lnn^|Jŋ D"t+ceeʼnx"J,%w¯=2uH&Mv x!-jrvZaswd麍wlP _A_* *84MCVC\2 RT#.]:wϮ4BDs1~ y~9ǞO4a_?;88p>ЄBȄd<04w@"v~9ӕU4'@(\0aM$Y\o-mn(T"nh7ЎdhFG..ҧJQx Ag,8y~ ^9h? j5NNQ?PJ׸i8B5c}0@:Z"CSϧ[gnBn]m۳g NvZ0.m+Ef_HNw'X[[C:F:FZEVD"]odEܿx߿wH>}|>W^AUUh H$6R\.#L˗-{,TUәzP( Nɓ'fNKP,Ώ=2u(Mv(ɓX]]m09 ߃Xr\.t:ݴ~{{{ as0KXtjS $JUUUr9Z__Ǎ7׿{{{-vdy4>si$666Z$0?؀iH$VNb8Yo!`2(%=VԂ~[_N /3oRSĠCcQI(ңzd\ԱeQqÊZN_>OjE- a@#z]g纫uR {,8}o;u7^;U [Hm)*U/o0p.Q^՞l]`'=Soh?M~|qhn#YwT*,--!"H #Zbkk%Bύe H8bK;VWWT*X,UUQհJL&t: UUQT}$ID"167rl6x٬Qr 悉?C!$x޿UUԱ.X jWܨV{. B!+ÿ=_D(<򞓓_]f21==y׀Q$j#\?s>ŷu(E%wy)4!B!dv N[>C! db0M)~G~D1);-siIX3BBKLL! X,FҖbggIbd2<7!Bz0{G~EšFU]ځB 59F777J:idYj5TUD"oPB!`B!B! D"H$jbW^(H$*8jP(MB!c!B!B!B! {Qzy~='''\B!B!B!rEL!B!B!B!W B!B!B!rEL!8ywsޤ1zn/8yw}Q p8<}R DJڽT*R):OL&RoߎdRJjbQ/sRG!B!!Śpǀ 9}Q@wm'(PJ@lFMw LXbt(AMRT }v zwQf4Cބ)(ogO`,) 2վ>q@k'T:NțmW?ۺs>Q[_K& ̀\!,9okwg Tgŵz H]׌J8F.C"ݻw\N\v8UUD\??B!B!$(@>7`h L=o/p6[&[X4|:1 m :̛&qS:?]u!.wk'B  _&D? tiw}ϯ_{3g&Ξ+.~5"DЇ#漉_ΚxxYG![@mZmma BHwTUE:FZ;kkk4F1Z jWn؅B!B(@z3gΛ\P\"^I6GKsQL2n^ʶЯ!g<֌-7G*EJIqΪPU IDAT~z3lUFōgܴΞyF=*Uk,gPzk~&\f$#.lΛ聶k|y˴D_C-QѫtȻrKt3x@ЌBmloo !B! w`닌?\#4!BpuEEj^h3nj *vyTk_22~76nv:0.ϧ[ۮ)ߺ%\BZɩL9QƢMyWf# !B!B!|P"C"lgS zk'}[En8C{ч#});w/Ѭ^b+04c d3jX4`[n"bKtͮ[|pKm_nE9ywP~S`.Ң2d2ijB-oC$‚k;MӐJDPVQ,>|l5UUQ*^īWSP% d2b1@Rzǔ%NiSZbggB!>{4MC"PUZ (# No% dYg~x!ϯ]%H`mmYjZUU/N;bXH$d2d2 MӚںD_PUd&cO?棃bnnD"Nm]UU~ s~q1^ŋκ5!ڍo;B!B'(E.bQaSR7kmΛPv`\#y;Nky|z4u@ɚZֵ鈿JQA]siD7"j5K.\ 1[-fw3jl VԲ#/rKiynў᰿@ȨIRH&jX^^>[zev>iVX]]uڅar9i`uuiX3accju`юAf3:BQU-~~sssXY($d2'5(MS,$RTLj#`iiWpPz_8m[XD>w&Ci0׏_geT xj=jb#?!B!db2yŝ6Qgϣ莁л`Op" _C݉)}j"sqڮCٹuB}'8{zf 3)sSC:~o}-71ָc1f%6!+j^7lVv~qGi< 86kgZSK @Xb "^[__o* kp8k[jMs'i\\J],"r $ ,mmmakk%pD# BFe^eb1g &nq5?.R7W*W۴C~B!BȸAB:NN8Ŏ10|ʽFyKs MrItpۈtMEd3E!퇑vlU ֌uQa0٭]?~ݫ>%gm[t9E?m״[S vŅߩvepluE oFƎmm#zڣ{nQф3pعᾳZĺRkLNxm{'7sss#-5O>Q.ze^e؈{{{0nk~~ߍ7zzo;B!B7BSTܱ-e(΂[ \@ԥ581S)*}v 9[0fO~w^k?~(%͛&[\`u@.5S;mSP[3{,E(7 }i}[Nϧwe;<DfyBZkmFnܸmkNp;>> aN H$NŚA1{/Bto(I8φ=^8Wg d2qJr>}ؿvB!2nP"0tW zfD}#e@] LpJ*_dӵSX &0{NKueH]KVޑ>nn~.D]74;6kmr ̨gu}أ=Ekzhs^+׏F*azuIY.JV ؎yBDXu!pD"bG"$oTvi?^g~>tɊDd,-=8h{KDcTzǯy~fMqZ"ϻF,mG!B!`26ȇ2BC֡!@"p!5,()r~' '1L`gݠ.Թ5MdvN*di}n-u}ך>>/"K~cɜ ̀,=kDȤ vTׅаɚ#K._,sDgϞ50,{?ۉyưׯs<;88@>G>G,s"UU˗/?o?!B!d`R2V(Sոck~Ѻg)͜7/-by~ WW$hvN%kS6\1|8zܩV/`G _~o_d>p5^""xPX33g%'TD"bo],Gh#GFedbHQG۞OaL~q{~Agݻw^UiG!B!wء|# hk|_oWqNkrG߂Iy+vj喟z n3jFm|hV{݂Ƣw?gfkAFwO'{ Ú!AҘtqqni$|-a~/3J@{uL'A'{zs>H$cu~~8=Agj!B! dPv'j.hk;۹4qpjJu+DNb ksSzkΛ?ژzo;Ur i6v?-5ZUR}E7Mmvp5y;=F mB=""2ilnnr\SiHӮmv/_l HRxE~E H$2ma?WՐL&" iL&BX4@w~lQ XYYqm!q>jZ>uP.en+++?ϫ]=?~wÞ_?Y&A*jD"];]QAh>+j5iE5= [Ggb_7ϬO?8c)׹iĎb׸RMɷ`P)ff8k&ޅ`۾s_'dW`3S.]._>4MC"@ZuU,jaί;aLUUr9Vrj;gk܆KvX NrJS`Il;̯_gʮ)yOe~m<a޴.{}@c6{HU J{ WU"~[K{ݣӺHe_,?Ylz3eG;lqQf_2,//Ç4 xj`_vvvJŠ*jPTj4 :7uXk^T*XZZB6E"@8F8FZ 'XYYA"@<|~d2HPUpJ[[[G2H$mO Ph$({],--!!H@UUTUl:~W {~~8G~~{P@VsQP.L!B! ;ZB';v4}](tg`.ZLt#9Q_wޥA!B!Bȕߞ/foyɉk=ΞlQ$jH!;emc<, sfIEԵdE2Ixc-F* ^zEўB!BH`P&9ozNl}8?Ώ ?Oi{HMŚz\bg2<|;;;MBo,C&%$hb"`'!B!(LM!BF7D"j5TUD"fP@>!B!Bȕ) !Bȕfkk D"VaooB4!B!B!L!BFhB!B!BE !B!B!B!@B!B!B!B !B!B!B!@Bq?qIc5cF_qNR'J0Þ[J%$ -g&AT۷oi Ofkkk s쪟A/,B! DX3Nߜ~ |P 6?g//2JI l'NߧOwt(ku -)t"xzECC,ڪ?ahp L^y ΢`/SדK2O{vAgB; b3W?0oօ?K}um-=-9x'#e@CMU !(MaUUDh0r޽KB? !2)P& }n+f+j ?z>eWΊZ0o0o" BsAny֌g'J=^=vBt(6 /£96&N};^~C:&~9kゅ8e[@~[oy4MQPUtjƘPj*h B?x~s,? !2 (@z3gΛ\P\"zI"\0C Febt(.P,Ӹi8JQ* # ^Мz34jFO"_{ctr`>2mX,y=B#TQWw徣ڿUtЯ!FB6iBIp!Bzw`닌?\[4!"s{eX-ыhK[A_6X/ꎸ9|L;i>>Diҡk?_CC09)'X4xD*AޕHpB!B!B!LEΞN,^Q~S`4+v%8Y59é)UgO T7n?04c d3jX4`EJn7Y3Et(Qm"E-k?]1;Ȼ2BBm m1q^}tT{p2L j!NC4ZZ O4R)b1D"TUElmm577MӐH$*TUEV>bHiD6mzMUUJ677իI$d2bJ՞~x-8=zaT*yǦ֯_՞kooӟ<D,=_R*“'OPհ~g?Kai,..BUUǖB!Sdte2r9ta٥vk_TZ|hmmz=TUŏ?EdYs~]~ v$~gz9_FyB!d|L`;QV韕mwq͚1K`4Plr^vR3xw_M-6jt8F )sk؏8R{E mYr(ѯ"mdžf%;u 悉:N -/[׭䥎s-/u.`D7jTUE.C8(XJcͶjj UUfiZnitZ"$$4Mz-ŋH&5TUE2}(qhzMZdY.x!ů=]?чiC<8r* Y~ӏ=+t\no; ϥ~C?v_8Ƌ/ΤH$xQ߅<7A'Qnn7͞SxwGND`o+j:RTzלFZ;ҡ)Gbr=8[;A.)/'喖9pyge|ߺ297 כne2'!>|MPVp\t+++-7bts5amm dT㍴#`iiIIR n)ŰjSO6ųgϜaccbqqe~~"PD5FD"dcׯjOz% |'r^a<ř#~O\xj=rl D MP.9?+#P'X,xLGC5WnN٬*j#?Me(E;-UQnȞR8X_,~ol6H$r|>rykk+p8D6-yjzjMp[ޗ_!P(8ʞڱ IDAT ndĿ"cׯb |zog~AKřA^C?rjJ5=ABp"mg'z~evQ\nJ ~ttأM˹$8_&^,7ߓ}B!dLSkSbGخAZN9{~ $czu:-(i5-+"=O}g5[!ֺt@w7yG y?7 n赻,lTN1\kX9V[?wm숫6"]9otr>LȰ7ը d2 NF0{'eߠu(Rm Şݨjo|럽3"yii~Ĺ4,qڟZZ}6wܷB|؈C{Fף˨>ΥJZH$bAA?? jaB?BS4ݱ-e(BkJ" }(EfJQԛ)ºnScT2)Eu݂5 ?(rq7֚E(7͊ZϭmJQ~N}SȻ EM*Y%mzføyy [pvu#& ib{en69׻/_+u^n?emO bX)Sa~׽>j[N PM1'H@UUTc2 ]ZjH$q~&u a/D/~< !2P&0tgrL3jZ2 . L8K2p:fmki{E:0NQ;f g\0af@))ߜON9sw/>!Jv]yGl9y/׌NNwzhs|F*azu*^9]gl 䛠1"蚃nhHw%`PGGGM7y^sc~aGzmO bzZE2bcdKiOBxT%jQo~eTvQ|@~a/B/~6u: !2P&c|(#:j=rIX|}у" NJH"CV` <vL悉 &>rR!OuoIv~ 0{{wgy~qf2s<;/>ile̜iwy!˸Wq2ςiˤu3'"W۝upurY:g<Gt_FJnvG. uT2tބ*a>?ߖ#k8GuC{VZ}m~߸B 45\jvWBRs6xmYL&7zMT>^ui'-IzaכٱXLlV(Lob1Uv x<~ja۸9m_sv{{M?'9۹zT*3=F VVV:Bt:צ UUMӔeYT*3{,e{h>hg>qsےC:ai{egq2ςqoqѴ`0fsb3dOgZ 7Ӽ_xӡK^\۴v'QE^DN/D6_ j軣PTRG()E-U8^}{>o7n;wg* ?Yt\u"刻W"{}֥V<*U~܃9-iwC 7$*G0_"y/wnВ}V߾;z"M5Wo@Z[[S.S.S^eY2 Cx7J[R)=}_˗Z__x֖ Ðizx<޷ZR(Ç] P"eŢrݻBWS?idԽ{puu5y6v{~AhhuuU?V.ST򃃳0q_|T*gϞiXgBT/˧R9|9~wI>W<׳gTǵϯT*Z^^V.eY~h⾵y^!8WFwVǨ,q|A0{1"{5o4ZhMSs;޸K6nwő/"4rВᛳCZh{'T 8>o7n;w/ \bثCC']GHUwa?h1p>yQh5$$>kIggzOj~Ӕak w@uNɭTn}R-x湿Ϲt:ב܊ւ[aUUݼySBAtZXLXLz];;;+h0v{~AVi{{[BAkkk~ ?qo45hR ?KXR4Sβ_F7ojeeEdRXLZM[[[,xkkKjU\NTJz]RI;;;'^y^!˸WFwVը,qFIM>fKHRK>Sz>2kM5o4}Ug>t8hnmWX$I=~XeO2EO>ayf}~A>fui$?|oߎڼۏsá+CgZ5/E稻d7MEJ3]nc\q,:C-3 r9I:J}>f 0 3ɭ7-Ώqǐ:.<2VRK'QX (dA|qn|S=gZEDzA?ammMDߏs{{;= 8NUU*E>>*!I-IS˃֥+{|mc޾};k'\pAA 0\pAA 0\pAA 0\pAA 0\pAA 0\pAA 0\pAA 0\pA 0j4t:?~zki&4>.kyyYIңGJP&$EOm׭[Nm={}˲TKJ%Uվ1yb Ð$5 UUEj˝;wڛH$T(cywpprRHb1lj,Kӟ&A(28x٬LT2T<W^W^WTn ʸ>\NKKKܬ*;ܾ}[BA:p>gYe2%Ib1qYZAp#0LP$œF;J<W<W*R.;t:5\.7T< 4LT"|4YK,Ɔ a2 CLf4k/LF3sݻzd2d2r{n !F`t p t휶J" BjڳsK$]Wz/j~,ӟ腎Ak?t:g^O N{~/ÎxzҸC{㰲іJ>4U4/^_-ITJ|>0&fY"zA~}aT*d2 I9m:88B8rx[YYK&ɮ㶶%Xe͛y_m_"T*  _]=X=^UL&B㕶L&;r_\.ˠwZqܿ_r+n_4M`HL^˲,X,4''$˗ߗV/&tD;JV|{wK$jsN KжWjꪊiϳ/<ܪcV;˲:nY_Fh4*B#^ȘdPR×KxKݶRev΂WEw{>Hd2d2y4%Htγ||N/3%H,V.†t:*'^|´/w,z&i,h,kkz`Ao?!^<Ǐ7Ә{ r|~~$O׳٬ִ_~o?|`` %WZ"TYkY*2N-g)H4͎xh7fa=~bGxUT*:\.\.ze~g4gP28_|*bسL*JueY1j,/im_5X[i r&D;ٳgӳgϴNz~c|muY[[ VWW8{ѣG65y2pP-kyyYkkk#0'-^O-J~uZ{uY`YܹU;hLJER~~cRT`asP1?Q!?Kö{Z7u-..믿֝;wnǃ%R+'rϰ"NiXTPҒrT;R!m^˗/.a;W/' 7։Dh4]%IV*ىD$i eq8X,6UF_रOk8jUI\.s[ nݺ[n ɤ 2^(J>~= ӴUjkko;yU䬷7lTZՎyf~~iwiv+^;~N0~{Ck,RR'LZ_4͞iO d;/8{PU/_>f~~iZe2Ht\'TpwZPb#Ե2;;;{nǟq`X,y---uTř7 e:~OMӧOff埇_%J?O&zљw5;P(_[ub|7l6+4{.o}|}h4^v}hawݻ0| NŴҳ?0h4>D28hiiɿn LT^ﺞjjJ_{=?0mo߰K#Jޘ{^[TfG:R ۿJh4:^?_5{^,cԠ9k˲Nz~Z]]ښ:¿^o u7~s=\,kqeq{66648+L9~RixZԘKn?\LJvǫ3J-Rz|>CehZj{{ZyơZІa(bq`<, 4M}q,򏵳3Cgyh֭[Rއ ,RV ;6޼yS|czb3IeY}=L_ԒO?S/[Hg]yX{b  .`   .` tΓOvOE-Gi'.dWNsM'sioo{.3dNO>u-yiy%IqIRX:p_y b>zۏs%<֥$В.N\,Gi+>1m9W9W=H9^_쬭捦"FzbJEXLd`8%I=|PTU1VVV$l6+4]J(JZ]]Ӂ b1-//+Nt\iC9ąҼto?|{n~TsW!KGΗl??u"5oMSscw^[[it'pz,R^/휶D"!IVt9^'-+녿_Z,Nt,%0]6mIn ;h9JRd/H07!_˒@[ݲ,:K*$)=[W IDAT}|6U*eY{nG+`WD0&,8r9Wr!}ix/|b塳^QKF~uYDv;E=G+_ՙwGM[sksyͭmߣ "SkODW{o~ޭSg-_595i!mў4.)J oHϗzkxo F׈;̽ H$r2MN岊ʫql6QU*XDBi*N0 !˲TT*Vx<޹sGjU|^\5YrvO>a믵B 0Nq}{Rܹb1UUϕtoooCGXL|{Ij4j*}y3iii?^^WX;?>믕L&L&%fg{Y}=>1jN:?y_d'Nc4 e2s}WqyqMreݾ}[B{at6c"In-$]tܫ2,zaڼoپgpv  ;'eCw 'ZhI7MYq>~_/Gq*ÅC>omh*<ܵTᏇ+ŖZ^ $lw}5RҒ9@:ښ$L˲d}}} L͛7drz]ގivK<Ɔ2al< TJBAtZwF3ښ 4H$%bSUVDq|Q2MSd>ov'՛TJTJLF?~TogFh4:0 ym>1I;?4θC,UX,?\.sy_Fg\:ޗw."`L$!ED wVGGHΗK{: FJEtVp65J۳4vokUHsû֥GwG08k~Ӕ.K?wͥfY['*h[Z~p/WUG^DtoG~`}Zsks]c1hye/x64gknZ8mڊ"__6-nnP((Rh}}c_,cvtU)j5mooK_O*:侁DT;σJұg牷Dh>y$4椼שV=Ǿ54ƽ9qZ@b< ;&iIK$v׽+o ˲fzg?u/A3|@ӛ\^f0ɫ:LΗ7-7pGﱓCz,g|js Ԡe{_s?,<޻KgXޒ֡B+Яg{C=&d2ܥcKI']T z1l;σ^GVՎJ},KP{z#{/byIJޘRm5^e"8 ʰl4긏+>BH:/sy!nj%11-۴G'o҇2nһwJW@78; \CBj]na˸w w"j~.~ȁqq"{ ۋ]Grb~4/B4T*OZR˗= m;i_~=a5iNs~Nz_uKeu DPsx^AW{i῭˭;87L#ȝ_N.ukl9vUHѿEeI/ًYKjhs`j+Ct8Ç?>,F0'NhypR_A<ɸYvM ---4M)zUc>ooP?zKL5՟AӼ/YyU2 Ctk]o ؜+:FUO]kZZ3OCnd}tRkGX;fwv8rt셖V!s_^K,ܾO ζ497ν%$Gڛ/L;~3 fu{UӸ~h}}]J&~ťaz_gظ4vÄYwVyKޖqivC{ݯ'Ϗz_>y0My]cϏ/zӶO{N۴#:8%o~e&n9O~_ګN?^i8Nc|',U/蒤ȯ=Ὂ~abNXΗg*pVzɾj3_ff{B ع>(z\LrYf~ ڥǏdI JT;Ϡ7^NǻwZPS}ް$Kz> qeVZ֭[]_Kے\.w.>`Y/A̳a>&_xqûZZ:Cl2sDzzGu^~[N`e;CoBaȵks|t[RK#H rךj.5UwO5aNb_#L_;s@׫<Ӵ-˲dƝi_K4́o5 vUb1eYmllt|{5NwŴg/]P?z82LǼb}$X,2gV{:|>l6tz-M;igfeeMt:폧7VAfYYޗN6/t;^黻}qmlltcɤ=z43s'4N1C{clm7]=RUSz{A~܃9p$۴e[|/{4w}W9w_ ´99ВKWO2g%<捦lv>| Rݷq,Zoj~^XKq VdoesRۖ~?~>6on@}<i888֔TeY P<? RoVTJO>|;%0d?~+VT*d2zaW߿B 0H$l?Ѡ9JqT*-//+ɲ,R)InNY{޽{* ~jeݻw繕J%?j7m榾 R)={ڏkqu~s+^?G=,K : ;ȋB!Ы" D4VA^uQOej^on$rPp&7'Q9/zRŠ3ڷZu~H)ڭ?ܱ~hx^DG~\j ?xq#\qGyj7oP((N+)^kgg"wjeeEt3UeeY%I!˲jڳݻr2 CXLjU;;;jd22 CtLd g֖ժrRJvvv.9θ5o{<wbQeJdY*P`FQ4A߬v}xk^XV2!VЭ[fe?PA!q+*py&I,˒i}y?0$}S;Zq浦7>*t>sáEGsks+O>ay]K W$ITۮǼ}vצᏇC~?4D6m5i$+E@ Ϲ{Eџgns',֥O Q E@ Yޜ<_¿Oo/ȋ>ࢠ .*L'?|B'\~N.`  G;}VU{h^k퓷z=uuۮ?ͥi.5n'|ldّ^#kooO=:O>ޞGiooOtz??6XTsCw666/<HպRFSΗ>S;Ny[ -\qd{a{іsՑspR""{o쬭捦"Fzb@J; P<S0sbNu w=LL&CIR^W^f@ zRAВm9ӼrGmp+q?|k~Ts7p Isut|_'Q459& q]뵵59kXz:4g70 Gϳ&9irbu-``؋U%sӹB'VJRQIH,:j>oȯ5o4eR hwwWtI~H$$Iju =\x52hW+I"%T!ބ~.KW6ol˲ zq9Zh+5X!yݑlڜ"/"j^s+%_#¯=k/rهz#ݠJK--_}8ێ~ x(KGѿp=4hwő.pUީym8|Hv3l-߹ڟAy$>I׈{,:R{moou7MS~R,R\FcLT:a2 CeVT* [YYQ.ӝ;wTV:^c}}ҭDB\NiW^W\VXVO:V>W2VLnnn]"vP&w9lVdRx\z]RI;;;mT=R*xֺ* 5 ۤ󴯇q[yKR>*JDzH$zY}=g۟_+LtzݞoYtt~=o_A"?/Uھmv sZq>'#礼]7ýwNR#=7{m+J))N͛]c.C9x\LFLFitq?4^0 e2i)ǵ,KahyyYXoNU(TUוJdd?wwws---Iq0  ٷ>i4qϯX,4MwyĒčFMa(=rZ^^:=yŴqx鬈m^kY2Yptv_=UWm'98_:j]ju}vz{G{oW!uyRK#??F޽G?*j*QsR~΂VH-'~^`gv:yUnt$\r=Y^^$l4TTjɤ֔df^~n޼Z?v&DbWer>+ {) H$c?+$)(uC:ܪG4U׵<iyyY\N+++C־j2ǏUׇd~Nzժ֧d2W56=zHx\[[[H8Y̳eR)uݹsǿyiT*}gK6y< AD*sÊWjVGv9=5p5soeïAUބ{֥_M}?BoB}íW$Ҽ'o[>8t.E4:?R5l7%ÍFWrhggJVi{{[j~RTG^PP<WRzWӷRRײ*~;h4WX,WSFuYձ|.f7~8:ogI]KWU/ޒj=.`WOCWEK'Y}y\%pn!p;N~Η}QՋpc1KO\qFAAU9XVeY$Z˗>T*/D˜Q ߼%dD`gPx 4HR= cγ^̃IimezJ~c~/u4&f_eZ܀h?wl?K^{et{ ~?sw@w,|?nZhڻ}>&H$ґ"{>4`/:#w?efI^+0Ǥir9%Ib1Iy\k B_ޏJEeu-ݾ/B?zzaE٦i`:acY;a i~{ s"JRzժ*^|y! `Lߎe}χ6m/ Ukl IDAT )",g[ϒ>#EP}ًYKjhs5`o߾/[lYFG2̲ǗBn" Fj*4;$?$'裆옞bT*l6۵$E::6(55e)uF7oP(hiiIis^k}}s 0\q7h޺: xo{U踡=-,#cy-P-ZhYp rg[ /ګْɤ޿cK? L{U*~M埥ye-//wT\7(&$׵d2鯨`>|YY {cl5 rš7m=p#{e=CC?|6wrO-1~*zi~rսޒťR+myPFiRchoJ3v}OS{"LoI~Uq5Ayngy{[&zRZM;;;~%G0%u厃-l/S?]x`oW=|YN=(tzgy^ZhR\uo"*4U0 j~DK=eYVǾ'-C|tr6= Uc3W/:{U S59 z{~RϹ\^8+i3{ۗfF˗/#ؼJV׺wGtܯ6ڣ={VZt.ne416m?P`3hᏇ7͎йy9TŬ_|b1eYmllzN;B|>?^8JLҟӾ=jzT*%4eY*S&i_ӘgFWVV:%N yeٮHC7ɰ0yv#5_5+3/Y{RO~܃9p䆪Va QOyU7/I=`E^Dt#cN?,'{˧$sQtY:|{Γ^6>"=?%wi7n@*aɑrDΗlwiA.˟[zV%~~IO}ڦdRI~R>}/?K|ݻ{P(t=-J z͎VUU*e2=|Pz]e0 qݿ_BAa(HVWW\.\.u IZvcRX=%0d?~[<ubQ|^x\Ϟ=S^W,S<榖z\.'bĪQs$W*=L}ĸO<_|T*gϞi ݻZ/J#DWZS̭ЌUBKUGr0VCs3W!E9ՠ 4`[ 0`/ȯ?sG>-{vP*z꼚5\q2{ 7Hqk}έ'SOo}w$WF":‡\uCC}ŹIy`wʊHz^X^{^T** JR,KrY=w*+0 b1UUV)0 j7oP((N+)^kggǯ; \NRۭ\.+*L0 Y}Uվh4yVVVL&Tմ%˲ eYLaqs$W,xq }4YiiQEY_*Ja3@ IjIҧ~Joךjh*$rͭ) `p1%I=~XeOI=>1o߾뵩ι Wr+X1QS稻T7͡ső(&W}`x9\qiOzjs',֥OC- p^%I`f 0p}=˷+⍼H/sp1)HoooL0`$tZx\z]RI[[[t 30?Ot3)  .`|ޭ'oe_~浦>ywkЀ. }Os9}wOʹzKͱ N_~E{{{ʅ9X,6s#&G6_΃Yޜhfށ {c`=zH{{{Jӌ3f5]~\tDֺRFSΗ>:dLa?Do-ˣsőm }gE[UG^KÊ#ENSjh*kD7!@d2JyŴt:ׯ3LARߔ2 Cx(I߿]: dYd2x$}Bd?Qo+sFz.k/]q+|jՒ;>o>q?Hv3k-_:_%$55ռTyc9峸&c57g弽=O5բ#D"gϞu}kG)JΝ;]ijmmM]of{믕L&L&%o~onn\*H(4M?**loVPxauqΧX,\.%ᷱX,$ŔN5 j5d/҇}d,RVK镕b1UUǔtiT*ʸ3?>}*0_kiiIBAa^T*iggg5$sm<}Y\/Z\\ ;{ضt?"e`bfs&x[՝H4`$x3Mdnך$p Ud lwHekI Eb_ЇIђ $խl"NCӴk$n麎L&\ֺ(Xy?#yE5?|&-oO~}FP@VtNb\*2~y}9os="dZP&6,Oԋ{'TCuഫ57,3WL4pt ~ +cy|u-,W`: *{m$l ᭟e{.~b?0凉ηv%]8@|i68::xxT3p6lBJ:$677>kbEQz5 BD"kFG[Dqq;AQR)R)ilooj|&⸰vEQMGѷ"mE/DXYYBR) l6mƈ)u}ƛ~3>7WT*|>MpK Ǟ1߃[}+W(y6bM7Q9']wמ˵=?n>롯QD+ZN|lTוzaL:>_TݨGA_Xq}A8o[,rCACX/Ҭ`oox9dUUǏGQ_߃#?6r>NzDȴLw<:D${FZo0755%`0{G{D2"#Cռez2Vglx _[})}5 HH67m8ל6Xke'j/ni [w9^-,>\ g1Ƕg{e{爝2^2Sӭ˚^] a|!.k/_xߴ][ϖҩW /fߧOBQܾ4=/ct'Exh4Pd'u7qwޅ0 ^ ,z6Qeئ,\W#?uׇYg|(eQ^g})4{AwKfy랈iZϽx2%YTGx͆~ץsGT|iw8/zJ$u;wj3+J$,#_ćzIvN%/w8޽{Bo*\só8x3X^ț Ŕr)t?$\.6r>(jRt颕'4X^mLj^~|||6 .F!+ 4[ؽ}J}Ckcl62 =a=ݎ[׽Fث}X{FuqD³K !fyhÄ^, GGG}_dtr0zr> &,X 9>Wvsӹ}#v &+7mw]cc\afa{t3^#9Ml[^gk͂ v =!q ^6Zk c !@!B|ggߌI$TT~{YUվm.bS'!Jjx* DݛZzil6d21fÞӚEQĞ `'hw0Fp7VVVzYww >O>jn1:Q/}XׇHseףqn?/iإVhnGAy?Q,~"gЦiTUa_a+Cz{! {XύQ{|_[BAFgW0lCAa'`pv2>,Kٔ Ӟ~Ƌ@06> ^?g>L{\a%PGslk!d~ӷaz 0Mn?o3;lbss|u|1 ;;;S]f)r4͎ a([isVֳA}0q.vׂ~넢(#ŕQbSs2+Q1Qo>1ø;}]&:t]9(su>ʻSP.JdzBBO#ĠPσ>>FT۷P.DT*=ϒڠ9*h~{ϣ='AvDعɤ1wttGGl]w'F;4Om W}|}~}]AR-?jL|וYFxc닮C!=Ÿw1 yGaߗق?#?0a"B'[VB_[=y7m._a0-<3!q=l}j8Bfޛ2~ln%d|?6V=?#B*芚YK، g7 q:}:3gyae/AwQr}zu?]xt ]_,/{ 4 T hV&q5p\}Ѥ|[Bƅ9o2W+Zm`م⒛Xt*aZ?\QU\oör9 ,G揦"tÅ_h:Įa?|劔翞{mduyȰtǖrEB9_ʡ{akP 纃yJ$,?dz\aߴa}m!ˇn8k !~Q?;K&er9(a H@QP(鰽bl6l6 0h4*EY.f?#{oMo9v{{#.nܸT*oW #UUQ(?{.Ol_&Q%J:j4?~3.UU2|UOAVCP@6EDܣ#JJT ϟ?`߼y|t]G:^|oZ xv]w ]ױwM sxRTG]fm 2>A1߿x} c|N}?1uw^aFz>V %^?AZNsgg{{{:h7.+@6&/l<2I ]y˄t=/Ine ZFl;+9_Nc)OUP¤|ŐKEX/-Xm Wp{zl ݇'XmzaKtg*{8|c\/zK6>9CEq镄ۯO7W];H$%lbss[[[H&H$8>>Ɠ'Oh4B&&<4MC"@"a(JCߐFCUU!rHP+6ıt< 7Mܿ\#Jhh*>rFdzjUKԈeYD"zRci MӦqgF\^G6E*aT*(J}7 Ú4M9=Aݻw`vwwCHePO aޯF~]mooZ"xX+z_2ef=2 t]6 c`.s 2>0Q/aI'Xw~7~VukP|./{ x~ 677Q(iw0<,zyGޗvE _|Aث3΀/~z'0o0?#"w:nc5= !ωϟCUUlnn2tڌL&=۷o BhO rBȘŵU><7>|unz2r>VW\giqCn5{ՆnC:(B! kB=MVB!A9^p;<*Ӟ],m ;=" t8ğŧB!ݻwQV;d2\.Bd2IBf 9 g<,;^>\@t*ў]H+B!M6E>GрaP˽V.#B!Wb/& `Bȕ^syc1H|_B!MTiPUT FGGG(888!2MӠ( @R'OhB!b zB!B!B!Bȴχk˫;|y]o>|LH!B!B!B!W B!B!B!rEL!B!B!B!W c#><k}>c# 5g.>^^3s!|hGqxxClmm]%r8<<ӧO9@>B8fO2d2X,rxB!dq90oOګ6,݂t(Az7k݂f^,;3@z'Aʐыr5+ccB~)#>CH&x10 {I$( 4 ofgsB+B!L ;!vJA.(βK–7bri~k¹z5NcV k GG>ah?8`!lP.sڦ*٬/qh0 p|&p>4+/B!W ;Yqī2+Fz\{Z{݆92;&,BqzB>+VVVzh4 |`BfqB!\L!t7gRjGP\q?GAz-KŎ |VrF /B!B!>;# l^aprܼ9OCic,Bqk-NZ?prW~ m<&5 - +I%ğ/><=8o/oڈ}ǰh| k[nVm`m/ijޠun1K VStɤsy˄yDŽJ⯽*WFv9c^~)sk\k!W=~!~>}T*{x꺎b#|}oL&L&CC BuO4 jrfݻw;WUɓ'=eu_{H$fUU:偞8AH$iW^1**ʥv-dYor9dYFcq>H$Pױ R R6{}^Jz-OnCR EQ|:k sM&#io _½!B (@X'NcKrv_aO8ț,;iWkn8],+gh1| 5Vr:6Z[Xe{3urU>Hb?R!\zm#ke\{P=lWƋ\Ph~b80I.wKErUi68::*E TfY 0J:$677njbEQz5 BD"ѱjFG[Rݾ~ǎ"HѣGe)T*T*t:P^^Mqam/Ax[UUNjh9" lT*#R) uwجuSttf& CPs~Cq~ף g|Nu'wpp}𳱱V}瑮^Ĝu}`=[M2>^W&/rCACX~WVVEQ#'~u,<3o\Λzi߿8 !BC"y(ud`ߴan yj~kK/☹a퉿rEFYyk6~{ :\W|^v5uռ B!2@GEo_`uC|]|frS镄z@_=aS:w8Ǽ {t{:ϛ1,ǏFxC(Oz5}{/ҿcp6zAcx$eó+2'&Fp!)нxrrr J>(j҂R4vxi!B' Y׽MaEL=JǗn".*z> X[ؽ}J}W\<庻az7+=zIg;,({lzb?!Fأ7Hxmf4pAחM:>`"!(}l [~caDu]=}@7B!0ޤ#+4w'ڍEM?ٖD9Ä͋0}<=[:~0w;^DhB/ʀtbgQy{Ǔa^BSI2\YYNlrw^%DλF#V9J "&qF(bʬp7ސ8m$~ ^8H)/Hx?I.~ot=ger }{=D!œ2x"0!>#Dߣ_~{ ʠqVh4(w !BՀ!I`5 nBdwsӹ}# &+7|ow]cc\aa;v3^#9Ml[^gk͂ v:Xe-au rz(K\g!dzv͟D"jbsPN6ڷ-p7sR?zZ7ǒ°K}-z^Z4dY$Ɏ1|[09/Aoz sxCVC ooܸӧOR032Iߟx9cu]6MӠ* m}/>wXXQ^'7  B!dLK # x<+ rݡ ^K\?OvF% ApiO?E WdMX`*> K&;g355ݞ 3k؈au>~]l6|> m=&eYz-fc#=H~6S8 ;^}(F[igaz5MuޑsP(H}R}9U޴<'rT*L&zazy~s kE*+"xB!2;P&WmO=ޑ V|yh嵋^RnbžĠ1˻~0CA7:$![vx:B!hߐlB5q6Y';;;A2<UUǏ?yUKT$IO<|AGDޥ7*|Q߼gj 36?HrxF]eCPA9Hy~:6ohk^!B&W]/JPۿ+i}[>rNP-?K'8^&k]pxk}x?xǽ}sBpyN!1aLl6d9#ؤ+.,R oB eЧJG,oy¶Ө˻,76[rX? s0ulѰ{#]/B!CUgDt f7LDdkÊXrk˳ S[ {ywu+F"Գ[\Yβx(bv'Bl^Ia"Bf2_Ǐ22Jx9Ei=߷6[iPǨ5ͨpao`-=q9:n=ǝ~ agA;i u*~NCh 9zsK A"s*ۮ~k4aulQDPh4 !B|BFxHkzsA'//>yն~hsֺ9Nr=sc2!7x[k;W{k[0+X<UOB\c7w:} mkkg#Tur ZQ7wÎm6V]4M귿]r2L=4MAQqviZy"֖FӠ  7t]G6 u>A9z{ۅ~|㞗2 =zeya]WPaRt]G@V Mcskkk<~c6tG}޽ `xg޿B!'L|#a\1v.ɤwm֓Fӟh9PU iL!2cŵU><7>|unz2rޓ y+ X,7rE U9v ث6uҡDB!" ROBžg IDAT+!B!$8 sU1;  [pÍ5gTB!wEZP$r楞DE2L!BȜ@9gpƟ?Yv\wo@t:*.Z^!rufh40 x9!r^z2m"VVVJ&B!L +zGNc&B%J4MHRh48::B\IȌiEaT*x B!BȌ_ЋB!B!B!B>_\[^sz~_fIB!B!B!B"P&B!B!B!+`B!B!B!B"iB柏ŏp;X(.@~-l=?C$B- ;jofP\q?[:>,;B!B!B 0 l^aprKCiG8,z=?\s`~k¾y/@1 /Z`mXWm` +K-}K6\sC:kmXhSh`+,X.@z-!9aza^OapNc޸y\! ,t]rjrfjy# LBQJRԷMӠ*TUE1* l6{^#!vcgg'''-H yufcTUT*Kir$^cww74ϡ*lll CUՙ>}T*{akk Dz;;;^P*P*w"w|*;>Ǔ'OBAgG!B!`kÂqŮة+b ^R{翜wK=s:@=l{U+ ,oɭ}!:pe5Wzh1| jٰ2[i uVsBB !x犽}!X,BQh4* @a9 ÀaPU|cssGfe( 44t]KEQ#i"NCUG!JRu$ɁԼ%x4 |k_*ү}Ar^yGGGHR4 ߿t{)X,zcDu Jy, 8>>4Dbl&~ָ2>?B!B!$,(@sK^6̍ѹK0\w;aS栰yTc1,mӜk3C Co ,,vx#X˶'g-퇕{ܫlx _[CzNʼ870`;- M8ㅓN% нj!Dʊ'ev1\ wBumOJ$( fvqfT*O2DXD:F&wAQlnnvbL&41 J0 ܻwsm%^}VVVUU1~S.}̺eKn~[/CjKCVxMAzNscTn>ó8xK Wd,n/NM셍"E <EAVNR*BM$cBFGXzJoce8T*S. \ݟE}ϖd; WjaͦW?*2z3AYݯ=?B!B!$l( .Do^ ~ ):~fW^ƒy\on䗽ybrpzN</$6|ӱ1x{՞X|^؄2MGܠ\aNc B7oQBz!7n-͓]jz [h4(x٨Fǘo} NkM{\ObO?B!B &,X NK+K0u@GH%O$ኂβŏ}#~Yp}:ﰽ}DG!E(y߇rGkkB-72$ /봅QeWzikiw!4 ldE2rR?zZ7o ,^xi)[ǠΆa@QӖǙzG!B! `_Z^x^]30z6.n/ºeڂn{!|c1K$[4>Ko\]8[6(A(9Ofzl*pt`h¼c-{}t52{ȅwBRei "b^MZd2BTUV:(cTyt޼y3v cDI?hEQh4:FmϨ;/#JQ^B!B  7 k\s;'D2[C3oC='[& GX,O8>[-O ka bgVo;-K0)B ҫ!mYn}V{k[0v+X?2h NckkGu\n9DNM]ׇ CfǏx& d2yJrq X{0T~j-XU+$zʇp;w<]_[G<;+fǟ\[1BNNNbl6l6 0h4*EDAT*|wHRx͛7'O*t]ޞW(=:j4?~S CUU\j~OUUQ(?m[RyK%Jj ,RRRyguS.f?#{^r'uE1!B!0L"[&,N}v5R{"Lث6/78Թq\oA^>\҂aޖpǦ5F ێ劗Ηn3#Q_]5\auE9C=wWlwL wqݎGz%1/!dD>iH$H$0 RS4MDAlooZ" LBUU4 ^{cϟf*:JN*4MO5*2׮T*FZ60%O<7>|unzrܻH$,cFdq}[05{Նn N!B!B! |ثcv{0#@sAY!C?B!B!B!3 LG}6һrʯe5mN!B!B!|UB!B!B!B&B!}6@!B!KB!B!B!rEL!B!B!B!W B!B!B!rELCsüm‡g`S/0= !\-?C$Ir8<<ӧOGO&Zy$L&Cũ1vaA։i:xe{B!B8M@HH$8KW K J Z`ٰWOv9w PhU2;&2bcpBHZTU(H$P(in߾͎]|يGB!BHp(2]}9uʶռz_^NoM8]aUUa* JRP~kGu|wHRh4VGGGSw"w|jy"$kr9 jpAǘ)נ_5&%H bccz)Sך=oooR,+ LBQSR)ܻw[[[H$A.C6J%JPƋ(oA2D.C2u Eg]ۦ^b|AB!2_P&Xr;gnnW K'O኷1` ^.X{ȣۍ +cy:X M0Y? B{Mp1"hyl )f4 }ŏ#ߩTj0iy-Ǵ&~N\u} +++ۃ(^MUU㡢~k0٤$ >>ţGNݻua`{{A ,zD/?K 힯TӴ8x) '^PU} .MFMݯ=[?N!B/@X,` ^IXmG(c/\sTz'A> Vz%y/愍?s/^f\s>>xނjTͦWN?A07Gwn? j5<BP3vvvh4'%DYa27?(u"2_QAח@Qz>PZNNNP.L'nD=geN !B!CBksA)^zrʯYm azJ߆eO'*BLƼUɄ\!ȇM!$zם2o޼+ϳ^h@Q//bXu{`BlߎXo"r mگo0 <1F_9JzG5wQۯݞX_/&CUz\w&>yuB!B!ok' kYt u?vi4gqw۾Iue붟Ğ' n[h۾~"8 !d^I$^^A04MC6E288t{x À(PUNAԾa]eNNN{iPUaf!_ ~G(7:<}th/--DM a {<;;꼟u0~6~'B!D`v_aaӶsU^A狥O;Kx ɞ1$U>|фy[{2{'+vDNLj6X*]H Q.s\.#J!AVByB6g$akQOEQFqY_a͜x'㮻Q|y;~'B!D`vQԹ-ګ'VG}:f|s!bDyð/ ,[;e{\Ku!2o`'Ed2m?x#~ooo9Fmr{CQިz|WjBt_Rwx8i,'2l.#6M{\zO2/D=^, IDAT`u~B!BL|{ߖu"?t(}Kk:a0ٻ6<}OUIvh[\}X a`ؓHlzȰ"{NtYf\:C}HdJݙYE:, c˰]dgp;,YKefbY}ߪ]H#7ރXe;q _9t V{[6k<44M,(J-[w ƽnV{# {^|9-=_szqԄ"p5?aU/ks=e9Np;ĭnZn˺bڟAT[γ^7,MDDGP(Dן l\۽GUUȲJRobu{U\? *wd2U6 _̱X5ƽ~ ^sN}ටzJ~uψx/:A~3>8ef!4LWQ儶՛Ճj6uŪ;=bø,clicV۠Tx#@z{5[κk6wg/Cx#@|)zщytgIx?e֍_7[y^T*㘙i\4R/UU<`ffƫk~<;n$[4?T{!Tm{nHښc/A|jS =7s#A4T*J@wslff1Kb{{ۛ333u᪪x$t a`$A"y1a%D/kLRu3JuoA~3>L}DQ S3ajS_: /tI$/M'TValu}0+a\3`j0Px- б^aRQ{_[ G{ kٷm +ORC> SyzvD6,$$t]GR(erRx<4ݻHPM.Jd2H&T*^}6t]{c~~c?ul6r|>ׯ#ӧr똛 \.d2\.׶7{{o #Z4Mu|>ߴ/q_jtbBe rAn=|@4,,,x}S{A=_G8Kω^nR)Ȳo#@e#t駟BedY躎h4I躎\.M~~]׽U* vx3&''( .^/bee}] }\xmw CCCxw>U5:>SNqA6wn/hZ;~%z]ヒIׯ#<|炚GAQ lllD"|vuee/M?ϗ u$.^%uł=byl- YNDDtDQ瘪PJDDDDDDDaLgޅry&n[[z%DDD,G/,֭[r &"""""" Y:<>|N9dYB_u\KKK""""""lpUDDDDDDDDDDDDDDGG O{޳D`LDDDDDDDDDDDDDtF0&""""""""""""":#݆isyޝ=~}O՛3ӟ՛U.š-c<#":>}bh4T b?b_"8D"n"fgg/G= ~G-IO""""":}B/E#6Qaքj {-@ZL̈́X!n[sʄuق5a\ n a^L0^HdDDTTEQ @ڍD"d2PU| ⫯8~ Q}kbbj&@K? 49I'vp{̆ułuł{C#=`ԀÜdDDgHR?,4M;\ LBu'e3\ /'?aLDsO[ޚp[бpBpaYל2Q kʂ@-`\3`j&B y={vfۣ'? ;%'=XK:c]WBB!(A;wS,@}0?09Ɉ!VS 1 w^8JDk̂5el~vA<bJǷ1|s&̄ {̆%@Ȫ{~SބOެLgÐ^I0:= Aý{{g͒н_%@K=a]`pB_bcH/$皧,g.H&4ۻQu raǡiTU(PJkkk-+>} EQbzzt@uy,--5]o{4MPTP(0??rbXVKޭ[N^S8x$kR)d2J\cj~?_gD"H&(^r#ת gYm% DQȲ|gx1b>3 \.cnnT d@~h4T*h4 (˘onmߔ冹0;;sq{?y?m?NDDDDD `yY–8K Nx_x-<}_3>6`&L 3aº|.@v`̈́@i~0 s.vuZ{.yl'~]-n/n_>g\3n Cs.;R޹ADtYȲ R@Qd2D"/Γɤ>xx SX,t: UU7L&!$TUō7޿cؑCr3𥉉i4MkMOO@`8 ˲צ(xAϸ Y"߿_w,#!!#:BQov/W]׽1L4e{>_~zפiż~d2(X[[ db4 hHK>wm u܉taL},/BUë%E@h9(օdք?Wa]`LL-zwg c#@U߫% ˰#kfCO 1  i#@]x#`8;v-QoӆC_yD5[m?g&z l=靇>DgYQ\="A™\.P9JZۘG>XFE<G"h i{u_R`$޽L&ϸU`*&k{{VFQ,,,@kr TUmF^5ins,cnnΛc333^e3~o1zdŠ:>3M744 R)yVG<o{n݂iul A#2 $fffB/?ϗ~Ưn[Z[VZ;_2L(( ~RA?o;.L/Uė" Aayiz+$ ҳ{/E/p1z=b{ժ{}Ga`۟`O 5D/8]zu'o~;X"WU˻]޽= )/a(;S5l{6RDt*iȲRT̹nXrxʵ5,..W-LT[Nu{{kY D{_wjsf}V g*J;d{n?ԶY.ļD"^Ufma>_R5ݥ~깴\.hV;hO}{NDDDDDumubWҭzm^5[Uz%U>kvVJ{oP 8!ym/텸 .9T ք{ C Ӊ۲ÒZ*K2* dYE U詽 ,{tifcԸ)9WT{bUnuj]<W娸}?Lp_k5A>ݥ 6(A; &쑃Pefžj϶أm'Եl}f^? 4{V/ncMO{!%HŃٜ2Q {2|HۗUӎH&Fu /e4S?veyPn`8Ʀ]U_?ǠsV{# Ksxq1 2h8}X~}ҟߏ1&j^-gVlCc||=_{'3Oު?:RQ kF7wI݆.wOLޮB2ګ hynq? V{4y힧,ø|9 ̣/y/ ~?iQ; `6GCRk:cBPk{NUA~ϷNz&pyN'w{#,.9mٰƬ?" H$uHF/޽[%wm5Tu:X}U(dǽwmD_n*L}DQ Ss1aY:у0%`4P5[eԽ?uflRqp¸Kx- б^aRQ{_8 G{ kٟm +^Ӥ_B) ֕qx-xc 奎!T`]`~`B*vQxs ;5K7DDGmsslH&H&uJ@/2J8Y(jmnn 4 Buo| ƽ~ ^ҥKbo Y*V5C(MӰM| j^/>'zy}J 2躎H$Y1??L&}~?o B̂qKBdd~B!E% Wv*;ÐSuɂ [n9g#ؓ-ҿJ*~F{!9K{y޴ .#8x  MBx1 O΂=iC|%B\\8lj&ιJw۟ ?8y# <̫Nz)~+ R!oRÀW״"~5qUK1? "My #x_뺎'Oɓ'۫_ceeo߾(P(/099ׯ_c}}ܧ~ Yf:(&'':r~7 mg?t]WTl6U๾?Ϙ(x".^|w-?W(s~qEض1~; w߭ƆW׌O8QU޹/~bccj ޞw.&''_ƣGæ j^G}EQP(v.oll x=וh:7<_J&x"y&olzeeⶹpMNNB4|w='>w111H$a!bmm ~iWsp{5DDDDD('|?=a: .{{-1Cw痨Au-g\5`\3ZvBAb֔l+VS(7n?)/baaJ?!Ǒf!|h^ IDAT ?GMT|?ܻ]_fy{w[K|)"0;ْpˇL̈́}ׄkʂXѩL&4>wZw["""""""`: Kc?Bz!U[c70+`{Fh9x"":](sLUU(JP""""""03O9wfL3FdvSe+n[\z%8?8b`qqHEUUܺu\.DDDDDDD`"f߄`]`gÞ )/!T࣓_Be躎|>SYt]G.;( .\`$Qѽ?bdlS:67$""""""""""""":# Dgnƴqfz]X֑eLg?Nb_"`cEΠ>}bh4T b?K{E"#>:q """"":BO|) k&, (Bh7, k:@!$HEC0a\3 8ለNR@ev @E"d2O>qL8DDDDDDaLt }5{=XS֙VSze|ltqaKܺbbнǑI0~j@aN8"?=;; M)DHRK{.EQL&@ڣǁgMX0&O|%"!Nۖz׻(pڅc~Sބc?ެLgÐ^Iu}#xXoW-ܽ;^H5OY@<QG2i^P( a{{;4MC"@4,u|KKKMiPU@QT*!ϷA2g}rT*d2Yw@?UUE*B4eϷ=~X ~!hO7q;Ϟ>} EQbzzt鼮ׯ#RP(`~~+u?'?ɑ=[zm֭[Hu)pE<|0u^{1q """"":Sru~`kոf~n7՜v[k75ek{3az'm sRS3a\3m9,T's{w`]qbw EQǡ(J`d?*/X !6H$#/X X xli[=GVAL& zgTUb1i? j(fggǑH$VL^~,ƍ^H$ t:wz1>>(d2bu}7niJRDϹ}:==՞o/7qwicii7KR s%ɺm/`nn3n5x?czmvh4u;G~ w3& KG.<4 =wÕYYŗegwؖ %- ֞l V*r.^!{{6u3( 8px~ξU{`)^W .bwy{`j&PO޲ټN!2JХ#WXBN677JR\oy,--5T鮭aqqVbXCt~𲿛rd2 KXe/tS]:\.7f8ơyV*~wm8^mvj}.q\-0ݓ*ʮ&[&dkJs^7Vߞ=b{I/O|%lvYVլ5 j']n{ku^ i8|UDDb6:*xh\.׽‘VJR`AQgиٽxJZRX!qK.u1~͖mu}'m^w3Ϛ]_\FR,ޘ^qw۫#t4}ԏo7\|Gyل'm'Pa?VU–{vǍ>'@xM$v=)+o,:ξm~OBT BusDr("D"oԣF'@M]|UUL&Fν[G}AiXn`j AEQ)!J!ӧ((JX__oyst}5̳VHYơZ]_(y>qݷDDDDDD[m , m㪷0vCحcwԞ sk>eQ4~T`cu"Vn;n%rǐoݺ-cZT]|v|Q_Q?ڵV6q4i԰똛k.g\qCS{ u`w%?Q?N}KDDDDDDo!=bwZZ޺_u^ct5\lw}~*ROCLӾAq1֘^BDD "ȑnubO{cFQ/${nݞm NۅěѨW( ~{ptCV{jh'`uu~ﴌC>ՎCfQ%Q}KDDDDDt0ŠH/siuXΚ~6{ytL@'u& tݶ+1kaqPDu{FfMh]k09?Ky){˸fx{]fl6o J7w}l>6wg/Cx#@|)z߉ytg Lu@׭qݷy=/█0_TajN(*l9Kc60zW̗rf0Lmf_0Ns ~ܴB,XW}mׂ$ )/äc|U" : =^c0~~I  &b^bfrw fE2D2T*P,7 ky\~X O>]__\{>|EQidYnYW.Q*{.4ExmGb~~.]B,7|պl(d2}v1^qbJ%d2$IT*b1*o/Hu麎۷l}D{\d3\Ӟy>8~Ɓ輑 B̂qKB~B! K% v*WÐSuɂ [n9g#ؓ-ҿJ*ܴL௝vN*tO[%a{7BC=ꄂcφs~!9K%{y 0ۀ$/,ؓ6W"a[?N_5K5__ KPǾͫ&ėb`@DD6771<L&qE4a4 }]Cy.&''|>|;T*},{/,..{}O?,fuhu\?ϛ.o{?ϠJdٮ^__ǟgLNNBQ\xc~﷽w»[j/G~ jN('|?=a: .{{-1CwA10-;! }kBx6 +y)E7]򗈈Ə#c?7gwwױYF䓻'k^۽wk/Efgz0>6޿q`MY"_""""""""""":uPq ؚ`|֚=f;`¿ úb<GlC";N<D 3a;>+N{*OQ7ā-.Ws""""""""""":uI~uق {vPLTbx7}ODDDD''|N """""""7$""""""""""""":# t,vw3 v1ެbwyքumǝR,K$C"HW{1"TUe,JX,Sr?f!v{c60>9nքS3!E6Ĝ2a]`MX"(u~B0&k7zR*0GQȲNDd*>v~@DDDDDD`:C_ yb֔N9f57c؀=–l9Aułuł{C#=`Ԁ""{vvSj(d2 ]ǬR@ulnn3x?9Dk nB_eҫJ_sD*) KBGBq̀&*`""":={gϞ#h 0LN ۍP!T ׻_(`~`r ` 5f6a}߂ ' Ӝ2&,`iKe5f`]`g;Y+Ŷ՛Ul+ UbG![bv-I7=yJDh;{X}jy5HϤK-XoB-=;^HLY@y6>>d2 MӼ}u]GP@.viD"h4 Y:<5>>MӠ*E(T*X[[C>o[933d2> rT dsss}/|-EAX{mqq>lyUUJFrmϯ=~X ~!hWw}qܽ{c۬O*~t6% LbzzxP.ky~g}D"ey KKKXZZ: ~ """""":mSβu~`ָf~t=k5N=tg!\5M ZFYkMYu75zpl`W3a\3vؓ6) j礂]C xU4v4uy?Xk^0??_R)"8n݂iul "2 $fff²m#ohH$m+_YqƍP,H5F]׻:u麊q,,,@QLOO7\2LW*xHaTU,X]]m9x*u;XWU˻]޽=g鼄PO޲ټΡt: YQ*077l---VD* p޹9T*ekciiJwmm U5Yx/g\.P9sA]6&ps;K γ^^H:xn,}Lܥׂykj;g'" Zx<-+6}o7ԇ]͔J,tHn7W}w6;f/^JŻfZ6ܟk_m8Ə<=b{ 71og6?pYh^6aj&Iho{yͫqn_|,|x[T䶪BT sDβ(+"&x"w IDATt'}q!haRUdhܻu_>sIz4gN[T]߽/nj/Sq{ 1?#"""""":oᥟڣvwWq[;aV͵tQ. <{_=;-\7vRQ kFwMܩ bNV߻{NH]u qPoz\;fr1{?2_kmJY}-ݵ=#"""""":oomgRO [~﫽c?~I/$XSqg,-= kn/s!"6<*nubO GQ/{nҞP(@4hQ/_݄guL oj}a]AeZιE!}P=~IEnhwg6u>{RDDtloo{P{vV{v]67?o~u@?J#[9ڃvoVD#"""""":oP_ܥi1a7Ԗuł5Caicw r<>0jW HuuxaKRDDtK& p[`ۊuX'u>I jz^闻,PUuX+sq? /jChN0'F 8٪ƴ;9e˩yfzy4>{auW|?]TrM&kN09-奮]="":ʙF4R({AqBeY+\oojao2vߵ5oޣmr9L]w}w\sq?"n E 5өٯ"%'m[jT~Tnaٰ}{ݶ0ںXz%|i:!u c˨;! =k;sA^ITBnBX btngXcf=D6,$$t]GR(ecpqub1<}[jv}}sssu}!EiXXXڒeef\FTB<ǃݻHP'bY`rH&}6W.e퇟̄ A """Dd*>'qlc1C|ixלJb|lLؓ6^;uB*M:#""" LDDDDDDDDDDDD}b0ža%-ؿ+KP`Еִo}V6i nњܱRvK0Byh}/}쯯< _"%x>LqfH$t: ]ס*0 EyTնqd2DQ@T n:R(0 @Pf}s'R)Ùp`ߴݐug~42}=np~͛ rR@4dY6㘙a0 X #bvve(뺷/0ifffz9Γ"t:4a`wwpDDcnnlD"X__G8FRryỹp8%$ \5MC"iMmߗŚ\Kuu~\.CuD"b1"!͢T*\.]?ia>0ɞW)(=jl5o^Epjuח%|3⅌Θ%[[跍a G!rCiOڨC MfG&0~9nI){~v"x6t-X,7mPv7/pI "DP5cee!d2^m+333xW&IMӐL&*ݻ]aFUUdYicaa!Wne BFQr9$ RlmR(赉BMPUիz7Y\\DRi9NAUfS\.^e+;;;]g4^;&-R,kG _ŔRe~7h~oALU[߰CU>`X;j~7S~% @r{ Du)\:5v}ow4u7z1ŴJ'm8SAV\~,SF"wvv{:NӼ|@ЪtSrk}mgg6y]~밶 ~_`mTZPmvg '03x K rZQ5k Ѻa-8S/֪=unש 4ʶe8-N ~""jTU2=8hͦׯpxF*^'^<G:F4m8n]{IrL |LX ?FT^|vo0_?/50C?U>`>8&m`ƏvƝ{ۚ7-35_w.]TJ8} ٣yρ u]KWNV#v<4 a0 $ r9~bmR ǫjC|r~Sh7YOm_wY LBu/6 Mo0Yg.$"""""f ɷs>> -uI C߅*~~Xw,΄{n-c!">RUL+@rcc#8N0p}TU<~DL)OF^Æ|ovE(h4UNje| oz=aAl"""""ˏkoқu_{XsDP{ll'EĴ|iA%bX,2,[8/g8}~sðCk V!~2*zᅡ( ̏L8S}Ϋ_q ݑߏy߁=+ s j0͆ }z[~<)EMqx})pCУKwCy""\.t:t: 0PTiauuAu{ 4m`YVui ֯R$ ,//7Ç133MDY7sqquxax+ okl6ܦ]_|>t:`ffƫ- 8yAK/dUUl6{fBDDDDDt)O? 8s17 B-ֹTySO8z5{g $Cp~C)6O8cĭ<Y(pʁR:fÙr !>sv 7L8PJGT::C@~)Cy`;u˂\F= \v za?83?d2H4kMØ2 jrbBLk5VWW[X?V[zDɓ:B)ra]בZoY/Q>w~ """""fp?-K6yDŽ:k֯CjܠnѦJZRJ]jO ̶4~yN{bSg?~vft =} Δ{FmvzspGL90L7ky]w^ C کq@Bw@w38idY0Š:(fggNUUX, Y0bb۟_g<G.C8AJ!BUծEW H$%B4Tm)deF 8 IDAT6MH$uao-XMӰ|jzQVQW72q}OWzhx0)G-ӫ B:ҾoFs5EkwkM*Rޖ.{Fjo0.5?2q`цLM $w!EL8>Ne?ΔCn{[6!uz(o~;FQ ޝ-4X,7mPv7/p1i}Dt9dY<|ЫtiH&MplX a^)]ױӶrs^~3xU>JCdJԇsssm+Eb<o RwLrmVhdi5\(aFW՜ G:~~EZmh5a:^g~~@DDDDDDÃOܩ/- 7PBi(_gxC2]St]4!6O/,luv34pEqmy_֐պ\/G!hƾW^(4)m~{1m:Otؽ2ox->zoaҶoDM<*:1U*,..6R 1he~s333iͮO"h=+++ T*$-JMx\h;}ZAq>:K1 ~ """""cL}kv[ABnxoW7<%]Ag j<-'`@oj4S\ Δq]wsoת[l֧ŭťW}} wpk5ݨb54.ָT*-+gbUϯ~STǏA^U,6/U"~zו~5www[Nq?\q"謝x6S@oΘHv/gܻt ,r[bҳ>^vԪTK}Zk}3@z-v];Si{چƯU흪Ol+PqkBkG?8"vkpi-^TU[ohFgoRi\k5|LX ?FT^|x0.˗-^.漮>Nq ygho@֖?w{ok488 ΥŮ>"^WA\/ͣ5huLK)'<\/έu"-UV̄y:DD:Y&BVPT}UU8iN4Ma0 D\sss;7IZ,fffL&+sMg}? 8}41@DDDDDD|ǜ1C࣐HRzZW؞7]aYï8lr8Zڗ0s};7mL^ϡݹu:Sۧbig=awxBhnBzVU9ZH$d2b*\q>Bʽ=,..bqqhxtayyqJJ.]_Ἦ~< ~ """""n?XΨX Vޖ,Z7~hs<ޠky_FuC]y.q׋خgvz::sNƚJvO_>>V^(H$|\.cooj_5 z덞'q*۵W2677qmo頦ew?~8MPkoy],""""""<>u(ܩ^3Diؗ}nNuJ%duRist -w׋*?wi_j >k[Rp?vUN9-xvWL8Tﯛ^Pj"n5*0x2=鄁Ӄ~X,RT[(_|E`O +LmAiVon41un,kVy]g&V!xk_Gen""""""S_ pW ɚ`2;_GA+c%li Gǵ4qet΢Ѿa7Θqx0m8j8 ͏̆ҼeysOQj~x Gu)*^QҾgi ^/ 'vvo$on*{,-wڳtDQժh7Tqd2ƙ_|w 9΍ T*$ 7Guon0 b1w|o\ "nEɪd]בN_&A*jjx<"kEݴvvv~|S@w}?Bq&i8L&X,v&Y?Q/>L@DDDDDD2FA,݂[nQx뀭 }Ϋ_qMԑߏy߁=+ s j0͆ }z[~s(0~랟Q{> ya컇%({҆3Jjvӂq]דHf_-2JKsmᶅ8>y[>])*oڰ>lr>'kzݯKkȯ\~X O<.WmW(u&. Oc˗X\\ 8\.t:t: 0PTipOPZבNQ( ]>x<̌W Ⱥ[[[uD 5MC6Ńv<w\'$7"ס:8 P(t]m?Ћ|>L&p8'O0 p8d@}KKq?P -Hn!DѯFWhux5(gV#N ^bJݓo2anЋJײ{6b0~sXHo$.¼k@~-wv^/Lbx@)(- zkʖ+ey ? ~y_vńi_B[N ǜs6Y0{=V/jsssd2uX J]3c5*2 84MTUeX,ZyiÇ}OSJjR MKKKH$mccm420 {ةl6x<۷os`_q︴q\MRxwԷs4E2p8 0P.r|fmJ:Ѩ_0BޝK81@HpW0ls~yҾsӁ}n .G}!iҶyǭ ==}2?2[}ӆ}ӆoGOeK ##KDtK[SyJ'-bii{/4 Cu4ɤo]=C4hd2d?꿳 D籸xMӐN}]Ra-ˀ~^ǥqossV(-0N_KUU,--ymRD"D"4yrmω.t]%"^I~պayUdOJ:W\_# ʋܚP{چDT)0t ?XLDt BCsssC盂Nr0 VVV¼h4L&q*2$zj~ Unh\! Qq2O?=6D"0tUgmkk+"a_qq pd20D"ፋ'U*lnn"7|޽{033T* 6g<ǽ{x!Qϸ00GnUɐSyµ+>nLb)e[Rp_ZZz#A~! .,1hRbSP.UoP:Us+b_[yF/L;)P;UV~nƥBX,}axzss)L^]]EzRb* 暦.J2 ]>,٤s90?2a_3~EnТhW6D$E oüfjZmX T4uDbt:l6uǽqu,TUmxnƩ)w:V۞ÈbbH$^eP2~tiiɛ:xwwכV]Ӵ~ZLDTu8ot:]᰷F }wwr kE߿bf(JM~z#5M/`1s!H%F@{n9=Bo iJ`{]>ٟ_N=kߺJF9^os5okwk1̕"!(y[nj?`ߴa&;k~d藍S]Iudomvaݲ`ߴ>].ܠ{8Ç^x`idSE̽{*᪪fHӘ?5:KM<0_]]VTꈩOVʝ|}Q% *^UՆֵ5Ǐl6uD"ceez&%~^Na]O+Ws7`߿Qt]Nʲ^e'|p8ن{'Ju b\*fD"޸X,Ө4qY|i^VBд}.C"@*:8!*uL3Mx<{vChBE-EU7]lL>(om]]s T~-YVzտ-nϗ0韝1ǫw#ߏn&94P6Q[[יr W}CX`tajbo޼DDi4WAU?T* F%b{{埵aee;eXZZjĿwՠas pp8O)<4kTvqr/S\q0(ݎKJQu/gLƛ*9/5J2J~]֣yG~~ Ŕno?2^GQﵓm)""""S Կ Oڭέ*v_ARP۟{ G>ik_ jpUħs*ںLlU~9GF3E5XKWH$=p^{"kl˗M‚7 1Oݻr?bs2*v amm ?* zJ~u'pHDbRiYI+9 {ma;?q\wAK{{{E:F"5m^@S菏 ϪV!#?nB5Xׂܮ~e:Y7zz;-oA~!{Ab0Qޗ5fXӖ7ճuÂ3Nj{_3ᴬ?Z nrܟBۭ~xe[iۚPj׼ԅ.eЪ 7_}@zVO~8{  qqoFML}Rix.b1D"SW5J666u]gz}98M?[Κ<^eᰍ~3.iſ{Q_i2ԡWǑN׭'n$w~Z\ &o"""":_ \Ho$.ºe=m{S KB߅sʄ<Ŷ_&6w3zogGjyGRzT֊^ձl+ps`~f¼cv{!E"dxPO}hTV08^off Eɠbooa@4Ә\z"WLk1L|u~^~~ƥBL&js0't5wY?.֤LZmL{`?c^TϜcLFޗ!/cؓ6웶[:ᠶPr]W bJhy[|_֙p >(T2'm/ }BjWn@Sq魝 ]7] ƹڏo=h4)0Ś:Ԭ>HD)&e=>vkooozFUU,//#P(:Pu@?~F^æhC;81~KrDDDDq!zµϯyS ݓ7YX-`h-.^^jyjړʫA 9 IDATrS[ve8c7%OMDDŚêZFCVk O$^yVm}\5T[֌ovӣ^d8xVTU4MCP™]/w.b B/qs[]lL?]]rbgKU)*g^)[UL,ʶzv4 MD!)S0kog ؾq|T`[ڗ~zn""pD"/H=D"^[@ZOܾ}{(ɳ zh}ዸRJkGT 4Qq r0Bvϯ~lyKKKb9Wi}OHwet?EbXkU[;kkko0 3i6֍@WTP Kp7߰aݰ_[}sƃ{{<ﵦ-wL((]BDDWZ///7"Jaii\3HRM^(r7&p@V<oE<DE"g2ЙLu@RA"|S?꺎L&vA{ 岷fem*<w]v{fa;~!yܙokk XZZjh4!t]O]O37~b~~2Eϸ;,Ġaoo;;;^Է|w0b75 @Wⶼ8u&Xw,njWy[nx+eo [Y/jQ~ygW~ PUV`~d™rw^u]ǸG?ǦzniPo6_ں]RS}-nv^I= u}UDDtB4躎ueUP#Nw ]WWW4 <ZcRiND"^Y9'@wN3??r"ϟ|LpOb1<~؛˗MkR$ ,//7Ç133MDƗA;8qu W(.T75cLp&`NJAq)[yTnMړvp2Jz#5IVNM=BndQUh]5;(g n8*?[oQLw xϭ<= A~-þi r1x[Ake>ϞtG~.s_"+naabT hR`wwRc_u VJ%ܿ޶Ǹ0t *ZᰘSX܍^k#jG4(X]]ER <=;;q UUa677vQTzM{Bbp8 TU!@ub1:}>lO_qpXt JjO?T {}aF077ySg4J4 z24MC<Ai=""{ץD7* 1I + ?4TI>;l[&;&BB=wQ??=mc$7x7Q$߷_=o߾٬uS~yqzs#a2< -]{҆=mtDDDDDt5---u\{^T*`J}3G7ka0͈;)@sz:up"""""nEѮ,1r! [WR MiϞzpk*/ۜ@DDDDD`* *Wڗ .cLCUDDDDDDDDDDDDDq1L"""""""""""""K0%DGooBy'ǵFKn naQȯ{Af҄뚈X,T*Ax5-7>wȯ-T JY0P)2X'!U/1i>c5*2 84MTUeX,v|0詟l)0?3a~db#@=6.V?52 JO[4ҒVlit]888osbkwk:j GkJ5΄6:.~ϯ(|.&[I|^{6PxHDd2^P*fOuTRP(|?h"(˾%{mQVH$}MY.QT*/#VӊHH&^Uam+mAL&A:Q.[~AWe"fffuaT*5i[*iZ_|kG"}9( GˠƳ~[~gwn(JX\\677f]?C?7#δhNtց=8Zvځ34J(0 g@K)*}/gmee YlVʂ+_6VNi 1oMW{n қmkߴ:4|tΔs ;=kҾi_3Q5bs]KFG>K䉈133Š:(fgg[>`_~]AnТhW6DuE oüfjZmX T4uDbt:l6uǽqu,TUmxkƩ)w:V۞:ÈbbH$^eP2~tiiɛ:xwwכV]Ӵ~ZLDTu8oDt:텝]᰷ s.ςo{_fr\ÚvwwŐfQ*lH$uaT*x/:DDDt11s!%F({n9-Bo i*Z{>ٟ_֩!a@ju_%|s3xk֚BD/[-7Ijo0t5?2q`)ͤ.gnYw!ܡ{-}`5l*ֽoW]8~n۶3qTY}vァ݅ q633zAiH&Mz""Nc~~\J6`xuu[Q!"~>Y)wiD@׾UZmh][[C8}f=]gH{籲P7xPvX'0:_b0 Wik]] pN~.wU]4U}:SN۾mƭ>}lg/l'vuB:qiCB]zڒ.vAAȮV.gԤ vZtmO٥$P hP\HBB|hMvpf2/c'ߏ LO(q hRƮA錘y:0WB}M-fB3CXK+N-oLjxK>K @!6ojo `4qm\MV*8Pu/Զ—%~QdMF6ͺnwş$ DD U0<.%%%&V vJ??ydannCJTVV5*  KKK1o޼SJO.]~{Jj=yf0* M*=悂KM1L`/ @ i$:צqJuhEY/FexKz<P_x{"""w1)QaV,xW{gS *dY xmCU&^&yY-@gןck E?3 5~ð?7Vɪ:`NEC4igu`xAD46tٓ>v2 a00?wyGRTܼy(((@eeeiL'CHgOiTMuRǗU3>}ncÆ 9jll1U_/Y".*\3CCC.鑣=x%]gqN)CngNMDDD0)v>FL|f?nvB'i_O )CMh{Vr*YXx9i-c_O 3e~>T݌_Ǝ/bM:]MS`+* ӌ~̾讥s(لeoYVY+L(yJuubXR0T;^GP~_3`n޼ ;\ YaZŇS^9(t|v*Ki9~|}0Y QPPݎX_ܙ.LmC~qHRSϦ/]/׃p>"""pԝIE$La&iJsj|⭰=b[c`da&W@<~'+^qT9TWT|خW W[P-| )FDŋ4كyAA𰼵7oϦE0 PKZMMM\GS PA@*ȻӲb./qi666/^LZ+xqy{>Ya2_zOuE{_ܯS}=3X\~_+,LiFTb⑅2/Sa߾}bsΤw)";;AcaZqȑ!ӫ']:q`0N2S/SyU=_R/]שn޼/"˺پ};QZZ*NaMDDD3&EH+qCh26`~xy T ^T~$T IDAT7eEjq [MsIb5k,؏b~?PUӤi~}XUc,y<@.mKzAMornxeʀۚIꗌc4!tBMc]oux\kkS|9 ]兦i?k:lja-*dˈ!#QC< 7eHKdܧ}p:6xmܹS:pn~3ĉAk3.]ŋxbkA/GAA͛'_zOur_:ܯzxWpQݺv{Rhf`L9&{&Ǫx 44bnN*^T#*̮ cl@ylk*qHf,>֜0 f/yŶ0-? ՞f?0'PIq:5|@\zE5 Ӟ@ bC< UJs_sE|c#~Bݢe5$q\G@_[\L}}=Ν;XV`pptR xD V/]_|());#Qt PpXf1RX i,%}-6044M6Vmmm8x ޴iyTVV`0`0X+ATWWΟhSxH.<Ζ=Ν;aTWWT<ϦCpĸ%2>." dpn޼555Ǣ;qعs'PYY9p ֢A=ֆŋ]ST^喝n:XΗTKu7obӦMرc*++@"J4{ntwwDDD;?hZ_QÀv _xxV{YAƱ dNwFwg!s_DDDDDDDDDDD3k;VSJ{GZKT@fP8iO&WKʴDDDDDZ.]iDDDDDt )-|9Mڈf^9(2_ L=4J81DDDDDjF=-t~"""""dДVFwojNiXyKDDDDDDDDDDDD3{,ProNLDDDDDDDDDDDD$%Vo /Rlҥ"hڵqmEfNMAF>\@2-f%W_}%9w\XVv ŌDDDDDDDDDDDDDD3+(a6 t+W̙3$ z?իW9DDDDDDDDDDD(ڿ\'{5d z \x3F_0/z Bu`L%KQ9.;y=8.70oz3v}r?.= )=9#NUVët'.Bׇ~2V_WÛo6:;;1{lhw'Q޽8]\yO͐ݎ!^b^ ]yyR1li}a6Ƅ);U &++R) ASX{7Fpvhy=m~=(u1xmo|>G_Wl?mq#y[?ďjp ic+))^ZZ8=+~SkkkQx! AwxΖ8[Z0wݿTcM"a@, q.ڿzϣ >]g⾒GBVf0Rxp޾.xN?md}Y{듇"g< mJq&˃NC__L&, Z=MF@xU8[Z~HS׋Cv;n:ۇA[V\E/su8[Za6G cOj/RI䇹%f b] x7?ݐ_򟿎E;Ò}•ş9owyo[u&Ws]Td?m|H`LK~%xO<ſ/=5#nlBb{{ Z,ӈ01C{""""""""""{ijZ:,`'Nl-G noOg8^1H*V 6ܚ(韖Qm)ەљzl=ҏڿoo{w$ʃ@9:wrR/@ztbb-n ɄW_}%%%l0LC{{;ZǏGgg'PQQӉ^9sF\VjpBXVڵW\ ;]u"O{v6 v. hkk ۧ2ضm[:pSB{|b?)ԩSuִeo4QQQhZopUCvՊ 投Oш!''GI?""""""""{cv=+yQUzquC0jm6qjH--}_Xɂx3&Lv,UUUt۲e`Z'jXl***j*p@72wou^(a1TYZ ^9UUI.v޾!z#tsX*oC6to/RY{d9^+ yR;x3kǏ^'T AodxP+ `bZjfsPUMҤUvɠX4;9v{C߶D`aV乐GwYAQ+ ]tUgut}>9x݅c廨^NjidVU55a*;;; }tlmoo2j!cDa /SMeBm0-aTcWWVk'WNNΤ(vфjՕOJY{W6c9E{IlĿ(+h")3Fm~= } b>h~+\-Y|76xk\;Hj`!r:0Ha4* :F1lm$YAzbDڻz֭[ՅNMe҅VwNű AhƍCGXw!݊ NM𗈈(>) lz]b'7ڛhnodz ); l<%KR*qj?qj{~h+^Ybus `^dv<C߶p=ҏ~?]~}?rD΍v?h/sN-YyKc>B"T/`2PXX6,5Tp%e'#L{݈邦ʍg?iOXfVUF&]7ٔX/]H5B{:nv8,[L>trɮI۟iGDDDDDDDDD*´ҩz noTWJی7Ex4őu+qa] Z !>O7wX}#3EڏhSXuC߶e,LykZQWW=zjȟE !c0.R,hႻX3q9syyy(,,DEEL&֮]7x#l JL$=TL-|~SSSL tmaӦM?0"""""""""$*p-m S{RCv;<t]\uk'{dR+!?Wfꍸ#*ͼI掯A+i2cv{o{bİ7iJ^^[gTVSYpmEj/T=[܌7|===Cb`֭غu8 trĪX2>+>FW[[[/f?KDDDDDDDDDDYEE8ݲƚ50V ҂owķ;wՕ4t%B+cюd!`Y]{Jwsaq({omq#\xi)n^x;W__`Eh[ S୷ oNNpt!CTVmƲJJooﴸ$裏d2d2E{{;"d2EՖb Ƈ2Y\'""""""""?ҥKtRY:@%VÎ45\xm5hIo/V#MM8]\tgπBtjg!Mb0'5Ar=%n\>ItzK"9owneOR-G7P: Ummma# bAUUoVG}N+˅+W~ӟ2"M!nzg"UUUa…A!bթϙ NV G*;Bx.))ֺ\.׬YT jpB]Vp|VUVM0O8}Ζ|nndlJF2z=L<^-5'*6xk sNNR(sN-YwW۳}C߶/&H6/z +^Plhoǩ7'$_;ts8.+Zl4`< VU 'QQQ%~fOOg}\c۶mV,M~۞dBEEx vvB@8D?555tǩSPSS TTTh4&綶6 ??[nř3gh4jbӦM!ϙPrgg', ֮]1l6L&F㔮7MDDDDDDDD+qs x/^{zz j of;< 8oltbӺup*z!҂ׯ#l6Hc:-XoBTڿyѓI;Th_?B'(x9[^}/@9? ߀{z#t/d) WlOZLBqf! ^~g(,,DEEׇv455):}͆tW\4u?mʕ+p\CNN]gg'Z[[?ىi{mtvv⭷ނfCaa!Z-Z-U߼Xj /sIXVTTT 77&IǏGUU***wuu nBQQL& M7223w..Ɛ썺r^ՔɺrOQgBNEz P]u{n *~?{bkɬN֭[a2pQEҥK<ew_ͽ{1aZUN5FKӉҐ /d h*ݲslaG(DDDDDDDDDDDDDD3`"""""""""""""BZADDDDDDDDDDDDD4 \c0 h`LDDDDDDDDDDDDD4Cd Sޏ^wZ;iߛ`O|0#'+0l06|?5 &c0 t;ThPl48\/ 8ۤQҍm>4Kq{+m^(tODDDDDDDDDD, 'ˏxڋ#|h< 3*|s]Qܢ7@DZ|1&T>~W8[ǻGf4\޹-m27]Sz_ 7MRJGڧ˖yp׃\aaè N?ڡ& Ȃn4jR=J9rZ|s}|V6]/Z ?gjq h""""""""""Ja`wCUaU0[<陥 rvXkZ 8:ۤn7"M.M!Vmװ:0,yPިs&_ $, s0&"""""""""IqUSMUlMVE-Xx<wTt9Y)Kkp®vlIl UfadUk'z^+!]7٘HojT3Q~8#is]À=3PUEiu;G`Jg#~9XKC4 8CJL? 0ˁZsD[[|9LDDDDDDDDDDS;Jb]6_Ӡp4cS>[ƻ%>4ɶ2'{z^ b,-uDv8o? /6;5/G_zh7Ao.Bo""""""""""g{q,sfvu~َIx8YUǦٔgy-oC~F8WJW&7 :O*8Fz?Nl]T_98"Lgx&q`*ޟį%ѴwT{zo(0lݒmWć5^ 60~Y^Ļ)l<z7[Ap®IN8_;5?kdURU>.{U@`*^i 3~vLd tܦN5>7Η lnZVM-CsB?L`t#!""""""""")PcwC&_{J+!NKËaXۑ2~ݐ)Λ8-j48(q^vwIp>n ߛԘo_h<3yZ;8a}NdO'-jx//S9~ğ3GN`_엉H*Gڧ˖yBDDDDDDDDDDS3^GNV vڡ&uPEe,Z *4qtx#eu;xn,lzڃr ơۡRdt=Dw+i  GM_p8>[|9T8rJki9 ebj/}0OZ]?إ57UQp,V_Jg@ we[ %KهF?k0k;iDDDDDDDDDDDDDD3`""""""""""""""ቹNg\}?@DDDDDDDDDDDDDV*~vQc0 h`LDDDDDDDDDDDDD4C0&"""""""""""""! fDDDDDDDDDDDDDD3`"""""""""""""ﺐDIENDB`qman-1.5.1/screenshots/qman_help.png000066400000000000000000003651151510660157000175000ustar00rootroot00000000000000PNG  IHDRS׫iCCPICC profile(}=H@_[A;8dNvQjP! :\MGbYWWAqvpRtZxp܏wwT#eq!]0 Ab>'Ix{zY}JdO 1ݰ77->q%xܠ ?r]vsa? ZR=Um5c?Ǐ(@@FtCEEMMMd.~lJK,4 $d$)  _B??Yַe~*77_=fjjf͚׫JׯWAAAbm߾]7nhO?]/ /_pf͚C[_|0;O۷ougsݐbQcj?Ȥ!4]pf0jAgeeo߮yuϒ+-CZZyꦛnjsiӦizGm(Ϝ9Swu ^ziȐ!I]k1ѣG+==Sjy2drss^֭[n:M>=Æ wܡB]yAylƨP%0 2iԫWLLIɰo|CsN8gymz)577UW]wq$ri*.._<.Ew$I+WԾ}4sL]wu4hҔsjܹw׮]Zf$i֬YAy#I/?7!3o߾!4q 'j\Y,:uɰ2m4IkÇmmm?K: O7GDwӞ={c9r?%I|IqiСzz%I+Vڵk5sL}-Dջ$iԨQϗ$:tH^W'N t3%i(}z5 i| 2~zSN+";3N;4^x~ :T}Ç?Q-%I^{&O,ݮO?wyG:r9u:uuKnf~2dRSSv EjTF.ۭkҥjhh$l6g?ȑ#etQz'w^xCܹsL}裏T^^kךz뭚:urrrt!_^>ykђdq-N*ݮG?ԼytA[N_u_~!}1Ϛ;{i~+Bڱc~_o԰a4p@y<=ڶm~_QwT[[p={z^7ns9:~~׭s7g~w;QIZzƍt_ Zz8 O~IғO>J۶m̙3k.}9rƍ*544hΝ:v?@@7ɡW^:yd=ϗ4lذAz!jW<4A]vW{ڵknfIҎ;t-rssͿ S$;V]tQ."-YD\sMT#QO;4}g}>}'r\jꫯx=ܣ.HwzuQ3Ɯf_vnV|>s9zջwoX Ѐ~3_6C ь3K.IrKIko4<{dXt2~륗^ p%h{oKf̘ `:~*/\~M0!3fhΜ9iذaf 7H/b2* $I>3|>驧Raa^~eYV]uU:q|A[o#G#%t/ ?f޽cXk|/T#O[{!CD? :c vmvH/baX-Ir]'OTii}7ꫯ*%%E<^xg8n$ @זnjt{voG?jkk5|p=Os9G|Ifi`0DfIk„ kبk:pjէ~'N7#am6kcǎ飏>G}K#G԰aâJ/\wc6b 箭ծ]裏+Ԁte$ĉ:u Y >@cƌؘ29W\q,^ ]q$+ŢѣGk߾}>}{Ջ/;vFfs1ՙ_$#_i…:s_4֟N3יLO޽5{l͞= /\Pyyy>|$i۶m:-$edd(==hcFӤI$dNf<{W?̶ҁYbM`PVV$^7onw!?beᬬ,}я~Ѝ2pHz#gddur#=W$w^ 0@_Gin\l͘^bk_ZF2ԺI/."]qv-_$wQ5moѣKك]i}738ǣZS @MG؎:f$ۧhÆ MtN?ts޽{w^'0;ƒ!#hi***FjˠUVVV(O?4(TM>]C |:|t,#P}e3l_W4l0yfguѐmŊz7F(oٲHX_B9rJM0vKc%^x>C=f>iׯ61uAANƌc_áJ:묳=1}uJJ~a}_ȑ#)Ɏ;fn;qDl/5s7ިq)''Gg}f̘aN7nݻz!Y,mۦ~ucNK믷_,Lq̶/++Yg{{սޫ{jСzGcNS@@222$ 8p@=ugl'h1byƼo>Hgun6۷o׉'ԧO]Vǎ3mwѹ瞫?_Q/K]uU߿~{ހù@}^^9":]vi͚5}-`J~[6S7tjkktv/ŭ[n%\bvwkA߿_/$i̙:tۧ7zN_~Z%Io?8@7`vm-%_)4x^mgaȑ׿O%I{}рѦ0D --l5vڠ!33S4w\͙3G\r맆}ڵkW#0gϞջwoy<߿_ӟ$G\Ν;Ww}F ?~\w_WXK,Qff.r޽hСJII͛O#ɓ0at3r?{ժU߿>vڥ)S6?ϻkn[|FkFovޭs=Wgyw^\R.Kt5HϣVqqΝcǪW^zϪ?馛nRSS6m9>PaarrrبݻwO>hϞ=_?Ϻ4f 2DPee4l0Y,z _bMqLC|O\'4\x>QwuW\#2=\wQ}}J$6ώTaa|A?~\\sMA!ChڵJKKNbh͚5Zl-Zcꦛnҿ/|Q?dddiرcK␆6n|/}ݧ^f𷶶Vj[n>#۷ͩ%{#;kN/}~tFoQ??jjj8MMM3Ht9f3rzI>Iӧ]'bڏ) =`!]͛+((豟wڼyGMcAAAk***͛tv]jUW!/[`sa㥑@QUU%*Il=:rmN4zh3_<jjjTQQ!ŋ/˥Ґ-**RIInOm***T\\UVVupu v@}g09shƌ1cnڣ?Y$I+VhwiӦPSuu$)??_eee*++ g…ֲUTTdnV|rl6s{dx=υ/p yyy*++3wx<*))j &6\vZv]A?/VnnnPNG d`8nWqqNg U\\lS]]-ͦ|t-`TB<OBֳ3qعsg]. "WuuuTʨwH2믑*,,TaaY/UaaBc%Y^^n>p W6$%L,DK$}z w|0υP#.faV^^4Ɵ6ml6O^@AAAPVPP\n͞=;q8 !2k,9NnaZURRB͟??h:-YD.+(Oʔ6 h$=Z"Z㡽<...V~~<C( .ի)F$|x|Id@s \ihңbݘ~0tdNUUU?F6zyY/?E0F˜:(q$Sxǣb!?% IDAT}鵍@gz4ΨG+77Wf#FSOD$yx.5<B )hVkѨ… pB9nO?ɓ'3(t/_gy&Y?cAk38-[,5*rŨvegg]Âhɒ%dVˣD|Oɨ{}ΪGVVVDf=ۘb/d;+_z<<sa lvo-zOKn^M%윬 4f dggwxkjjb M2EWΗ ζs Ř"r-O Ѧ7eEDdթN˗/tX$V9e *\˨ǴΪGՙi6MUUU }k}򥫷@sK8<>@0Kee$ohhBXԾ+K ta]{ϏT($v{B*yyyACIIPeeBղ***n5&ǓUNM\XXhB=|%~h‰͗Xu<0xp;ΐ?Ə}QQQ@TTT!b (}yyyf"wb͗ Neϥ~:dZUPPŋyyyj^j^ؾNUUUf$|!+NU^^PSH 9Z`{=kdfR~~~VUf͒tQ"H.v+)c-;|~n‰͗Xu<0F\jkkUZZ2Pn[Gv]6,Z*//WQQl6V^--*ͦ%K?މbURR lf/*˕X%˥iӦ)77WV2{1ܹS . *vN-[3HTUU)??_O?tP{1]C!]fyx|0)I:c˗mݺU.ˬ,`: 9*×9s}ɒ%Z`,XbsJҐ3v՗bՙH3kUVVvH/Xʗhyx.|^sa JzH҈#Brw޲ZfvK/饗^RCCC> r\>|VzFSNաCBNvWph֭?Q:$ǣ'OfiĈZ|yȞ@/UVVnn+''Ggq|>_|Ԟ={5 rrr$IwOСC_^'O4ѻwomݺU?Oo_FݻwMu0ٳGrv̇Cz*''G'O4?p"9Nn'? {|6b[q8*..VUUVXMeԕ:L<OSܹSԈ#dug3vSNfw-m<֯_ҰXuUSJ`>Oeh‰˗x<0Q,Qzi$Ͼjݲ:h"'I}!$MQQJJJdɒ._xtjٌdC˖-ѤI0puSᒤWiӢiAۜ8q"c31ټy3]zAXB*** Z+q8r:LE0@0saF~{_=\ *//OVVUK,iwM tIӧE)spIͫiѴmN8ӱ =`!@Az4VqqdxvU[[J\W^ѱgϞ[|@NSC6Mn[n[.Kv7oTWWkƌ$ժ 6ѤI^Z*,,e%In[3tO8QuuuEEE*))$-YD+V:!8Nfdٔ+ө`ev8r8n`g멝Aݭ[W[[0t1sˀwW#f-6M˖- z-ծe:[)pm6[t]:"-,,Բe˴j*Dte˖iA͟??`쀿Vq[nے1G7 t?Kii,Y"nׂ tҰAxu)#M1 tyuFVX)SSuuu{*++ks*\ZЌ4. Fp_YDSEE***p84o3iZ]rp]]l6mKyy5~xUVVvu@`$\MMJKK^3pu2v=LA\9.quF̲þziVVV竭 F2-rgغuApmC1sv:]:"9NZJASij֬Y;-]SePfEqqong*]k#.v] ,Ђ T]]:i tΚ5+Z+VXxŊ?~9qqqNnVkB8Z?w)NpB󽚚\.s t:ҷbŊQYY tu@G *x֡m-???{FΙ3G/6:ЙH]nyN p۴.+p]]]@@?1:tjѲlx]EEE_? \QIӧE)spIͫiѴmN8ӱ-d/  =`!d:ܘ `0 =k ohۚQڛ AT^ٔ'_+:͇6\M5j}$u,fx|:ѽ2}M!#,?Օ4|۵N*gO0]{bM/Qk>?>ȫzu^3ȧ#R^l 8=e]Mf]~KӯodekӴlM[b͚2ޟ~Y)w6͢ek94:~l>MIc/>'I;_eTm؜1%ҊT-~WcNIsokҖ|bߍtNv6kf3)ZJ y?߄͚QЬAhŰ;EwNu@Ci͚~~IҐM G"3nS>؛.el uf6E+7Z}g?ozus\k36e/3Tb1COӺ73w'FֽCe4rh7390p䉳s5QKgPV?^=fzM?` xPjN%ta,y hҵy4H'{iڵ7]+7Z^Q'#FMq6랲^nФ):ÿ].ESskfN-3T^*W[]m [)4~.&3ΛXhrh?$K}0/G]UhcGܷ(&^ڬ7}7nIKXE{X3v?:k}"YdX; jYsokҾ)rHy#|tWh?LLlVb,i^IzV@( &]UΠ7§vkT`XZwj- :k(h˼! tuC^{It_Py+U.je^-~1Lc\Uݖ Hq7§F+opNI3 ߊF۱xGC߷Kؿ#Jw6X)e4d@NӼ_ԕc#7@ol+Iج!8M+7X} _r_V7ծavQr*lK  5hޒ36k԰F?m5iAQʍV`5ǽr?轰`@۴>W׌B%u,a԰F{k[Mo=a_)KUؾMz^ w΃SHi^ }@qc.Zfl>_,t,VUuՕE}bÖԄCb~E>=My}o0lk?_ﱶbbDvQ2!Q?%?{`t5 iXc)ZB6lOרx5y|SȞ[_~FȱxsnmԤK egim3$[<߳y߁S+^2t-my7U4)gOco ;kx~s[t=Yߛ[v49Y^85eMA=czzîG^93F͆5جuXm,fM?{3S^<-(ʦ,q/el’A]{̀rk>fϣ G/m۲rU,zfz4 XhyU`]2cp]nv﮽A(X5B^#hSVؑU>77:J_`-LI,&o 97`5r{G@ǎZNbˎ/ e2f?k)3v@2~Hl/`<_׏zhGǢ)o-8~Z˜ۚȯ{%hk~&ݏĴc-]Iv,LtGNeGt v+z5.[ozEK+=p2oTn39m>[J$y_ґzl>.& {e%n o;1=fT7nIMnG 緼ekz[k9h{rb͗d_t_#@[%{~,;f1,n$k}Uw,T{}"hCŽ]*]8J$2_?:uz%kq bL~SV^c3?/}BS'IR.r 9IhGKCfӺ~'|#|c97?!:!D}"v@~Hl/d]?u._DGъ|h2_ҝGXˣΨ$~k~&>] `t*PK4-0*6=U鑤# IEh J* m;p`O]);O }Oϗ  *>VR5z7k:-Z̆y[s&K)ƞ߬At?ݸafkc>'Ϟg/˧>U?_}}qEG k 9%{NSC `7/ʍVq/Mə3 ccT<d%iȀ{ҿ%5=M4p }t>G5zZ}0o<[vXt>x?o; Yh?${`:t/\(Q_,Q,)wGnߓkyYdbd'+!.וVUw,Eޏwz~-f_}Qa%j,Q74kfMkw E<W{ވ&M!hL O/qO _6z9vu'|Iu@/Fzs)$[ fx{?ʍV dج~4*1mI nցd234AhFi78fwz&p4hkѤKk5s2@!߳Duס#m%@JGRvv?_"+b-:Y<t%mK Xx&nt~VfzEr{58=z-musCٸ%Usnk tm=p6z{^=hX%ݓ  ԉuʙ[?nLk>Zfjj/jF TN9Zw; qKnun}Z_IIX$:{2l ih;AL=o(zkƩZ)Uzw7KmzFtԀi':~HD;~^(QX%|_'JV/ˇXˣdCB,.g(m7=ɤ77~1 7Fڳ)8^*S;$ɴ6?zhM00WTExгR4f?rC[v1IҶx&qu2O(pPBmgyȖ YLi:s{h[.(AQ;Y`< @z˧ vd;/'r:@c:QCWM(_oQ>\z~XєG/zH2sGɮtF,3lD}*F_{7eFkithilisy'oҳ?l[~C&o lvʖwS@ӤK:R Fw54^ƞ߬Gh(c/j Mۚaa3y|S^t?glEE/~66^MX'I䌠u,zeS-9#hߗ6ʦ}ѩdi[Mo=*ziCܡ TslPV; =u,͚~o^^51~s"=Wfxu5{ }r՟_\ct-#e")D_XMG,5l`yc0F3MT\Fssס;}/Vܷ(^ 8O| W.<|CK!(ΨŚ{5mly7U[v4k^=[ڨ}|_obF oBYb/+}-gS{ӔۚB~_lіwۮn\e%4>AN JgiߌͽISԟ)Z6CHjҏjҌfs ]Jн|og}>2Is4EW9r$$ͼJjO){`2?fQߓCZMO?>W9F́M*qXeKhݛZfގ X~#zzZj!sqRUشLeexG k mIW~׶Zw ֩wv)c5UKyǯֹ;jvd7 u`yf[A3F>o.T6Tn5\+_S_;>SnKݮGҿ~?]@Zjso~WU8NC/Gݸ֫v&.?~YSV}V_n'nCn۟[y?%IIݻ @[|?nv3=_a5l^N~Y3we=wy_<ϵ%I.ݗ5A }0 `'O@ >A }0t_̿Ѿu_WюvhG;юvhG;юvhG;mv7?@s~I>U_{xW_:_?_'l)`t/ʝ/rķ\z{)]>{Na`tqTp`_y$ISt0j";GWJJVl%``(vA }0 `'O@ >q;][n =t-*O@ >vw_U{;]x[~$i޻[mKz=srο9'a#qbGu8*7 FϨ߷ksAݯԾGm:X֋]wܵ)w)~:}}z}<+ސ$Y?%O:o(I2>ynχk~X=G|=yX~]Vc_{X+N$OOb] <ԁOjCtMA0z_|gfoQ*fa o'1{7U.Wc[?)_?gf]GU]W|^U;?&ަnV?_ 7 _y>h{h 0q盏{x~j~^>QNw_ΏuNʸ7?Pᆰ+ިys =lcr.99'g=W/Nڅt%}zÕ |]7y͏?z[~:2_ӓ/_ѧ7>=|D]_ʗӍuU֭\>/څu`Tgk>~VJKM_+U?tvNKX{~k.ʘ_=oYuڬOns׽Nu:Ϻq~ڑa[OtؿuǽܬIrya;|/ЕstEСdž[zgwr;ɸoD|qo,ܸzI)%|ꥆ`\ ~𷓯6|ȿ*Bc~q.qo4͏>ww~6Z-5Kj_9.=|WƩz}; x[{7._acQ^WX|~^߸zQ_"BꀭOn\+Я}Pg9f-C=߷2_~ܯ{fwq~2x=FCU~{,_zO_^Pysl+ǽ{73;6:X]ʒGe|s|K67?P~汕琮jZY {sُ[[쟓:vU}>_zewCA6cw~R?Y]{w7сOݘ/w~=5_7+ڝ'yW}mk?&/P|j]+_ϭy>ЕsoB_?vg[9Xww_hw7׬ެ¶ΗzSj+!քyҴݴyՇҞuU?hbktk3g!N퍫TOGZ魚~9p {w~v*ܼv`׾zY_7?572?1϶z뗇wK`g=<}z7TZTt㞓}Ƹ{?qߵ˕Fƽw;0z>Qݾg%@ڳЁOնzfϯ~ÐjoTWÆmieC}ouYv;ΗwƵ뎻h=a{C/PdWVϳ`:بoY~οyYzK.]S98}<@Nik]k9U1y_Zm~vsۺn`7V3їDe?=a;ҍVj6 ]{bX߭V|_j>4qҶ ;_6ccڅU|^.c&PyV?n}vs /^?}{8Ooټ=pjnůnvjs'{'F}w;0{L}UT[a+~^߮MT/yOTAmk K͏>SokgCn̗n7 _S%\7zNs^/;v~2/ՕzkVeRxDj.|džu8jG>w5{\>oqtg}wU{vklyfܭgo< ҥ~f]|s羿>34\>_?t.;<ٳP[{Vϕsj>ϝ:̋$Q/QؙZs?zFG|n=\D޶~W/cݴoyn{zhMo3lWu,7hP˺P׿3s?zFJ@?̃; γ:DgE rŠ~Oߞk* ˽k?TwlĕstLMEu"nyf=\2Ļz/w_ z9-n~n\X37yW[ѯ~feqV0#TZU}¸_ʸd=\=w;*uPު Kُ׿3^fFkVzK7^ܔʬC ,{Śݪ=4ÛfdcK뾁G|С1l9J=[_nǻi/W%g!8d0վ3?wwK޵C b ):2,ڵn{̃yENC=մ~NN9S:p سַ.I}-f̓4J*C=+WB,,ɖ뎻t8jж>l[Mgњ`oC~NZV3Fs۳g^\ :no\w_{[߈~w_:O>d]M0 ;U_,k݄T|>Q@]W~=i}]\>__B`#ֵ oӏ?ԕ/+`#MtŚ׷g!z՞vxf]{֡dž'uU|^P7?`e{'zYHZ ~73β #-jSU?[f2 /m͗n ?@ >V<W2T.S*Cg6'+L*,[EQ\.khh%X eUPHXL{z%e٦;66X, qb .JMi0488UylW\qO{E?~g ,KG,˒yrd2]_a=ߑ#Gr9B뺊Fm[inٳgkx~@fAIbm2 (KHK'IrJ+SSSD"iK~w_1l0/HHR}Z tX,T...n{BTrA? \XmZj4 R0W6Ļi ?EX,&4eYV^MPyrG\.}Yz_頟Ƹ`۶F`۶511!I* *ˊD" ׮gR +3??['{Ԯ]'p5ל_< taۭ»5Z aFڴ{zƽT*{!o$_l FOܜ"Μ9b(bt:)feYL֕\NDBJaJTT*JRS,S. fY5>>.ʯ^,JR 햗J411X,X,N@i%8:ybqr5+s;&qT5_pA]o5eN<)dLT:V2\}>W2T,S\vs_nC'fffdY\\9{:D",J|V A0z=Ӳ =~zU,|\n߯W^T BljMBA###f*2 C0 Eѣ-B!e ,K)Nw5xT*Oyĉ!u358U.eJںgff/8#4??Ѯ^NR)R)sthhhӮN8!dYV_R%IIݻ lӯе3I=ܗ tIrM /mͩ\._HdY/F{|{뒤gK'뵩dF_l7-I^/;06(Jm9۶oi+SN)JiVP(8[v۹_v` Ri[me-4522Bqyg6dCN^V1 CgΜy:zh߽Va}/a(+בy---R=&dYLvv`r,$|\ձc4::2|R$$EH$H$p8\z'4 <?[^^ntb8m[SSSAyrux뺛f`j 8je<W$Q\ho8b B\-//q*X,64M nRiՉ \.t:]"ٶx<΀"6P(httTrY4 t>BAlVޙ>9~uj%9+*X, K>eMNN6RT*ճտ **٬d᠒wiim.S,S$aT*AUt4$驧 ~q_q}ԩ~_QQ]kvU*eT9ϭz`` xr\Mc3BAu]MNNn몧J|u]yT*>a(L*ill,JH+XueԪ\=ALZBPp6U:бcdjBh4p]U###3&&&亮|VW\}_[_ j+C'l˲GFǽ}VIV(X__~E0FuWJ_턯~Po8Na._/{U\j>mrrRrf_eZӧ555fH$d|/Bd25/vaIbc. z=ڶTn;?wP<~s CNuq{'ǹ {76R]ЖeՄR)f-Yb:|dJedMT$Q2ԙ3g4<<ܴ`~|[hf\nZW/+=bVKTR\ mܜj3Mͪ{f}^Ns'4Fœfm 2˲twJ"v]WPh奥p9u]ᶗݮ>-lG. ?D" ò,+'vۮP˲6tL[.\в/RIHDmT*ic=սׯ_jtc;9Νt_CQV/WɵWpjԳ8AjlV*|쟳i5Km\ ~ul"P&izuJ9wEznz8˶maJ`Vtnܗ6kp_}iڠr^B:l%Whk hIjrrܷ;G:9m;Cu gƆBNj!_;avZg_o8Z\\mAdVK@~U}~3Fh7f^-c?̰,KeAHRQXm۲,Kry `~*JoŞK7SgZ_ןv?FLTPP>W$arGuq>H0aATBP m2|Mp ~Q]v… n7L4F:}Շ~F"PVٮՄB²L4aff׻yV?k(v]jqIsHT*y'qyJRpxJƽWu~nuXA555L9~L&kBp8 < B-b=S-jkX,&4eYMW*KBX0F555)]ٶEцѶmMLLF51??rH$Ab7ՄPp8xvgz۵kyy9ʭ˱N{///X,ϭ5r\<+J^ț񅌭+=Dz,bѦmfff8ׯfr < y8+h>tRTCeR)MLL()V0'G<00 qtɆ=5G\.cǎq-,, V{:1999TZc/~/\}tីU1r$. *AhE-..jvv[-JiiiIhf?bfү FFF亮<ɴ\^P(hhhHDBpXa0 yL&TovCR\ו8qfٶCQ_iz۵kyyYCCCJ& R~*^oT~WcH$#Bƽg~?$:vkҗ$}&Iw7aOvCt&0PH'OT.kZYIl~R$Q*ZK FNv=ϵ%I.ݗ5Yk0M1Ij1R<2f#!۶577TnU! YئJFFF'#ᰆf-&``*JۃbfJyf, n`\.\.GG-'O@``$={'NhqqqSp8x<.۶e$)jrrrvaR0ѺdsaaAeihhHR~z0zؘbrRTfgg8Κ{ꩧ42dG422B}kΜ9#tѾ{?to,˒$U*J%y---le$ɲ ܬv8mMOOK<ϓyW3dRpkK I!Ǝyr˟\Ŗ?Cf?R ¶mMMM=Y%u庮_\.ד7::ybbBnj[}$W,KXlՐ?`-Q٬2L<|^.klܜjbbBi*)NT۶xeMNN6|T*u,;zj+)03 CD"}¯,JbBbr]7=ҒlʎbA]*499YSX,`bfu]EQٶ-4yr2LB!tL&fX8NM[\\y_URЅB!kaUXT499r\[^^3(4,c]*4??/IAs;RT뵛בsPhzTF`=K56… +rFܜb*SOZ\\d>dJUedɤΜ9~^uXҩ|> \.7Pu'D"VmՏ~%{`[u\.V IDATF76ܬi;^X;J6]Wy=JJ|t 0C.S.aD" j* HExm޲Օ~e*[vwygϝ_7ƽT_ł=kr#מy2MkQ6U<8ZXXPPP>ׅ ~n|ٌ~փ@G<ϓeYrGfZZZwT*A,IcccbJ$d2|il|Bo'Ub_'v;6ԟ3*JMYudJ!% u`ij499ٵ/ucuO/RѣGj2u8Ǖfޡtm<I / Ү_绺v;[5ҟm'j>77Uz,//krrRm;]cYSOe/t_N0 R)9rDtZu]MOOn3RJo^~8jOyj~kKzǽW_:5?_-lu~_ouT*dt`q"x;̗V6_vT4ӧmCJ|@?22\.'4H$tIMLL0}bjP(TKKKli*7zI*A n#`;A$_hr{z?Z~@Yar|KpBWY~Z!X,&4eY6 jÝȶm-,,(6,maXlXu~~^rYHDccc ]U<qV*eYI+Wsp8x5lm뮝T*9OOO7\a(jjj47KNޯ!pMiƂՂH$R>a xK8`l_1_"H}_ {'۴jW*4::x, >HnffffafeYL կ d2}Ʋ,k||\\._RV*RTCeR)MLL()9ޭ`NZُx``@ɓ*5j9j\Nǎ8ZXX/\ɮ[NoffFeu]5ͼb1+H՚lvͱމ^B|>H$ĉJ$,KP\}ǑRNzI&-/\nϝ̳Η|>d2X,V/bQL_RYU,,kZ.VZ\\fggqu%0GPȈ\@p-eE e2˥  )H(0 !dZ1WT4::x<.u8NpS8l^_*ҒѨlnnVtVT\5n~[މ^OOb,˒aZ*DdYp>T>W"tiiIt+i٬rЏ{NeX,8A }IgϞm/nZuYn{ٳ z0]gʶm"hT eJ%-..*5m;55H$kffBp!yZZZR6UR ǕL&U,uwYIȈ BЦ~ۭfΜ9#tѾ{?4<W8eYJR|>롗,Kinj;=גɤ0:I FO*-R$Q$RT󗗗k8:5}/u511!i%l8Q8ΧV;N_l]mkjj*8=S\eYr]W-U_r]wSm%^mѲ,bfП 0zy ~Z\\dp8iIjY[\?W& W06$r̶mIZ |&&&drtMxh۶8#@dDnׂ1IR6mXR(l# rɆ/$J"F(JD"m+W|m%TUi lPHXL뮹ollLXfX,ѥRI ס_?88\Ǟ)Ezܷ^L&ӧO4M=Oxp. U4<@v.] /(*ү=ȶmu/ld2)0V LԔ"xtss(2Ǐv*BAH_|Q٬湽֖y:==՗/_trr`7Iٶp~p{0yL3Y%myt1v헗0Ynwy+MG`muS_*`}ϲ?d2QQY3ۤKSכ"UY~L&:_3[0yUKk 7:NZ+2l[eۚ?]#xYF {&zvvv[J$NNNlnl^v]alׯ_l6g2O54eY.P6= , 8X|Y7q30Dfg 37w_3U_Iëך/_l^Y}c hlEXiMYSCdR]m'^t:vjZUҝ:heY,dY }_*i&βj$PcMmY{8|P>?+C37m+[i*cy+ypo߾|}|y~F[n`VTIT٥`wϟ8j5a(V(ď1L`$("%I^W,EħLJ9tM[~I>ey==_cg;lVuݾܓDJDz]aVrENz?bZ֟D\riWu*{||~O6{!ZVe ` jn6m}as潧8{܏vNo[חkxL̗2k!z|hnj}_m,ϷoV//G >x3<}Vt$}*qx?1m{JhUP`U՚y~-f=/O9C:ehdi;:-A fcYV7W!%[~Y| `~7/KQo7)"u*`a-imu繎uxxV8UE`gmҖiqٶQ|8:<<ᡊknw{{v](\]UM^Ç|8rZ y-] ykwwZGeɲ,E^̷d}q0 gS:88c=u+$U<m{.fY v,Ka8Ƈz/On5 h4ZZesIErGeU|<+9#Qp8T$UV!MSeYp8|t)rvv<EQ, w J߃EQH<ϓy}_ko'\I,BeYqa0 o)˲~HaqJ_fv]WGGGrGGGGٙB} ^^^U[( l#ٶ,vg]UtkXv[L[ug?88$id2QSY{;Me|.RNgn s35 `XeYVUt˥ڹ0ԧOyʲ`0P%j}j5EQ0 m(")sq(`x<^6zZEQ(MSsyWxtthϟ?ϼwuu%qGu%I"qT,aU3},7y>}h4亮l~j ð4=,{p~Nӗ^O_|m_/֏0>2֦>Vms=45سGgj*\xUF2>}mݝh4WVK( U0p8LJDnW^onq|o )^:VkRtqq!qTk6 PEQnWIJ,Z-EQڟDnWY:::Rj4s߯h(eӥ[WXjM0?KRY{&TFs L&*E Uە$yS}E'''p$mt:s^`g^3[K:*Hp8*ViVLVy2LtT^^)S`u#Iv3/_úVs +Rv{&l[Luss3ߢT;Ѣ <ϫ`ɾn5Z~fz^\p.seY.YI@|/֭MRE,B5mMOSlXU6 u/^wXV*REQ(s]^^eU:wM&*Pm,Plۖ8 a{dY,dY }'*i&ײjmd.,I:??S>'%@Q)IzjLgw$ǚu|Mf{~/Wn_{cgUڟfzXtwˮu !7o<+* +evUSumeSef N*sI?]׭35sX@cڰ~>ƛgQOi~8HZVl)lW=dᚙ~G5.]ڸO*suJ, No9Dze~>y^j}~7t.RFC_|xlVY}CzxVUwzӯ9۶0 6޷n{k>)Lpu}^?x\2s,GW)6ˋeYWxqCBӑ$EQ IDAT8gޛ\Mp8tVlJUHmqZ&eY/XuuuuF1 v]WGGGhT(Ke ֒=xuw]>d2Qպz_]0|=)L@1tO[w2O9\pܲ,5 }ieY:88M2߯j|0 7_5.ycj)cEQXw3;...~h$hn*mNTȶβLJDeYVRū qPEQ,˹5n玻Uё(REf*(}GykFv.~d_&IUqwvv>Ύ.//U<ϓ81?~~_ӟ46pA,vwwm]*s)MSF#Y5.//3;}4T 28L?nM;We<=j8,KYx9;;eN3պYۚ [A0ތx,HUzyyj5L$Q^WכLQ Pd,oZM`-=yVSE (eq(`x<^6zZEQ(M7_j ك=_8~f,˪qy>~Xes<"_K\וm*BY4 f<>~z$I8΃׫j ð[8v,{p=L9ӗ^e/_#7HFJ y+Iy'˲0TUPdM&̎ȶפ?2񶸮t?f~VKem[''' @EQh4qA qfֶeY:99yڷmVZ ٶ](wGf`?_Ǒy;?|PsWEjZ*BEQݕ_:itgs8JDaq+Ijx$I:wE$h%A0 gXO3kn?[Vu_ff,#IsI%۷o+ts:xZ*Balޓdi&M=>??m:;;{R^ >ekZMTnwf-q\e/'ٶݙ cј[WVK( UPpk3k1OWL2O{:cvu8+qj;ͦ0TQjռ,KVKQ`$In[<1xAdn,6)5h4ʲ~|ߟa7-}E;^FtL4M%Zxnoov%IT_|Ƀ$Id۶!zރ{7L2kf `Is[Cy^Ͷu=[eN>~1ܻ5]׭~MZ|7z{{[wyUSiYVU{w^N&j,;_p8Sv`2Tgzz v&[n;t4U0`F4g$Q׫:yI k}7ۼ{βן/&Ç*<庮|x<yNUkcl~oSt- 6 Н/چ|eZ:͛`tVCXz `Og-[gj6=6_xL j5?yM&٧ӯf{E۾K\mL=вse8V}_m+s CA ˲yX5ݜ)vWeYdݧ'Y߿ќcY~^g`y&VZJiYV :F/_ӱv=)3i-Kly|WQU;89j d_ˢ&8_X|yh4ipeYO><]]]Uo߾[=EŅ0rM?fY~1^}붊q390 uqqpMpV(Te5Hޮtn+I9Z6FW @3 \I}y,54 ­Amۮ֜L&\@Y= yk4U??~'e(!s) C}Aqj y^t{<ϵ[?˲dYPכ\|d}q0 gz࠺__}Vd1MD3W9On5 h4ܚxl8;;S犢eg$"9#˲:Ǒs}fYgQv/wO~'z/}m3ZMʲlaf%}8]{u*wggB/O?$o4Y0LFI3 k37!<2UAn#;k6s5]Uǒҭ5 5[:EQ$ITmrGoth<SV^Oqy,5>l(ngg_QB70 x,ˢ?x7.XVKH?^Iޞ<_xz.q$IX~_Y-=$믺yhPTvvvyރiyŲ,}uauj$Up( id1sj}by899Qh$۶ t:K P^oE,)20ё$,KE!I~OTȢEI3s2{ӟ}>P_gg<+*#C͋^:Кߪ[g>뺮...VnM\^^Vp7*)xL8 3etnSk* uZus܋L>˲woW1~Ody^e0$ Íھh˗/ڨv':2nja?y¶mtEMh5lVY3>V$rGZmsٙQ97GS6`?VǪU@`4o۫# ܷkW۾ͦ0y*Bn繒$(RH@im;L8bY[N,z\źiZKY-ܮش1yz @6?wݶm 5 +q*z$$O^_?g:cjeVu*KpggA8]{}n7i$͕>?6)i5uI b~82xAnodPl&v]WqK^cQPX{{{EQ$ITmU}4M._}9#TF4Ug-` x^UMú}F70oeYthFGGGtt<{snoo%IqjI4Uә/_d۶qT&,>,K_~UQy1ZMI*XV4d2Y^2_~ZhZ} x7c+E,,Uv*REQHQ P>}+ *mz'tغ8({@[)MSz'g۶)B?j6~z$I8Pe3j0qex,lgNJQB_\וmz=S#Ǐr]Wqu]IvKgVE1_4?`ƻ0Tj/:WJDɲlш /^uXyWönp/^FQFϭ8V$U=S$U=( 9ƶmA :''' `Z-9#۶HaV,B(Iaݕ_r(j<ϫYt\VŅlۮZ;SeYu]\EQ( Cu:,H*di4۷r=l̗V%T)J2l~uuuqq1W{9-Iuj'@tsDnWY]ё PјkgP*R.tiͦ0TQjqej)",8Z-WxYXHm+˲ /.@ `lV{l^^ x:x|_ܦ,KT% 6_̖ʒtfyWAup8d22q=ɞfyWEbƚvv:e0 9qxooog u>dۆ0te(Fx- Z?T_Lb2˲\%o5[:۹hT/]~q_z~\<`ƻ0TE+ o6&t7p4zb}&uU&p7l6mM@w:p}wղk-{m Vqx-ep]\EQ( Cu:gc:r]Y/1Aq|1 utUx֭ybˮP`K#G_oY0`l#jzi-jGn:ګxlǻhhi&un]Zôez&e\wcdα,y6=KzlQU"w%`˲m4勮6*`%j1!*d۶]=41W-bR<&wڹƬm[eY0PFzDGgoA, TҏC6, ݚL&ʲL>88`+Q[)YlYu4Mf F#?MN4sPVKq(*`-}Ϣ\ּvykFcmg i*"*I*+8MӹkPVKQ,KyWc>`繆á 驊PY=XIqj*.I~_a*]\\|?O( C]\\TלUt:P}_EQTeك#`Vr@cwGA(um&DATԶj~$"I6߯}tt0 |,UE@`l4M|m۪~.˲lFuuqq!{ sY>ex7&Coz= CIzVv qKn;4'N}kVeƻQ03m0\q,KQԐ-BiA|߯j,SE @ed_]]q}Qz]IqE,ͨPFCʶ35?~(uqne۶Pժov38Uh4 )}=ww˲l>}ppq[7ubs:OwǾcm#zHŚ&6׈ivQMDDJ[労wDU-nʔ[#t & FsnsIU0ךJ_#I; 682Iq,KjUfv4Mg?w$d2՚i>TUٶp8,^_Iq<Ͻ׺s]7g3Mk`{Hc'-dץ׾fxv:3(|`0=iέ4[zWh"^syqWOo].%}bwQbˌ#/`^T TN'_#/t0控窪w&/e;ﯝȲL@A&ms%$=MBc8 \rpMDm  Me;=,+_k}EQ$t{{85ׅmX7~{> 33wݺuݙ>X4|\$!}A0 ]EY$3gJ%]^^Z*˲W+IZ-5T?&n/͢mzNb-*z;~3̳,SVSZᡂ In?YG7ߢ1O[@;>Q$JDrYVK,Rr$!q$Ind2QNVͲKbxTh>6]h|>t~4zχ-zb֡v-u08O?4ug[4^'ٿsDYVrYQ쇃3aY2[JRZ6ɡE 3/1[:37i9}~mkjtӯO֝YIEgc3zo˼nuf e#d,믿J:} G.%%]a.MT*}E*!`m'?,Oypa;}ٶ4Mg%9WINMJ=My޺0//ug=64KVeY5==^X|,KJE;;ݮ4U\Vx( ` th~QmHJ}|Ǐ׍d2w;xlFckI@A98?y:$yj4,T8) åkWWWUﭝwZ-aN3ҲI%h<ϟ5dmYoJ<<_`0Xxp8T^WJ4O:F^]]qA%I'^=͇dfa}cqWEm[?V$͝NGz}n;Q^ غkۺQ}_I5 f}I6ߒׯϞttvv3Uռbln,l6uss0 A;q Veo`0QEz3wwwlβLHAqZj*eY,R$zO*j\וeYǺR ~_io9:L&j}_(I5MIjXNOOh4;j:۶Zj舭OO;z_~k J>`'Mr{{+qT՞l < ^O?E}z3Z,+?r޶_$=⺮nnnT.l6`83X'''[?s ``cHNp0 'H  kB_|Ãh4XÃ|g}$RAV41RQA[{vs"|, ,o$Itttw|{,MSeY8v5LU]$)I%I `kF^{o&Ǒmt K$+F׶mq9C5Mqn$n<80 :{NOO[ X54U$OHV믿j<v]WVKjHYJ%IzWIic5ld<lJVi3MSJ vij<k0Plh<+M<<".U*+۶$zŠF0 urr8E0v;ߊT*O^ǜi,ڲղ,aC9#y~:j;yNNNh4dY8Vί^^я?CUU9mMڹn-REyJReǺ`0(tN3~G(iqNSVǪV3sG3vZ:u֗u[/a*<$<x=@VKH?sz8Jh\[y<߶_Rٙ4UVc+j0 `|aoJ'Ih$۶U.U.̹p5}b$JDZ*jI۶uqqraqT.8Nxe3g;#۶ggeYy73|vn[/jɶ'c^˲BuP*tss#۶ueԼ[# ^0vVe^NG`2svi\VRYZT{Iz P$j6y2Ӳ,uaF4y'ٶZ6 T*3ogY6Su}}-۶uuu9z])Ia/Ah8.]'^NT=SM~! MjNW$O'(ZZ_6ê\~JeuO cK^y&8 clTuuss$I|UYzT*~N33g(+^7vlf'U/ο)_gC0Iocu]IʫV$oga,ʫNҷdJV3ۚyޓo "fkVIO$8O&>X&i4g{f ַ^vYԢ8Mg>-"~N2M&<>ȗe6_Zm3 y]X[g\u>~6s;t=No$}URqI`/noo*4Ml6g/˒m k4?;p8L4MVH=[HZ&al:acxM8Mgsppm_VťRݬ//ngQ˶m?Sq[YYg\sh4CsUջdG-a0 庮,ʷj%sfcvO*$}K,^__}=tsox7M:\,lϪ|(mMDm/Eavnr~(ynooDZá~ZxVn}WE/۶nk%||e޺/;\םegL#)}{s9˲7{eL¶g~ۉQse1˪΢K7]{e KqX/2j5UU*$,8M7Lnnn^a8.//O?-Hf|<-zخ:׍nQҘZ%ONNenooU.Eѫm vgc JKLaXtgs*M/Eavx^#F#I*l}/eY$- U|~ɸ^7:<&,ӯ*I x `*H|9=-yJᵙ-mۖ ׉$Iv²up/۶i!gUڹ/:#ϗT<?Je{DZϱh\ysɼ*E`0Pߗ$/"gx}D˲h4eݮ$I2²,U*]\\y;Fc&(Y>:hX{qX/"U*'+[I]&iK֗vJTrYFx `f?Q/}3׍d2p8eFc뿗t+}Pa<g6okl/t$Pz]a*M<4 =r8u8`'> PgggVyUp/L&5MZ-a0 y~(d۶>$IdYlVQ^uqhۺQ}_I5 K`0ЧOynoo-~vl<Ξf#,S͍0,|0>SEQ0 8,Rz*rGlxϚͦUT亮QF8B-eYA󼼍E&vuR P)I zB4s}igsp8J2vgV @VqZj*eY,R$zs+,SVSѐ뺲,KXWWWJtaxqN&j|ߗ8JDfS8==UѐK+3`>8cƶm[ x:6_Rٙ4UVc+jP(kXgX;88ȯP3$Q$rGjUAV-Mض e%Ih$qT.8N>,9qٶ==ӆ,Ņ<ϓ-)`۶<ϓy*~8AT*,t4 fƄ93\.R\7}&뺺Q$/╔O9T*snpxxX\tⰎMx)bX^'JRt:3kBEyEp<`0PΟ𞬳N9$Vp0y#񙤮T*=D0*Г9,+N&Hߒ0v[il:yO%fKWI3[5ul\"cv5j֭o>޶y2In?Nncu]Iʫ ߒ8綵Ȋ"sqx+։m$~jUmk8$HKcmqn\c5b8`[HcsIf{/k]__6~JTfsr,ۖ6 J íQnֈ4MVY&VmI>Nm*j=EDs~*ivL?l=X8WŽniR:mTnz6q0gF;g}.oaR:mozVoqn;?ڿ?ug`E gyc8ulMZ%x|2&aɿe{/Om{i56YDUym4g˲l&^+βLZMjU O$Iv]؇g+q;Z'mMlqimO[@;Q$JDrYVKB0Ifx;^,z^^@n-eo$:y|LOdvv'08O?4q:MmY֫vqnu%IeY[eEQj[3áo[/۶,˒yJ7>=2sљg;֝d`0xX:ttt'ËھveY'I0۞qoN@q8 ͍$tʫe:y>h4E>5esqd۶UV8Jm0ٙj^EٓkQ^ܱ9 a&q`f2lj) Cad^K}EQ$۶g%I"˲d۶:v;׍C͍ w05 F}`O><[RUvuhYlFaƇ0ݡR%)ժ$*mj6WRrGij4)|ѷeNOOE yyLt}uerGe)cz=ce9#mV @ $JkDֶNW4q[I8$kZMjU˲,Y$Ijj4r]Wei<Ji.Lo2׉d2QVS^rGIlJVfi4}ie6cu]UUZ-}W_ߚBg< ^O?E}z3Z'H  {0 'H  {0 `=<<d2eY$qٶMw0> eIh4m**}_vNGQ׭VKA)LJDɄ80#!"eiScIT Fy`G gCHt$q~/I0yTc w0T\eYʲN GrG?UV8$`0P[: PR뺲m뮯y~G(亮oNS֤RIA}9#qApNNNh4dY8VVE P i98Ĵji4~ĺz3q6zl?P<*bwI,KQ}#IYi<~3^E=/}_$n8Y0 gβ71xm$I}{u'oX(fEQj$I4yժ|ם>1I%I"qTVjUu)UajA̜WYVE*J׎;H0mq^9l4폯ٗT0//ׯ_%=Mn$bLO'fVI轤ܟXe\|eߛw G~j2zqnve>3G|ן4M> ͌w` h@z'#̣^F$m[II{yC~< Pʲ&89l}M2}>34W1^KWE6R}Zg2  {Tmc{Cy4L'Lg$ Ї9s<{e3 "GΏП͍u-}~jV:<KNWݙDCٟEp]7O^Ϝ%jvY;>sX]Gd2QVݖye8O?N]f,0@x[yI׎;@8{oz yoMϸm&>kU_UO} f`$y1o xo\4v?>yǕ{G=tttoWnveޚ3l3X9ߣ׊;@HcqW}>{p8d?`h^}ٶ4MgrR=W lIKCEӌH̬2}mqͿb,:nveޚ-=ϛ}8|7sѶ2 ׌;@HCz>^Rͣr(?[6,Sە$]^^>I&YJ7P}&`Y岤?_-iEL1zN `«Ṁ/|=hT*O~t{nxZTu+v2h8JL,Ƌ8|ϲ,Fcf|c㷊;@8Օ|ߗyh4myH`0-Σpz0 i Fzs8 ͍$ɓ e85U.uyyqٶsUU9Rf痾E;(m$ϊt:[k`0ЧOynoo꽯_nڷMNA\.?~a:qUoum`0}t:Lj5߹l2׍îvA $I~`jח-{<ϟ;h;׌;@Ƈ?h4瘎F#5詫+u:I߶MDnW n6j6,+ߚt4VyqDZjf>R;,SVp8T,KXZmji~y³M7NOOv$Iht:yynn^j8u~~f<_"׍.d2+q$NNNTמY= ύ׌;$$ᆪ7$IrGZ-\\ͫ{qq!$x?OI?k6;TG   r]w{*"IZi^wLaZ*MS%I"۶8oɧ8$@`z=/qy4h4RD@$Iw< ^O?E}z3Z%2 IDAT'H  {0` }EzxxPѠcH3RAV`* A1 ,o$Ittt0$ni=,SvL&ݮR$$ɿ,K8lۦSv `|8A8 hm۶Ǒ8:<Nֹk̇UZ-ٶ`v{S%:qxdf> Ƈa@F=LBAv֮-fЦҷEV ?w\/Iwww$G֥lIqL|.Qj;4g{f+Mdx&QƇ`YVt$]Lu0/noo4Ml6gz.JԚ9i~vpXHwsFis+-MTN1}62[v|Udmj8Ia~)"sJVzTzo{ ׈ ;h4?ߺ`4>XJIMRRS{,8v̡I s_$fWGBj֎,lϪ| Zvn|Wr]Wet1Iٶ]HUڹ(yU*ު/]4;*QT5[<ߺƇ`oWL&%I"q~ag9˘m&c*HUQnEUm3ͳdY6-*϶,~)"seYZjCA'$Q~ﱝyQ16X6~[wE> o|? ``&v͙ڹ,${n :??ֹ\"zQukavnzdvv-uKqtyy~],vEo]]|Xg\/Kѕo|Σ׎;G{o{`_Ĝ>t6ي{0eks[ gEKqXE}<(ߺvﭝϭ*:ם{.?ߺ3տH?sV0bsk$k3[Z۶o?mz]~% y?l~r[avn+z݄IKVvgVBnz{yRt Ŷys&q(^zuk#!gތ4y̛뾉`,v%IOWeR%IFc&Y(YvI?,KF#˲Q\\{||,Iy߽8ME*ʓ%E$0vFQ<"93\+Vƨz>NA0 |Xd2p8t,Ƌ8|w =|yqH8{T*o72 U8^J((Ia$n80\+Y$a=_>l?j^L&e"_#Flۖy;N։k?&kˑʲJ$0JR@ eտ/Q^($Q̓e^+ C5O>ɶmjdRI@eY6SQw}}-۶uuu9z])I~K+^NTPS 8JLV:??ϟ$~ɲLNG`fL3*ug%I*^I{J27 bmuez^Jr4MuzzuVghZm[@v;fk?ߺkq0Zey$y=SJ$Ov g}_ R,%b@at&v"Ei-P-Xwyې[RU8M*S d<<ѫ-۔%B~<'d>*DH,*f_s}v]eY 澨K2[䩤aYi>3n},YuNS â݋L$I% I8^y,s1{hQʴyn{{}Ϲzp?`{Hq$I}YWWWMQ e\(2躠湫~A ,[Yj*g=ϻ7~yldx, Muc6Fc枹$?۷o}~{v_\U5n-*t|y le3d2YYkw4>S8~GI =7fq/U=e3ן>WvuC_m8k"ݷs$Ij*u$Idٶ]ڲm⾟o+]<}Y\N~WYF x<uba {fcwyK~ yPFC 4U}<{u%ٺ.K;GwτeiooXX{{{, l DK/l$yLynoo庮< EpzOnWn08Я* e^z'}Yܗjcw<=0q9S!yk2ubR*r/U?.^o"X//۶%ժ,˒yJӴ (Z f$I4 tppPƲͳ|]*y̴ϼsnSw<@ӄm߾}+`F#IRZ}TkfE۶qg.+Ͳ}i$I%\?zZ_Ye{yVϵ|Lhǟcvy鋋bǑm:;;Sѐ8T*k3NOOh4pXz=.nq5MQ/l֗/_,˒mzj6+_Wyn/Ou{{ TVu}}=w,KY1ݮAQMoEծCY틢HqèƇ`>]NŇmmbY˲4LuxxNNN9n1]T1Jo'''zE@88noovx8#yF_k%á~'fV=sj<+2Y$Itxx(־ܴ_;ב=Xz2cbvElPVNNNs6Zswo$$_':\-V888Cw%rlGIs'7:SZf9w,#@ic^KңJ;e PFCY)MSٶ]<4@qy,4L4u{{K12`f0h0;^{;A 0ptuuEgeYܗPtwwNnƽjN+w-qjwUeׯJTx8sU{uyyT*j4}W4h4p8TZh6}0 E$C[5 5MFWs(p,SN/ө&Iǘ},MS& A˗/ Pe)MSi*l6_U8 Ðttt$I tƂ~/۶U nooIn$}k0e) .u]UUM&WFj6 p~P HՒ$ C]^^Gyk0}x {4+y8e۶ܿ' |ߗ8Wn cS!_OVh=8no]sKWWW=n=ϣCG0d2ytXgYϋn2ȶmy'TVnK94MW^볏yq_ Pfsn еRZm{;N 3m4 `xQi_Al.UY W„xY=}}Wظ?3_L88 PRyL&~q/-aqxhޙ{zџ:o IDAT]FCd<0,a^c۶ժժ cZ΍Cٔ8my x<_[ѳv{+֎ao߾=fS)MSS8R*g5UinT,l6uvvV xyv:ٶ(v`j)iv]e{ɶZu]a8Hi<r}=Iz޿FQb*|M 㸨b}OUө,mr]w+{%7 zbgzTyz( ]UQZUV[Zj,trrRk^<Ȳ,IRe~ \q@}o,˲亮,Jfa~JU2sK.>fkqXT9y^ńc$I켩֝eK9u˨?!βfP^4hy+fPR,}yUKڮjeuUךJD^OmHlei]3OEs9?k}sasqg3Mj˲V߶5ڱ4AYOt~&8[4_8V[9ud+knI4K*;{{]8 ~ ~Bu~?1ܷGnm+}a(ueYփfڜe>\{ pe1Ij\"%+kynj9]۶ yEyZvb̾qXO~X9y>/.=ۆuZ6xMJDj۔ 6 Ӷs۷.Zy]/o},ul6Z-nM`~qXw~O/yluZb6?^zUeorO5a`~ׄKV].|*su=fYe)"9Vv%zufSh<VnWi*jiqVz7({m.=\r*JǶY!yqF!y,d2h4p8\ZR6s^+l nWY)k}ռ~}i:PfSqiZT !h4RVr8%uN#۶5We1ZVQ]^(g/˲K̗ǎ*uxk1Xag0T,3&5g뺺VU>}FC^ؾ`v~0 uqqyqF=}/e7ٶù͵Zmqe_ubUl+=&}Ewwwׯ_t]S>5ieOprGөzUEu~~ileYdH?7 e٣_g _:"2)byqXu``rm쵹^f5 ٶxnt] ¼wbN 7Ueԋ{yn,~.n+ǰ@7/1^ַu]ϗ2-7{0 vWݳvVx&M&⏩B5K(T KA DMYh۶l.A`0P.^cm6}ϟuuu+USYn/S//-S*L}&_R?8,VV҂@c8.BjyiBY&L koY㰪R憹L&m1a\W\ZTFVf1^U6R}p<o|o0/r{S4ޤv=WA3:88{>˲ORܪn+yrQ)"}_JJZ[4[e4U+ g\yqbج[.|vn9Sj4m+~q,km={1y깻;oci2a}?X~fOvqVTƗJ}^<(cc}@7?_cƽ{.R}15N (Bfi ƻ`4l.i*Y+o>yNJ+-zri{/ h4hϽ<ϋ0XZ0T`0Xy>>%o3>+Ib˫7OL㶫۲_0K6=^ &ITjUNG'''ys<&VƸhh_AzY{hoӮm%scá8uU{Κ@sq`S+CAgzRV-T_6. *<Z>Zӳ쥏jex&؎h)bg˧e$ө<_IR,u]y6I ˔Ko~'|y`ŽT9۶x\x]񮘐fƄD>}Zspp60 YZZ]qW*"-/UEå&b5͍_g*m.5jl^e| FQ17+biϟ?'jumйK߾}{9TiپUsj,uA[WVʞ//y40 F^/]|j>_eBf&lR躮6>8J四j]Uӑ=-r5ca(۶8;df0+bηZ}̗ TVBY˲98M@\@cYZV%UmʲLjUVk `<{jzMSzcUU]\\,糳35 9J2%tvN0 yvka(J{pyy)q=berGfss~ pnޘj6 pn~N&R^56w,|yyoh4~x9xFEu&LJ<{yO>V)+qcWA(FcA=9#qe&8`0(ۗӶu ooou{{'x[qF!y^1GG\''' `5t]c5☣H^oud1 C9#˲.IUU9#9cbY,R LD~_FCNGϾ_bFjZq=yp,ˊõn,}j]/a(󔦩(*>5,Bim"޴}//u4m5 )xFJ?@o_G35JE_|QETDVUwss#qtxx}~EZY_~C2rlGIs'7'.\/<^9ޟ0 %mooi> ut8m{io߾1$x)IUi(t:U*y'Ibgl$ e۶4UES>`988u -]0,jiooo)7 `|{{{kYmT*8@-op8<`0PEY1 [TapJE_|Yzl[jDZ08ʲLIj:{.k܎HvhcŘ#s_>OPՕ3&5g뺺VU>}FC^Ox z=/Uo2o3h4}oeWAs_3_F}ǽ2ڷ?8Vem{ /1^U6aBUwy6='k۝eu{V9qhPsODjU*I"h5Z$\וeYk 36YqXL;{,Pz]Fqk<۷o2ڷn4Me^O8.ˮ=A!rGid$I}%~̿WU%+:^ojU{{{E<庮|W$2Qoe|.dMsyaטٶ`ؐ?<Oz[`<A׳K@[gggs{.#]V  E_j~{>d:rG_V}̗۬]߯Gͦժ,RŒЫ SaؽzM(nOٽ2-; >x,˶biWx4M GQ Duz{>Ih0ZV֌K^6Kݯ"`8.>o6hv٥L_ximOgc`PʲLȶmhqU*ROvVE9^EWz.//8 uѧ,8j6:==]y(}p8T:==U(E~ĮkeY_~Yo-'Q_w7?IM0>VǶ'}>`|fO;ƧOWR_bgF `|ߗmJTQN(0 غ_~N؂ } w `V]]]NӾ5tuu, x,ׯ_vue^}9#I\Ih<k4)7/(o~=guaٔ\:??mے4MeQ @(|٢,˔֏80Tt<Ctd۶(Rכ \U^|ف[g#>(oevK&IvMGB㾽KGч[RHܱg+v5_|W^뺒80 _\ij8.Uq.:(*5~l=LӧgGGGj4s9t~gìV0 u||8Uae$Ivt: `yHR^Wx<ɳJXVKe)cu\%i0h0KZMʶmi(4 V^+?sQ9|=8WM<ϓwvRueY!0>_|WPJT{Z5wN&ٶ-y\x$Ǒy{{{k6۸iX-z8b۶UVsqGjU5TٝNGi}XTy&__cvquL:Z }ceYV\fyo߾ʼvy?{8:0mjc۪}~m[3/>`|TnWKn.0J{۞/IꚐu]q8`Ԅe/gOFʲLj8Yzɻf맟~'vR$ :88(B S]<_-b5. 8g'ǒ˶bd&z4MW.q(c>%lx<~fZ"Ƈe`k~wܼJڇT*Ee_ަ]m+46gsy+MSy'bMX0mXy?ۤPsEh$IV; _MAujmBaʶm9W'feN#2Rogy^Vk.d}rkMatd0 z?U$ʲLm{Mqx80?eYVTx<ϋ6_\\,eV9bvz9HQ4-SmEQm8qٶuGk%2m&^dz=<}Ed]Uj^qmzn{M6Rnυeφá0\:p8\ӧC(Rѐ*縼8 @+Ǣ%z]m˗/JTeɶmz=5MnR$ʲLqyWTm3/Yz{{b c+q9,4LDZ \K:99Q^Wu;LV2ȳqak6 Ij4EJ+ug2gnWY)c :eݻ͘EQƬnk4V1{M˺j亮,R$Te #%~7l?3*|( keY_~GNM_C(I_[zΟf``,RՒ$ :6dl6F l^VjۯrYxO`x<,I XR(B:uu}}-{PDENGm+"z=MӹS$ JEVZ0Af,v $6W,ue!ƻwttF18{V0I<:}u+{b5,˲=4p8sonn8~׵gAN(\?RTA=IEQԾuy,h4RJjr]Wm+MSEQ`P3/|ƒЕJEa*"xNTHpe<}tuu%?]Ge{츿y޷7h4"ƻܞeAaʲ'~h(MSi*\{Zkֶmy'TV$I8<{0+^R0 ˼m۪VV {H}v1<:̔ȡ=e@agHKxabцE9 ѣ$ԍC7jݮ<ʅO"q<_(RVSXOR(*ˍ}?bX[ݕiS]d2Ih4*|R<~hsq_T;sΟz=j5IyzⅶF]gָh$LȕjmuIJ>.}lNN&^Pv/II0Bи4/0 #RNժ0xM:R(dZuY츟w-sNIɔv{c*ɴtbQ_~hxJQmC+8 _q* þ8&{mWɉ­aKV}}8l6+t*Qay܎fܗ%,CE߰Q2}픔+++K&)ck6j62 ClVud]PI#+`2͛7C?DLWYTnWlVmu]IauZeM < u~r8FsA4;~VWeiwwwgΝ;3Ǵh鱚 8a[9h$5 y9mZ-,X&`Ģ(J`I*J}_BAz}`:܋܋õL6WVVjɶmnL?W.za(iɍll<i^NO^_I}ǞZW\s(ښ VWWy^2uzVW"fVՒuKm۞9p iq8evHzT7.s h۶wssoՓlՖ8/d-i}6 c\[ϪZZ&_}_ei{{[|Њdb `̢(:f5DUVK4dJl6+08 Xj fs M^P8j߸FM3߷e=_.6wjXġwcgёӐ3N^i}r&>={zӼB[%2Ms?})˲ Zm[rm۪T*NUGemEj4NNP&Aq~^NLS}$ϗaT*%Ul8a$Ϙ8% ڢ(Jx{{{K,a(ikkk.}8˸/0T6UTG^\{:}.K5q4 ǏP($FFcT8eY2M `\kez Pɗʽr8:88HONNTV>#˲y7eY H*ʲ,;\ժZ B7GGGjcƆJ\MQ岎d_Tqq_}B ue PIU9I-rܧmgPIlZWz~J_Hd2z왚\+$ANq/$I~|Á|S5K)Iz!.mS6U\ig5Kv#z=:Dn50X(۶p#2n`!X+ݻo77z5s ܹJ~O715`\[?яGI~Tw~_I>3}חz<:::s_|>}JL[/uONNFu@0nwϟ!NNNCH$}IR{:~;A "ƭuΝ$Xv}e2I_x/_;%I/_0 oomOq_~me2!IH^7δ?0\ӓ'OիK{O1"EQ?zȱ5~_}?7o lu1o~×\+}(Kt]}Ix[YYʊ}}gsLFK}d2}7:99ѻ;pa퉥O) P&IyZ3vsLF?/yVW_ ý{'[tJ'|2p+++z=|R^o>z1pP[I:Oӡ/pMW|5߿w#E>쳾J{; 3^~wy'|^~?GM:>[zM*Wݻwn5E4~zܹ_WV1OΝ;}Oڗ?>J^O}Y2Fwկ~+w}w_ٟ?g?Y߱ݻ7"9-=%xpmVtҁ˗/OӧOGkؚռq[+O> BݻwY{ְ'i$}OW_%7oJYyFQ%o͛7C>|zꫯKϻw}/ q߯^JmT*"ƭWWID/0d崳Sm_z5W^%EUiI;W:hm0fjs=;iɗ_>}GzNNNBtܩώ߲sԵ65`:?%idbZ ;]99,PKvQEo޼QS&dkwaa:h8 ;O׿(J u}}'z1;w&:]fJV#ƭ;$mTxRdd{=d2{nrtmz(_B/_LùNleN7S=}Tֻ+txli0xUKW.?.ZOn2`*q˗//\ ?# b~ufk̞y>qЛdtBnsC^ʊ~'不,_k=}TLQ\=-N!nyџgq 7͟-ݻTwCꫯzw?þ 0iu?I ҳ'|)λwJ: G5uY?я fcG޽{C?яsXF~oyD?Ϲ!x"%魷ޢ70>/翽җm oӝ;wVa?~3P`jnw$@_!I/|ojT@(X7ڟ>}OnBZn`!7J>*ʭ;\.wk}vwwu||,u Wʟ З_~  ?o۶|ߗ2 Ci*5 5 EQ47I&ѳg^PAn^_xE[mI.HeX,juuU1$6MSq u]: %!ƭ` ΎfyT*rG\Ntpr^wU*eYkccN`IXBZ_+IfSVK8L!"uIR6at KB0nq% Ðps&yr]Weɲ,anfya}&}Vd2*r]7鏝K_0sǼh5g,ɶdf9reיm[nU.2Vs]WlVtttDSZYYtE* NN#4ffyi]URia&w1v9,Ng,K\^x󋙦-ede)ʲve24dMs˲}n;dx'۶GRdBAimmm X]tzB8I ;?l({7%V:q<&2 ClVbQh4;ZMf/xm;Y;xܙL& jZ_Ǟn:nll<\+8izZlJK:+ Z]]/Qi_=P lrsxy,k}_i*ʶm&TT~,+ TR4 @a&lnnP(Ȳ,e2{*|ߗ!8(R\ޞ|Wkk?!ӯz~ӪVۓyIr|f9*Y˲T,LӔeY4ЏY%󴷷7t۳џ`٨ƭh4Z/0qHfS=766[˲dYtxxWyVF d,Rjv0RU{3l6Mimm-ѣG4~f'}O?jr/۶%Iv[ZM^Fp]WeI:e}W& @FCsk Bke{s}VC1}y7Zڮ.,78L;}qut/, 0nU, 84 C{vyaHyv; Rښ VWWy^RU@,L[("8*[=˨ksܶ2ӌ;vfI߸jqvڹ?mX,&?J%])Ӫjj*۶ ]˲>rz~@;uv^>6 JU>'wñ0Bqݤkaͨ5Tk~yK;ckO0dM5MYRtenz$Ӎי_/44́7*k(JBI".f>'\֚UG PNtE;MӔ裏xw58UW8::tNnEYVCUUA ֟dr4œE}z}N:w_:z?RV%I+diQhH:j8 g퍃!4/ ۖIDQa{{{ 2 C\N[[[z'rb~ IDATnE>W.\M8_RT^Ob_a*ͪT* yu19͸_}o>kf<;]L5ciǏU,LL*0"VieeEٳgt:}ی~w|ǏU(F1pes;;;,KiooOA( þdDT.ݮU(TTϥ?eYŢ?~<ܚf/v[VKlV6e4MmnnP(Ȳ,e2?T.UT|8hsqo42MSϞ=S2 CiV5cAÇ8gIŗe4c;</젤Z* Cy'˲0iXvN\.H\Nm˲v;7VTd4R42?h4ar^8Z CIER2˲,vznl6+˲ܮv>2 Ca(f(R$۶eݮvvvSollT*%/"z~J_ 9 /U$>Non`! n`! ha Ku||]:CXsp||<_. pK2 C:888sqp||R43/^2J xBW*,0 CRI{{{ [j( C 0nUYxgϞ} QXTR2m,K3hW@ @^`ccC>cm̟ML `B&(tZ->ӷbC T@hOh4E*Q[#u]y'۶v`Lʲ,Iտ7^]]M\+CU(^,K}kgggi픤YZ]]UPeY @fR$#my/˲ݮu"#F[h^ Pe%_wp5&?t֋8ԋ4f8^gticXaCx~eeG˺pڊHD۴mA TV'C4ndmŢQzQ!yjZsM5k۶XqlgZPPVS^A$=|PijmmoV\.7|[__y @r9a*}_R/\mZl6+0麮LT:Bj{{]/q_ ;^| L{i/Ul6UTfIL&FCZ3|>u?+3dYVWW/e-˾q-y6a `:FCk0 '.Nns2jK]^touUclEk yaw(ny^yYET(*s @ju'9,㷾L[( ǙVyvYψEGΖ;&uC[n+yjJvfIܸjqB˶v^jͣ1><::J8^jj*۶Y˲>`nUom; 777֍ۛy$]-~Sz-:[~~ kb-``|q֤khzMQ.29j]Ӹ-8^>O:j=qdnz$ӛ[x^9޴alYME|]z:5u]"WKRX{xG4)B]-8N5UhP$X04lv(G<4~ogyC jI,>uii/#ۚnspѤ0n(l6eYօ$dtd2C(/[Jud?sooyavfپ4 C뒾ƭh4S?~b|> dfRYԼZM+++rGϞ=Sf}ǏU(F1pejX,}a:NGz}nّeYiz왂 a2MSZmdeY*z>i6I6okjZfNB ˲d2wS\VR}ทEE>vܧӚͦ>|(qtppy} Z* Cy'˲0bXvn}9 l6U>t\ёrlۖeY9 +ziǝ9}HJx,L (R$۶eݮvvvȠh( ä?ZK g94,Kan^*ʲ,;smZ[[Ka0 Az>efiaATJ~~.>DK[oEo`f?|_{/Ig9dY֘!I0ޟ$ߏ/|8ov}0pC A 7ğ,ރQ 70pCV\ץ3Ke%X~܏r܀n`\[aX7xq8D9/.]_Ջ/ R(ˍ~Ծ)JBYVNN0 ֟qض-)I @aʲ,y'5[?e}Aca nR/۶%Iv{@L=^g|,˒t:t|=88eY.=SRQٜ)^__WP{Ͳ,w:}0 $З(vutttiwO5xV|? ,˺q=zHRIanZ*}IR^W^[L;ldy^Mőnfyaz4 uxBi[n\5U\UPP @<ٶ5H \m1ս2g8Ӑ4M9#qfn+˲8΅J, PI~N\vqζm_J<,KBA]:'t:rGBAjcccǫT*9yL&#qEs~vܧKq_l6l6+k>{l6wEY=>?}䄎Dk+@ mnn&HLF{{{,KV&Ms/xXv-I2MS[[[I^X,qAG%Ijݮ<ʅAfu5xmޞ [?{Rqo\Wuݾx~vܧ."j55́m*٬rr9eYa.Ɨu_\gJ69;dSѐ4YM8Z\3zⅶe\xgIV}ARNB3wn̶d kOn*\Y=MyiXV<뚛Dv9O˰v0 e f}$9Zzfi2xʤtkڰeT2pT*J7o>9oZqVTٔafr]W&mJY8MWZ?nWlVmu]IJn;h48njtrrrГ_<6eiwwwgΝ;smu i}٬ήG{˴>⺮|O ?ot0pr_EI,IRIP(^_h]tŁy+3JZ-ٶ<(ښ VWWy^2oV Gi?Mgbofi}5{4/r s5^_n{NE YVKIm{ 1=/ǡ8:<I:~&2Cx1Նa(ikky؁|6MX3;cL;ln7 PTR6M+}y^r^ P&4MS{{{,k3 5Kh4dYLB,ǏcAqe*s;^Vʊѳgt7j8荧m9wc 6mW?>f\ -RX9~fe;;;,Kioooh[/l6C9Dju6VKbQ+ Zt:׶_iKOlTPeYd2}/8Nr9 IWػ;0))HHAmS!UiY;0K?lKƵCكֲݹwg(SUFqx$_2xRBJEF)ɴniA,~UQw~Ooay^}# Q7=== r:r8f} $ /6kkԿɴrf07#GhppP~\':_^2mLcpfׇ`09mxBJU0 U Bjmm]4χTtWJJJ d7u?öoR555zwr! ɓ'p8o߾9N3wϞ=TXԈ U=Un$~q詘dmXPҢFXO=@YK jkk5 8p@N3{I@A`~_ B===y]K(&<  @ vp8r5<<RA@ekϞ=T"ݭn*k@ E0 P$@ E0 P$@ E0 P$@ E0 P$@ E0 P$@ E0 P$@ E0 P$@ E0믫_n(6-2MMM믿Nnuvv>PuA@v]?fKKu===)|ljiik(_].kY\_^;Sa6er>O/RDtÒP(P(dzt:eͶlu6 jkk[t}V$mgiS$0av]CC;vP[[[ZAΦ&I҉'͇C^W^WO=Z[[>\TCCyv] jhh B!v{Cx;v+O`8[8L ell,m0<ދLӺ}a^wKJ\g3֢|G TYqP5u t<ZiQc?^ ץBNj\j}|5-c~)ic>Sf/4{}0&S,er%pCPΝzpp0ja61l63A}OO^^K3)*mNhԓn_KKl6[~n[z}. H۷/grr<3-')f]A뚄N3aG,2 b֨zjmmI۟ۯNahxeMҒr?[.,]H$f Xݞ`e鍱i{p8bW y]*$f_j-%8ΨB_!6krv~)K,7I3$e`ʚq(CDLe#M)Iuuu-1^W|MMQWW f>LtppP^W I΅Iӑ !~&~v'k\__ u֑ )\BH)خKvosK&Yw#8jqk%:N$c׌Zrf:XVYxFN81T/3^zW8a>4y^;4 zr)MX3}@7~v`yLfcMMMr\:y500\WWgn+QV Zn~s Ź?HGB63'm!/g%CЂTB]B?K61}&Y@ `. -mS-ig(t*c= ?}O&XV/\Ig ZFfD*bk9ka i5{zzzUxnkR:v62Sssv!kN vwý̇T9wJ6I?[z#YSSÇYH(uNGcw!Kd|ׁB] ?ǼS|_`I:x~mB{ӹXͥ.<K ` >O#'śYM4555oTWWaE"suuu)M-\;cQԽ`!d+=̴;::!if8>|X?xT7]e>8N~/өcǎ-xݑx}IVKKK3?,.;4YFRmmmjkk+x>+S]]]ftNhՂMTDkœM\dS+Z@p}ff0xD"P8NqOO{8ɓ'uɨc̕H$bd>YԎǺp ֞={52n#u1k ;~B_Iح u\* }]ZqK.z}V.7Nd=^*R"|oƒa<x DvnG822bS}nf𹩩)/moԕ{?3v=:֩-7#N⎇\oֹ\_*YFuu]_IY!xZ]B8q'zjTb\gwLMM]7)D6ӆxe8B~ofs_rAKؘr>555:pjz)Iovn:;; m,#8aL,)nVG(2Y)k0s8f'N(!هzDv8x`Cumxm9Ijjj9/m`HÇcvl6|>:;;sR/nwԃ^ͦٽLg]1 r04 LV6Czk]_4TYǩlڷץk~vvvƜ믿g68N Q͖z!7/`` `,):v>auuuln[.KPH@ |h v 5n#G`R]]\.y睘vH4bZZZK/5\#Gpرcq1hCC>S?я,áum~Kjnn6zzzvy饗bʶEg\ӟ9r$t/ y7x]]]q3 q-B^Jkk:;;׳Bz޸ٙ`0}V&p?^ @ζ}{ u({ߛƒ266={I^W.KpXlv9e^$}3ϨI;v0 7HXx77Ktll|N*2{,m?88}Yn[6M6MPHfJ.D"g,fZGp؜(7000Ӷ6ElLˌx~V࠺  !sٶ_GG9U16R b<6raD׼\__8 @IGY`.:QBD"zgzZ(?\NId%x?/׫:ovww'8v/u"iv``@w`___,f6,+$ݕjY{i]K\N;p8={'Y$ULqwFe$I?_z*3333m55we,ń):::AEpdT?UަvUf:]my'tq..]п *S@@ hQE `(H"A`(H"A`(HFNM_MTXV*6=$i6V,$ȩ+t }ɿ2pY\$wgߡBVQȥw/=\(?{+VާwnMQr(G9Qr(G9Qr(G\kY'E955>3/kUlzȼoLˣ;G97qyOX`(H"A`(H"A`(H"A`(H"A`(H"A`(H"A`(H"A`(H"A`(H"A`(H"A`( 'Opļ>00ւRGGGηz.I z ^|X400V|>~sP(jhhVCC^x<1lڱcG>zzzۛq8p@^WCz7~6e{~nkxxXsȑmnn4J1z|?ynlT׫AMT֩vvafgfLϯ Zá1n3cĉB3qUlzHyGOxļ~]>WR(v555QL`085}bZ^k@q`` ܺͿSmppP#k6?|YFg,QN mlxf}-s񂡹bd5ݚAk.g3`=wiɺi>Ϛo6-cnZ.W["u:lr8QI`&~b(zsG555 ɹAH):8,@h٢޷nzXA993kd:Ԙm g5q$E:M$ز Axf}mn]XY:Ms}:ydAxkر|ͨ㵹B?+~RX9ÇKNرcV$1MD%S`МzNtEoá??6>zhZ?֚5k̵`׬Yp{HD$ך5kg… :z^y啘sۼy ?sڴi֬Ya+v_6guVov}ePl&NS7o$?ٟgXhnʨ Iw%Zd+2@љɨS@Xr|>$t=\b@vҢp8tW0%I$illJOAF< IDATUVQ5kh͚5jkk֭[2*B]IzRː-<@}[ߢ$OfT)H03bL=S^z;*=֮yի>^ǵLtMػ7nBKǪ|O$IF~Rxn'_ UWWgFrm}[~?;жm$Igv%ǣ3gu_e.qب/~P^^Z* (| $~o߸5}/[s5sn{uUlޜ7tk|\*+rϟ+ԔVۺy>pA{.X%|mfvbu;Ɍ%hbbBN3*\RRZMLLJBNlذA|rAѶm۴uV5 \l6*А>裘>t:@֭[6Es!*+uk|<۟7̌H O_{MJ5y~vႦϟתʘsǣ2'a+5>7P}U3[wl^oTxmߕĵ/7]|=sdR +E~wѺČ \I{@ٱr6]tIfc b\X,ܹsq 544$)3>rKTnMQldΝ;ٺto^jqLMi*bt˖Yqp<(Ink{`Om=0Jӟ^UO3";eO0㉚ribbBP媫ӦMn:UTTkJ'${U]]W^yE6lQ*tΜ9[o0:~xNО}YUTTW^Q]]<***411Ysٞ_cc} ٳzTZZNUUUyӐ JJJxqFG 333z`A`0()˕v///s=!є%%%ںuNy~Jz;wT}}9&miSNOT[[|;ނfdSSIIY7`PΝy=~˦rcmj s:~xoذA B?|7A% n߸k?VUV,ә$I/p7n $ ~kZyl^<s*|y,n7Kx݋Wz$uu}\GIXr[_,/;g=2jI]|\/Ә9Yp^۷oWmm$˚Qmmvk֭z'n:MNNTNSO<Ʌl<vekEE<Oz|Im߾]|$iڹsJKǨ._li~ajzzz`O}Z###Q7l ϧڤkJn߾]~yy~iUTT.gbgy<>}6x<:sLNo֭~m38S[[4hm69NMLLDeh۶mΝ;S 4%uVUWWkbbBov9?ZH䤦UZZ 6,uff&*駟Viii5Wg󫭭KimFرcQuE5 LŒTZZ!9s&\H!]\\_mLQ:xSNJ5~;::v|._: ~_g֯_ֳH`>]ᆱ2'jZ\3^YV&i6Ԕn~|xl>J}M7Kwyʲ2}1}#RC$Pǣ_\yOk~nuYJ?2W}i|K[WWgNٳgu̯٘+WdkJFE&''Ϳsv^g 裏>4ٓgΜjQsMйlH)v:uJr:q8PQQau2.]{s1,3PJJJ̵\E~g;s璎>HӚGթSbgϞM퓵C:חt/qdhlluA=sА?w{3334[RRbN?==Ke ߎ$UݛQ{L*+U^#{gjJҽ5kkW8.\P$кݻѣzQUVi__<\9آe95׵K~5.]JfޜTwS_4{%Ę~cd[ /-Tp ,x2::9Ax(k:mK>;wJ5S}Nіqh>::Q6:W_}uѭkq[t:K82o_*uʕ+:}JKK$h!cXLX(@@]uw]6[hLZPG87nS8%Xжy֮}kת1l|[آku}o{z6k#'"|O̠3k/=4S[[z38Δׯ@Z6YhENryyyL(3q8QFȘ;ٶx2 ;w\gեKtE]z5e.יΔLi}=^^Kܲ^_=lt;~zzz^Ϟ=M6𡡡#7t?7s7WS]F222"ǣy۶m3M5րU682;,ǙeͭLo DJKK r M'cxTWW'i111gڸF=$ბΌLba=BS6:חt/qH0Ԛ5kk.=#I/^4¿=;SSZ^۝؇u*eef x]_XRFnϩ0Vր <=<+wͩ|.}xDJ% y ԡC$Qk۷og|Ak0/u\FS|ԩSt)mذA7nT}}***O'?INi]HF}&\N3빖3 u}t%bLo]QQciÆ zǏOmg.Htuy"JlڟN\}=^5@@UeKiyYW2{ րnʲo ᮍ]]V/;(YSQs Oc4/T0 zX/4\lǙ͹SZ3D`6OCleZ/l\gW_˗%[/v>ֵôF,Q}[_O5Z=zg3n|1bYs7S녺b%#^3} UQQ;w4tk|3']36s}y¿#8Ke h\몮VUUU̔Ɣ:N#^ &֪TQLoffFP]]]Ȉvڥڄ^QQΫW5XF}6_|#ƍݐ9m۶B:wFFFTUU%ө[ ~/0o|Tr΄Ukhxͨ_֮՚͛م ĝkfj_ǵf挶ϫonYItseA3S;mdK h7n+))Ν;[O3FʌlllLqg ֪1XyI ds~_\Էmt:U__fffrO .339qI^`&㨤Ĭi84/s?.//wIRoooTpʕ+ǗH旿Ld gNB޽,+7Z*J{lެ7nO:rϟg.hUeeFWkVr*Ry<*x4߯+tƔk6oV޽ V kqs|X%u|[oF׫BӺtumڴIڸqcN333:~vܩ*ի:sfffsyovܩ75pΜ97^՚ȈN[ڶm}>}ZΝK33˗uҥ`0imܸ1k 6hݺuFGG5<<4iљxM6iݺufwqTZZ?0Uڹsg,,U[hmʟ_lެH `[eޝ韍f\ 5>nޝӱB]Izs![k0rgUEE; 6Yjηب۷:t:[o1 ,f 1X}[ߊy ` }]P+C4kJ`ƍR_[7]gϞĄ<OTfTP, = $inUTBڶm`T bN|ۛ4*))ӧ522Br1gZ?aA@AmݺUGӚTII***$)ẟrʕMu=::J!R!G@AkӦMZn5==˗/khhHΝB]Iz-?XN2]o%UŁ0 P$VQ,MgrIK;}֭} iagJݘϞ_^y=㖾j*CRn'm73-$ H;yoHR_Geeɛzw[ևܡ+VvS`,$ șukukꫛok^」η0=Q_\X!ILRpJl6qI+YY32lewQn=9W+4N&b:ZGdY k~nfE=M `}zho|O% W}m$I5qz +u+i~NOIMIϽ|qK{ j/ǽhcg?<{ ܧp`kV;J]]!E~?;+Nߪ[HvW*_WUy_t>6룣~Cڶ$3d྄mM?+t;dگ:i}w7V}YM[;{^g^1_Ls5n]sq}Lk+d}6O_&#3︥VuC*7V_z;Y$#:/x]RuW67ٯnGo^?&X/hUh}9+W*o^]]AL9*'m7c~H`ovϴ2Yk]ϣgt7g~{\_Ry(EQ 7+_<ͅLYGX@ɮߐ_ҌL,#xG/ rju:ry_W(|CQǸo-9_S+Al{+ST+u}jOgϯjn?Rgj;dӯs1F QmҺV~ܰ/``0ϹNZ2{ ]ZiַoHg2헪\g:Je),_zOj;@R;zs'&ҟ|TfkS-3H+\jsOG}lq61e/cLm:W1UI; z\WƯݎꄁG=2ϵ6ד޷^;qIDATsGoI:n*iqZ3׭x;,~~?ɚ](r7`j2.~>ץD> )iK\iWY{>'oCAɾ뉶mWFf {_T!4Rx>mDOuKuS+tU1L-4k][3іԩۻ{ж3$;@%t+mA\%.BfjrCp6]rNs:ZkcL `-%9HcKꠓێ?dW<\fŧɩTG+gVu;٭ 3v'G[{6u'bSrx}|9{σ ~[b&Ko.W679S])j4)2VRmsѦܯF`[N9fv辶#vijQrP/ZS[?<,~*i""_}`r)1h&Vt-019q+cm cyITH%뾮k3Թ3XN_;7\OzR<?lhu4G7GWD<g/' bͯPNΞ`?\Hy#F7vgUY̟qzjdl{뒅s-M_js|:x gvzg(/7rS+c#;+}k5/^o =ո'Ix{zY}JdO 1ݰ77->q%xܠ ?r]vsa? ˇ>ӞS0"H@  )0LN`Z,eddj W S__ǐ10,*]uUX,Qgdd(##CYYY p.\`01WVVVBgZI,g?(wy<#G ,`dVfϞ̑Lٳg:n@֭[uQ=zT͋zkM7pkY,wѣG_RW]uU_}Ms]b:W^yEGU[[77/~ mڴ)X:r /h׮]ZpNvv/joo׿jʕ3g}TKKZ[[siݺu gß,K&>o voIC&|#r8O~r-?O}S<Owmݦr9rD-ojkXΜ9љ?s}ʕ+#ͦ{'b]w֭['߯Wwq9n__ph͚5 :}}}B-].z~~V^`0;vHկ~5}np jiiǕ~u>_HOOsx&L1ϙ3gҥKcr VU/bt 9Zpx }_$رCrN>1Ȋ+$Iկt9'?$-ZHGg6 I>}?-IgJL[RYYJJJ~z|>͜9Sn;j?_WOZBZ?y-_\n[(I[| ϟ%Kc$7ߔ$uuui{t=BCbK!~aIR{{GuW<,Yb&}~I䲑ݼyUVV6& ~HTFFƤg1lٲEݚ;wx =[okI= MdeeDLV*((˵gϞQn߮O˖-S ͡Ç>{^| f3{֛oGZxvfϞ{/cxV^|]p\~7gokkZw^s_g?q͞=[3g4UW]0{SOOO}CXC:W^^}]*''G5sL?Q uΕ;`М)ްu ~X75w\IROO/NH@G?j&|ɨ?:k󩱱Q~oFVU/z-;w.b[nEۛ]^oľ{dZm֭[c?(gQ_??E裏,wx2zZR]w̙3uY}_7 ׾5=Cڼy:::B# %! M|oQ .$Ѳ8ֲϟÇko }}ݧ\:uJ'|Dʰ),$?/I:tnG$a~^ZǴzj3o&|IԩS׬Yp Q0o㎨/>O'POOiǎb5ENXW_m=}N>9s'0's <@__Jtwŋd{uys+V(+++n__.\`7?I/$FҥKz500g=s挤P{c>KdqoooՉ|pǏ믿noOn =[*--fӏ~#=3B }СCC{C_[[oYO?~XO֍7ިm۶%}  i6/"^]wݥK'~;kƌ׾'N\vرΖ_ŜxH>r~Pu?oY>lu9֪Ut?wl"7oN8yi֭wt钖,Y\)}S2߽{~[n׾7w/}}}q҆7gC 0AO1|Лo-[wޑ$=ڶmn喤0%KHz-zUwuz-\PǏWMMx|/l0#i̙3ڻwopR^^֬YeggөSFt}tW3n]tIN8SNIokFYYYfjϛ7ZG>:uJoy..\m۶gϞ_kC߯ۿu]K.ԩS:}9NeggwUGGvE 0PK.A19<;Q,Ї\L͜9S)߯_˗/$' m5ZϟcL˗/ZLteee)3st)Ɂsd$acr0^uU?駟֖-[89`0(׫@ {yלƍjnq؁Q'N `={VϟOk0u1I1Z1cfΜ Y@@~_.]R%]2L@ K.ҥK8C@@  )0"H@  )"w,@ H JҬY80\x1R `H$ EAR `H$ EAR `H$ Edr `;lIm/$= EARERPf͚qvW?WtQ/l:/^L )0"H@  )0"H@  )")(IflZˆy+zG`H$ EARD&bkmmZctFRWW!ٷoc]QQ*IRSSo͡CdC#j;Iz|RKK޽{rvJJJF4xBmذA.KuuuC)Blپ}n:mذ!}dL4t:exp8TTT$͖G%%%]ͦ"bbرC]]]]mmjkkU^^N0}X9,FcduttZ^W.l3xrTZZj.w:rzڽ{7_&4amnnV{{$ ;t,˥FntrRV0&ߨmSSS!FTUU=#ݻw34RXXhVe]KK!n<O0fuuujllTkk: ݫVl6NҡCT[[]svڪ{qN%]]]sF***JCEߝ Xl66lؠ{ycc |0HcR?cJǨr\CVX;nBr\P\U ౬0LG1oYY^Н|***͛UWW7>ʴk.9y<vnڵkL=Ωn4NUUUr8kUUUڴiv{jkkU[["|>uvvfiݺuiݺur\|x޽[-ٍ9kTZZJ=zAAp8FOf[C5$2SSSR7UEEEl))zDp UVV&)6伱:_Ν5hὟ^<:::o߾H?_xR9V1`7xܨ穊 \.566Cz& `L MMMr*++xzi&8^֭[905=|5xp8TXX8MTss***Mmذ!bE̥5aIxxQB4gx-7pvCSee֭[sq)Իbc:R`Ɣ0xd6KKKUTT$׫ݻwK2ZSSӀ1oxj0۝ n-[lNt|Ǣ>T}}roD{Fؾ}[۷ot:͞CvҪU!ƟSb::;;lL~f{n|>|>s.5%.idiYTT4V:c(昉o:' j9U㺵1?{9N稏K *//7G>_$?6.yUUU%ݮʘSC|ySSׯiQ/6ۍD34V8S{&:ֹTTT7鞌^{$|0Hc0&w8V+,,T]]v:;;=7XC***ƴch>Tŀ1W$d:n{DMnäH UlڴLl>+**;VǙ߃*"ņn׮]QxͦREm[QQҨWXXhXE>_Qٴi9$Y{njjJx.5c8or۲!+cV 9۷/f%FGGv`*((0C.Ygrh|׆*[GGUTT]ve{L֭PAAԤ v8p@G6Mv]w6[Lr***R}}:;;ep87 g9nכ4YJ7oMss3s00}ƨW _6 uvvm/Zvy^|>uttEþBøyTTTp قhL0 ]3dDgUXX\W]]M6p2Xm7ުUQQ29l6uttA]]]***Paaa•8C|ԦMt:eե={LqP]] 6vrhC&%F---*--Ugg5XSS^U{{{9:aYfq6HN[^^ IzoΉWIHJkk+'!ŋsL:;s`F>S `Ԇ u: CiL֭n79c^2HO$TXX(!%׫N555 HCIAI5kgٽ;_UN\IFQ\x1rz 5AR `H$ EAR `H$ EAR `H$T} IDAT EAR `H$ EAR `H$ EAR `H$ EAR `H$ EARD&UPPu֩PC^WGjiiQsssHz!utt|Tn[NSv]GG:x^kkkŸSׯ$l6>|xm^-[fL%%%r8$ǣ3v/]T>BUUUݻwaTR `Vmmm2..%ۭdhl6rE,w8r8***`H8/EEE=>o=`!l6=#%]I&=kX'V6-**)kaavmWWW{6vqӦMq|n[]]]C&dKJJJ؎0VRRb&D^*++mt:UQQ1ٳ'" ;}gϞ}Ni[WW"Io|>_Ķnt:#r~ɛ6mRYYYJ\.9aX}$+giWWWDXVSS1ۧOt:#rITPPٳG]]]c6mJ|1Pn:e\LƘRMMM2# 9')ÏpDlgH\.9)=`"}mp/Qﯻ;"aȰȓ$uAAAD8|Xn0uFnUZZ5qiiic5pSSo˥ 6Dt:wI=/I]q.֭[g91*C7o͛)'5P 6ĝ !b~C[Nn[G6mL8lڴiwn>O۷o7_RsscwrQАqh=`#1+z(kzVWWDX7r>^oDXo.i33677'| 0FҌ޹n[ϗn5{644ݛ,ϧ׫Tn[NoWWהTYY Ԥ&'{cYfq6`ݻUϕ$nm;?ŋzo+R `H$ E)D:8HAR `H sZFMm\;WOXt_!=bԲo<-<R& /꧿[ ]O99HK֧9* 0sYv@ŋZqc1l9AI#?\=~"]57~/ ٙ^=aQs<`NHc|:GtM:wުWfꕮi_$!<_sxqיˈ U%۲اe| 'R11\s>3=yzBeeZ^fǤfG /gg[/k8YH;6xSՁ*͈x`j:{N>S3":^ӯ~=ڎ['0~1)~Mzip>kΞ38! xx !VL?0G)/s M|wުO͐$} BAzS9} zk6+jۿ cֿlMP5~uy^-^/ -V F^҂yA=X;C_~`@ڎ[U U*wTs}@< VZZ3׃3vjgl;^o쏚nN~PG_X`~0#jy9AU0o CؖíCw^Ҝ>ZRu9uhx?O'{>hL1Z0i4 ]P ,CsSO5T [c&tM?RsZ0/Tά!kϕLO"ԑT|W l}_K -Yc3KmSp"+-Lˊі*W h}߼ ]gŋ¶, ^LD<${>Ȗfr. ]Ƅ{O.Pj-//K޾Lٲ㇇mzԫ,J *޴P"E>,'JF02FF`xA_ `qz {vx_;6Vl;60dOJkKV{*J 5Kߙao zmXM:'"|^܀OgzkWЯj;_U{0}ixHRv=Cb xH~}ӑ='Ⅱֶc<@eg$z]P ޻/;/_c/'}r.'Ґ @k v]x/ȡ8ێgPX'Ą́pZ:{.{ٞ^qk|/mǬQCvEL{nUn*A<ċNL-iLG+̡j H-1ok<86e k1>s\ke bŃkn\o𼺒t5T&[0/8dì3zw}#QnS#eeK~CXΞr@s6^n^"za.W8`<=Vm}ƪ̐kn@ŋ*w5'?juFKԼpt2j5ZOcZ?Uӯа[L8chz~ͻ$$I}OC.N4@@a<s3cuΓV?gC.]LcDZ6g& !V<5*[Әj9A}wKuժGvfqR MƄetM'~u׍ew̿=bmkȞd_0˕^_6X~-44b@Dr9F2#?^L:dGh6֞35s &oY~円7܂x c L61^yA# 鎧\LK|f_x9Wt͌X'Wf{~|ު\$q 0^C_~` x_+B=1f3멚~F&9A*S[+"r@B=Ԍ!rU%#5՜ y$۶s靁a^\9U%Q/ 5(I':Rŋ\9qU }A<ċ^~#v,\/o7n# 91)>?g꧿#tn_[Ѓ?}oa?켤_(7;O沸!T= F,¶,zx @<[<ϔkn@ }zE+SZue~0CZ8o .>}r9C++dgh;[vPyڸvlcs~=֗9.3u3Q~i猸nЫ+B sFdls*_:XPUm3C16P;^=aQ<x* #0xH~;ik~/ 5ұl3O4]zS~s;/i><ϒgut,9z \]w%SY^i x0 ۲Tb@K %Ϟ %I&㑝Yzͯs/smǬ:ܖ8ңsn@젺NZsƵw33=y3'?(凖\a}?b[{b/lRU0S9؜a&du̓;gx@n LEXU| kz<${=V0xH~;VikFűr~ ]X$%i֬Y /j c|'y~Xu w^ҜF`jwɟ+I:ڨw~6j˫QAR `H$ Edr 0X;k$3_J ׊39 z@  )0f rw^cYU2/j>SUPKî{tŨV p LN&kn@K*^#?\LELuL xQ@+6!^6.xa@W9U-:ܚI@ >p}ەVgz,nlqtי  0l

;bH%̙34D^_Ir ̿6t\c^&w3F}u4hI<ÇU[XXЃ@ t@0$لN?:IP&A`hIP&A`hۀ wIENDB`qman-1.5.1/screenshots/qman_open.png000066400000000000000000004053341510660157000175070ustar00rootroot00000000000000PNG  IHDRS׫iCCPICC profile(}=H@_[A;8dNvQjP! :\MGbYWWAqvpRtZxp܏wwT#eq!]0 Ab>'Ix{zY}JdO 1ݰ77->q%xܠ ?r]vsa? @@<$81@8Հi,yyyIC$SO{z%IW\qN;4SN9E]{G~t!ʕ+u1Iҵ^3gnkĈ ڻwV^B~ÇѬK.ٳبoےnI5vXegggSO=wZҹ瞫1c(77W^W/֭['NHl6~ӟjĉl:r^uo~駟ŋPÆ g}_555ںu7߬ٳgkܸqO /77fM4I̴7ٳeu{{׿u]tE>|x̠!C?oݻW#G~]~ݻ裏ngQFo{Lwc:tzNIQQ,X'* >У>$ >\v$޽;bjXy晚;w.B;V￯[nEzjqaeee_֥^G}^K,СCUXX_~9::~;``Lt`0ptC555izGDg}>裘ϙ# I6Mm6M>]^{Z[[_|Q4ZOҢ#FFal3G￯;C'Ngy~gtyiȐ!رcSMMMڷoz!M6M#Gԥ^?͞=[G.cǎo)SHlb#qb(/_.)VbѤItsd?Os_w9眣%K駟6i2jԨ=zT~_$A_B+Vgq4q%%%I-~mذAZDCEga߾}:콎z${/ٵr{3> ꪫ7?֒%KӟTǏ7%ٻR=|IRsszeu-H O?Տ~#~8ˉx"HCW.kJD{{߯#GjBk?~7Ã+[,}k_zZ?iӦMuk̙9s~0G:TkSNǒjװ{n=wbo,Y?0WֈN8a>æ) IF ȑ#  =`Y,ڷovޭ#GDl?zh3裏8Ժt 577oڧ+R&MR ЭުK.DOnx~izLUQQO?+R{{Z[[>T_z::=\38Czqf9r$w۸qz+DPޱcGabѣ>"M8QӦM^P0V^|ź袋{08ÇkcdS]riʔ)f]u8ӶmtgvyG1cl6ƍiӦEk׮U]]]wL:AugjZd,YOC=904$iСNy<_Fs=G}wyG&LЃ>Cz3=}{ߋf׮]jiiѐ!CuV=zԜ>9_Ws9UVV=… pB{O/$^M7ݤ3gSkkkۺul6nfvi5d1o>Ս7ި.H/wء^zI )4R ._r-B  '=J1B?O@\vefÇ{oTSSZZZt=\^{M׏cI~NL둨Çdп8q"nT 9s߾:'~O?$-YD=>ρ0$!''|p ]u֨<ða$I/֢Et%h:qh߾}IZp~+_,ϧ?P/ڴ/֝wީs=WCձc;Yk֬ѰatewG~T__GyLǏ5j(AQO>|I͛7kĈ?Cڷof͚:>{1okĉkE9vi:q߯_rݒkFRh>,k!͛7O/Vqq {Ν;_֍7ި6 sҥ/Y,ǣ:KEK/L:=zTwy-[s=W'Nо}{u=o|CYYY:~xB``8qℂ``3`0sfT̾;Qeeecǎk4;vXmݺU999{^ =s= E<&L7Z|9 dChuѣG#:y|+O 655}ҟsW^^^SWKҿ*''Go9"0̜9S&LѣG~z0ǎS[[[?-b(Ρs?joog}Vv[J=[[[u}}Nݼy{=w}Hd^SCC~>   |L в{Np;_E6M999IQYYYS^^:6 رc:vXZ;~Q΁0^aX4h <jkkvX"j1ǣz3nܹSC[6nhogɍ: r󩦦&jhhf1ҥK%I555Zvmƍb *--ӢES" TAAA,i/z#ǓrcICC~TXX8 *<:]>نc=)۪;liEoB؀r4Ǻۻzݺur:1cިW544DkikXlx*5ssҬ{ބlͷ?i޼y@\.y^544}׾!*/WWW\m?"^N{9^gGi(60 4HK}o1uxI6lЛo)ӭX 1zK56ם5RqLeee4s:r\r8q$fiժUjv=" c[fqr|]dj֫IonuU]]m2r:TCCChTuH>+((qW:k97aLmLYgNT 崗Dm4]67wgkcj#'&Ñ}8x9iҤNߏ']755 }@!Iofqy^UUUujtҸAJ-_mvJJJzfwx4w\l6UTTDԑJKK+~֬Y#~Uiii ozI[YY))׫ X5 ,мyTXXUMe^dVXa(x;q=5ݜYAARWW'sNT `r'0z]SS֬Y#Ir:ZzmۦUVLRE.Fq.6ϗ~` ܬXB>O.+nݰcp\qI~1²5zf3_2 %EM}`N'/iݍ׌Ǫ_wC20_ wOnhhyjUlLiz;m쎁D^v)XJ0ƍUUUeN`LUYY۷k13%X@ݙ!vlbPQQ o+FcU~~>7+˨tTXXQƸ&glQprc tϨs1bR#}>_̑ Ƶq:1zQ s\d)c;al?iҤCw555Qeee***4NϞ_@8i/ҍ)gnnYH\M(|>_DQ9NiopFmjz+u:Y 7Av=NaLe۵nݺ=`ǪO5776ǓrPeeeZ^R2u6v=*bMTuH>3xS{L~wVptAƾxRh/'?7oViiiPuuYpO`4 x.Ɍ`m f/X~/ f@5@fYb^^^c}<^:*cZUZZUV{xFEaaaDjjҥf@Qs\=Q[[Fl6Z**m֭[555B둅7}%]!QMMMf=~ҥlҥOUUU~g?;w\Ruuʴf͚C***RIInwBm۶לNg-XOha}Zl*++U^^.U8ڵker~utӘivl6/_yn :Rn[sΕ͛4|7{:,ZHVH|cYf&M$ө-[Ad#-Mf:C2VXכ$^<;n2HϚfi˖-zZlZfM̙Z^#66-=pBԨQV՜&Q6lЬYbfz ] m6 t)cTXXpoi>pnkΝgV[[3gF~?nf͚5+fݢJUUUڹsg:aEEEZϳ7h"Y v544Btt]c6U~_#vG44h"mذA^7"-/_s됨&UTTn?hÆ #=wNO߯ ܹS>OVU'"z^_$ 2rUVVj͚5:=Z.K .dJ @@{92u+jʹQ۴Lדi4uԨ6nhgIC._L/E{9}`_UU9EOhVUk֬Ix 彅r qL '& =dcI;oh,$9d!@ 0d!@ 0d!@ 0d!@ 0d!@ 0d!@ 0d!@Ȓ!Cî[WF$߬WW΍ڦ%f0d!@ "$@wh޼y*,,nUSSv߲eKBpB544|T.KC6M^W^Wn[v F͟?_dZ}.|ꪫ^Z*++SIIv$& r\3f̐7.//Wee$i͚5ڸqc2`tRuuuk6M6MNS.KQZZjNgv]v]EEE1)9RTTN?,t0RfZuFsNI'عsgHp^X5FZ֨l'oXt҈sٹsg\.yp_'Fv-[L˖-Scc~v{4ǝ:,Xw-܍7FqFSϛ7O.K^WV5S[V-];| fe~G߯+Vy<nseroƍ G]]-[`MZh"Z<^@g:śv9>/",I+V0nw`P0Rfu\4ivl6|>9tƍqGk*--0x(W߯ (ܚ&y555q}udI JҐ!CH a׭ܫaKo֫+FmҒg[H^  C A2DI޴kSKF)spg 0d!&7iצ=Y}@f r> }dqԢ$2֕9>@bHksצf߳~ݩϧ 6,noՓ 1}@vh;YN7orH,8H `#fS:g@f?x]~x ]55KC} t! @lі:V>OyS@@ D#c?iMڷ?W~ɪ՘rnsa6-j>џ:T9X~OeOhڔcz{hӧESm_d KfO[}1WRv}mQ͞uh 6,T|~@AIhh]vdk{}vT7jA1?6-Ӧ-«z֦Q;Moc^ٕ}sEW{u~*I*ծshUQ zeW8汪׍ؑmj$[r?3Z?ZLj9_+cЇrViИ w:oB,Ck\55&uԀf\ЪTCugڵxN̒`ΛUS:oBnanT%6,q{ɒ-_:oBPM5 ܻ2~ŵ6/ 时Pṅd%"o0hxKC A=^ժm7솯9Ge~i(@+u>+ܮjxTľ64iù-dㅑ*>?qLO>J6taa64</v.|oK]ϝyi+o:`7{RW w6o0<_b=Rk09C't`⽿S9%g9cHhVnzKԽmU,iKYw{ޚJ $k+/iӃ:,}sWe (>oy9? ۰`TP<]Cmwz^Yo~Tj%u2sO]8=mTo#t55=9~I2Gv4eRK%}㒤ONsqxWCכ)۰^ٕ'QqOc%j*w-qGm-팩#ލvįL9E[ܡ; nǞlߚcV;;H/I#'ٝcTӥ.KRDW nmX5kc߫qͿ!ԨcEv8WIZlNyQk3gSHܱk Sg~?ѻ|Q!]>GI{&/ y$V>Wߥ\_r(VԜޒ zAo $m/}jȶ׌@mX;xOFxƈ3\dAehmOh+3V]8voҗvdkќ^N?#Y`AXKo_ L}mӳ9~jSZ,,a.yJ~ޝ3 r%31$9>`6>DNĚ}O=t %kAۤxKW(W@btRzRyl: ƾBw 阍2U6G/lN5cj nv͘~hnKY>:m6N_?QVҥ&cx{/|G̵:)_u7t!3ʕL(QmD5򆿟h{?Yy 8!}XݸxD\^1 1s*oc g ,~ ]Mʮk$>a<YdSr 7ey Yь⍤t9M86H6Kf2Λ V<9vKOU|~ 'qY%}l>J5(FD3g>C8[~T _oaʱTHrBӞ:^w5葎L7_:j7 ,Ԡ0`L<=4Ǯ7,ZOkwY4{_t͗FZw͗8P*nh̒Tw{u`ΛUS:QN#Y%*ܮ$č*nh;1,Es"*LaXmfI[^ <ރ3Tq<( IDAT՜2V~0ǫZF ۆ5MDuϞm~_sS#W:%RDJXɞg:~00˕L(ǐ}}P<9 [&bFnu m ͌ѝכ/@o(>?˱b'j3Es"3kr cKqMR} uƥNNIy&{֛/Ku5bxR.vQ*ծ}x(G#YV5}>i '9zeWdy5}<q5]?-49Ÿޢ{:f1lyiGvfX)G7!߭htu0=h-UZ4Mœ{0K ]Φwe^ѮY%rhhybnܝlǞlR7έC ~kv#+|j~/~i;a`+~Q!w=B(ƍH]mD׷TG1>Ty޵hHt}}zC/iv/m7їvdkզXw]jͭf~8p0K+7hK'`Pn[yi|t/1wU*) L_:j7 Y4dR=nצ~S搏}Yuo]y\FV>`=G8&A~gc{خ[WF$߬WW΍ڦ%-O{r sk{e-_GY\GpҢ[z>n0 H?t<ƍ뜬͖ 't<,yfɖ c HC ϗ,Z aM}L( q94fw D{x$%ivʽ6z$ifrn6---)}6s@ 0d!@ 0d!ٻض;DLVIjj>S*3I[%#EɃNH`ޭ3,Ǟ}f' l4y)Ţ aRy Ȗ޹t#=- wLDQ$~AlZ߿sO>A`萣/~Q(byg+}qqqqqqqqqqqq|\}ΟT Mps*G) '?~~O<]Eg?\rw|Vk?Pk:^T?! ZVz%IL`WFC^RXϒJDhqO>A`O>A`I_{>z~}E0 '@``]u}FgߦvշFzm]G*woЗM`<^?P(_t/u۾K b%-I y=6 a羡r!_;Rk@?a hOn= ޽-ǞxZC_!FX#:_z!=6>~>@WɎ'2ѳz_CT k*O7i>z쉧+ƌ+ܽ>KA`PR}{Zs{PǞxZGPHE=gJzgxxI];i-}Iwow>o{cO<-{xɪc{A?:nr~wnk߁CW_?ʽW|;۽N[~IO%I>óo?=tm |JjM{k//H҃ u} Te|z\֮;vj 7omw߯ٿzk~uSx=zvO=`νB=ёvg/{♆|^.޹-wu?7'. ,uv;~?@O5 $.X#/Wod y֮Lٷ S}Cܮ{vj[ArGV׾t˯2g(OIz݊ 턢>Fc([[.Xmdw`v߹?Ӿ3U럞Qx+?=Sch߁C~e{UAPgG;:}Uݫ?UFjg}h{V=zhmt 2ѓLZX*_=ͺ*6> |JsI?Ye`uv.~$ݽK]?B^lP?c2&h?ۿx;|<׽?gtɁǟԓA֮_ ۿ~_~w^oq:_T=L;|~I?PK2ohoN~[5Y4^NrǞx(Տ ӪLv*~l/Xr_7$9G_ ;pPC{:RwJ+A~*;z-}klU~շy[? {dg <쉻yF~s^ }v :w66>_sW B|5{ẀV'=u5[AՃgοɚ`'F/7k^ ˸4tmrmμ b/XWVjtL3v3m5SPWF7mdbYP'Bw@qWsr^Up2[{~ݯ8W40n |J|ҿ,V AzzU3U.G;x^C9Z.o*e- :SLVV#ޟU_eu/^׾%o6)|q߁C]sf}!O/`O E~}?A*IO?=g80V.շw:#>poz^~jO}{]~_wo=,7^We9{ͺeO}~=(TƇϷ}=AzzON>`F{쉧6qt/־uG^fzw_Leo9U~xI/jO}*k3w硨XE %ׯˇ_c=oj*W4x)/>*A|a޽zx[?xxUUoDrPkw{_֮_ HЏF;WZ߹<}aZhd{Uʅ|A_Oj"V.֮,eCQKC_zһ~o߁±?)Os\#sNy􉧫O6ja?xU?w`cǶRYE8rIC_Pҡ*1v÷䜇m}؟yA}o;~rV~x[?:C^ߡ/[O~?hS E-o*1O_ow 9x)SNMtB:/}C~ yQ6EGsgEuWl3'@`` ׮]̙3z:=h4y?Hqq% ieY)@cOX\\$ɶm R(X%qnKP(#G(*k~~٬庮2&ƞkW^+T*E111!Id2-799h4뜙LFpXx `,KXL|d2X,T*qB!*MqIm*J-r òmh{' kffF޾ʕ+x6669O$mR$Q4UTҽ{n#GdYH$ Nǽ`k&re۶eYJVWW^HDȶm/X,za -IիW^]]m۲mw FI&:}%=Z˶mj``@of r t yB!b1b1ٶY,Fe۶Ѩ,R>eYP.8r;eYrGXLuXLdRpػrH$ B!ݸq8˲U*T,*bݻwO|'|"Iڿ?MSŋuܹlǏ{A(ZZZUQ˲oǩj2|mV2s5228JB!MMMyt:]H fٚLx̒ѕiە޾;Yٲ,B!/`Ym2bQpXhk|r7] 0zF޾~)f^Al\ zn%ȼV%H\?"Q eY^7NWkȑ#-z?Bf̾5}{glllh}}]4993ٽ+}'2~Õr;44̲f3 FFOr$رcd۶mv b1aJ@$qe+J < h`k}}]:ydվ4==ǏoTW2X,X,} H$vbX,V B0[ieeERIXLD&k۶xser9I2e{ԩS:}fff433#u.۶588osssz饗466w}WJnݺgz?455eF"aiqEQE"u]% q,٥/JRJ&rG\JeYb1 {屝|+5YUիW]- ֐J/ŋr]Wm[ܹsp¶kinnN4661=5?% /Л4??l67ΜMJӒUK٬.\y]BAP L/--)4<^q@}wYh4\.I"I<}˧(511m8HdRmkaa%=8 n(:{{g>S_M0IR&QPP<o: eyK`/,N+R8$kbbB|^P(reH$8w\(HG}׏,?JTo"P8V>‚5h4 -u]qA?hg(Hzݎm>2cضU.ǑD8l+r]Wl6 H$"۶544H$z=\9rDeiaaADBPH\NtZx e2e~ojjJXLtaO"8ZYYi{vOfff5??xHgh[mrGW8VP[fɚ^XXP.ʤ._bXs-Y*۶e6b@?ڹ~J(D"12.۩G*ҥKm[x\ht\im,RTj/OdS' ǽ{bR>V4ux%Y߿_҃}G~t9XLdP(\.+hbbBP(}L& j,S,mUUJ&*Fm[hTe)˲,MLL(U-|lF&X=?IU7;X,=i4ZaPPXT$HS{a/8o2()֜ײ,aJ&e͞hT>h1f%O>:A? u 455UU&&3?H()JZ522╇ * U-szo}:9lqb4o>;y8Ѯ~TlۖeY ~m;iڋeYun^+'NS"7ٗfk2r%[5QfYɤbǩx5bڱRgY9BTlVPP*! ibbB(H4 Tzf޽{M7L&5>>RǶmT*iii**J ^@;~l?sebbBeP(haaMPʶmrȈL@t< xySOqVf4oVNpn?2h~-~Ny~_>#9:WOн=eddDp[:qV& ,|_&ɒcў\Nmghe/;޵Z]Vx;~B!/;rՔu:VTZn˲jVu̲snu]o|jjJ?y% eYϷc~WяGz%)NW\.g7i~ѣyV mw>;{Ze}\=6z>nynnfw3^q\/{FO1 +++~-fL^nV*$ɛ4gv7iw_}bhh+Fflie,aYY͈bU=Yʲ\o~l?slJwxkYVk\*?n nʲUN6S_3Nyc+ `INI̞|҃Lr\g\;6O:=_\V.mU{ms4,Ijspxj6j~2,KmT*UtZSSSfM]6I?J3}d 6*sv9)Af>;yhxx{MtM};;Y~zeݍ0zFDVeN,˛$L5Ye5؍󭮮[9J)JѸ*%9WVVOz;&; d3I],3aJƜ9w+ԏ:\i&i7A?#*N Tz}SmX,*N+N˲,/C7jjjJ?ϫ~mgO=\.{bA׈ [w dAe{>u6?r˔)G}5fZnB!oY[ DN=W/I4ꇕ 5<_cA> ~oXA< 3._=6gJyJݍ0z$qa2E m7yB]AϔOw[qfI]S^X[e&hSi&b1LwP`B?ڝpmw?{_)JUsz 5?{H'ljx.o;^W/{FOYYY\Ddmۊ[~Y׶-'c,BJ$gA̤8.Gf+_%,m\rY+++lP($q455hy}2LƷ$MNNVE$Q"ʹ psZDws\.{D*Hżd2_o +{,[LЯv+3NrcS/v^?@b`bT*d2)q8aDIF\U<eY:z7Nrrb9O:V<W4U$i{ ΗT*yݜy % % qZgY685f5A7n(ʶm9rīewB6& ܗeWR2T,?ek,J[I%,&hw+KKK,KeS>F̶+ibbB\.{Y:7Jnt]g+W'XZZ +3NF^۪W$?u0~E='i~~^###~PHbQL /c=Wh4R\.L&|>X,h4@&8_܃p5_t:R$۶hyT*Z[[6u/~k]UP8^(J* r]WL_,KhT\{hw+rmۖeY޽5kii˒,kszo}ir9/X*ƳVu/ϠC:9N:~J%=裊D"^rmO{];zew$$=#w?.bY:x< ---$IٶѣGF5??/jt1$h ߻I>~讀O}}7{@d2* ;b%˲dve6@oa h2Te ˅.;k.#>'r/_4 `O>fffj>Kf.㚘P>|G/ \.S,iddDW8$eY-K$rG;z(H0NTϸsY?yu-'r9B!IR$&M7/ ibbBXL/_@weY$ E8\6L&evofr:*k||\8m ꘲fr]Kz{ @cOXXX]pQ.U(nѨ!HǑzĄ$)4}LPm6{8(H(ƍ;RPHSSS,˻bH$X,X,U`J+<;zo^{lh4*AO,R,S>oiL&Vs]WrGLfGM7+NW_,߽\wO )fR1&әrY\NpxGǑeY*JZXX nrO3E0zR$4bQ*Dd۶DFU*t=\9rDeiaaADBPH\NtZx fe2lojjJXLtaE"8ZYYi{)vOfff~~kddh4ZsĶm9S/[f^XXP.ʤ._ݸ[! yD"2xL_tIeiddD XTs_HD=\v[i%M%iWB^]]m۲m;̦\[z}P((*+_.^plڜ!i۶d~v%٩[/?χNzu{A ŔL&%=3hbbBP(:& B7mUUJ&*Fm[h[ղ,MLL(Ue9_6D V~O{bsmFv{U:22"۶5??t8&qM]}]h`~}gM;,KDBXLTj~111ᕋeYm[eՔK\*H$p8\S,KpXR23Z~'bOMߩ EQVqOyv[_;χNK1x:B=%xlVKKKU5x B\Ғ\׭ر,KdRXLԝ3&23d1}M9ښPfZ?u;~OjTdY9BTVlVPP*Q"rܴ 3􇉉 YBIx۶ NLLTe&E"9rě4<\.W#G>f޽{-emV<EJ%ao"<䍂ZR(T*ի^j3^3.-Nvng~|D[㽎~| H222p8-My%%b/V>k75yGѶW.q],s_/B^@a\V:VTZ˲l`~YTtU[r^;3?Ө+'͒澃d-m%Hj&u%]tITJBAhTd) ۳t+J-MZ%I7nܨ+~2[JmK/>z޻9{u^@%VVVvZd PmV*$ɛ4 g7QS}bhh+Fzf"l A?l̒țvbYVזv"H*UJNdU.J%Emv=^??bu6 ڎvχNҫχ^n~^{]$FB^00fy>3Q ݩ󭭭T*,XL`Ƿ\r/vfWi=fvPwliW]hwݩrX,juuUȶm/j7ů^?(3zU@{χ^n~^{]?422{IpkI@+rmjO FC;l i׿DNQ1f[?:jK\NԮ)V)fNV(^o/|zu{A#Q9J/˲It:]-aYVL8jDvR)R)WJvKhfG3A &P V!n3zF-N?v<{|z罎:-;=37ӉLu3T@[\Y&05\LY=}LQPA<2Ѡ)RdܚT\X,zk&Z93z3{og]^G`FOY]]$9;Lgvfq>S>&cDj%ۚ 3Lba۶ȑ#۞O0Ap8X,ְ 4F۞Br1;Qfbq^Vm\RƼAs\_qoyj{n?q罎~`FOYYY!Dďmۊ[~ ضđ@bUPHD,Ђ8rgew[> led?9W\ʊ$ijj& 8v\ ?e/)HTMb1Mpr}2lx$GhTRɫo6`܊l6|>p8\[O7>>>^U&moyCxU bne\[^χV^wx:v {ER)%I9#q H$p8m`u]/ pQo)+N{?455Ust:xQ*_j&w< ʶfꯞ^V{6mۊb:rH~ܨqa=s* B ZZZD`qoyj{J<zy㽎:v`\.yxB!Ee2&4십289dF544Dj[]]$ݚ%b{0F8rNU*dvչ-JܿW|^kkk޲Aqㆾ/X,6?eٶ-˲{k&i_w[M~{,KHīB\.'-R4U. tu1??/qd۶kgV~‚ǽ+ ZZZ2lڿBݻ%J@A׭K~ʳWK7?Wv+{u^nI"I<}˧XF @p&&&ԱeKɤlŽ,UfJ_|@!Nf$k^O?w0e2 leYm["f̝~JZ:PHKKK]fjUײ,qIe H=!w,3ˑȈJŢBc6n` @Wd2R$eY*Jfd6dd(3'@ =ڵk5;vwյk4::+?ydر`/3jƛӧOS}ܬtq]vM?я@Î3%zg)$mP6̌洼qz뭷d۶n޼W^y{=8qBr666O~R\U*҅ v_ hvvVdR/"N<Iҙ3g{DO9~fgg[:;RԮ^7`o#=^|iMOOS(꫒ .tӧe۶s?^?7|JtMσؘfffk Ͱm[333r]e> s*CVWW0cllf|3Z>@&''u͖MO^rEٱlG۝:u*000W_}j5:z{ IDATu]ٶI 0 ^077[oIz6Ol/{{ rJǼ꫚.^JRʄ /̘777E]d' kffF^pu]]rE/^ ,[axxXJ&m[mk}}]˚Hcccw'Oj``@TJgϞǽ` \nyzzZ/ƴ+Wܹs[ޛr D4[.'N ;$L.+Whzz?vSe_ 5K^?fOE/{W_a۶]VV;==cǎUemg\̌}Yoyuu-ljao_OsL?5R)mllhrrRd8l-G討?Q;Ν;WwIZ?1z?~w/,//ʕ+ fs;nv?zD;n4?kwک?_fffd۶7^pA?588??;^=40zN2ӧ588(dl& ]͛7588IMNNjzzOtMivvVT333tgffL&/ם [.fu}}VWWuyݺuKmrfBOHRMx 9 f,1h?ʽ]ƶ'Nhzz:qi``@roI:u\z뭷\om egn\sllL{Ջ/X󫫫dy2mr]71,o۶~ 4ڃ*As &VoL]aY5}҃pU};ox?1JRZ\\Zn=R~Cvzw{@kgT*[ +=l{jFLvWsݲ,%ҧ&`Vo_Ћ/jllLǎYr7A͸088Q~%[cʭ7~6C}a37gVgzeϱzύ :q℞}YMOO{Ǹgd=4zh?tZ;שʿ7;Su<h`ʉ&kϜ9S3?::ze`&*F-3lf2p7!lXszDollxK[j/(:|K{jqH>{0TlzzW[c~Ξ=gjtt˘m[o8Dz:F`E[==3666Ib܊YpnnDۼǯaj\zι*c?zk4lllxm&mppPMVkuuSΟ?uMNNɓ5w:~a&F3Tdjj``@'O&wb)ɪ^}UI'L* -..z4N8~'h%sS\ؘ存m:$7ިбc?qicc ׶@7f2kN>]wg[rܜ+W΢xfff,7|SmkzzZo7 nyw\:wx '?n޼YuF={VoL&庮wYs~UXU...zЮc>7imkvvVz:kΝ;_m:u:_'~CA_+v{ァiMNNꭷުuw+R):qℒɤ400 uu…NajPmOWc&F?/K7_1_/q h >S?{z B,DWR0__2A$t??׿3~_50VRO_4&ѵIt]j\9vD|WԲDO?6b$P/n)駟?90)ڌ{%W?;$b$:_GO>dx"""""""n uh4OSa3Q|Fm7__@DDDDDDDDDD+&|]_5* 20LDDDDDDDDDDDDDt!&"""""""""""""ׯ><A0q`Yznnn: x{`:"㣞8wb{F;igoX^FB54MXuvApPp:"ض>|Pxt9&t3=DDDDDDDI@Du%,;;r]>lFe_ۧ0 zj~Ү-C޽{WkbmG_Nh2mj=U{V ʥ-]=mLׯ>{||ܸlۗ\5Ma⾰u'ɽg(RyW,߿_:f1Wg}_48X,ܾ~jX$I|Ǘ_~ ]7leJ9.]o./uTɿSgUeWۮ[֯`(&"""""": SXh]|(a`0@ӴwuG %I8i Dضug4!MS ۶aZUVgU}Dy !0aYw^`0PA!Zt:. A|0 躾vW˺fYvgx||8&)gzYv*0T}=S˴gi.s ]m6]d)ظl۶- \xt]x4~j˼.^`0i*L9.]o./m;EzQxU/ _($"""""s0uaj7A3u̟&y|0 j?Zq6qrEqF {}B$IlU۶(P xaL&*S^K3-& t]|>?h?C9T*/ i,ˠ `8h-Ӵ۳:2YqI<{MeYk9 P탾--@ZxENKi8Nc(j$Xq.UqX,;UαYvҶSgeW(Zڃ~ !6\Nzu]-A:~cB{ X-wm/Y9P$,~&4'$5"uokqQ.i4?C.VkFO9.˲f~ݞ!clϪױAqCU!p@:7&k7p]Ǘy+HyrV]j5Lv7AQY SǓĔݫ,5-YIUOn +!ћf.+HZ |ʶ'j˹cgufRmlϪuq6$e4LuWsU9pmoinMq5+_ ӵi=CB,[jl`! ٞUX,ťyu)Q1Au!˗/E 6w_KYm+ Ry其=e,V#3ޖ{Qz}{#gU x6$yCҌd0@6bYf~f]KQqުcunZLwsضf%Iz-f}ܱA?v=C !Y[1LQxk#`"P !0LN~},*3𔁯SxcrbnŲmX۳:R*۶;=.777*u]G$[gvI<Afxxo6roVMmw.ǮK^^h0 aYjgd?uy}'9$ ÍߛHz}2m𔁮S)eTlV`ނ]ogqIdɁ.gq}XIedN7{6oWڥK)/K\@:(vr1LX,T 9;c@ؾǦ^Pu]6g$g13Ei'ԕtҿT ܞU!qc:swwwVɋC󡨸CFrd k:U1^~lyoS^ʿc1ۥ6mKkl{UO8꧸3;Se,p8\m[䀟eYK~a8Ϛ˶y@eYeԊ3)ژɽJ6%QUAYxmOϹ=B fknz洜ɥz闌8V{b;xss,n,Yf\]W\ݹ_j,k)~ZR~ٶUN.QoT^_`~U($ mYuv""""""&p`4Mqhq8qat]P |R q EQ(`Yq<σ0Ma4 \B@W^!㥥-x*A`K~k !> :L'Z}۳ 8(`ƙxMM`8u]5,mwۍ)sUI u:^z$Iit]|>`0=4Ur5εe=UO&rdWTFJyi"lcMa^,\E9Qa:} 5MC}lf1l&4 -1,˂imlyնm!e8>hma>Sw ڶ`X}3G0MQq_: yc:qض$IEZ޶Yro$;맜u%cm2y,mKĨL3*QQ-{UWl~縹ixzz|>Ge[IA 2<{LeY;V*>%I|3\5߫j]jv4me&W PNDZր IDATDDDDD|'L jĠ\`0|>omh۶1͸4]wwwL&2eNС0o_x^~os`": $ \-[Ur߶%""8W :!"""""Dt2C4s.GDDWcX,zp]YDB0LDDDDDD0Lǭ@3j8^,ː)4MS{A>hh4վďNDDDDDD.aB 2q 8eAu$I0 D!"""""`De"QgI@DDDDDDDDDDDDDt&""""""""""""" ]LWky :s `8" Cpq0Nq+յ$n4 y l+٥+E4M]/Zpa5 ^e4MdY4M7\EG5DDh`˲pww!""""""""":tfh۶/Z+ٟx4 B!`6ޠp],pDTipInHwԕ$""""""""na!`Y8>hp8Lze`4M xw0D߇8&": :$}WΓ'L8}L_KA8 b˲V爢_j"""""""""""sIaqضMa"f۶q{{ 0OOOX& f4 QaMˏiZ7lۆmۜFtƼyBz=|>/]<>zgiK=>>n\n~8t:m<1,˂y[8qZr)Yٞ\y)s5+uӵϚ^"_R|#(6}}mJ4M^M<1LzE:]KGDDDDDDDDt< SG'?9`,Wk9]垇qow*$@*˲{dtfo_Ŷ_y\yS;Yu?C./| =BM-oKGyLuwͲlr+/qp h MTr`V>ۮ-*e'ۥh`jvR"/+YE+*.M-}Y-]\xW=׏) !^|(T>nW|ʗ2ʛȠj<?7Msc:{=""""""""0uFqAOqNk{ ֱiz },!lFeK_`yp]A28(Mtɗ0rU6pQ=Xs[mlNzxNc03sU)u}oY12^x|銈V1LQ8-ζ:!TMU˧<޳gZIgRԶ.~ S, 8Cή7/P{,k值icwȀhO3h}y~m엊K$: jk%_)DzVʈL/]7^KqimDDDDDDDDSlp6k6\ric۶w[˲l5Mp8T>is[p8r?Jrxbxa`8t8d& .4'$%j}yvG/qT!d0q?q2]] vsu8Z?iYΦU3s<>>Z:hq0< pe8Q#0uJh48pG͘1 Am0T/_TA8y(E,x<^;yp]i0F|=& lۆeYHT/ ý Py=F,~35SL.eR"$eh_xAq CfGAyxxp8\~yFQ,˖^)3\ׅx$iu`LTi/SS>`&ld2xMB@W^!dIDDDDDDDDMa:'"LSz=iH4:]3fe&,CE}qò,Fn4t:`0PKSʠ70 gtIqu-Y!Ia d!`&(Dj}yz,`RPe{zb^9to[9)>s@4<==a>#˲ e={0 Py`eNWywss1>|nB\mVA/4G>Ww}5fb -'9`6f&"""""""""8 Oow뵿*6&0#Is!`vˁQy\ t]a>^0㸵x(_"""""""""""3%.DDDDDDDDDDDDDD`""""""""""""" 0х`B?&]ׯ_}y 58p0 qiYznnn: x{`:"Vku] qtD,4 y5YW Kkد0](i0 5hJ#x<$I4Mտ8pow4 .>0,=Jqض:lA0 ;_hi , wwwLY .iN?}vIdx*ëlh4yP;@e-Z| Xqi\zz5.lKfC ˲*-|NREm[7|ʁ4]ZFr&""""">?aQ%,;;rT3)>n\6jzU^A*gUٶ q ðK|ZNv微K!Jm]zMӄak#uJӯhuUY޼y#z=ضV>ԇ`zt9b:Dz,F#}ZeTӴ[uG %I8im{ih4Ma&lۆijC!(Zb& t]W{yx|*鹺_L!!,t jpONKFrFڶ\>7Z,K}?A:$돜 U]ſ۵x^7 `jAuul}HM\jCinLVUI6KU*gU-W+,.ul}h}]a){@mK\ !6,mK׭.~KQA|xPRЏ#S P 0ϗ]U3X990\B`4,81((`33l / 躎0 y69k\S)$ fJLm{gt0m#cDDDDDD1L"O~.rC[9R ϊ#N7 c JzʁmsrƆ\jnM:$-0<"sal,`fٛ[ղеW%]9l:cD`_ЖK//m328ZNd:˿j7Ynr_W7m6-|h:z:yUYv}u U_V궃e1"""""4ui*2r39p E@l8MV5=yn#i{lcir-MS, 8۶լS ]տ׷mFSX~奛^rMd}F};ꐁ,˖GΚB0y܅z+流[|Au]!KDQmo-*[궃U؏0uFqvc@bu:6 l5WMO]ߑ: 7=h.ϳLEp̾CҌвѵWۮuh#=^^&])^|?v}vM.meϥ[Blc:m[ę$ <;{J}h,.1"""""(>1P(P" !^6rhm,ܤ2J}www^m]vҽkv;~:Sqʿ!? Tkzসۦc}lƗ_~du}9;7Y{T4u}.'%=|%/9lvmwkj4Mչ^p8<8~_ͦK5ypiDz,rP;jzs! WRۖ; Ԡ۾5MCC[M ,[Jvy>:lP'ZۤkOzxxp8p8뺪n}K)N& `@p]իWHAus ƮA^jA7MϮc*MӄmKuK^}]YaXE<=ӱ%I.i]u*lZTWLTið P/KNǘfcm֏5`(0Ng!MSl6Soz6(>8eY0M #˲FM!2ض&,yhzvQΪ=QuV6S-]*`Wʒ$y 6Ll]Z[:el,ógTP_c+u]=O-2 IDATȲL~X,vԇ6kLjG>Ww}5fbYq]eFll6D (ca~y'ƻ_~{U}Iuݝ{6E۶ѵ˄rF=v\A@7A4X,B {j0]8[9EgU8z,C4M Y}0 BdY8g0>0 .DDDDDDDDDDDDDD`""""""""""""" =*~z3Agq Capq0Nq+޵Bt),B t]A~u] qtzz+S^J4y~x P=tא|}H' t(i0Ԡu R_M0L`f .>0<tK$ 4U谾o0,1A.=#8lV/{:0/p ?!& ۷M_e6F͛7|A¥,ː98bX;DDDDtfh۶(% }//^4J}ၙ@9HXv\H *S^4M8Ӊk|Ӟ;4Mx</{˲`YZC?ݶ8et]k1п-vpYe*nlۆmp]ٌAt"""&B,q\jh4eY!>ǁ|$j|i#R K' "3;1߻C8yK+e-n894MXuZ>(m*-Çlj]ȕ4L6~$ g,a6,`9(H"$beL "b{FDg"@efk/FQtՁ+97 C" vb/k\(0͐ep]BDDDt N2 C$4E7C0 i"2<==cL&B`6a8B4DQຮ bqc0~Es4 sp9eӳJ͛7B--5Ϸ:pphz=wj^,j)MMz[}rLi_^eʶm8_;W mcuj?Vjy{f3DQbھ~cT)/e{W}d>>>n@4u,Y>ޕRޞs۞ecXsOy.Zxo:[Ϲu˹H*^>XF$A}_~%t]7|HzyocV)S^%{lzMӄak#MAY~J{]U|#""0ueYFu]=Py5MklVqCd$V۶m*FHi¶mB`0 d2j00>X7%D.KUҳN0,P9N7eÊ{퓦)8k;?DԄKUwVD]fl#wkJq>rpj[T*^]UL4͵jy)[4xmhS_,/B CXFӥj>{Ӟ" @!{r)_tSK|r"H &gzn*sjݾZOq/ϟLO !6,޶/lZEzB-^>Tiԣ{cDDDtYN1 C A|t뺮ӄ<1B+8Ɓ/Ƨ|ƭ|;Yg+x# CxMA@$I0U5uҌ9/6}O>$===æ^HYAu`GT5*mnq ͔ߵ,km]I^ rpq õA~~JWǪsEֵt'86WT$BL&$IrЬ"jAh۶E^&]C_PmO˲T{=S~+CR7G,dYwީ|8=B1x%ZGq/1usU|U-aB˲H/%VP6]c[*-QUPo/ijAq8%ruX|ӏU65Ы=6{䒄2e&"U^MkyƦ6D~vaǾ)ϳ}'a)ަ?dNyiGnea_mrK]ǥn7d=VR^.|iԣ&w>QY\:C4ls]\?t},}۵q- .x%(R~nzVM`,}sN+ S^*\vm9ȴiy޲~~lǪhx*/mܶg`s4ӡr-R8)˲e?7)JyymF:d,˲!gM !`ֶ B-9^\jQ=vTeCxOcDDDTśnr-=ePmkz=<mA$Iy[uNcű  Po/lt]&M|?~l[Whxejyi>NrU}]QtP{6lyy繚QGedl|9M$I`&noo+-}.Qqުe|uvzzW>iԣw>Q SgoxBJ[B>l{wC)<σyB7`Mx<۷og:rySCLcc~K=,)/Bu]z>Hb-|Ϲy)lkf~WSA1p~t B躎$I΢^J}/.q\cUCw""" :#suoWHojA>4m{[[q}ݩv>}^b ]KJϞ=k%߯;]^ھm{F??P]RK@埣(DcU˥ϦThLʔYZ<[#L]XXeq Zl/'""0ub8S}M?AtlS֮`el;]V4͓ $IF.ݥS9=9gYVcT*.;񪖗C)/u{d~S?]7]qcVǩyqߡc?V{&mKti;V%qc:swwwMbݗrȗi^hZ^_RNDDD0u㣚e0nmۆ;C>ٶaAޠ[tiá4Uzmpq\8`Y҃wve1j|X>2\C=8Zegy0 xV%v򚛞9]k|Sonneύ6Ͳ,c躮f 7QҿQq`4Mqhq8zC0 躮n P=|R=q (R<4M2w߿d2m۰, iaU48á:an|H|ʇ.OEZ<<<`8b8u]&~ ۶1L6a^ESJy)[&{ PexmAiB!+qV>]u:5Y-,Wfұ_p]իWHAus FKWgr|}d2YG]ll6Sbzs~N-0^HSu˧\Һϗ-;eb݉٬ݪDDD} SDQt^ 4 ingztLjz}q ˲`&nooQO@-E$A,3-uCDl;]"}:C ?߷li""Kz{|u@ڡcXqܨt>|Pˢ6Ut;񪖗2&{O.m ~_գ$I0Ϗi8lVy$ (w9,97IOr;,n2_3"et]ȲLX,v-uCk߉'|ԠL : u1 0[[i4mf3.MDDDDawwwL""""j$t??׿3~:}$IummͲDDDDDT\+%D9C4},@[%""""0uNǭEgu8zȲ iB4j'""""0]q{{ 0 @eAp/]<DDDDDt~$ """"""""""""" ].|`;q4MV+uGxe(~$ %3,a6,<9(=+vZ,0^։Wroj/gb[_4M|quQa6!2!.Ia= ^i" CA T- ÀiȲ OOOX& f4 QzgiK=>>n\X4acK7oިe MD$p ݻwf/ "g(ѩm'[y7o@^|>ߺj{oSK{f3DQҲv~uIeRÎ,{H[,M!r)mKbשuYz+g 0G^\ b|F4 몲yDy58j5Iq M@mKF#i 4a6LTKi !0 EҬ*00L30 i.:[k@, [u]z=6rvvrxiG<==!ZRvnu@qjtnjcSK:1,Rܷ4ځ:Wdyh>-+H۾WVqzlmuҧy<-ge !6,Հk]o}=̇f7GQ^!uCv+`0T7!uՌ&y|0 j?Zq6p3%LL9G+x# CxMΎ٤8Bd$Iu#KL] ۶(zjFHq uݍx9HT*/ i,ˠ$:*Dz; y9{=, xu]*t)i$Pg|'I{u]a0q ýCwIRo(>WԿl>!eY[Uf}i,W(iCn !UCv+{Sz=躮[}@=fqyrIgMTMWli|3N8.^oiڔ-|l_si]և:uStQoey8Ԇty/V}hN?"""""""-\zC4=ed0ZWm2peF&0 _s5XmAu!(R_9TWOM GDDDDDDD``UWCr3ϥ0bkl0jfl,sY@Ui,Kd>(֕6u1}m ~l#ePFsyٿ`W$0M.}Epj_yE9 ߿m$Iٖޗ~uC=GDDDDDDD}0Fqi!|}g0WQ9â9W5h@1bsJCT=X<%!&T^__;٣6i E1pͶZk!rF#Iٞ})|߇Bib2_~:KXu;q`%( IDATi ZQo8dԵS.x,뤴oB.8Nk. lg{QI9SoeN^˱K#9ީd@e˗4MSہv5=azY,x3Hf6\rӶlr`˲-My}4U}mu9CA<6 -R(e'f4@yb&69XDmj6DZqnv5Wd2 z`d2iAYeW1et52 (R}5S\ҺuډSu]躎?"Ih]ױ\.hLTiXV0l10ź1yi[n'^ w(l6`0Pi4MZhjž"\1MS̀YVe4M<>>2)fFZO5}Ya.&⍢3q h"""""""""""""Dtg& `"""""""""""""0э`Fp` ?}A!8f8>ǁy,/DiW^6M0 18Q貂 Œ}9O"b;HDv_$ p!r/,ˍmjeY+sDQ]6?]5^2 m7PA6C0 ضG}{{S6N!|>y4 Q}ժtcMԵm?3 xxxmr4M[6޿pQْZezm۰moڗ&91 6>3M?t9٬L&, W^yp\랧|(TR̓~m#]}REg6q5M*o/qz}r[|H_RmpuI ýYK;5=n:KzTl$AXVt]O?je|[.gԣ>=Nyrz6<߼.ѱޱ, X$ guUe= ԵW tVu B<1 e4Qf@~gL00 `ve.KIKuפ}s<h4i*baL&{W:}|,/gM]""""c1Lbzx `gi_uman< !0aY) 7 ,֯VFB IsuLl6( 8lrP`{un>4?`vt`<c8"2ֶmc0 ˲vOYAu5BtN}yg8 !0N$ѳ6Ydr:i;eڊ)l:_ɼtu]7!lF$X,8@uaUڮuQ_rR7Y^n==붃M{DDDDD+%WUoˇo{V +ڔgMTM.o3"u}ۃBr8p͇&'+[ιJjm2ď?fIoV˿-%ڗ:ϳKyY2e.?;L!Ak/67ҼoDu}4M&.'y}dY g|ﲼ49^|T;uy\텻b9ls;Y۬MQ_p_$[!=އ4zKDDDD0zsrr|jYR>fYO#g AQYlw}uI%N,kcg@K,߈.Ѿ]o=\}A|}穚>}bzÔ; sk{o&]܃NjSn>4?cDmYmL&p]AuN5/mЗ4̓P6&sDQ۶7v;]Ayc6a0:o6S_|C)I]׏ N]krr`sSU+zkRЧ:MT>;rz6Isw@4M.qzLS!&ϳbbQz'|埻)|߇BJib2_~ies_|K)___kX7߻*/uW7=ogz^]""""C^y}}U~87Z&W7_jpP%s1,?f̲l#m?ݷK/}< 8<σj&G <yFQ,6^9evֹ3 ]G$IMӠ:%FQLTi/}?j.{7_^^`<:-6Rxuҳ/۶aYFw~7LSu4MU>aX:[IխGlۭuϛM{[DDDDD0LEfwQ4ijuC|>WoU5,4e(jBǰ, i񱕇<1mۆY!<6$0w(!$8Z,C$@i""KWQ<}Gem{cȁSI4Z:yyl~4 oooX.Ȳ2,ûw`ꏢ(:KbÃ:8W,guyir:ٗ|>p8T6I,˳4l6h4RKP\nS[;73=]w; }S;yĠp]岳e1l|>DDDD!,g&IXW|?Q뷹0jB$p]=B֗$"""UrRBDDDDDDt\zgX tSa\+ѭX^!\_IDDDDDDt! Qqٌ(8󗈈8 Ȳ iB4e"""""""d 0 BdY8g]DDDDDDtjjń """"""2anDDDDDDDDDDDDDD7{]g#&yq0Y8W<a6F`Z>4Z\V<兙@tp <ϑ$QtJy48N/I{GDDDDDDDu0LDB,q|x ˲j7 C C8jYDWNEI K8 &3;&uM΂ Cض,jy(:g\92&=#""""""":gS/q`۶PKa"fv۶0`&,ۛ:ֶt !9<σiu]\Vku1o8^MOM:WƟB <<<6e\ʼ`00 _|i4 x^ömض'tqPOms?~7SZB~>uٶ q]ב$ 0ܻ@|ka}ge\.g's<8|(T^L~4}ꔗSp8T}dni:,iY7]kM۳TeRVֺ{ضmc<WIyn;ea<Cu@$\ kA$I14MeY, moY4)Lӄm0MBq !F(Yy2@smmCQ9S']\h4B$HBu٬tpK]בeуioooQ [戮ܒau}+w2]ϩgLŠmەR7߻aNaL&g \49^ ɴ5 e4͝>ny9iZzm4m|"y, Ţt^gȇSAڐ|o^_uO """""0aj4,ˍu̘6yr0 7j?ZqJ _98@ΑJ@$I0w)J&hcAA򢭠~Ȳ <%C}g`r@uaUٔxMˋkl/-/u{qI5r4OmQ理K|CkҞ]"NWuNeY*]ve뺟K@DDDDDD{S 躮TYV V*r檽d +~&4͍ȥޢ(*=fյM&'ϳ8(&gskyOԥ{J458| ,6mNw!ll4iS+;vϚ.{2e&"U^֏M{y٨em\3V}}u˭O""""""Wﯯ?9#kɁg9X[mυ'd>G>|PPpU.ay}ҟz||TVh/ȿmNw<ǥ3}W.{d0=˲ҴeP=6]=?v. ˲{pWz$"""""a1`|&˗/brD]~)///<u]5_ci¶mL~8w9cKC&˲N|\ׅ#$iuѨr哈`(00 ~c!MSV|7MY!"V+q ˲`&[ Yݻw0 BuC}uҥ0Aª\-q)i3(_2}gP8bz q5c|U-Vuilh@ALe:^r:奍el޸i8. _u|C慼뢽>%=g~<<<@4a\"˲pr哈/|wL jx r]岳e 1l|> """"""""""j$t ǿ׿+v?.bZ!I{pnmMDt1e4 e `"8;ۋ7"%""""""""""%nDDDDDDDDDDDDDD7`"""""""""""""0э`FL?}Ap41qv]qc6]MӐ<tr<3zvAuu]o/vͲ, <<<@u@}l版t(i0 iF, '}WqIAM0NaIAu] Ca؋t|IrjvF>ۮ BL&@$HTm඼ ayrPB`:~lx<ϼ""""""0݅|y<öm&ʅy$IN5MFpr Ç0M5V+xuLJ^J>vyG]ۮۮ4 B ÀeY,k'vm. q,ˠ:+g4?<<g𗈈DtAt$e!fcXUab8qV+FR$Ij/e=~p?VE7u]21|߸,KgB54MXUxEm[<>>~ʆ_Dt2 Cض,jy(:g[\8˲oB 2ע(0 U_qk|1O4>~Vq0ajO49)0Dʹ4 ma4MdY7umBsxME|߇*ZJ#4 cqc^j=FvhZ۶Ắp\X.;i>k8b0l|f^V.\`<61|hzmەqj=jmpgc0 2`{{MSxrҪvP? !rrr觪S^G]ۮ[~u]F#DQLq{?|.S>?eFoJ9-.k! %k& Ig[};ea<Cuz,X:vt2=Һ(RfUz\f,#neD%f|rm%Wɲ]{U/2Kqj&""""""`9 zs|rp}[e?υd>8&EQιlн]Bq R)=:r{EKЊ2!߶U_.]L ;{| }Y/]>ep<^rybrL=Kx:u""""""[%74MS.ѕAyl8fGp]B<==!"5xk4M:L:wrsk$ r22(Vf;nt2@[jPJG,lT/W(dvy+Ym|G0Jj^w3.7eKmn0m[͜Iw]lvq <~ bPz:LWKyL['gIODs݂ ypggIKm|//Aޡݲٿ ODQqWѽbz8ŀB 3%D}Cfdd_~rJn!p)R/8Ǿ>Duȥ<___϶.KWyL\B e4$5K,+웉]Y./lm4,r !t]G$ DDDDDDD}=7\C{ش鏺o?zvG/a羕O8]~W81v|b$˭`WdY˲yΠmp]wogem jgm-n`eYfU@G|ˁq43޶8^{ SSm290IRNi<+`2'qL&gοR{u3s}L/_ǸS7Mmc:Mmb;XuӥrB|qænUT+S)^jO*[l{}!xkQ/EQ۶KgjkH?0NEf j0MӐ)VQw\j7g>Si qò,V @ex$7(9f~<<<@4a\"˲پ#"5Pe5YnȁEIFelξ%01T5Z ,!LDEbz8xxxPak3d_t;mVNjhWQ< _[`/XFǁm۪MQ^$"9k\.],HK%""""""w;5?wW<a^h4VY똫 u]4M8$In4Md2a, e S{Ez<+e8i*-˂g=<5֤I\v xyy(ԽG!b;ADDDDDDt~Ld3L])0D@5 ma4MdY7u2BB`0Ar4M+.ǁiHA`ZӧOu?S޿a /_4^a6lá{ig{U,Ŷm8bޗ6[j==/y@uaս}&4}@յ4++o۞X|!Jvgv^ݱmׯ_ߗʹ38޹Gh4I`>2.ɶmo,s^$gڶxfGQf[Uz< \. b}p]DEl6Hqz """"">+ԶVUkM{jgP3c5(oA!dPv1{U]r] &^6v_i}Xg|Geb6!gXeY@n>-%tY>{%Y$یc~}پ>0;I;gyeeI~=:'~Xw(R|d`>\mS8H0\"'dL2UARMge+1STP9,l"*WtfUڭUȿmڀkk}?kv,.K^`k|rP$+icI&5/5l{,sYBkeW~ΥU^&"""""p h MT,9e_DzٸUrjFcw_\S^yQվȽ岱ed/5msB$ }^gսR{g_⾠\4UKG7^_"˲e?oBo? ÃAR}z~8y]?O\Oz~{ SoZ2N9пw_Sk;t2|<ҟD^]m൮{Q{{݇<BdYVdr]BSZsǩnse%?EEm{co埛i,3ۻn1rFnYއ/ju?g"""""cz8PŀB 3{AQ{,94#.9($}}h vOe bRkOϮs6ߏ?4Mw[ZS̹gbYvϦNjbbn,mCue """"""d IDAT{Soy؃9! ҥok u{FĶ=K V{z]9ݻwOi2?yٵ˧Um'>4k(dP궃]62r(J3nzy/>V!mևOQ} Sk8C5_5#m{<ՀNo:ޡsIpY7ȁs[9˲m_[Vj^ۭחJOq'<==e6γkNׯ_U\vl˲Z=^EW(?( eeX֤lz٤?,;_9x?;dut=}oY=:>)/|先azUjXC粿i#B.6lq=2H8?!sUf=vZ^m*v}WꖗSK""""""{Sibx q8z0 躮%au!ӓ﫿Q,L&ua& (]VTAmXt8A e}>}b/_}s/U]qy\U3q hN4MضtڴmjxLَr%3 C躎ywtD0NUMT/ gQy>4w_FW\Ud\zu6?///!LDEel.lVm Xz)}DQPYa^c\nvgv^|QxVГ(o8Cv^I/hm[.jV[0j:>)/(/DDDDDDtw15Wۊ3$+u]F#,˳,KWf<öms.MDll/0 |a` 1]nd2eYX,GBtM`&f_$""""9IXW|?Q뷹0QO= V+$Iu:KBma/ u4M? b962&=.Mte!F@ub8i&4Mrl"b{]ibXpv%DDDDDDDD`+8,C4MQl8l4"%"5.q|w{t˲0ԿJ 8oDDDDDDDD}0ѕYVx||aB,A\l2""i8޶L @$Kxj&k"!D """""I@DDDDDDDDDDDDDt&""""""""""""" Lw; 8!411yptqxrM7u]F#qlvUZ] Ͳ, <<<@u@}/ """"""K ] PiF, ̇!80<)i)L<)\p8D \90,Ca2nd8m[$A&ԭ__v2JϷ|.I ]1lf q>XzO {}i:jyp]///,=e V۶a6\|>@~H@Nv M0L g0 X˲z kq7N~$Z&eYٿe>npՊ{ MӍYޖea4m ҥ}9[%dqvW)^/MEQrMDDDDDDD$ "jtʌp۶eY@R爢sOOEQ|, LYa>tEQ_k\82k"""""""Ka=_A6Q.0`&,ۛ:Vt !~g!0 ۠rT˾q]4M$I Z'躎~ C Lϟ7>{}}ݻ\VTk,˳>.mq0%4޿a*/|hzVsFb?ώXzM"Ab*N`H j!@k&6I\jիW sU[B7l_|d2QUUr]>;g6qa;۲i[epo...dEK65}NG^9=8k&g1Íwm4MDZ1z<i[qնUیKƳUgξM!.~zƘ+Ro߾Ci{ݪv)b*6?wv4dwۭ5UFk~f{}߿,wh[+P֋t]I&\u-&5VqKԧfWoӯNG/^Pu2,KFWm]#uƦ]f\:&ϖ%1j^۶V`cϚS GcvBhbƘz2l4-5Ƭ\tk2RL@6;}}}a{c;[f&דDHHƘzŗ &wwnَwmvq ȦbXϟ?i؉}3:{޾WVf.BI۷u_nVń6ҶlՎ 8v}ɤ~{V1izMƗUϯUy{o'8(777(Mܷ%}]t:'Ŗw۟7&x6[ @몪;Czɲ..=KqXDmYlxǩcݯm݇ńuR8I9g['1Me$I?q`k߿#>k{y4k_}0R Va*;Þqᝓ^v0BqhŮq]wϱMדImۡiLS]__K%d t:m+&}>! [m_q4AlYrTQƦ 3n6nRtZ%ff}izi(1d2z_}g_&Cmkq0d2E(Wjx'uIU,S2˗vQFy<FXs3JTa*(zK4MtR̾Wʑ4MW&M,էvئ^0y݆$?T]ڤ|W c^ݽ:ۺ+хz;az/&˲?h#nJ~!6}7Knzh..-K7-x<1Fzj.vxlwz :I6;&f!krMoy̝L&dYru澞:m.O `o:BQ) zLeY/s\kDzG yۤ.emۯ E={Fm`k׿Հh oR!^8Vx HL$J^l۷T3h#AgIxkHi}EQ EEQ'9tJE{ Pɉ\ו$ihr|R<}h  `< y( E^1HYd7MSen+ql8~s*أ}nAtZsYG;&Ǎxaggg hI$g&I~8uuuEP}_Qm2ዢHXx+l" c W/JevHI}#`/*cvqqAc<l )˲~t:Ur]UibDfkm V y(a=q;Le4mmy PD9slSJUU-]km(CKǂ}oc׻g-q0ǩ^ni'9?/MSq,c^|.!"1;8΃O2cIh4wU+dϫrFF1 ,5 _/] :1Lr79 =MFgcnwU}yc>ǚ]=muu?8D1N]hWEeY0i>$\P$zm5]u\ qm.~x\&A?8| qX׭hͳImsճ^5׻g0͍$)aWo:I` IDAT49zu}*`;9]%[@;gʲL`}mAZ'.5-gSy{}纮 Xy~.Qe 亮jnMĮ!"r}}Dag…axD@ `nqeq(?xb۸N86̙{ٺө%I`a58H8hUޛjZΦڸ?c=ǚk%- 1I6i7m^'_mMĮ! `dK)"EQT~8ӧOJ?ї_~)I$uǏ}_i[Qٳg_~0ԧO<7ƨ(󽯴Ix2(s}k͍>~(uy^,QO>g_|gϞ1ٳg~4IӤMq<{mٳ>~_k}]}?\oMɤnwr}_mƉ6&qb M"OwA\/ OO$z_o~52$cz=%c!+nx w )!Ou/$黿_.MӅ0 $IT8lȶc!-ٳ2>GRAqlqcVHA UUUk[" (v69+xD P׫1F3a?q]NJRYJTIP9O `dY OTp$H `< _^xm4)MS* @NG'''r]WFѝ}EQ EeH~~M</q( ]\\P3t:蚧P5.5}g !*얖UU}]UeN:N\eU(pQ/a0yHaxDY)MV>z0 uzz*҇Zqq\_+}NEIRH'''r]WeY*˲;Wnyl?qkl9'ɝ+eћ7odQɉ+~q}l^z^@-#_x!i `IQ ÐijgėVNJH,Ki$IW_u]\zpad:;;[~_Q~s~\4nWNg5zMsWe1~T/&t<:6/_z0Tuy?xJHA3+_Ml\?mif>DUUu]c6:ijψ/k XXJE @UUݻwuL=u~qq1(ZH5音+/1:??WYkVmR/ی]~ulCyXNGXIgq/$w|) `N#uF„Y$jHDI,(Zv֪.׮*cǩWMNNSF#UU5 e-%i4͕3,s{Rn(骕UŅ޼y7oReY}m4ak}}qKMvؔ1fX4]xiܥ_v]MZo:干f׬]?xH{/X섛1fI&םY5hWؿݶl?;!nDnx=,F𡒤vŪ־f4)IEtt,4UU|߿wbyYs38N]e\g566_w1\YկmݸP/|>Tdiۭ')[ƞ3t aXo]YFU$M};Y~{i9w~+LL=lV"sEQʷu ijψ/VCM޿i|Lye׶rmϕu?o?xH`N.9[Ƙz2z4-hYbEa4i4Sl}_@_$^gntfZrN?]&79ijψ/VcI8n?K}zٵm}lKeW*Nd.΂,[u&ЋP$zm]uvr[sr>d$?V-2םȝ=mgψ/e^2陳mfE}kٵ6\Yg%!:N> 0 v&m?}_UUm|G<;x<2۞=nwڶx^8nW`ۮIU~>q0d2E(W\x'uMeYVOh|4.BѨ<ϕ繂 `0Xh8<ϛ;}EQ~__75oeKtM PK]㱌12իW*b&%MzӮpZqu:u:Cvµ*?>N?Ҿ+}}q\ǎof4U @s^XիW*Ru]:ӆm2>7['iۆgM6_vPڽivy^(4N0vk}?x~"?I!`lQ7??gL&eY'rdo~wGe}gϞIZL}w y_Wo??җ_~?έT铪ҏ?(q_J{%Ijzyۿ?u]yWO}QקOZ< GIu"ٳgu9?~_+E={na/Tӝw*?~ԟ ٳ}I777_z ;YvgC/VQͿ7u;}MS%I$I~_//R'?>|KE+eQkǯso>gwݽɤus]&q]Kvo:7?O庮.//U1/U4h4Zpإ]Ip:?K~eo{+'-cz=%c!+gS|-`#/_`fA_\?Iw7z\? `xI,Kq|m1( CM6{.ะ3%IӴV6N>O1FA(V)Ɵeݮ(R$rpwHǩW`>YU@R=[UaWfY5nWaTyuG)?q``Xy(Rud2(2i ?NOOy|WUUCY88kω(tss2 ׯ_Il[a58VSshs]]wH\yFu:Hx<3m:ޛ~ٶM ` tvvVH)RTqD-REQqA ʉ` cB01ftfԵN[u݅yWqYgzedR'0ŝj0(M<˱Uno綦}[ 68(vzervy5l49CpzzZ۪loze춚UUl=زI.Ǒ1^Z$-kq,[9n>>lhي6>85ױI9ic h {&vr4MDZ1z<'*{={n{kٞzLvW;!n+U6aD=x<%$:Nk\zöϱ,vA}"xO%nzݮ˱ۇ%zߗnp0t:'vq]eҕUי0,BI۷6vC\ϟel>Vhg?v6yۯ;mWf&Io|曽?[GVL>sö1Ƅ0 庮<? z qpv_un?7|_0͍$)aWJX%v&&ֽnk˺7{^ʶ-;Nov \>|*+`)򠷀躮 X}JJNӵe:Ie1}Us&(W>χ7nqpekkܮkt{V[+.8(תJA/Lha8|SwMډ -ׯ-;-cEQA&^w mZө%I`a%vr06 IDAT׶uaO<}y,eQJ߿qu/>ٮGMgU/nWmAAL&ٙ(REJ7n=iJeX|-BѨ<ϕ繂 `0Xh8<ϛ[1(R݂߯6˲vuu~~8*|̓l]]]}aؤiZ콥i(gui2WW_-f{ݻw0N?J]2W^(r Iަ_i0 ӎ۶y> _`v_6i]xC88yBNGAq9d$I֚$"UUHxϻ͍(I]EQvh4RUU pVmh]s[Yg?Y=nIZ-[w65}y~Z鴎Ma(Giۺz~=v,R΄PCϱ4M?88Megٴvmϣ&}߳+g?d2GgϞQ_o~52,X^Oxg) C ÃeW߽}ѕ*- x$XןJHѻ_|{Q  ޿+*m$QEXi>ֵuOfٳYc`0trrr: ym q4wM.W\8%=D10D;@S$%E} {d1FA(V)Ɵeݮ(R$4)[*[*GE>'dvj<>N\e5( o_Mæ5mw0N:;;뺒,5Nyzi3ʲd2abar2z,KE!q Ps.㺮 <A &61r]WUU=9Lt}}>(?$gM٦&ܶIZ ϱ_[/a(cziZm˹ii2}a(eQQ2ƨ)/uEQ^vѯwe01#Jo_{~Mܴ 8(Փij<Mq\pi,K]^^֓ӎ)"}]^^]7N5e1>o7;W{h鄦FVri2*[O 5g=3seyYNGѨ~t~~^'1o_QMϮ Pggg9l?JZ_j٨ڈ/{~Fl [@`8S'9wHg&ev֖}]LM1Yx~'¹}slxkܥgղ{k_t:Ņ:^x0 뭩˲h4Wɶ_ֽi?{qďSFcv"qO(`i'GtWtن]&gxv'|_O&F#F#c˾k0믿K^J|<Nd.Tϟ?:j(˲Io;Qkyת%qYqdzǮi}RuQJDo߾vE'!rss#I{ؕ0\U,v}Ʒ'jb'}ˤ0/˒-Cg9nn~\PáOC@ZUU)I0 a 3%I`ae8H`u;! ~_鴾]vɮ*t]_Msrn( UU`mV^wm#cEQAŋsv|ypp0d2E(Wz'uU,S2˗dzQFs{uu%Ϛ<ϕ繂 `0X(h4R}_͝۷4MIa>_}kƘ߽{wv~vg(RWJ4M[QMsrn[~曭Y[zהu[/k,˖p#...tǑ8L&JdpXK("}UU(zoWؿ\I( A uzzj42g?eWp}M<9 h4RUU p.6Msrn%}6C&i=TUϟ<c겮:øpI"IϞ=6Jo%cz=c%I<;;Sl xȓ`]+"IF~ ӧFIDeY*;p1Fa܆hm8xx8$#T󜕿[@  G0 p$HCOׯ^FJ(+"]\\(GY('p\t:} @NG'''r]WFX^OEQbo+,% xHI\H<ϫ'M1FQ)˲{a*czJ>|Pʲʙ8VUe1ϨO8^ G| ,5LfƓ0>;;SG{^O$ɽDZ1u2<A ŋ]E$8 L}}EQtI($t:UY G0pD1 @EQs*RyϽa4ͲLnWQ)IV4MG 8vuк[7it"9˲z!WMSy.uY=UUQ+q RZ?==,Ӌ/z¤sߗ;'fTO3Ym1sG>ޟ1F~_Aܛ|E;Xqԟc<{gd6[ڬ&g}yr]wmq8t<̶l01feBI6Q|{l,mz^]/ƘՋy:?ٻDZ6 WB Fd\g170[c>J|֥ҧLnK3MrJ?;f¡!]eºYT]m8;9]7 >V>уݒٖac˺߱:I+J˂:6@d^H{`:qY1v;<ϫc_c8u]~ZNGfdZ0|VuT٤GY WjƘGCâUsYپ19_MhywmۦeYaW_^^Խb&m]泧?mr>X=ڕskj?;f!ѡ]=hBaVƢ(4 V2nsm}3seY3A0Q>'MsTuɘ8` 0nt֚= WtfV®+xlW3/0ƨjUn6n/Ϟ|S)&Jtgt9i~nCσ  2T+}WW_}5]iywm&/m2LHeY\Ѩ1W\L_6R/,8ɤ lrFlPsp4M炧{ݲnǩ JTnoގ`>MJ9eǟiF5<5ݻ퇷w޶luj 81*c˾.{|w*2$qR$IQmv; 6 & {}߯%8;]nZ}_Y)I E0 7j+-||ʹn}Mwu-SGչMe9c3grTVYkm4Oͦ$)IMeoOgׯ,;MUu볮m2v{f~ 'rٶG<\]z~fWӏ1CmY88JNJh|AbLλ^ovx<ϫqzyWgc,lJ^/wu 8)Xt:HQU~8N,_Zogg/?̭?sce~mT7?/R+IGǏL&я~'z|wh4`0{n[~;YU ]Zc,{R+׀Ca>.ܶ>xݺ?V?yⅾ⋪_U777K_{v~&uu}}]m_(글EՏsŋz?.gEQ/^ۏ-Gm}~rG?O]__+sg?ǏmǏU?qoywm wy?OOgw}7s/Ba.ld4Mj??+s??Pm-^^|~'\$?k9{H3 oݷֻRGDZZOv:a~ x޼y#|ȓ`]!IA_o `F*Bq,ʺca|  IDATxYS8ʳ>3z32VԌ-`0j;*82V3A Lp0> WWWs %IBQVEz|׊HvvgqM&ϻ1F~_YQq5XVKyQ!'0<g!29#I%͙i\Xgd2Qer]UYb0NyHaVga*!X0 E亮PKWz0 u~~.~uftrv(e8VE3{yyy)cKch4tvv&9p:nWAh0,{ Z~1v[KVS Ði`>{&ͦcjesZ.y;<|ع/4 A,u{{ʲU`>{:6Wzctyy(Zuj5:C1y[An|V%cP߯qŪ37ˮUYUo9h:Ng4 [m0<j[-8Nm:X+}J e9mt9F<ϫm!WAk);.֙&Iu{-ninDǺՕ޾}[%zF+s}gP gp;:C1]mg] 3}4˲Z/ӯ;Q>ˡ b\w.^^uemr. ?$[~.J :nu[mbz1F/_}lՕ1-x<|./6Yeutߴ^?g٢ϗc>ol8N<{:1-Qʲyywy~W\V}_86E_c>o$q2z+ @SRa2̝ʺK97eY0 g\g[P{_&ITnlDgOk>;:ļ{/e6;VF'c:;i_jۍ4Tɒ`0sf@,l jW1g0/Zf9SqyC>Ol?B8V8ɤ q*6v5\sɒוݶJtf{P-he&a:ǩ }gsNšSgӏ?j?|HI(=*ecˮn `sJ3m9lBl<ؤ$gmª( `LJz=y~-y⺮ X?=1IV#fȲzcd[IR۝[8(R۝y H۳jcuK9`Q-=WRZomE+0Tٔ$%IV߾-|t:Ֆ\JǞL&v=\ ?}w3qR㱮tE(Vx'u 2i*cc͛*8sonn0eumʲLY)uݹ qљlS:dY,g$a$QXHA(TeU_>m õlώ?!IEQv8y)ISno Ccd۷oL,۾Ў~xZHdY^FQK8FZ~_^[uEʲT线|q+Yi4)sA u~~^[ur^SZUXzU~%5u~~.ēM,8gOx>`0PY p&VwOil?\׭%1U<POǏ$$x}k.GqVpx9;0Tg h@ȓ`]!IA_oǭޛ3h4RQѳKbQJӔ/x\__ tp8xRSBy~x,c/x Lg0<$$rn+"z=ykEQvM]^^~,˞l98VR7qM&ʉ';xH㳐eǑ$y'u#3("i2 1j,%I4MW^/Iqf4M 8Z лw('T;T4> ~_^O^IZ-Ih4Z8E1L&U8u:u:9亮8 }_QQNa0NyHaVg*!X0 E亮PKWz0 u~~.~uftrv(eY{^xrr]yqq!icrww0 Sς PٙOÅnyy7"me^hy7mKc_Q}zWjc8qq\թjGMl6h4f}_WWW3榶v-!o`BWݖ8ʲL*8uoxMr:]Iz?89Wu%}JN&*8NbŰx璴VҒKRNu>_;ލ1 PƘ}yyw:(j֮Otyy93yn̡>ݮ1smne}nzx<3k>+_]7$KEpUd]ye<v V6Z>?˩Oih4n%@h4m8*頫)8 TvFsɍ<ϫmWAk)9.znchnDǺՕ޾}[i7]Eh> ';=ܮt<$)w&Ůnekק1zaغܧC|>ع:˲u<:mo`*{CCϞ{ `a՞ZxYBsaYw{źʹvn!MnØyzc^|dͱ`>e>[8F.Du̻S]V<tϺޗ1fr_R2竭??~?{<l8N<c  cꫯsOh;;x8v^3q2&I =ف6vHsו ضb.*uV$9rVryxd7VUpyw=yhwUsmOh;;x8vxjYO0Nݝ$)î`[x AQnUݶ<} tRj6[[@Cus:nkCϻv{CA<>χe?zLNCTJ;Q/^G!۶?^ r{{,\. Cq{30\y&$QEv3\3I{V})L& YQhzYlJ$Y+k߇Cus8( cjKzNvm9fq(;]\\{Gvի{q6wrSi:ev׌x&;Z/2u}}N(EQ<[KIӴ y y`0ܛ0 uyyY]kzᇲ,Se @nw|@qotf*۔$v26Eʲ֧mpֵmvg'.d2.//E4ǘw߿Ka 4idVYn+"텯Ynu|%IR];=I6wo{.|9v^6i$IDZ\۷oUǑjZ{y#ez 8rGXhk߯V{:ZwwwHggg}_eY*sWۣ>|z>?2F#y k oScIT^ﱕ:??yU鲳1}eY<D\j4t:z[zzjZ6Y.=mvi$IT^|)dY{h0,Ka8s]h8,˥ :|~$$ŋv7{_u <*cZ- CF\( C}VjG_? Iw;?nޜ (FPǏ\c0dD4^k:8paSFy~x,c/x Lg0<$$rn+"z=y$E6g'$cZ-y^wy#MS]__?rnqM&:g'0> YqIyr]J92c(R+a*c+R>|P$JtoLDql*MS`>gqZ-AwQ!,;0RjIFq,c$( cy ...]ehv8ussC쉛L&*BEQP(|]Ec<_k$IT,y< *e޶MTfSQi4 x$9-ONˏE$us$s_z<*d,.- `$E0UBa*"u]E4M<Rnp/ܶl~fSFc1}{{p[|q2zWqՊm8㸺Gw<]osmm.I;}imn8,`0*}:fb06A''u:+Sp2Txqj=ug0Tכ FQT5Pr:6 Ùs<q]WnWATaϽ}.M9w޶3u]eYK\J:c5|6~~~~Vᅲ*`0o><` _WEjZUc1 <]^^gL8n[m67<Q۝y82ƨn+go_7]'Lzm1n7i;}it:}_a}c#VKYu$HxW$p8 qp%趚ͦ0TQsj)"`d2p8T3Gc: PEfQ&-u6ÇBP*RKh4468Jce)u-|V| 6uݍ^j4 ^yx_JT*rn_i镬]^^(V)Z-cT~uM^MKE gnwˮi?Vv۴.ߗvO7 Cu:jUpe* ^j8)FCV[= FV9SJ@eYl9]h4$* ,YcuOv)6uv[Hu&8Օ*]!e6+ief F0a>;I;-=l;[O~3;kNëMLɲl=ֹۤ~v8]32Ic|u#bW<ڳ.[ /KP}:{`2nXW9~p٭KI"<^o˗/}ݢ?,Yѻ̭ IDATpsU&ϘϞEIJ}3<_S/ߺ\Z:ulytݤ_O6gRw}iWlM{pJ"`z3.b}wv;@ e_=svzn g30 +u:,[m<庮|ߨOy˶emy+w/ߺl,ۑaMK$XyFYU VI?աpKW{L#1;D\]{(gIVzL&3VYw)6uu48jj6KʸnB>-3B{M[AK6-ce;/y4Lh4tqq0 {Q Ȯv,zj~v8}>D'c:8 6{{uƘ*H8 f_<@=S}ype֪kۗls~1||\{mˡolm1JMvW_=zNSMkV `dR69m[6H|ه*4M炄+Am9nY#iy2fٹvu`><\6cu6gegN?yhwUsu]q?;qv`X0Nݝ$)îYvA|UۖXl ZɐeEu\UYk%tm( ٞ泺[/۲;س@/usRG:K]]X[b:ONeܮC_:y|Hު,KAv= Pq? 0 WAx{{+Ivs+QEv3@g3b{V}޶-L& Yfzъ0 l6%II, A0/Qժ^{}a3y^źK}x\ökk&ܦ~v:eL&՜nglh4-8VEs...fꡎϯC߶vvؤҩ΃8)Xt:HQU+m<ϓUpo4MDZ1zMt\`777}_aveY,\8~MmScJ 9`pE*˲/[ȲLVKQi2TA_E:l@z݄1|v\777jjۊ7|SK9߿Ka 4zItUsRW%I(ʘ$ܜ8e1Fo߾U3}l6}*ۢ>i?9m㶎vؤ)σE''2z=5 A q8FZA~_XuVE~m}-a,h4R @6<4Mի*^P< :]'>(1FEQ(MSF4}eY`>;|V[\׭%A3j-emVZ[MʹMʲT3e\d21U37]eY˗<޺:m㶎vؤҩ΃#I%I/^6wZKeQqji8m7o}zNGa4`)$X_F_H׿۹|q `G1T8~c3( ڷp4km}Lh8<)  h<gfY_p2 Vx޽{G% +   `x&8$rp%cZ-i룖%"nEz ~N0 _jIFq,cNx ...Z9nDZnnnhRDEQ<^]|WESi($=u;H Z[?'I(eaV,VnEͦ(h4b0slN;}Ih?*]-ҧ$¢JUraըDYu]Vs,K*O +q>̢($F~_u]?cq$}aD纻fSFc1v۴îlo߾{ܞl-Xc]x8E$qr Pӑ뺒>%&Ipvs>ϼ>h( CzDDEU( y.qK09WsuvAS۔sCHVc01felquZmA::my*˲zM]07̼nWUᅲ*Al?wgas~stZ-_sa.m9xNEuhۥ\ZҖb`,}Q~0ٵ/ƘѾ1vmVq+]]]۷Տ'\>'5m?wgI/qKnnnfTWr˲lgR;f:OM!/6Cc"bWfo[.K?edYV¢r{^wHs;heY.\ f`KѯMvm_]{76 -i1zFc].3qE*Ruu8d?;5C~_:fmZ/8TIC$Yv;ElwQnlh,w97^];ENޞH~mwwboY<tU.4MgaիWt:7KNnOʲ\}̧I(cceYVp]CSI?;cߦ!1ɘNlYՇ=vukU㱂 ׯ_]UvMHrGv[fs:m?Gߴ6 ]\\( * [A+s'Ϟc|_z5@'c:@8ރ6}{{љpƘ*; t4,]yyrb? M~N:uQL&z捂 Pue UyJ$O>: ^{+Bb?c<,O^  2T;Tnj5O<ܿ/Zj<gdL&*ə۲M{4KN@|.V|(6<ӏO' yk<k27$j-\im[z}ժv:7ΪW63Ck/}ozY3Wh4һw缾P׶̻u<sߗN90Nݝ$)î"YpAQpvUb<%6(y@]UKYJ:t?˶_OL&奢(R3muyy0 qU4MWbK ەAE*˲w{=p:IEjga|nnqo:Ij ]^^K$'}WEj e1]'I̵Ħp?G_ɲL^OFCAq9xhVWqWݝ(ٙ|WY\6߮2ϲLHy+۔TL&z=?ٙч4U^dR}2Tm*`^Gnooh4tݻx^VUm!m mL4իW{láy^ci1F+˲gk~xX<?Ա\׭%llVR^I,K|RU8 *Raɢ-~w'6mc98ڤOGK^xAm`g]0'cZ- Ãmt>+cU޽BNyy#/$I?_s>~{AtG v*FHq}~.1 Ðm=qA `$Yuv*N ⸮h8{l0(Ik;y|WS|8)2Ƭ|W_}x,U$_u]}eY6un[(nS>|$I)sQRzr0TQYկ~5w۹yq_yb2(2V_Wv*C΃(xrnx(亮x</|_sQ~r|DZϫ·Y)MG޺/zI* Բ]\\h8LㅿAE[ۖs=S @X}_]l[ꉝ8J9I4)=nZڽfLm9S`ι3${ۥ eJavam)%LIMڍ`!;Ai#]d'Hup>HK$1)|>ߏ}x< yg(R >xlr8r8to~@aCP(yޤ)++K)bV9NuttHRҀ\3Ĕ52n[CCC %kq8zzzNS---r8jiiсRN4[鴲S*O;Del6tMVSSST/4::5}8N-sfUWW+ FMv㱲t:ldL8^,1 Lpxx8f~2T6rNdc>Eeee|퍚{N֬YSLja~ oʐ.&'O2zv1<\gphxxX'O͛MoJ&p‡n['j}9ϗtMP_z922#GX<OTȵL#4s\|6y~.2_EE ؏Fm;z10?Jy ~iKk3'}8|K̜ycT5kXm65GyЬlޟ] 3db$+eZ 4Wia=2k_,3E--- 6Mk׮UGGǬـeeejooJFk Ș1,s-`۵vZ9N+Xdv~23"_NXM]}~<UQQavޞ̱qfxssCC\m***L䡡!+ &p:gEٛ3;tsZK^&3&I.˚_؎wsC&Y|}TWWCk׮αBMMM1mz2ktK_Zl*k,[痋e IDATyX?Z4מARssgݾE6M*++I8OuR Br:jnnVKKˬǜY/̑Аnzzz`:LB\6:d=T2(ۭ@ bM)Ϛ5kdt6xUuCPsr2CCCqCtef>4ML:}iP?ȵ$sD4244$ۭ+V$ۛ7o;o4>q~Ef_0Li3e,2Mp9Yd=Ll^Yv4441߃WsmyABK]ҝҹUoovVc^Jf?DKtbVp8r~1'3tIkN]3@a"E)QMi|39xvlJ.?9 `07C3%2'QRMMM¬ܡ&(bŊ(lƈ)3\xJPkfę u({wlVȹ"zMa4t:q~sCPL򑑑򝑙BLr|y>+G@nlN\Kd2{yIZkܖY755]?6[痏y)g-"*Htl|ޟ `,J^7m([w!g#]>1VUUIR.8.Hߟ>zjNSnzo7@ ^uӦMZM]*^@+у`fZA ޛ:x<*++)M& Ʊyt:ywYt9?8myݴVEE5%;|~c>< , _jlldc?ٙg|> }MMv8V|,t̳ Nl)oޓ}rv0J^Wn[gA=8nWEE۵vڜKUd9xR)󀮬lևufy^577X\dc;xuv}l.Cgll1ߝ+JC*kJ+M?6lԤ|=Ҽ& 1z8q9J!rATTT-rϜmMͅ=|y>+qY޼Ldfff]1_ϼM0Xu/vZ|X{kN B;N gt:oOOOwLX `6񂽳ݿD+3r&<Z 눚XTWWkӦMڴiSV5f |$[C-Dۙ.+m 672 <;<<'OQa&33ffbN|YFRn05kH<,ҽ6׳y~&j#Q3G1%=*** REE`JLc~t>yi.ӽ|`{̃3ǧ)wH@ *;:Ju߅=|y>jlkkf{O`PjnnُNĚ:^5\.KkөM6ŽnNn&뺝㔅{VWWGdm6ג͡ٶ)tk/̰0%Ǔ)eKxޜff8'OEGq3z{{ҢP(͛5<<,&!ϗ^֬Y2m޼Y@Z+z6S__n::: \|䁁p8x|>߬Zf8^oβwy'+eY]]qfw1;r:::T]]OCj}xxXY_uuN@Nֱ6***sH6n"?<b>{.WQQa)"3<t4p fȈz{{ %ʤ`3% ks4z NS`PCCC)?$Q0JF,i<8Z'СCjllDxttTК5k3ceA I3MӔɜ9/ ʬRfYZg51h@ jČUX>2ec?t萕7[d!hyrIԨBNS`Pzd`Y544{.sNG.'Oɓ'iRTL@a 0P @ 0P @ 0*0YMCk c%|"دTvK4*9j$I~* Mo}5lj?VT\dڟvlvlvlvlvlvlvlvlvlvlvlvl+%IԿ]1#^|pr U_~Mc`F?O~5@A `(@A `(@A `(@A D)M uh`P׾]3R ˶OщW4y=׷&>׋{aRF0Uf.$B]|J}E+Јh#aMި3E\llTTV](Ye[& 53Ebgd `aV } ChWSzʓWJ0:Z }VU*%%riTvңxрKާA ,YDvn&ܹSHh%}+.מ+y[mֿM♯G>ѮG'nWw)q3*vmhWTܗr/h@o@I_c u4hm+( ۭöxL_/G&n%XsO9iImqeإ^/zO.PcxE4٨>3qg$lWw)=a{U'u䍒=<3g4٨m7~VU*י"jO!/{ʩG&nWT56w~߽{ۧN&D(pV__[nSee|>3E~ Xn "R;mjҦ&V`ҦFI%k3E~טa6^7\GmW4J1B+:UK6Lܮ*ۥ?K{r@wT*v+mF+hηRjST6O5E;|E~K2Rcx^aq7f8"n>SO~.=4y6M5 I RF4&_6OŽY=nI7ti޽ڻw$ ݺu$Iϟ>F䚪 Sz!)'ͮuf¯aZ'WIj^Ee3ݟ$3q5WL_~,_pLyG&n)yI uduM9W"JB//׮7t7ZtZ&dFf,֩3ݟtY3qGByIgퟭs 6yv.g^ܫ'lZ蛡rftܹS[lM7ݤx@Xq)+v+xϢ.y_{‡\dJSrqdyIŧr4ىJ&/>Jַ&>SMzE6oߴy[v_˗ʰ J?xnl&=5?dm9檳SZdnݪ[ &-[Ӟ={uV]pA?u=衇Ҿ}v=Nep#?UdЬ2lOiZI҈r>pncx rAJ\5]e\֚2A rXTێ\wkKRl노|1㠯h aOc&rxGlp႞ym۶M۷o<zW{n0"F0}_4@>}ڭ&Rϭ2ҙ"JK/=SzckFf./:kemLfw)M=_4ŝj n\{&oTcxY̦ 3!v'v$n3g5s_w_v/R7tnm ``|rjhhЗ圔|ߩqbMhs+M]/=4yUNxb|+/^G4*[&@g22M‘OZ/˧+hSwwz˓1J ި ٶb mܸQ[nJ3"FXmۦmݺU7nTCCS{YF%}zdvNթ2lq$8ӹWU5LժuN&oʰKO]EzM-YYap٨ EROEbs~SzH?cTc8'Zs=y63_o +5_/ F=_. ]d;3.l{KK6nܨn=~xު& Dž k۶mWNUVV+'x"vdR&oS)I4::"JH 33NjL_&oMPG-c3\/(?D|t?redU?#*+ lez~ojSǕq/s_~Yw[Jݫ۷롇Ҿ}RnܸQ{9XB0P>;wjӦM/ϧ5U*=Oy%L_<դYdv3@Yj+|(:|Ѹgs}]t^|FdmwCg.=>km, ]gζέiMSMqQ>u~'s#Jj J_֚ͩLu:whCOܭ ut띡Lvۿ[m۶Mw2*/YjhhPҧ5WhGNjq۫Q}w>Ѯ*:Sג]U*׮7.}CߚL̘g:uviT^~!ۥ?O_&^o׋{fg۷ogm_J"@^yiTt;Z- _|VJyQ. %_?*:L@3*OYEoLi䍪J]|J.+eG&n.!vWJYR{?}M>O?T`*$NkH[T^~A#S{|*v$ U? ]䨙^R]/7<=}6km7JΜ-U?kDc^f讨uV2J@XT~@z_*{^ ݥm7jֺ^o,kkd `inkx%鹒+.s<^|V_6M6Fk*h@`! mSuRuWm{JX,=`* 0A `(@A `(@A D$vZĵm~7m(A `( xFۑ 0P @ 0P @ 0"IaIz_ôUhIWh[n$ufP Jio4UTd<"Qȱ$-]T4   ``~_ѣ4Nqjnn֞={t_6lНwޙx9o} `Usç%IuJ{_$3.R֭Swwwk Wm{oݺCԕdBζ.yjkksfId^MןTsssALo֭r\ йsٿ?3Bgŋ;vLcǎiZqc^՜g*tۥF%^zڿ9 xV픶Ifȫ!߯n?0xtټd'NPGG6lؠf;NIY@!\[nYؘ ҚM f]]VwΝVNgge[,y);Қ鶋s˖Q9^FGt^OļO*)c\̉'T[[k`7 [Lvl^;>>ӧO۹bJB!\ؘzzz,&.TuqWd,dF߹@G*A|Kd5\'IiFG%]]N?kO5?|uܑWm17짿_mmmQezԺuzjUUUrillLΝuѸzU[[zJ˗/W[[]Uӧu#{c2+uָRfz/~Q.KO=֭[6\.~8q"a\ϯU־zzzݭG}Twwz577kٲe*//8L~X`֦UVY?R׹sߟr0_jhhj;N=1uD%v6lؠzӓ8577[Dd_1kŽ$S$i߾}yΥLK&QGGGrVG=tl{ן鴎^ҪU= W>Oȩɋ /F-[4:cdƎӟyFTc.>.:%Ir\~g5uuZqmmV)\ ;@WYsi(%]koW?񶵮GYpYg*2ュOG?{7/uEdxxXgϞ@ֈlnn~_gϞxZkr:xI5l˲\b||\gϞt:U^^9v{~UmmV^{&ݿnҌ)#ә?OZfbx:23"0Yg\=oxxX]]])XFࠖܙ*<j{,/I*v8 qKZq_/Iŋ9B^qȴ]L {*PáDI+O*<[fq2Vܜ8~}k(˥ue-ClǙommmz7La[[[LF`ay<饗^3'&s5)Fv:::ܬ;#n0~Ν;r{lذAz饗bS1<<1kYx<U^^zku;::➟і-[T__?lmmnמ={iÆ xŒltdr=z˵}v*3e\=OR,L{c$zβtҴEtF-,s q!i:w*PsByo./ZkW}w%0#1ե}fHCq?#n$ tZR؟`p|uQ|Ҋ*}$MbJ[*}wwc2>+s!^7*2<Mi])d^{5>Li:ٿfӧO=tS3"׻/vZey^{[ѣIzKcccILb'2Ll[H0g%Ih{}PiMMҠŋdvIWÑ_lK'7v)v8>xI]쳺gUc*zj𒏮T(0VQ^qTt:4օ?&~IW ^DLfykp,^|n:n[[֭[zk ߯_򗳮ڸd~'k3b'2Ll[H0g5h9Yow&R,4{oڥ|z]<9 Zqg?JE,.>e/q5/"ڵk׬[|,/~|qF-8,f %zlՕڻҕk^˵j*577r{O?f߉2ɴg<@;܍8Od"/Bp)I҇/_kٿ_:;U~1ΎײBg&U~}2.T:;ĕ_Sٔቷ$夗|t*<*WsZv!1ȿ+Аhm΅vs9SZ92p03`6t!dR]t>@zU[[u֩{m#>^eM,Q{Gj;Gԧ$I+Rҩ8O7  j3h*Hcg$\diٿRlD?U\L&٪Uxv։Mٳg%M"3#[[[u&0nݺj<Z[[$jr~]'z577=qk}s1v]6lнޛp{ӖǛLkk6l Kv|<}􂸎#Iԧ>5=Uش*/y"2~Æ )[e:ҽi]d߯cW:;s3 /Ĭ;yg518b#Ǒ̼e\7^8B#UT%L[Ejns7ʗNُӂ8.++ǣ{r:*///~ re)ѣG֦r=*//כo[o5g߯gϪV_;wNZ[oUssǭٳgcs9GAG۷oٳg=== T}}on3k2===xhkQKu^@2og5K.MX9SOtiƍ٩xBiE+xeq鸱ct)q9)W߯XG~kV^ݙ%'V ɳ|.`/Z[[,˥1>}Z]]]zj\.Z*+qG?wܡe˖nܹs:xy/Z*:xVZfĉ[6u./C֭oѣ w^+Sxٲe~Ϟ=ӧO' ,kllLVJ mOOǵ|rUUUVcccz:~x˗r.GK/ӖFzڵkעoR2/٘'^{5kݺuQ?-52'%||}zUZءktʖ-_^Uwߝ&7r͙*[ZK6nT:w-o>T$),Ik{Zj0_\.3˗[ٽ?[o;/uV_L9c(D\n喘w) |*v8r.+#$Zr6 U$n֖5逶)yK W;?rSڿR@>utt?*xj\?ku۷/2saoĉt: Gء;vȫ 6Mcccn i|R^C0իUUUZٳѣGi 9(5t9b `(@,NzL/^ǽ3ߦ"k_(uٮKZYyX~  5օ6CRzzg(yh'`@5SzuW0oH/ցbu[Bce{Czhˤ$髻l:URP!mnmj+k0X)= Zڰ&m㤞7/a+*"*$]@)>V>tpc]8n60Og*'g{̙|ZJ0-~L`\| |d"#ld(ρ0`ξlkX=Fʊg$`$D/nnp]Zv|_t#nUwfy'ΐᇟ,=MhI+;7Xǟљ8M=]W:Kt>A0amT) ktatpbҬn7=ݖ+k:3X?-z#$;K\Y!qMmޣmȽ!moT,e1\}uq0w=Z6oO#knґGv}ٹٞ “W֤_\c]36oH8D~l퐭̇ftWͮ?0Ȭ$#ͿiU׆rYX߿6MhS뤾dYL,^ѬUfz=7K|~D+kޣ!}\Ѽ2宙;C1?$0mc~t2snea}`q6M+Y -KZYַvLheM FўG h@E _L*҅@Q:tZdl9f2L'ˢ/#~]6~Ѧ/ns۔ EE']eY_ztU9=}X#W{FGAc]X;"Rgْj?e\g5sEQ}}YqbTS!0Wz*us}*Hjo#wsV{Üʚ\3_oG谎c$*IDATҦ_2#/=Yٰ:LXA3Ez U]3<1Dk]?SgU:Q#z?Ln7L\):y=['Ww7MFe~f' =zt~s۔vt*iTY!qxVurYR53Xyĕ~d0&kvD7dS#\Bmy)Qlg>%sᄅݱB>^ԑ]A+(`>kx8ȀsJ b}eZ4IҞQ}mj,ΖGgN]Ȯ]W|`z}.G{%91rQ.۬YaeKoзfg^zz m̄ߝ*Nx|n7ΜKVz{SZbk ٲSglPmL= R8$?UG{9\wHǽ:ЕZlY U~ѦEVݪkKnnңI/wgct;dOeDl@jKf' -[{:b2#x#L'wah|_sgKs;ߩ"L ۞ڳTO.믬Sm NtvR_T3ߕqXG.,Q6\U:QhB?iʁ Z.Ǵ-9_~+-V$S0`^,JYW~Yеu+/sە6N& fLrSڳ?OEjFY u\5Y,RյX+hۺ0<璈6dZz#?}QZj̋ߕm T Ƚ!kȽ!^?3+S{jHبT4SdDP)$CnHi%*upVjdihStTDDJupll$:@^Ob}2\I|mǕͶ-cgռnh ΞIw^Nls|v&|\zZP>_6{tDǪ\_|q#>u"K|z&_K؛=ƪ18P_71kn;f1]GeZ\k2`8y"m w{g1qY܈\uGfol :o֙ܿV*Q([GԷm o@OoqW|z(m1_nֳ\IV}m3.ԇݮ?~n+Rn9U+˱;wDčbom=wLZ_6DZDq/m4ĝݘ IW.nFa/Prn:[ݾ?W;Й7}Q^h_G=1=׿}u^4VrqA>JOc vo\Fa'I_0i=g3K}\v%iDD@FVQ?&zSj[q}0ŋƙi!0@F2"20@F2B `d #/IENDB`qman-1.5.1/screenshots/qman_search.png000066400000000000000000005343271510660157000200200ustar00rootroot00000000000000PNG  IHDRS׫iCCPICC profile(}=H@_[A;8dNvQjP! :\MGbYWWAqvpRtZxp܏wwT#eq!]0 Ab>'Ix{zY}JdO 1ݰ77->q%xܠ ?r]vsa? }"xdD=`OI*D6>ڞ ;N?{\p~hܹ']gQQ֬Y~ZzUQQcK/_OiӦNokΝr: /P?֦~`Q&I+Wԣ>iӦŵ-׫FD}yfK`yPSN;9XqqNu>ı-XpBKz饗jժa2e?襗^>1},.K6-'Cqqz!\.r-~;Ђ C=ܣYfiܸq5kBPڏF____,YN;M%%%;wyM>] K4~xM2ESL1>3g֯_/ǣ/\g̲_{W .}3ҫ@v=k6p%5f2;4nܸ/_\'O$͜9KnI{zzzuQo~S?kv~$ϧe˖J~k:v>y^}K_2뮻4autt藿Iu1}[ߒ$XBӧOv` 三'Z:Tqq&N>Ĺ0>}/^VaVXa~g`irwHy:thvuuwL6Lvޭ{/oKz뭌gmm6۟'|MuttHN?t-YDXHDuM7nV=zTV{3<Ç$dVaai,'NLd?f\+V/~ IW_3<駟n|E鳟̙'СCzgi&?~\tR-[LCSNU$/-[b?O3{hŊG?QIҭު~5kL?>VͦZ͟?_3gTII~im۶M$ݮG}Twv=_|Q3 vݚi~oʕZbfϞO?|;fΜ HƹXb=7xCo멧u].HvZ̠ ̟?~z5}t}ӟUW]޽[7̠Gtg( ;[ַקO~믿CW^z`p뭷jʕr8 Bz뭷w^mܸQ-Z˗k޼y9sB|>Swɒ%뮻4g>|X---g<_xIuW+K/I+Ըq۫_Wz=y8yd8qB7n40]rJ]}fW^yE믿N%䰒C&RPPqĉ)ۇD2կg}K_2Mv ^4OdEFPw߾}:uh޼yڷonVIݻp¨paa\.3b E"}_$]~Kw%AK,I'駟ջg>[|qfo쬳'> ]r%'?p8G/6p8rJE"{я~Ǜ>}OfS̚5KwyJKKUSS#I}}}ӟ$I')S4{DTXXK/T iӦߢ^بO|z%IwygKӧOuך_yz']_}g_tRqg{Zdɰ匇{>OϜ9SW\O~Iٳ'I&#$?iT^xA+W`3Hկsύz:}`hhԩo+IZlJKKuWرcfpo;u7oΝ;%Fwy^}sS$ѤI+V3/~QG.++5\#I׽ޫ%K_e;.͝;WwՕW^~0ayS;k,Kե}5\ӧ+г>+Iъ+4cƌc5k^}U]|Œ;wC&Gm㪫Raaᰮ*]uUp8B-X@0{V;[<'ڽ{493zfرc6$If{L:s5{l8pshkyyy<'s饗Jl mc9rx +WjܸqD"zݭ-YDg}Z׿Zߌ4|wc.SQQ!I0txܑ\Xg<ߏD"˯ƴ6ڇ~[<}Q͝;׼4F)SH)po4sSLÇ/|A^7MZȷi`0jOFZvwwGotg'x50V~:u.\(I1L*\5soo/uJ5F ѣD"jii*,Ծ}{n=z43f07tG:A#GikV ,P8>1]ve7}3ΐ4ֲ40׬$ڵKW_}.`g$1{.]T3gΔn7`uG/~!p@kcv%I曵l2;G866gqћwĉ[TRR3gƽχ4^K2\N4 u -RAA~ ecK"/k|@կ}6mwڿfϞGy|>nKKyf̏;-)SDr<|pRoLj*͙3'*gJC?f/R#P}W3u\p>c9rDGylMMM/z(?772wyk %%%K.D]tx }+_1N; \'꺢BG_|>pI{:Nj׮]:묳NwfмV?c`Ka\.^Zg}a;oկ8̘:DN3خ]Fge~:9tYgizh3g~a`ѤI$=x/3SO=7o^{5s9z衇T[[ky^_|Qo:,w}}祗^ROO&L'|Rǎ3O͛?_U]]=v׮]kךzg$ oV-[L7|ߓO>)ݮ+W3o &hԩfO}'-ܢ.H=?oY%I%%% /o7@@HD/bo}K^{NG}<G>+ Իn3;P(ke]"8p l(h{t7o4?=ɓ%Iׯ׺uteNSoo׿j߾} Zv>OK/ nKׯ׽ޫkҤI:~^{50Рɓ'+k6v;;;5gM<_N8믿^gqJJJ̠޶?я}ǎ:ujԼ?ۧ˗Ug;ꫯӒ%K /^ӼytgWOSs%KHvm)x!UUUi5n8w.FrB{~_}׾&i [nÇb 9;ڵko+ %U{9B!7dp6l"a{* * .^8E"#ZYc܇XpQg .Y0RW=ܣ^x͛'ۭ?:r䈮˿$+_9|v^/ZdɨAYf'Tqq>=S~z7tvjz-j=.]ݻw*enF+ iҥ:x  3&M2GJֱct1!}0 .R}3yWW~_&zJVYgjՍ_zW{6$?_/… u7tX钒[NOURRBP(я؇Ef0ͦo]0]]]5sL͚5K&Lиqt!|>}4$s8֞={t{O .Ԇ tСH{4i&L>ݻW[lIt:qӟTG=9 B:3&= 5WǏ04 /w#\B{B!Aa!} 4qDM8`#?ǏSeȈB7NǏWQQ % q߯'N/%=nO}(&Ȅp8'NĉCl0 '@ y0wyT

ZZZb.m6\.-^XNSr:z"644kmsJsnݺ5ǶfUUUE}p8Yccw $y<UTTtn+󩩩I)?MӡC4i$M>]\p-Z'[jkkӟg:tH4}t-ZH_~~ _$=z't͞=[rۧV?~\SeeeR˝ `zU^^.an9񕖖jΝ>76jHl#+=UZvjjjdU__Js(&555z @! kM:::dUVV2y<[n嫫rxt:jժaARm߾]v]`P@@C[lKcp\񽑸nUUU}|TWW'c8ƪ*y<gSO=ٱct1߿_X=|{13;xMW8+&߿'͞=[]w]s7oʛv].K.KeeeZ;*;X/GV{*3z4|L3Qii\.:::rT]]-߯άKr` twwA>/T]]TQQ1bOjmܸ@s8*//\]]v|>̀CMMك-UZZZ;Nm߾]@@wyg먪J֬Y#ǣ@ Z3cT]]-׫aA=7,;}tM>]5455Em:~ݿxacI:tϟW^yX~߾}ViR ڵkctf=j?md۵uִrd弧b?9>eIGuuuf`ovQLKrsy& SdehpK͒gp:gkcqӡñv|678" |cx<漭/~a~xʖi cw˕DQ*{%ϒ=>E#~1lp~t 14'n^Nl6v{&IG]#a8S$9-X\`+D|}٨^^x!3MӘn\q|@`D9Jy~JNUxk.m۶-# 8#vP6M555*++o.I ԤuhnWEEEZݭFIҖ-[l͛S%K?;vL7i&}ƍo~sXP / ?cwM6驧2?_hQ ?fsjn[d橱 (=+:UҚ5kdr!rW{{ʴeA9vmܸQUUUr8*--5*ɨxv|~Y^W6lPUUK9PVlݺUCG۷o7n8o2͛KFn*++cs+Q?.]JLslhhЂ rsNuttD啑 ΦtTL\י.zy`ݺujhh0]C~_VRKKKToTҪU$ vZ7d׫ ɑ`zףݗS= B!<ޣPyhL|lOKV+\SޥXOsJ;+ϥ@(--UUUny jmmUssՒf[߮]d۵vZ~IQ]]nᆘsNIҲe5&"rZ|>NS[l1] 0Nr^~ioo7˩nOr~oL(t[Ha_?~LkxnX}AۂAsP&*2# 46t-n-VEBT| A_hfs=Nz _YgGF`V p\r\rZn]e 'C^7'Fy^I#S\ys,2_1cT$R/_߉징rd<%=c(˘}t,Vʑ7׮]l6~כIjjjRSSSJA2RK>WD#3"y'곢ݧ~OՍSў"yjdFD:"^`M_o-8X"_[gջwkԧsVnxFLӒK^&kXu}z}R$r}.O޵RZ=%{38/ ֦1;vph*//WUUGZjy0E6ek.v-Z(%id ` ofݻ:~<7xө۷+֣;nתUnN+**Suu\.֮]kDhǣ|www>m۶Mv][nuen{ۋ'S]]s81箮y`(*twwA>oضTVV^f<@To ͦjy^ )0n}>_T`qjVQ2%[KUUUiY)ɰ=p8vaNS.K`p]˻r$񨮮ͷnwJVLbmxnX`׎Oh=)RɃ%QC R䜈 h\83~  \p4zNԝPdJDŏhC,[]`^WRV,z$c=|C2j3{ryjzfRUUUjhh0{~^YY9jOt7*++S0Ժu$R'&ɜL{QfHDλj~zi%=%IeeelΑ6ʐRiiyjhhnee#8[T\}^!lg%.٨2Y|@K՜͒ x(shόV$ BH mvuu5۬F?MΔc<܈-cXvml[Csww y2F}9X&l9J4dҵ.VgvcnY-G:?37'[RK*DΉh7 PG}f ,IߋhOq :[mGfFrk:CR&!h'.Ov]iغu&USu{{{1uwwuDg28 Qf=dC&=nB=LZXId73y}Vӳۼ?61UUUUjoo1iXflKyAel? rHQ5>9^Kg73 je|D1{FΉ(2y C107S5N S)@cT493F٩&-_-U/^|a77&<7ڼe-7 &r!o6<v~pZ2-RK:a֑sLiԃu}|jRvkǎڱcGZ!ayi<?ԃ+sJytIf&dk5 1s"G6%2jG.~sU$iѢE-_K)gڕwX7Q#M ,c .="K ڵ+mpbXEF3j~9ٛpZMx3*++HQcG~L/*GL X7(VQ^h~9:_dRfs~  FfD 8<7D:u&R/=Kף5kpp2gcn# S20xStyn6LZXMtonu?SQ_0^H{NEEŘmd^\lge>f` 5{a7ᥥ O-'s.Kjjj.ZfMԅv,0ކ 5fm.jjjn,M"Xjtl6ԘoϞ  ZǓP9庻ͼe˖am6***y{MMMʇr%rlyt3^jr\x< fvyZJbސ|?8*%] W$I ~BnQKј[ p@3}籱ܞVT3\]g(ifiFfy0>:gso(Rb;+Y6~_7nԆ T]]JA4VVC}477\}}o߮2W21zvttaLQss^6lؠ*-f˽ˆjhhЂ rsNuttDvL _Р 6 ;)pZ6lP 0ox#pl~jooWYYlbnHӍ7JC#w!˥;veu޽ǝr[nchv+Rmt/VQ*C˟3vjmm-LdQVL|E+tOH朽E"斥b9'M,OyX¶”m+%iZ°/WQ[| ,rN$KN:sL\oOd3_g R\SծzszuVթ[MMMcjooOg.֪N^W^wy@(Rb;+YyE~_UUUrr\ Pkkn$~uttĜh._\x<öh,Ay<s2XS[֭.cFn|Ңm۶eE#q.v{J r:r8yhooћH~1ιfWSS:;;UVV&!=׭[+jkkڪ 3}f.VQY2_q)|Ex ;c \p@%(vΉHGMe9UڊwWoh)'dCJ݅q;י>B+T묞\~p c555tdúufs@ yzz"S/Vf'[_;៭<Zj\ff)iđ2y=t!D}IW2' IDATI0aRܹS>l<@8Nm߾]`0.!n bGfԽ{^ָq*ش';vphժUi>@ ˗sRr͛^s%IvMw NOOu@ikk#bXhѰόR$ɞN=keQ<04B* 8 aUVPkdH/c>\ ` ;nJ'C455vpr) Cjii!`* &f7ozYg̕$oۡ61;===]H@~ y0 Rmmmڶm[ƶirb?sEMMt:W^zww_ږ~fZdrr}wӾzQOyw|aQ HiX.In )0'||~Y]߫𢑃h|/n-VEBT| Ɨ---RuuZ[[MK{J'}l]l"I  X.C! u伧uU߈˖7@@jnnٓF^Wk׮Wee^:;;U__?l;::twzl;vŋU^^*9|֬Yǰ766~<@@#qm6\.-^XNSr:mhhqdλUFp+uyWedFD T+R{=im-ww=W7NE{֡#XgLv~C3;|}SС.gUK4]$D EΉh~̵[PŏO}ꯈFfDxOgE-E#l_ 2ZE / ){x:z~uR:T%׿LT]ZޭיNdVkds\hdM6_[nf#=3Ϭ_1[Kybr\f0 ptxvݪnluul6ۨ4ݮ͛7L@@r8*++v067UUUv\.vnݺƌXf:r\r\*++Smm{^UWW+(r/M~2* zx` HSẅHSXQp@(2#:zUH"D:'°J6D:u~ LҰyl.gU2۳.{-4 9'SɃ%QC%mƑ.m4 K7!vIMD"- .^gc!2ZQw6͝}r.i9#e3Ћ,"[,?Q"EyCtLx {Ihq"h7ăȲi¶{*)B0fA#JM_{b,"kgeٱX,BQw u?%x幸!q`2F,ff0 clYa=θ#k6܄a(O/{^=.uf2☽f,~NJSqzqHnTOq]\,Hǐe[[[cr mS]'zBZz>4ϏG߆m]\gXZ"no2E<w1W-0*bpwױ%Tɗǯ׺{};n5{x{3oa l[}:\VZwvvq 2TU]=ô~ڥ06 Àm(nI\*o|A&?Ql6 q=姾Oz#|Gnc8[χ_Ly?{&*.m?ŷr/'^jmSU_zǸ`Q./uU=[D~jY^uԗ㉴ShϢ(8:㾏œ/+>} I* ǹ6@|:qASUU($i.[D;qH]cqga/sc@&J1|4\W}kY\ܦ-;bY،Evg7qŵk6O2LdXF e2ػ?z.SgĊd|.|$q^ex?dXa+Xy5lT67k3/m⾼{n*v)eKg']U_zǸ`QZzw~Jv^gz/Q'nW^7~ڳ} zqGavQ 2* * ovIeo烶A zbN35m/I>\iv0$Aeg^/sc@4Q 4 yhcXvW^%Iryahq.q:k֩mېe,lU1ИϺi{M|=ag{:7WnDEL;vQW_b/k0.KUs0ސ] B,-( x(* ӯx=_T`}hV=;?g93彠(i:Lӄcc٨۳} zqGQ^Cue'ݲA N3tZ>-8/I>\iv&Cy+?U¤_ƸˁhY1L^[[[( ܄a`жmTՉo|S8o_wEθQ|8ȷܣ*&ț({^w=|{ޤΗҽΈn՟Vqa\M{uYRT,׶-W{(L|QoイԳSVy{~˼I.o'0˺^˨} zqGQϲ,75ص|:qaa&icE>\iv0㐤~Gqgl黉_rD)qvvjj UUo8)=|cߐI墮{X_䷺kRw(y}qr2ax\/дIXKK/2HwZ>|Eyߥh?bc(~eQ鋻Hk}}u aQe'ϟ%04}A3(󩪊bT*akk |qAS72g$~He~_zqk㐴qglQ%_ѲD)vQ#wz=w՞6k?ɬ Cy]rb<14cۓ?ym7@E,=8_yI>wѽwM\ľlq+L_CZ8߬Q e$k6/oF=}V4}AsQQIss4M(Rv>h{帠)2!WM-uQ㐴qglQ%_2`(fV b.d?/Ц :t],pgfl)-2t]ym=`P䇗\y/~u1h;5 \|2|+Wn fzg aV6}K O+l6˶Q/L?Wu.K}]&lssS]IJKt”Okק}Vθ+Pv'''Vma\v>zqAS,i}Z[K=a8E=H{vpUqCQϨYexNsc@&J|>\.7!>L{qttqfQ*&7 |~.v=Hm@јyxs.k(Jc.]>::Zx}plnyxv8  \^5>of^|rߜ]M|Y}K|`m$pXayk?xKy5`, ^1M,CQ- nP~^綍{{{/m$IB.n_nM~lC6KX,0 yO,h/ øŊ$ RD$brך/g,L\gQt8r~sXe粷A γ3wT*})8/> {?O/AEgൟ^D;sUEqE뢨gq[Ww9-+LX,ٳgm؋o5ͩ3eT* 4E,s}X3<{ BfU\DFXtzCYA^\FiNhL] $uj5uYnGGG( T*ꫯm:*at]mnl6seY=QqӋ*?{z3rO/jE׋(Y8ܸr Zk4pBQhqn}IhYP(:$I$Imz=ozpC>,˂i4 ml^_ bZ80 c\^2^agg|at20Sa_>}ԭ/^ͭ  W^`Wޮ7ps|x3Wc-2_6?^yt ?cpgpR̫_ZsmfꏫXasW|ꏫa ٓ`ga_Ziw2Zr ,]*Ja¦O~.ƙ~`{{mFVK8ĢT*A+g\<1M݊²,ut]dY(]#ˣ RUU!I.8̀BqG~WT 2`7Ri"v>h{rgggBXPm3Os(8E=h{qq?W=YdG;?z>stڟQDK>n߾ t|| EQ5Gȿ|>bZjDϳ_}Č1~/ϱ:'pwFek?y\T`bhHu*""&"@e?emlI>s^I׿zg/ֿ_骯$IBV'** EA\y%4FWUU.dY=aVyV)iN""񹊈h6(n¸Eݗw1ܫ௟ٖipvտۋ7րgYVOœ'Of:"4M 8۶!˲Ӭ$""&1LDDl{O@V\z]W-}w{.g2{ҁ`"""""""""""""`(%&J|>S6$:?L_Rr9RA[rps۳/ux%NOOqzzRtոˡT*2?/>߿ǻzw;@}}_9}\.tNOO:hnD:!qI7}k?z\LlfaQJ%2}DDlϘ%NUUl6^NN۶y?\il.OP} VWr\ޥ! IDAT x@ya\`t߽wgמo+8WmX,yZFvWǙq#"KDɶ, Jq`6R6EQ`f/Ex1},[u h4VTz<0.k5lac%E`Ù?x=zx3{ߜcy/#<{ |lS|Dvvv?W*18"]"J6R''''0}DL&, "͢r/0 vOf迭xz+넵s\XunZ(0Mz^ M'_"""""X5 KLjRFw7f迬zޕ+@]Wz, ,cssHDDDDD4g;+988iϠ*3R iN- e4i0 7pb6Z̙-~җ%rӞ=_ReYPA4L/^g- mț|>4jѼ,J$ eZ%//[ 5M_ǝp6+W\x_/oO0.QOkc7;.W| wV{)Jx޶ܿ_^9qaMO >y9>Vxtpow߿eEu4e }WhZ0 aD:us%xW$y70vj|U^Ɵ~0|xK,}U=(hcL'[x>0+AY~EKa82/q>mwôA3ma4 jVM\g`!v)Di0QJt:Ϛ:4MEض ۶i Àښ9X( mNP(@uD}9m? >I;v,4 !͢\.G'i'qݲ,#"0HCȲ5( }Q4(EQP(`D9i5/ԧͨ Z_t]GR,:EQP,!Iԁ%}ögaΗ|= W;EozV,֏ɲ~G]QdY(2Rad24-b˲ƖN-j"^9%߿G>`o+ᾰ{இg^V07@3^;{ >oi5+o~53=. J{szH_~Xo0N>-%uKċͨDq^$/AǃXWK0θh4-fGQq=828v)82L~= z\ |{b&t]θ(ۥ?D)!Ĭűb ( 677gd j;Sf#|jt)UUqxx۶=Ϯ\ bM`6 0n#z=j54ͱ!UUQTf";x@j6V@U|[wm۶Q.ݗ${ƕJAedYH41(u hLO1H}d2n7NKRgiž/)W{T`Kc>,c}(ǏCelmmϹ\n 1W|S|[⺮}VoQ7AIn}s |(9~kl]Ͽ<,ʆxd8˵ǂ+ogO lQA #H?̷7zO"wyWq^8dYuU;ORd<妶ڗe︯3 ,r2O骪,{<qdqVaQRqd?h{6,4R,V,]J;Qp`"\h4\v=Lbs5?KXȲ,\,n#pH> Uՙ{KJ~[rCOqKĀ}ڃHW) Ȳv=FߗV/)C=|IɗygIjoF[~Mo?-($^܈/L_,E/,q~f%׿_ zk3_KC3$M7#|Gn+?~>_]ָ|.7Ծi,˚eYr1LJirHI8Nt6qd?h9.u}K`DtD4jJ&ueYcg~zO?D:3uMb zj!,Lә:k֬l67k68V W \H|&&}IQAڳy/)u{v0pSͨʯn'^({iuXZ닳\dw'39\4{] > ".ĥO,!]6*aPO[ݻwL{ \%QN\LR7 h\.72{%qy%8+!sjqd\s r\mci%vpņW^M& [fi$WWϟO|VUUFY~.;:: 7QrtDh6/AW.Q.Q.wYKJdy//,KߍZ8$I +AYq޷aS_E<)?ΠϷq_K\`I|~pOJ-t3p`" lb9Yz,=O9"i6S^շ5ϝ60긠h6ͱev;S^٫7lݢo{w9,2_nb;8aҼnmƌT?39o'-A敾|0}^gAeiA$HIk_j:=zNs[3Lu:_]8E=w$ig8kmǭ:>Fag_U_j>.HÇ'{`ߒաFiڠQǙx!#:i.xXODʲ]$loo u|~lp=c!:8Ҷ^qTO]r9::t@M$J%۬Q-rvvvotV*Uyooobp(Irvwwg[{G^S_Ɨ(WT[a=/qgAi݄~3[ċ0_L5n@.^¸Vޮ`~{>6# |욒&LD07ǝ >o{^z}>LJ_}Dџs8ۤ/Aƃ|\nb;Ύrw~3u9_TUv,˂m4 aqIy 3 {._=n?h9.u}r{8߻%/D=RVٳgx Mr$vbiqt:h4!2^x۶!IdYFVCXFiNh[qj5Ea8<+]{5fZk ONe.rbc~lߍ_uKͽ2Mӽ܏%};TbϞ=:i6A3*fǏC4ez juf9NMj:GzU~t}g7_:>߆l6ꥨ/mV]{ *PAӷvʷpp&_X*ֿ_.?8{>ʥW.*~X㪯E?nomFqr|ݞ˗|A3zATf@9hGz-*/AYQܷqKA”{ |mi( n[jڵ%v0nIyKs1\O "`kkk/^؞?|bZ-g^GR~/ϱ:'wFek?y\T``/kcK{I׿zA*Ҽz2Q`u:N$jX%_d;HD 0Qt]K"^].{b3K3 nmw{,_U*d2wࣣ=-7nCI`` ֚kXo񑑈&u,öm4M3S Q۷DDDDDDDDDDDDDDs;qz?xw޽{WDDDDDDDDDDDDDD0QJ0LDDDDDDDDDDDDD Qh$-ܹ\T*s|>Snx?,{;?t\.z$""""1֙DX,Bu3E6򺎎ώhnQQȲz$""""Q&Eim;itm/UN7Aq,2E(D\eYTU"ڶm8EQ` 7o LJ~|c\=eIΦGӴi?aL HK}vp,CuLF\ʁ}>KI'T*iZ@DDDD?prr2E*Ϸ~n]UUT*(JG%rlR,h6jc/UUE>g;i Y]ױ MӰ;sclN|atm Kl6 ۶I巾X0iUuwGUձT9b@DDDDDtp`"""Zzn]Ue4%AZ1%ҸLi~Ӳ,qhel6i2MjvfIܙlcҏ3R>& Emh6Sg@4w_Qb{mooP((c{d}//w4M7vb.窽 _{̙ZfarPU,_[~aWr$ ibssӝe6F3Ga3h s 0ܽlFBј7AgF9UUu"A=y~n8ς_\`oQJs^FB01jP(Ɩ6 mò:W՗v;Lf~{&}[|RKqGR $,TUXSۥ 8g}x!,cYĪan=fT3ϸns# 1L"|Bm@4 i9E/g rL&CȲ5( 4 H,f{t$8HDDDDD`(E jM|>oV%ބ{fVUǏ!2^br/8DzF»yfu,LDvg-e%IBXi(JW48˽X,B4ض'O/E00 gpgEQd29jXZ;41 K'' /`L z-_~^eŷי4jP,dgպ^HKrMI^9213| bc0CX[1G|!NQlnnN_CVCٜ+ ,rg9ލLs#{H[(AUUA2wq<}ic/ӄܗFb6ٿ$.__s8"X O;˲:~AUP(@es×_EU?j * qKaXѲ{F$j[K^ R~l'^AӃmoo/Ehө͋w pgpU}g2wܤ~ 21a?dh FýDzZ-fqMﲟ&""""Y&Ji:,ۓ0iKN3uv{/DpwK(\FbOi3/Qs^:KY.5?/z퇨~~S7u||rry,39':^ZxP|Lԫ/1>33zIﲟ&""""Y4QZrҶmȲ EQO/x.vG6ǙXzte7Wݻw ċY{{G3:/z$IL1?yU bt#ٲ,Mmzh4iaY6^z5ll{]} Z~l'^ضG-u\|l`짉h L"/ g-K&Y,wٲOl6ǖ?/^EҺϖHF뙟uUg/'՛e=vx葻wiq_e(GiwݞD~KCq9s}WljqRٜgΫ~y,ύDDDDD4`Hq&f^6YWm 8MӦG؜ru iRb9Y`Wl61/Os,O-ѥv|0:}+Z.]~Ϋڣ9pd2wAo`/LK'&"I;{^&1_"k}&w/O1^Jx0hu+xּ3L\X ˗/qpp`3 H6E>w.IFcŃ}>{/dY[P]ΰT*4(Js_{vyM7RE$r9.M=S^ϭ{RiW0:}{ttN|N`rm4T?Գ|>\.7U_s?SUJpf"_~4MȲ EQs-3]ױ YtZ|YvO?E{u]pgy"q6 ?|QƣUIP*U1{0|q5L\X!24Ms'""""q`i(0M^6 yȲ/^mHYQP,=gрix F1u *at]mP,l}yZgϞM\.O]ٲoWF߇(0 m}6 a)Z@4x]Rmֲ~qaGA۳3eT* 4ݺ&;dRgrPbϞ=fym(۞L;8(ˑߢ0_~hy3]Egt:ٙk{ݝ,3L}vm ]sT%8O5^Jx0HeYhfۛ?BEQdfl4 *^BZ]h\XZ >,˂i4 ml^'nkk R B$t]qOj0 (rP,:Emnd`BB`iey拦V.e߽rV\.UU( AӁeYs[4(?|>0iy{?4}Auֲ,lmmP(@uHI`6̙IAˡhq7]v9~, OiPmclv10R6vvv 0( :?N*ݿgn@5ٳgc"GeYÇEuMѽg,IL;ضm4 \{N\- ~-X}(JPUnjP(@$X5d20 CQH`, FÝ9r """""""""""J2idYFTiEAR[F2;jJw xU&Ѳ,C4+g+2Q3E(eYT*havϊX]>ix ,ADDDDDDDDDDDpi¶m83@3HEQ¶m-hZMvg;ǙK빳%IKSveZ*XnC$7?5MCTy N^o3~vS48۶ct] FW]*ѣQ1L tW_ T]ׯ(s9{`0TgdYFZEZݺZua/:`Y`X/0 s~t]'_zōìX b1W$5͗,8==0۩T*ip%e4q0.ܞ 0?Vf[Oab16V WWWpgm)2\ׅ(V$)xf 4b8 0 0O ;qww8`4)"$LJJUy^!1 0 0 0&{|/_eS{pCh4t:ү#mJ} 0 >0O{hϟCUUXUU|9QBw/>>>BQ<P¶퍻~ݒ$fK'ƚ( &ge8NtTԒq]0jiת뺘0 N@)hZ%x|n>q/X)'VS;'.-*$ e-;11avT;ҽٳ7 CImo|Τ:i~o¶m3 ZmiچQדK~8P38+C/%_Kj%KIgea^ >˗/i?ID3ZnZfFmju-Y׭Ɏqw<0 (,lZ$ H_M$(;nn-k+c~g}ih6p]B4T:\l6i~l66VߘW&iS$,]#˲[V3 jlX0 ee\AdY ժMJӤ(R%?IQȲ9^6B]\ׅyPE, YQ~]tf)e%e}}Vk˯:XGϩ( : }JȲ,j(܂NIu~8P38+Z/_KbKqgE/QP6?*ϱd1G,YY񙷼_WڶSfKp2o}=ϡ( 4M'''⚧4;sRل$IH\=y%i1WB2"-B#wJH,)f6Z߈q=Ͼ{EeglxOӚ&l>?7c5=3̾ àlZȠRekz^'vՖee,Xvw~<,ʬX,]'Eegt—NO[]3$Cq8vkYv];#\abp8}wj`}TѠԞ wͪ=KXYӴ%c4hX?+ rY5>3M=U?Dw _Nq!ۜǰ66K}U;Be$I]V}t]x^TzM%tͱ̛G׃,t:t:7o䖡'o}MN3Q, ʱcI!Tx=y%m1.Q].֖q]K}i1q[m~6~mY-3(YVEJv+u Sa]>}JtMg_S d0ll,ړj@Uߓo6 M9xDm, `:ǏCVHGZM)LyJ/>HQX:6.#2d.EGi%͸)dik.D87=O)%:~jmJvH%8+Z/%_k1%0z<lZB$/R X?TU/b^HȣiFTU`0u@2zjmҼơ+Eˡ鳰>$t:epgP%nwnƔZOKh~Y_hTQ/mmƣ",c:}(y¡٭lۆ(hZTCe69hur|="PLMCWn= %?(5<t]QϙNݺtz +h\n؇teu7ƉidcILANj}/ɞvEFq*=F :4#: `@Rv-Œ\JjQYD æd~ ]];v_BZl6t<FvƔ>q}CVw{&gE륤gE,GQ/6:&)i}Mi&џf`:b4Jepuu֦v{) (h6KTua40 TU<<<,ݏ]Q[.zR0jCH/x<^wwwPa! 0ij۶s?]}~b6^| M(意?<w{&gE륤K~I쳢RV#Gl^z/?uwKmZ|8#EYi!.eڭQgRׯiJ>::Eh?u.}}XR6:Lӄik7 e4d.EGe1PVqzz|ӶmQvN_E]WT"t*l]vb 2۲86RgJqӸvkzHa^f# hX ~e@38q;4E&۶1 BNV B$sH n0 (" * ۶k.,xYy6POS sQoWt}t/4rƚhhN-eqIY+EMحe"~|7 DaXܠZnNݝJwޭ}< q0 ҿO&bkM){.{xx(fxkjLӄ(|`q"ײ,4M@`0x2qMv~/ϰfTU,§Fm{x<c>c</}7!s2l_3Oǎ i˲뺘7I?MS㍺в,.ͷWZLӄmh۬'Jf`ai!nRi沸<^.x[]v.,G X,0bFm,4 4M\^^b>^g–a<8r(Kr!2**1vFReYdvY( \߂p]mMDJiAUQ1@h#;0 /_2Iayv,Kz4>}'ΫUO>c}yT*a&OFQ, >&A2]ERH$t:TU4 \^^].NOO%IBZ  S&4bX>j8;tRsضԦ(ܑ16?iQu6͛7Kĺhu%N4 777:?9yvdӁ,˰m^oIq3eYV5yP=m;aa}RVCkٶ MĆ@8==0eh4`<ϋK_\7F#LS@^ti0$*,j4mmp'qpyy iΓq99>(yvk9vcO3̑ IL\I.UTCbǛ˜Y4jKulێTC(TvYn4kAEQj˵H(JhMt:k<{Z* Lӄa"H.1־u=8T*0 Cdsض(%,KGX5/n$/Y_vIKLϤrTTDf[M2bԑI.w x=dYƳgBeS]5ܒ]`RߓFO$ ${z{t]GئtF$IZ{xz0 QrBYQRQ<ٽϟ?)mKk%lJ"]~Bwf3QRnFu1 Ć$vLӽIX_|lӟ2JY{1Qײ2!{|Ʊ; jϒ0NNqǽ_~*Z$I8vB`0/E+ERƞ,4߮i 4X!8K'ʈa1̾ sֻTӧZn l6EM`TUyC6k+|_( dY^_U=uw!Y|>(4mrrr"ɪߓHCCuS&$I 躎zy) .j`0BӔeYkߠ:P,{m$%K.iHIRT*  ˲]( noow>N+n,j6B/nbZFTKZ9*RgI=-qDRy/RnC~H"mzδCT˲2#$B0ô@~.s(Q j[˗eKyV[3 /I$/Y_vIJ猫Ϥr!vŽ658Rն,[mIO e.ih=V,'{rTCyTo)]}B.ޖm<lR x[M_]Fs4 ngcffv/v9襤Tl6 uL]$Ic6L='|@ vhhef}S@3́Cܦ$A>,wO>Reb2pƲx}f>ZBUե̓Fw IDAT"I %]Y1MSj2ƽ_/g9襤T7({izM'"6,˂ix||8NS$gq=)Oy/KnC|ILY:ZRUUm@EO=9^6-:+]\TEV߉M^=%,NBe7 Ee2a|$iպJþ)E|ZV)<$oʬP |]ׅ 'ǏAIyh;ì sļ@I k~,4 L -t UUEJc4Ƌno1K(]'($óme\Ç29^v@,.aՂ,xMjGio~O S{e?1 9̫Vޔ־H{v2}oEZ 4Mu G6>?6slnO-<=xa22$QT)u5Mh4u@ V(]Vk֪ #z-K˾_Rs&퇤r)bڠF^&.ݮؔb&E-T#1PdEދ۴PV鈱mP<"ȳixXŋO~>*s쒵)Y\y?978t8ĥɍFc-%, iqtW*LR?Xcןe`*,~3S~הu/RBoۈQ=_æ.qjs (ǐqV>;y/Knt:e9RZx||5aclY:L{bS}6z%՟IP,Z Lv"%0:t]7tSQ?VGt7?hڳi`s$s%QkŢve9i<&hP"췰VQж!?v?a/08@X]` ,,VV .4M~9wee }V˽ w0ڑKsg-'CR9"4-v՘ ?9y9bIhSm,;nđYHK׭V jl)}t] dYl6'ֳ ̻׎a<1q}SWLVSICV*CNjl6[;QOʪ=AI"Y4~xa0^'''4 ޽ڔ#)wwwPaI;[E_ C+u+.,#-R砃G2eXn4M)^QȲY@%v>ר"E]siE/Eߡ艤T.`8Om;^oۙUF0 jKG. EQl6quuwm,~v#GE!{rT}_Vk,:|48j jX,䩛i>*˞Nh6bٺa BigRy/]޿iK_^^.-dض-Ϸk:UN7&!xt8ӅI%nnniڒLdK^~w6mYh4h4ޝr-ʿ͛$zq\\\0 x,驐lo]9ms@=8K)>c}+?7|í0 0 DPUU?;;aXX&7( K?)0̡+aPT;ض0 do~~ ˵|9os `aa'E 0, 0e/S:[ a)^fa9bZM+UUaY 1,, 0 飯 *6o ba0 0 sĘz.dYuf&ð<0 0 LY{Ky,s\\\p{2 0Gwy-aaX/~??aɝۿ,0 V뿆Fɀ?}a)i/־'| 40 0 0 0 0 0 0L_?L߾\ϟ6faaaaaa9xaaaaaaaH`aaaaaaa#iZL&PU$j& jѾ$Iwd]׏-d2= sT躎Vaw;& =Bv(Q`ϳyXh4m{w?E,Bz= \<ԞHk$'ZkUUSnϟgI]0{Q N+iKZxkF2sj5UU!˲#MR}Fϧ"Ɏt*劢@|"mp>]CĥͶmh'bb~x$h45@nnnc5 24Mi0 kvuy?~ b`YV.APi9v{lLib^ 9?Ea0 >} ] .FGM麎NYI:\4zQT`YVa{NjOda'"=EQ.9<σ,u}㻟:p 61MY/N'/i9==7 cL$F1 uIgq\<>~ӧ'k)lgҼ)e_Q~t6׃%4qyyWNv\՞YӃa(0Zb6E2_~ Y1pyy) )f6%.XY#mѩ+8tv8x:<b8>gXr/)[&gj.j(_NV1 Zmdm[weSݛ 8˲`RF x>>>BQHa&j=vZq[xU 4!oECMD;xy>u]߶m4͝$ Fb0 _tR{"=:Z/'c>q7QVż|o*I ykyK_ x}>4fg8QT-g3o{><-Lb/Rob6ݻwp]wn=4MmfoTb[UNJһ̶Ƹ@s`J(t:y4/y?4:.z >ߪ}FI~z^4ah+u1bNMҞiuL 3ǂ{ذ7ηEC80_`9h<-SK$A?jN)h4BZݺPH bSky4vih6,8 Ý©,%O az'% l6$:I3NڞqRvAqHuV7Mo!Ea/0 Q^WCA;A<^/4a^o=B'}e-+{X<Ȳ UUVVلip]‘"$_&xxxzCRCNi3]]t4MZA/_Be/}Vce>0 4;KP;kR(gӉ,څy:D}_{Ȳ{C@-Bo8yXbz۴+zNjO$`^Z(0fc8ٴu`+n`0zRU?|L}zݭ_yI$nY^j6Pe]$gĵ烩?e >zl^=iVjZlF]Ztu}M*NEC|+Iժ2I(T*bw8Ĵ,k/['iϴ:I{&KYybR@"!Ea/p `9(0g7m۸뺸Ň\]]a8<^G9?ϟn ?~fk  >*J}`-%89˺2QX,#S$tucvYR9J^CeLStݵs0ņ"R^*zmjŽ hOeB}( !\rtdixߏOz"IjOm8/^,,"T{NԏݴoiF{6&tIslc糚ػe_R{)j:])8=˶Ǹ 56qe@>N^?]$LL#qmmrK"7eMz)+~RlUW?{Cf~R)1jUqLEϔip˲i8өg0OʔCmض-Ot] h3{_ҷw{7M{4ʘI;4jru3o B<Jp&~I*,A{EӴ5S;YYEq/]f:4ϛWu)jq+fa&? uiHHN-XtL%*2$_ItVQz)+gT8b Y 99 6%̞^aϬڅycA:z@7J[0gwѥoZeo޼I~eI퉤* nooQMd.CyXqC/iaS{ IDAT/6RD}N_7RZ8 X9-3em94yۭbCChZ:}˖n+W&$_sfzhy88Cs,C8?0GfQ'-ڱndHץe>n}^TDv;}حNNqH*9~!'OhQW4F#*Ԧeݱbnn+i#-qSt<E^'*]{o :"h~w, iqtT+kNbO-&l}?J3LR:9\{(%_l0$EVI }8U^8C, 4xCk3̑@zS#8Y&nwҥ@׾$ImHFۦ~ Jٔ&QsZ(}rr"RQ "Љ |`3ȼ-]- ?~8y7|SE ߂L}ܤV*P& :Ȋ,n I퉼]u̓DP0L^f(@QH݇y%~I -,!~S@xc%/{^.qȫ&$Պ'9#_b: ڶ1=.Oؤ sgRYRk9S$qe$va戌 آe4m*vA^""N I鄢ƅ M'',֙ zٕv-OҥU܂54Mwb`oXP:ꦅ$<+-<7:uA siz6MSw< ;,EҌOZmE{-̶qv 7icR\,xHz! ^f#}qJ#x,&N4V*Z-_JI3 Fc8$ V <TZuV'JNEQ0r;iU 9ƭVk?t]~X5HeY͉}_<+Ijnnn2'7wf"X"鮶, Zmu]˪]dYiOuBV(mX2QU*:N<%l6d!۷b|J"d~S]C_ObOH 3u]kB/hF z=\]]M^ߊl*l_r(t]<<<D w ^/Ts?d!L(BNйC4<<u][ػe+IK\*J$d:0M i777Bl 'y8i<WK^CQvm{ip˲ 2޽{uE)^f_A!8m,33I~QEɅMEl˗/iOGtݽ[qo泸ߏџN m> S45=%bv-l)4מ7~>Y4:wmKmH{)B{.//aY XjӨVۅy0 cFd;61jhOzVq2=QLo)8"DGj?rmdY^~N;дrwwׯ_uݣX,pvv:ƅ2P} . ~ X6+XS!߳ o߾ݫSviw5I4vHZ{qx"7yj_R*j˲pww$qO[m9/q.6hqR?xj s a_׸JI/>l6qzz M0̈́ϸikZPU$a>E^jbp=@}Ns$IB9*E[%Z؜/~UV~c ŵˊߏџNjӜ2C% qp~~z.$Ip] NڟY4:gXt:E^ǡ8ˎ=0Q O7pk0`Y&zΓ"Lt:I0 0 .ð=8vvv,*y^ T, 0 Ôo~~ ˵|9os `92\ׅeYk08aDN0 0 ð˰=0I™aacS@3nsOlG$zJ0 0 .ð=#&^fyga`9B^՜}P}5aa]y?ɇNT/jE3 0 `aaaaa]!2\ׅm۸Faa/3 0 -|;aa8gϞqC0/^p#0 0 Ä3naaaaaaaaaaaaaa^faaaaaa9xaj0Ljw:7 L&WfY& Oj& :NK4Lҽ& jZag|/o?c{|'?aeF$nt] ޿/V sda sܠZnN]bYt](11N1~oZSq|>h4m۹MP ^yMViK9 8* h.>~^]VۨlzA0Mmc>~Ra9~{|/_o!rqqNgv~_~WE;&e2$ f$ u 0[mTn9|fM`0PUU@e( ÀaSnpy6AeTUTU躎n˻v:V%'W(:]t 2<m( 4MCyJ˲"=gKB A( ʙ Y-":/,dg>}~WWW,+tS 0Lv`|9%5*phQv _~ˢϷo_\z5߾{y}lWVm)BnW3~Oy,r0e( LE(5s1<9Nxat,-8ڶ^ȢK˲PVy.//IPip'NgI aC9xV WWWpgmqRzKXhuݭY/.Zb6: `/}<16.?ENNN`)뺑dv<l4M \ (Ow?O~!{1?}]e|gx'n7l\9O_L~ۑzw;%](-`W灇~P6>C<} o/>wEN?rCOQrG Gw^3q;v].pG}?.`t:O8zXMw~pyx[~WI~'iּ~,q2<4:χy~8pA>}W?q4Ps?Σm8؊G}{?i]b1[[jyv{t6~znQj4 >,L&iZ_:q1~/~ﳆO\/X]]Qi]σ;;;~Sl&bR3.S|| ~_ov|/{&۷{wP(7cg d;qs ?!dFvێ0H,hzNc|p_87ZWo=~5c/ysϹ>~5dqu+;\ C後Gs~x㇏{yT+2>c-8s] CkY{ts?=XI5EI۞O$ 4M$Ɂ>az)^'X0QZ]v9u MJ_?vy,-`C%hDBZ0L&aӪuq}7L\gn/9irx\&{UUE4E4eYX[[ bk6h&N8=6`Y" Ð>JZv-=6Agz=n h0LtFommhlf qeAGI}x$_'q#*Hm4Wp7 R H&}'nݟ_b+d2K R)\vMR$R4M/.h53X,"ϻI"pn?>0`6\"oEgeYT*]پw.t" ԾX7NwVW;nѐ\Q?_,,.G9]/UUE,z[~nWGţ>?+F'g}&|~yOwޑ#nW"v~<v飯*TUE* 0L;a}P˭$Fxu!:>{yOι֕J[#> "rt\#:3ʿ珱E,{JR ‘L"-Ãȑ^c~Gp/Z#îsεF G=~?o`đl!]j4 S4ߚ|X=iL&:χ}~q,bz؞8=AD Z?tsၟ? ȱ\?Jm~gj}7pqA:?pj~Ie30m2D>a D"qsa1~>v~h۶]~l"ϣT*u2""ˠ~ʯlbp W8] Yl6+GWU94ͮQ3z=Qa_@4K0h4~[nacc烎ӴO6oFW麎x<kgyF&cV׾5pM-^>l킨׃'n~)qjdF;gǏˤW`> }k\rϻ+4BN{#A&M. 9dK'KSGrHН4,(}yU o/F}~iƾ9s*c?6W\NjS k뾧Zf}ky0qga-s "qWߵIֹq>ivѬDg\TBT(F0Miu_NvqaoJo'~ /1 g$^1m=@߰&ۋw{7EQd}W(ۧS^ձ[4ܸqs[a%f9ҿ]XD"aEZERkR:Gv&{iOܽٞ9-=/ 5LA`u $ ~oX$7bmbq~nNn:o4TUū{ 3JdSׯꢪګz]Oϱ:2lbeed˰,K&lF.{o}>S׿Ѵi+>Bk$oXF]{'noZڑ߸}> ^ ~=-A)s8#ۏy)|//⣶m.W~m$w懋>Ϗ~p҈A/8?ôϼߞґkӦvQ=Q߷8}O\> s9Ol}/&At 3W,|Nr<9-=_3|r9ހ`!AunMӰ^xa:|I_I~XL"o{2xZ2j~7-hظUMxnOReBsQ9z5ZKT {)j}֏ G21P9Xh/KI病ݎ|-_΄y@ݞ Ĩ Q9ذ~y٠quk׺fuS:m>-I'iHCg&"Obl)ln!bk r99=XѶm׍X^=uiZ7 >w ] F:7 }HDi ğT6'vbQ[?9;O4AzB/_ivGousw}ړ^۴ֹi˰ ߴa=F lGmuN&:|W߃^oSLb/_&ޚ9]I׮=4^m^Nw~^m:-/?֞mCׁm yJnGa1A_>߸:q?^*ʏ9u}ߧ%O4oii˗/f "Ψnh#Liiv;tx|wF4j`ύA0Q_>nK?-uȽA?NcO{ ^OJ?dbub]7"#hPrX,RZLהa{du|wvvznH$\E"9] 8JU*y5*FC'NZ$eoڧ=qDѮc7D+=iͨi줸{ͮ$(b4MCqV?ׯ㗿%]]Ioۮ/~ ?A“Kh~iuuU,qՑv7.8- ?<pt(uAJ_4O{cF jtߕh9\:#:r%9hƀj=2:p髤I땞D`yBUU!!Ϣq/}U9l聾/_;ggr{qD:?9= n0h#KEUdQXyl?qo\E;7A{ߋ(HӲo$)^|NraF~Y#\hiϩ%/]IYMӰuض--b8d2]4aQ\EJ@[^3 ښT*ɤfq^vs=ReXM1ZV!ޟh4˫].6(n߾-G< |^d2)d\h4dfeYhUU=o<.]0pͮzkz)˲`&lۖ)J=}M`Y=zqDiT*|V*F{'ϻ|A_ֿ/Zߟ|IpC.F_<̿5sv;NO9ywjx<0Fu~>, qrpeLEQdW^G4i0M3:->-A3z=~Y#sࡇb4ΘD"T*|>?D,͆l6 ˲pʕEי~wY؀x=(_y!X"N+pt`mt_\q'FnwwwiVVV>5,'$? >^=`"3P( #HX,l0]aYLDt(]F@)֚=+ީ#ڄ~L֏/juPZ|$gW}|GKGߟg했=1C@Dte2OMAQMDip\#?V?=ihMtC8~Y{["b%""""0W95Zr!D"iDQ\v!Z8֮h8zh%ڨM6cNvKDDDDDDDDD0 hL&>":q+J X,шfcx!hԾ{xw_z볹8 ь`hF0LDDDDDDDDDDDDD4#&@b1#͞D"}ܸqA $sX,I@Q!ݚ ܺuK4Yr ^oމ(, RRAUU%de!qBD"H&0MqضjBf91e( RL˗YI0.css`6lۖf<ËE۷a6 IDDDDDD3 `" i4 ƌsmmM9²,s 4 j `zo~:666 jTUa0 eaeeeb!OTpvb\.7s xNC9lDDDDDD6&h,@0*J(Jt]6Vbdmx饗F~W^jcaMӐJ b L$9O-uDDD4E#\z.6M@H'ˁG͐H$x<˲dm((EA<24MGdD"ΘfkkcwV::ƍ0 >,t]G"Z#~S& qh&[P[*S4DQhjg~xn!qsc2(ޖ @Q~l;;;wV\v⽖e!0 j5T*ju}A'mrKDDDDDDchD"+ΡD"!GjKR0 mʕ+L$,BR*Jrr_bTI4F&JڵkxDO4,//wg,C48X[[s;yh'*:'A[6mmm!buuUZd2 qzk]]#/f|>RԵM6E4E,s0qn|f:7n@UUlmmlZ4ޫ: À8$[/BUU[X+q~>y_0H9²,ضL&#/FqdQ#'%_#G<ѷia z?1L{]""""""&dR^BP+aSUU9]gLtTF_gq@X=zDB󮎹j*"FTծ$z}#\AYB6ƍR+Wmlnn۸}6Q,21SAzrsmHB1*n2Hz}wd)U p%=k㨟^_tlk` b;Q;˯P(t$'.uX\;_#zMDDDDDD0 w "ssČ6 A%TjS 2fP^#ĔvH(c˫SE@kI: [v4v'CAZ&oD${(΃wNKyQ'R5m8?о@'L*IaBXqDh!xN ??gXh84єSE:ך`#4M-:EG~z>D轻wzW8FE$ ]TUT*ܹsgk+~YB6m}uuU&Oj^SӋif3zXLc:?`|=a΃i"Cu׹c}o4rP˲d4M9[=qY/~Au.f]8sy_7o\ktu{ߠZh&r?S?iq稀^Sr~^l6d2eX%m#~9h=YNӴSZCղ,8J$A.&w~σbMLqLfӕX rq|aEX,5%$No;G< o9z.usq{lC%"""""mLM0EQz'u$yu zuZMH/iڝցh4Ѧi677 /Lzaֳ92 2@ۈWm8S9zXu]k׮uuװrT hTGŔ^S~NI/尳3ڭ$#.ӲYDDDDDD&rfSv6ZK̋ccğE¥Skz%׈A֠( |w J5b #1A3H1|~΃ݕJoObqo6bT*S`9ue uzZ2-zMDDDDDD1L42 zS'Da) :N~굶lX,[naww7NQo=8EWʔWךēN|~TQÞGy𴑂A2vy1s<m+Y>zפϰFGс_t[q[-­[pƍIQ D3`gg HN@ IDAT"NwuXD"zlʎt:1MSggǵ]@R۵+N=U`^kP<-.J\e!.H u4M١yx\N7::V<gDֲS;(E~&눞IqD"iS.ew6~tPNifO{iD(Hr qqZ¶m!׭ms̯qϰ Z"ƛ]IYEQŰwnt[q ރ׫PUa%h2p `h4dfa6ǁiPUճ5ҥK0 7oDV4\۰, i¶mR|>u#LN& d:̽=Xh4m+=l!Ja}}]Ʊ3."KX1 kQo=kW*/0 јwA.a"y&lۆ(PU|Ts^?qF}Qtj5<6Mf%ڭ8xW'݊rcb|헟`ZERA4fڵkH&4 Hg;$.~myJL呏&\¬ag}4MeY<^g&4M*~a_oeZ緽OK&""""""&j+++H&0M@QضB Gwk6X[[C"eY0 V1h4T*%; mF&EB@t8zkkkX]]϶mlb@uh&RTnܸaO?̫L4L"n޼R$DR?۾s=ǀD3MS(X߽gbt?3& j љ0ʹUeW"Mu$ ul!0GU?[Ff&hq$Ir=b:\uIvKfDbmU""""""""Q`fZPi4 aqj5EdzkOb UUa6J""""""""9C1DDDDDDDDDDDDDD##|b{>s_=&fDDDDDDDDDDDDDD3 `"""""""""""""0ь`hF0LDDDDDDDDDDDDD4#&"""""""""""""L&fDDDDDDDDDDDDDD3 `"""""""""""""0ь`hF0LDDDDDDDDDDDDD4#&"""""""""""""L&fDDDDDDDDDDDDDD3 `"""""""""""""0ь`hF0LDDDDDDDDDDDDD4#&"""""""""""""L&fDDDDDDDDDDDDDD3 `"""""""""""""0ь`hF0LgR,C:>1P?]Y1X_h-24H$d2 4iǁmh4((JseիPUJG/DDDDDDDDDDD4SXl6zMUU 0`Y" DK* X_h&1L)W^$5Mi Q&ߖHqF!]u$ ($Lo#|++^d2PE( n߾-~5V^@pm8{9$ qh۶յhGQ^[ZZr=,.fjbzݵM6eY]ibssS[>tzl]ǻc.(h6'nO<ƥW*!}mxW]ݟ S_DX^^v}o\z}fzJվh1L't]I5MJ% ,+A,\T@kt:x<._4 lm D*r%si8\j*-4M9::L"VWWjZD"T*ub=f]בdNܾO?qiZWF>߰qZ7Xkyykkk'&K ڿi, r?&ɷdFXjyo\Ʊa2H}i4d2cFONUU8ɉ a|+ r "jL|9Z\|rYV6f)ٶsFWڶm`mm5YLD\S?W* + ceeE~βa87L\/@+|ey6Q,qʕFr9t%mFX G1sࡇb4h,666F׮]BDDDDDDDDDDDD3G.<`yŮ|>#it]_q\h0 4M UU,_/h6 OLSt]G2t8vvv""""""""""""!0Lc8:h4""""""""""""!0L+ ( Q"""""""""""""0ь`hF0LDaX,ʾqƍ(y\7n>Ld##8'9mئ>q ܺuKg:}O%^^QP٠( LӄifzJrf@R3MӠ*PMR0M/_f@X~Dg~j;{vv躎Mm۰m[p;ӓSh0L4t]Ɔ8m@4X˲p]J%kkkleoq`6U4qv~l8'9mئ88X,"g %^^ݎ(HL̀l6 UUQ*]h#H0HSboo{{{ D"jzM3oQ&rbgq度yd2 q|f{ """"I0є0, X CUUضRBFvZtx;;;jyTU$ qrϑHe$y{KD8wVᥗ^:q7n0 ,L&iک 'ʠLlq"LޫiZUWmxeɎ8۶Q.Q,Ol/ia8 q jk@܇_SL{R}H$HRT*φԎ\9L= =Q~۶Q,Q(p-@ g$͛7^ zyɏa( 8eumT}z=} o=D3Bu(2p}=۶a64MC2eYXYYq}(,1 (Cﯓ2 m6j4MC4ix<.;{UUE4!aj5g06#Jx˲L$H&26a L4ML_ irjtb]T*EQzv)OCUUR)h&4Al5:RY굈a0 h4Y׃^7|?z@DDDDD4 LM91Stlmm*,˂md2Z&T xt9RTh3l7:PU+++Ϗb]l6Q*EfFb1Iz1MkiRkDv$64MrL&Q(d9D"Ȕt]6l{HDvEyWH$rP  YO\){,amW\銍H%r"j*Ҧiv]t]apgl0sZڑ4\7gaa/!qg/8ͦ߸q}:M:RYTʳ^$eYT*aM?o=H&PUJs]Bpbrs:D= ^AժglbjjUQ}z=S#:Z ׃^7~DDDDDD `P(d4cbZT*۷ocuuk:;Qu^At9fT*=ĝ;w|թ;ͼF8)nWV8TUMQۓۃJaYzظ b]$.]Xt~_PxN~ tRGYXf;ypүֳڃ{]M8 h,S9Yw6 #:D#"""""DhFJ%J%(h4 4a\kTĥK:nܸ+ }QݠI24/6m:c wTU S{=vql: bX,"H0 ZRΝ;#a{Px6 eY]\l>u{?0/v44\7ga?D[vԵz'z=^kҶ ׃}ߏh1L4c͢34N##LP(N꩝`l6QVaYk^?}kuuU&ES{G4OدF5ˠIԕaD=uu\&7M LbyyesmrfA%~Y,abXTÌ r4q9z6(^e7lݛюZ5ZqR,Ō0A^z M"&f\>[.;((ǝ_kוe*bu]v]v͵v3]7N-}g_q F\\_ass/Bϑ\rT*%Cئ}f,(^賚:+:,rR}'::GDDDDD40ьk6Sڊ~y-JiϕJųt JLZ*:,׺ub^ YA:IŽKK^GP˗Ԓ^OCO[<,hɓavypڮg9q_7lV= 2h@*rw˲p2Mz祰l6^:vי)(bPgaq| BUU!.'"""""kMӰuض-;h qdڂiw IDAT, ۞۞ZqT*'~ ZR bssSK4k׮!LB4D"EJ%0 r;wFR|^g2#:2LZV*R)qW9j5 E$ 7o¶m(UUJNgXD<nb1Q[FLlxx 2Hy0J<J%`rxJ%ف].G>ʪ9Mq9vgA_-=Xh4mj5?QF)iף>/c|.]ay󦫞z1]~DDDDDDfMF7|1{xבd{n_.CQhֵ~3/MwvvN ZOS_y_@4h|jm\xމ].gzL&zk8wXrNR|Dmowk]e /8/*.^x7@izAӶm??)Ԏ\縯~= Z~'/^DDP@P _ׁA}0u {ə{D=ה_ׁ_7k zw?i~F+s>ͮ9C1DDg.4MJ`Suup=Bg~_۶qeVb&"""""b߽g>T`h4yIgwZ0aʪ m۲,q/;uK?TT^|nnn{jGY;{);@b@P m+_:Eɗ "adB: \NTNG~n 8Z*jL> lmRf Pq*Jj4 @f3gsX6 ZR("ǟ?loyvI9l,ӹM~&NsmVefgq%_Ҩ/IQ:N|l{j\iy(G?o5Wm|B읚̣ό⯹Vm̢^ox:g Q]XVՖY՚[ *J\}~͂6FCOOO"(Pjـ愘8q 0nH@m8Ɠ@x.L&z8[,?sg_UvfhlNN3p.,KJg=z=ߗ;-y f_3xEziuScb׽ߤ{8L>=:`u/&ۯ2-`0n;7.{iQ}\6L8*o5&2"E&ZllNQTJ}}j~m{͞;mźߧuu! CY5W_ӼEѫ{mU\Wi|.tfɺ^kH>"ltz8\~^OZMAP@߾}{8I呟YŃ߽ɱqc,~lE#O'9?9tx/nef}Yl+<&f...tqqp3DV`ϼͶ×R]^w9}[\"u`=$/'0m~Zb*?glo=WwwydދGME_=fQu]=>>qu]MSynE/>~wތFcמsHK"OsgcyK">C0fC1&8T*,3AI2X<Js\~傹 h$7K%i:]9}{>Q_OñQ{EiGXDT?$IFy6vu||ObcR~Ϭt:'7(C?#^8rCQCO`0y,+~r]Wa򂹢etyy,d}gݿ$,Z%굗|ͯt+`_ &ݿH?lj+*Z4AǂЪ>ibot[],ҙ===u(v.,ki}liSbL+?7ٶB!֗`]{P|{y!~I~?&/EcU%wx: I{/JV:7iGIE?sۤFߓD(7"^:yR Y%۶1*^/^m[wwwՕWݩ^m[϶Z-ZTKf]~Ik]]]VFc~t'oRC\FE/U=rOp@y` S:n.0 e۶,R_{]ч亮|h3&xm^ tqqz^/=g7t}}0 }1,ϟUe۶ hnnnd۶|]7e ~LPN't>>>}U*OottqqT{]3x_v-h(>V⫓|0 U*dY:5sO\C|ons-tK)x̶m5 ]\\C8+̣M&]^^j)A&v޾TgI{QȴҹI;Jz~(!~p%MY5Kob%>,jbYxn>вG?t(.//u}}'GnFE}>w:F!  09etcr^ Lyd2ɉ<ϓm P?ve:\Z-~,HEFo( `9 0i @mT*i8j<Rȶmy6Y3߻ӓժǑmqÝ\n5 T:b04:==Ydd 30eaY^-e4_FrŜá LW]ާөNNNl68JnnnEћM=h66'_I !qu){xxm:99HQQo/֟WI_>-O ;gga Md(=O K,Ninaqj5IZ(6$B ,NAzscYVJ鞠'd`މn+d۶\UEFzz||$OO+I};_?寒/gv;TzLû^sGwwwXc@Q `kP IDAT?shi @= l*xϥZ d۶(xtE;TTd}Uժ...ENNNR <ib@Xaj4ɶmU*ٶ0m۪}_'''KET]|F,KVK;9$4٣* CEQ$۶Y HLZ/ƦW$A'˲TTTTIZFq*r;Yc۶&/f^9_iyLZx}M4 Jvdr]WJE{QV.˦G~n#Nq]]]--ꙺ}tt%9o<KgVjs{JڶV5?{"Ļ1ش}ܑ~n{~ߴMezm<Ǹ-IR_e7-qqOXP(>}eY:99VK|Won @fs)l4j55ԏ)i:ժ\]J3=`Va.$W$TNG~Z*ځMјLT۶ϙjWݎ믹slS_zQ$mY+qz=u:>VW/֓UL^`̔KwjY_6ZT"]|t:UVEs 23'Gtݥ+ҘHKNIzp)ǩ?1ZU]ylٻq-N&zd kGQt0mv]/6!>˲4 ԧuZտ Cu]Izq!z_~iyyyˍ8)ﻼT.lM/Zm.\?~mRys?Lllw`cOqK%wd8xp|d1,'/fbwvW hJUuVuM{Ț(-.\L_Lr]wm嗟y*J: d2ק9{7Ift6O֝f'^gm^~2`@{qkDǷ㎤3&m/Y׻ȗ}wjޔw޲[-qq6 P,!(ޮ|D|k&]wGFZ{lNIzjr]W NY^.L{)i:dvv-q+gm>~U{Y^Vlj?{}]}EkY ^m0,[$cbKw:px4ccu]u]=q]2KOoS{W ik:W$W*m4&e\r/nQG:'q̤svx4ů>pFIkU8qnVt˯(ue~9~ [v0wh8jZj4K|KClgf9ߍ jj%Mjx\/=^leiдIR,KmtoIysoTRTRy&A\fly7/Y<+"U*24Z& 6孿u~lY+JظL&sIURfy^"_z^/-Jܚ#\CܿMv;+}K#_6gE5( wݿLS]^^NA,<ybAӓժǑmۊHHpT'''j4:::Fd2Y5M9RxEQ6JNsyd09XnۊH˶8YȤ{z||z~~Z d۶Jáݮ*lۖyL:L&; C]^^J^.oR_ny:99Q^y*J*J Pn7v0uF짘V=320-Z;qM}yeiIYNөnnn6>6ӗU CwPGQ0 7:"_ysrFl 8zt\na_v۶~2x〛 pQyqk㎴\fS좘$W6mlZϊ2Nk $}wѿc߫^jxn:-q{}'IWx_z||L$P.x+ 8xO˿UOK}7{2cnK8/ e,28TTtyyp^!_a`@fbK"ABJw}Gn$?/'n0@ Vz~~V*1u]EQ'u:<1຿_̞`]I^Ͻf۶^{)=yFɓj*qdY0TWM`M2_($V:79}euI|?g=Ic.Yv~n[KIˡT*.^H0DN!i}ٴɫ14'fCшㄴ5|zllVո8X(Ħ<ʶlvi`{o:TjRZ]j4sf׶m-}~_v;Ui+oz;#kZ|%dj*uΖjd04w\ޑai~&-Y>}eY:99KSZ]4iOk0,3r07;Po4swxy4wh2G2 [T7_NOO0e\n l6SشܦI̗<=I~Mϵ}{{+˲tss>Imx,ÇW;2wMztá+J?)qg'ChZK&Rr0 [vբw3IG{kiܓeOl/jUJEQMGQ3\:99YyMϥax)I9J8X'FiKIKQ9=Y_^Ħbgә0\~>zF|U;z\\~0q[!y,ηI ۷os Efbjq;V^]PIu{b*_bÇ Bم{&iy)?(`Y`he]4uuݥˣֵpŠ̮s M8abeyyoZ6_6myK^:m}OxO5/<%r/R6R9UT8q|eYk/N@}X}I?"rؤH6K$qOǗGI~nS~yf(eY+ާr0ǰj亮#M)?˲^g8u2/EF~&-mKؗTV]FJyDԪG)3~w(WN/{:͢z||8vNWrؤĺϥY_9qN〼uwPk'e}|IYQC?(<ʡK׮O{b,:2(Dӓ$Zf/Ju?h^EgI/)eY+6v*f%G=AjP\EV[T*'4Y> IDAT3_(43t/|41vxr/jߗ_ܦ_v]˻V^L&sw7;m?Wrx0Ⱥ<5꼒8'˺8 |}:=Գ]?'G٤' =ϛ Kf|`ZdL&>fs.l6;٧^QR, '3FM>WTVy^<>ճ$DYm6s߹ߛrT*sRӹغ:f]|WEq3qkY4.IRjw/Y{E:藲<mNA yq[6TeuQQYTŅ,˒mvG Z;J[sE(M4mV}V6e%J,d9#_L\r3ez88@^}0TEm[eϪm;}~|~UDjZ @A,%|\C|onצyٶF8fr|x%)mt:}A˗/FKNټʡBz]QœaY3@zzz@^OḀ׼777m[neY~7|uYϬGIizgiϼNGKu(ϛ:th4^ZsE)N#dR?8Vɲ,}EaT*ɲJ#i/Y<9YrG<>>}U*͵S[\%gig\yƟ1I=+J|ic;??WVSm[RIPnWXJEmTD'''j4Pǎ C^NuI0Vi|x3uƲ~I͍~ga&l:j4Nswv5AFQ0 >*i<8::Fd2Y;0k6rGRIX777hptѿdu^s,yNOO󦹈C8$,l_!~"yMY^q2svvpHEqk4>p\n{kIO?D``8 ]u]EQ'u:&)]jUH'''>\.+VcrORϊ_y޴KIM,Ϭ%cgݮ~*˲?vLj55uyyZ,&/_s0qǏ_f<8hĭ///9~H rgUe{ġmi,2!yjlnC.=SՒeYKmhT*-Ml[Գ"Yǂ_~)zUil[϶7EGdisFCmiHs$Yoqt&)r;Yh۶S0Dzm[Z?|f⬬q+ {_}(ꗀ}0p`ҕ]^ϟ+@ݶm-]Yxzz*.//sTRPj6 ަsvs'YIj0OSu:qZ-U*Uܯ6z]NGnwi@ZՖtFC* CſiAk0,^Z]9֣(Ǘ4?O|ݻ5I=~PmuRḀs=4=iI!~~v<;$S[VwYԳ"YIZ~I4uR|٦_o/yʢ̺_VT*qk֘dfҸﯜ6'IOOOOS~_v;.sWZ|ׇ^o,q+ EZ/[||d2Qד|U\TB LnEcfҲ8tnuݥknn4?u/IUy6 ^4g)'̣$-=*h8߳jkwgP.^3}>YYV1_`s,8x6X0>l] fi m To߾-\UPQɲwE+7 >|[}KE'6g_WZ{=̦mvrxk?_I՟gE쯳Ki,meii˾=KRTЪ?3ͦl`0X9̞h\oɗNJhi\pwwl^,kc'sJBBBrh6#UW_o+kLm[+c>tz\>sɋMx 8Jҫet{Li,KmfjIRSVzxxp8`0зov>yos|IĦ,wiLiڤ?[Wϊ_g!i%Ҋ_v//H.ogICE՛y3MZmѝiy,Ti>h<Rq8>08X->geO|ͱ ][e|fYtfMNOO فڮU:_˓ف)˗>ct]uɉ~<)vw*$)m/I~g_o_m~IR~&-/Mmrضm[a* CU*Z-<79џmRϊ_gwGcK#~u|IH/EwK{-]hHѝҹm\4-` qyq-JgeO0_`5`@~(J:r' |y6ȳCHk٫tMDv[v;, @mZ?~\{m:m{:I\{6LZliaLTT*j>nLJMM)Fڱ-pձcT+aMcic%!FaID ydU©Wn?׀!&4cu_SQ#U~iW%˹E˥$~u]TnWƾULi 5 ///ua4MF#ZUesE/_>z!;<B"E<<\":/<ϋTNy<.`Eҽzo+rhKI6ui D'sC~])??%V0op]7WPv$9z?w.BU_ޯhT,\K]+;t]z ?; Nl63Mʭ::Ea}?D ƥ_@ !$t:dYC~NQ%^Ȭ٬7cT=VTѩڊ񳪪FI2m{DUyu{J>ByyyL&_F%^x]D;V__V$SFWRufKq)-g\pqn^cXMbKL0b NY> Ài}R>8kzZu8qy+/_T,Rr*K\"pB6pxxx$RF}NQ89sй.bYUգ#M\+E:CIJ$ly<ز4zgv{Miʿ#l#8h4[r0MSv0*BY/<'˥<=]d{Zvz&?S!8v! @^G'˲Ω^x]D;V__V$Sk۶*4M1uGqI|˂eYmrJ #aZU:hG9VL۶ϫ B!h=e8׼ /__puuUUa\(".rlx0!lM`Y|ߗS8K@UU}ax~~bXm4M뺸d!{*gyjEY<"*:]5 }~Wt: m;7^Vt:vmmo=o\G^x]D;E__rIbgדDSٶqL+ ,B^`0XNA9<xtC`0eYrUybh,m|y]~{8qny+/_{Aأa9&&:)t]ijl4M(EQ>FQ{UuQtZ:)~YN_^^򂧧q{{ qHGeϛsMUWخEQbr9LL:+B.\NuhF!?B'3yBB!]QױX,Z{b^^^rrNp]mc4Hn!̻>y_Z{WWWh67Q/7B;!qr&B>bt:M|؊6ab>ò,\\\pB%Ik?hzhxg%¸D~I^0 d|<<</?L&9AcW Үdelk0v?ԃibfVUa@ut: UUef̉;?4MےiJ6qB-t:ݙOs;M,mp]|TuYڲ"M 98L)=Fas(t]yl6J.EQ8;;^?hZkIYJHČZtEg´L{]ϙc0W ɿ# MbN+,| N0\TUAk,GHc/y=jBPUm{΢uؕEƗ0 yޖ.:A?ߛ JkbXiB4M3VYڇ"/޻.TUyzҞ:N\in0]*<:>JFnMZS[ yى"&9#+yP NVPUuyi+3WWW t4n2rViuu:dyui&\Ν<=2!: :Gs>ќ-n(ZY;(r ۹Q}GGl6})뎲YxV8_D!P#O>AQh>:2!bp Ls)T =kZnrɂ( e?Q~__⊺>}ﮐ(o$>eYڇcVX.?fObwۂ])h|>?xוUA~˾YoGH?bۙ**|BYex|Z&nN 33ϭ&8v廧;é5\L)=0 csf3|ˮUK{HAlib#́Ls)T ?].Y@z(m׻%ܶmEQB=H6;>z8ZYe'4Vej_Юo߾ɎN<++$tDsLCtw"V͹ q0ϱ\.(4O/Ξv廧;CQ &0 jl6"}^(euJ^wȵPnrLs)lfK6]Ib/BEwݪ*aތºݮ>Jl}86Y.?E>L&0 FCqoUڕ|^MZJ{]YIUj sw ߷ ȼBVb2=vi_LuYy-(n۷o@B !`ZAu9P4<<<_ͽd׬Ĵ%A$0viS=g*B\2؋(KS]ewwu 50x`>Np]z C%ttlWh'N^uj5B9iʺJlj6|ߛ[;MWɗTw&0Hʱ\.1pyy)ϒI!"d֤iKyV\W,#y% OqߪƉ("X]b?} a~}s"ڇ.=fOanb6UzTJ:>}lHmǓ NH:9Fnnnpww'?m(;coȣJA>f}O?mwyyIJ`BHuGkj}  UU%a:zgg f  ;\C؞ibey]6=nP,彙I=ϓ[~,3K9.`aś ʶmuZ]9FWD,GtuirS &躾e_9~H bFUA.YN?\>\bs*4N"I^^T_뎪)O}DHY0!8F)N^8k8C"9WWW$apxxxJ"EA}nLs)3+b‪h4G,rzl&(% 8LKzzo姇LX>*<]kT|\.⳪k TE.iN?b|\4ϵ"uh=;·iQǩ*n}D1 `BH%p(g^fv&>aja6!(rVu@6 c8foђ4t:t:f3("eX,0jrg~"L~4!xgQ. BP.)!B{\!/!B!B!B!/omy;g?/!B!B!B!&B!B!B!3B!B!B!r&pBJ( xzzLӤ0'h n(c&7n:=xCzx{{g)?YQX%׳$yKFAe|K_؎RRu]K $Enk1)VBmd^whgNT;팜+I䛛sۅeYl؎o]{!Bygc0’!$/^^^BAR ꅴB94 _|pd$GC!B!RBĖAr!B!B&T%aX?b3|: aĞaY.ږeh@u yFΙqmg%֌ū+4͵4MgΎJz?riq ~w 4v ۶m;۶i rD׋}޴vM{9k'}k]?i6...\|d293<C4ϸ@لiuZ˲ΣGד6ш{`YZ} 777h4Eoa\4^͓Ӑ^InLSc9md?&EQ0 dX,*.Q={}Ml6aYVlg3H|G4 eAwύߋ#a@ٔz7 CsKVTU=%MPסiV"9/sj5 *4 GWEQ"g @^Gy8 @لi;Iڶm!*::,Z;W,]{l=ض uťdK=d-Edz0 diTU}Wi*O4vL]ׅ(kY/ E_4,sz Xu&=|:QOaQE{k6L̵LSsTv&&E6V0 iob> }?gnqird3hpx&OJz%M^~1NَRz rpRz\ו39e8\~b&t: mFJ zNJ{E|?hli6zvb Ok/ygVV77s}N1PyzS\GN^3N.bƲ,fMf~_luZN;M 6OP(i4yr{z%M^~1NَRz r `BHQEl[FyO&"qz`mh1|ߖe3X.oS> V+L&۳Ku_QE?K|SuiC_[@o>N}ϛaJYn^?j8jáq䥇͢:n˹ljSgl6PUl+ (C.R8$,sa(;~ EQ:& 8ļ<岯-:,:Γ &fE; 窪;`-V}777 ZV:˞WEUKE5/ZpRjĹAĮ`NO̾],;tљ"O>ҙ[> q6%Zlx}N_)w]gDq[2 c˛{{| vg)ڱcaW\*ТDdyNAJ%N|%I<~_]vQB\ h[r|8O%aщ$mGm"vD['ǝ\.sI<*̗ R-4!ԈflּLb#qdq`19f}v}Α(r<8TisDX8^)*/J{K#_JcםNN r `BHEڮ3Ҟy:1l9\.1pyy)s{Sߏk/e|N_׉- S][ҕ!Gb?wnk{\giPUAS?b,qWlW&\C0L_~-U`m8U5NU.>ta6^òwhǵۢYtHJvVt<}FWD2 2y\^#//n&g)6=M䡇M>|߇a[+N'>3VL*U%NhӲ,ض ֆaʟ]ۉX}<<^)Ίؾo>-TUigx{S}./?'o"&Zuez%k^^Dx~K7R~x0!} Mb!,vښL&pCQ~vXGh˲0 ,^D4 6dAd۶q{{f)gmN&-KNZ{s/sz= X4>4M{%~~ alO%n;$l6뺲] /so|lzy/!ϻ;4MhZs;$zֵNg~Yp K^z,;lS Nnmö-є'[Ngmrp8DDŗ/_Nyk')|Uh۱G{<==>{):?ϱ}ϊX.,kٜ|h ? 00֯߾}C˥^#//nJ>)M/w%!Z\ bp8j9`"ku`\AEt:Eр4 A`X`>dL&@~0 Alvp,E"PqG|jYHc/UyNv&isZIyu劤0 Ǒˉg<|||>m0 h4rD^i0Ms&{7E(UUu̪SD.yaA5;U`ݱjl6a&E(}hkMW8ql}n?gۅL&2{||irƮA"0l6elNG JS*+Z-vggKy.0A׉}ض UUX,󼳩͓n8}HFz%/d;!,~4!4M9!Gr`<C4ZlG!B!W!|t׿1矩6&B!B!B!3B!B!B!r&pB!B!B!BB!B!B!Bș~ B!B!B!#?o}?LB!B!B!BB!B!B!Bș`B!B!B!B98L!GBQR>Ft􄷷7Icx1ޠY69Fooovz.qťSKUlǎi뫬 6!?ҏʘOtݭ ooo,+{_!ֻW؎QB96&#$>v7ͰX,X,F;#?eYvxzzGnۓ!l]?u]:0veZ˲˥m۲&Gt@7bB%'Q_BE4ض]ΓseAM;#- XVg?ScWiM`Y& z|P|߇j;Dqqveu|TU0*;*~K(OB{!`B!B///xyy Ȼ]0 mۘG(Z+t[}6׊RA݆m۸|>8mɕ5^oiޯJy},˂ir+J!C%/\XF]la4AZ,^!eY3 @N{}!o/j"vF#BUUOVu]y.;4-_}n7b/_vd. Yڣ4zPEiX,?X, qyy3>Jo\.1Nt?ЍFn( 9zFFQ|"?*//"ȊE,b!nVNݫhG6#q.fqO\,y? 4MYC~EiW KKyVjW~SB !4Mt]Y8 i\ׅ([ (TUa0 z}{۶.|߇0 eAuZ{Fy\ UUqz.i4m(]kAzzɨ,8/\Yg!OMl6aYV<ʥh{ɪ$m˳r Ð/Ui'l9?]ׅi{MH1irhX.4 abD2GcG^p,o":[6c+t]_)}c,Lу( Hĉn{di%Fc8WZF3G'DcX/"0 t,ڻCGݑo -BVa2or]|KOSEU+?ccM*>' ,˂eY; } JZCAȥl4M*{U)/R7gUޯ\*W~SB !VAd5qYua|Tea6L,\ݝ(5Muѳu]`0{WMgVV,6D&]fyDV߇ykI^hK=_d+Xtr]mnM~ȥh{ɪ$Wa_0q]wkM;gMFz pss#iJ< dyzXbO>ہ]aEēdg^p,obo0*^g_y=J1!d3ϊ,σh4bAa#-o(+1F} A@UUZߋC0\TU㻾Gݑ4+(z4͵&Hˋ't=nE>^iݨ~AQ9e{l斯.W=xUz%!f~/9*ql=ʳ*W$UrL" f UU1 hW[s,+7!pت4Ggy_es UR؉vNgCeKEH7+ Cz=AoVm/Y^o/ C^~oOȳs>#QȊx&/D-w5|7 I y MՕ9\__777D:xՕ0 Qg4zPEvnY(W!|CsV0BVaNGvuG̣HG6m6m}&9A%:y= \Eاh*J|.+ʻ=y#didr)-|v䆢uGuUdbesWҒUqZEU䒦}>?:|,XUJnM)5tשiZߎ;?Qwʬ:Lӄmu}C!$>5MSwD?&%ދ]>TU]ۼw~DՉqEA|& 8[srD^X.XRKY:KٟhMfRZ, [!Iuvz2qx|lo߾b)4MKB)KE)"49Eܱ+*)}V+y֥eYr4MyT1}땬mDyKJzB?RTv*W~SB  !&: +* fs{uBTwjeу8sI õmGw7 jZ1]׷!owŃ6V+z=z=9ömh믹Z.3]EO䖹Y 9G?*`U R.Np]z]b ո-QϽ^Jy7)'O$mϽ=GeϗΩ_L%pg{K&0 e䌒oqDʣh~i1y^֓yH{"l z9{zϫ#nKʢw~+k﮸V:BZfiPUUnq&l0*Al~h e͢$yVv],KF#\^^Im[XޚA491& C, MA.q*~uGU\\(V/lv|JNZyjˏ-Csoe̗دQf#駟dF* !g:Fי%2#v%D_ZޛwB~YĽzN2{zσ8uAmUy F3_Z=0XM2 Ài%㬵#yEUiOw^__1vsn}_ui7o/Vhi^;2r;c!ۼg˲RB]op^UʳNYwT!HEy|)Fm['qD^i岫}~eU7X*krl8L)=A^no%emuLa(v)?s^餪Oz?ё`Y4KHL\KEAݖڲ%%a(maGQ4 Wߋ{5);g.˲`v~ZMYإm˟@x˥<жJ⮢(4MƖ]DTUOOOx<`0z~uA nTi/Ϻ{-q֮sgtiq48mPY 0 eaY}_hcwXd:y)cG>'l>} |.'Y M|z%ߦg^_r<==9GYĉUE_B &jNn ۶a6|G4 6~>}ax~~>b5ӮmU`2mޢlYq${~0 X[n+y/ mNswwf MsK;{||i, @+j3UM ~w~ |]lY:Z~GZ=z= X%WG߇}EN+4Mhgdq*>E[r95M뺸w*~g7WDevUSEIJ1L5\\=:vΤ>dh1FU՝EUiOw0\Ek+|w10a۶ *FaJaX,XV;V\n:Er# 99'\ilSfZi_~[=!bf[V7jg86yi<|///xzz**@9Ld.yއWmy>>>ʜIa4*,{V=9OGyKUU//!B.g_^^R -LӔ+3'!UVcR<5/H4 V[B#_w<B!q KB!,I#"vs'ʓ$G`B!Ḻ:Nu8BB!gXmUt8٭ IL!B>mlsNUUM&ҝYK!rkyN6)?nZ aT%^żR6Lӄ8u& zzx>H3/',p hB!Ge6aX`X  $&n gy?B ooox}}ݻ ]z0 e>z`>HBr+ ! cZnnnnW M`va~9gH IDAT-hf UUa6FQ믿2NsOkYnK@|B%ض +~>PwBq0!///! mg&l!ZܒB!G[@B!B0|h4(B!# B9&\L mh1L0 UUuv ۶q}}|7 rD[۲V, M־y.ͦ|V0w4M@ug[*{X˗/ɳVmX% P1N1L5\NUP+uX?b3|5OOO0 CJE.*۶qqqMӤ,'I\l6>4mK~Y,\z矡z"HJTv`>X|ws5dHh4p{{ jNnV?rG*u\b:, FCUDqPQ8_jy, m=oh0|>d2r<('xyy9Pu|"$ ҶU'%ݮdC?u!y,_QRQq7; DI. 6 )NS3ZIB:lg? {4 fef/Y(m/e0 yԭ ]׍=KUUyU\lvTTi%M^}J>E.iv%%kho'_T\J>QtݑUIvV,k0 מ \+LȯyHRZSt[Qn4)5z:c3 !GtdBlya5фg3Ql,K9;nŒ`6mLB֛lnZ%Y{uܔq*=D>ߚG /Qi&2^odd;<777 ';Ţ /=BXkl\TOAm,*t{-X$1R=-EhAH'=(n=%ًFA`8hd*֋r~e=,2O|6mQ|7 מm<.|߇yVjjV Oh62Yx<^,k|"N{D^q,rI2e{*KRq0r~ƉyUq)yG5igyϲ6~Fi͏98Q}-/%ʸǝwM'J|k^2|4eH s U&mu] M")5.ڟI'Z")D)֏c\.cgg}G^KX3:m2]Vbooa\.^'=ϓzNړZ3v-Oȶ8y6c.ekfWd$7qS&NϫKy'Қwlָ);T{Lm;@ Diw^(ɘiarwtt4ih6Yz1jbiډZ墂8ѲN޺IzH\TK|˗/1q~~b2ָnooQQafxa899g}6uǯhgVkkݏ_~e||z[9Ȍ=μ#/Lmtp `"4qgݲ;^D.|Ucٺnb_uyDY"rQA$څڱ˾e{I6C!0p{{x/PTu%Qh4BƳgNzi_ uW^nwꦯe'WqN'dۋl^ضTK^|NH3WT]T=P],/6/g^l\b{Q3n&ߣ;To t0eU&N`S{-muAld q| ^P*K!Vuض=Emh6]-]ۛ|][grD=Dٞl%Q.YT۶sol2#ӏrss2E'3uy|}^<]n;RL{Ni_ޤeZ6^d!/DRq%K8f^'U%qWv?U;(Ov,/gԼ6ُTU;T{ǧ|k^Ou0e^08ɂmS iVϫAJ@xfx-]V P,QV<!^d!ODRq%((3 qpZ6NϫK~w.O,/+ ׿x<7|3n?F8<¯~+t: ]۶Dždћ7o~hZ+QׯiZWD[{?$DGquZ7o[[1uk1.=zGS]&^?1v5 z yuC?+v-Oi/2y|B\dq%⶗yl)8d32O#.z!q,y\yȢ:Y_g8(yjsKI!I&ql=CT惪MgSYǗ,~?b3?;~(wL zY"^?u~)>۶;7n/Di9>>iOYZqϳ~?7?<<> \\D>蛦9BwU'(o8 "",O͗/~!˗>[~(kL֠iZx.QvㄯvK?;䮐 -}'6`"ʅ=z Ot:*t]z䴝F>cQ0(Cu狿|hBjb#5ŋ`0El"""""""xrnöm˲!:.//Y@DD+X0pxxսDDDDDDDDD >| """""""""""""ڰ|wq}||3o߾KDDDDDDDDDDDDDxhK0іxE@DzgGGG~,|GDDDDDDDDDDDxV߇i0: /Vq m5LDDDDDDDDDDDDD%xhK0y8??5y ׉lV{{{+S?iJԾb6quu+j5 V>(QT`!RZBĶt`z;;;˅<p0P.q||"m899a}qu񘈈]e]TBXDh4_L4 > Àm S7Me!t݅\.hn4M1,˂y8==]rP@لaYzHDyrh4‹kIv=,zKË0ËE,bC """""""""";0ei0 ⋮O&A\t{'«.ٶ ]e9+-MDDDDDDDDDDDۏ(ZR4uݵxq_= >,˂8~Ex[4{`Y{{{ue\.S(.//8"&!t]at:k]vx9,yT ^/|x~Ju, CmV(m &\G FFot]eY, O>]'vwrzzeY}V k]@qzz 0'yOCih6}Ϟ=~Ϟ0 nd_"""""""""""/?g޾}+0m қZ(ILD4~f&< i0ʻ,"uQ.|߇0 gAb۪j( ZíV """""""""""<^&\h۰ma,ApNDe6t]v8==eQ.'x!Kh~_~9ϼ}Vos `"""""""""""""- DDDDDDDDDDDDDD[/m ^&"""""""""""""LDDDDDDDDDDDDD%xhK0і`"""""""""""""- DDDDDDDDDDDDDD[/m ^&"""""""""""""LDDDDDDDDDDDDD%xhK0і`"""""""""""""- DDDDDDDDDDDDDD[/m ^&"""""""""""""LDDDDDDDDDDDDD%xhK0і`"""""""""""""- DDDDDDDDDDDDDD[/m ^&"""""""""""""LDDDDDDDDDDDDD%xa6 #C4M~]__T*lKQRߗs\__4{W췔Woi'QUi#p}}36 kk=d}ڶc\]]jF.h;f~}ڋ IDATt]ۤRD˗/1 2H4T*ضgϞen~86 XD~߳؏4M|߇/Qfb8ܲ,Xx̂(0nf$qj58Jc=f-#b~g\"g? @l/{Y.:: r(.ē'x(YdA ޖKPmrkbI XK|۶yL[Fc?ATiung㳳3XO>in8j!^x|oory곆azgV s۬Vp]7ܦyp]a F#, pm0vݭP(??=%bggat:KEϟò,A^F~~+Aԟa1qqqSQ=nK=. 'vl| oU{y^XGF#z7=>xU~+3>qQ7˔)7e,N(v+躎?8vNZi nn֮lRz;K(*TӲ|߿k85Ϋnlɴ4/N"gփrz, XX+)/xm(}ò,840)\M|0 e8{ip]J%Zok#]q||bM0P,aT"n8IubbL7Bfk$Mp||xzMc|^dLWwhqC<+J^'ʥX,NgRaa&>E:B˲xXT0 0RiqivvRzƥ((F|:>e3 8}]/'^ҪAf|W=oUKxd|>my^%Oh0m^73B0-i[m:>1IbbzssM^5R;ݍ( `gD,+ 47 ^[yib]e(VݞzS|ek8n*DioT"n>}t6/{|:8mo}&ggg ?#?7{ȓU۶.LӄiY. nDqQ9-{XL Q2ن H>t]Od{yiQAS=Lc_,E6OJӁy,  Yz̲'']eylqͳ֭ A, /ѽ6{Hu]3)Em9uO蚜HN&YzͪeYsQ1躮[/IK~zK=Lkز'<+(ف8IQ<{|QuR>3)#8n]2ZyuN[SݮUmKqB?$긔v|ڏTi4:LC<zzޟrS$&LD hZY3Ƿ>4Z9f3,^sU'99O]UI_S]yc4mc"o6ޢ^^4 0prr>l|㓍YKy=T>gݬ8qpq)/%q:/\6g^ћڦlO} ]aFfD۵l{Ik4Mh4T*wnu]\.w1w:Dj0X,$<60:P.a d.?˲p~~ޕ|sszju4M8۶~x|nw]čFO>eYp8e[nwŤ}4;n=6 ض 0aUփlۼ-Q.\ם'B/yߪw`* c /%q|:2Z&'g8lyniYQ\^^qE4ͩ|Syk^Ql;?$*R^q:|zY988aq>u'Cm/iG*w~6#BELD!zJLӄa'1vwwQVa&4Mh4) X+001L2߇yp]a@4 mF#E۶WNQVavOq{{]T*pB>,x<qXq^\.zh4kf.J=ߊT*فeYhZ]Y2 [qm^`0.2lۆi4 nwmo"dLUY pı;/&lNIĉY2]v<-O3<+670DޚCm{\RKQMq)E8DyO%.Tm꺞8Dy^^^ggg{p۵l{IsdiĶgϞ@V0M3|&㼌B t"Do;~>_|>oJmLDDDDDDD"SL{@""gk@f`"""""""ʤMӄyr~ytqX!o&""5(\E\F}ku:}IDDG^|ɵ?hk0eR݆m0 e! Ct:\^^#F\󗈈;~467_\/_>۷o6&"""""""""""""LDDDDDDDDDDDDD%xhK0厦ik} װmF[Ӯ){yqvvƂ{q}} 43] 8r  6 @T5j Q>?g{2SM(Rr])qT*mϞ=c5<e+X,L) *\ P؏}ީ À4->LDa䃈횲PA}޲^H-a?agﳽaoo퓈y^R}~Bf{qڧNj/ 6*5>LDDD%.//YDD$^m6NNN/^`EP*P.YDGD۾=DDDDDDDDkmO}'(<5 S?kM4۶yL 4 4 bgga|GYyi<mFzvK8JLӄ}nv82- p'G0Fk|uݩQgEYm\]]A`YVٲjSOL~ZB4 pnnO>i8,Nq]k^Nldfl{Li/0 | vvvP.þ?)Ov2~OUfusX h48%j^zTُȳdlHc:JZy8/k6mZk64M vsr4 Z-yz=|~[̎"Əc t:Fܶ3/N, :de4=~'O&5 _5!...ܺ2'(yO3ls|QMۋ>e/-Q0eSY[u\.}˲8L\i:,˂eY(8<<\ `Fe sV8|߇a(pg~r]7LD꺎bbqo躎cob0DT*0 'njZXP(, CXJ`07QSRkv&˶mj&YTi\,8a6u/80~S.a63Nyʴ33n*͸p]wIk"7UQ'ODŸF^:/&Ohf/]ö2s;2nËHcR}alz.N奝%DBfkJL'*=~5/4MC /pvVj6r\XԼ'o9Aۋ>e/yQ0eilH롕eGL _Je}|2d,[T*-q>ËTuQVHxFn;Z bRipϟ?ݝZ*Rb ~~ф4) _q'䝺C۶=n=T*Yv-d bBә{.$ߗiQ/\.hOO^y5iKt'0N' E>vwŘvQq{(J^ ;>g PT?&{taKTy%1#;LD[o]jOs EEBq`03u4-}Ŏmr2 z ^8h0dYng6A~&_WR0{gU;CQ.:ԉ_~<2^qE'[LeL]G2.i*QDR.ǿQ5U2f/rbϞ=[4iS.^x}x| FndZקK|a2k3o,YISDۀ&~gEbɻ ØJ;<σeY8??`0@d_1 ggg ?#?2m4MhN랬klbߛEv.kgqȴ3Ym#ߎӏTgAF^˲h};QSIǘ8aٱj/l^zTݏd%/T&OwN>VTyF 咼u_M<Tq(qPOq`CG dLJ(|>Y wm Dt(U œoE\ '^e*IHRIXWx<zueiqD8?8:٦<>N$0:O_%?_m{tͲzO&}Qs&I'W{y٢ҢzT^Β(Rz?J<dohH:eQض ]zPqSiE岬Ky7U#gsWWW8;;~3/v;+Jʓogg'WM0vN12^w?[lToo2hYTS^ڙVֲǾcgpW>WTq'ľz7U%NzӮeY bjun"~<(|͡ RQm/bq~5MuDyʶ36vP,3^ R^MH1n&1AuXi0Xx:&q~~~Bqprr+gggjsqauP.縺 7Ij<'޴, ayΩf_vzEɱZnY$ѦɎdO=igP?~,Uy~Bf{quT88\D+Nr9k,|FO²,\\\`8I,!aR &'p) À8h6 `~bp[a@u\.0  Dw8(h6S)sY]{]qqq\5;RYqڵl;srZ kEMEdL?4 m0u⶗~JuAxrc8έ#ꫯ0 _zAq3Gy3%mO8%u>ǏO?e)_@?OÇ,i""R4.gϞ@2Bqww7WQ ...vqxxay\$ض>)DD˿ssyDD /0Ik[X,"b "x6nooon 4y """"5d%"s]rA}0|=hh4˗/#'˅'7^&"k۰ma,ApNKQDшk,yQ6 D~/NTdnPPe.31>_[.|gwmb|v8<_IbK#!)j;Βdfeu]ضX;Sݮ&f3LE=j5Zl/jyǸɸFmr90>}G0 #eqMv?mFVs۬T*4mDP8q:e^,ʳR0nTrtBeRR`0h4J?D%UqPߪiqx-e\m+_'=v:.x'J؝*u*PT6c]Iݴg\ b)ygg'vV(t|$(㴨F1`KI~?3=&'T12<'~6YI 6OD);|IRɶkq)ͼ5˲V.YWɔh4BSCt]Od{yiQAS=iZt7{ƇN`Y1 qss=X'я8Wqs2pI a$βo?%Ny^3qe|)d۵긔fޚeiKU2P,a&FQxH\FaIKq%8&;S'{d3U˶!j\b;\%D?y\vfW48O&(y~E~.rU9;4Uݩ'% IyiwCүR]y/Vǁ]eqs']esx)G˾5Ǒĸn](u>emV{k[(ߋۮUť,YFa^%[.ӧO ~ik[v(kyrz_4K+N{dRuq0N;Βϳ/2w'? DDbjr 4dhjz%~.* ['d'Ү慎/m/6zz=<. >쳩eskvOEy7zMeVN0%o4KQ'ۮUǥ,y#.̫dE\Ե, 0MvmnO%]ǕE1qBu|KqP%YQ;!d\kVw%꤬e'&nw.}^F'cфhY ,_kEޗؗ(Sݮ71ZeF6={l}~pe-Q8qS߲;eגL:a>3*;퉓,A\dzӮUVL=ĩw~zKW?V^g?wKRbv~"Χ=nFoصj{qǣ}Sq0פ&碶N{Zu\Rw2.U~O\xdYlۆFa{q3 QVJeǁ뺉<=N鷪Ds2_?Aq'ۮU%q7/rI{^e [.b}{{pGIų4Ǖ(1q""_S]6.m.ϊWdqq7|wooòy?|_30mSql6~Į<躎 MӠ:*ʝt:p](]Ng+`d&]''']qttr 0P(Ϋ, ]777{u؋WJvQ{QtgcE<;o$ JDvu"}˧mx^[^=-"e~a`-,T6dGr )n0DЮ%٭gK?F.ss9'3d2r,[]\8ߚfatrCwZgtw!Czuf=taf0MCMt-iee3si$VVVڞqARVHX]]m۰m>ѮD9 }[[[, h\!>E>V;dC]-aBXD2m r|><'ìFQN=xudE ] QW폅]OU =/~aφ2Hd볰ۻnj0Mt:b1My2JRۙZ HRuR… <L,h7l8-//#ömhEQP*QTFiL0Y^^F*i,DZ"ɤ?.4j5?n,˂a~w{:hg2E$ ;;;f=- O:밉L&XXXa(@Z~2 IHvm~S\c3Fv xGboQ6R H$0M@Q|>v](z~~ϹǧxVq.(2 6zbeTm~p|k{I8|vv;)e^e<@bV+" ~ =/~ae%ᴳm r_ ڟ.\SO=ufV>w """:47aO<!n MӰ@qDD 1BDԏ/>#|Ov7O|͛R=B$$"""bh8LDDDDD4KKKu3]nDDDDl { mH$<BUUB0ԽY~!3" 4Mh0y2 ADDD 11 =>06|M|-߹yos`""""""""""""")`""""""""""""")=J(Jǿ鑇Qu/whJp0Mx<]]vww[b# K,.VWWi4^677 ]'6MnnY&X~ IDAT_hRkïcwwiNm\#4"H`-hzg;cD4Rs0aoyi`"Eeex! ( Rr#刘.L%!'Ut]mpJB4%4M.؅myyjo1imIwg9"3b:4H$PUm#K։'W*0??eY\5aB=$"%= DӃD4Q/z5MZB۶&ψ&F(c?[p h"""""""mll3CoV%""" mFє `" \.̙3]Y__axǡ:8t]pgl6uɐH$۶aYAP@V D8Ϟ=R7$[D"H&0M߅ z:eYbuu]8|>ص0Z4i4MyT*pg(oƋ(m 4?P(t WӧO0 xd@!t)A4e (˸t\ɓ'~oii D3MZꛍ' TxO?J8X8Y~0=Jm?-8lnL&ӶWA>˗j22^L*((Jd2;Ku oKA䳰 Zdݰ4;aj,ض 沾ђwz=nkk˯#XZ&_onnB4z)zw V3z0tt堗HGqNn>g>F48LD\.6 cmF2p]a,躎Ŷ7z4?GQg}(Td娟$*UUѨ!BӴL&i6 e!0 L&Q*ZS/ &lV=D:D"(m>eY0 i4+K aeeBAaAn_D}H$`&/?vOA /}|˨Co2s|f4 퉰+a?NwYbp}JM`ƾߝ =(<$80MVi8|_&I;wS<84 -oxF"qP(ZfbqQatLcfKKK, "N1֦mHR vj5dY8@uFb./dau]={h,Zbm7d2L&yNw1Pxd2 ~{躎\.u{z4 bmSĕxC8p>c9'd(PU AbX˃X,h4 󰼼_JoLl察zi|6)d0 !Hu?RX,""mX:K@kgNj/l_[A2ힰ[þʞO&^F'^os|V4)퉰+a?gh6PۮdY}~m1q=h5?V[K$PUbrCQu{s3 c9'd˨ӽX,UQڥOsD=o4dIם}W*x|(q!f܈x^kZח=d|_=!ɪ6/ =1A㥟v_aSF:ª&=veO|6i34r//V*xאŪ\%otz äLjFK@k;av%:$ҮQUH4wx ۶zCK[YyHӴ@Fr]rӽ B7rV=Bxa`ssR b{{{׍XI?2t5yWAj,~i'SNN>{lnCsVg7){]vl~U/ ⥟V|a痠aup ,ziRaWnIkVRWHT* JAWer#7&ZsC0uzC꾝BEjZCa˦K4oDK} zְo(_V"`Y?.2L3Y~Q{m ?ʶI}raw~4sKKK4 DLf(.0[Y=nRu?SN/4HyFt33/AՃ ᔩ'IAYҤ'F_ )&}&װ๹9X,BuJ◣N/}hqCc^Q N N666BXusuܹ3뗉utk282dogН/jL&L&wlۆi8Z4ZhcD{55Dcm货hqv\BqU߃zX%/it贼Q?KDX9~VAa߸8T*8y߉ j]g,GaIui-'d{Tݍ0u8\Ύ7m{(8vͲMb{SiN/a¾LJ8x=_2)|쥞M YRl8lgby^[,b&TUFPauѸ0MƖ^bX( vLj%{ h9{pth4v{3}eE4xUUm%I$ўuݫ|vE&>I?ُQԃSd}rOIIeۥU z?i+'5b|2677PnЩޝt|V_&<;A^o}.,,ר(JfM/vu^v %_PIv /u}ݭI YXRl8">e٤t4zIW Àip]J0cDD4Q*ٰn<hTdYߠD4|,ڷ%Exq;?SVØJ:vlj666ϟoil+X,@i6tEA* jiAP(߫O4q7hՋF yYQ,--54Vga{\ZZ/29H5w@{[ŽQԃxX%_wNg,Gl~td2/eu~oU=O>kf6TUivXMzwRaYBς`u\.5lnnv}){( ڞF vr}< _ OsqrAeaײL:ª¬we9J)&ևWz)+AmV(~[iX< >F40Ml6 HoЦ@VHX]]m۰m,)tiM62LCx<UUq% EQ*,dsd2r9Xu'8NǷW/\M`Yrmhꗁ9|K<;wD!~f1770p%8Ll,:;"LwiBӴ)~mn) -dža׃!Lbee9w'3~O6LJomm,DQrtde=O>k>Nݰf˦l;0)lF<gL?xnu( ڞ(H&m\.ۦl~ k'J?Q~;Iw 'd!|Vv+ΰ+aǧlyr[FXXX8~_ ˘(~{ZNP?7H;Q?0H~+\zN z뭶uFwS;ʕ+~"l6^x_133:SN%"ZwE;9Nu]躎YBgyu {jOdx-ao9ߠ%~l;DL8ɤl^ ޕ gQ?e8_zu5|__8~w=/e2?J߆}#O$q\j| 8&""3Mɓ"#ꑮ,H$K.qiFluueu,b2F~[8qDÃK][:D"~ǥ\$%WW8$l`QopG??7oJ6M_<{-[>eYݖHl8 *2DDD4=EPi%"&"""""#KKKi譟W(I}u4_^J"""JtiBQM ۶H$y\ׅ4 nRgJgϞmˋ(gΜ0J%bQǶ2_$.&"""""#|iB4P.Q(PT/5!8pADDDDDDDDDDDDD4d_|G8#nϟn͛7~#^"""""""""""""`""""""""""""")`""""""""""""")`"Z-b1F ( '}lη]z~FxX__g9a8c!DDDDDDD*((<BC( Rrtg'֟ .$_!""""""0Me9sgΜATbPi۶N;ӏX<Z8PUxDDDDDSjkk 'OD:fd<σmۜLDDDDDDDC`"""""!j(JPU """""""{D4",˂i4 履-paIY}:ďD"r4 -,z,<,//3Mϟ4>Gea"a2z8ײ3@uضR @XtXZ< ][}DDDDDDDDAD4<|˲J X:T*=g|4,,~Gp?k?(SOAQ躎D"_1[X[DDDDDDDDA0M=>DTzK9z2 `a Ȅ~yNDw)=Z(Zg Nx (,1m]Raܨ=0 fAH$2xQůۅ]|-%Jl6 UUU3<3}ݿx6䈈h(4M4a6t](٬P( 0 lnnT*X,boof@35M dGpaX__o1t?/4Bf[n&/(΂^VaqqD ,˟.2Lˌ4!13,TUu,ZR˲ᔉ" P(0 bs[wR?@vU&]s ;^;a +_˦äQ՟R=+ DDDDDDDDA057;waOB\.oT IDATy*2 2 t]g kĉ 3Cn{ +ȉ4s7^62H%ɆYү~E NQqv<) k1|M?u]G2*bhGy"""""""=hi0g$U*y2K!CϮ~ ;GU]"i{{"_xOEQ}ϝ;qiRT(z\% """"""`"k-@3@^C\UUafp N-Gю"-ZγN^fC~'Ēm$۽K/x0vq> ;djXD"oUχG-߸Ag2i(B&뺰, XlO \Z[˗/c}}=6M.XMl(ST߿ob1˲}qb4?ܯj@B*jxHk&8;KVE6" ϟoA( bOK1[?nA)/A3UUwaE&eu]˲yEQzD---hg5t,_rc=]Q*ꫯfMO.,AePW\}݇#G@4=zGŵkZ/.N:΀RSNAUUi ]1;; uQ(3th ;eàFٶGb{{%fggaY_vjxu΢V!#/^ܷ襞;_A[oن<ݐ gcǎP(_lR~0 G+W/ﺮ#HX,sWg e """"""" o?}QO~p;|oC8pc:u\ _BnnnB4,..~4u]#|Ov7O|͛R='\FA>Wk ,k &""}΁2%|LJ), "22h/uH$0ٻDlF"yp]B4wg5|Ma+JKDDDDDDD0ud&TUp.\`Py M`0_V&UW܄ixDZD"Mz>x5H|ʦ'4MC\ /rK.uݖ}' !zn!.;>YG: .' Ni_)0ˤ'Sy\|b~~>tKN8o4q۟^ 9(9 Nz)뺮ömegѴdڭAI`)Q(aYX T)3 o|2Xնmض uQ.aP\\\liض7J1""²,,//wlBUUxi$E!/P.˲zP 4MDkڥ(a(xM&=]s&׍X[[C4S,iZC^S!D0F۾D堪4 ϟl[]]0i,,(A2e~}&GDiv\V6^dƧL8EA.\]]P )S®2킰xggg0+?M~%2I,~1m'r}'LB4*Ga* 4Maǹ9AAx0pNB;Ru{aaac{"#L'u}(qM{vkPϳb_{NӏDSVP( H Hݠh3ϕJAUUҠ%۶q9 d2ْ6Z l44$t]*(bXH 7~6hb À8{lKXAix4D!DGV4,,,A-J4qM&=__HbDumPU e54dg,BXlIQA&W=4򷴴˲΃֭mHR-Ȱ_V&"t/g"@6E>o"K6>e)x6CQ3vt]v|>lvyl}fegO_&%/f 6bѨ_R6U*X}gҟ_sQsڑb-m jKi-0s?L5YdO&wm&&"Bh:7)a wqjP]'#Ϸ V*;q sUUQ,:XNa[*چ5%Sdep6/UVlqԜ?ø>0 ĒLZ4*JCr沐dy^$SEoZ懵~Qms [_w?$^dħl8E K>oy|L<]/-iƧ>]os}6~%2 ,~1m'36gT ρn}"Hg"'=vOx,E,//cyy'Ng4mWKKK=ٳgqI,//ɓX\\wiQ4)Csũom#DSaǧEʫqvL4*54vꉆZð~:+deF[ ΝDC9ڽ%=+=uEf<rlDK@M |>?2- 0DfN u*4MkimCQ ]0EϴaDTBX/Aɰ!:b}ˑx!;~`![Ta}}wĵ<#/a0g0h}t|v /dS6/g2aݢvAl< 2AS&评]q+G/f 6D\yPAQt?VTٚJ"L\0^+AܕtnK/dz(/%M48L4e*"Ѩ?"9H$XXXeY~'u]d2@22pNú^xbOvZZ,%e˟>L/U ܆?NAAsߏA~S6/AÎ0zZ!d}6Y~Ao +wQq~wNaܜ?\,:LDRӠvOq[0=(?!DDS(OX̲ 'u];ΝkQ(RVuqYj5lnn""w3jLL\ٶ Mpy8q"FlN `t뤵뤈:u"lʖ?΍ e=_Zngal~ ">{Q?4^dܯ~ ;>GU/hxgA~;8ˤd,Nugmga`kk +|>6%}+C>sK`vRG|GƵ;_?sr`)T*P.ibD_ؓB4Ԛh4:6oMvW,eRߠq`7_[VO{T*TUj5<3d2ŕJ|'O;UA-$/a%s|kOd˟lx=_Yn)t/Ag<~d 3>eOD=v|CD'ςhvq.aIigYnM?VNMa:)Lӄِap]BwBt:楑tDS^ض=!fe9s忓'OqEF4cu0;;; 8( z{]VI}٩DIk|ٹA4E+GKԿ[xu먉NON*h4*ݙ|=rQL~ ">}hXt|ʆs[y'F,˗>gg_.(+?>t~vl6_^][da gLӄ뺨T*~8xC/tI鿏ލb|2677*:;HXZZjj0݄ ]6iiG/dS6ꗥ]E|]/[ZZ0 _nv>,v8oG_9t3LJ;K_r|l,Dt?&K<[m׷_H?FxwE TUi~NP5MC.:ְ˗/#!H6\.7A4A4MiRfF{M  IDCEX56ݎ`eeD.lKE,Sty iTUŹsH$iZ~#jtmm{y4H:~'ޭ/bfsmnz$?' 8=~~ r,h'ar _>Q_XX>9]ZSNaff:N׾uqqlK}T6r;v:t: u:fgg. y晶#x5H|ʄކD"8v\ŋQ*OV_ !zsWg혿Fȑ#|>6.H0dE6 i_)2v~vl6,j@~ C8pch q$I8t:!""r4 S9y$#uݟ}v5躎/| 47oޔ:{M9ׅeY 2Elk(?+hpg)Wv]dii ;;; #3aKRPU|ADDDDDDDDDDSĶm$ xu*4Mpgو:D"HRF8wWM`""""""""")a&4Ma<rB[[[ ". ÀiHpB26Bs@DDDDDDDDDD{@D]}+_:#:"""""""""""""%Żo|kBDDDDDDDDDD4d7o9])D7&"""""""""""""L4FRTgxW9?GE.~x'BM~x衇p^~eɦq^&]]g+xC7>I<_ă[ٞ~woZ7Djg3|^.|.yx1h#7~Pkx_#G\c[P?a_;O{}Ө~_?ܸq}ǘ:t}ǣ>J2A+xW0??moܸᗫ7n~ٟ%>q|3X>dѴ;wwwkkx7oヒn}7w^{ &>r >C8;}K [`oo x_W~+u|_Cg7 6wS9mcrxEisss~awm||m6w?yn 3~6.{\Oӎ?p>7n;f9""""""""".n] чo^{ ?cn]׿Ż8 Ų o|5pg`_y0-P,{o=<>x}=u_y&}v#WUۻ6筫W_~_F;K9wfw~?>]o]i{G~ vC|;ϭ<+f~/o nܸ]8~7nÇIxӟ4ٿ>,C3.s\?RRtW>|/X#""""""""~)_j www٥5i\ؗŲ o~׿ Gz(ppi?5o|#urUk8sxz̓gZVWov=ߡX_{]⡯OC10oƷ##ɗ w,у`۰r'm^n[_Zާ_7~EAf'_Όn/y?~K+ Xv5]0??Cˏ5(bcay&^u躎a*E6e :t?_׏S9"""""""""WAÃP, 5 ߻q?|5A0+ϊY=+/cw;Kn7.>r 2ll&A3}WڐbIVU>=tO|O@_?W {j<_l7kowR xo\.w?Co&{9|<oײqq[f۶ӟ7H8} s=9˲um7}3>_~)~d2麎G}=})ԿXЫ`~~ԧْ7oo|: 4:??i\*tZ8~8to~B'mlZK4:$HUԵqAw}ֻ֝gvVثP(\)+E(wW6ub:m*tY%-4$MrH94׌{>|?5;u] ✐0?s>lƃ>8zhN3Sd|*mtAig:^ΣDr⎓\#"""""""|sw" mɶY,Յ񁁄9z^gn, X AЯ)&ak^7,™ʙ^PWgd%YclgQt]j|I~376JI.^}-(t=tKUD6ew FFFpeqhaD%˗f3jkkeut#ף###@MM ;猪=uffB ~:t(]27q0tqQZY? ^Cl{ ~? 8^R 2|/j0z<bΨZ! e ں:ۍXJ㝣 --_]dٿB:f9*QjըejZ^ Xvm`0N=QQQǃCEݣN|>t:Ux'x:gΜIZu1l6cݺuI:>V+Z-/چ(JƧvQJ=tb6Ŭt2ӝG;Q>HK,IY$!t~SuB@ybxASI;+ؘMjm{s:1vCc՚ވDݎGfV/޼ݻqhz1hg'4z=6T%p; }.>}%078`_^~8K}5rYzCvϞ'+8zѨ [~)VGd2_ tt9W.\@cc+W HB2ҕ+W`C%"rs`PQQZ@65%fߏ3g`ƍ +?!kӲBww(%l DoqqX555jQA6!4E\vwdd:aƷqbwqqw$ VzAf9ڒBfZii娰P3R\..KqiZ1e!J}6 6|>xy&`3B_|m.MEEE{w\p. x7*t|*m!<ҝf<"""""""""T\V&n[,dԎ $+s:@mے~^gr>,߳'véukF8_5)dR'yɶm0[(,)AaItk_힅(ε"5gp=0b=^ 3'(EzGk1 [Ā Jk }֤1vXo:Z1m&l-9ٌ18J]Nh2\.@⌻tO|AxA3!P&lםcϤY۷o 0<^&Ds-ST9!W+VNI9󈈈(fv;޻ݻaz٤5hoý{7j%,*ZwX]]zl9ˊpJڲ z ׻pa:ݻۡXobЏB6xqR/(-l-lNb 8mUv͂[~rV>sQy31_t|͘`;t&6"(< έQSpfOXzMJ***_YeټlH6J/Yaׅt:] sz6M^ZxG/j Bw6 Si^#2ϙTc(͆׋'qeN^,ljR=h('[Akz1+d/ .WzdDt wu7ۡe_ d6\ٹ9Z(_puOw/:SNLxGR\*Xr}_RvY %zdddI?W^^.?èزeˌlNdAiJ% {]8nG"Nw?~ǏGyy9*++ш7_Opxֹ$g<oSMy$0 C3ZaB[W \kwbx8fk`lL m~N+Yo|]xM-׻0vCg$ܦZM(+!l]\V3+d^L3Vebk/G`|D W=H]Z3lja :JU\v܋-4ЩxJP,m%\Á7x/_6%ead!xNl۱}v} Jl\#!r)|GDDDDDDDDDU[706]0vCoi};pq1˼* o U;X9r(Y,m9-UdVtdFp Wg`<ϳܚ^[yqOMcC^z⟯}[`_ȜXg]?®B|+o+YVs AXAaKl]'=)5ft:|>YE~1+x=bf pFQp ;0xu3GkSvJYDbڵkĦClj[Wj̮X"fVUvwDefrrղϚ1C0/H_<jƍ/e@[,VQn6\`~>(fY cG\d|~[AXbVeAa|w/p=L23z,?z-qWg c] LE҄.^P[ٌЧⶖ_ʎktY?׃}=F{OuK#"""""""lg(K,ap zՅ]]bobxXw~u56Ɏ9b5?LM޽;f2f¦&\•;11LmJӉ(2ܺ5굛bf&:b[?j’,ٶ ݻs:SOB{jz|穧fll,\nqo„wzt߹PyaS!;b~gdŸ`bgKߋyUυ-cʎjF>r `4QYYJwڵkQVVVa>}~?fX|>TVVB& BuwwBoooArF\[q!l6jr=%s# /|GDDDDDDDDDں:7mbWCgADbA})_m0׻ĬWłҖշh:W7WzB8Y 0>0a1d%^P\o] jz --SNG<g®F۷h4b3X)//{x տjN=?DMM zmt9x<lTCa\8> #"""""""""JzWxYrie6U 5>=j8u.\NS8(%۶aɶml0T}}=l6|>FFFE IDATja4krJζv\X8DSvUUU(--EEE|>._n;w DDDDDDDDDDDD(Z~DDDDDDDDDDDDDD2|6000ͨk&SlY`>;?UA6 OU4rzt>\V׈m^o]YEDDDDDDDDx}<1`] N5p2hXY,Kx6-}K$Z7M;3z/m3'@pjpd!5h:dL[5UA.v ([#|jdj8kמeBZs=o]Lպf[/Nin \g߹~|퇔GNY@ɷأDDDDDDDDDP=~r]f+iQo?3u/ pC^ѠT,- .pmxc( 9güM]Yj +*Te^mD̿;m#RCږV#""""""""E~f hmU=?.7NS{GzqeuU>>O??%8gMYJs] ;teY h.2) }P6_kQ5B՘>oK"ք풻 iVmրxM4[=(đ¸YUAlh\~#pƯl ( ϔBYeܙ}4%{`T=;7i>o*J+gJRSͶ luA,- aqoLt*9~21+>2SQVj{풮 MshrRo76_E@tH.D{4x}C3iTEڱq M X%WD )P7^WPV׈{Zż#1JLUcӋ(^`%;fހ\., 58cw1T Л.\W߅;6+Γ |qDDDDDDDDDsu鶗 -- ᅧ&dp=ee!LY,I4[xf׼@1S0k.~(Tpj`)Xj .lCSqqt>4)8#j5kw?3qMt-޶ny+'Q[R<^zL!:A~O]\"v6Y5e}S8Swt 8bڍSS[CMSqw/Y Άu"D!;gƣ7]*~Jhv x!qwlz=[kq^ߺw>16z͏bwhg1D۽={@ej҇Nx*d;JQ C`X8)OFza<k]K DzUp?WVЦVJY&A¹N F_y ܑK1ҾI[0V-*F.@&\.!ly4NcE`4tT%w>{ \lY?ZϤtGҒx$~ȥ=( v>-OsRƪ;c1+0p'dƳs_tm5i@Cn >qLCL-eEӻ-f؂1H!J L=Y<5lJ ;dcٖyPO8S:2Kxu<*kmYY(yLtEjz4I,!ҒTE-\yު.BpWv};c )mtηwfjTk={SFeu"ۚb^eٹ bt Yc؛fKϩ7Ua<'"2'nt^B_,d€!쯶MW t\HWPu$<: GOA &)=N דm'{^ѭ(-AV33H5UA\r|Ihͪg:{/r[VLCړ,\xުuhK|TE- fc6@[,;ʔK- 4(:G q5+BFj>{>jg+Q9[׉lJbo,U,ɖMMtSAnjy0Ĩ8#wޘ㈈pz] N ;LR,ƵⶹB& Z7߮Xqjh(R $pdwh%yGmUPc[Z*x\$(hnP tY&aKdJ5md{&߳0\ZsPEr,8BP]ڿ%5o,‘E Ⅷ&@R3~E29[։\^#MUvL+ Rߜz8ApW,N'LDDDDDDDDD~fQւ;J;ӡwaguV`S,_Yq3#^Y%w0oL;VjօT<^c{aC}5p32Gې:;O؞ҠV>~OWd?[8rR󭟷jn:7kzh/ӵWV0Ο~yzQ-vuΖu"Δ~)e5h?ɽS[?LmIo2G}%wB5'=p;kH_q3w@XYJI7N qiӤطO3H@ w߷eU[L|X*ٖG,K>j7Vkj=UCn74fn6힃IkBg]l aMץ[KY<Ĉƨom2(?c'dhUA8&{;6NZMcTz\>8U8k׺)jɖVKP[Z&evuDJƙ cvl{~Y&[[Ė3j!8՞9mۥj:>ڿjq&֯}ɈSwoZ&tʗu"Y?R̟!<3@߱WRcu=,kpS_t .GJVOx;/ᶦWqj]F:=(?>YML!565UA G!$6/'0:6̮!o_/ǩuӤXS9&?q٣ٔu ׺cs{]L!kKO qI_o]myd)˦jfne!1P֏tpk UgߕYftu4/ႨͦtN|<:FEY&h6e~-91SZ~}grHr)*\V׈wHy+g]88i}5mmM[u%*+17F `{qo_b~j[?+(O 5x/Nz@pW0:w~\&bOp+=_c&[@gzµ -ل{:j*pʷO]fkxmBL=:B3Δ·; q5 #m !%\"v#VIF^s7fߕxf<tӹohFe)(t5Fǀ_.Λ~S쒻 -ՖLCDimKSԶ5(^`@t|ٵ/qz5 ~oW߅1 _vc𗈈hpY 7l `)\ot,]f'_[k]+C̠K8;[GqHWa?V$`ˣi皷O,Ɠ-X-A,\6[ǟ-Nj u&՟G8S2<6;6MZ.?kX7ĀF)$^éQxSS=1x|_3lA1{t,-nyv.ՐJ{uͶ jQsV 3~ ywU8_NJbZ'\)OZ-Uw]g1>Ϯd]""""""""""""ʩE:wDi Ey'%߯8Onk \_""""""""""""5!3+FLDDDDDDDDDDDDDD3Oi0sX q-}?5= /\8~#""""""""""""Ұ q h""""""""""""""ݘLDDDDDDDDDDDDD4G0LDDDDDDDDDDDDD4G0LDDDDDDDDDDDDD4G0LDDDDDDDDDDDDD4G0LDDDDDDDDDDDDD4G0LDDDDDDDDDDDDD4G0LDDDDDDDDDDDDD4G0LDDDDDDDDDDDDD4G/<@IENDB`qman-1.5.1/screenshots/qman_toc.png000066400000000000000000002501061510660157000173260ustar00rootroot00000000000000PNG  IHDRS׫iCCPICC profile(}=H@_[A;8dNvQjP! :\MGbYWWAqvpRtZxp܏wwT#eq!]0 Ab>'Ix{zY}JdO 1ݰ77->q%xܠ ?r]vsa? >$3{^^k}ZryH M4A`H MdrjUVV!5_󩳳Smmmjkk# q0^eX4tP :T% edd(++K~_GѣGICi HHVV8jjUGG@Mv23 MZ, 6LYYYxٳGO%I|IB3{lYV8p竮J7vϧ?񏒤">L>Oj;`СCcA{0'w׀%\SO=N2}y'ԫ]v_TYYYP%+o[֎;}v ֘+^2?+++ݻO]wuz駵}v駟fiٲeڸq^uթR~{v]_ڵK/~_hܸqA7n8=z嗵k.mݺUouW-w 7駟V]]^xmSNĉ%I?|йظqvܩw3=yv b34i@ҥzWc=!_wuzϫV[nյ^ &WUUrssCo>$@~?|\RW\qEL=QO:$~ߧ~N}'7l6.N;4q:@>O֔)Svopng'xB6kȑ9r>cmڴIH%%%2cƌѼy󔛛2I\ )0_JZ7'?A/\pZvy0rH=zT^zE]?OAk=aرzGgu9?1c4vXIҮ]evڥRzGtg_|{Ogy b}i@ZHرcIIjՋ/uf>M38C; 1b$^~eI̙3 /PG1{[ 7o.r]~ڸq$+F}}uw2ʘ믗??7ߌh?w]3foN~+v>[gy$鮻ܬ}{_נm;~3I_n70+Fշ~[]tMjkkpCE;Et%K.QCC.\O>Y---Zxn۷OZdIO?u뭷j۶mڶm:.sp*++K>OwtE馛nҞ={gxw|>|Ds|>h(HL=ܣ&?^=~3'|m )d%I^W7ouW]E/m6>sjĈ#F=avG9rD~>Cvm:3}-t~袋4i$ 2Ĭ3&njj޽{tRM6M#Gԅ^$ѣe̘1zw5eIƍU__/)8/j_/XR iZ5qD8pY\xŋSOѮdԨQA=#9r䈼^-IReeك׿-[38CcǎՁ四shܟxhZLk׮sk_|Ds|Xߌfy߯.L"[iOxb=?~Y4F7  rrr$I---ڱcp8t7J qNN>s'?Qqqq]f䪝 n4o46LyrV4:;;~9Ҝ+^jfFϜK0]J7VkǺk:V5\kرc׿ŋbX{|D_bMoFbі-[4|fk;vz!%x@RZoVUU7c~ܮozesjܸq!>c{~_TggC~T_x:S{瞫}k amݺu/CyΝժ_יgiӦirج,I矯;O|>8i>|6֏1uQQnLb8p޿NS555ڼyN;nȑ#g̘!ݮcjڴijmmժUTSS]3Έy9>Oi{ڼysX7~+**tiiZx/^kܸqZtii`hHaÆI*ܬg5j{?0a~=o?Pv~?a2wVkk M6ȑ#]Ygɓ'{Ղ "nw…Zp|_|Q}v]wu9s*ߦMdu 7SOէ~!ChĈfo׽{OZwymsNmݺUTWW'Iҹ瞫]vo4~,@b7ވWҥ^#F6?|AGrE9o_3{ァ{G$iZti//  E233J_^6m %I-Rii. >\mmm{i…7}x륗^.ZH~>l 6LG￯^{+W*;;[]tРqbhǎz衇̞Ϗ<;ӧkԨQ2]{>z'̿7lؠ#F tRݻWf駟nϛoi.Gwՙg+Bv￯:Kzڴ~Wuu$+G/sh?=+Ǡ1ci&effꮻz^hܸqjC]j&L?zH je#GMwCzqo|;O 655s̿s?СC{Z_Uzwjzgf3gj„ :r֬Y tQutt$;A?{~ORgg>S=3[z]{{==3=.a}{aC={۷N<>#.V&/ǓP]<\,Kt(;юˉz|jn+333:::i WY, :TCbqY߯GѣI}DI`)aZ5h uvvرcjoo)x= \fRرc:vi4X =4A`H M4i"/IC h@?z  i0 &c@+++ӎ;t:{}[EEEڱc85RQQ@Z D/CDoŪVyyyLl6͙3Gyyyr8$׫֪F^7NvCCCL]f5o޼֫RII,XpܴvUQQ!ǣ.,\mܸQ4sL555ǩHn[NSv]jllTUU~x0p}tjÆ *))Uccl6n,YcuŴ튊 knkΜ9D 6MW6^Wlϧ*fG`􉊊 vUWWkʕANqoNSm>HzRSS X֭ F+VR}}||^^ٰ =RH9cǣe˖ yР}+..6oњ?n<*++JU]]v 9@ rxTZZxSWWl?@ߠ0R.77׼ƌqvn\HJKKwkjjvvUUU @R47VMMMe`ۭyu{|[ݘk…Ӝ9sT\\l6444mpSYYs]fXqillTeeerիrpBfN˖-3Q !ux3nqxR0RNW LV2?ĉ%)%E|#.s:H!p" ;f oبrj9"I%馛nnܹsʸEEEIkIcccL.X q3ߵa7znUTT{4|(///\z^W+WTuuuȹ3+**s`zPaaaz]R[ly^ɾXs#嚚rJIң>͛7kŊ3gl6[Ó%cx VFZd0ʗuuua ׈a^]R l2y<.+d}IJJ#n$y<ϒB3a4jkkC>3\zF8ܹ[v$njj2+3zNYIuăx 4~_4E}bݺu*//7O0E[`l٢G\kQ_1Wrrr8Hz9sĉm1K M)Pk,eéշ-;==O؞P.+13 ƱZ0>Kzےzn4 7d̝f0PWE</@14Luueٔ@2TVVjΜ9r\ڰaT[[k]1$ի.c{jCHFw p8B{p4񮗗bsX z5xNrq<@jFz_j[.bK_lN_u,ϝ;W%%%*,,6xZlYHN\lۏ[Fd#ie٢ޞ枖7䊷q(YsizA8'#$=Udy0+Ww9ΐ/16}9SSS-[e˖t=J}Q͜93j4B]_5n$T&HۜN}5_fMҶgH ak :zo~?{hW-K٣KؠmoJ6MȘ ,l69ãX ?^A֭ӬYk4U8ZMMMfZ cZOyx466iOFn' 0ъ4kMM$)???kJ.ݮ]ܗMv@rp* oF07lؠTEE$> ^W\}ugN,dWʂʼ?]͙3'l99//5skV}ѐ7m6bŊ>?6UUUn׊+Bt:z4g w^^̙#r_1K^^^Pf̬$kuăx7Iv{|üACK,ђ%K(#nHc> IDATxT^^Bsټysg.+6tP@w˖-Ӛ5k-[rʐ,X\]]aժUr8rZfMuRXB.+(#brʕ8q\.6nhp.R]]jkkG}4dxp(777)יQkll4W]]q H0fO]].\(ۭ'pp񨾾^uuuZn])TWWV^^l6[TC/DJ_Ϗ7Pmm-o &͚5Ks̑2˻555Zn]*++xr^mmq媩QQQ~2v}j޼y***61^Wageee F!MCCp84755iܹZ`h4E 'rHKҐ!C8P̙ hʕВBn[ .xRxUR;6hBimmر#ۛ:ujg֭Sqq̙^tv3A/o߈k{V9&@ i0 &@ i0 &@ i0 &@ i0 &@ i0 &@ i0 &@HKҐ!C8ˮZG$߱AۖLkkk\M`H M4AD&UIIp8xب&Ԩ:d7F .T]]]vt:eبFUWW\nǎQK}}͛'Ilڲeqxl*..Vaa$QA3TTTvϘ1C^{Μ9Z`$iʕZn]B0vUQQnnVnnnH26M+V pp(???l5"8.*//7>n}qFl6jkk%}FmmmPO׮}=jl!WI!=_du~+Һ ƲvǀlaaaTd |B3 x4w\555;N͙3縿jժ lO̙X]vVZ=mWX|IozAF 0{$ܗ.KN&YCxuYt4>+//WeeeҶiO@/A؆s߾g GvZv=hp y@Dq:w8ZdV^1ș:q6zþ<?#a֭ӬY>;˥ׯUuuuЌ6f@7=29H׫*UUUt$+77WMMMa]jl~ ni<޲=TII USSӫ=t *//B&1\~]p8BY}\.9~qFrss#~׽iNNNkjj F3,r_3=Hl8 pn__7ۭ 6(d㢢5peeo˥}t:z>=.]v=Xx< wr?10p8d-YDzr8!?~Ĺp׭[4?uTXXhe\RR"ۭFlqlTVVfufmղeT]]m]dnwH֭[U:jjjdɒ^?#i_=O@ky DS^HR&icM6(ȷ_\| W iו',Sux{>,SMeȞי4mQ]qQKm=ϴrԪ)gj ¶IӽtO{ۖwgsآQ#~Wa>N(pl^ݡs|rKG,z}ЖA?MMiuUV<5(oνCfwhXe~D1M״[5ާyt9>OwiՊjlFLLwftllhCuF7|7-?ۛ^ЩyE;گmn՚M$vo -|phJgw`C+GW1S yvxz5iUةdU߲3C3n[5ݩ;*i{MfP԰Ϫ~z's)]󊂇{;HD/?_S}:')Q?RRɩO'^|2_d0 rx]:5fd {ү$$ܶl~M;Sg]-GK`a^=T.4*VԘj,C/fꝿ_k;ǫ2Ugk Zߍ˻3ҧf[lzu?iӤ f<-9i.פ ]6է ͆N-ݡ56[4i_Mi҄vxOVH%ҞJ[[dϑ&Mk҄@˳"WмNh4L׼Nf z\V4 qxhPK1گ۵yGρ!Ǹ>缢@S|u]0S.j{`A.!0 #{Tp~~56''z1龭%35Yf#qss|*8ǧ˦B\u>3\}b}SNem"McE;4v, %9,wd??GJZ99d3\ϽO{o9"5P>lRuv́ Qΐ7]}[*fwǿLΐ7KgOQlO;tD|sy^QԚg2C*s s\ [;Xy{ V?h*~3l0޲@;l]}V3-_~k{HQ׵clPe5̽C{d5A3|d>=MO:zF9bڲ~*8ǧI9^F>Je 0r]|||x3 C-~_l;ݮtvMrz ƻԏrr*h/HUy>K%%@za)ǂwV;ݣN }ָ6]?+IfoLl $ϟxLWC۸kWl|!{_/*/~ڹ2DQ>kv[15Qߺ3ren'XXۺlࡔv52FgTV%saogY/Dhh3HZ¯g6X>ٳI]ө9VIZLqĤ  /?KTTJ355iUw3JNa{\*^׉h{A{/ QD6hg[~Yr p]+g-]̿qC6L95hY2Hr {u`8g~yL;ߴ*[VsS;͡ &wjR=zo p|Yqj0N7D=9~=ů}T ZFD~5lo@>3o=Qqh{A*{2_,#~%̰\F4gOcF~՘nXxr{[9<(n,Ҽk:5SMAxfط&thVW:cD+u{e% %ƛǑX>(9.>@LZKlox4<9_]"spzR%q~vsXC-毾HF eϤ(D<ȷg_)`'Q?dv~G9p<1`ݟe4|tҶg~W^s$٪C5ާs|XyZd wI wT:CC@,(R#n/[]\k^]ZJ%='x̠\6g\@({?mF EvX*Q<g9өj/H8ʋc,Iy~ᘍZL^4hT_ 1/N͘ک9z ah_Ȳ{'T \Ts^2z Fs]{[̹"9$zMɸb1֐oc'sq]+$|G~eo!ꚐK~9өj/0 I7;"IK`}ͼBi|wCMFcxN`Πft ,6-jmh5Ғh9s#ƗIa8 &oDں5Δxmb1t&Ǟ5k0_ QŵurpK=__T]?+I*[O!=Gz~[^OsŽP*hGη;Ёf&M벩>j ћ 1Gнu5RLܫ;$^amtvGP4Ũhs),Oc̛巶]kn.ylfv{ڒv]~&CZniS;s2Œo㽿t='Rlۊ5ɸb1Ud_PC=ۯ{om7{ FܫtDS0:D=__T}|0Sh>GeQpn>,S/?mnUMDchfOn9d wyU;9?mn5ܺ3Wz۬X)x&Mmz}KH: siVĻԏ‹t ͷ}RU^o1 \s}Xc ^n,Ons| 5jLyKfۉ\ש*/m*޳Koh7ˁf^ @UfvԼN\lݙ#x#%t ɷ}RU^oI~I2dGnִ޿)G@op-{E6-?=Y̥ <\=@EW/a@^ 8%Iwlж7,_\43ފyp"1l+MMC@m/6~5gV6X.x_H=kՁyu\E~Em;:0$Pc IDAT3-@,fsj jQ`NPf >i0_*@E[[AњM:')١3&\4d䗤!Cp4]-e/Iڿc-)dָ~4 M4A`H M4A`H M4A`H$[;_'O8_0?X3u{zzzzzzzzzzzzy#_=5`$UV]VMY9'q0 !+$rFKK䀠OFR97e圤[.=tݺRSqSgjFR}Yjk_p8wq39 ST٣ǫy_pB9ܼOR V%@0 &@ i0 &@ i"CT~Q~?{(=Ml_.d@Se`i c#^Tw"8jB׽/?9UToe"ǂ}kR?ˤ/fwyԿ^Gg:sΜ=ze~P'U?ޗ1١]e!{l{ IR|FjQq3g/˻?GY)߶Mn78۴z=(#S/W66rA7-T#oR>N*`<0~^zYK=9&iC9^o y/oP,8q"c}wu{}c<ƞO*{ Mԅtu\'ѝT؞yGZҵt?]{Mտ[q(c ca=|{$pM9{A\Ǻj߱ց}PoPM=:u?MnN*`;}Oo*{=n앶{DV7~rC [7trǾLǿ' oZ|ӏur>_P1v?gjb-M?_߾qq[ttӛ;~/t8QzQUq|F5~1tޗζVP~˅C }y[Ï]_V^S7e>e啶p1ٶ=u/fo?Gtx~Vֆ^[nx[7>𣻎ǙieR00Dq"S/z'\|&`oY-lVB3߼{*-!TM9{^v%k<{_~ۍwg>n[hZ}?wtӹt,O࿙|Ы?gx﷓yɴtkZRݼ1_GG={_},NZX7LNsO=39ョ/fug^h=qṩccGtݺo3;᏿@gξ<7u? Ͻ Ͻ[(uCOs9{A{0 y}y{=U}y{Ʒn#ߺ~>󝽃*WϜ"2?xHwΧoomPΜ=67~<8w~X{F= Ͻo_4Fީ3_WYr;|o9wn5?oǿx~`^[zn|>¡WO~x_>hyۂs~kh=yhǺŷn(k{;NI m͠TpQ3 Ra}[}Oiebvڤ孴Vǟhze?f?IDԽ/?ӝOo2?oHCps=OAwz~Vpz'o=|WwqݼO3gww|pӛMO_?}㔶kzGw/` M߼hw>IЖzi>sǟ'{?sOC|@/+cl|]K/:6Iz~Vb_xS)I:}{왶Νc}}뾟q{xG!}";s>tt{y]xnJLìn{&x_G r]|oY /w~}NZT>6мC|DOu{{Mw.oh?s_x8'7$YN>l~ïutdt=WN$^xwzw%I6.vs}00`D q)q):F0`0"N10庮,˒$qFZ qvʊ/flۖi Paj}}]jUU(}$iiiIzښ~fyi4myn2JŎs^*4xup"@ض%)I PQɲ,/_t <[[`i9 ~-˒yJr|_LzW_}UF#u]MMM?WՎӶmJfffv Y[CZuueIcup!@eEuIہy* v횦v> Cַ52O8o|r)TUUU!亮\וeY$-//wR\.9*7cUU/uVG.TcrqqQ/RZ:11q(mͦankT3d/^ GC'ٗVl>0L?[5 HMB^ P}a0N{Vޏflvh߻hH!lrnS|GcWEj&I+][wbmmMv:팃 HnAZ^ Gζm]rE!mۚ$=[k}}]z]ijiimZYY$mPhi׽=}-JA)`Y4770 ELLHb\nv ̌8VWW HbvvVccc[CJ.//utIhKRQZ{J%>up!Ʊ @}_ccc,Ke)"uArk^qkrrR}_m˲,a qhd8Nc;lz]o}3zױ:`|Cҟ%o?Z׊O3D!'A^xwzw%I6.vs}ݛ=`D A #F0`0"`Db p $Rhqq㜫W4MMOO+U.$-,,h}}y_|QfqI0K/~"q|nl6+0}mv^?׆azO,& ` if=w{m[i* CY%dƮAlf*10y^z^*Ju0$mGR[VU$IzMZ8d2]<10amu뺒 =clllHjo00 !@U*IR>L&#q${w㛜02 kJߤsPE2MsJ⍍ t'Tp¹msUIiF3 677YYYa01p'm8kfz\.w_ퟓlmm  ZǪV}_;%oEm5I{f* ~T*e C ` ~ ߝ!qTmRVEQ A( CŞ%{&{v{ޣl?!CQTT(zV۶-4%Iz{4eY<ϓaIBWTuMNNv=ի2MSZ28QC#cUUYVJydo$,N*1T*J׽}3ǑuMViX|Xrܮ0Ji؛H0 h4v^uC e-˒eY=V oH$>};_Zi&($ N$}Ŏs޽{0`0"`D A #F0SL0 y+˲$IqhViccCqK\˗%I/f{ $Rhqq㺫W4MMOO+l:FuUծuڵQ)cAp?XZZyښyN۶$4%Ia*"Y%4` @ZMP(X,vԔ$ X٬J}j^iq<ϓ*j4mߏ˲,EQri*j}}qyy(433>3Hr g@ꫯӶm˲,륗^j 3/BjC_ /ƱKZ GQŎJFb6 U*I_W& Ą$M*`s\cMRAe||%&mѶmx^{0q2~-J(mr,KzguoVr-xuݴ5FI0y (qd^{010mWp*Iq흓*`0J]Ovimav Hwv/|C'i]˲ĭ~|q^<0^-3LZYT 4v|$VJ{㞗aY`;۶uwmk~~^T׏reYiйS _ux}}aYSL,innNa*"E⑏R,//u]9UqV*UՁ:ΰzX.MOO}ɲ,Y(TUg,z]"5[---]mmmMmuڵϋXAhmmm>vA?ǹw ͦۼRhqq㜫W4Ͷ1D($ɲ,/uEƆa(z~Z۶$4ۮo}_|54 CKKKie/ Gw>guӃ5<2M3ul6RIF PϮjjjJhii*rϚiV*Jmհm+6 ^}U51~լVi}}u]]|YvV;g۶eYK/)cUՎڶmJҞ~Ǚy(L:\NA MT67lc` 433(8ήHZ>GQŎЍFCbk8>>.q:1JR\VV$sڶ=5NִT*eT*wTr9@qfCg&o$lT*v8 >+m4iA-766:OxdFaZqÊC'٧qA~ٶ}_3 #۶[`yP'm$ ðl]M:`c$~éXMe4$u٭c:;I۶۝eYeirRm-0F0Nkuh\T(J۹fSRIvU˗uU---) gGQt(պLFɘmۚO#xyg.{u0{t:`aVq\.lŋrGiz~NZ1'ϐC0 0>cUU/u j {UD VUIr&&&T.*$05MSawlLd2|&&&T^tϼ\^ZJ"Z0NҶXұ{ڶ~ðljqqQƙLDk20^A( CW pRc踮+i}qYq׊flPj$mO$̷,khW*IR./ _czvd2W$mUi~r' 84h/Ij}14\ҒLT^?=rm֕+W4>>ڶyI;[^4M---U&ׯx P^t򪀓жP(ͥi׽-J|SA,+ O[Cz]re^^^VmϚܜ0TE2M3ݏ6"ŮҒjzA7xCr*Ji:o +J!Q8n:ICRQZ{J%04M(DZ F_eYihމ 4==-566^E P\v8cMNNj||\˶mY0 1߯j)Y|>eI8Xk=(lz]o}3zױDߐgI:}4[wtֵL8QIЯ^>]Iҭ+ܽ{w_f`0"`D A #F0SLQqlaaAGrYZMaH,˒iGzY333y { A h`d2/ueY,REj4VZ__g^!411!I Pz]id P&ojbȄp IЯ^>]Iҭ+ܽ{w_1޸T.!mkuuUX,p2b h44==fd0i4 pF0`0"N1FfDZ8GfNp!5;;\.'kj Ð$Y%4G= PPz饗FfNp!fϾLy~~^{Z\.0 GjNpBm44ݗ\.\.w\or٬,˒$aJ8 P>OQ8VFOMMibbeYl;nC&qI_vU≜\.a^4My'~~a~~^aʲ,K^8* @F#0 ---뗌q9#T,>0 EQl۶;dyރC&MZ?7 EQ$4ev[xRqRjfm[8r劂 PV֑~`X%qv=[hl* CY%u~o%{JxmA^<*պI[PܭҥKP6i+0 u^{u#P,U,dp'smi踰mkuuukޭn!qevZikY.__|*Gy8ma^TZzccc|'zNpIhwDP\K/z.I=AZQ ^krr9W^i/IZ[[6k||c\k[T\^?Fd2iVZMp;U*Y%4e?7AV<]|Ya*411!˲dz[VuE9+Wmx(c-J8zU0>CɖeP(hnn.}{{.ܜ&&&ҪJr({FzcTC t0ܵ3 6ݬ?}f333*J Peɲ,AK.i}}:u$Ǒ8޵!chmmMaqzŮU*Vc3 CZmZ-..ϵ,+}lW.kŞx# ˥l2MSmkuuUaU ebbB }2VWWeYl8 QNu]}j]ŋ2MS.]RHw*F@\V\bm4Z[[yXlKl6UT$}]QHZ?Kh$8b[+m;<%I龹`ccX2:ɴOcbi;L^0z>VG hLMMu]ϩT*-{9ɶm!4v~(8_t=7 {)ZlYVϐ,NݪY{Ԕ&&&$mq{sM鍢HiZ>$ @XTX>~$DZ*$ivvm*Ke'{ Ty._0 E,˒iZXXĄ,R&IC[IT*2MSo0a2MSRIBaW*r9ibb" T*][RGTؘoz.4Ӷн_4T#`ffFRIaʲ,Y t%U X.]RVSE2 CFC.]RZًZ[[K8g~q90 u-,,X,K ,IOf6p`?~n׺V|' 9 k+IyEv㜻wT A #F0`0"`DCʕ+ܔmL0`0"`Db .^(qE666T*񉞓qٶ-4ժry1 C|^ʲ,IRj4PZL&\.'e6rg9暬D]<<<Ct%,y,ЖZ V!!66aZv{pKD|)F襌f4<%ٲ-ge[;\>~$TUT8Nt-˲jloo˲,feYX;m]l"r]Wjɶmd22+rGAy,R68#벲"۶|ߗeYrGDbdL&U,e\Nah}}}eV%4JJ8G1(=l6d2;m]l"뺺~1jFdr9JKKKrGP(nGurr]W|^Bt:-۶yn߾nH$4???zX, +@u&:{A5jkER)鑝lVkkk*= Χ ] LFAP0 # 9úJ%79|n6}$@5feJ@m\zn\V\z-IuG=0=.`vSl}}I/T*%IjZ}!zdž6( ;{سt:/f8𹛦R0 %%#T*#G <ϓi,k1ӼӜ%C Cչd2m[j6j4t:#gFijL&庮DgpQ,u8eɶ#{yz]i T4 Sf5??/q̞T* \S,--Ec}W&Ш=~Ñ].\$=n*z뭷j$)A';7\Ն?*bc?I`` '7L4M޴tZ_|񅶷g"Qit:cN,=fs?BT/K( IDAT|4 CKKK/u])˲s. %IZ]] P:LFtz6Lj~~^[[[}_TJ|~|qd^ ?'La(GGũTs{{RX]b`` j5ݹsGlV˶mIc֎^%I_>1p7|sf``Ƅ{J:6!DBJR* t`1v[oVۥ/``mxs[oQ0 3f0``lookooODD Nn}LF{{{*晄|kG Wѐa$˲d&E P&Q2eY nh4TA9+++JRG~֖ףߗfǺBZ!۶=7Tf 0[^^~.rL4F5u$Aзwq>f*Ѿ\49( #;7gYH@a!qϧyn߾ T*L&3,v*J*JJ$J&r]WeiuuUoxNbQt#pұˣt:c H$&Ԇ#}sߥ=,|qg#_/( =vn JruOJV\[oV%I}'X,F|In7>W0$I^\4 %I)( õQn( 4^wT^KZTT$Iկw:|>T*V5VmXT*_z+:﨎o ;'AoYF4j!T/\ Q‘A|/|L&d2F%J8Nt8ylV>X3%IKґaz~q8r]W=:ƫa(Nkeee"5I$ZD"nZH$;00Sjܹl6+e۶Ojqlv9lص5qٶ?\VKiFݮZmnBb(u庮<ϓ,Ki G @BAr]WZm"{Z\.;wDwx}\gmmMw{&Ľ!iAeY{$˲ ֨;+޻.HYQ\׍a'W1ӂ!RIFClVm}udd8NtVufSfJ&2 Ca<娻x\v[[[[f*z뭷μWlRJ$,+Z_8yCqlVeEAiCd{9lTWmPP^W:7|fq5Mݾ}[(G{rt.?<_ EZ]8ako+Ivww}G㒤? y-,,(>ӗ_~9zsssZXXիWkv]Osz}o]3?x`Qιvu;?˥KtU꫊bѳwo˗/kaa!:?Sw׿utO?4z}7_;{n߳.k0 0pA?OopZXX~(,=?ϵt]u݁ҥK裏>;+kaaAe,fX/_G}4׻z;>@W^ݻw/n;ֽ!|wyGn8/\c<Bܣ\|9 jwRb؉r8ի}ǽN滔nssszw߻ 7ɓ'U9Qvr] v׾~w ΋aa *INg3zA}]70tUuݾIa ִ ?axn;^tIwލj?7|v'5ZXX?G ի}!oat:$u}]v3{;Z{X^K.ӧ#n^ׯ_vGy%}2 CW\˗|% {]Q͇pannNӟ&˗/,>70n]X[{8 :>\ٳg8ɓĽAd$ѣG}ݮDžꫯ^ >|(?}Tc_4zN^_~ݮy?|>`7tRF7hߏέVCuF[n zwƺߏ?8yaaaSa`?77wE}ݡF{pF00^}U}o ;Can݊O׍x=}Ktww/`裏X,v._~~( gF_3lwvv 0駟DAfwfwww"uWۍFKAjo8ɓx<:gs8Wg}>HAڻqJ 1uՁ{t ׯ_WQ8|r848tS(իz\@u]=x` fÇ[ӧOtbs ݻץ|ʕg?;ӧOu޽x<+W |g&jwwWX>9GǏ+\iB䇻wvv/a >JS^aDϭ>38` {qArI#lgɟ'7vѣGw^tl.S{za5;~藿?~'zA_=kkꫯ&n_}nѽ{ kvC}f~{=Dz7͉Oo{؏=҃t]ݻwo%QuR?|P}8v{o0#?K/Q \EuAt:M1t?D'?d]wJHq9 Zz?$}o[1|ͩ>``+Ep5]|yׯG?A@ f(0[^{5ݺuKALlًW_ݻwvvKJ|i f;ݣb}o!9- 믵꠻0 +2 Ca(u]jggGϞ=f0U6E?BP|߱O?Bw)`0#`F A 3f(0}b\ו82 Cy* H@ Ld2b(4%˲,r9u bQ[Td`0``dYFR4~\H黔zp:t`iiIdc*jaѾv"s`Yl>f{޾"APPP89a81D}_J(N"z]N)N"[[[}_TJ|o_`IrGLB`(HUPPXr]W}Y%4E000eͦfL&e Ðy*˪T* CST*Q{ A 3f0`0#`F%S:8J$2MSp*8Q`򖖖L&W<{c"B0Ms`rӡ0' 0VV/͛)]Jf0`0# "NkooObb.LF{{{ؘZ0\pa(kssb#B}_,˒?bhJEkkk}dPƉDB'HȶmB0I}!g9Ŷ07TV^3 #| {f2MSFc`T.'6<֯l\.Kұuagt^?&޶VkÝ۩K4IR}:>PyJ$$. kmOS` t:{px 8F@`ii) .GT*}#v-˒$u:Ƿe}.㆜x<ߍDŽk^3 #wkE,4|o`I}ekUՒmr' ɤ,˒yxhl(:WG4Ч]E˰a4㎕e;"Q}_i|{T*m[tz`$4ݿL0p ‰ Qq⴯o։ R 88ϣqB⓪rJR:Ña Ύ=) G J].}~ B{ps8pDt&!{~~^4M5l)cmG+4eYnmO%mmmIVWWw0N2p֖|W*Xtf2#k$iA|/N&uµLRٔym[```J%mnnq%Iy'˲djZԝyJ3+c'QIZ[[ӝ;wte٨sP(Ld ,˒8ܔyQ|TqUPPXr]7:7\qlRkT*]kkkm[ZV=js̭jf:{c^4tSjqqQZMbtk8jU?jf&\D]ܿ? mۖmcwP(P(h0htu֖l6J"dFε5#[*5asZ^^P(۳}^I^zj~ooO(s矫VkT"|׏c ``\ U/m/8o9g 0%خQ溮$s!awe*RPPݦ('0{-v[oVۥ bQXLmK~pNnS'L4MyZu9!o { A 3NbxqLF{{{ؘH(02r\ @v[z]Z"HtS}Z-y'08Ţ666d:C]=Sۥ`f Ltd2%ٶ0jjJ!LrfS}_m+P E0pAJl6yXL\NdRAjr]WoVT&뺲,KnT* )8LӔyj* `E0pA4MIm/^XLrGA8jYVWWJOR,8X,X,*J)Z-l6͡,E0pAxH$@EP,ejJREv%M&Z]]=oܸ!4vNy8p1ar]WT׏<6N/LHh۶|ܞ¡04R)bo}}00ɤVVVdZǻ+4eY.ݮ$)|~v[4Mgڒ$a(Nkee\ 00u,FsZ--//{~RΛRIrGdREkjrgY[[ӝ;wtehBn{\__eYrG?R=ms?.//U,h44L( ; ``L&}ik3mv{d20c h'`O%vy PȶmIREj6s8%Iq+g```GA _* hD1``GY%IJb`-, Bϳ92HT8#۶g>8)"vD:::mjZ {K@/ZDQ^G5 0uݕ0F FFA! {0 `'~G tttD$t =A {0 `'~G /iyؾ~]Օ1;j</S$8~w~ q˶m G͂m-q$I~KZx ``qe|z:f߂;Vwv߫SEQQgm*J{49-sL&2}nlQ(|85 E֖- }_#c$d2Q_٩iY0L& [/KY56ϳ9KBgKhw:~8Weasgf5~YXDq<`Stzz/[5ƨVɲSAJg<˶mEE4<;;sט|˂M^84Mg1ȶQ}ΥRIR5OwOu]ɲ=څyYm0T,v^P(jf}0;!MSZ-qX,\.rY*c}in, }h$ݾu.ዋ ٶvrh4R2mǑJdiXko{{{f$m:88PߟYm}WZ';}"v1fi6VT*ٶp8,qn|ˎ7Lttrr"t4uN&nkT*}.B`s͜ɺy4^˲\Uߗ8rgދܲjj {li(TgB e{]noo%.3:6EQJR4o }FM&řIuF$Iv?JgKwzoVՖ  VyشLEKgq>m>λa\.|E=$Id۶>lbu$p8ܙ%d}wͤi~/c̣ELEyx8^ݝNOO PJ$N~_?~뺺NϏpb|YJE Z|,Ϯ! mCVK''':99QRɗn4[<~>+y0l槈8_y:8K ik=ǬM{b:GUTy,˒eYXn7J^<[r^W @Yhndb(c<ϛY8"%Iϙu]7]6S9-z: mzEQo,Ka]D<]E{F-o$Og_[+* VWѠ :qtyy$I?<}\ 1F{1xI?O I͕ǹm~嗍M0gYv)^DV4tqq1`0]}c|~{qFA ^=4m{n)[D, X3D>}WTB!;Y6qttD {d20_/<ٶ8n) ;~"~K `? = ``y0 8lۖ$EQft0 U4utt777s}Y^obY4{3\DZ8ޖp(˲$IƘg- }ss3x<ы^*rGm+c}u]isTUU*ό1stn߳%~>- Cj5 Ù尯dRJ"cux4x<7ȶ$-;/~38V2ƨR}n%x=V(|_J%IZdvT*5J"Tk7`KtcBmn58󼹮mV}_qhh2H_V)h<\38~y4ys5tG*IǨT*jZvu]a8,f]~c0WaYV$t)݇fSI|גYGw0,8ovY }^EXtt9-ͶZ(k;- mY<$lۖ8o.`4ժ<[MEs3d7-888t?b6Iҷ~Urww}?t=ϓ1Fq/ kXmw2 TT,eY4͗^f[ C*8,MӼT*}ٶptLPXysVXHu,~@T,/%}3l u gKEOm/ltlf AH ` q `xTB!gtV@ym[qnS&?F}'`O`0˺|}p8T{t?TV庮 ކR`X%# lutpVK(tݮá$FJD:7P(zlpfْЖe)ٳq+cAϽ PAϡm6yyqq!u'˲,F#5|_>vs<ϓ1f~uVUU*ό1n?d81f}m9< Ţ,Z{idb(q־4ME*Jsx4kgο,Kgggr]Wүg]ו*Kgflqxϡ5ͺ===UB u5庮jFL'lyczFs;]{|.O5=KdYVfu8upK{?uh4RRO n ޸4Mg^\\ȶmGZ&uDZ>}t Ǐe۶gr0<:|}i<]fZL8NOOU,U.g;˅rXj6y-,IJDm@~?~:t~fǙ0~yfuL_&3w*[YR}hUVS+`u_IKlFgYY˖"L&t::99+s]ӝɺyCڬku]}9wf5],^6;*B!$QzO_:xP2I]~?W-<e$_Ϧ;is{{+IsfN_GV7}i. c5ND~_Vkn u.`T<[&McatphY>u㺁y @Y1ogj:~le ::xƘG^u~^xeyчfgהLe_Jv=At8n^`)]睞k\(t~~J4M.N6`4 5WoY*x\'$~iϟ纟wqqj6~ u-4C]˖v^NfSjO^5x;wjzERztpp ~&񢥯ﷵtSΖa6` ><rG%I2f!1flVF*T*yHl ,o 0Neam>TOOO\AQ$8/y) hD1[Jl$I(;C0 ]__},ZBӧOsþTXGGGo.jUJe3cnnnf>t:js?:LXei4l* |inn\.qٶ8v)/;x0ƥixnm3Ih[L \וhu*cc \x<뺪jFL&se38ΏQT 7.Mәԋ ٶvOuGxnl;溩W:|+Z}qFgYj /<XEY>>gYVTt+݇fSI|32EIHR\sgAnXte3Ypm K@/ZDQ/QH XM1V"^1Ff|Mo.mc/hh~ʖt:jJ͸Ԯk6uN/+9 $Ib<0M&IR3cdw}R~Ȃn۶U.\$I6wiHx˲T.uvv  `Haʶm]__+cY%۶jT=FǏ庮%oool6s5R]QܷjdnFneTy`X:<<ǑeYL&jJdXyڝofSI}c`5D^% +̾mo%`r,qdQ$FRF$ox?Ͽ5H1BNu~Iҿo>m/ltlf =A {0 `'`O =A {0 ``a+JaJ| ~G rvvb(IDzm[ZMٶM0C岊Ţ$Q^d2$ys X!JEjWF(@Xe#I sߏF#XxjU&"z,MDim?),V"^1FaGeY0]9!^@Px>Y-0qKl^fKD;"M<.JsO0C:$VqsJvHד*x}h4s$I4Ll6疊,KAT*#I9u^\\u\|㱎f1FJ*J~~_nWinB!?[~t">vrYȶR(|σ85 E̾jUJefcv:u}yN]6}Ӳ,a(KTD@~k̲%_|j]qvvb(>Աm[ZMٶmLjXXEcf˲tvv&ug纮\UXT=aJ_뺪T*M9}ӵ}_l-Nt޲ux?Zg{(*JDz]D}3p?ʶmg~xj58ӧcRjJ 0ZG`}5.Unʧ~PV8Vȷ,KZMAx.\- =FQV5s0 Xqtyy8l6g\^xYJ4ŅlV^kk93=-jfBh(:3W|-+inh0, }u>q7g>9di:bK! IDAT=JRZeݺ<:7gh4뀝L&{TS{ `,+ZtJ:A8$I;[uݹ-;$lί9xagԺazegךm:/eݺl9ޓ)=v K@/ZA2Q-y~Y$e u 38;1[ vf8ms{N=ooo)֭A~ o?,+ߗM뙽Cau]]]]i4i8vuo߉)aӺxƘ|euCn_Y(]emw=vMCvOsm;mߗ9nZUTT*~8Vi]C FF*e̲l!l::&oYX8Zt:O:L,z`k/QݝͦͦǑy @`o&u<37.[ZwYeldaͲfKN_:{6ٵ<|3[msigپz_vL&u]}!_% + `K4JXٝm/_:Î, \-u<ٶ$I2W4[u݅c3[>3 $݇-{m/X9<,% xsuy{0:$V̈́++MSEQ$I:>> V_si87>d2gn>υe\.l$=ftHZe}ϩg*su~?,%/~n.Oy=QUV\UjZ/iz0 %Ix2IT:>>8,KDv[I<mF#AcWwww:<pkeۨS3H$}7TW?)Ǝp'fÛ+ctxxsK!'?$7WO_6:63=y$Vrg3q$=/>f{"U*%I8ev>/3"ffv|X3`O =A {w=BAJEɲ,IR HiR$!v:==$%I8%Iu]yzN0!oQͻ}-R @>}h49F$L&j6se5-[|<h滫+c߫T*Rg:A lix.CuAZ8DZ\וrGseY:;;ymm)E5^ٙj1mmΏDZ㱌1*2̼_R纮*J>YG-XVygkP奌1*JsZM*c})OY˾k8n\.X,*IuM&|kǏm[ٱ}JVn+i6pnrz~K `Y$)I0NQIR;] $inh6PT$IVk&Fu>u]5%|5o9dǗSgK˖\b~x ``B ILǻ@\ו$`HK$2M*$˶m+Jz.{߸qCijmm\2@q}}]) Ca(} ŞƍKTij4*ˣLaLry*7f_\d ,ijT%I9%2l߲mqlΎ$%՞4͹8=^ka$Ut:*ˊH0bvrQ.|kaJz\J\f8'kgIS' xl6äiI=81wkZS |ŸEK밺+e۶ ÐigI7i<%*+I+++'N޽;=qR駟8.gZcn[;I;I2MSe:n'ٺ̳q# ̀eY'ƭ`\`=eK>㵁NTNðFn\⩫4ag+4EѱDixRL0 mnnŔ 0d|ߗi,K:q.$ٲD/u{aP((NKv:H1 CLFSёͦ$P(U(FqNdzR%N\{wl0;Qu]J%I#VUY,\ ,z.˲dFR^W6iw0a2MSJE|~j @fStZ[[[ PQ%mqr9YT*T'_$۲,KZ&`q)˪VE0d/j%^VNGkkkj6HankmmMFcPRIe)ioo:**j62 #jiggGkkkSQO[uUgrYwܑx (T׵v18rgZA EQV5p%'tz9JRw"`ȓ~s>/IyXM0dN%VK0DlVZU:VXL!KfAzK0D6k\bL K0, $H  K0, $H  K0, $H  K0, $H  K0, $H  K0, $H  K0, $H  K0, $HXZw\%@m cݽ0h<О (f*ۜi{9}}~?fO{LsLFoz]5Idylۖi PaI$P(}5 Ņ$q{xfr]74M05/u݁HHRiZϦiʲ,YU3%9٬$iggg(R$˲y<Ӎ71!tri*N+NuݞV2MST6KtR8/a*oOۯz 83w>s|˲_Zj&׌93 CIߌ&NN__yL>xm[2Mg>|88}~eY}?`Qƥꫯn'm[RIeT*Jhضt:T n޼u]qmnn.fNE666c|W=I('N{oVWWG pjڙ;mn4۶UV%/lLz׉:yBa/^lZ3~}QY28T*4M5 U*/cٶ$g}~XZN*L<tz~}A EQ$q>_T*=x Hdz_iuqZ+*X_j55MIk8_O#1hsq~x(T."êxpPKn+$|4ЩTJ)3? t:rZ]]r]7ضh}iN* bx"J}y$0l*&I !{bPzتI6IkG{L&ӳ.dPVSNگẔNORʼ_< AQI+k[C<^ӽj$) 2 CA\.+& Z6P}+˲K/iuuU\Ne-xk"ϋI'}n4o׉8v=,Nxm5SUd c~Sݽ=ܝ___W. ˲tppΎ,*306N8$1%%0SWz+56 #I.Kxra8۟뺪VIR$k c'di* 4͢㸮+I Sn{*u777D,qpw%q\r9U*'/b^w{L?iߏI?M8noo8"q:*=,R&Y~}{yoݸqCijmm/g2^9:X$TRLJREɺt 8n2{8,4{ύN ;$qrqYLVE pc\NilMjc:O%]1C Hα?Nn>A ]rعUNGrYQL}Qy ݻn;nq/;SV*s!Nu_4ӯlĢ$c袮u_(:/2^~~ttqmmm< L:y\'/m H:~dqvm7qNw G0.|3Ϧi& (T,}1~9Iv:ӵ!˸JbxzTqzgnqMǢ{dWQ j4IQ$uߍ=AxƁ/ь_d`e,*s4T*Iڶ$ѽ(~۶;wmVZh9it:IRtp~i۪j~zҾqEpg"dYZ${~Ax؃8l6{/~꺮LY0I!YeI9ΤXe28n(f?v'bNgL[),4;74,3$f%Q]u?wvv>1Z쟋iO'J%i'-30lLߞi `\GGGIQPyJ.i0:7nH^{>u]mnn&IaFq*$M% 0y۝0lZ^7MhY¬(N^zwZ;NB'nIR6U&8/uDYҪ$5d3 CLF\<_']e9fٞf^4t0ыhoo/onny۶uK?'˴'m[CmT*%{"Icuݞa* ]{tϗmuoh|.RXJ\VZU:믿< VKJejs]W( C53mkYVP;j1tdj5yOsXׇG4݉LXOUsTRәGGG**J}_+ CEQvz+VVV8ݻ7w;˲uV-˲ymVnooz,<3k%}R dW^W6iw0L2T*3oT>h1: mnn& JDSwog~V7~`KgzF'Iw~\=A0M//"'dwzOlvlvlvlvlvlvlvlvlvlvlvlv>$ }0 `L{~ӳBrXV}? ; }~@s$H  K0, $H  K0, $H  K0, $H  K0ຮtpp95Mu:K((` T.-I+mV2.׮] 0A(d˶iƍ,KJM9#IuVP7 CU/٬|ߗeY Pj4Cg|j0 U׵7tƆ2L3^}Ձ5Go_z}]}R$YzR |O^,KRgX*g)q666MXZ53,٧mH[]]=q*J=Q;R~z i燮]ݽuw[6U>.>G۶$qlNRowZqڸ'Ͳ,yK?;\t&a^韃 PP:SfSa*N}a8l6;Rԓm6=9Bpℨ$Z>oEj6j6=NzNi0@8ֽ6e'ULړ+Liömx݉㞅0/ {<7PVKꥫW:N~n6I:^{SN{c_Aܝޟ$jja!woy;ӓP>::cZJnFCa*ͪP(T*T* Tv'DSTT*n}q sfU;N\:NOBAQVcgXTKnZmdUfzt7nܘٺ>IrT*?qx)v>n'~OZaoX[;<.MO" x9jI۟iC1vsXSWXO#NdzEt㵕=S>W^S! `@Q^O֑.(J?gMN}N߾j b0z_4HfW=JnZIt>*OXVSV뺲m[&ӗ0 {\<$%= ݓ^v\mݺ_w]'6Q2o9lI?gjF;ض3-JO,}5#uǪV}_4M+kYi/AZL&$}' ܻ ~aTRWdt}ʶCRulpt:I:MC')7֝Wgrmm۶֞l6y^Ϛk,wd=磣hvqW_M~}K,SX6.>qE:` uU*$=Nٶݓ@Nn}?YOt}}]K۷ol&UF'f)˲fRAh4tƍ$0$`^zz=ik˲TVjkwߟ>i* dbq";AoqmO?mmmmIzqJ%9q@1MsQ(:u\[whS ` T׏zooO{{{{L%}_e{ZMGGGqF0WR믿>c;::ښ٬\M= tu$Q) ChL4 $W!Z-kqL\וiIV$Y:lZ4>xܳO^Ofj4IutYq PjZ:yI{X\$\.u]ٶS+.I?+W cIRw"+B cW P<ٶd8ZVm߷it% CEQ$˲xye+JIӲ,iY5g3n/JM?mq3nt:s_,KiN%v[eq+++6euyxH$`jJLTP\Npy90 u֭I lN8Ν; ˲:q{D۶UVᩫ->.uum2и缺:ye~ZWUA$UnMr9U*Blv/U(0x׸9xVqLZOd2CWlqEiI׉q3(N+"mll$qgi=" SjVWQ }O\8UASQz ~ǹ^YYYsFv'F~(i yvvT'{'>q4͙&&/2qkժ|W:V>u]wf 0}L S?><<x~QkvWY5dʰu>|8y^+q*5M.MHgYwrza4s/Zeݻǎ~z>wOˬusλ?'=(^SmJӲm[v;I_DiI[2I~ê=n}ߗiT** ~_LhooOmVu]jxQ˲f(VR,KQG N|C'O)Z4N.Sa^oopQsf^~=I"jՋ`Ԛq_:;};rλ?'=Q3Gߌ+^]YYɔfStZaqaxcV%˲jE 0LA&ݮiHqǰ$Z|Vg~t:=2Q=>qs*.Ӟw79DIvLcu]aLq,Il~7͸8:k׮ MmݼyS׮]͛7fM{. 0GGGIuQPy[(FNtTדu'\MHM8*4dr}n'ktlVLf]M=8?&N!=NKRҧΫ:Ng*# P&T$oֵmQ$qt.rM:%dY|O~>::RJwRGrc `rj*"˲djJ9{j4ͤh,ĺ{8z.umr*^nܸ!qT\.xo8b3=eY}0Lq ߤͦ|WErG56kڹ,˒yVCp}\4,r7.~ꟳN/ueY0TX4z:N eYy'qEZB=qeEQ$dYVfƆ \MF|>\XMy_ElۖeYI\橓Ӟߤ|Ol4j|'=N+$ )|1'1qNâq2q79ƆדJT*3IwOWI}9I:]8q9q.wI$]rhݕeYZ[[cHgfvR-}u.GkX(J_  `b}}]mf۶٬ulX}_\NQ) C[Y#` $Z&ueYQEjZ#@cxHҧKh"//c `XLoy}7tBP??ףG$I{d6ApfTX Ba??7M3 /Zf~?>{t5דO>)Iz7/ƿo'`>nPϿWJ?߼W?7O&{}ֿ6noOF;w$ICw? ;я~81!I<\|{I3<$0|zng\o~v^|E&ӶOZroy}Sҳ>}{?Ùϳ|hoOIҳdNN$=Oɟ;o+իf[zWիq#o7?$۽|Dk>.̤/$采_=699你VVV5q.mя`UѓZcϺ{ÒO\s3@ի$luG]K%.L$I;?}Rk|詠=Jw~Փ7$yk\nuڵiуo[׆̫3heeE?g;CzKVK7S>곟>ڵkzw}+_X{/~mn{zg~V+++v횞}Y=x@#'=__ /7׿uo|Iٶ^xAOxqXp]vM/)ۻب;mrmO6±#u5l+:$M!J`+Atk^H+5ij@V(tC4fRj#EbtsSl'3`{>c~Ix9ؑ?^_aFdr tᷭYz{`d$5_㒊/Jƾ7|/1>=9k~=SW?ycUfjjJ>FT!HkkͶ r\ڽ{w\XKK:;;UQQ)l6566j߾}Z|sy<޽mS4iKYj cIn.I4?3*)sbgu\uIҺT 'g3s; * x敤nyUfS] FjgQ!fIRd588vUVVUlIü@ /jhh(&,޽{rҒ]J8p@C <ŋJl# t:xҥK1<::tSWo uy566&0:S1ccc 1xTj{~17::jΟdNg׮]Ky_|Y@@{v\g_O$9x*JիFiThtMr[;ӣ߯ SiS#yjcG8vL:(øSx㷚UnԬ?MO>*>?:5G6?)H5J3u-ϼ*I]LLs"Fִ1***5ErrK4.1^j5îDj5t`qll,湋WRVUF;ꂴ$i+>\cn̍Ly9U3[|7,bZR۫êس'.̔YuxKu)|fUvyuk}}yMFF㒉xэj֝Ⱦ&7=Tkw7Cg^}6ƿq\jmm5ÖT.6=#(|s%I>ɕqa]g@ aؕ, 4K]wN`^v_ؘFFF411WhY}se*NO4Qz)5Q ̌|qBYgnYUU{ {7?;;CP?J:O<.|W>S/S`Q0L퀍 1:ʧs!ߖE^_+q}}}Y+-6`uyԨVr8￟{'^Nx.zu}._ @r%Iw>Xw>k?;ӣ{57m{Q$|xPj瓭9egf5ͱ0ޕn%ꝡr{e\gJwSfmz)W]kPkpp0.tr)-ZUgQY8\Leq4cOB"o߾-׫tA^7/m%3 rKΝ;&[Ig^ >Ql@zF؛HWO@CIR՛o& XՙyxXc"!g+Ν]̌&Ӝ'ǣ7,D+9.ZxagG\+? !e,I[UWyy L r:kjx]4R#YJMMMqafS  r`0I9544Ľ_ݻrTYYu(iHUlQoA@R:~nZk.tfc||\R$tICB544,y9;vHR\P=Sب?`A}U[V3XFo*n[---qr̀tα^*Izcֵ2{cg> 'bTN(п5vt{z~m5o1F%Z;l#w%%+VxDpcwfVcI_ U=-mZ5::Q\.uvvklxp8rMڵkx,-[sj񋌟KuWښUgOտX'0?3uv9WuNLn ya\U"),I~f?6ϸNJpɓ+Ԙս|ApZ IDAT_v]/^]kzبӧOg\1G~71*(?<9"ݮqmEɶLrP jkk%en^&''x|Oe)h-} JK2rjkk`LqMM<{/^Ν˪n>V.^!&OHcsW6wu1@ `Y(hjjJVUCR$]j۷o/[Q*+,;`˪OuuuT ^k׮1@y(,{u@ Ck0F1Na]>q#40bY}s6>Vņ3R[yH7*ߢCqc ?ma{>ߞP'0 k[BA3-_F,gz)7:gyIҏutM?s e~ygU!3>ǓP0 am\HOSaD7K$I% PݰG*ՇV4BYXI țQֶ0굽^ , +--وn3]= 3y23k _<0^'FRTXizz=2ޮ${U#WXF,^m~uooJT:N/}N/w̛ա|%zDFb+C7zc^;ݱϽ-է$Ll yCZtHaoEǭ{"c*?U{=]>qe{Ny4Ζ{r]ǎ1\)zY\t.r]> ytv7tT0汧[l c {zyszk.ϗL7rVUuS\iEWunJ?~Y¶bCX[Yxlqeqsi{^?:..,K>{oG;oi[I쯻*+%+jKUH=Ac_H<﹮垇\uZ> R-:$iF%^:.؟<2zBWO{M_([ ~/o"UaWLߢi߉AplltJϺ.=jTXޚ(7 q2cBY˼ߍM-x1=#y[|2Ŭq[2_OrIu'z4͔zc*P\cb*#bkr疪~u4Cj  /^9>Fkr=nrJ:Њ cǏ˓;=1̡~HH'B)[fΖ{r]KqgyWշ#m7ձqU+%:\~s S˥bKj~+ >}D"~ρKcсGJc[>~]xᮿDQȋm/ɞ2VZXGW֩FͥbOt,fvzBy垇\u|}1 Q]Z/S ww+1ˋ%1=#]*,]F5wg:6Ԭ:N0'Hptϒr=n%ݜXR^-+V^{ئd-<䳮 !Q~>\-QKp byDF-ЗYV*M삅 {O7%f݊ yB:_T3P8*f{oLNZ;u]qQcfIw%\^DْU.%nMdONɽ}^May/SrǼn"- u 43"ޔuttoDXdǜGb9;B8n=s1-c/Yum޶ՇF2Yϝ=o`յ>{(?7h=;+x~mӛa<,u|<KO~_:U!R1\bm aonE;!w^3|0lc®"P8Jus昿qIo钵 /umX ,ioiLo4wsH龯[%fks)Ҋ7:c_oLVl~u42VlF-"缵*lο^^bxYbsPV56RdDٌrJ9_L@?"n,z\3 mGҚ3#Ϗ/gSe?*B~U}i<6%y}m DŽtTY߮ҸؠNj3e%/\\sV6e=x.32q~]+{T{޴襎ytkKUX"A-_F,g|2GB-a릯D~>I\q([>^=N0'wsH[-_IA]:51 e[tkb> 3 * 6) & 0x3F]; encoded_data[j++] = base64_enct[(triple >> 2 * 6) & 0x3F]; encoded_data[j++] = base64_enct[(triple >> 1 * 6) & 0x3F]; encoded_data[j++] = base64_enct[(triple >> 0 * 6) & 0x3F]; } for (int i = 0; i < base64_modt[input_length % 3]; i++) encoded_data[*output_length - 1 - i] = '='; return encoded_data; } unsigned char *base64_decode(const char *data, size_t input_length, size_t *output_length) { if (NULL == base64_dect) base64_build_dect(); if (input_length % 4 != 0) return NULL; *output_length = input_length / 4 * 3; if (data[input_length - 1] == '=') (*output_length)--; if (data[input_length - 2] == '=') (*output_length)--; unsigned char *decoded_data = salloc(*output_length); for (int i = 0, j = 0; i < input_length;) { uint32_t sextet_a = data[i] == '=' ? 0 & i++ : base64_dect[(unsigned char)data[i++]]; uint32_t sextet_b = data[i] == '=' ? 0 & i++ : base64_dect[(unsigned char)data[i++]]; uint32_t sextet_c = data[i] == '=' ? 0 & i++ : base64_dect[(unsigned char)data[i++]]; uint32_t sextet_d = data[i] == '=' ? 0 & i++ : base64_dect[(unsigned char)data[i++]]; uint32_t triple = (sextet_a << 3 * 6) + (sextet_b << 2 * 6) + (sextet_c << 1 * 6) + (sextet_d << 0 * 6); if (j < *output_length) decoded_data[j++] = (triple >> 2 * 8) & 0xFF; if (j < *output_length) decoded_data[j++] = (triple >> 1 * 8) & 0xFF; if (j < *output_length) decoded_data[j++] = (triple >> 0 * 8) & 0xFF; } return decoded_data; } void base64_build_dect() { base64_dect = malloc(256); for (int i = 0; i < 64; i++) base64_dect[(unsigned char)base64_enct[i]] = i; } void base64_cleanup() { if (NULL != base64_dect) free(base64_dect); } qman-1.5.1/src/base64.h000066400000000000000000000021011510660157000144710ustar00rootroot00000000000000// Base64 encoding and decoding (definition) #ifndef BASE64_H #define BASE64_H #include "lib.h" // // Global variables // // Encoding table extern char base64_enct[]; // Decoding table extern char *base64_dect; // Modulo table; helper for `base64_encode()` extern int base64_modt[]; // // Functions // // Return the base64-encoded version of `data` (of size `input_length`) in a // freshly allocated buffer, and put the size of said buffer in `output_length` extern char *base64_encode(const unsigned char *data, size_t input_length, size_t *output_length); // Return the base64-decoded version of `data` (of size `input_length`) in a // freshly allocated buffer, and put the size of said buffer in `output_length` extern unsigned char *base64_decode(const char *data, size_t input_length, size_t *output_length); // Allocate memory for and populate `base64_dect` extern void base64_build_dect(); // Deallocate memory used by `base64_dect` extern void base64_cleanup(); #endif qman-1.5.1/src/cli.c000066400000000000000000000113261510660157000141600ustar00rootroot00000000000000// Command line interface (implementation) #include "lib.h" // // Helper macros and functions // // Helper of `print_page()`. Return a statically allocated string that contains // a terminal escape sequence that matches the color of `link`. wchar_t *link_escseq(link_t link) { switch (link.type) { case LT_MAN: return L"\e[1;32m"; break; case LT_HTTP: return L"\e[1;35m"; break; case LT_EMAIL: return L"\e[1;35m"; break; case LT_FILE: return L"\e[1;34m"; break; default: case LT_LS: return L"\e[1;33m"; break; } } // // Functions (generic) // void init_cli() { unsigned cols; // terminal width according to the environment // Set `cols` to the value indicated by the environment cols = getenvi("MANWIDTH"); if (0 == cols) cols = getenvi("COLUMNS"); // If unable to read anything from the environment, set `cols` using an // `ioctl()` call (or set it to 80 if that doesn't work either) if (0 == cols) { struct winsize ws; if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == 0) cols = ws.ws_col; else if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == 0) cols = ws.ws_col; else if (ioctl(STDERR_FILENO, TIOCGWINSZ, &ws) == 0) cols = ws.ws_col; else cols = 80; } config.layout.main_width = cols; } bool inside_term() { if (config.misc.cli_force_color) return true; else return isatty(STDOUT_FILENO); } void print_page(const line_t *lines, unsigned lines_len) { unsigned ln, c, l; // current line number, character number, link number bool in_link = false; // current character is inside a link bool has_hyph_link = false; // there's a hyphenated link from the previous line link_t hyph_link; // said hyphenated link wchar_t *reg_escseq = L""; // sequence to return from non-regular to regular text // For each line... for (ln = 0; ln < lines_len; ln++) { if (inside_term()) { // If inside a terminal, format the line's text using terminal escape // sequences // For each line character... l = 0; for (c = 0; lines[ln].text[c] != L'\0' && c < lines[ln].length; c++) { // Colorize text inside links if (has_hyph_link && c == hyph_link.start_next) { // Hyphenated link (from previous line) start in_link = true; fputws(link_escseq(hyph_link), stdout); } else if (has_hyph_link && c == hyph_link.end_next) { // Hyphenated link (from previous line) end in_link = false; has_hyph_link = false; fputws(L"\e[0;39m", stdout); } else if (l < lines[ln].links_length && c == lines[ln].links[l].start) { // Link start in_link = true; fputws(link_escseq(lines[ln].links[l]), stdout); } else if (l < lines[ln].links_length && c == lines[ln].links[l].end) { // Link end in_link = false; fputws(L"\e[0;39m", stdout); if (lines[ln].links[l].in_next) { has_hyph_link = true; hyph_link = lines[ln].links[l]; } l++; } // For text that is outside links, make text // regular/bold/italic/underline as required if (!in_link) { if (bget(lines[ln].reg, c)) { // Regular fputws(reg_escseq, stdout); reg_escseq = L""; } else if (bget(lines[ln].bold, c)) { // Bold fputws(L"\e[1m", stdout); reg_escseq = L"\e[0m"; } else if (bget(lines[ln].italic, c)) { // Italic fputws(L"\e[3m", stdout); reg_escseq = L"\e[23m"; } else if (bget(lines[ln].uline, c)) { // Underline fputws(L"\e[4m", stdout); reg_escseq = L"\e[24m"; } } // Print the character fputwc(lines[ln].text[c], stdout); } // The code above might ignore links that end at the very end of their // line, therefore we handle them here if (in_link) { in_link = false; fputws(L"\e[0;39m", stdout); if (l >= 1 && l - 1 < lines[ln].links_length && lines[ln].links[l - 1].in_next) { has_hyph_link = true; hyph_link = lines[ln].links[l - 1]; } } } else { // Otherwise, print the line's text without formatting fputws(lines[ln].text, stdout); } // At line end, restore text to regular and print a newline fputws(reg_escseq, stdout); fputwc(L'\n', stdout); } } // // Functions (handlers) // // Main handler for the CLI void cli() { configure(); late_init(); init_cli(); populate_page(); if (err) winddown(ES_NOT_FOUND, err_msg); print_page(page, page_len); } qman-1.5.1/src/cli.h000066400000000000000000000011631510660157000141630ustar00rootroot00000000000000// Command line interface (definition) #ifndef CLI_H #define CLI_H #include "lib.h" // // Functions (generic) // // Initialize the CLI. Currently, this function just snifs the number of columns // into `config.layout.main_width`. extern void init_cli(); // If `config.misc.cli_force_color` is true, return true. Otherwise, return the // return value of `isatty()`. extern bool inside_term(); // Print the contents of `lines` (of length `lines_len`) to standard output extern void print_page(const line_t *lines, unsigned lines_len); // // Functions (handlers) // // Main handler for the CLI extern void cli(); #endif qman-1.5.1/src/compile_commands.json000066400000000000000000000171371510660157000174570ustar00rootroot00000000000000[ { "directory": "/home/plp/Documents/Development/C/qman/build", "command": "ccache cc -Isrc/qman.p -Isrc -I../src -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -O0 -g -DQMAN_GZIP=true -DQMAN_BZIP2=true -DQMAN_LZMA=true -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 -MD -MQ src/qman.p/meson-generated_.._config.c.o -MF src/qman.p/meson-generated_.._config.c.o.d -o src/qman.p/meson-generated_.._config.c.o -c src/config.c", "file": "src/config.c", "output": "src/qman.p/meson-generated_.._config.c.o" }, { "directory": "/home/plp/Documents/Development/C/qman/build", "command": "ccache cc -Isrc/qman.p -Isrc -I../src -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -O0 -g -DQMAN_GZIP=true -DQMAN_BZIP2=true -DQMAN_LZMA=true -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 -MD -MQ src/qman.p/util.c.o -MF src/qman.p/util.c.o.d -o src/qman.p/util.c.o -c ../src/util.c", "file": "../src/util.c", "output": "src/qman.p/util.c.o" }, { "directory": "/home/plp/Documents/Development/C/qman/build", "command": "ccache cc -Isrc/qman.p -Isrc -I../src -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -O0 -g -DQMAN_GZIP=true -DQMAN_BZIP2=true -DQMAN_LZMA=true -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 -MD -MQ src/qman.p/eini.c.o -MF src/qman.p/eini.c.o.d -o src/qman.p/eini.c.o -c ../src/eini.c", "file": "../src/eini.c", "output": "src/qman.p/eini.c.o" }, { "directory": "/home/plp/Documents/Development/C/qman/build", "command": "ccache cc -Isrc/qman.p -Isrc -I../src -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -O0 -g -DQMAN_GZIP=true -DQMAN_BZIP2=true -DQMAN_LZMA=true -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 -MD -MQ src/qman.p/base64.c.o -MF src/qman.p/base64.c.o.d -o src/qman.p/base64.c.o -c ../src/base64.c", "file": "../src/base64.c", "output": "src/qman.p/base64.c.o" }, { "directory": "/home/plp/Documents/Development/C/qman/build", "command": "ccache cc -Isrc/qman.p -Isrc -I../src -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -O0 -g -DQMAN_GZIP=true -DQMAN_BZIP2=true -DQMAN_LZMA=true -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 -MD -MQ src/qman.p/program.c.o -MF src/qman.p/program.c.o.d -o src/qman.p/program.c.o -c ../src/program.c", "file": "../src/program.c", "output": "src/qman.p/program.c.o" }, { "directory": "/home/plp/Documents/Development/C/qman/build", "command": "ccache cc -Isrc/qman.p -Isrc -I../src -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -O0 -g -DQMAN_GZIP=true -DQMAN_BZIP2=true -DQMAN_LZMA=true -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 -MD -MQ src/qman.p/cli.c.o -MF src/qman.p/cli.c.o.d -o src/qman.p/cli.c.o -c ../src/cli.c", "file": "../src/cli.c", "output": "src/qman.p/cli.c.o" }, { "directory": "/home/plp/Documents/Development/C/qman/build", "command": "ccache cc -Isrc/qman.p -Isrc -I../src -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -O0 -g -DQMAN_GZIP=true -DQMAN_BZIP2=true -DQMAN_LZMA=true -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 -MD -MQ src/qman.p/tui.c.o -MF src/qman.p/tui.c.o.d -o src/qman.p/tui.c.o -c ../src/tui.c", "file": "../src/tui.c", "output": "src/qman.p/tui.c.o" }, { "directory": "/home/plp/Documents/Development/C/qman/build", "command": "ccache cc -Isrc/qman.p -Isrc -I../src -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -O0 -g -DQMAN_GZIP=true -DQMAN_BZIP2=true -DQMAN_LZMA=true -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 -MD -MQ src/qman.p/qman.c.o -MF src/qman.p/qman.c.o.d -o src/qman.p/qman.c.o -c ../src/qman.c", "file": "../src/qman.c", "output": "src/qman.p/qman.c.o" }, { "directory": "/home/plp/Documents/Development/C/qman/build", "command": "ccache cc -Isrc/qman_tests.p -Isrc -I../src -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -O0 -g -DQMAN_GZIP=true -DQMAN_BZIP2=true -DQMAN_LZMA=true -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 -MD -MQ src/qman_tests.p/meson-generated_.._config.c.o -MF src/qman_tests.p/meson-generated_.._config.c.o.d -o src/qman_tests.p/meson-generated_.._config.c.o -c src/config.c", "file": "src/config.c", "output": "src/qman_tests.p/meson-generated_.._config.c.o" }, { "directory": "/home/plp/Documents/Development/C/qman/build", "command": "ccache cc -Isrc/qman_tests.p -Isrc -I../src -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -O0 -g -DQMAN_GZIP=true -DQMAN_BZIP2=true -DQMAN_LZMA=true -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 -MD -MQ src/qman_tests.p/util.c.o -MF src/qman_tests.p/util.c.o.d -o src/qman_tests.p/util.c.o -c ../src/util.c", "file": "../src/util.c", "output": "src/qman_tests.p/util.c.o" }, { "directory": "/home/plp/Documents/Development/C/qman/build", "command": "ccache cc -Isrc/qman_tests.p -Isrc -I../src -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -O0 -g -DQMAN_GZIP=true -DQMAN_BZIP2=true -DQMAN_LZMA=true -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 -MD -MQ src/qman_tests.p/eini.c.o -MF src/qman_tests.p/eini.c.o.d -o src/qman_tests.p/eini.c.o -c ../src/eini.c", "file": "../src/eini.c", "output": "src/qman_tests.p/eini.c.o" }, { "directory": "/home/plp/Documents/Development/C/qman/build", "command": "ccache cc -Isrc/qman_tests.p -Isrc -I../src -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -O0 -g -DQMAN_GZIP=true -DQMAN_BZIP2=true -DQMAN_LZMA=true -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 -MD -MQ src/qman_tests.p/base64.c.o -MF src/qman_tests.p/base64.c.o.d -o src/qman_tests.p/base64.c.o -c ../src/base64.c", "file": "../src/base64.c", "output": "src/qman_tests.p/base64.c.o" }, { "directory": "/home/plp/Documents/Development/C/qman/build", "command": "ccache cc -Isrc/qman_tests.p -Isrc -I../src -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -O0 -g -DQMAN_GZIP=true -DQMAN_BZIP2=true -DQMAN_LZMA=true -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 -MD -MQ src/qman_tests.p/program.c.o -MF src/qman_tests.p/program.c.o.d -o src/qman_tests.p/program.c.o -c ../src/program.c", "file": "../src/program.c", "output": "src/qman_tests.p/program.c.o" }, { "directory": "/home/plp/Documents/Development/C/qman/build", "command": "ccache cc -Isrc/qman_tests.p -Isrc -I../src -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -O0 -g -DQMAN_GZIP=true -DQMAN_BZIP2=true -DQMAN_LZMA=true -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 -MD -MQ src/qman_tests.p/cli.c.o -MF src/qman_tests.p/cli.c.o.d -o src/qman_tests.p/cli.c.o -c ../src/cli.c", "file": "../src/cli.c", "output": "src/qman_tests.p/cli.c.o" }, { "directory": "/home/plp/Documents/Development/C/qman/build", "command": "ccache cc -Isrc/qman_tests.p -Isrc -I../src -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -O0 -g -DQMAN_GZIP=true -DQMAN_BZIP2=true -DQMAN_LZMA=true -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 -MD -MQ src/qman_tests.p/tui.c.o -MF src/qman_tests.p/tui.c.o.d -o src/qman_tests.p/tui.c.o -c ../src/tui.c", "file": "../src/tui.c", "output": "src/qman_tests.p/tui.c.o" }, { "directory": "/home/plp/Documents/Development/C/qman/build", "command": "ccache cc -Isrc/qman_tests.p -Isrc -I../src -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -O0 -g -DQMAN_GZIP=true -DQMAN_BZIP2=true -DQMAN_LZMA=true -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 -MD -MQ src/qman_tests.p/qman_tests.c.o -MF src/qman_tests.p/qman_tests.c.o.d -o src/qman_tests.p/qman_tests.c.o -c ../src/qman_tests.c", "file": "../src/qman_tests.c", "output": "src/qman_tests.p/qman_tests.c.o" } ] qman-1.5.1/src/config.c.cog000066400000000000000000001017111510660157000154230ustar00rootroot00000000000000// Configuration and configuration file handling (implementation) #include "lib.h" // // Global variables // config_t config; /*[[[cog import cog import config_def cog.outl("const char *keys_names[PA_QUIT + 1] = {") cog.outl(" \"null\",") for option, option_def in config_def.config_def["keys"].items(): if option == "quit": comma = "" else: comma = "," cog.outl(" \"" + option + "\"" + comma) cog.outl("};\n") cog.outl("const wchar_t *keys_help[PA_QUIT + 1] = {") cog.outl(" L\"Do nothing\",") for option, option_def in config_def.config_def["keys"].items(): (type, default_value, in_config, comment) = option_def if option == "quit": comma = "" else: comma = "," cog.outl(" L\"" + comment + "\"" + comma) cog.outl("};") ]]] [[[end]]]*/ // // Helper macros and functions // // Helper of `conf_init()` `conf_handler()`. Initialize the values of all color // pairs used for transitions. #define set_transition_colours \ config.colours.trans_mode_name = 100 * config.colours.stat_indic_mode.pair + \ config.colours.stat_indic_name.pair; \ config.colours.trans_name_loc = 100 * config.colours.stat_indic_name.pair + \ config.colours.stat_indic_loc.pair; \ config.colours.trans_prompt_help = \ 100 * config.colours.stat_input_prompt.pair + \ config.colours.stat_input_help.pair; \ config.colours.trans_prompt_em = \ 100 * config.colours.stat_input_prompt.pair + \ config.colours.stat_input_em.pair; // Helper of various `conf_...()` functions and methods. Return true if `src` // is equal to "true", "yes", or "1". Return false if it's equal to "false", // "no", or "0". Set `errno` to 0 if parsed successfully or to -1 if not. bool wcs2bool(const wchar_t *src) { if (0 == wcscasecmp(src, L"TRUE") || 0 == wcscasecmp(src, L"YES") || 0 == wcscmp(src, L"1")) { errno = 0; return true; } else if (0 == wcscasecmp(src, L"FALSE") || 0 == wcscasecmp(src, L"NO") || 0 == wcscmp(src, L"0")) { errno = 0; return false; } else { errno = -1; return false; } } // Helper of various `conf_...()` functions and methods. Return the appropriate // member of `systype_t` depending on `src`. "mandb" results in `ST_MANDB`, // "mandoc" in `ST_MANDOC`, "freebsd" in `ST_FREEBSD` and so on. systype_t wcs2systype(const wchar_t *src) { if (0 == wcscasecmp(src, L"mandb")) { errno = 0; return ST_MANDB; } else if (0 == wcscasecmp(src, L"mandoc")) { errno = 0; return ST_MANDOC; } else if (0 == wcscasecmp(src, L"freebsd")) { errno = 0; return ST_FREEBSD; } else if (0 == wcscasecmp(src, L"darwin")) { errno = 0; return ST_DARWIN; }else { errno = -1; return ST_ERROR; } } // Helper of various `conf_...()` functions and methods. Return `t_true` if // `src` is equal to "true", "yes", or "1". Return `t_false` if it's equal to // "false", "no", or "0". Return `t_auto` if it's equal to "auto" or "-". Set // `errno` to 0 if parsed successfully or to -1 if not. trit_t wcs2trit(const wchar_t *src) { if (0 == wcscasecmp(src, L"TRUE") || 0 == wcscasecmp(src, L"YES") || 0 == wcscmp(src, L"1")) { errno = 0; return t_true; } else if (0 == wcscasecmp(src, L"FALSE") || 0 == wcscasecmp(src, L"NO") || 0 == wcscmp(src, L"0")) { errno = 0; return t_false; } else if (0 == wcscasecmp(src, L"AUTO") || 0 == wcscmp(src, L"-")) { errno = 0; return t_auto; } else { errno = -1; return t_false; } } // Helper of various `conf_...()` functions and methods. Return the integer // value held into `src` as an integer, and set `errno` to 0. If `src` cannot be // parsed into an integer return `INT_MIN` and set `errno` to -1. int wcs2int(const wchar_t *src) { int val, vals_read; vals_read = swscanf(src, L"%d", &val); if (1 != vals_read) { errno = -1; return INT_MIN; } else { errno = 0; return val; } } // Helper of various `conf_...()` functions and methods. Return the ncurses // color that corresponds to `src`. Allowed values for `src` are "black", "red", // "green", "yellow", "blue", "magenta", "cyan", "white", a positive integer, or // "#rrggbb". Return -1 in case of parse error, or -2 if the terminal cannot // support such a color. // // NOTE: Setting `src` to a "#rrggbb" causes terminal colors to be re-defined. // We use an internal index to re-define colors, starting with color no. 255 and // decreasing by 1 every time `wcs2colour()` is called. wcs2colour(NULL)` resets // said index and should be called at the beginning of `configure()`. short wcs2colour(const wchar_t *src) { static short rgb_i = 255; // index for re-defined terminal colors // If `src` is NULL, reset `rgb_i` if (NULL == src) { rgb_i = 255; return 0; } // Try to parse `src` as integer. If successful, return it. const int srci = wcs2int(src); if (errno == 0 && srci >= 0) { if (tcap.colours < 256) { // Terminal does not support 256 colors; return -2 return -2; } return srci; } // If `src` matches a color name such as 'black', 'red', etc. return the // corresponding color. else if (0 == wcscasecmp(src, L"BLACK")) return COLOR_BLACK; else if (0 == wcscasecmp(src, L"RED")) return COLOR_RED; else if (0 == wcscasecmp(src, L"GREEN")) return COLOR_GREEN; else if (0 == wcscasecmp(src, L"YELLOW")) return COLOR_YELLOW; else if (0 == wcscasecmp(src, L"BLUE")) return COLOR_BLUE; else if (0 == wcscasecmp(src, L"MAGENTA")) return COLOR_MAGENTA; else if (0 == wcscasecmp(src, L"CYAN")) return COLOR_CYAN; else if (0 == wcscasecmp(src, L"WHITE")) return COLOR_WHITE; // Otherwise, try to parse `src` as '#rrggbb' and return the corresponding // color else { unsigned red = 0, green = 0, blue = 0; // New color values if (3 != swscanf(src, L"#%2x%2x%2x", &red, &green, &blue)) { // Unable to parse src; return -1 return -1; } else { if (! tcap.rgb) { // Terminal does not support 256 colors that can be re-defined; return // -2 return -2; } red = (red * 1000) / 256; green = (green * 1000) / 256; blue = (blue * 1000) / 256; init_color(rgb_i, red, green, blue); return rgb_i--; } } } // Helper of various `conf_...()` functions and methods. Return the ncurses key // mapping that corresponds to `src`. Return -1 in case of parse error. int wcs2ch(const wchar_t *src) { if (0 == wcscasecmp(src, L"KEY_UP")) return KEY_UP; else if (0 == wcscasecmp(src, L"KEY_DOWN")) return KEY_DOWN; else if (0 == wcscasecmp(src, L"KEY_LEFT")) return KEY_LEFT; else if (0 == wcscasecmp(src, L"KEY_RIGHT")) return KEY_RIGHT; else if (0 == wcscasecmp(src, L"KEY_PPAGE")) return KEY_PPAGE; else if (0 == wcscasecmp(src, L"KEY_NPAGE")) return KEY_NPAGE; else if (0 == wcscasecmp(src, L"KEY_HOME")) return KEY_HOME; else if (0 == wcscasecmp(src, L"KEY_END")) return KEY_END; else if (0 == wcscasecmp(src, L"ESC")) return '\e'; else if (0 == wcscasecmp(src, L"KEY_BREAK")) return KEY_BREAK; else if (0 == wcscasecmp(src, L"ETX")) return 0x03; else if (0 == wcscasecmp(src, L"KEY_ENTER")) return KEY_ENTER; else if (0 == wcscasecmp(src, L"LF")) return '\n'; else if (0 == wcscasecmp(src, L"KEY_BACKSPACE")) return KEY_BACKSPACE; else if (0 == wcscasecmp(src, L"BS")) return '\b'; else if (0 == wcscasecmp(src, L"HT")) return '\t'; else if (0 == wcscasecmp(src, L"SPACE")) return ' '; else if (0 == wcscasecmp(src, L"F1")) return KEY_F(1); else if (0 == wcscasecmp(src, L"F2")) return KEY_F(2); else if (0 == wcscasecmp(src, L"F3")) return KEY_F(3); else if (0 == wcscasecmp(src, L"F4")) return KEY_F(4); else if (0 == wcscasecmp(src, L"F5")) return KEY_F(5); else if (0 == wcscasecmp(src, L"F6")) return KEY_F(6); else if (0 == wcscasecmp(src, L"F7")) return KEY_F(7); else if (0 == wcscasecmp(src, L"F8")) return KEY_F(8); else if (0 == wcscasecmp(src, L"F9")) return KEY_F(9); else if (0 == wcscasecmp(src, L"F10")) return KEY_F(10); else if (0 == wcscasecmp(src, L"F11")) return KEY_F(11); else if (0 == wcscasecmp(src, L"F12")) return KEY_F(12); else if (src[0] >= 33 && src[0] <= 126 && 1 == wcslen(src)) return src[0]; else { // Unable to parse `src`; return -1 return -1; } } // Helper of `conf_handler()`. Return an if statement that becomes true if // `section` is equal to `s`. #define conf_section(s) if (0 == wcscmp(section, s)) // Helper of `conf_handler()`. Set `trgt` to the boolean stored in `value`, // using `wcs2bool()`, if `name` is equal to `n`. #define conf_set_bool(n, trgt) \ if (0 == wcscmp(name, n)) { \ const bool val = wcs2bool(value); \ if (0 != errno) { \ swprintf(errmsg, BS_SHORT, \ L"Error in %s line %d: Expected boolean, got '%ls'", \ path, line, value); \ winddown(ES_CONFIG_ERROR, errmsg); \ } \ trgt = val; \ return; \ } // Helper of `conf_handler()`. Set `trgt` to the `systype_t` stored in `value`, // using `wcs2systype()`, if `name` is equal to `n`. #define conf_set_systype(n, trgt) \ if (0 == wcscmp(name, n)) { \ const systype_t val = wcs2systype(value); \ if (0 != errno) { \ swprintf(errmsg, BS_SHORT, \ L"Error in %s line %d: '%ls' is not a supported system type", \ path, line, value); \ winddown(ES_CONFIG_ERROR, errmsg); \ } \ trgt = val; \ return; \ } \ // Helper of `conf_handler()`. Set `trgt` to the `trit_t` stored in `value`, // using `wcs2trit()`, if `name` is equal to `n`. #define conf_set_trit(n, trgt) \ if (0 == wcscmp(name, n)) { \ const trit_t val = wcs2trit(value); \ if (0 != errno) { \ swprintf(errmsg, BS_SHORT, \ L"Error in %s line %d: Expected ternary, got '%ls'", \ path, line, value); \ winddown(ES_CONFIG_ERROR, errmsg); \ } \ trgt = val; \ return; \ } \ // Helper of `conf_handler()`. Set `trgt` to the integer stored in `value`, // using `wcs2int()`, if `name` is equal to `n`. `min` and `max` can be used to // define a lower and an upper boundary for `value`, for error-checking // purposes. #define conf_set_int(n, trgt, min, max) \ if (0 == wcscmp(name, n)) { \ const int val = wcs2int(value); \ if (0 != errno) { \ swprintf(errmsg, BS_SHORT, \ L"Error in %s line %d: Expected integer, got '%ls'", \ path, line, value); \ winddown(ES_CONFIG_ERROR, errmsg); \ } \ if (val < min || val > max) { \ swprintf(errmsg, BS_SHORT, \ L"Error in %s line %d: Expected %d to %d, got %d", \ path, line, min, max, val); \ winddown(ES_CONFIG_ERROR, errmsg); \ } \ trgt = val; \ return; \ } // Helper of `conf_handler()`. Set `trgt` to a string copy of `value`, if `name` // is equal to `n`. #define conf_set_string(n, trgt) \ if (0 == wcscmp(name, n)) { \ const unsigned value_len = wcslen(value); \ if (NULL != trgt) \ free(trgt); \ if (NULL == value) \ trgt = NULL; \ else { \ trgt = walloc(value_len * 4 + 1); \ xwcstombs(trgt, value, value_len * 4 + 1); \ } \ return; \ } // Helper of `conf_handler()`. Set `trgt` to a wide string copy of `value`, if // `name` is equal to `n`. #define conf_set_wstring(n, trgt) \ if (0 == wcscmp(name, n)) { \ /* If the terminal doesn't support Unicode, reject all non-ASCII TUI * \ * drawing characters */ \ if (! tcap.unicode && 0 == wcscmp(section, L"chars") && \ (value[0] < 0 || value[0] > 127)) \ return; \ if (NULL != trgt) \ free(trgt); \ if (NULL == value) \ trgt = NULL; \ else \ trgt = xwcsdup(value); \ return; \ } // Helper of `conf_handler()`. Set `trgt` to the color that corresponds to // `value`, if `name` is equal to `n`. `value` is formatted as 2 color // definitions (as accepted by `wcs2colour()`) and one boolean, separated by // whitespace. #define conf_set_colour(n, trgt) \ if (0 == wcscmp(name, n)) { \ wchar_t fg[10], bg[10], bold[10]; \ unsigned nfg, nbg; \ bool nbold; \ const int vals_read = swscanf(value, L"%9ls%9ls%9ls", fg, bg, bold); \ if (3 != vals_read) { \ swprintf(errmsg, BS_SHORT, \ L"Error in %s line %d: Invalid color value '%ls'", \ path, line, value); \ winddown(ES_CONFIG_ERROR, errmsg); \ } \ nfg = wcs2colour(fg); \ if (-1 == nfg) { \ swprintf( \ errmsg, BS_SHORT, \ L"Error in %s line %d: Invalid foreground color '%ls'", \ path, line, fg); \ winddown(ES_CONFIG_ERROR, errmsg); \ } \ nbg = wcs2colour(bg); \ if (-1 == nbg) { \ swprintf( \ errmsg, BS_SHORT, \ L"Error in %s line %d: Invalid background color '%ls'", \ path, line, bg); \ winddown(ES_CONFIG_ERROR, errmsg); \ } \ nbold = wcs2bool(bold); \ if (0 != errno) { \ swprintf(errmsg, BS_SHORT, \ L"Error in %s line %d: Invalid boolean value '%ls'", \ path, line, bold); \ winddown(ES_CONFIG_ERROR, errmsg); \ } \ /* Apply colour changes only if the terminal supports it */ \ if (-2 != nfg && -2 != nbg) { \ trgt.fg = nfg; \ trgt.bg = nbg; \ trgt.bold = nbold; \ } \ return; \ } // Helper of `conf_handler()`. Set `trgt` to the set of key mappings that // correspond to `value`, if `name` is equal to `n`. `value` is formatted as 8 // key mapping definitions (as accepted by `wcs2ch()`) separated by whitespace. #define conf_set_key(n, trgt) \ if (0 == wcscmp(name, n)) { \ unsigned i; \ wchar_t *keys[8]; \ for (i = 0; i < 8; i++) \ keys[i] = walloca(BS_SHORT); \ const int keys_read = swscanf(value, L"%ls%ls%ls%ls%ls%ls%ls%ls", keys[0], \ keys[1], keys[2], keys[3], keys[4], keys[5], \ keys[6], keys[7]); \ if (0 == keys_read) { \ swprintf( \ errmsg, BS_SHORT, \ L"Error in %s line %d: Invalid key mapping value '%ls'", \ path, line, value); \ winddown(ES_CONFIG_ERROR, errmsg); \ } \ for (i = 0; i < keys_read; i++) { \ trgt[i] = wcs2ch(keys[i]); \ if (-1 == trgt[i]) { \ swprintf( \ errmsg, BS_SHORT, \ L"Error in %s line %d: Key mapping '%ls' is invalid", \ path, line, keys[i]); \ winddown(ES_CONFIG_ERROR, errmsg); \ } \ } \ for (i = keys_read; i < 8; i++) \ trgt[i] = 0; \ return; \ } // Helper of `conf_handler()`. Error out with a "no such option" error message. #define conf_no_such_option \ swprintf( \ errmsg, BS_SHORT, \ L"Error in %s line %d: No such option '%ls' in section '%ls'", \ path, line, name, section); \ winddown(ES_CONFIG_ERROR, errmsg); \ return; // Helper of `conf_handler()`. Error out with a "no such section" error message. #define conf_no_such_section \ swprintf(errmsg, BS_SHORT, \ L"Error in %s line %d: No such section '%ls'", \ path, line, section); \ winddown(ES_CONFIG_ERROR, errmsg); \ return; // Handler function for `eini()` void conf_handler(const wchar_t *section, const wchar_t *name, const wchar_t *value, const char *path, const unsigned line) { wchar_t errmsg[BS_SHORT]; // error message /*[[[cog for section, options in config_def.config_def.items(): cog.outl(" conf_section(L\"" + section + "\") {") for option, option_def in options.items(): (type, default_value, in_config, comment) = option_def # Option is not allowed in the config file; skip it if not in_config: continue # Option is allowed in the config file if type[0] == "bool": cog.outl(" conf_set_bool(L\"" + option + "\", config." + section + "." + option + ");") if type[0] == "systype": cog.outl(" conf_set_systype(L\"" + option + "\", config." + section + "." + option + ");") if type[0] == "trit": cog.outl(" conf_set_trit(L\"" + option + "\", config." + section + "." + option + ");") elif type[0] == "int": cog.outl(" conf_set_int(L\"" + option + "\", config." + section + "." + option + ", " + str(type[1]) + ", " + str(type[2]) + ");") elif type[0] == "string": cog.outl(" conf_set_string(L\"" + option + "\", config." + section + "." + option + ");") elif type[0] == "wstring": cog.outl(" conf_set_wstring(L\"" + option + "\", config." + section + "." + option + ");") elif type[0] == "colour": cog.outl(" conf_set_colour(L\"" + option + "\", config." + section + "." + option + ");") elif type[0] == "key": cog.outl(" conf_set_key(L\"" + option + "\", config." + section + "[PA_" + option.upper() + "]);") cog.outl(" conf_no_such_option;") cog.outl(" }") cog.outl() ]]] [[[end]]]*/ conf_no_such_section; } // Error function for `eini()` void error_handler(const wchar_t *error, const char *path, const unsigned line) { wchar_t errmsg[BS_SHORT]; // error message swprintf(errmsg, BS_SHORT, L"Error in %s line %d: %ls", path, line, error); winddown(ES_CONFIG_ERROR, errmsg); } // Helper of `configure()`. Initialize configuration in sections `[chars]` and // `[colours]` to sane defaults. void conf_init_chars_colours() { /*[[[cog pair = 10 for section, options in config_def.config_def.items(): if section in ["chars", "colours"]: for option, option_def in options.items(): (type, default_value, in_config, comment) = option_def if None != comment: cog.outl(" // Default value for: " + comment) else: cog.outl(" // Default value for: config." + section + "." + option) if type[0] == "bool": cog.outl(" config." + section + "." + option + " = wcs2bool(L\"" + default_value[0] + "\");") elif type[0] == "systype": cog.outl(" config." + section + "." + option + " = wcs2systype(L\"" + default_value[0] + "\");") elif type[0] == "trit": cog.outl(" config." + section + "." + option + " = wcs2trit(L\"" + default_value[0] + "\");") elif type[0] == "int": cog.outl(" config." + section + "." + option + " = wcs2int(L\"" + default_value[0] + "\");") elif type[0] == "string": cog.outl(" if (NULL != config." + section + "." + option + ")") cog.outl(" free(config." + section + "." + option + ");") if None == default_value: cog.outl(" config." + section + "." + option + " = NULL;") else: cog.outl(" config." + section + "." + option + " = xstrdup(\"" + default_value[0] + "\");") elif type[0] == "wstring": cog.outl(" if (NULL != config." + section + "." + option + ")") cog.outl(" free(config." + section + "." + option + ");") if None == default_value: cog.outl(" config." + section + "." + option + " = NULL;") else: cog.outl(" config." + section + "." + option + " = xwcsdup(L\"" + default_value[0] + "\");") elif type[0] == "colour": cog.outl(" config." + section + "." + option + ".fg = wcs2colour(L\"" + default_value[0] + "\");") cog.outl(" config." + section + "." + option + ".bg = wcs2colour(L\"" + default_value[1] + "\");") cog.outl(" config." + section + "." + option + ".bold = wcs2bool(L\"" + default_value[2] + "\");") cog.outl(" config." + section + "." + option + ".pair = " + str(pair) + ";") pair += 1 elif type[0] == "key": for i in range(8): if i < len(default_value): cog.outl(" config." + section + "[PA_" + option.upper() + "][" + str(i) + "] = wcs2ch(L\"" + default_value[i] + "\");") else: cog.outl(" config." + section + "[PA_" + option.upper() + "][" + str(i) + "] = 0;") cog.outl() ]]] [[[end]]]*/ set_transition_colours; } // Helper of `configure()`. Make sure that the configured paths of the `man`, // `apropos`, `whatis` and `groff` commands point to executables. void check_paths() { is_executable(config.misc.man_path); is_executable(config.misc.groff_path); is_executable(config.misc.whatis_path); is_executable(config.misc.apropos_path); } // // Functions // void conf_init() { /*[[[cog pair = 10 for section, options in config_def.config_def.items(): for option, option_def in options.items(): (type, default_value, in_config, comment) = option_def if None != comment: cog.outl(" // Default value for: " + comment) else: cog.outl(" // Default value for: config." + section + "." + option) if type[0] == "bool": cog.outl(" config." + section + "." + option + " = wcs2bool(L\"" + default_value[0] + "\");") elif type[0] == "systype": cog.outl(" config." + section + "." + option + " = wcs2systype(L\"" + default_value[0] + "\");") elif type[0] == "trit": cog.outl(" config." + section + "." + option + " = wcs2trit(L\"" + default_value[0] + "\");") elif type[0] == "int": cog.outl(" config." + section + "." + option + " = wcs2int(L\"" + default_value[0] + "\");") elif type[0] == "string": if None == default_value: cog.outl(" config." + section + "." + option + " = NULL;") else: cog.outl(" config." + section + "." + option + " = xstrdup(\"" + default_value[0] + "\");") elif type[0] == "wstring": if None == default_value: cog.outl(" config." + section + "." + option + " = NULL;") else: cog.outl(" config." + section + "." + option + " = xwcsdup(L\"" + default_value[0] + "\");") elif type[0] == "colour": cog.outl(" config." + section + "." + option + ".fg = wcs2colour(L\"" + default_value[0] + "\");") cog.outl(" config." + section + "." + option + ".bg = wcs2colour(L\"" + default_value[1] + "\");") cog.outl(" config." + section + "." + option + ".bold = wcs2bool(L\"" + default_value[2] + "\");") cog.outl(" config." + section + "." + option + ".pair = " + str(pair) + ";") pair += 1 elif type[0] == "key": for i in range(8): if i < len(default_value): cog.outl(" config." + section + "[PA_" + option.upper() + "][" + str(i) + "] = wcs2ch(L\"" + default_value[i] + "\");") else: cog.outl(" config." + section + "[PA_" + option.upper() + "][" + str(i) + "] = 0;") cog.outl() ]]] [[[end]]]*/ if (NULL == config.misc.program_name) #if defined(__GLIBC__) config.misc.program_name = program_invocation_short_name; #else config.misc.program_name = "qman"; #endif set_transition_colours; } void configure() { static bool ft = true; // true if this is the first invocation of // `configure()` char path[BS_LINE]; // path to config file FILE *fp = NULL; // file pointer to config file wchar_t errmsg[BS_SHORT]; // error message wcs2colour(NULL); // If this isn't the first invocation of `configure()`, call // `conf_init_chars_colours()` to reset UI characters and colors to their // default values if (ft) ft = false; else conf_init_chars_colours(); // Find and open the config file if (NULL != config.misc.config_path) { // `-C` option was used; try to open specified config file, and fail if not // possible strlcpy(path, config.misc.config_path, BS_LINE); fp = fopen(path, "r"); if (NULL == fp) { swprintf(errmsg, BS_SHORT, L"Unable to open config file '%s'", config.misc.config_path); winddown(ES_CONFIG_ERROR, errmsg); } } else { // No `-C` option; try to find and open a config file at the standard // locations // ${XCD_CONFIG_HOME}/qman/qman.conf const char *xch = getenv("XDG_CONFIG_HOME"); if (NULL != xch) { snprintf(path, BS_LINE, "%s/qman/qman.conf", xch); fp = fopen(path, "r"); } // ${HOME}/.config/qman/qman.conf if (NULL == fp) { const char *home = getenv("HOME"); if (NULL != home) { snprintf(path, BS_LINE, "%s/.config/qman/qman.conf", home); fp = fopen(path, "r"); } } // ${P}/qman/qman.conf, where ${P} is a path in ${XDG_CONFIG_DIRS} if (NULL == fp) { const char *xcd = getenv("XDG_CONFIG_DIRS"); if (NULL != xcd) { char *xcd_dup = xstrdup(xcd); char **xcd_paths = xcalloc(BS_SHORT, sizeof(char *)); unsigned xcd_count = split_path(&xcd_paths, xcd_dup); for (unsigned i = 0; i < xcd_count; i++) { snprintf(path, BS_LINE, "%s/qman/qman.conf", xcd_paths[i]); fp = fopen(path, "r"); if (NULL != fp) break; } free(xcd_dup); free(xcd_paths); } } // /qman.conf if (NULL == fp) { strlcpy(path, QMAN_CONFIGDIR "/qman.conf", BS_LINE); fp = fopen(path, "r"); } // /etc/xdg/qman/qman.conf if (NULL == fp) { strlcpy(path, "/etc/xdg/qman/qman.conf", BS_LINE); fp = fopen(path, "r"); } // /etc/qman/qman.conf if (NULL == fp) { strlcpy(path, "/etc/qman/qman.conf", BS_LINE); fp = fopen(path, "r"); } } // If we have a config file, process it if (NULL != fp) { fclose(fp); eini_init(); eini(&conf_handler, &error_handler, path); eini_winddown(); } set_transition_colours; check_paths(); } qman-1.5.1/src/config.h.cog000066400000000000000000000070141510660157000154310ustar00rootroot00000000000000// Configuration and configuration file handling (definition) #ifndef CONFIG_H #define CONFIG_H #include "lib.h" // // Types // // System type typedef enum { ST_ERROR, // parse error ST_MANDB, // `mandb` ST_MANDOC, // `mandoc` ST_FREEBSD, // FreeBSD `man` ST_DARWIN // macOS X `man` } systype_t; // A ternary bit, i.e. one that can take one of 3 values: `true`, `false`, or // `auto` typedef enum { t_false, t_true, t_auto } trit_t; // The color of a text character. Unlike ncurses colors, which are short // integers that correspond to a color value, `colour_t` combines foreground // color, background color, boldness, and a corresponding initialized ncurses // color pair. typedef struct { short fg; // foreground ncurses color no. bool bold; // true if foreground color is bold, false otherwise short bg; // background ncurses color no. short pair; // ncurses color pair no. } colour_t; /*[[[cog import cog import config_def cog.outl("// A program action") cog.outl("typedef enum {") cog.outl(" PA_NULL, // Do nothing (must be first member of `action_t`)") for option, option_def in config_def.config_def["keys"].items(): (type, default_value, in_config, comment) = option_def if option == "quit": comma = " " else: comma = "," cog.outl(" {:30s} // {}".format("PA_" + option.upper() + comma, comment)) cog.outl("} action_t;") cog.outl() for section, options in config_def.config_def.items(): cog.outl("// Configuration structure for section `" + section + "`") # Section "keys" is special and is defined as an array, not a structure if section == "keys": cog.outl("typedef int config_keys_t[PA_QUIT + 1][8];") cog.outl() continue # All other sections are defined as structures cog.outl("typedef struct {") first_option = True for option, option_def in options.items(): if first_option: first_option = False else: cog.outl() (type, default_value, in_config, comment) = option_def cog.outl(" // " + comment) if type[0] == "bool": cog.outl(" bool " + option + ";") elif type[0] == "int": cog.outl(" unsigned " + option + ";") elif type[0] == "systype": cog.outl(" systype_t " + option + ";") elif type[0] == "trit": cog.outl(" trit_t " + option + ";") elif type[0] == "string": cog.outl(" char *" + option + ";") elif type[0] == "wstring": cog.outl(" wchar_t *" + option + ";") elif type[0] == "colour": cog.outl(" colour_t " + option + ";") else: raise NameError("Unknown type '{}' for option '{}'".format(type[0], option)) cog.outl("} config_" + section + "_t;") cog.outl() cog.outl("// Main configuration structure"); cog.outl("typedef struct {"); for section, options in config_def.config_def.items(): cog.outl(" config_" + section + "_t " + section + ";") cog.outl("} config_t;"); ]]] [[[end]]]*/ // // Constants // // Alternate configuration file locations #define CONFIG_PATHS [ "~/.config/qman.conf", "/etc/xdg/qman.conf" ] // // Global variables // // Program configuration extern config_t config; // String representations for program actions extern const char *keys_names[PA_QUIT + 1]; // Help text for program actions and their corresponding key character mappings extern const wchar_t *keys_help[PA_QUIT + 1]; // // Functions // // Initialize configuration to sane defaults extern void conf_init(); // Locate and parse the configuration file, setting all members of `config` // appropriately extern void configure(); #endif qman-1.5.1/src/config_def.py000066400000000000000000000335371510660157000157120ustar00rootroot00000000000000""" Program configuration registry A dictionary that describes the configuration options used by the program. Structure: { section: { option: ( (type, [constraint], ...), (default_value, [default_value], ...), in_config, comment ) }, ... } Where: - section: one of the config file's sections (a string) - option: one of the options in said section (a string) - type: the option's type. One of the following strings: - "bool": a boolean - "systype": a system type (one of: "gnu", "mandoc", "freebsd") - "trit": a ternary ("true", "false", or "auto") - "int": an integer - "string": an 8-bit string - "wstring": a wide string - "colour": a color definition (see manual page) - "key": a key mapping (see manual page) - constraint: optional constraints for a type. For the time being, the only type that has constraints is "int", and those are used to define a minimum and a maximum value for the type. For example `("int", 0, 80)` defines an integer whose value must be between 0 and 80 inclusive. - default_value: a default value for the option. Must be specified as a tuple of strings. For types "string" and "wstring", default_value can also be None, in which case the option's default value will be set to NULL. - in_config: set to True if option is to be allowed in the config file, or to False if it's internal to the program - comment: a brief description of the option, that will be used to generate comments in the header file Note that section "keys" is special and can only contain options of type "key". Also, all other sections must contain options of any type other than "key". """ config_def = { "tcap": { "colours": (("int", -1, 256), ("-1",), True, "Number of colors supported by the terminal (set to -1 to auto-configure)"), "rgb": (("trit",), ("auto",), True, "Terminal colors can be re-defined"), "unicode": (("trit",), ("auto",), True, "Terminal supports Unicode"), "clipboard": (("trit",), ("auto",), True, "Terminal supports clipboard operations (OSC 52)"), "escdelay": (("int", 1, 10000), ("60",), True, "Terminal escape delay") }, "chars": { "sbar_top": (("wstring",), ("┬",), True, "Scrollbar top end"), "sbar_vline": (("wstring",), ("│",), True, "Scrollbar track line"), "sbar_bottom": (("wstring",), ("┴",), True, "Scrollbar bottom end"), "sbar_block": (("wstring",), ("█",), True, "Scrollbar knob"), "trans_mode_name": (("wstring",), ("│",), True, "Transition between the mode to name sections of the status bar"), "trans_name_loc": (("wstring",), ("│",), True, "Transition between the name and location sections of the status bar"), "trans_prompt_help": (("wstring",), (" ",), True, "Transition between the prompt and help sections of the status bar"), "trans_prompt_em": (("wstring",), (" ",), True, "Transition between the prompt and error message sections of the status bar"), "box_hline": (("wstring",), ("─",), True, "Dialog box horizontal line"), "box_vline": (("wstring",), ("│",), True, "Dialog box vertical line"), "box_tl": (("wstring",), ("┌",), True, "Dialog box top left corner"), "box_tr": (("wstring",), ("┐",), True, "Dialog box top right corner"), "box_bl": (("wstring",), ("└",), True, "Dialog box bottom left corner"), "box_br": (("wstring",), ("┘",), True, "Dialog box bottom right corner"), "arrow_up": (("wstring",), ("↑",), True, "Up arrow"), "arrow_down": (("wstring",), ("↓",), True, "Down arrow"), "arrow_lr": (("wstring",), ("↔",), True, "Left/right arrow") }, "colours": { "fallback": (("colour",), ("white", "black", "false"), False, "Fallback for B&W terminals"), "text": (("colour",), ("white", "black", "false"), True, "Page text"), "search": (("colour",), ("black", "white", "false"), True, "Matched search terms in page text"), "mark": (("colour",), ("white", "cyan", "false"), True, "Marked text"), "link_man": (("colour",), ("green", "black", "false"), True, "Links to manual pages"), "link_man_f": (("colour",), ("black", "green", "false"), True, "Links to manual pages (focused)"), "link_http": (("colour",), ("magenta", "black", "false"), True, "HTTP links"), "link_http_f": (("colour",), ("black", "magenta", "false"), True, "HTTP links (focused)"), "link_email": (("colour",), ("magenta", "black", "false"), True, "E-mail links"), "link_email_f": (("colour",), ("black", "magenta", "false"), True, "E-mail links (focused)"), "link_file": (("colour",), ("blue", "black", "false"), True, "File links"), "link_file_f": (("colour",), ("black", "blue", "false"), True, "File links (focused)"), "link_ls": (("colour",), ("cyan", "black", "false"), True, "In-page local search links"), "link_ls_f": (("colour",), ("black", "cyan", "false"), True, "In-page local search links (focused)"), "sb_line": (("colour",), ("yellow", "black", "true"), True, "Scrollbar track line"), "sb_block": (("colour",), ("yellow", "black", "true"), True, "Scrollbar knob"), "stat_indic_mode": (("colour",), ("yellow", "red", "true"), True, "Status bar mode section"), "stat_indic_name": (("colour",), ("white", "blue", "true"), True, "Status bar name section"), "stat_indic_loc": (("colour",), ("black", "white", "false"), True, "Status bar location section"), "stat_input_prompt": (("colour",), ("white", "black", "false"), True, "Status bar input prompt"), "stat_input_help": (("colour",), ("yellow", "black", "true"), True, "Status bar help section"), "stat_input_em": (("colour",), ("red", "black", "true"), True, "Status bar error message section"), "imm_border": (("colour",), ("yellow", "black", "true"), True, "Pop-up dialogs border"), "imm_title": (("colour",), ("yellow", "red", "true"), True, "Pop-up dialogs title"), "sp_input": (("colour",), ("white", "black", "false"), True, "Pop-up input dialog prompt"), "sp_text": (("colour",), ("cyan", "black", "false"), True, "Pop-up input dialog incremental search text"), "sp_text_f": (("colour",), ("white", "black", "false"), True, "Pop-up input dialog incremental search text (focused)"), "help_text": (("colour",), ("cyan", "black", "false"), True, "Help dialog entries text"), "help_text_f": (("colour",), ("black", "cyan", "false"), True, "Help dialog entries text (focused)"), "history_text": (("colour",), ("cyan", "black", "false"), True, "History dialog entries text"), "history_text_f": (("colour",), ("black", "cyan", "false"), True, "History dialog entries text (focused)"), "toc_text": (("colour",), ("cyan", "black", "false"), True, "TOC dialog entries text"), "toc_text_f": (("colour",), ("black", "cyan", "false"), True, "TOC dialog entries text (focused)"), "trans_mode_name": (("int", 0, 65535), ("0",), False, "Color pair for mode to name transition character"), "trans_name_loc": (("int", 0, 65535), ("0",), False, "Color pair for name to location transition character"), "trans_prompt_help": (("int", 0, 65535), ("0",), False, "Color pair for prompt to help transition character"), "trans_prompt_em": (("int", 0, 65535), ("0",), False, "Color pair for prompt to error_message transition character"), }, "keys": { "up": (("key",), ("KEY_UP", "y", "k"), True, "Scroll up one line"), "down": (("key",), ("KEY_DOWN", "e", "j"), True, "Scroll down one line"), "left": (("key",), ("KEY_LEFT", "<"), True, "Scroll left one tab stop"), "right": (("key",), ("KEY_RIGHT", ">"), True, "Scroll right one tab stop"), "pgup": (("key",), ("KEY_PPAGE", "b"), True, "Scroll up one page"), "pgdn": (("key",), ("KEY_NPAGE", "f"), True, "Scroll down one page"), "home": (("key",), ("KEY_HOME", "g"), True, "Go to page top"), "end": (("key",), ("KEY_END", "G"), True, "Go to page end"), "open": (("key",), ("KEY_ENTER", "LF", "o"), True, "Open focused link"), "open_apropos": (("key",), ("a"), True, "Perform apropos on the focused link"), "open_whatis": (("key",), ("w"), True, "Perform whatis on the focused link"), "sp_open": (("key",), ("O"), True, "Open a manual page using a dialog"), "sp_apropos": (("key",), ("A"), True, "Perform apropos using a dialog"), "sp_whatis": (("key",), ("W"), True, "Perform whatis using a dialog"), "index": (("key",), ("i", "I"), True, "Go to index (home) page"), "back": (("key",), ("KEY_BACKSPACE", "BS", "["), True, "Go back one step in history"), "fwrd": (("key",), ("]"), True, "Go forward one step in history"), "history": (("key",), ("s", "S"), True, "Show history menu"), "toc": (("key",), ("t", "T"), True, "Show table of contents"), "search": (("key",), ("/"), True, "Forward search"), "search_back": (("key",), ("?"), True, "Backward search"), "search_next": (("key",), ("n"), True, "Go to next search result"), "search_prev": (("key",), ("N"), True, "Go to previous search results"), "help": (("key",), ("h", "H"), True, "Show this help message"), "quit": (("key",), ("q", "Q"), True, "Exit the program") }, "mouse": { "enable": (("bool",), ("false",), True, "Enable mouse support"), "left_handed": (("bool",), ("false",), True, "Swap the left and right mouse buttons"), "left_click_open": (("bool",), ("false",), True, "Causes the left mouse button to invoke the OPEN action and/or act as the ENTER key") }, "layout": { "tui": (("bool",), ("true",), False, "True if we are in TUI mode, false if we are in CLI mode"), "fixedwidth": (("bool",), ("true",), False, "If true, don't change width to match the terminal size"), "width": (("int", 0, 400), ("80",), False, "Current terminal width"), "height": (("int", 0, 100), ("25",), False, "Current terminal height"), "sbar_width": (("int", 0, 100), ("1",), False, "Scrollbar width"), "stat_height": (("int", 0, 100), ("2",), False, "Status bar height"), "main_width": (("int", 0, 400), ("79",), False, "Main window width"), "main_height": (("int", 0, 100), ("23",), False, "Main window height"), "imm_width_narrow": (("int", 0, 400), ("54",), False, "Narrow pop-up dialogs width"), "imm_width_wide": (("int", 0, 400), ("54",), False, "Wide pop-up dialogs width"), "imm_height_short": (("int", 0, 100), ("6",), False, "Short pop-up dialogs height"), "imm_height_long": (("int", 0, 100), ("10",), False, "Long pop-up dialogs height"), "lmargin": (("int", 0, 200), ("2",), True, "Left margin size"), "rmargin": (("int", 0, 200), ("2",), True, "Right margin size"), "tabstop": (("int", 0, 100), ("8",), True, "Number of characters in a tab stop"), "sbar": (("bool",), ("true",), True, "If true, show the scrollbar"), "beep": (("bool",), ("true",), True, "If true, beep the terminal") }, "capabilities": { "sections_on_top": (("bool",), ("true",), True, "Show a list of sections at the top of each page"), "http_links": (("bool",), ("true",), True, "Hyperlinks to HTTP URLs"), "email_links": (("bool",), ("true",), True, "Hyperlinks to email addresses"), "file_links": (("bool",), ("true",), True, "Hyperlinks to local files and directories"), "hyphenate": (("bool",), ("true",), True, "Hyphenate long words in manual pages"), "justify": (("bool",), ("true",), True, "Justify manual pages text"), "icase_search": (("bool",), ("true",), True, "Ignore case for page text search"), "sp_substrings": (("bool",), ("true",), True, "Include substring matches in incremental search results"), }, "misc": { "program_name": (("string",), None, False, "Program executable basename (discovered automatically)"), "program_version": (("wstring",), ("Qman 1.5.1",), False, "Formal program name and version"), "system_type": (("systype", ), ("mandb", ), True, "System type: mandb, mandoc, freebsd, darwin, ..."), "config_path": (("string",), None, False, "Path to the configuration file"), "man_path": (("string",), ("/usr/bin/man",), True, "Path to the man(1) command"), "groff_path": (("string",), ("/usr/bin/groff",), True, "Path to the groff(1) command"), "whatis_path": (("string",), ("/usr/bin/whatis",), True, "Path to the whatis(1) command"), "apropos_path": (("string",), ("/usr/bin/apropos",), True, "Path to the apropos(1) command"), "browser_path": (("string",), ("/usr/bin/xdg-open",), True, "Path to web browser command"), "mailer_path": (("string",), ("/usr/bin/xdg-email",), True, "Path to mailer command"), "viewer_path": (("string",), ("/usr/bin/xdg-open",), True, "Path to file viewer"), "reset_after_http": (("bool",), ("true",), True, "Re-initialize curses after opening an http(s) link"), "reset_after_email": (("bool",), ("true",), True, "Re-initialize curses after opening an e-mail link"), "reset_after_viewer": (("bool",), ("true",), True, "Re-initialize curses after viewing a file"), "terminfo_reset": (("bool",), ("false",), True, "Reset the terminal using the strings provided by terminfo on shutdown"), "history_size": (("int", 0, 256 * 1024), ("65536",), True, "Maximum number of history entries"), "cli_force_color": (("bool",), ("false",), False, "-z / --cli-force-color option was passed"), "global_whatis": (("bool",), ("false",), False, "-a / --all option was passed"), "global_apropos": (("bool",), ("false",), False, "-k / --global-whatis option was passed") } } qman-1.5.1/src/eini.c000066400000000000000000000247671510660157000143520ustar00rootroot00000000000000// Extended INI file parsing (implementation) #include "lib.h" // // Global variables // regex_t eini_re_include, eini_re_section, eini_re_value; // // Helper functions and macros // // Helper of `eini_parse()`. Set the `type`, `key`, and `value` fields of `ret` // to `mytype`, `mykey`, and `myvalue` respectively. #define set_ret(mytype, mykey, myvalue) \ ret.type = mytype; \ if (NULL == mykey) \ ret.key = NULL; \ else { \ wcslcpy(ret_key, wnnl(mykey), BS_SHORT); \ ret.key = ret_key; \ } \ if (NULL == myvalue) \ ret.value = NULL; \ else { \ wcslcpy(ret_value, wnnl(myvalue), BS_LINE); \ wunescape(ret_value); \ ret.value = ret_value; \ } // Helper of `eini_parse()`. Strip trailing whitespace from `wsrc`. If it's // surrounded by single or double quotes, strip those as well. Return any syntax // errors pertaining to non-terminated quotes. #define wsrc_strip \ wlen = wmargtrim(wsrc, NULL); \ if (L'"' == wsrc[0]) { \ /* wsrc begins with a `"` */ \ if (wlen < 2) { \ /* wsrc equals `"`; accept it as it is */ \ } else if (L'"' == wsrc[wlen - 1]) { \ /* wsrc ends in '"' */ \ if (wescaped(wsrc, wlen - 1)) { \ /* the ending `"` is escaped; reject it */ \ set_ret(EINI_ERROR, NULL, L"Non-terminated quote"); \ return ret; \ } else { \ /* the ending `"` is not escaped; remove the `"`s and accept it */ \ wsrc[wlen - 1] = L'\0'; \ wsrc = &wsrc[1]; \ } \ } else { \ /* wsrc does not end in `"`; reject it */ \ set_ret(EINI_ERROR, NULL, L"Non-terminated quote"); \ return ret; \ } \ } else if (L'\'' == wsrc[0]) { \ /* wsrc begins with a `'` */ \ if (wlen < 2) { \ /* wsrc equals `'`; accept it as it is */ \ } else if (L'\'' == wsrc[wlen - 1]) { \ /* wsrc ends in `'` */ \ if (wescaped(wsrc, wlen - 1)) { \ /* the ending `'` is escaped; reject it */ \ set_ret(EINI_ERROR, NULL, L"Non-terminated quote"); \ return ret; \ } else { \ /* the ending `"` is not escaped; remove the `"`s and accept it */ \ wsrc[wlen - 1] = L'\0'; \ wsrc = &wsrc[1]; \ } \ } else { \ /* wsrc does not end in `'`; reject it */ \ set_ret(EINI_ERROR, NULL, L"Non-terminated quote"); \ return ret; \ } \ } // Helper of `eini_parse()`. Discard all comments in `src`. void decomment(wchar_t *src) { unsigned i = 0; // iterator bool inq = false; // true if we are inside a quoted string wchar_t qtype = L'?'; // type of quotes used by the string we are in: `'` or `"` while (L'\0' != src[i]) { if (inq) { // we are inside a quoted string if (qtype == src[i] && !wescaped(src, i)) { // `src[i]` is an unescaped `"` or `'`, thus the quoted string ends inq = false; } } else { // we are not inside a quoted string if (L';' == src[i]) { // `src[i]` is `;`, thus we have a comment to the end of line src[i] = L'\0'; return; } else if (L'"' == src[i] && !wescaped(src, i)) { // `src[i]` is an unescaped `"`, thus a double-quoted string begins inq = true; qtype = L'"'; } else if (L'\'' == src[i] && !wescaped(src, i)) { // src[i] is an unescaped `'`, thus a single-quoted string begins inq = true; qtype = L'\''; } } i++; } } // Helper of `eini_parse()`. Find the first match of `re` in `src` and return // its location. range_t match(regex_t re, char *src) { regmatch_t pmatch[1]; // regex match range_t res; // return value // Try to match `src` int err = regexec(&re, src, 1, pmatch, 0); if (0 == err) { // A match was found res.beg = pmatch[0].rm_so; res.end = pmatch[0].rm_eo; } else { // No match found, or an error has occured; return `{0, 0}` res.beg = 0; res.end = 0; } return res; } // // Functions // void eini_init() { regcomp(&eini_re_include, "[[:space:]]*include[[:space:]]*", REG_EXTENDED); regcomp(&eini_re_section, "[[:space:]]*\\[[[:space:]]*[a-zA-Z][a-zA-Z0-9_]*[[:space:]]*\\][[:" "space:]]*", REG_EXTENDED); regcomp(&eini_re_value, "[[:space:]]*[a-zA-Z][a-zA-Z0-9_]*[[:space:]]*=[[:space:]]*", REG_EXTENDED); } eini_t eini_parse(char *src) { wchar_t *wsrc = walloca(BS_LINE); // `wchar_t*` version of `src` char *csrc = salloca(BS_LINE); // `char*` version of `src` (after removing comments) int wlen; // length of `wsrc` range_t loc; // location of regex match in `wsrc` eini_t ret; // return value static wchar_t ret_key[BS_SHORT]; // `key` contents of `ret` static wchar_t ret_value[BS_LINE]; // `value` contents of `ret` wlen = mbstowcs(wsrc, src, BS_LINE); if (-1 == wlen) { // Couldn't convert `src` set_ret(EINI_ERROR, NULL, L"Non-string data"); return ret; } wsrc[BS_LINE - 1] = L'\0'; decomment(wsrc); xwcstombs(csrc, wsrc, BS_LINE); loc = match(eini_re_include, csrc); if (0 == loc.beg && loc.end > loc.beg) { // Include directive wsrc = &wsrc[loc.end]; wsrc_strip; set_ret(EINI_INCLUDE, NULL, wsrc); return ret; } loc = match(eini_re_section, csrc); if (!(0 == loc.beg && 0 == loc.end)) { // Section wsrc = &wsrc[wmargend(wsrc, L"[")]; wmargtrim(wsrc, L"]"); set_ret(EINI_SECTION, NULL, wsrc); return ret; } loc = match(eini_re_value, csrc); if (!(0 == loc.beg && 0 == loc.end)) { // Key/value pair wchar_t *wkey = wsrc; wkey[loc.end - 1] = L'\0'; wkey = &wkey[wmargend(wkey, NULL)]; wmargtrim(wkey, L"="); wsrc = &wsrc[loc.end]; wsrc_strip; set_ret(EINI_VALUE, wkey, wsrc); return ret; } wlen = wmargtrim(wsrc, NULL); if (0 == wlen) { // Empty line set_ret(EINI_NONE, NULL, NULL); return ret; } // None of the above wchar_t errmsg[BS_LINE]; swprintf(errmsg, BS_LINE, L"Unable to parse '%ls'", wsrc); set_ret(EINI_ERROR, NULL, errmsg); return ret; } void eini(eini_handler_t hf, eini_error_t ef, const char *path) { unsigned i = 0; // current line number FILE *fp; // file pointer char ln[BS_LINE]; // current config line eini_t lne; // current config line contents wchar_t sec[BS_SHORT] = L""; // current section fp = xfopen(path, "r"); // If this is an empty file, do nothing fseek(fp, 0, SEEK_END); if (0 == ftell(fp)) return; rewind(fp); while (!feof(fp)) { xfgets(ln, BS_LINE, fp); i++; lne = eini_parse(ln); switch (lne.type) { case EINI_INCLUDE: { char ipath[BS_LINE]; // include file path FILE *ifp; // include file pointer if (L'/' == lne.value[0]) { xwcstombs(ipath, lne.value, BS_LINE); } else { char apath[BS_LINE]; xwcstombs(apath, lne.value, BS_LINE); strlcpy(ipath, xdirname(path), BS_LINE); strlcat(ipath, "/", BS_LINE); strlcat(ipath, apath, BS_LINE); } ifp = fopen(ipath, "r"); if (NULL == ifp) { wchar_t errmsg[BS_LINE]; swprintf(errmsg, BS_LINE, L"Unable to open '%s'", ipath); ef(errmsg, path, i); } fclose(ifp); eini(hf, ef, ipath); break; } case EINI_SECTION: { wcslcpy(sec, lne.value, BS_SHORT); break; } case EINI_VALUE: { if (0 == wcslen(sec)) { wchar_t errmsg[BS_SHORT]; swprintf(errmsg, BS_SHORT, L"Option '%ls' does not have a section", lne.key); ef(errmsg, path, i); } else hf(sec, lne.key, lne.value, path, i); break; } case EINI_ERROR: { ef(lne.value, path, i); break; } case EINI_NONE: default: break; } } xfclose(fp); } void eini_winddown() { regfree(&eini_re_include); regfree(&eini_re_section); regfree(&eini_re_value); } qman-1.5.1/src/eini.h000066400000000000000000000040451510660157000143420ustar00rootroot00000000000000// Extended INI file parsing (definition) #ifndef EINI_H #define EINI_H #include "lib.h" // // Types // // INI line type typedef enum { EINI_ERROR, // parse error EINI_NONE, // line is empty EINI_INCLUDE, // line contains an include directive EINI_SECTION, // line contains a section header EINI_VALUE // line contains a key/value pair } eini_type_t; // Contents of an INI line typedef struct { eini_type_t type; // line type wchar_t *key; // key name if type is `EINI_VALUE`, NULL otherwise wchar_t *value; // error message if type is `EINI_ERROR`, file to include if // type is `EINI_INCLUDE`, section name if type is `EINI_SECTION`, // value if type is `EINI_VALUE`, NULL otherwise } eini_t; // Handler function typedef void (*eini_handler_t)(const wchar_t *section, // current section const wchar_t *key, // key name const wchar_t *value, // value const char *path, // config file path const unsigned line // config file line ); typedef void (*eini_error_t)(const wchar_t *error, // error message const char *path, // config file path const unsigned line // config file line ); // // Global variables // // Regular expressions for... extern regex_t eini_re_include, // an include directive eini_re_section, // a section header eini_re_value; // a key/value pair // // Functions // // Initialize the parser extern void eini_init(); // Parse INI line `src` and return its contents extern eini_t eini_parse(char *src); // Parse INI file at `path`, calling `hf` whenever a configuration directive // is found or `ef` if a parse error is encountered. This function recursively // calls itself whenever it encounters an `include` directive. extern void eini(eini_handler_t hf, eini_error_t ef, const char *path); // Wind down the parser extern void eini_winddown(); #endif qman-1.5.1/src/lib.h000066400000000000000000000015551510660157000141670ustar00rootroot00000000000000// Header file includes #ifndef LIB_H #define LIB_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #undef lines #ifdef QMAN_GZIP #include #endif #ifdef QMAN_BZIP2 #include #endif #ifdef QMAN_LZMA #include #endif #if defined(__GLIBC__) extern char *program_invocation_short_name; #endif #include "util.h" #include "eini.h" #include "base64.h" #include "config.h" #include "program.h" #include "cli.h" #include "tui.h" #endif qman-1.5.1/src/meson.build000066400000000000000000000046611510660157000154130ustar00rootroot00000000000000# Executable build file # Compiler cc = meson.get_compiler('c') add_global_arguments('-DQMAN_CONFIGDIR="' + get_option('configdir') + '"', language: 'c') # Uncomment the following to expose extra warnings # add_global_arguments(['-Wall', '-Wextra', '-Wno-sign-compare'], language: 'c') # add_global_arguments('-O2', '-D_FORTIFY_SOURCE=2', language: 'c') # Configuration subsystem sources (generated from config_def.py using cog) cog = find_program('cogapp', 'cog', 'cog.py') cog_cmd = [cog, '-d', '-o', '@OUTPUT@', '@INPUT@'] config_h = custom_target('config.h', input: 'config.h.cog', output: 'config.h', command: cog_cmd ) config_c = custom_target('config.c', input: 'config.c.cog', output: 'config.c', command: cog_cmd ) # Non-main sources src = [ config_h, config_c, 'util.c', 'eini.c', 'base64.c', 'program.c', 'cli.c', 'tui.c' ] # Dependencies deps = [ dependency('ncursesw', required: true), ] if get_option('libbsd').enabled() or get_option('libbsd').auto() libbsd = dependency('libbsd-overlay', required: true) deps += [libbsd] endif if get_option('gzip').enabled() or get_option('gzip').auto() gzip = dependency('zlib', required: true) deps += [gzip] add_global_arguments('-DQMAN_GZIP=true', language: 'c') endif if get_option('bzip2').enabled() or get_option('bzip2').auto() bzip2 = dependency('bzip2', required: false) if not bzip2.found() bzip2 = cc.find_library('bz2', required: true) endif deps += [bzip2] add_global_arguments('-DQMAN_BZIP2=true', language: 'c') endif if get_option('lzma').enabled() or get_option('lzma').auto() xz = dependency('liblzma', required: false) if not xz.found() xz = cc.find_library('lzma', required: true) endif deps += [xz] add_global_arguments('-DQMAN_LZMA=true', language: 'c') endif if get_option('tests').enabled() or get_option('tests').auto() cunit = dependency('cunit', required: true) deps += [cunit] endif # Qman executable executable('qman', sources: src + ['qman.c'], dependencies: deps, install: true, install_dir: 'bin', install_tag: 'program' ) # Unit testing (executable and tests) if get_option('tests').enabled() t_exe = executable('qman_tests', sources: src + ['qman_tests.c'], dependencies: deps + [cunit], install: false ) t_all = run_command(find_program('qman_tests_list.sh'), check: true).stdout().split('\n') foreach t: t_all if t != '' test(t, t_exe, args: [t]) endif endforeach endif qman-1.5.1/src/program.c000066400000000000000000002552231510660157000150660ustar00rootroot00000000000000// Program-specific infrastructure (implementation) #include "lib.h" // // Global variables // option_t options[] = { {"index", 'n', L"Show all manual pages (default behaviour if no PAGE has been specified)", OA_NONE, true}, {"apropos", 'k', L"Show a list of all pages whose name and/or description contains PAGE " L"(apropos)", OA_NONE, true}, {"whatis", 'f', L"Show a list of all pages whose name matches PAGE (whatis)", OA_NONE, true}, {"local-file", 'l', L"Interpret PAGE argument(s) as local filename(s)", OA_NONE, true}, {"global-apropos", 'K', L"Show the contents of all pages whose name and/or description contains " L"PAGE (global apropos)", OA_NONE, true}, {"all", 'a', L"Show the contents of all pages whose name matches PAGE (global whatis)", OA_NONE, true}, {"cli", 'T', L"Suppress the TUI and output directly to the terminal (CLI mode)", OA_NONE, true}, {"cli-force-color", 'z', L"Produce colorful output using terminal escape codes, even when not " L"running inside a terminal", OA_NONE, true}, {"action", 'A', L"Automatically perform program action ARG upon startup", OA_REQUIRED, true}, {"config-path", 'C', L"Use ARG as the configuration file path", OA_REQUIRED, true}, {"version", 'V', L"Print program version", OA_NONE, true}, {"help", 'h', L"Display this help message", OA_NONE, true}, {0, 0, 0, 0, false}}; action_t first_action = PA_NULL; request_t *history = NULL; unsigned history_cur = 0; unsigned history_top = 0; aprowhat_t *aw_all = NULL; unsigned aw_all_len = 0; wchar_t **sc_all = NULL; unsigned sc_all_len = 0; line_t *page = NULL; wchar_t page_title[BS_SHORT]; unsigned page_len = 0; link_loc_t page_flink = {true, 0, 0}; unsigned page_top = 0; unsigned page_left = 0; toc_entry_t *toc = NULL; unsigned toc_len = 0; bool err = false; wchar_t err_msg[BS_LINE]; result_t *results = NULL; unsigned results_len = 0; mark_t mark = {false, 0, 0, 0, 0}; full_regex_t re_man, re_http, re_email, re_file; // // Helper macros and functions // // Helper of `man()` and `aprowhat_render()`. Increase `ln`, and reallocate // `res` in memory, if `ln` has exceeded its previously allocated size. #define inc_ln \ ln++; \ if (ln == res_len) { \ res_len += BS_LINE; \ res = xreallocarray(res, res_len, sizeof(line_t)); \ } // Helper of `man_sections()`, `man_toc()` and `sc_toc()`. Increase `en`, and // reallocate `res` in memory, if `en` has exceeded its previously allocated // size. #define inc_en \ en++; \ if (en == res_len) { \ res_len += BS_SHORT; \ res = xreallocarray(res, res_len, sizeof(toc_entry_t)); \ } // Helper of `search()`. Increase `i`, and reallocate `res` in memory, if `i` // has exceeded its previously allocated size. #define inc_i \ i++; \ if (i == res_len) { \ res_len += BS_LINE; \ res = xreallocarray(res, res_len, sizeof(result_t)); \ } // The following are helpers of `man()` // true if `tmpw[i]` contains a 'bold' terminal escape sequence #define got_bold \ ((i + 4 < len) && (tmpw[i] == L'\e') && (tmpw[i + 1] == L'[') && \ (tmpw[i + 2] == L'1') && (tmpw[i + 3] == L'm')) // attachment to `got_bold_nosgr` that fixes a quirk in `mandoc`'s output #define got_bold_nosgr_mandoc_quirk_fix \ (!((ST_MANDOC == config.misc.system_type || \ ST_FREEBSD == config.misc.system_type || \ ST_DARWIN == config.misc.system_type) && \ tmpw[i] == '_' && uline_nosgr)) // true if `tmpw[i]` contains a 'bold' typewriter (NO_SGR) sequence #define got_bold_nosgr \ ((i + 3 < len) && (tmpw[i] == tmpw[i + 2]) && (tmpw[i + 1] == L'\b') && \ got_bold_nosgr_mandoc_quirk_fix) // true if `tmpw[i]` contains a 'not bold' terminal escape sequence #define got_not_bold \ ((i + 4 < len) && (tmpw[i] == L'\e') && (tmpw[i + 1] == L'[') && \ (tmpw[i + 2] == L'0') && (tmpw[i + 3] == L'm')) // true if `tmpw[i]` contains a 'italic' terminal escape sequence #define got_italic \ ((i + 4 < len) && (tmpw[i] == L'\e') && (tmpw[i + 1] == L'[') && \ (tmpw[i + 2] == L'3') && (tmpw[i + 3] == L'm')) // true if `tmpw[i]` contains a 'not italic' terminal escape sequence #define got_not_italic \ ((i + 5 < len) && (tmpw[i] == L'\e') && (tmpw[i + 1] == L'[') && \ (tmpw[i + 2] == L'2') && (tmpw[i + 3] == L'3') && (tmpw[i + 4] == L'm')) // true if `tmpw[i]` contains a 'underline' terminal escape sequence #define got_uline \ ((i + 4 < len) && (tmpw[i] == L'\e') && (tmpw[i + 1] == L'[') && \ (tmpw[i + 2] == L'4') && (tmpw[i + 3] == L'm')) // true if `tmpw[i]` contains a 'underline' typewriter (NO_SGR) sequence #define got_uline_nosgr \ ((i + 3 < len) && (tmpw[i] == L'_') && (tmpw[i + 1] == L'\b')) // true if `tmpw[i]` contains a 'not underline' terminal escape sequence #define got_not_uline \ ((i + 5 < len) && (tmpw[i] == L'\e') && (tmpw[i + 1] == L'[') && \ (tmpw[i + 2] == L'2') && (tmpw[i + 3] == L'4') && (tmpw[i + 4] == L'm')) // true if `tmpw[i]` contains a 'normal / not dim' terminal escape sequence #define got_normal \ ((i + 5 < len) && (tmpw[i] == L'\e') && (tmpw[i + 1] == L'[') && \ (tmpw[i + 2] == L'2') && (tmpw[i + 3] == L'2') && (tmpw[i + 4] == L'm')) // true if `tmpw[i]` contains any single-digit terminal formatting sequence #define got_any_1 \ ((i + 4 < len) && (tmpw[i] == L'\e') && (tmpw[i + 1] == L'[') && \ (tmpw[i + 3] == L'm')) // true if `tmpw[i]` contains any two-digit terminal formatting sequence #define got_any_2 \ ((i + 5 < len) && (tmpw[i] == L'\e') && (tmpw[i + 1] == L'[') && \ (tmpw[i + 4] == L'm')) // true if `tmpw[i]` contains any three-digit terminal formatting sequence #define got_any_3 \ ((i + 6 < len) && (tmpw[i] == L'\e') && (tmpw[i + 1] == L'[') && \ (tmpw[i + 5] == L'm')) // true if `tmpw[i]` contains an esape-]8 (link embedding) sequence #define got_esc8 \ ((i + 4 < len) && (tmpw[i] == L'\e') && (tmpw[i + 1] == L']') && \ (tmpw[i + 2] == L'8') && (tmpw[i + 3] == L';')) // The following are helpers of `man_toc()` and `man_sections()` // true if `gline` is a section header #define got_sh \ ((glen >= 3) && (L'.' == gline[0]) && \ (L'S' == gline[1] || L's' == gline[1]) && \ (L'H' == gline[2] || L'h' == gline[2])) // true if `gline` is a sub-section header #define got_ss \ ((glen >= 3) && (L'.' == gline[0]) && \ (L'S' == gline[1] || L's' == gline[1]) && \ (L'S' == gline[2] || L's' == gline[2])) // true if `gline` is a tagged paragraph #define got_tp \ ((glen >= 3) && (L'.' == gline[0]) && \ (L'T' == gline[1] || L't' == gline[1]) && \ (L'P' == gline[2] || L'p' == gline[2])) // true if `gline` is a command to output delayed text #define got_pd \ ((glen >= 3) && (L'.' == gline[0]) && \ (L'P' == gline[1] || L'p' == gline[1]) && \ (L'D' == gline[2] || L'd' == gline[2])) // true if a tag line is a comment #define got_comment \ ((glen > 2) && (gline[0] == L'.') && (gline[1] == L'\\') && \ ((gline[2] == L'\"' || gline[2] == L'#'))) // Components of `got_trap` and `got_ok` #define got_b \ ((glen > 1) && (L'.' == gline[0]) && (L'B' == gline[1] || L'b' == gline[1])) #define got_i \ ((glen > 1) && (L'.' == gline[0]) && (L'I' == gline[1] || L'i' == gline[1])) #define got_sm \ ((glen > 2) && (L'.' == gline[0]) && \ (L's' == gline[1] || L'S' == gline[1]) && \ (L'm' == gline[2] || L'M' == gline[2])) #define got_sb \ ((glen > 2) && (L'.' == gline[0]) && \ (L's' == gline[1] || L'S' == gline[1]) && \ (L'b' == gline[2] || L'B' == gline[2])) #define got_bi \ ((glen > 2) && (L'.' == gline[0]) && \ (L'b' == gline[1] || L'B' == gline[1]) && \ (L'i' == gline[2] || L'I' == gline[2])) #define got_br \ ((glen > 2) && (L'.' == gline[0]) && \ (L'b' == gline[1] || L'B' == gline[1]) && \ (L'r' == gline[2] || L'R' == gline[2])) #define got_ib \ ((glen > 2) && (L'.' == gline[0]) && \ (L'i' == gline[1] || L'I' == gline[1]) && \ (L'b' == gline[2] || L'B' == gline[2])) #define got_ir \ ((glen > 2) && (L'.' == gline[0]) && \ (L'i' == gline[1] || L'I' == gline[1]) && \ (L'r' == gline[2] || L'R' == gline[2])) #define got_rb \ ((glen > 2) && (L'.' == gline[0]) && \ (L'r' == gline[1] || L'R' == gline[1]) && \ (L'b' == gline[2] || L'B' == gline[2])) #define got_ri \ ((glen > 2) && (L'.' == gline[0]) && \ (L'r' == gline[1] || L'R' == gline[1]) && \ (L'i' == gline[2] || L'I' == gline[2])) // true if a tag line starts with a formatting command that sets a trap #define got_trap (got_b || got_i || got_sm || got_sb) // true if a tag line starts with an allowed formatting command #define got_ok \ (got_b || got_i || got_sm || got_sb || got_bi || got_br || got_ib || \ got_ir || got_rb || got_ri) // Helper of `man_loc()` and `man()`. Decompose command-line argument in `src` // into a `page` and potentially a `section` (both of length `len`). Return 2 if // both `page` and `section` got populated, 1 if just `page` got populated, or 0 // of neither did. unsigned extract_args(wchar_t **page, wchar_t **section, unsigned len, const wchar_t *src) { unsigned src_len = wcslen(src); // length of src wchar_t *srcc = walloca(src_len); // copy of `src` wchar_t *arg; // current argument wchar_t **arg_dec = aalloca(2, wchar_t *); // decomposed current argument (e.g. `"ls(1)"` -> // `["ls", "1"]`) unsigned arg_dec_len; // length of `arg_dec` wchar_t *buf; // temporary wcslcpy(srcc, src, src_len); arg = wcstok(srcc, L"' \t", &buf); if (NULL != arg) { // Argument #1 exists... arg_dec_len = wsplit(&arg_dec, 2, arg, L"()", false); if (2 == arg_dec_len) { // ...and is in page(sec) format; decompose it into `page` and `section` wcslcpy(*page, arg_dec[0], len); wcslcpy(*section, arg_dec[1], len); return 2; } else if (1 == arg_dec_len) { // ...and is not in page(sec) format; provisionally set argument #1 as // `page` and as `section` wcslcpy(*page, arg_dec[0], len); wcslcpy(*section, L"", len); // However... arg = wcstok(NULL, L"' \t", &buf); if (NULL != arg) { // ...if argument #2 exists... arg_dec_len = wsplit(&arg_dec, 2, arg, L"()", false); if (1 == arg_dec_len) { // ...and is not in page(sec) format, set argument #1 as `section` and // argument #2 as `page` wcslcpy(*section, *page, len); wcslcpy(*page, arg_dec[0], len); return 2; } } return 1; } } return 0; } // Helper of `man_sections()` and `man_toc()`. Place the location of the manual // page source that corresponds to `args` into `dst` (of length `dst_len`). If // no such location exists, return false, otherwise return true. `local_file` // signifies whether `args` contains a local file path, rather than a manual // page name and section. bool man_loc(char *dst, unsigned dst_len, const wchar_t *args, bool local_file) { char cmdstr[BS_LINE]; // command to execute bool ret; // return value if (ST_MANDB == config.misc.system_type) { // `mandb` specific if (local_file) snprintf(cmdstr, BS_LINE, "%s --warnings='!all' --path --local-file %ls 2>>/dev/null", config.misc.man_path, args); else { snprintf(cmdstr, BS_LINE, "%s --warnings='!all' --path %ls 2>>/dev/null", config.misc.man_path, args); } ret = true; FILE *pp = xpopen(cmdstr, "r"); if (-1 == sreadline(dst, dst_len, pp)) ret = false; xpclose(pp); return ret; } else if (ST_MANDOC == config.misc.system_type) { // `mandoc` specific unsigned args_len = wcslen(args); // length of `args` wchar_t *page = walloca(args_len); // man page extracted from `args` wchar_t *section = walloca(args_len); // man section extracted from `args` char *combo = salloca(2 * args_len); // `page`.`section` combination char *combo_ptr, combo_post; // used for analyzing `combo` unsigned extracted; // return value of `extract_args()` int searched; // return value of `aprowhat_search()` extracted = extract_args(&page, §ion, args_len, args); switch (extracted) { case 2: snprintf(combo, 2 * args_len, "%ls.%ls", page, section); break; case 1: searched = aprowhat_search(page, aw_all, aw_all_len, 0, false); if (searched > -1) snprintf(combo, 2 * args_len, "%ls.%ls", aw_all[searched].page, aw_all[searched].section); else xwcstombs(combo, page, args_len); break; case 0: return false; } if (local_file) { wcstombs(dst, page, dst_len); return true; } else { if (2 == extracted) snprintf(cmdstr, BS_LINE, "%s -w '%ls' '%ls' 2>>/dev/null", config.misc.man_path, section, page); else snprintf(cmdstr, BS_LINE, "%s -w '%ls' 2>>/dev/null", config.misc.man_path, page); // Try to return the 'man -w' result that ends in `combo` (barring a // filename extension) ret = false; FILE *pp = xpopen(cmdstr, "r"); while (-1 != sreadline(dst, dst_len, pp)) { combo_ptr = strcasestr(dst, combo); if (NULL != combo_ptr) { combo_post = combo_ptr[strlen(combo)]; if ('.' == combo_post || '\0' == combo_post) { ret = true; break; } } } // If not found, execute 'man -w' again and return the first line of its // output if (false == ret) { xpclose(pp); ret = true; pp = xpopen(cmdstr, "r"); if (-1 == sreadline(dst, dst_len, pp)) ret = false; } xpclose(pp); return ret; } } else if (ST_FREEBSD == config.misc.system_type || ST_DARWIN == config.misc.system_type) { // FreeBSD and macOS X `man` specific unsigned args_len = wcslen(args); // length of `args` wchar_t *page = walloca(args_len); // man page extracted from `args` wchar_t *section = walloca(args_len); // man section extracted from `args` unsigned extracted; // return value of `extract_args()` extracted = extract_args(&page, §ion, args_len, args); if (2 == extracted) snprintf(cmdstr, BS_LINE, "%s -w '%ls' '%ls' 2>>/dev/null", config.misc.man_path, section, page); else if (1 == extracted) snprintf(cmdstr, BS_LINE, "%s -w '%ls' 2>>/dev/null", config.misc.man_path, page); else return false; ret = true; FILE *pp = xpopen(cmdstr, "r"); if (-1 == sreadline(dst, dst_len, pp)) ret = false; xpclose(pp); return ret; } return false; } // macOS X specific version of `aprowhat_exec()` (arguments are the same) unsigned aprowhat_exec_darwin(aprowhat_t **dst, aprowhat_cmd_t cmd, const wchar_t *args) { // Prepare `apropos`/`whatis` command char cmdstr[BS_LINE]; if (AW_WHATIS == cmd) snprintf(cmdstr, BS_LINE, "%s %ls 2>>/dev/null", config.misc.whatis_path, args); else snprintf(cmdstr, BS_LINE, "%s %ls 2>>/dev/null", config.misc.apropos_path, args); unsigned res_len = BS_LINE; // result length aprowhat_t *res = aalloc(res_len, aprowhat_t); // result char *line = salloc(BS_LONG); // current line of text, as returned by the command wchar_t *wline = walloc(BS_LONG); // `wchar_t *` version of `line` wchar_t **idents = aalloc(BS_LINE, wchar_t *); // manual page / section combos (in `line`) wchar_t *descr = walloca(BS_LINE); // description (in `line`) wchar_t *page, *section; // manual page and section in current entry of `idents` wchar_t *buf; // temporary unsigned idents_len, descr_len, page_len, section_len; // lengths of `idents`, `descr`, `page` and `section` int wline_len; // length of `wline` unsigned res_i = 0; // current result unsigned i; // iterators // Execute the command FILE *pp = xpopen(cmdstr, "r"); // For each `line` returned by the command... xfgets(line, BS_LONG, pp); while (!feof(pp)) { wline_len = xmbstowcs(wline, line, BS_LONG); if (-1 == wline_len) { if (0 == res_i) break; else winddown(ES_OPER_ERROR, L"Malformed apropos/whatis command output"); } wline[wline_len - 1] = L'\0'; // Extract `descr` descr = wcsstr(wline, L" - "); if (NULL == descr) { if (0 == res_i) break; else winddown(ES_OPER_ERROR, L"Malformed apropos/whatis command output"); } descr[0] = L'\0'; descr = &descr[3]; descr_len = wcslen(descr); // Extract `idents` idents_len = wsplit(&idents, BS_LINE, wline, L",", true); // For each ident described by line... for (i = 0; i < idents_len; i++) { // Extract the corresponding `page` and `section` // (Formatting and error handling here is a bit hacky, to account for // darwin's flaky `apropos` output) page = wcstok(idents[i], L"(", &buf); page = &page[wmargend(page, NULL)]; wmargtrim(page, NULL); if (NULL == page || L'/' == page[0] || NULL != wcschr(page, L' ')) continue; section = wcstok(NULL, L")", &buf); if (NULL == section || L'(' == section[0]) continue; // Populate the `res_i`th element of `res` page_len = wcslen(page); section_len = wcslen(section); res[res_i].page = walloc(page_len); wcslcpy(res[res_i].page, page, page_len + 1); res[res_i].section = walloc(section_len); wcslcpy(res[res_i].section, section, section_len + 1); res[res_i].ident = walloc(page_len + section_len + 3); swprintf(res[res_i].ident, page_len + section_len + 3, L"%ls(%ls)", page, section); res[res_i].descr = walloc(descr_len); wcslcpy(res[res_i].descr, descr, descr_len + 1); // Increase `res_i`, and reallocate `res` if necessary res_i++; if (res_i == res_len) { res_len += BS_LINE; res = xreallocarray(res, res_len, sizeof(aprowhat_t)); } } xfgets(line, BS_LONG, pp); } int status = xpclose(pp); // If no results were returned by the command, set `err` to true and // describe the error in `err_msg`. Otherwise, set `err` to false. err = false; if (0 == res_i || 0 != status) { err = true; if (AW_WHATIS == cmd) swprintf(err_msg, BS_LINE, L"Whatis %ls: nothing apropriate", args); else swprintf(err_msg, BS_LINE, L"Apropos %ls: nothing apropriate", args); } // Deallocate unused memory and return if (res_i > 0) res = xreallocarray(res, res_i, sizeof(aprowhat_t)); free(line); free(wline); free(idents); *dst = res; return res_i; } // Helper of `discover_links()`, man()` and `aprowhat_render()`. Add a link to // `line`. Allocate memory using `line_realloc_link()` to do so. Use `start`, // `end`, `in_next`, `start_next`, `end_next`, `type`, and `trgt` to populate // the new link's members. void add_link(line_t *line, unsigned start, unsigned end, bool in_next, unsigned start_next, unsigned end_next, link_type_t type, const wchar_t *trgt) { link_t link; // new link int i; // iterator // Populate new link link.start = start; link.end = end; link.type = type; link.in_next = in_next; link.start_next = start_next; link.end_next = end_next; link.trgt = walloc(wcslen(trgt)); wcscpy(link.trgt, trgt); // Sanity check: new link's end must be after its start if (link.end <= link.start) { free(link.trgt); return; } if (link.in_next) if (link.end_next <= link.start_next) { free(link.trgt); return; } // Sanity check: new link can't overlap an existing link for (i = 0; i < line->links_length; i++) if (link.in_next) { if (line->links[i].start <= link.end && line->links[i].end_next >= link.end_next) { free(link.trgt); return; } } else { if (line->links[i].start <= link.end && line->links[i].end >= link.end) { free(link.trgt); return; } } // Add new link to line line_realloc_link((*line)); if (1 == line->links_length) i = 0; else { for (i = line->links_length - 2; i >= 0; i--) if (line->links[i].start > link.end) line->links[i + 1] = line->links[i]; else break; i++; } line->links[i] = link; } // Helper of `man()`. Discover links that match `re` in the text of `line`, // and add them to said `line`. `line_next` is necessary to support hyphenated // links. `type` signifies the link type to add. void discover_links(const full_regex_t *re, line_t *line, line_t *line_next, const link_type_t type) { // Ignore empty lines if (line->length < 2) return; wchar_t ltext[BS_LINE * 2]; // text of `line` (or text of `line` merged with // text of `line_next`, if `line` is hyphenated) memset(ltext, 0, sizeof(wchar_t) * BS_LINE * 2); const bool lhyph = line->text[line->length - 2] == L'‐'; // whether `line` is hyphenated unsigned loff = 0; // offset (in `ltext`) to start searching for links range_t lrng; // location of link in `ltext` wchar_t trgt[BS_LINE * 2]; // link target char strgt[BS_LINE * 2]; // char* version of `trgt` struct stat sb; // used for verifying file links // Prepare `ltext` wcsncpy(ltext, line->text, line->length - 1); if (lhyph) { unsigned lnme = wmargend(line_next->text, NULL); // left margin end of `line_next` wcsncpy(<ext[line->length - 2], &line_next->text[lnme], line_next->length - lnme); } // While a link has been found... lrng = fr_search(re, <ext[loff]); while (lrng.beg != lrng.end) { // Extract link target from line text wcsncpy(trgt, <ext[loff + lrng.beg], lrng.end - lrng.beg); trgt[lrng.end - lrng.beg] = L'\0'; if (lhyph && loff + lrng.beg < line->length && loff + lrng.end >= line->length) { // Link is broken by a hyphen const unsigned lnme = wmargend( line_next->text, NULL); // position where actual text (without // margin) of `line_next` starts const unsigned lstart = loff + lrng.beg; // starting pos. in `line` const unsigned lend = line->length - 2; // ending pos. in `line` const unsigned nlstart = lnme; // starting pos. in `line_next` const unsigned nlend = lnme + (lrng.end - lrng.beg) - (lend - lstart); // ending pos. in `line_next` // Add the link to `line` if (LT_MAN == type) { if (aprowhat_has(trgt, aw_all, aw_all_len)) add_link(line, lstart, lend, true, nlstart, nlend, type, trgt); } else if (LT_FILE == type) { xwcstombs(strgt, trgt, BS_LINE * 2); if (stat(strgt, &sb) == 0 && sb.st_mode & S_IRUSR) add_link(line, lstart, lend, true, nlstart, nlend, type, trgt); } else add_link(line, lstart, lend, true, nlstart, nlend, type, trgt); } else if (loff + lrng.end < line->length) { // Link is not broken by a hyphen // Add the link to `line` if (LT_MAN == type) { if (aprowhat_has(trgt, aw_all, aw_all_len)) add_link(line, loff + lrng.beg, loff + lrng.end, false, 0, 0, type, trgt); } else if (LT_FILE == type) { xwcstombs(strgt, trgt, BS_LINE * 2); if (stat(strgt, &sb) == 0 && sb.st_mode & S_IRUSR) add_link(line, loff + lrng.beg, loff + lrng.end, false, 0, 0, type, trgt); } else add_link(line, loff + lrng.beg, loff + lrng.end, false, 0, 0, type, trgt); } // Calculate next offset loff += lrng.end; if (loff < line->length) { // Offset is not beyond the end of `line`; look for another link lrng = fr_search(re, <ext[loff]); } else { // Offset is beyond the end of `line`; exit the loop lrng.beg = 0; lrng.end = 0; } } } // Helper of `man_toc()`. Massage the `text` of every entry in `toc` (of size // `toc_len`) with the `groff` command, in order to remove escaped characters, // etc. void tocgroff(toc_entry_t *toc, unsigned toc_len) { char *tpath; // temporary file path char cmdstr[BS_LINE] = ""; // groff 'massage' command char texts[BS_LINE]; // 8-bit version of current `toc` text unsigned i; // iterator // Prepare `tpath` and `cmdstr` tpath = xtempnam(NULL, "qman"); snprintf(cmdstr, BS_LINE, "%s -man -rLL=1024m -Tutf8 -k %s 2>>/dev/null", config.misc.groff_path, tpath); // Prepare the environment unsetenv("GROFF_SGR"); setenv("GROFF_NO_SGR", "1", true); // Write all `text`s of `toc` into temporary file FILE *fp = xfopen(tpath, "w"); xfputs(".TH A A A A A", fp); xfputs(".ll 1024m\n", fp); for (i = 0; i < toc_len; i++) if (NULL != toc[i].text) { xwcstombs(texts, toc[i].text, BS_LINE); xfputs(texts, fp); xfputs("\n.br 0\n", fp); } xfclose(fp); // Massage temporary file with `grof` and put the results back into the // `text`s of `toc` FILE *pp = xpopen(cmdstr, "r"); xfgets(texts, BS_LINE, pp); // discarded xfgets(texts, BS_LINE, pp); // discarded for (i = 0; i < toc_len;) { xfgets(texts, BS_LINE, pp); xmbstowcs(toc[i].text, texts, BS_LINE); wbs(toc[i].text); wmargtrim(toc[i].text, L"\n"); // Discard empty line output if (L'\0' != toc[i].text[0]) i++; // Failsafe: exit loop on EOF if (feof(pp)) break; } xpclose(pp); // Tidy up and restore the environment unlink(tpath); free(tpath); } // Helper of `man_sections()`. Massage every entry in `sections` (of size // `sections_len`) with the `groff` command, in order to remove escaped // characters, etc. void secgroff(wchar_t **sections, unsigned sections_len) { char *tpath; // temporary file path char cmdstr[BS_LINE] = ""; // the massage command char texts[BS_LINE]; // 8-bit version of current `toc` text unsigned i; // iterator // Prepare `tpath` and `cmdstr` tpath = xtempnam(NULL, "qman"); snprintf(cmdstr, BS_LINE, "%s -man -rLL=1024m -Tutf8 -k %s 2>>/dev/null", config.misc.groff_path, tpath); // Prepare the environment unsetenv("GROFF_SGR"); setenv("GROFF_NO_SGR", "1", true); // Write all sections into temporary file FILE *fp = xfopen(tpath, "w"); xfputs(".TH A A A A A", fp); xfputs(".ll 1024m\n", fp); for (i = 0; i < sections_len; i++) if (NULL != sections[i]) { xwcstombs(texts, sections[i], BS_LINE); xfputs(texts, fp); xfputs("\n.br 0\n", fp); } xfclose(fp); // Massage temporary file with `groff` and put the results back into the // `text`s of `toc` FILE *pp = xpopen(cmdstr, "r"); xfgets(texts, BS_LINE, pp); // discarded xfgets(texts, BS_LINE, pp); // discarded for (i = 0; i < sections_len;) { xfgets(texts, BS_LINE, pp); xmbstowcs(sections[i], texts, BS_LINE); wbs(sections[i]); wmargtrim(sections[i], L"\n"); // Discard empty line output if (L'\0' != sections[i][0]) i++; // Failsafe: exit loop on EOF if (feof(pp)) break; } xpclose(pp); // Tidy up and restore the environment unlink(tpath); free(tpath); } // // Functions // void init() { // Use the system locale setlocale(LC_ALL, ""); // Initialize configuration to sane defaults conf_init(); // Initialize history history_cur = 0; history_top = 0; history = aalloc(config.misc.history_size, request_t); history_replace(RT_NONE, NULL); // Initialize `page_title` wcslcpy(page_title, L"", BS_SHORT); // initialize regular expressions fr_init(&re_man, "[a-zA-Z0-9\\.:@_-]+\\([a-zA-Z0-9]+\\)", L")"); fr_init(&re_http, "https?:\\/\\/[a-zA-Z0-9\\.\\/\\?\\+:@_#&%=~-]*[a-zA-Z0-9\\/" "\\?\\+:@_#&%=~-]", L"http"); fr_init( &re_email, "[a-zA-Z0-9\\.\\$\\*\\+\\?\\^\\|!#%&'/=_`{}~-][a-zA-Z0-9\\.\\$\\*\\+\\/" "\\?\\^\\|\\.!#%&'=_`{}~-]*@[a-zA-Z0-9-][a-zA-Z0-9-]+\\.[a-zA-Z0-9-][a-" "zA-Z0-9\\.-]+[a-zA-Z0-9-]", L"@"); fr_init(&re_file, "(\\/[a-zA-Z0-9_\\.-]+)+\\/?", L"/"); } void late_init() { // Initialize `aw_all` if (ST_FREEBSD == config.misc.system_type || ST_DARWIN == config.misc.system_type) aw_all_len = aprowhat_exec(&aw_all, AW_APROPOS, L"'.'"); else aw_all_len = aprowhat_exec(&aw_all, AW_APROPOS, L"''"); // Initialize `sc_all` sc_all_len = aprowhat_sections(&sc_all, aw_all, aw_all_len); } int parse_options(int argc, char *const *argv) { // Initialize the `opstring` and `longopts` arguments of `getopt()` char optstring[3 * asizeof(options)]; struct option *longopts = aalloc(1 + asizeof(options), struct option); unsigned i, optstring_i = 0; for (i = 0; i < asizeof(options); i++) { optstring[optstring_i] = options[i].short_opt; optstring_i++; if (options[i].arg != OA_NONE) { optstring[optstring_i] = ':'; optstring_i++; } if (options[i].arg == OA_OPTIONAL) { optstring[optstring_i] = ':'; optstring_i++; } longopts[i].name = options[i].long_opt; if (options[i].arg == OA_NONE) longopts[i].has_arg = no_argument; else if (options[i].arg == OA_OPTIONAL) longopts[i].has_arg = optional_argument; else longopts[i].has_arg = required_argument; longopts[i].flag = 0; longopts[i].val = options[i].short_opt; } optstring[optstring_i] = '\0'; longopts[i] = (struct option){0, 0, 0, 0}; // Parse the options and respond while (true) { int cur_i; int cur = getopt_long(argc, argv, optstring, longopts, &cur_i); switch (cur) { case -1: free(longopts); return optind; break; case 'n': // -n or --index was passed; show index page history_replace(RT_INDEX, NULL); break; case 'k': // -k or --apropos was passed; try to show apropos results history_replace(RT_APROPOS, NULL); break; case 'f': // -f or --whatis was passed; try to show whatis results history_replace(RT_WHATIS, NULL); break; case 'l': // -l or --local-file was passed; try to show a man page from a local // file history_replace(RT_MAN_LOCAL, NULL); break; case 'K': // -k or --global-apropos was passed; make sure it will be passed on to // `man` config.misc.global_apropos = true; break; case 'a': // -a or --all was passed; make sure it will be passed on to man config.misc.global_whatis = true; break; case 'T': // -T or --cli was passed; do not launch the TUI config.layout.tui = false; break; case 'z': // -z or --cli-force-color was passed; force-enable color for the CLI config.misc.cli_force_color = true; break; case 'A': // -A or --action was passed; set `first_action` to the program action // that corresponds `optarg` for (unsigned j = 1; j < PA_QUIT; j++) if (0 == strcasecmp(optarg, keys_names[j])) { first_action = j; break; } if (PA_NULL == first_action) { // Error out if `optarg` doesn't match a program action name wchar_t errmsg[BS_SHORT]; swprintf(errmsg, BS_SHORT, L"Unknown program action '%s'", optarg); winddown(ES_USAGE_ERROR, errmsg); } break; case 'C': // -C or --config-path was passed; use `optarg` as config file if (NULL != config.misc.config_path) free(config.misc.config_path); config.misc.config_path = xstrdup(optarg); break; case 'V': // -v or --version was passed; print program version and exit version(); free(longopts); winddown(ES_SUCCESS, NULL); break; case 'h': // -h or --help was passed; print usage and exit usage(); free(longopts); winddown(ES_SUCCESS, NULL); break; case '?': // an unknown option was passed; error out free(longopts); winddown(ES_USAGE_ERROR, L"Unable to parse program arguments"); break; } } } void parse_args(int argc, char *const *argv) { unsigned i; // iterator wchar_t tmp[BS_LINE], tmp2[BS_SHORT]; // temporary unsigned tmp_len; // length of `tmp` (used to guard against buffer overflows) // If the user hasn't asked for a specific request type... if (RT_NONE == history[history_cur].request_type) { if (0 == argc) { // ...and hasn't provided any arguments, show the index page history_replace(RT_INDEX, NULL); } else { // ...but has provided arguments, try to show the manual page that // corresponds to said arguments history_replace(RT_MAN, NULL); } } // If we are showing a manual, apropos, whatis, or local page... if (history[history_cur].request_type > RT_INDEX) { // ...but the user hasn't specified an argument... if (0 == argc) { // Exit with error message switch (history[history_top].request_type) { case RT_MAN: case RT_MAN_LOCAL: winddown(ES_USAGE_ERROR, L"What manual page do you want?"); break; case RT_APROPOS: winddown(ES_USAGE_ERROR, L"Apropos what?"); break; case RT_WHATIS: default: winddown(ES_USAGE_ERROR, L"Whatis what?"); break; } } wcslcpy(tmp, L"", BS_LINE); tmp_len = 0; // Surround all members of `argv` with single quotes, and flatten them // into `tmp` for (i = 0; i < argc; i++) { swprintf(tmp2, BS_SHORT, L"'%s'", argv[i]); if (tmp_len + wcslen(tmp2) < BS_LINE) { wcslcat(tmp, tmp2, BS_LINE); tmp_len += wcslen(tmp2); } if (i < argc - 1 && tmp_len + 4 < BS_LINE) { wcslcat(tmp, L" ", BS_LINE); tmp_len++; } } // Set `history[history_cur].args` to `tmp` history_replace(history[history_cur].request_type, tmp); } } void version() { wprintf(L"%ls\n", config.misc.program_version); } void usage() { // Header wprintf(L"Usage: %s [OPTION...] [SECTION] [PAGE]...\n\n", config.misc.program_name); // Command-line options unsigned i = 0; wchar_t short_opt_str[BS_SHORT]; wchar_t long_opt_str[BS_SHORT]; wchar_t help_text_str[BS_LINE]; wchar_t tmp_str[BS_LINE]; do { // Short option swprintf(short_opt_str, BS_SHORT, L"-%c", options[i].short_opt); // long option if (options[i].arg == OA_NONE) swprintf(long_opt_str, BS_SHORT, L"--%s", options[i].long_opt); else if (options[i].arg == OA_OPTIONAL) swprintf(long_opt_str, BS_SHORT, L"--%s=[ARG]", options[i].long_opt); else swprintf(long_opt_str, BS_SHORT, L"--%s=ARG", options[i].long_opt); // Help text wcslcpy(tmp_str, options[i].help_text, BS_LINE); wwrap(tmp_str, 52); wcrepl(help_text_str, tmp_str, L'\n', L"\n ", BS_LINE); wprintf(L" %ls, %-20ls %ls\n", short_opt_str, long_opt_str, help_text_str); i++; } while (options[i]._cont); // Footer wprintf(L"\nMandatory or optional arguments to long options are also " L"mandatory or optional\nfor any corresponding short options.\n"); } void history_replace(request_type_t rt, const wchar_t *args) { history[history_cur].request_type = rt; if (NULL != history[history_cur].args) free(history[history_cur].args); if (NULL == args) history[history_cur].args = NULL; else { history[history_cur].args = wcsdup(args); } history[history_cur].top = 0; history[history_cur].left = 0; history[history_cur].flink = (link_loc_t){false, 0, 0}; } void history_push(request_type_t rt, const wchar_t *args) { unsigned i; // Save user's position history[history_cur].top = page_top; history[history_cur].left = page_left; history[history_cur].flink = page_flink; // Increase `history_cur` history_cur++; // If we're pushing in the middle of the `history` stack, all subsequent // history entries are lost, and we must free memory accordingly if (history_top > history_cur) for (i = history_cur + 1; i <= history_top; i++) if (NULL != history[i].args) { free(history[i].args); history[i].args = NULL; } // Make `history_top` equal to `history_cur` history_top = history_cur; // Failsafe: in the unlikely case `history_top` exceeds history size, free // all memory used by `history` and start over if (history_top >= config.misc.history_size) { requests_free(history, config.misc.history_size); history_top = 0; history_cur = 0; history = aalloc(config.misc.history_size, request_t); } // Populate the new history entry history_replace(rt, args); } bool history_jump(int pos) { history[history_cur].top = page_top; history[history_cur].left = page_left; history[history_cur].flink = page_flink; if (pos >= 0 && pos <= history_top) { history_cur = pos; page_top = history[history_cur].top; page_left = history[history_cur].left; page_flink = history[history_cur].flink; return true; } return false; } void history_reset() { unsigned i; for (i = history_cur + 1; i <= history_top; i++) { if (NULL != history[i].args) { free(history[i].args); history[i].args = NULL; } } history_top = history_cur; } unsigned aprowhat_exec(aprowhat_t **dst, aprowhat_cmd_t cmd, const wchar_t *args) { if (ST_DARWIN == config.misc.system_type) { // macOS X requires its own special `aprowhat_exec()` return aprowhat_exec_darwin(dst, cmd, args); } // Prepare `apropos`/`whatis` command char cmdstr[BS_LINE]; char *longopt; if (ST_MANDB == config.misc.system_type) longopt = "-l"; else longopt = ""; if (AW_WHATIS == cmd) snprintf(cmdstr, BS_LINE, "%s %s %ls 2>>/dev/null", config.misc.whatis_path, longopt, args); else snprintf(cmdstr, BS_LINE, "%s %s %ls 2>>/dev/null", config.misc.apropos_path, longopt, args); unsigned res_len = BS_LINE; // result length aprowhat_t *res = aalloc(res_len, aprowhat_t); // result char *line = salloc(BS_LONG); // current line of text, as returned by the command wchar_t *wline = walloc(BS_LONG); // `wchar_t *` version of `line` wchar_t **pages = aalloc(BS_LINE, wchar_t *); // pages (in `line`) wchar_t **sections = aalloc(BS_LINE, wchar_t *); // sections (in `line`) wchar_t *descr = walloca(BS_LINE); // description (in `line`) wchar_t *tmp, *buf; // temporary unsigned pages_len, sections_len, cur_page_len, cur_section_len, descr_len; // lengths of `pages`, `sections`, current entry in `pages`, // current entry in `sections` and `descr` int wline_len; // length of `wline` unsigned res_i = 0; // current result unsigned i, j; // iterators // Execute the command FILE *pp = xpopen(cmdstr, "r"); // For each `line` returned by the command... xfgets(line, BS_LONG, pp); while (!feof(pp)) { wline_len = xmbstowcs(wline, line, BS_LONG); if (-1 == wline_len) { if (0 == res_i) break; else winddown(ES_OPER_ERROR, L"Malformed apropos/whatis command output"); } wline[wline_len - 1] = L'\0'; // Extract `descr` descr = wcsstr(wline, L" - "); if (NULL == descr) { if (0 == res_i) break; else winddown(ES_OPER_ERROR, L"Malformed apropos/whatis command output"); } descr[0] = L'\0'; descr = &descr[3]; descr_len = wcslen(descr); // Extract `pages` tmp = wcstok(wline, L"(", &buf); if (NULL == tmp) { if (0 == res_i) break; else winddown(ES_OPER_ERROR, L"Malformed apropos/whatis command output"); } pages_len = wsplit(&pages, BS_LINE, wline, L",", false); // Extract `sections` tmp = wcstok(NULL, L")", &buf); if (NULL == tmp) { if (0 == res_i) break; else winddown(ES_OPER_ERROR, L"Malformed apropos/whatis command output"); } sections_len = wsplit(§ions, BS_LINE, tmp, L",", false); // For each page described by line... for (i = 0; i < pages_len; i++) { for (j = 0; j < sections_len; j++) { // Populate the `res_i`th element of `res` cur_page_len = wcslen(pages[i]); cur_section_len = wcslen(sections[j]); res[res_i].page = walloc(cur_page_len); wcslcpy(res[res_i].page, pages[i], cur_page_len + 1); res[res_i].section = walloc(cur_section_len); wcslcpy(res[res_i].section, sections[j], cur_section_len + 1); res[res_i].ident = walloc(cur_page_len + cur_section_len + 3); swprintf(res[res_i].ident, cur_page_len + cur_section_len + 3, L"%ls(%ls)", pages[i], sections[j]); res[res_i].descr = walloc(descr_len); wcslcpy(res[res_i].descr, descr, descr_len + 1); // Increase `res_i`, and reallocate `res` if necessary res_i++; if (res_i == res_len) { res_len += BS_LINE; res = xreallocarray(res, res_len, sizeof(aprowhat_t)); } } } xfgets(line, BS_LONG, pp); } int status = xpclose(pp); // If no results were returned by the command, set `err` to true and // describe the error in `err_msg`. Otherwise, set `err` to false. err = false; if (0 == res_i || 0 != status) { err = true; if (AW_WHATIS == cmd) swprintf(err_msg, BS_LINE, L"Whatis %ls: nothing apropriate", args); else { if (0 == wcscmp(args, L"''") || 0 == wcscmp(args, L"'.'")) swprintf(err_msg, BS_LINE, L"'apropos .' failed; did you run mandb/makewhatis?", args); else swprintf(err_msg, BS_LINE, L"Apropos %ls: nothing apropriate", args); } } // Deallocate unused memory and return if (res_i > 0) res = xreallocarray(res, res_i, sizeof(aprowhat_t)); free(line); free(wline); free(pages); free(sections); *dst = res; return res_i; } unsigned aprowhat_sections(wchar_t ***dst, const aprowhat_t *aw, unsigned aw_len) { unsigned i; wchar_t **res = aalloc(BS_SHORT, wchar_t *); unsigned res_i = 0; for (i = 0; i < aw_len && res_i < BS_SHORT; i++) { if (!wmemberof((const wchar_t **)res, aw[i].section, res_i)) { res[res_i] = wcsdup(aw[i].section); res_i++; } } wsort(res, res_i, false); *dst = res; return res_i; } unsigned aprowhat_render(line_t **dst, const aprowhat_t *aw, const unsigned aw_len, const wchar_t *const *sc, const unsigned sc_len, const wchar_t *key, const wchar_t *title, const wchar_t *ver, const wchar_t *date) { // Text blocks widths const unsigned line_width = MAX(60, config.layout.main_width); const unsigned lmargin_width = config.layout.lmargin; // left margin const unsigned rmargin_width = config.layout.rmargin; // right margin const unsigned text_width = line_width - lmargin_width - rmargin_width; // main text area const unsigned hfc_width = text_width / 2 + text_width % 2; // header/footer center area const unsigned hfl_width = (text_width - hfc_width) / 2; // header/footer left area const unsigned hfr_width = hfl_width + (text_width - hfc_width) % 2; // header/footer right area unsigned ln = 0; // current line number unsigned i, j; // iterators wchar_t tmp[BS_LINE]; // temporary memset(tmp, 0, sizeof(wchar_t) * BS_LINE); unsigned res_len = BS_LINE; // result buffer length line_t *res = aalloc(res_len, line_t); // result buffer // Header line_alloc(res[ln], line_width); const unsigned title_len = wcslen(title); // `title` length const unsigned key_len = wcslen(key); // `key` length const unsigned lts_len = (hfc_width - title_len) / 2 + (hfc_width - title_len) % 2; // length of space on the left of `title` const unsigned rts_len = (hfc_width - title_len) / 2; // length of space on the right of `title` swprintf(res[ln].text, line_width + 1, L"%*s%-*ls%*s%ls%*s%*ls%*s", // lmargin_width, "", // hfl_width, key, // lts_len, "", // title, // rts_len, "", // hfr_width, key, // rmargin_width, "" // ); bset(res[ln].uline, lmargin_width); bset(res[ln].reg, lmargin_width + key_len); bset(res[ln].uline, lmargin_width + hfl_width + hfc_width + hfr_width - key_len); bset(res[ln].reg, lmargin_width + hfl_width + hfc_width + hfr_width); // Only if list of sections is enabled if (config.capabilities.sections_on_top) { // Newline inc_ln; line_alloc(res[ln], 0); // Section title for sections inc_ln; line_alloc(res[ln], line_width); wcslcpy(tmp, L"SECTIONS", BS_LINE); swprintf(res[ln].text, line_width + 1, L"%*s%-*ls", // lmargin_width, "", // text_width, tmp); bset(res[ln].bold, lmargin_width); bset(res[ln].reg, lmargin_width + wcslen(tmp)); // Sections const unsigned sc_maxwidth = MIN( text_width / 2 - 4, wmaxlen(sc, sc_len)); // length of longest section const unsigned sc_cols = text_width / (4 + sc_maxwidth); // number of columns for sections const unsigned sc_lines = sc_len % sc_cols > 0 ? 1 + sc_len / sc_cols : MAX(1, sc_len / sc_cols); // number of lines for sections unsigned sc_i; // index of current section for (i = 0; i < sc_lines; i++) { inc_ln; line_alloc(res[ln], line_width + 4); // +4 for section margin swprintf(res[ln].text, line_width + 1, L"%*s", lmargin_width, ""); for (j = 0; j < sc_cols; j++) { sc_i = sc_cols * i + j; if (sc_i < sc_len) { swprintf(tmp, sc_maxwidth + 5, L" %-*ls", sc_maxwidth + 3, sc[sc_i]); wcslcat(res[ln].text, tmp, line_width + 1); swprintf(tmp, BS_LINE, L"MANUAL PAGES IN SECTION '%ls'", sc[sc_i]); add_link(&res[ln], lmargin_width + j * (sc_maxwidth + 4) + 1, lmargin_width + j * (sc_maxwidth + 4) + MIN(sc_maxwidth + 3, wcslen(sc[sc_i]) + 1), false, 0, 0, LT_LS, tmp); } } } } // For each section... for (i = 0; i < sc_len; i++) { // Newline inc_ln; line_alloc(res[ln], 0); // Section title inc_ln; line_alloc(res[ln], line_width); swprintf(tmp, text_width + 1, L"MANUAL PAGES IN SECTION '%ls'", sc[i]); swprintf(res[ln].text, line_width + 1, L"%*s%-*ls", // lmargin_width, "", // text_width, tmp); bset(res[ln].bold, lmargin_width); bset(res[ln].reg, lmargin_width + wcslen(tmp)); // For each manual page... for (j = 0; j < aw_len; j++) { // If manual page is in current section... if (0 == wcscmp(aw[j].section, sc[i])) { const unsigned lc_width = text_width / 3; // left column width const unsigned rc_width = text_width - lc_width; // right column width const unsigned page_width = wcslen(aw[j].page) + wcslen(aw[j].section) + 2; // width of manual page name and section const unsigned spcl_width = MAX(line_width, lmargin_width + page_width + rmargin_width); // used in place of line_width; might be // longer, in which case we'll scroll // Page name and section (`ident`) inc_ln; line_alloc(res[ln], spcl_width); swprintf(res[ln].text, spcl_width + 1, L"%*s%-*ls", // lmargin_width, "", // lc_width, aw[j].ident); add_link(&res[ln], lmargin_width, lmargin_width + wcslen(aw[j].ident), false, 0, 0, LT_MAN, aw[j].ident); // Description wcslcpy(tmp, aw[j].descr, BS_LINE); wwrap(tmp, rc_width); wchar_t *buf; wchar_t *ptr = wcstok(tmp, L"\n", &buf); if (NULL != ptr && page_width < lc_width) { wcslcat(res[ln].text, ptr, line_width + 1); ptr = wcstok(NULL, L"\n", &buf); } while (NULL != ptr) { inc_ln; line_alloc(res[ln], line_width); swprintf(res[ln].text, line_width + 1, L"%*s%ls", // lmargin_width + lc_width, "", // ptr); ptr = wcstok(NULL, L"\n", &buf); } } } } // Newline inc_ln; line_alloc(res[ln], 0); // Footer inc_ln; line_alloc(res[ln], line_width); const unsigned date_len = wcslen(date); // date length const unsigned lds_len = (hfc_width - date_len) / 2 + (hfc_width - date_len) % 2; // length of space on the left of date const unsigned rds_len = (hfc_width - date_len) / 2; // length of space on the right of date swprintf(res[ln].text, line_width + 1, L"%*s%-*ls%*s%ls%*s%*ls%*s", // lmargin_width, "", // hfl_width, ver, // lds_len, "", // date, // rds_len, "", // hfr_width, key, // rmargin_width, "" // ); bset(res[ln].uline, lmargin_width + hfl_width + hfc_width + hfr_width - key_len); bset(res[ln].reg, lmargin_width + hfl_width + hfc_width + hfr_width); *dst = res; return ln + 1; } int aprowhat_search(const wchar_t *needle, const aprowhat_t *hayst, unsigned hayst_len, unsigned pos, bool fullsub) { unsigned i; if (NULL == needle) return -1; for (i = pos; i < hayst_len; i++) if (fullsub) { if (wcsstr(hayst[i].ident, needle) > hayst[i].ident) return i; } else { if (wcsstr(hayst[i].ident, needle) == hayst[i].ident) return i; } return -1; } bool aprowhat_has(const wchar_t *needle, const aprowhat_t *hayst, unsigned hayst_len) { unsigned i; if (NULL == needle) return false; for (i = 0; i < hayst_len; i++) if (0 == wcscasecmp(hayst[i].ident, needle)) return true; return false; } unsigned man_sections(wchar_t ***dst, const wchar_t *args, bool local_file) { char gpath[BS_LINE]; // path to groff document for manual page int glen; // length of current line in groff document wchar_t gline[BS_LINE]; // current line in groff document unsigned en = 0; // current entry in `res` char tmp[BS_LINE]; // temporary unsigned res_len = BS_SHORT; // result buffer length wchar_t **res = aalloc(res_len, wchar_t *); // result buffer // Use `man` to figure out `gpath` if (false == man_loc(gpath, BS_LINE, args, local_file)) winddown(ES_OPER_ERROR, L"Failed to locate manual page source file"); // Open `gpath` archive_t gp = aropen(gpath); // For each line in `gpath`, `gline`... argets(gp, tmp, BS_LINE); while (!areof(gp)) { glen = xmbstowcs(gline, tmp, BS_LINE); if (-1 == glen) winddown(ES_OPER_ERROR, L"Failed to read manual page source"); // If line is a section heading, add the corresponding data to `res` if (got_sh) { // Section heading unsigned textsp = wmargend(&gline[3], L"\""); if (textsp > 0) { res[en] = walloc(BS_LINE); wcslcpy(res[en], &gline[3 + textsp], BS_LINE); wmargtrim(res[en], L"\""); inc_en; } } argets(gp, tmp, BS_LINE); } arclose(gp); secgroff(res, en); *dst = res; return en; } unsigned index_page(line_t **dst) { wchar_t key[] = L"INDEX"; wchar_t title[] = L"All Manual Pages"; time_t now = time(NULL); wchar_t date[BS_SHORT]; wcsftime(date, BS_SHORT, L"%x", gmtime(&now)); line_t *res; unsigned res_len = aprowhat_render(&res, aw_all, aw_all_len, (const wchar_t **)sc_all, sc_all_len, key, title, config.misc.program_version, date); *dst = res; return res_len; } unsigned aprowhat(line_t **dst, aprowhat_cmd_t cmd, const wchar_t *args, const wchar_t *key, const wchar_t *title) { aprowhat_t *aw; unsigned aw_len = aprowhat_exec(&aw, cmd, args); wchar_t **sc; unsigned sc_len = aprowhat_sections(&sc, aw, aw_len); time_t now = time(NULL); wchar_t date[BS_SHORT]; wcsftime(date, BS_SHORT, L"%x", gmtime(&now)); line_t *res; unsigned res_len = aprowhat_render(&res, aw, aw_len, (const wchar_t **)sc, sc_len, key, title, config.misc.program_version, date); aprowhat_free(aw, aw_len); wafree(sc, sc_len); *dst = res; return res_len; } unsigned man(line_t **dst, const wchar_t *args, bool local_file) { // Text blocks widths const unsigned line_width = MAX(60, config.layout.main_width); const unsigned lmargin_width = config.layout.lmargin; // left margin const unsigned rmargin_width = config.layout.rmargin; // right margin const unsigned text_width = line_width - lmargin_width - rmargin_width; // main text area unsigned ln = 0; // current line number int len; // length of current line text unsigned i, j; // iterators wchar_t *tmpw = walloc(BS_LINE); // temporary char *tmps = salloc(BS_LINE); // temporary bool ilink = false; // we are inside an embedded HTTP link unsigned ilink_ln; // embedded link line int ilink_start; // embedded link start position int ilink_end; // embedded link end position int ilink_start_next; // embedded link start position (in next line, for // hyphenated links) int ilink_end_next; // embedded link end position (in next line, for // hypehnated links) wchar_t ilink_trgt[BS_LINE]; // embedded link URL unsigned res_len = BS_LINE; // result buffer length line_t *res = aalloc(res_len, line_t); // result buffer // Set up the environment for `man` to create its output as we want it char *old_term = getenv("TERM"); setenv("TERM", "xterm", true); char *old_manpager = getenv("MANPAGER"); setenv("MANPAGER", "", true); if (ST_MANDB == config.misc.system_type) { // `mandb` specific sprintf(tmps, "%d", 1 + text_width); setenv("MANWIDTH", tmps, true); sprintf(tmps, "%s %s", config.capabilities.hyphenate ? "" : "--nh", config.capabilities.justify ? "" : "--nj"); setenv("MANOPT", tmps, true); setenv("MAN_KEEP_FORMATTING", "1", true); setenv("MANROFFOPT", "", true); setenv("GROFF_SGR", "1", true); unsetenv("GROFF_NO_SGR"); } else if (ST_MANDOC == config.misc.system_type) { // `mandoc` specific } else if (ST_FREEBSD == config.misc.system_type || ST_DARWIN == config.misc.system_type) { // FreeBSD and macOS X `man` specific sprintf(tmps, "%d", 1 + text_width); setenv("MANWIDTH", tmps, true); unsetenv("MANCOLOR"); } // Prepare `man` command char cmdstr[BS_LINE]; if (ST_MANDB == config.misc.system_type) { // `mandb` specific wchar_t *gargs = L""; // `man` arguments for global apropos/whatis if (!config.layout.tui) { if (config.misc.global_apropos) gargs = L"--global-apropos"; else if (config.misc.global_whatis) gargs = L"--all"; } if (local_file) snprintf(cmdstr, BS_LINE, "%s --warnings='!all' --local-file %ls 2>>/dev/null", config.misc.man_path, args); else snprintf(cmdstr, BS_LINE, "%s --warnings='!all' %ls %ls 2>>/dev/null", config.misc.man_path, gargs, args); } else if (ST_MANDOC == config.misc.system_type) { // `mandoc` specific unsigned args_len = wcslen(args); // length of `args` wchar_t *page = walloca(args_len); // man page extracted from `args` wchar_t *section = walloca(args_len); // man section extracted from `args` unsigned extracted; // return value of `extract_args()` extracted = extract_args(&page, §ion, args_len, args); if (0 == extracted) winddown(ES_CHILD_ERROR, L"Unable to parse command-line arguments"); if (local_file) snprintf(cmdstr, BS_LINE, "%s -T utf8 -O width=%d -l '%ls' 2>>/dev/null", config.misc.man_path, text_width, page); else { if (2 == extracted) snprintf(cmdstr, BS_LINE, "%s -T utf8 -O width=%d '%ls' '%ls' 2>>/dev/null", config.misc.man_path, text_width, section, page); else snprintf(cmdstr, BS_LINE, "%s -T utf8 -O width=%d '%ls' 2>>/dev/null", config.misc.man_path, text_width, page); } } else if (ST_FREEBSD == config.misc.system_type || ST_DARWIN == config.misc.system_type) { // FreeBSD and macOS X `man` specific unsigned args_len = wcslen(args); // length of `args` wchar_t *page = walloca(args_len); // man page extracted from `args` wchar_t *section = walloca(args_len); // man section extracted from `args` unsigned extracted; // return value of `extract_args()` extracted = extract_args(&page, §ion, args_len, args); if (1 == extracted) snprintf(cmdstr, BS_LINE, "%s '%ls' 2>>/dev/null", config.misc.man_path, page); else if (2 == extracted) snprintf(cmdstr, BS_LINE, "%s '%ls' '%ls' 2>>/dev/null", config.misc.man_path, section, page); else winddown(ES_CHILD_ERROR, L"Unable to parse command-line arguments"); } // Execute `man` FILE *pp = xpopen(cmdstr, "r"); // Discard any empty lines on top, and read the first non-empty line into // `tmps`/`tmpw` xfgets(tmps, BS_LINE, pp); len = xmbstowcs(tmpw, tmps, BS_LINE); i = 0; while (!feof(pp) && (0 == len || L'\n' == tmpw[wmargend(tmpw, L"\n")])) { xfgets(tmps, BS_LINE, pp); len = xmbstowcs(tmpw, tmps, BS_LINE); } // For each line of `man`'s output... while (!feof(pp)) { // At line 1, insert the list of sections (if enabled) if (1 == ln && config.capabilities.sections_on_top && !config.misc.global_apropos && !config.misc.global_whatis) { // Newline line_alloc(res[ln], 0); // Section title for sections inc_ln; line_alloc(res[ln], line_width); wcslcpy(tmpw, L"SECTIONS", BS_LINE); swprintf(res[ln].text, line_width + 1, L"%*s%-*ls", // lmargin_width, "", // text_width, tmpw); bset(res[ln].bold, lmargin_width); bset(res[ln].reg, lmargin_width + wcslen(tmpw)); // Sections wchar_t **sc; // sections unsigned sc_len = man_sections(&sc, args, local_file); // no. of sections const unsigned sc_maxwidth = MIN(text_width / 2 - 4, wmaxlen((const wchar_t *const *)sc, sc_len)); // length of longest section const unsigned sc_cols = text_width / (4 + sc_maxwidth); // number of columns for sections const unsigned sc_lines = sc_len % sc_cols > 0 ? 1 + sc_len / sc_cols : MAX(1, sc_len / sc_cols); // number of lines for sections unsigned sc_i; // index of current section for (i = 0; i < sc_lines; i++) { inc_ln; line_alloc(res[ln], line_width + 4); // +4 for section margin swprintf(res[ln].text, line_width + 1, L"%*s", lmargin_width, ""); for (j = 0; j < sc_cols; j++) { sc_i = sc_cols * i + j; if (sc_i < sc_len) { swprintf(tmpw, sc_maxwidth + 5, L" %-*ls", sc_maxwidth + 3, sc[sc_i]); wcslower(tmpw); wcslcat(res[ln].text, tmpw, line_width + 1); add_link(&res[ln], lmargin_width + j * (sc_maxwidth + 4) + 1, lmargin_width + j * (sc_maxwidth + 4) + MIN(sc_maxwidth + 3, wcslen(sc[sc_i])) + 1, false, 0, 0, LT_LS, sc[sc_i]); } } } inc_ln; wafree(sc, sc_len); len = xmbstowcs(tmpw, tmps, BS_LINE); } if (-1 == len) { if (0 == ln) break; else winddown(ES_CHILD_ERROR, L"Malformed man command output"); } // Allocate memory for a new line in `res` line_alloc(res[ln], config.layout.lmargin + len + 1); // Add spaces for left margin for (j = 0; j < config.layout.lmargin; j++) res[ln].text[j] = L' '; // Read the contents of `tmpw` one character at a time, and build the // line's `text`, `reg`, `bold`, `italic`, and `uline` members bool bold_nosgr = false; // a 'bold' typewriter sequence has been seen bool uline_nosgr = false; // a 'underline' typewriter sequence has been seen for (i = 0; i < len; i++) { if (got_not_bold) { bset(res[ln].reg, j); i += 3; } else if (got_not_italic || got_not_uline || got_normal) { bset(res[ln].reg, j); i += 4; } else if (got_bold) { bset(res[ln].bold, j); i += 3; } else if (bold_nosgr && !got_bold_nosgr) { bset(res[ln].reg, j); bold_nosgr = false; res[ln].text[j] = tmpw[i]; j++; } else if (got_bold_nosgr) { if (!bold_nosgr) bset(res[ln].bold, j); bold_nosgr = true; i += 2; res[ln].text[j] = tmpw[i]; j++; } else if (got_italic) { bset(res[ln].italic, j); i += 3; } else if (got_uline) { bset(res[ln].uline, j); i += 3; } else if (uline_nosgr && !got_uline_nosgr) { bset(res[ln].reg, j); uline_nosgr = false; res[ln].text[j] = tmpw[i]; j++; } else if (got_uline_nosgr) { if (!uline_nosgr) bset(res[ln].uline, j); uline_nosgr = true; i += 2; res[ln].text[j] = tmpw[i]; j++; } else if (got_esc8) { i += 3; if (ilink) { if (ilink_ln == ln) { ilink_end = j; add_link(&res[ln], ilink_start, j, false, 0, 0, LT_HTTP, ilink_trgt); } else if (ln > 0) { ilink_end = res[ln - 1].length - 1; ilink_start_next = wmargend(res[ln].text, NULL); ilink_end_next = j; add_link(&res[ln - 1], ilink_start, ilink_end, true, ilink_start_next, ilink_end_next, LT_HTTP, ilink_trgt); } ilink = false; } else { if (tmpw[i] == L';' && tmpw[i + 1] == L';') { i += 2; unsigned k = 0; while (!(tmpw[i] == L'\e' && tmpw[i + 1] == L'\\')) { ilink_trgt[k] = tmpw[i]; i++; k++; } ilink_trgt[k] = L'\0'; i += 1; ilink = true; ilink_ln = ln; ilink_start = j; } } while (i < len && !(tmpw[i - 1] == L'\e' && tmpw[i] == L'\\')) i++; } else if (got_any_1) { i += 3; } else if (got_any_2) { i += 4; } else if (got_any_3) { i += 5; } else if (tmpw[i] != L'\n') { res[ln].text[j] = tmpw[i]; j++; } } // Insert the obligatory 0 byte at the end of the line's text, and set its // exact length res[ln].text[j] = L'\0'; res[ln].length = j + 1; // Read next line of `man` output into `tmps`/`tmpw` xfgets(tmps, BS_LINE, pp); len = xmbstowcs(tmpw, tmps, BS_LINE); inc_ln; } // Restore the environment if (NULL != old_term) setenv("TERM", old_term, true); if (NULL != old_manpager) setenv("MANPAGER", old_manpager, true); int status = xpclose(pp); free(tmpw); free(tmps); // Discover and add links (skipping the first two lines, and the last line) if (ln >= 2) { for (unsigned i = 2; i < ln - 1; i++) { discover_links(&re_man, &res[i], &res[i + 1], LT_MAN); if (config.capabilities.http_links) discover_links(&re_http, &res[i], &res[i + 1], LT_HTTP); if (config.capabilities.email_links) discover_links(&re_email, &res[i], &res[i + 1], LT_EMAIL); if (config.capabilities.file_links) discover_links(&re_file, &res[i], &res[i + 1], LT_FILE); } } // If no results were returned by `man`, set `err` to true and describe the // error in `err_msg`. Otherwise, set `err` to false. err = false; if (0 == ln || status != 0) { err = true; swprintf(err_msg, BS_LINE, L"No manual page for %ls", args); } *dst = res; return ln; } unsigned man_toc(toc_entry_t **dst, const wchar_t *args, bool local_file) { char gpath[BS_LINE]; // path to groff document for manual page int glen; // length of current line in groff document wchar_t gline[BS_LINE]; // current line in groff document unsigned en = 0; // current entry in `res` bool sh_seen = false; // whether a section header has been seen char tmp[BS_LINE]; // temporary unsigned textsp; // real beginning of `gline`'s text (ignoring whitespace) unsigned res_len = BS_LINE; // result buffer length toc_entry_t *res = aalloc(res_len, toc_entry_t); // result buffer // Section header for the list of sections (if enabled) if (config.capabilities.sections_on_top) { res[en].type = TT_HEAD; res[en].text = walloc(BS_LINE); wcslcpy(res[en].text, L"SECTIONS", BS_LINE); inc_en; } // Correct arguments and use `man` to figure out `gpath` if (false == man_loc(gpath, BS_LINE, args, local_file)) winddown(ES_OPER_ERROR, L"Failed to locate manual page source file"); // Open `gpath` archive_t gp = aropen(gpath); // For each line in `gpath`, `gline`... argets(gp, tmp, BS_LINE); while (!areof(gp)) { glen = xmbstowcs(gline, tmp, BS_LINE); if (-1 == glen) winddown(ES_OPER_ERROR, L"Failed to read manual page source"); // If line can be a TOC entry, add the corresponding data to `res` if (got_sh) { // Section heading res[en].type = TT_HEAD; textsp = wmargend(&gline[3], L"\""); if (textsp > 0) { res[en].text = walloc(BS_LINE); wcslcpy(res[en].text, &gline[3 + textsp], BS_LINE); wmargtrim(res[en].text, L"\""); inc_en; sh_seen = true; } } else if (got_ss && sh_seen) { // Subsection heading res[en].type = TT_SUBHEAD; textsp = wmargend(&gline[3], L"\""); if (textsp > 0) { res[en].text = walloc(BS_LINE); wcslcpy(res[en].text, &gline[3 + textsp], BS_LINE); wmargtrim(res[en].text, L"\""); inc_en; } } else if (got_tp && sh_seen) { // Tagged paragraph argets(gp, tmp, BS_LINE); if (!areof(gp)) { glen = xmbstowcs(gline, tmp, BS_LINE); { // Edge case: the tag line contains only a comment or a line that // must otherwise be skipped; skip to next line while (got_comment || got_tp || got_pd) { argets(gp, tmp, BS_LINE); if (areof(gp)) break; glen = xmbstowcs(gline, tmp, BS_LINE); } } { // Edge case: the tag line starts with a formatting command that // sets a trap for the next line; skip to the next line while (got_trap && wmargtrim(gline, NULL) < 4) { argets(gp, tmp, BS_LINE); if (areof(gp)) break; glen = xmbstowcs(gline, tmp, BS_LINE); } if (areof(gp)) break; } { // Edge case: the tag line starts with a non-acceptable command; // ignore it if (L'.' == gline[0] && (!got_ok)) continue; } textsp = wmargend(gline, NULL); res[en].type = TT_TAGPAR; res[en].text = walloc(BS_LINE); wcslcpy(res[en].text, &gline[textsp], BS_LINE); glen = wmargtrim(res[en].text, L"\n"); { // Edge case: there's a line escape at the end of the tag line; // remove it if (glen >= 1 && L'\\' == res[en].text[glen - 1]) res[en].text[glen - 1] = L'\0'; if (glen >= 2 && L'\\' == res[en].text[glen - 2] && L'c' == res[en].text[glen - 1]) { res[en].text[glen - 2] = L'\0'; res[en].text[glen - 1] = L'\0'; } } inc_en; } } argets(gp, tmp, BS_LINE); } arclose(gp); tocgroff(res, en); *dst = res; return en; } unsigned sc_toc(toc_entry_t **dst, const wchar_t *const *sc, const unsigned sc_len) { unsigned i; // iterator unsigned en = 0; // current entry in TOC unsigned res_len = BS_SHORT; // result buffer length toc_entry_t *res = aalloc(res_len, toc_entry_t); // result buffer // Section header for the list of sections (if enabled) if (config.capabilities.sections_on_top) { res[en].type = TT_HEAD; res[en].text = walloc(BS_LINE); wcslcpy(res[en].text, L"SECTIONS", BS_LINE); inc_en; } // All other other section headers for (i = 0; i < sc_len; i++) { res[en].type = TT_HEAD; res[en].text = walloc(BS_LINE); swprintf(res[en].text, BS_LINE, L"MANUAL PAGES IN SECTION '%ls'", sc[i]); inc_en; } *dst = res; return en; } CC_IGNORE_UNUSED_PARAMETER link_loc_t prev_link(const line_t *lines, unsigned lines_len, link_loc_t start) { CC_IGNORE_ENDS unsigned i; link_loc_t res; // If `start` was not found, return not found if (!start.ok) { res.ok = false; return res; } // If line no. `start.line` has a link before `start.link`, return that link if (start.link > 0) { res.ok = true; res.line = start.line; res.link = start.link - 1; return res; } // Otherwise, return the last link of the first line before line no. // `start.line` that has links for (i = start.line - 1; i > 0; i--) { if (lines[i].links_length > 0) { res.ok = true; res.line = i; res.link = lines[i].links_length - 1; return res; } } // Return not found if that fails res.ok = false; return res; } link_loc_t next_link(const line_t *lines, unsigned lines_len, link_loc_t start) { unsigned i; link_loc_t res; // If start was not found, return not found if (!start.ok) { res.ok = false; return res; } // If `start.line` is larger than `lines_len`, return not found if (start.line >= lines_len) { res.ok = false; return res; } // If line no. `start.line` has a link after `start.link`, return that link if (lines[start.line].links_length > start.link + 1) { res.ok = true; res.line = start.line; res.link = start.link + 1; return res; } // Otherwise, return the first link of the first line after line no. // `start.line` that has links for (i = start.line + 1; i < lines_len; i++) { if (lines[i].links_length > 0) { res.ok = true; res.line = i; res.link = 0; return res; } } // Return not found if that fails res.ok = false; return res; } link_loc_t first_link(const line_t *lines, unsigned lines_len, unsigned start, unsigned stop) { unsigned i; link_loc_t res; // Sanitize arguments, and return not found if they don't make sense if (stop > lines_len) stop = lines_len; if (start > lines_len || start > stop) { res.ok = false; return res; } // Attempt to find and return the first link in the line range for (i = start; i <= stop; i++) { if (lines[i].links_length > 0) { res.ok = true; res.line = i; res.link = 0; return res; } } // If that fails, return not found res.ok = false; return res; } link_loc_t last_link(const line_t *lines, unsigned lines_len, unsigned start, unsigned stop) { unsigned i; link_loc_t res; // Sanitize arguments, and return not found if they don't make sense if (stop > lines_len) stop = lines_len; if (start > lines_len || start > stop) { res.ok = false; return res; } // Attempt to find and return the last link in the line range for (i = stop; i >= start && i != (unsigned)-1; i--) { if (lines[i].links_length > 0) { res.ok = true; res.line = i; res.link = lines[i].links_length - 1; return res; } } // If that fails, return not found res.ok = false; return res; } unsigned search(result_t **dst, const wchar_t *needle, const line_t *lines, unsigned lines_len, bool cs) { unsigned ln; // current line no. unsigned i = 0; // current result no. const unsigned needle_len = wcslen(needle); // length of `needle` wchar_t *cur_hayst; // current haystuck (i.e. text of current line) wchar_t *hit = NULL; // current return value of `wcscasestr()` unsigned res_len = BS_LINE; // result buffer length result_t *res = aalloc(res_len, result_t); // result buffer // For each line... for (ln = 0; ln < lines_len; ln++) { // Start at the beginning of the line's text cur_hayst = lines[ln].text; // Search for `needle` if (cs) hit = wcscasestr(cur_hayst, needle); else hit = wcsstr(cur_hayst, needle); // While `needle` has been found... while (NULL != hit) { // Add the search result to `res[i]` res[i].line = ln; res[i].start = hit - lines[ln].text; res[i].end = res[i].start + needle_len; // Go to the part of the line's text that follows `needle` cur_hayst = hit + needle_len; // And search for `needle` again if (cur_hayst - lines[ln].text < lines[ln].length) if (cs) hit = wcscasestr(cur_hayst, needle); else hit = wcsstr(cur_hayst, needle); else hit = NULL; // Increment `i` (and reallocate memory if necessary) inc_i; } } // If no results were found, free the result buffer if (0 == i) free(res); *dst = res; return i; } int search_next(result_t *res, unsigned res_len, unsigned from) { unsigned i; for (i = 0; i < res_len; i++) if (res[i].line >= from) return res[i].line; return -1; } int search_prev(result_t *res, unsigned res_len, unsigned from) { int i; for (i = res_len - 1; i >= 0; i--) if (res[i].line <= from) return res[i].line; return -1; } extern unsigned get_mark(wchar_t **dst, mark_t mark, const line_t *lines) { // Return if no text is marked if (!mark.enabled) { *dst = NULL; return 0; } unsigned res_len = BS_LINE * config.layout.height; // return value length wchar_t *res = walloc(res_len); // return value wchar_t tmp[BS_LINE]; // temporary unsigned ln; // current line number // Necessary to get rid of valgrind warnings memset(res, 0, sizeof(wchar_t) * BS_LINE * config.layout.height); memset(tmp, 0, sizeof(wchar_t) * BS_LINE); // Generate return value if (mark.start_line == mark.end_line) { // Marked text is in a single line wcsncpy(res, &lines[mark.start_line].text[mark.start_char], 1 + mark.end_char - mark.start_char); } else { // Marked text is in multiple lines for (ln = mark.start_line; ln <= mark.end_line; ln++) { if (ln == mark.start_line) { // First line; append text from `start_char` to end of line wcslcat(res, &lines[ln].text[mark.start_char], res_len); } else if (ln == mark.end_line) { // Last line; append text from beginning of line to `end_char` wcsncpy(tmp, lines[ln].text, 1 + mark.end_char); tmp[1 + mark.end_char] = L'\0'; wcslcat(res, tmp, res_len); } else { // Intermediary lines; append entire line text wcslcat(res, lines[ln].text, res_len); } } } *dst = res; return wcslen(res); } void populate_page() { // If `page` is already populated, free its allocated memory if (NULL != page && page_len > 0) { lines_free(page, page_len); page = NULL; page_len = 0; } // Reset `toc` if (NULL != toc && toc_len > 0) toc_free(toc, toc_len); toc = NULL; toc_len = 0; // Populate page according to the request type of `history[history_cur]` switch (history[history_cur].request_type) { case RT_INDEX: wcslcpy(page_title, L"All Manual Pages", BS_SHORT); entitle(page_title); page_len = index_page(&page); break; case RT_MAN: swprintf(page_title, BS_SHORT, L"Manual page(s) for: %ls", history[history_cur].args); entitle(page_title); page_len = man(&page, history[history_cur].args, false); break; case RT_MAN_LOCAL: swprintf(page_title, BS_SHORT, L"Manual page in local file(s): %ls", history[history_cur].args); entitle(page_title); page_len = man(&page, history[history_cur].args, true); break; case RT_APROPOS: swprintf(page_title, BS_SHORT, L"Apropos for: %ls", history[history_cur].args); entitle(page_title); page_len = aprowhat(&page, AW_APROPOS, history[history_cur].args, L"APROPOS", page_title); break; case RT_WHATIS: swprintf(page_title, BS_SHORT, L"Whatis for: %ls", history[history_cur].args); entitle(page_title); page_len = aprowhat(&page, AW_WHATIS, history[history_cur].args, L"WHATIS", page_title); break; default: winddown(ES_OPER_ERROR, L"Unexpected program request"); } // Reset search `results` if (NULL != results && results_len > 0) free(results); results = NULL; results_len = 0; } void populate_toc() { // If the TOC doesn't exist yet, use `man_toc()` or `sc_toc()` to generate // it now if (NULL == toc || 0 == toc_len) { request_type_t rt = history[history_cur].request_type; // current request type wchar_t *args = history[history_cur].args; // arguments for current request aprowhat_t *aw; // temporary unsigned aw_len; // " wchar_t **sc; // " unsigned sc_len; // " switch (rt) { case RT_INDEX: toc_len = sc_toc(&toc, (const wchar_t *const *)sc_all, sc_all_len); break; case RT_MAN: toc_len = man_toc(&toc, args, false); break; case RT_MAN_LOCAL: toc_len = man_toc(&toc, args, true); break; case RT_APROPOS: aw_len = aprowhat_exec(&aw, AW_APROPOS, args); if (err) winddown(ES_OPER_ERROR, err_msg); sc_len = aprowhat_sections(&sc, aw, aw_len); toc_len = sc_toc(&toc, (const wchar_t *const *)sc, sc_len); if (NULL != aw && aw_len > 0) aprowhat_free(aw, aw_len); if (NULL != sc && sc_len > 0) wafree(sc, sc_len); break; default: aw_len = aprowhat_exec(&aw, AW_WHATIS, args); if (err) winddown(ES_OPER_ERROR, err_msg); sc_len = aprowhat_sections(&sc, aw, aw_len); toc_len = sc_toc(&toc, (const wchar_t *const *)sc, sc_len); if (NULL != aw && aw_len > 0) aprowhat_free(aw, aw_len); if (NULL != sc && sc_len > 0) wafree(sc, sc_len); break; } } // If the TOC still doesn't exist, something must have gone wrong if (0 == toc_len || NULL == toc) winddown(ES_OPER_ERROR, L"Unable to generate table of contents"); } void requests_free(request_t *reqs, unsigned reqs_len) { unsigned i; for (i = 0; i < reqs_len; i++) if (NULL != reqs[i].args) free(reqs[i].args); free(reqs); } void aprowhat_free(aprowhat_t *aw, unsigned aw_len) { unsigned i; for (i = 0; i < aw_len; i++) { free(aw[i].page); free(aw[i].section); free(aw[i].ident); free(aw[i].descr); } free(aw); } void lines_free(line_t *lines, unsigned lines_len) { unsigned i; for (i = 0; i < lines_len; i++) { line_free(lines[i]); } free(lines); } void toc_free(toc_entry_t *toc, unsigned toc_len) { unsigned i; for (i = 0; i < toc_len; i++) { if (NULL != toc[i].text) free(toc[i].text); } free(toc); } void winddown(int ec, const wchar_t *em) { // Shut ncurses down winddown_tui(); // Deallocate memory used by base64 base64_cleanup(); // Deallocate memory used by `config` global if (NULL != config.chars.sbar_top) free(config.chars.sbar_top); if (NULL != config.chars.sbar_vline) free(config.chars.sbar_vline); if (NULL != config.chars.sbar_bottom) free(config.chars.sbar_bottom); if (NULL != config.chars.sbar_block) free(config.chars.sbar_block); if (NULL != config.chars.trans_mode_name) free(config.chars.trans_mode_name); if (NULL != config.chars.trans_name_loc) free(config.chars.trans_name_loc); if (NULL != config.chars.trans_prompt_help) free(config.chars.trans_prompt_help); if (NULL != config.chars.trans_prompt_em) free(config.chars.trans_prompt_em); if (NULL != config.chars.box_hline) free(config.chars.box_hline); if (NULL != config.chars.box_vline) free(config.chars.box_vline); if (NULL != config.chars.box_tl) free(config.chars.box_tl); if (NULL != config.chars.box_tr) free(config.chars.box_tr); if (NULL != config.chars.box_bl) free(config.chars.box_bl); if (NULL != config.chars.box_br) free(config.chars.box_br); if (NULL != config.chars.arrow_up) free(config.chars.arrow_up); if (NULL != config.chars.arrow_down) free(config.chars.arrow_down); if (NULL != config.chars.arrow_lr) free(config.chars.arrow_lr); if (NULL != config.misc.program_version) free(config.misc.program_version); if (NULL != config.misc.config_path) free(config.misc.config_path); if (NULL != config.misc.man_path) free(config.misc.man_path); if (NULL != config.misc.groff_path) free(config.misc.groff_path); if (NULL != config.misc.whatis_path) free(config.misc.whatis_path); if (NULL != config.misc.apropos_path) free(config.misc.apropos_path); if (NULL != config.misc.browser_path) free(config.misc.browser_path); if (NULL != config.misc.mailer_path) free(config.misc.mailer_path); if (NULL != config.misc.viewer_path) free(config.misc.viewer_path); // Deallocate memory used by `history` global requests_free(history, config.misc.history_size); // Deallocate memory used by `aw_all` global if (NULL != aw_all && aw_all_len > 0) aprowhat_free(aw_all, aw_all_len); // Deallocate memory used by `sc_all` global if (NULL != sc_all && sc_all_len > 0) wafree(sc_all, sc_all_len); // Deallocate memory used by `page` global if (NULL != page && page_len > 0) lines_free(page, page_len); // Deallocate memory used by `toc` global if (NULL != toc && toc_len > 0) toc_free(toc, toc_len); // Deallocate memory used by `results` global if (NULL != results && results_len > 0) free(results); // Deallocate memory used by `re_...` regular expression globals regfree(&re_man.re); regfree(&re_http.re); regfree(&re_email.re); regfree(&re_file.re); // (Optionally print `em` and) exit if (NULL != em) fwprintf(stderr, L"%ls\n", em); exit(ec); } qman-1.5.1/src/program.h000066400000000000000000000457011510660157000150710ustar00rootroot00000000000000// Program-specific infrastructure (definition) #ifndef PROGRAM_H #define PROGRAM_H #include "lib.h" // // Types // // Option argument type typedef enum { OA_NONE, // no argument OA_OPTIONAL, // argument is optional OA_REQUIRED // argument is required } option_arg_t; // A command-line option typedef struct { char *long_opt; // i.e. --`verbose` char short_opt; // i.e. -`v` wchar_t *help_text; // i.e. `Print verbose output` option_arg_t arg; // i.e. --config=`myconfrc` bool _cont; // when false, indicates end of array // (example values are reverse quoted) } option_t; // Location of a link in an array of lines typedef struct { bool ok; // true if the location exists, false otherwise unsigned line; // line number unsigned link; // link number } link_loc_t; // Page request type typedef enum { RT_NONE, // empty request; only used by `init()` and later replaced by // an actual request type RT_INDEX, // show a list of all manual pages RT_MAN, // show a manual page RT_MAN_LOCAL, // show a manual page stored in a local file RT_APROPOS, // search for manual pages and their descriptions RT_WHATIS // show all available manual pages that match a name } request_type_t; // A page request typedef struct { request_type_t request_type; wchar_t *args; // arguments for the man/apropos/whatis command // The following are used by `history_...()` functions, to record the user's // location in each history entry (history entries are instances of // `request_t`) unsigned top; // latest `page_top` unsigned left; // latest `page_left` link_loc_t flink; // latest `page_flink` } request_t; // Choice between apropos and whatis typedef enum { AW_APROPOS, AW_WHATIS } aprowhat_cmd_t; // An apropos or whatis result typedef struct { wchar_t *page; // Manual page wchar_t *section; // Section wchar_t *ident; // Combined (

) wchar_t *descr; // Description } aprowhat_t; // Link type typedef enum { LT_MAN, // manual page LT_HTTP, // http(s) URL LT_EMAIL, // email address LT_FILE, // file in the local filesystem LT_LS // local search: find `trgt` in the current document } link_type_t; // A link typedef struct { unsigned start; // character no. where the link starts unsigned end; // character no. the link ends bool in_next; // whether link gets hyphenated into the next line unsigned start_next; // character no. where the next line portion of the link // starts (if hyphenated) unsigned end_next; // character no. where the next line portion of the link // ends (if hyphenated) link_type_t type; // type of link wchar_t *trgt; // link target (e.g. "ls(1)" or "http://www.google.com/") } link_t; // A line of text typedef struct { unsigned length; // the line's length wchar_t *text; // the line's text unsigned links_length; // number of links in line link_t *links; // links in line // Places in the line the text becomes... bitarr_t reg; // regular bitarr_t bold; // bold bitarr_t italic; // italic bitarr_t uline; // underlined } line_t; // A table of contents entry type typedef enum { TT_HEAD = 0, // section heading TT_SUBHEAD = 1, // section subheading TT_TAGPAR = 2 // tagged paragraph } toc_type_t; // A table of contents entry typedef struct toc_entry_t { toc_type_t type; // type wchar_t *text; // text } toc_entry_t; // A search result typedef struct { unsigned line; // line number unsigned start; // character no. where the result starts unsigned end; // character no. where the result ends } result_t; // Marked text typedef struct { bool enabled; // whether we are marking text unsigned start_line; // line no. where the mark starts unsigned start_char; // character no. where the mark starts unsigned end_line; // line no. where the mark ends unsigned end_char; // character no. where the mark ends } mark_t; // // Constants // // Exit statuses (same as those of `man` command) #define ES_SUCCESS 0 // successful completion #define ES_USAGE_ERROR 1 // user provided wrong command-line option #define ES_OPER_ERROR 2 // program error #define ES_CHILD_ERROR 3 // child process error #define ES_CONFIG_ERROR 4 // configuration file parse error #define ES_NOT_FOUND 16 // manual page(s) not found // // Global variables // // Program options extern option_t options[]; // Program action to perform upon program startup extern action_t first_action; // History of page requests extern request_t *history; // Location of current request in `history` extern unsigned history_cur; // Location of top request in `history` (i.e. the last page inserted in it) extern unsigned history_top; // All manual pages on this system extern aprowhat_t *aw_all; // Number of entries in `aw_all` extern unsigned aw_all_len; // All manual sections on this system extern wchar_t **sc_all; // Number of entries in `sc_all` extern unsigned sc_all_len; // The page currently being displayed extern line_t *page; // Title of current page extern wchar_t page_title[BS_SHORT]; // Number of lines in `page` extern unsigned page_len; // Focused link in current page extern link_loc_t page_flink; // Line where the portion of `page` displayed to the user begins extern unsigned page_top; // Column where the portion of `page` displayed to the user begins extern unsigned page_left; // Table of contents for current page extern toc_entry_t *toc; // Number of entries in `toc` extern unsigned toc_len; // True if last `man`/`apropos`/`whatis` command didn't produce any result extern bool err; // Formatted error message for last `man`/`apropos`/`whatis` failure extern wchar_t err_msg[BS_LINE]; // Search results in current page extern result_t *results; // Total number of search results in current page extern unsigned results_len; // Marked text extern mark_t mark; // Regular expressions for a link to... extern full_regex_t re_man, // a manual page re_http, // an http(s) URL re_email, // an email address re_file; // a file in the local filesystem // // Macros // // Allocate memory for all members of `line` of type `line_t` and length `len`. // Then, initialize its members to sensible initial values, specifically its // `length` to `len` and its `text` to an empty string. #define line_alloc(line, len) \ line.length = len; \ line.text = walloc(len); \ line.text[0] = '\0'; \ line.links_length = 0; \ line.links = NULL; \ if (len > 0) { \ line.reg = balloc(len); \ bclearall(line.reg, len); \ line.bold = balloc(len); \ bclearall(line.bold, len); \ line.italic = balloc(len); \ bclearall(line.italic, len); \ line.uline = balloc(len); \ bclearall(line.uline, len); \ } else { \ line.reg = NULL; \ line.bold = NULL; \ line.italic = NULL; \ line.uline = NULL; \ } // Allocate memory for an extra link for `line`, and increase its `link_length` // by 1 #define line_realloc_link(line) \ line.links_length++; \ line.links = xreallocarray(line.links, line.links_length, sizeof(link_t)); // Free memory for all members of `line` (of type `line_t`) #define line_free(line) \ free(line.text); \ links_free(line.links, line.links_length); \ free(line.reg); \ free(line.bold); \ free(line.italic); \ free(line.uline); // Free memory for all members of `links` (of type `link_t`) #define links_free(links, links_len) \ for (unsigned link_free_i = 0; link_free_i < links_len; link_free_i++) \ free(links[link_free_i].trgt); \ free(links); // Return the string representation of `type` (of type `request_type_t`) #define request_type_str(t) \ RT_INDEX == t \ ? L"INDEX" \ : (RT_MAN == t ? L"MAN" \ : (RT_MAN_LOCAL == t \ ? L"LOCAL" \ : (RT_APROPOS == t ? L"APROPOS" : L"WHATIS"))) // If `n` is smaller than or equal to `history_cur`, go back `n` steps in // `history` and return true. Otherwise, return false. #define history_back(n) history_jump(history_cur - n) // If `n + history_cur` is smaller than or equal to `history_top`, go forward // `n` steps in `history` and return true. Otherwise, return false. #define history_forward(n) history_jump(history_cur + n) // // Functions // // Initialize all major program components. Additional initialization is later // performed by `late_init()`, `init_tui()` and `init_cli()`. extern void init(); // Initialize additional program components after `configure()` has been // performed extern void late_init(); // Retrieve `argc` and `argv` from `main()` and parse the command line options. // Modify `config` and `history` appropriately, and return `optind`. Exit in // case of usage error. extern int parse_options(int argc, char *const *argv); // Retrieve `argc` and `argv` with the command line options removed, and modify // `history` appropriately. Exit in case of usage error. extern void parse_args(int argc, char *const *argv); // Print program version extern void version(); // Print usage information extern void usage(); // All `history_...()` functions also save and restore `page_top` and // `page_flink` inside the history entries they manipulate, to keep track of the // user's location in each history entry. // Populate the current history entry (i.e. `history[history_cur]`), setting its // `request_type` to `rt`, and its `args` to `args` extern void history_replace(request_type_t rt, const wchar_t *args); // Push a new entry into `history`, as follows: // Add a new history entry after `history_cur`, and populate it with `rt` and // `args` using `history_replace()`. Increase `history_cur`, and adjust // `history_top` so that it remains equal to or greater than it. extern void history_push(request_type_t rt, const wchar_t *args); // If `pos` is larger or equal to 0 and smaller or equal to `history_top`, jump // to history position `pos` and return true. Otherwise, return false. extern bool history_jump(int pos); // Discard all history entries after `history_cur`, and make `history_top` equal // to `history_cur` extern void history_reset(); // In case a `man`/`apropos`/`whatis` command fails to produce any results, // `aprowhat_exec()` and `man()` set `err` to true and `err_msg` to an // appropriate error message. // Execute `apropos` or `whatis`, and place their result in `dst`. Return the // number of entries found. `cmd` and `args` respectively specify the command to // run and its arguments. extern unsigned aprowhat_exec(aprowhat_t **dst, aprowhat_cmd_t cmd, const wchar_t *args); // Given a result of `aprowhat()` in `aw` (of length `aw_len`), extract the // names of its manual sections into `dst`. Return the total number of sections // found. extern unsigned aprowhat_sections(wchar_t ***dst, const aprowhat_t *aw, unsigned aw_len); // Helper of `aprowhat()` and `index_page()`. Render a result of `aprowhat()` // `aw` (of length `aw_len`), and a result of `aprowhat_sections()` `sc` (of // length `sc_len`) into into a manual page like index document, and place it // into `dst`. Return the number of lines. `key`, `title`, `ver`, and `date` // are used for generating the header and footer. extern unsigned aprowhat_render(line_t **dst, const aprowhat_t *aw, const unsigned aw_len, const wchar_t *const *sc, const unsigned sc_len, const wchar_t *key, const wchar_t *title, const wchar_t *ver, const wchar_t *date); // Search for elements of `hayst` (of length `hayst_len`), whose `ident` // contains `needle` (if `fullsub`) or starts with `needle` (if not `fullsub`). // Return the first matching position in `hayst` after `pos`, or -1 if nothing // can be matched. extern int aprowhat_search(const wchar_t *needle, const aprowhat_t *hayst, unsigned hayst_len, unsigned pos, bool fullsub); // Return true if there is an element in `hayst` (of length `hayst_len`) whose // `ident` is case-insensitive equal to `needle` extern bool aprowhat_has(const wchar_t *needle, const aprowhat_t *hayst, unsigned hayst_len); // Use `man` and `groff` to extract the section headers of a manual page. Place // the result in `dst`, and return `dst`'s length. `args` and `local_file` have // the same meanings as their synonymous arguments of `man()`. extern unsigned man_sections(wchar_t ***dst, const wchar_t *args, bool local_file); // Render an index of all of the system's manual pages, placing it into `dst`. // Return the number of lines rendered. extern unsigned index_page(line_t **dst); // Execute `apropos` or `whatis`, and place the final rendered result in `dst`. // Return the number of lines in said output. `cmd` and `args` respectively // specify the command to run and its arguments. `key` and `title` specify a // short and long title respectively, to be inserted in the header and footer. extern unsigned aprowhat(line_t **dst, aprowhat_cmd_t cmd, const wchar_t *args, const wchar_t *key, const wchar_t *title); // Execute `man`, and place its final rendeered output in `dst`. Return the // number of lines in said output. `args` specifies the arguments for the `man` // command. `local_file` signifies whether to pass the --local-file option to // `man`. extern unsigned man(line_t **dst, const wchar_t *args, bool local_file); // Use `man` and `groff` to extract the table of contents of a manual page. // Place the result in `dst`, and return `dst`'s length. `args` and `local_file` // have the same meanings as their synonymous arguments of `man()`. extern unsigned man_toc(toc_entry_t **dst, const wchar_t *args, bool local_file); // Create the table of contents of the an apropos, whatis or index page. The // sections of said page must be provided in `sc` (of length `sc_len`). extern unsigned sc_toc(toc_entry_t **dst, const wchar_t *const *sc, const unsigned sc_len); // Find the previous link in `lines` (of legth `lines_len`), starting at // location `start`. Return said link's location. extern link_loc_t prev_link(const line_t *lines, unsigned lines_len, link_loc_t start); // Find the next link in `lines` (of length `lines_len`), starting at location // `start`. Return said link's location. extern link_loc_t next_link(const line_t *lines, unsigned lines_len, link_loc_t start); // Return the first link in `lines` (of length `lines_len`) that appears in line // number range [`start`, `stop`] extern link_loc_t first_link(const line_t *lines, unsigned lines_len, unsigned start, unsigned stop); // Return the last link in `lines` (of length `lines_len`) that appears in line // number range [`start`, `stop`] extern link_loc_t last_link(const line_t *lines, unsigned lines_len, unsigned start, unsigned stop); // Search for `needle` in `lines` (of length `lines_len`). Place all results // into `dst` and return the total number of results. `cs` siginifies whether // search will be case-insensitive. extern unsigned search(result_t **dst, const wchar_t *needle, const line_t *lines, unsigned lines_len, bool cs); // Return the line number of the member of `res` that immediately follows line // number `from`. If no such line exists, return -1. `res_len` is the length of // `res`. extern int search_next(result_t *res, unsigned res_len, unsigned from); // Return the line number of the member of `res` that immediately precedes line // number `from`. If no such line exists, return -1. `res_len` is the length of // `res`. extern int search_prev(result_t *res, unsigned res_len, unsigned from); // Extract from `lines` the text indicated by `mark`, and place it into `dst`, // allocating all needed memory. Return the length of `dst`. In case of error, // this function sets `dst` to NULL and returns 0. extern unsigned get_mark(wchar_t **dst, mark_t mark, const line_t *lines); // Note: for efficiency, we only populate `toc` and `toc_len` when the user // requests a table of contents for the first time // Populate `page`, `page_title`, and `page_len`, based on the contents of // `history[history_cur]`. Reset `results`, `results_len`, `toc` and `toc_len`. extern void populate_page(); // Populate `toc` and `toc_len` extern void populate_toc(); // Free the memory occupied by `reqs` (of length `reqs_len`) extern void requests_free(request_t *reqs, unsigned reqs_len); // Free the memory occupied by `aw` (of length `aw_len`) extern void aprowhat_free(aprowhat_t *aw, unsigned aw_len); // Free the memory occupied by `lines` (of length `lines_len`) extern void lines_free(line_t *lines, unsigned lines_len); // Free the memory occupied by `toc` (of length `toc_len`) extern void toc_free(toc_entry_t *toc, unsigned toc_len); // Exit the program gracefully, with exit code `ec`. If `em` is not NULL, echo // it on stdout before exiting. extern void winddown(int ec, const wchar_t *em); #endif qman-1.5.1/src/qman.c000066400000000000000000000006731510660157000143500ustar00rootroot00000000000000// Main program #include "lib.h" // Where it all begins int main(int argc, char **argv) { init(); // Parse program options and arguments, and populate history int noopt_argc = parse_options(argc, argv); int clean_argc = argc - noopt_argc; char **clean_argv = &argv[noopt_argc]; parse_args(clean_argc, clean_argv); // Run the main handler if (config.layout.tui) tui(); else cli(); winddown(ES_SUCCESS, NULL); } qman-1.5.1/src/qman_tests.c000066400000000000000000000234211510660157000155660ustar00rootroot00000000000000// Unit testing // To create a test named `foo`: // - Define your test function `void test_foo()` // - Insert `add_test(foo)` into `main()` // // Invoking `qman_tests ` runs a specific test, while `qman_tests // all` runs all tests. // // Exit codes: // 0: all tests succeeded // n: n failures happened during testing // -1: test not found // // Invoking `qman_tests all` runs all tests, and returns the number of failures // in its exit code. #include "lib.h" #include #include // // Helper macros // // Initialize the test suite #define init_test_suite() \ bool test_found = false; \ int errors = 0; \ CU_pSuite suite; \ if (argc > 1) { \ printf("Running: "); \ CU_initialize_registry(); \ suite = CU_add_suite("qman", NULL, NULL); \ } // Add test `tst`. The name of the test function must be `test_`. #define add_test(tst) \ if (argc > 1) { \ if (0 == strcmp(argv[1], #tst) || 0 == strcmp(argv[1], "all")) { \ test_found = true; \ printf(#tst "\n "); \ CU_add_test(suite, #tst, test_##tst); \ } \ } // Depending on `argc`/`argv`, run one test, or run all tests, or print usage // information. Then exit. #define run_tests_and_exit() \ if (argc > 1) { \ if (test_found) { \ printf("\n"); \ CU_basic_run_tests(); \ errors = CU_get_number_of_failures(); \ CU_cleanup_registry(); \ winddown(errors, NULL); \ } else { \ printf("No such test '%s'\n", argv[1]); \ winddown(-1, NULL); \ } \ } else { \ printf("Usage: %s # run a single test\n", argv[0]); \ printf(" %s all # run all tests\n", argv[0]); \ winddown(0, NULL); \ } // // Test functions // void test_eini_parse() { eini_t parsed; eini_init(); parsed = eini_parse("include /usr/share/foo"); CU_ASSERT_EQUAL(parsed.type, EINI_INCLUDE); CU_ASSERT(0 == wcscmp(parsed.value, L"/usr/share/foo")); parsed = eini_parse("\t include\t\t/usr/share/foo "); CU_ASSERT_EQUAL(parsed.type, EINI_INCLUDE); CU_ASSERT(0 == wcscmp(parsed.value, L"/usr/share/foo")); parsed = eini_parse("include \"/usr/share/foo\""); CU_ASSERT_EQUAL(parsed.type, EINI_INCLUDE); CU_ASSERT(0 == wcscmp(parsed.value, L"/usr/share/foo")); parsed = eini_parse(" include \t \'/usr/share/foo\' \t "); CU_ASSERT_EQUAL(parsed.type, EINI_INCLUDE); CU_ASSERT(0 == wcscmp(parsed.value, L"/usr/share/foo")); parsed = eini_parse("include /usr/share/foo ; comment"); CU_ASSERT_EQUAL(parsed.type, EINI_INCLUDE); CU_ASSERT(0 == wcscmp(parsed.value, L"/usr/share/foo")); parsed = eini_parse("include \"/usr/share/foo\" ; comment"); CU_ASSERT_EQUAL(parsed.type, EINI_INCLUDE); CU_ASSERT(0 == wcscmp(parsed.value, L"/usr/share/foo")); parsed = eini_parse("include \'/usr/share/foo ; comment\'"); CU_ASSERT_EQUAL(parsed.type, EINI_INCLUDE); CU_ASSERT(0 == wcscmp(parsed.value, L"/usr/share/foo ; comment")); parsed = eini_parse("[section_one]"); CU_ASSERT_EQUAL(parsed.type, EINI_SECTION); CU_ASSERT(0 == wcscmp(parsed.value, L"section_one")); parsed = eini_parse(" [\tSectionTwo ]\t\t \n"); CU_ASSERT_EQUAL(parsed.type, EINI_SECTION); CU_ASSERT(0 == wcscmp(parsed.value, L"SectionTwo")); parsed = eini_parse("\t [ Section3 ] \t"); CU_ASSERT_EQUAL(parsed.type, EINI_SECTION); CU_ASSERT(0 == wcscmp(parsed.value, L"Section3")); parsed = eini_parse("[SectionIV]; comment"); CU_ASSERT_EQUAL(parsed.type, EINI_SECTION); CU_ASSERT(0 == wcscmp(parsed.value, L"SectionIV")); parsed = eini_parse("key_1=an egg"); CU_ASSERT_EQUAL(parsed.type, EINI_VALUE); CU_ASSERT(0 == wcscmp(parsed.key, L"key_1")); CU_ASSERT(0 == wcscmp(parsed.value, L"an egg")); parsed = eini_parse("\t KeyTwo = another eggie \t "); CU_ASSERT_EQUAL(parsed.type, EINI_VALUE); CU_ASSERT(0 == wcscmp(parsed.key, L"KeyTwo")); CU_ASSERT(0 == wcscmp(parsed.value, L"another eggie")); parsed = eini_parse( "\t third_key = ένα αυγουλάκι που in English το λένε eggie \n"); CU_ASSERT_EQUAL(parsed.type, EINI_VALUE); CU_ASSERT(0 == wcscmp(parsed.key, L"third_key")); CU_ASSERT( 0 == wcscmp(parsed.value, L"ένα αυγουλάκι που in English το λένε eggie")); parsed = eini_parse("key4= \"ακόμη ένα eggie ή αυγό\""); CU_ASSERT_EQUAL(parsed.type, EINI_VALUE); CU_ASSERT(0 == wcscmp(parsed.key, L"key4")); CU_ASSERT(0 == wcscmp(parsed.value, L"ακόμη ένα eggie ή αυγό")); parsed = eini_parse("key5=ASCII specials are \\a \\b \\t \\n \\v \\f \\r and \\e"); CU_ASSERT_EQUAL(parsed.type, EINI_VALUE); CU_ASSERT(0 == wcscmp(parsed.key, L"key5")); CU_ASSERT(0 == wcscmp(parsed.value, L"ASCII specials are \a \b \t \n \v \f \r and \e")); parsed = eini_parse("key_VI=Other specials: \\\\ \\' and \\\", naturally"); CU_ASSERT_EQUAL(parsed.type, EINI_VALUE); CU_ASSERT(0 == wcscmp(parsed.key, L"key_VI")); CU_ASSERT(0 == wcscmp(parsed.value, L"Other specials: \\ ' and \", naturally")); parsed = eini_parse("se7en=\"in double \\\" quotes\\r\""); CU_ASSERT_EQUAL(parsed.type, EINI_VALUE); CU_ASSERT(0 == wcscmp(parsed.key, L"se7en")); CU_ASSERT(0 == wcscmp(parsed.value, L"in double \" quotes\r")); parsed = eini_parse("se7enUp= \'in single \\' quotes\\\\\'"); CU_ASSERT_EQUAL(parsed.type, EINI_VALUE); CU_ASSERT(0 == wcscmp(parsed.key, L"se7enUp")); CU_ASSERT(0 == wcscmp(parsed.value, L"in single \' quotes\\")); parsed = eini_parse(""); CU_ASSERT_EQUAL(parsed.type, EINI_NONE); parsed = eini_parse("[garbled$ect_on]"); CU_ASSERT_EQUAL(parsed.type, EINI_ERROR); CU_ASSERT(0 == wcscmp(parsed.value, L"Unable to parse '[garbled$ect_on]'")); parsed = eini_parse("κλειδί=value"); CU_ASSERT_EQUAL(parsed.type, EINI_ERROR); CU_ASSERT(0 == wcscmp(parsed.value, L"Unable to parse 'κλειδί=value'")); parsed = eini_parse("key=\"value"); // "value CU_ASSERT_EQUAL(parsed.type, EINI_ERROR); CU_ASSERT(0 == wcscmp(parsed.value, L"Non-terminated quote")); parsed = eini_parse("key=\"value\\\""); // "value\" CU_ASSERT_EQUAL(parsed.type, EINI_ERROR); CU_ASSERT(0 == wcscmp(parsed.value, L"Non-terminated quote")); parsed = eini_parse("key=\"value\\\\\""); // "value\\" CU_ASSERT_EQUAL(parsed.type, EINI_VALUE); CU_ASSERT(0 == wcscmp(parsed.key, L"key")); CU_ASSERT(0 == wcscmp(parsed.value, L"value\\")); parsed = eini_parse("key=\"value\\\\\\\""); // "value\\\" CU_ASSERT_EQUAL(parsed.type, EINI_ERROR); CU_ASSERT(0 == wcscmp(parsed.value, L"Non-terminated quote")); parsed = eini_parse("key='value"); // 'value CU_ASSERT_EQUAL(parsed.type, EINI_ERROR); CU_ASSERT(0 == wcscmp(parsed.value, L"Non-terminated quote")); parsed = eini_parse("key='value\\'"); // 'value\' CU_ASSERT_EQUAL(parsed.type, EINI_ERROR); CU_ASSERT(0 == wcscmp(parsed.value, L"Non-terminated quote")); parsed = eini_parse("key='value\\\\'"); // 'value\\' CU_ASSERT_EQUAL(parsed.type, EINI_VALUE); CU_ASSERT(0 == wcscmp(parsed.key, L"key")); CU_ASSERT(0 == wcscmp(parsed.value, L"value\\")); parsed = eini_parse("key='value\\\\\\'"); // 'value\\\' CU_ASSERT_EQUAL(parsed.type, EINI_ERROR); CU_ASSERT(0 == wcscmp(parsed.value, L"Non-terminated quote")); parsed = eini_parse("key=value ; comment"); CU_ASSERT_EQUAL(parsed.type, EINI_VALUE); CU_ASSERT(0 == wcscmp(parsed.key, L"key")); CU_ASSERT(0 == wcscmp(parsed.value, L"value")); parsed = eini_parse("key='value' ; comment"); CU_ASSERT_EQUAL(parsed.type, EINI_VALUE); CU_ASSERT(0 == wcscmp(parsed.key, L"key")); CU_ASSERT(0 == wcscmp(parsed.value, L"value")); parsed = eini_parse("key=\"value ; comment\""); CU_ASSERT_EQUAL(parsed.type, EINI_VALUE); CU_ASSERT(0 == wcscmp(parsed.key, L"key")); CU_ASSERT(0 == wcscmp(parsed.value, L"value ; comment")); parsed = eini_parse("key='value ; comment"); CU_ASSERT_EQUAL(parsed.type, EINI_ERROR); CU_ASSERT(0 == wcscmp(parsed.value, L"Non-terminated quote")); parsed = eini_parse("blah"); CU_ASSERT_EQUAL(parsed.type, EINI_ERROR); CU_ASSERT(0 == wcscmp(parsed.value, L"Unable to parse 'blah'")); eini_winddown(); } // Where we hope it works int main(int argc, char **argv) { init(); init_cli(); init_test_suite(); // `add_test()` all your tests here add_test(eini_parse); run_tests_and_exit(); } qman-1.5.1/src/qman_tests_list.sh000077500000000000000000000006601510660157000170140ustar00rootroot00000000000000#!/usr/bin/env bash # List all configured tests. This is a helper script used by meson. FILE="qman_tests.c" MATCH="^[[:space:]]*add_test(" LTRIM="s/[[:space:]]*add_test(//g" RTRIM="s/);//g" exit_on_error() { if [ "X${1}" != "X0" ] then echo "Command failed" exit ${1} fi } cd "$( dirname "${BASH_SOURCE[0]}" )" exit_on_error $? grep "${MATCH}" "${FILE}" | sed "${LTRIM}" | sed "${RTRIM}" exit_on_error $? exit 0 qman-1.5.1/src/tui.c000066400000000000000000002544641510660157000142260ustar00rootroot00000000000000// Text user interface (implementation) #include "lib.h" // // Global variables // tcap_t tcap; WINDOW *wmain = NULL; WINDOW *wsbar = NULL; WINDOW *wstat = NULL; WINDOW *wimm = NULL; action_t action = PA_NULL; mouse_t mouse_status = MS_EMPTY; // // Helper macros and functions // // Helper of `draw_page()`. Set `col` to the appropriate color for link number // `linkno` of line number `lineno`. The color depends on the link's `type`, and // on the value of `flink` (since the focused link is highlighted). #define set_link_col(lineno, linkno, type) \ if (flink.ok && flink.line == lineno && flink.link == linkno) { \ switch (type) { \ case LT_MAN: \ col = config.colours.link_man_f; \ break; \ case LT_HTTP: \ col = config.colours.link_http_f; \ break; \ case LT_EMAIL: \ col = config.colours.link_email_f; \ break; \ case LT_FILE: \ col = config.colours.link_file_f; \ break; \ case LT_LS: \ default: \ col = config.colours.link_ls_f; \ } \ } else { \ switch (type) { \ case LT_MAN: \ col = config.colours.link_man; \ break; \ case LT_HTTP: \ col = config.colours.link_http; \ break; \ case LT_EMAIL: \ col = config.colours.link_email; \ break; \ case LT_FILE: \ col = config.colours.link_file; \ break; \ case LT_LS: \ default: \ col = config.colours.link_ls; \ } \ } // Helper of `tui_open()`. Re-initialize ncurses after shelling out. #define tui_reset \ { \ winddown_tui(); \ init_tui(); \ init_tui_tcap(); \ init_tui_colours(); \ init_tui_mouse(); \ termsize_changed(); \ init_windows(); \ populate_page(); \ if (err) \ winddown(ES_OPER_ERROR, err_msg); \ if (termsize_changed()) \ termsize_adjust(); \ tui_redraw(); \ doupdate(); \ } // Helper of `tui_open()`, `tui_open_apropos()` and `tui_open_whatis()`. If // `page_flink` isn't valid, error out and return false. #define error_on_invalid_flink \ if (!page_flink.ok || page_flink.line < page_top || \ page_flink.line >= page_top + config.layout.main_height || \ page_flink.line >= page_len || \ page_flink.link >= page[page_flink.line].links_length) { \ tui_error(L"Unable to open link"); \ return false; \ } // Helper of `tui_toc()`. Search the current page for a line whose text matches // the text of the `focus`ed entry in `toc`. // // This function calls `ls_jump()`. To increase accuracy, it tries to set its // `trgt_prev` argument to the section or subsection that preceeds the `focus`ed // entry in `toc`. #define toc_jump(toc, focus) \ int prev; \ for (prev = MAX(0, focus - 1); prev >= 0; prev--) \ if (TT_HEAD == toc[prev].type || TT_SUBHEAD == toc[prev].type) \ break; \ ls_jump(toc[focus].text, toc[prev].text); // Helper of `tui_open()` and `toc_jump()`, i.e. `tui_toc()`. Search the current // page for a line whose text matches `trgt`, and jump to said line. (But if // `trgt_prev` is not NULL, make sure that the matched line is preceded by a // line whose text matches `trgt_prev`.) #define ls_jump(trgt, trgt_prev) \ { \ wchar_t trgt_clone[BS_LINE]; \ wcslcpy(trgt_clone, trgt, BS_LINE); \ int best; \ if (NULL == trgt_prev) \ best = 0; \ else { \ wchar_t trgt_prev_clone[BS_LINE]; \ /* ?/: is necessary to avoid a spurious -Wnonnull compiler warning */ \ wcslcpy(trgt_prev_clone, NULL != trgt_prev ? trgt_prev : L"", BS_LINE); \ best = ls_discover(trgt_prev_clone, 0); \ } \ best = ls_discover(trgt_clone, best); \ if (best < 0) { \ tui_error(L"Unable to jump to requested location"); \ return false; \ } else { \ page_top = MIN(best, page_len - config.layout.main_height); \ const link_loc_t fl = first_link( \ page, page_len, page_top, page_top + config.layout.main_height - 1); \ if (fl.ok) \ page_flink = fl; \ } \ } // Helper of `sigusr1_handler()`. Reset terminal RGB color values to their // defaults. void sigusr1_reset() { if (0 == strcmp(tcap.term, "xterm-ghostty")) { // To reset its color palette, ghostty needs a special escape code sendescseq("]104"); } else { // For all other terminals, we use their reset strings, as provided by // terminfo char *s; if ((s = tigetstr("rs1")) != NULL) putp(s); if ((s = tigetstr("rs2")) != NULL) putp(s); if ((s = tigetstr("rs3")) != NULL) putp(s); fflush(stdout); config.misc.terminfo_reset = true; // The above might put the terminal in cooked mode and/or enable echo raw(); noecho(); } } // Re-configure the program. `init_tui()` makes sure this is called whenever // `SIGUSR1` is received. CC_IGNORE_UNUSED_PARAMETER void sigusr1_handler(int signum) { CC_IGNORE_ENDS // Don't attempt attempt to reconfigure on ancient terminals if (tcap.colours < 256 || tcap.term == strstr(tcap.term, "rxvt")) { return; } sigusr1_reset(); // Reconfigure configure(); late_init(); init_tui_tcap(); if (-1 == config.tcap.colours || t_auto == config.tcap.rgb || t_auto == config.tcap.unicode || t_auto == config.tcap.clipboard) configure(); init_tui_colours(); init_tui_mouse(); doupdate(); // Cause next `termsize_changed()` to succeed, thus forcing a redraw config.layout.width = 0; config.layout.height = 0; } // Helper of `ls_jump()`, i.e. of `tui_open()` and `tui_toc()`. Return the line // number that best matches local searh link target `trgt`, or -1 if error. // Start searching at line number `sln`. int ls_discover(wchar_t *trgt, unsigned sln) { wchar_t **trgt_words = alloca(BS_SHORT * sizeof(wchar_t *)); // words in trgt unsigned trgt_words_len; // no. of words in trgt wchar_t **cand_words = walloca(BS_SHORT * sizeof(wchar_t *)); // words in current candidate line unsigned cand_words_len; // no. of words in current candidate line unsigned ln; // current line number unsigned line_nos[BS_LINE]; // candidate line numbers unsigned line_scores[BS_LINE]; // candidate line scores unsigned max_no = 0; // line number with maximum score unsigned max_score = 0; // maximum score unsigned i, j; // iterators trgt_words_len = wsplit(&trgt_words, BS_SHORT, trgt, NULL, false); if (0 == trgt_words_len) return -1; if (sln >= page_len) return -1; // Record candidate lines and their scores j = 0; for (ln = sln; ln < page_len && j < BS_LINE; ln++) { wchar_t text[BS_LINE]; // current line text wcslcpy(text, page[ln].text, BS_LINE); if (wcsstr(text, trgt_words[0]) == &text[wmargend(text, NULL)]) { // In order for a line to be a candidate, it must begin with the first // word in `trgt` line_nos[j] = ln; line_scores[j] = 0; // Candidate line score is calculated as 2x the number of its words that // exactly match the words in `trgt`. An extra point is added to said // score if the last word in `trgt` matches just the beginning of its // corresponding word in `cand` cand_words_len = wsplit(&cand_words, BS_SHORT, text, NULL, false); for (i = 0; i < MIN(trgt_words_len, cand_words_len); i++) if (0 == wcscmp(cand_words[i], trgt_words[i])) line_scores[j] += 2; else if (trgt_words_len - 1 == i) if (cand_words[i] == wcsstr(cand_words[i], trgt_words[i])) line_scores[j]++; // Candidates that got full marks, and either (a) don't include any // additional words or (b) are less indended than the following line, get // an extra point if (line_scores[j] == trgt_words_len) { if (cand_words_len == trgt_words_len) line_scores[j]++; else if (ln < page_len - 1) { if (wmargend(page[ln + 1].text, NULL) > wmargend(text, NULL)) line_scores[j]++; } } j++; } } // Return the candidate line with the highest score for (i = 0; i < j; i++) if (line_scores[i] > max_score) { max_no = line_nos[i]; max_score = line_scores[i]; } return max_no; } // Helper of `tui_sp_open()`. Print incremental search results in `wimm` as the // user types. If the user has selected a result using arrow keys or the mouse, // highlight it and return its `ident` (if `qident` is true) or `page` (if // `quident` is false). Otherwise return NULL. The string typed so far is // provided in `needle`. `last` contains the last return value of // `get_str_next()`. wchar_t *aw_quick_search(wchar_t *needle, int last, bool qident) { // Search `aw_all` for `needle` and store the results in `res` unsigned lines = config.layout.imm_height_long - 7; // maximum no. of lines to display static int focus = -1; // focused line unsigned needle_len = wcslen(needle); // length of `needle` static unsigned last_needle_len = 0; // length of last `needle` encountered unsigned *res = aalloca(lines, unsigned); // search results as positions in `aw_all` unsigned pos; // current position in `aw_all` unsigned ln = 0; // current line wchar_t *ret = NULL; // Search `aw_all` for pages beginning with `needle`, and add them into `res` pos = 0; pos = aprowhat_search(needle, aw_all, aw_all_len, pos, false); while (-1 != pos && ln < lines) { res[ln] = pos; pos = aprowhat_search(needle, aw_all, aw_all_len, ++pos, false); ln++; } // If there's space, also search for pages that contain `needle`, and add them // to `res` as well (only if `config.misc.sp_substrings` is true) if (config.capabilities.sp_substrings) { pos = 0; pos = aprowhat_search(needle, aw_all, aw_all_len, pos, true); while (-1 != pos && ln < lines) { res[ln] = pos; pos = aprowhat_search(needle, aw_all, aw_all_len, ++pos, true); ln++; } } lines = ln; // `lines` becomes exact no. of lines to display // Update `focus`, if the user has used the arrow keys or mouse to highlight a // line if (0 == needle_len || last_needle_len != needle_len) { focus = -1; last_needle_len = needle_len; } else { if (-KEY_DOWN == last || -0x09 == last || -GSN_WH_UP == last) { focus++; if (focus >= lines) focus = 0; } else if (-KEY_UP == last || -GSN_WH_DOWN == last) { focus--; if (focus < 0) focus = lines - 1; } else if (-GSN_BT_LEFT == last) { mouse_t lms = get_mouse_status(KEY_MOUSE); int iy = lms.y, ix = lms.x; unsigned ih = getmaxy(wimm); if (wmouse_trafo(wimm, &iy, &ix, false)) if (iy > 3 && iy < ih - 3) focus = iy - 4; } } // Display the search results const unsigned width = config.layout.imm_width_wide - 4; // immediate window width wchar_t *tmp = walloca(width - 4); // temporary unsigned ident_len = 0; // space dedicated to `ident` column for (ln = 0; ln < lines; ln++) ident_len = MAX(ident_len, wcslen(aw_all[res[ln]].ident)); const unsigned descr_len = width - ident_len - 5; // space left for `descr` column swprintf(tmp, width - 3, L"%-*ls", width - 4, L""); mvwaddnwstr(wimm, 2, 2 + needle_len, tmp, width - 4 - needle_len); for (ln = 0; ln < lines; ln++) { change_colour(wimm, config.colours.sp_text); if (focus == ln) { if (qident) ret = aw_all[res[ln]].ident; else ret = aw_all[res[ln]].page; if (wcsstr(ret, needle) == ret) { swprintf(tmp, width - 3, L"%-*ls", width - 4, &ret[needle_len]); mvwaddnwstr(wimm, 2, 2 + needle_len, tmp, width - 4 - needle_len); } else { swprintf(tmp, width - 3, L" %ls %-*ls", config.chars.arrow_lr, width - 8, ret); mvwaddnwstr(wimm, 2, 2 + needle_len, tmp, width - 4 - needle_len); } change_colour(wimm, config.colours.sp_text_f); } swprintf(tmp, width - 3, L"%-*ls %-*ls", ident_len, aw_all[res[ln]].ident, descr_len, aw_all[res[ln]].descr); mvwaddnwstr(wimm, ln + 4, 2, tmp, width - 4); } for (ln = lines; ln < config.layout.imm_height_long - 7; ln++) { swprintf(tmp, width - 3, L"%*ls", width - 4, L""); mvwaddnwstr(wimm, ln + 4, 2, tmp, width - 4); } wnoutrefresh(wimm); return ret; } // Helper of `tui_help()`. Draw the help menu into `wimm`. `keys_names` contains // the string representations of key character mappings corresponding to all // program actions, `keys_names_max` is the length of the longest string in // `keys_names`, `top` is the first action to print help for, and `focus` is the // action to focus on. void draw_help(const wchar_t *const *keys_names, unsigned keys_names_max, unsigned top, unsigned focus) { const unsigned width = getmaxx(wimm); // help window width const unsigned height = getmaxy(wimm); // help window height const unsigned end = MIN(PA_QUIT, top + height - 6); // last action to print help for wchar_t *buf = walloca(width - 2); // temporary unsigned i, j; // iterators j = 2; for (i = top; i <= end; i++) { wchar_t glyph; if (i == top && i > 1) glyph = *config.chars.arrow_up; else if (i == end && i < PA_QUIT) glyph = *config.chars.arrow_down; else glyph = L' '; swprintf(buf, width - 1, L" %-*ls %-*.*ls %lc", keys_names_max, keys_names[i], width - keys_names_max - 7, width - keys_names_max - 7, keys_help[i], glyph); if (i == focus) { change_colour(wimm, config.colours.help_text_f); } else { change_colour(wimm, config.colours.help_text); } mvwaddnwstr(wimm, j, 1, buf, width - 1); j++; } wmove(wimm, height - 2, width - 2); wnoutrefresh(wimm); } // Helper for `tui_history()`. Draw the history menu into `wimm`. `history`, // `history_cur`, and `history_top` have the same meanings as the `history`, // `history_cur`, and `history_top` globals respectively. `top` is the first // history entry to print, and `focus` indicates the entry to focus on. void draw_history(request_t *history, unsigned history_cur, unsigned history_top, unsigned top, unsigned focus) { const unsigned width = getmaxx(wimm); // history window width const unsigned height = getmaxy(wimm); // history window height const unsigned end = MIN(history_top, top + height - 6); // last entry to print wchar_t *buf = walloca(width - 2); // temporary unsigned i, j; // iterators j = 2; for (i = top; i <= end; i++) { wchar_t glyph; if (i == top && i > 0) glyph = *config.chars.arrow_up; else if (i == end && i < history_top) glyph = *config.chars.arrow_down; else glyph = L' '; swprintf(buf, width - 1, L"%1ls %-7ls %-*.*ls %lc", i == history_cur ? L"»" : L" ", request_type_str(history[i].request_type), width - 15, width - 15, NULL == history[i].args ? L"" : history[i].args, glyph); if (i == focus) { change_colour(wimm, config.colours.history_text_f); } else { change_colour(wimm, config.colours.history_text); } mvwaddnwstr(wimm, j, 1, buf, width - 1); j++; } wmove(wimm, height - 2, width - 2); wnoutrefresh(wimm); } // Helper for `tui_toc()`. Draw a table of contents into `wimm`. `toc` contains // the table of contents entries, `toc_len` is the number of entries in `toc`, // `top` is the first entry to print, and `focus` the entry to focus on. void draw_toc(toc_entry_t *toc, unsigned toc_len, unsigned top, unsigned focus) { const unsigned width = getmaxx(wimm); // TOC window width const unsigned height = getmaxy(wimm); // TOC window height const unsigned end = MIN(toc_len - 1, top + height - 6); // last header to print wchar_t *buf = walloca(width - 2); // temporary unsigned i, j; // iterator j = 2; for (i = top; i <= end; i++) { wchar_t glyph; if (i == top && i > 0) glyph = *config.chars.arrow_up; else if (i == end && i < toc_len - 1) glyph = *config.chars.arrow_down; else glyph = L' '; swprintf(buf, width - 1, L"%*ls%-*.*ls %lc", 2 * toc[i].type, L"", width - 4 - 2 * toc[i].type, width - 4 - 2 * toc[i].type, toc[i].text, glyph); if (i == focus) { change_colour(wimm, config.colours.toc_text_f); } else { change_colour(wimm, config.colours.toc_text); } mvwaddnwstr(wimm, j, 1, buf, width - 1); j++; } wmove(wimm, height - 2, width - 2); wnoutrefresh(wimm); } // // Functions (generic) // void init_tui() { // Initialize and set up ncurses set_escdelay(config.tcap.escdelay); initscr(); raw(); keypad(stdscr, true); noecho(); curs_set(0); timeout(2000); start_color(); // Set up on-the-fly reconfiguration signal(SIGUSR1, sigusr1_handler); } void init_tui_tcap() { tcap.term = getenv("TERM"); if (-1 == config.tcap.colours) { if (has_colors()) tcap.colours = COLORS; else tcap.colours = 0; } else { tcap.colours = config.tcap.colours; } switch (config.tcap.rgb) { case t_true: tcap.rgb = true; break; case t_false: tcap.rgb = false; break; case t_auto: tcap.rgb = (tcap.colours >= 256) && can_change_color(); } switch (config.tcap.unicode) { case t_true: tcap.unicode = true; break; case t_false: tcap.unicode = false; break; case t_auto: tcap.unicode = 0 != strcmp(tcap.term, "linux") && tcap.colours >= 256; } switch (config.tcap.clipboard) { case t_true: tcap.clipboard = true; break; case t_false: tcap.clipboard = false; break; case t_auto: if (0 == strcmp(tcap.term, "xterm-kitty")) tcap.clipboard = true; else if (0 == strcmp(tcap.term, "xterm-ghostty")) tcap.clipboard = true; else tcap.clipboard = false; } tcap.escdelay = config.tcap.escdelay; } void init_tui_colours() { // Always initialize fallback color for B&W terminals init_colour(config.colours.fallback); // Initialize other colors only if the terminal supports color if (tcap.colours) { init_colour(config.colours.text); init_colour(config.colours.search); init_colour(config.colours.mark); init_colour(config.colours.link_man); init_colour(config.colours.link_man_f); init_colour(config.colours.link_http); init_colour(config.colours.link_http_f); init_colour(config.colours.link_email); init_colour(config.colours.link_email_f); init_colour(config.colours.link_file); init_colour(config.colours.link_file_f); init_colour(config.colours.link_ls); init_colour(config.colours.link_ls_f); init_colour(config.colours.sb_line); init_colour(config.colours.sb_block); init_colour(config.colours.stat_indic_mode); init_colour(config.colours.stat_indic_name); init_colour(config.colours.stat_indic_loc); init_colour(config.colours.stat_input_prompt); init_colour(config.colours.stat_input_help); init_colour(config.colours.stat_input_em); init_colour(config.colours.imm_border); init_colour(config.colours.imm_title); init_colour(config.colours.sp_input); init_colour(config.colours.sp_text); init_colour(config.colours.sp_text_f); init_colour(config.colours.help_text); init_colour(config.colours.help_text_f); init_colour(config.colours.history_text); init_colour(config.colours.history_text_f); init_colour(config.colours.toc_text); init_colour(config.colours.toc_text_f); // Color pairs used for transitions init_pair(config.colours.trans_mode_name, config.colours.stat_indic_mode.bg, config.colours.stat_indic_name.bg); init_pair(config.colours.trans_name_loc, config.colours.stat_indic_name.bg, config.colours.stat_indic_loc.bg); init_pair(config.colours.trans_prompt_help, config.colours.stat_input_prompt.bg, config.colours.stat_input_help.bg); init_pair(config.colours.trans_prompt_em, config.colours.stat_input_prompt.bg, config.colours.stat_input_em.bg); } } void init_tui_mouse() { if (config.mouse.enable) { mousemask(BUTTON1_PRESSED | BUTTON1_RELEASED | BUTTON3_PRESSED | BUTTON3_RELEASED | BUTTON2_PRESSED | BUTTON2_RELEASED | BUTTON4_PRESSED | BUTTON5_PRESSED | REPORT_MOUSE_POSITION, NULL); // Initialize terminal to enable drag-and-drop char *term = getenv("TERM"); if (0 != strcmp(term, "xterm-1002")) { sendescseq("[?1002h"); } } } void sendescseq(char *s) { if (!config.layout.tui) return; putchar('\033'); unsigned i = 0; while ('\0' != s[i]) putchar(s[i++]); fflush(stdout); } void init_windows() { if (NULL != wmain) delwin(wmain); wmain = newwin(config.layout.main_height, config.layout.main_width, 0, 0); keypad(wmain, true); if (NULL != wsbar) delwin(wsbar); wsbar = newwin(config.layout.main_height, config.layout.sbar_width, 0, config.layout.main_width); keypad(wsbar, true); if (NULL != wstat) delwin(wstat); wstat = newwin(config.layout.stat_height, config.layout.width, config.layout.main_height, 0); keypad(wstat, true); wnoutrefresh(stdscr); } bool termsize_changed() { const int width = getmaxx(stdscr); const int height = getmaxy(stdscr); if (width != config.layout.width || height != config.layout.height) { config.layout.width = width; config.layout.height = height; if (width > config.layout.sbar_width) config.layout.main_width = width - config.layout.sbar_width; else config.layout.main_width = 0; if (height > config.layout.stat_height) config.layout.main_height = height - config.layout.stat_height; else config.layout.main_height = 0; if (config.layout.width > 100) { config.layout.imm_width_wide = config.layout.width - 20; config.layout.imm_width_narrow = 54; } else if (config.layout.width > 60) { config.layout.imm_width_wide = config.layout.width - 6; config.layout.imm_width_narrow = 54; } else { config.layout.imm_width_wide = config.layout.width - 6; config.layout.imm_width_narrow = config.layout.width - 6; } if (config.layout.height > 18) { config.layout.imm_height_long = config.layout.height - 8; config.layout.imm_height_short = 6; } else { config.layout.imm_height_long = config.layout.height - 4; config.layout.imm_height_short = config.layout.height - 4; } return true; } return false; } int cgetch() { curs_set(1); int ret = getch(); curs_set(0); return ret; } wchar_t *ch2name(int k) { static wchar_t fkeys[12][4]; // placeholders for function key representations static wchar_t okeys[94] [4]; // placeholders for representations of all other keys unsigned i; // iterator // Navigation and "special" keys switch (k) { case KEY_UP: return L"UP"; break; case KEY_DOWN: return L"DOWN"; break; case KEY_LEFT: return L"LEFT"; break; case KEY_RIGHT: return L"RIGHT"; break; case KEY_PPAGE: return L"PGUP"; break; case KEY_NPAGE: return L"PGDN"; break; case KEY_HOME: return L"HOME"; break; case KEY_END: return L"END"; break; case '\e': return L"ESC"; break; case KEY_BREAK: case 0x03: return L"CTRL-C"; break; case KEY_ENTER: case '\n': return L"ENTER"; break; case KEY_BACKSPACE: case '\b': return L"BACKSPACE"; break; case '\t': return L"TAB"; break; case ' ': return L"SPACE"; break; } // F1 to F9 for (i = 0; i <= 8; i++) { if (KEY_F(i + 1) == k) { fkeys[i][0] = L'F'; fkeys[i][1] = i + 48; fkeys[i][2] = L'\0'; return fkeys[i]; } } // F10 to F12 for (i = 9; i <= 11; i++) { if (KEY_F(i + 1) == k) { fkeys[i][0] = L'F'; fkeys[i][1] = L'1'; fkeys[i][2] = i + 38; fkeys[i][3] = L'\0'; return fkeys[i]; } } // All other keys if (k >= 33 && k <= 126) { // Key corresponds to a printable character; return it okeys[k - 33][0] = L'\''; okeys[k - 33][1] = k; okeys[k - 33][2] = L'\''; okeys[k - 33][3] = L'\0'; return okeys[k - 33]; } else { // Key does not correspond to a printable character; return "???" return L"???"; } } void termsize_adjust() { if (page_len > config.layout.main_height && page_top + config.layout.main_height > page_len) { page_top = page_len - config.layout.main_height; const link_loc_t ll = last_link(page, page_len, page_top, page_top + config.layout.main_height - 1); if (ll.ok) page_flink = ll; } else { const link_loc_t fl = first_link(page, page_len, page_top, page_top + config.layout.main_height - 1); if (fl.ok) page_flink = fl; } } void draw_box(WINDOW *w, unsigned tl_y, unsigned tl_x, unsigned br_y, unsigned br_x) { unsigned i; mvwaddnwstr(w, tl_y, tl_x, config.chars.box_tl, 1); mvwaddnwstr(w, tl_y, br_x, config.chars.box_tr, 1); mvwaddnwstr(w, br_y, tl_x, config.chars.box_bl, 1); mvwaddnwstr(w, br_y, br_x, config.chars.box_br, 1); for (i = tl_y + 1; i < br_y; i++) { mvwaddnwstr(w, i, tl_x, config.chars.box_vline, 1); mvwaddnwstr(w, i, br_x, config.chars.box_vline, 1); } for (i = tl_x + 1; i < br_x; i++) { mvwaddnwstr(w, tl_y, i, config.chars.box_hline, 1); mvwaddnwstr(w, br_y, i, config.chars.box_hline, 1); } } void draw_page(line_t *lines, unsigned lines_len, unsigned lines_top, link_loc_t flink) { // Clear screen and reset color werase(wmain); wbkgd(wmain, COLOR_PAIR(config.colours.text.pair)); change_colour_attr(wmain, config.colours.text, WA_NORMAL); unsigned y; // current terminal row unsigned ly; // current line unsigned x; // current terminal column unsigned lx; // current column in line unsigned l; // current link unsigned s = 0; // current search result // For each terminal row... for (y = 0; y < getmaxy(wmain); y++) { ly = lines_top + y; if (ly >= lines_len) break; // For each terminal column... for (x = 0; x < getmaxx(wmain); x++) { lx = x + page_left; if (lx >= lines[ly].length) break; // Set text attributes if (bget(lines[ly].bold, lx)) change_colour_attr(wmain, config.colours.text, WA_BOLD); if (bget(lines[ly].italic, lx)) change_colour_attr(wmain, config.colours.text, WA_STANDOUT); if (bget(lines[ly].uline, lx)) change_colour_attr(wmain, config.colours.text, WA_UNDERLINE); if (bget(lines[ly].reg, lx)) change_colour_attr(wmain, config.colours.text, WA_NORMAL); // Place character on screen mvwaddnwstr(wmain, y, x, &lines[ly].text[lx], 1); } // For each link... for (l = 0; l < lines[ly].links_length; l++) { const link_t link = lines[ly].links[l]; // Apply the the appropriate color, based on link type and whether the // link is focused colour_t col; set_link_col(ly, l, link.type); if (page_left <= link.start) apply_colour(wmain, y, link.start - page_left, link.end - link.start, col); } // If we are below the first line, and the previous line has links... if (ly > 0 && lines[ly - 1].links_length > 0) { l = lines[ly - 1].links_length - 1; // ...and its last link is hyphenated... if (lines[ly - 1].links[l].in_next) { const link_t link = lines[ly - 1].links[l]; // Apply the the appropriate color, based on link type and whether the // link is focused colour_t col; set_link_col(ly - 1, l, link.type); if (page_left <= link.start) apply_colour(wmain, y, link.start_next - page_left, link.end_next - link.start_next, col); } } // Skip all search results prior to current line while (s < results_len && results[s].line < ly) s++; // Go through all search results for current line, and highlight them while (s < results_len && results[s].line == ly) { if (page_left <= results[s].start) apply_colour(wmain, y, results[s].start - page_left, results[s].end - results[s].start, config.colours.search); s++; } // If some text is marked, apply the appropriate color to it if (mark.enabled) { unsigned cx = 0, cn = 0; // `x` and `n` parameters for `apply_colour()` if (ly == mark.start_line && ly == mark.end_line) { cx = MAX(0, (int)mark.start_char - (int)page_left); cn = MAX(0, (int)mark.end_char - (int)mark.start_char + 1); if (mark.start_char < page_left) cn = MAX(0, (int)cn - (int)(page_left - mark.start_char)); } else if (ly == mark.start_line && ly < mark.end_line) { cx = MAX(0, (int)mark.start_char - (int)page_left); cn = getmaxx(wmain) - 1; } else if (ly > mark.start_line && ly < mark.end_line) { cx = 0; cn = getmaxx(wmain) - 1; } else if (ly > mark.start_line && ly == mark.end_line) { cx = 0; cn = MAX(0, (int)mark.end_char - (int)page_left + 1); } apply_colour(wmain, y, cx, cn, config.colours.mark); } } wnoutrefresh(wmain); } void draw_sbar(unsigned lines_len, unsigned lines_top) { const unsigned height = getmaxy(wsbar); // scrollbar height const unsigned block_pos = height > lines_len ? 1 : MIN(height - 2, 1 + (height - 2) * lines_top / (lines_len - height + 1)); // scrollbar knob position unsigned i; // iterator werase(wsbar); // Draw vertical line change_colour(wsbar, config.colours.sb_line); mvwaddnwstr(wsbar, 0, 0, config.chars.sbar_top, 1); for (i = 1; i < height - 1; i++) mvwaddnwstr(wsbar, i, 0, config.chars.sbar_vline, 1); mvwaddnwstr(wsbar, height - 1, 0, config.chars.sbar_bottom, 1); // Draw the drag block change_colour(wsbar, config.colours.sb_block); mvwaddnwstr(wsbar, block_pos, 0, config.chars.sbar_block, -1); wnoutrefresh(wsbar); } void draw_stat(const wchar_t *mode, const wchar_t *name, unsigned lines_len, unsigned lines_pos, unsigned column, const wchar_t *prompt, const wchar_t *help, const wchar_t *em) { werase(wstat); wbkgd(wstat, COLOR_PAIR(config.colours.stat_input_prompt.pair)); const unsigned width = getmaxx(wstat); // width of both status lines // Starting columns and widths of the various sections const unsigned mode_col = 0, mode_width = 10, name_col = 10, name_width = width - 28, loc_col = width - 18, loc_width = 18, prompt_col = 0, prompt_width = width / 2, help_col = prompt_width, help_em_width = width - prompt_width; wchar_t tmp[BS_LINE], tmp2[BS_LINE]; // Draw the indicator line swprintf(tmp, BS_LINE, L" %-*ls", mode_width - 1, mode); change_colour(wstat, config.colours.stat_indic_mode); mvwaddnwstr(wstat, 0, mode_col, tmp, mode_width); swprintf(tmp, BS_LINE, L" %-*ls", name_width - 1, name); change_colour(wstat, config.colours.stat_indic_name); mvwaddnwstr(wstat, 0, name_col, tmp, name_width); swprintf(tmp2, BS_LINE, L"%d:%d /%d", lines_pos, column, lines_len); swprintf(tmp, BS_LINE, L"%*ls ", loc_width - 1, tmp2); change_colour(wstat, config.colours.stat_indic_loc); mvwaddnwstr(wstat, 0, loc_col, tmp, loc_width); wattr_set(wstat, WA_NORMAL, config.colours.trans_mode_name, NULL); mvwaddnwstr(wstat, 0, name_col - 1, config.chars.trans_mode_name, 1); wattr_set(wstat, WA_NORMAL, config.colours.trans_name_loc, NULL); mvwaddnwstr(wstat, 0, loc_col - 1, config.chars.trans_name_loc, 1); // Draw the input line if (NULL != help) { swprintf(tmp, BS_LINE, L"%*ls ", help_em_width - 1, help); change_colour(wstat, config.colours.stat_input_help); mvwaddnwstr(wstat, 1, help_col, tmp, help_em_width); } else if (NULL != em) { swprintf(tmp, BS_LINE, L"%*ls ", help_em_width - 1, em); change_colour(wstat, config.colours.stat_input_em); mvwaddnwstr(wstat, 1, help_col, tmp, help_em_width); } swprintf(tmp, BS_LINE, L"%ls", prompt); wattr_set(wstat, WA_NORMAL, config.colours.trans_prompt_help, NULL); mvwaddnwstr(wstat, 1, help_col - 1, config.chars.trans_prompt_help, 1); change_colour(wstat, config.colours.stat_input_prompt); mvwaddnwstr(wstat, 1, prompt_col, tmp, prompt_width); wnoutrefresh(wstat); } void draw_imm(bool is_long, bool is_wide, colour_t colour, const wchar_t *title, const wchar_t *help) { unsigned height, width, y, x; timeout(-1); if (is_long) { height = config.layout.imm_height_long; y = (config.layout.height - height) / 2; } else { height = config.layout.imm_height_short; y = (config.layout.height - height) / 4; } if (is_wide) { width = config.layout.imm_width_wide; x = (config.layout.width - width) / 2; } else { width = config.layout.imm_width_narrow; x = (config.layout.width - width) - 4; } if (NULL != wimm) delwin(wimm); wimm = newwin(height, width, y, x); keypad(wimm, true); werase(wimm); wbkgd(wimm, COLOR_PAIR(colour.pair)); change_colour(wimm, config.colours.imm_border); draw_box(wimm, 0, 0, height - 1, width - 1); change_colour(wimm, config.colours.imm_title); wchar_t *tmp = walloca(width - 2); swprintf(tmp, width - 1, L" %-*ls", width - 2, title); mvwaddnwstr(wimm, 1, 1, tmp, width - 2); change_colour(wimm, colour); mvwaddnwstr(wimm, height - 2, 2, help, width - 4); wnoutrefresh(wimm); } void del_imm() { if (NULL != wimm) delwin(wimm); wimm = NULL; timeout(2000); } bool get_str(WINDOW *w, unsigned y, unsigned x, wchar_t *trgt, unsigned trgt_len) { int res; echo(); res = mvwgetn_wstr(w, y, x, (wint_t *)trgt, trgt_len); noecho(); if (OK == res) return true; else return false; } int get_str_next(WINDOW *w, unsigned y, unsigned x, wchar_t *trgt, unsigned trgt_len) { static wchar_t *res; // copy of `trgt` static unsigned res_len; // copy of `trgt_len` static unsigned pos; // position in `res`/`trgt` int ret; // next return value int chr = '\0'; // user character input int wget_stat; // `mvwget_wch()` return value mouse_t ms = MS_EMPTY; // mouse status corresponding to `wget_stat` if (NULL != trgt) { // First call; initialize `res`, `res_len`, and `pos` res = trgt; res_len = trgt_len; pos = 0; } // Get input from user curs_set(1); wget_stat = mvwget_wch(w, y, x + pos, (wint_t *)&chr); curs_set(0); ms = get_mouse_status(chr); if (WH_UP == ms.wheel) { // User scrolled mouse wheel up; return `-GSN_WH_DOWN` return -GSN_WH_DOWN; } else if (WH_DOWN == ms.wheel) { // User scrolled mouse wheel down; return `-GSN_WH_UP` return -GSN_WH_UP; } else if (BT_RIGHT == ms.button && ms.up) { // User pressed right mouse button; act as if she hit ESC or CTRL-C res[0] = L'\0'; wnoutrefresh(w); return 0; } else if (BT_LEFT == ms.button && ms.up) { // User clicked the left mouse button; act if she hit ENTER if the // `left_click_open` config option is true, otherwise return `-GSN_BT_LEFT` if (config.mouse.left_click_open) { res[pos] = L'\0'; wnoutrefresh(w); return pos; } else return -GSN_BT_LEFT; } else if (BT_WHEEL == ms.button && ms.up) { // User pressed the wheel button; act as if she hit ENTER res[pos] = L'\0'; wnoutrefresh(w); return pos; } else { switch (chr) { case L'\e': case KEY_BREAK: case 0x03: // User hit ESC or CTRL-C res[0] = L'\0'; ret = 0; break; case KEY_ENTER: case L'\n': // User hit ENTER res[pos] = L'\0'; ret = pos; break; case KEY_BACKSPACE: case L'\b': // User hit BACKSPACE if (pos > 0) pos--; else ctbeep(); res[pos] = L'\0'; mvwaddnwstr(w, y, x + pos, L" ", 1); ret = -KEY_BACKSPACE; break; case L'\t': // User hit TAB ret = -0x09; break; case KEY_UP: case KEY_DOWN: case KEY_PPAGE: case KEY_NPAGE: case KEY_HOME: case KEY_END: // User hit UP, DOWN, PGUP, PGDN, HOME, or END ret = -chr; break; default: // User typed a character if (OK != wget_stat) { // Reject function keys, arrow keys, etc. ctbeep(); } else if (pos < res_len) { res[pos] = (wchar_t)chr; res[pos + 1] = L'\0'; mvwaddnwstr(w, y, x + pos, &res[pos], 1); pos++; } else ctbeep(); ret = -chr; } } wnoutrefresh(w); return ret; } action_t get_action(int chr) { action_t i; unsigned j; if (ERR == chr) return PA_NULL; for (i = PA_NULL; i <= PA_QUIT; i++) for (j = 0; j < 8; j++) if (config.keys[i][j] == chr) return i; return PA_NULL; } mouse_t get_mouse_status(int chr) { mouse_t ret = MS_EMPTY; // return value static bool dnd = false; // set to true when we are in drag-and-drop static short dnd_y = -1, dnd_x = -1; // cursor position where drag-and-drop was initiated if (!config.mouse.enable || !has_mouse()) { // If mouse is disabled, always return an empty status return ret; } if (chr == KEY_MOUSE) { MEVENT ev; if (OK == getmouse(&ev)) { // Record cursor position ret.y = ev.y; ret.x = ev.x; // Record button up and down events if (ev.bstate & BUTTON1_PRESSED) { ret.button = BT_LEFT; ret.down = true; } else if (ev.bstate & BUTTON1_RELEASED) { ret.button = BT_LEFT; ret.up = true; } else if (ev.bstate & BUTTON3_PRESSED) { ret.button = BT_RIGHT; ret.down = true; } else if (ev.bstate & BUTTON3_RELEASED) { ret.button = BT_RIGHT; ret.up = true; } else if (ev.bstate & BUTTON2_PRESSED) { ret.button = BT_WHEEL; ret.down = true; } else if (ev.bstate & BUTTON2_RELEASED) { ret.button = BT_WHEEL; ret.up = true; } // Swap left and right buttons if user is left handed if (config.mouse.left_handed) { if (BT_LEFT == ret.button) ret.button = BT_RIGHT; else if (BT_RIGHT == ret.button) ret.button = BT_LEFT; } // Record drag-and-drop if (BT_LEFT == ret.button && ret.down) { dnd = true; dnd_y = ev.y; dnd_x = ev.x; } else if (dnd) { if (!(ev.bstate & REPORT_MOUSE_POSITION)) { dnd = false; dnd_y = -1; dnd_x = -1; } ret.dnd = dnd; ret.dnd_y = dnd_y; ret.dnd_x = dnd_x; } // Record mouse wheel activations if (ev.bstate & BUTTON4_PRESSED) ret.wheel = WH_UP; else if (ev.bstate & BUTTON5_PRESSED) ret.wheel = WH_DOWN; } } return ret; } void cbeep() { if (config.layout.beep) beep(); } void ctbeep() { const int width = getmaxx(stdscr); const int height = getmaxy(stdscr); if (width == config.layout.width && height == config.layout.height) cbeep(); } void entitle(wchar_t *src) { // char* version of src unsigned srcs_len = 3 * wcslen(src); // length char *srcs = salloca(srcs_len); // actual string xwcstombs(srcs, src, srcs_len); char *seq = salloca(7 + strlen(srcs)); sprintf(seq, "]0;%s\07", srcs); sendescseq(seq); } void editcopy(wchar_t *src) { // char* version of src unsigned srcs_len = 3 * wcslen(src); // length char *srcs = salloca(srcs_len); // actual string memset(srcs, 0, sizeof(char) * srcs_len); xwcstombs(srcs, src, srcs_len); // Base64-encoded version of src size_t src64_len; // length char *src64 = base64_encode((unsigned char *)srcs, srcs_len, &src64_len); // actual string // Copy to clipboard if (tcap.clipboard) { // If supported, copy using escape code 52 char *seq = salloca(7 + strlen(src64)); sprintf(seq, "]52;c;%s\07", src64); sendescseq(seq); } else { // Fallback: copy using xclip and/or wl-copy struct stat sb; if (stat("/usr/bin/xclip", &sb) == 0 && sb.st_mode & S_IXUSR) { FILE *pp = xpopen("/usr/bin/xclip -i -selection clipboard", "w"); fprintf(pp, "%s\r", srcs); xpclose(pp); } else if (stat("/usr/bin/wl-copy", &sb) == 0 && sb.st_mode & S_IXUSR) { FILE *pp = xpopen("/usr/bin/wl-copy", "w"); fputs(srcs, pp); xpclose(pp); } else if (stat("/usr/bin/pbcopy", &sb) == 0 && sb.st_mode & S_IXUSR) { FILE *pp = xpopen("/usr/bin/pbcopy", "w"); fputs(srcs, pp); xpclose(pp); } } // Wind down free(src64); } void winddown_tui() { if (NULL != wmain) delwin(wmain); wmain = NULL; if (NULL != wsbar) delwin(wsbar); wsbar = NULL; if (NULL != wstat) delwin(wstat); wstat = NULL; reset_color_pairs(); // Initialize terminal to disable drag-and-drop char *term = getenv("TERM"); if (0 != strcmp(term, "xterm-1002")) { sendescseq("[?1002l"); } endwin(); if (config.misc.terminfo_reset) { char *s; if ((s = tigetstr("rs1")) != NULL) putp(s); if ((s = tigetstr("rs2")) != NULL) putp(s); if ((s = tigetstr("rs3")) != NULL) putp(s); fflush(stdout); } } // // Functions (handlers) // void tui_redraw() { // Main page draw_page(page, page_len, page_top, page_flink); // Scrollbar draw_sbar(page_len, page_top); // Status bar unsigned pos = page_top; if (page_flink.ok) pos = page_flink.line; if (pos < page_top || pos >= page_top + config.layout.main_height) pos = page_top; wchar_t help[BS_SHORT]; swprintf(help, BS_SHORT, L"Press %ls for help or %ls to quit", ch2name(config.keys[PA_HELP][0]), ch2name(config.keys[PA_QUIT][0])); draw_stat(request_type_str(history[history_cur].request_type), page_title, page_len, pos + 1, page_left / config.layout.tabstop + 1, L":", help, NULL); } void tui_error(wchar_t *em) { unsigned pos = page_top; if (page_flink.ok) pos = page_flink.line; if (pos < page_top || pos >= page_top + config.layout.main_height) pos = page_top; draw_stat(request_type_str(history[history_cur].request_type), page_title, page_len, pos + 1, page_left / config.layout.tabstop + 1, L":", NULL, em); cbeep(); } bool tui_up() { const link_loc_t pl = prev_link(page, page_len, page_flink); // link right before `page_flink` if (pl.ok && pl.line >= page_top && pl.line < page_top + config.layout.main_height) { // `pl` exists and is in visible portion; focus on `pl` page_flink = pl; } else if (page_top > 0) { // Visible portion isn't already at the beginning of page; scroll up one // line page_top--; if (page[page_top].links_length > 0) { // Newly revealed line has links; focus on the last one page_flink = (link_loc_t){true, page_top, page[page_top].links_length - 1}; } } else { // None of the above; error out tui_error(L"Already at the top of page"); return false; } return true; } bool tui_down() { const link_loc_t nl = next_link(page, page_len, page_flink); // link right after `page_flink` if (nl.ok && nl.line >= page_top && nl.line < page_top + config.layout.main_height) { // `nl` exists and is in visible portion; focus on `nl` page_flink = nl; } else if (page_top + config.layout.main_height < page_len) { // Visible portion isn't at the very end of page; scroll down one line page_top++; if (page[page_top + config.layout.main_height - 1].links_length > 0) { // Newly revealed line has links; focus on the first one page_flink = (link_loc_t){true, page_top + config.layout.main_height - 1, 0}; } } else { // None of the above; error out tui_error(L"Already at the bottom of page"); return false; } return true; } bool tui_left() { if (0 == page_left) { tui_error(L"Already at the leftmost position"); return false; } if (page_left < config.layout.tabstop) page_left = 0; else page_left -= config.layout.tabstop; return true; } bool tui_right() { if (page_left + config.layout.width + config.layout.tabstop >= BS_LINE) { tui_error(L"Already at the rightmost position"); return false; } page_left += config.layout.tabstop; return true; } bool tui_pgup() { if (page_top >= config.layout.main_height) { // If there's space, scroll up one window height page_top -= config.layout.main_height; } else if (page_top > 0) { // If not, but we're still not at the very top, go there page_top = 0; } else { // None of the above; focus on page's first link, or error out if already // there const link_loc_t fl = first_link(page, page_len, page_top, page_top + config.layout.main_height - 1); if (fl.ok && (page_flink.line != fl.line || page_flink.link != fl.link)) { page_flink = fl; return true; } else { tui_error(L"Already at the top of page"); return false; } } // Focus on the last link in new visible portion const link_loc_t ll = last_link(page, page_len, page_top, page_top + config.layout.main_height - 1); if (ll.ok) page_flink = ll; return true; } bool tui_pgdn() { if (page_top + 2 * config.layout.main_height < page_len) { // If there's space, scroll down one window height page_top += config.layout.main_height; } else if (page_top + config.layout.main_height < page_len && config.layout.main_height <= page_len) { // If not, but we're still not at the very bottom, go there page_top = page_len - config.layout.main_height; } else { // None of the above; focus on page's last link, or error out if already // there const link_loc_t ll = last_link(page, page_len, page_top, page_top + config.layout.main_height - 1); if (ll.ok && (page_flink.line != ll.line || page_flink.link != ll.link)) { page_flink = ll; return true; } else { tui_error(L"Already at the bottom of page"); return false; } } // Focus on the first link in new visible portion const link_loc_t fl = first_link(page, page_len, page_top, page_top + config.layout.main_height - 1); if (fl.ok) page_flink = fl; return true; } bool tui_home() { // Go to the very top page_top = 0; // Focus on the first link in the visible portion const link_loc_t fl = first_link(page, page_len, page_top, page_top + config.layout.main_height - 1); if (fl.ok) page_flink = fl; return true; } bool tui_end() { // Go to the very bottom if (config.layout.main_height <= page_len) page_top = page_len - config.layout.main_height; // Focus on the last link in the visible portion const link_loc_t ll = last_link(page, page_len, page_top, page_top + config.layout.main_height - 1); if (ll.ok) page_flink = ll; return true; } bool tui_open() { int res; // External handler subprocess exit code error_on_invalid_flink; // Open the link switch (page[page_flink.line].links[page_flink.link].type) { case LT_MAN: // The link is a manual page; add a new page request to show it { wchar_t trgt[BS_LINE]; swprintf(trgt, BS_LINE, L"'%ls'", page[page_flink.line].links[page_flink.link].trgt); history_push(RT_MAN, trgt); populate_page(); if (err) { history_back(1); history_reset(); populate_page(); tui_redraw(); tui_error(err_msg); return false; } page_top = 0; page_left = 0; page_flink = first_link(page, page_len, page_top, page_top + config.layout.main_height - 1); } break; case LT_HTTP: // The link is http(s); open it with the external web browser { char trgt[BS_LINE]; snprintf(trgt, BS_LINE, "%s '%ls' 2>>/dev/null", config.misc.browser_path, page[page_flink.line].links[page_flink.link].trgt); // Shell out res = xsystem(trgt, false); // Re-initialize ncurses (unless using xdg-open) if (config.misc.reset_after_http) tui_reset; // If web browser failed, show error if (0 != res) { tui_error(L"Unable to open HTTP link"); return false; } } break; case LT_EMAIL: // The link is an e-mail address; open it with the external mailer { char trgt[BS_LINE]; snprintf(trgt, BS_LINE, "%s '%ls' 2>>/dev/null", config.misc.mailer_path, page[page_flink.line].links[page_flink.link].trgt); // Shell out res = xsystem(trgt, false); // Re-initialize ncurses if (config.misc.reset_after_email) tui_reset; // If mailer failed, show error if (0 != res) { tui_error(L"Unable to open email link"); return false; } } break; case LT_FILE: // The link is a file in the local filesystem; open it with the external // file viewer { char trgt[BS_LINE]; snprintf(trgt, BS_LINE, "%s '%ls' 2>>/dev/null", config.misc.viewer_path, page[page_flink.line].links[page_flink.link].trgt); // Shell out res = xsystem(trgt, false); // Re-initialize ncurses if (config.misc.reset_after_viewer) tui_reset; // If external viewer failed, show error if (0 != res) { tui_error(L"Unable to open file link"); return false; } } break; case LT_LS: // The link is a local search link; jump to the appropriate page location ls_jump(page[page_flink.line].links[page_flink.link].trgt, NULL); break; } return true; } bool tui_open_apropos() { wchar_t wtrgt[BS_LINE]; wchar_t *wtrgt_stripped, *buf; error_on_invalid_flink; if (LT_MAN == page[page_flink.line].links[page_flink.link].type) { wcslcpy(wtrgt, page[page_flink.line].links[page_flink.link].trgt, BS_LINE); wtrgt_stripped = wcstok(wtrgt, L"()", &buf); if (NULL == wtrgt_stripped) { tui_error(L"Unable to open link"); return false; } else { history_push(RT_APROPOS, wtrgt); populate_page(); if (err) { history_back(1); history_reset(); populate_page(); tui_redraw(); tui_error(err_msg); return false; } page_top = 0; page_left = 0; page_flink = first_link(page, page_len, page_top, page_top + config.layout.main_height - 1); return true; } } else { tui_error(L"Apropos can only be performed on manual pages"); return false; } } bool tui_open_whatis() { wchar_t wtrgt[BS_LINE]; wchar_t *wtrgt_stripped, *buf; error_on_invalid_flink; if (LT_MAN == page[page_flink.line].links[page_flink.link].type) { wcslcpy(wtrgt, page[page_flink.line].links[page_flink.link].trgt, BS_LINE); wtrgt_stripped = wcstok(wtrgt, L"()", &buf); if (NULL == wtrgt_stripped) { tui_error(L"Unable to open link"); return false; } else { history_push(RT_WHATIS, wtrgt); populate_page(); if (err) { history_back(1); history_reset(); populate_page(); tui_redraw(); tui_error(err_msg); return false; } page_top = 0; page_left = 0; page_flink = first_link(page, page_len, page_top, page_top + config.layout.main_height - 1); return true; } } else { tui_error(L"Whatis can only be performed on manual pages"); return false; } } bool tui_sp_open(request_type_t rt) { wchar_t inpt[BS_SHORT - 2] = L""; // string typed by user wchar_t trgt[BS_SHORT]; // final string that specifies the page to be opened wchar_t *awqsr; // incremental search result returned from `aw_quick_search()` wchar_t help[BS_SHORT]; // help message swprintf(help, BS_SHORT, L"%ls: query string %ls/%ls/%ls: select %ls/%ls: abort", ch2name(KEY_ENTER), ch2name(KEY_UP), ch2name(0x09), ch2name(KEY_DOWN), ch2name(KEY_BREAK), ch2name('\e')); int got_inpt; // current return value of `get_str_next()` // Draw immediate window and title bar if (RT_MAN == rt) draw_imm(true, true, config.colours.sp_input, L"Manual page to open?", help); else if (RT_APROPOS == rt) draw_imm(true, true, config.colours.sp_input, L"Apropos what?", help); else if (RT_WHATIS == rt) draw_imm(true, true, config.colours.sp_input, L"Whatis what?", help); doupdate(); // Get input (and show incremental search results as the user types) awqsr = aw_quick_search(inpt, 0, RT_MAN == rt); doupdate(); change_colour(wimm, config.colours.sp_input); got_inpt = get_str_next(wimm, 2, 2, inpt, MIN(BS_SHORT - 3, config.layout.imm_width_wide - 4)); while (got_inpt < 0) { // If terminal size has changed, regenerate page and redraw everything if (termsize_changed()) { del_imm(); init_windows(); populate_page(); if (err) winddown(ES_OPER_ERROR, err_msg); termsize_adjust(); tui_redraw(); if (RT_MAN == rt) draw_imm(true, true, config.colours.sp_text, L"Manual page to open?", help); else if (RT_APROPOS == rt) draw_imm(true, true, config.colours.sp_text, L"Apropos what?", help); else if (RT_WHATIS == rt) draw_imm(true, true, config.colours.sp_text, L"Whatis what?", help); change_colour(wimm, config.colours.sp_input); mvwaddnwstr(wimm, 2, 2, inpt, wcslen(inpt)); } awqsr = aw_quick_search(inpt, got_inpt, RT_MAN == rt); doupdate(); change_colour(wimm, config.colours.sp_input); got_inpt = get_str_next(wimm, 2, 2, NULL, 0); } del_imm(); if (got_inpt > 0) { // Input succeeded; show requested page if (NULL == awqsr) swprintf(trgt, BS_SHORT, L"'%ls'", inpt); else swprintf(trgt, BS_SHORT, L"'%ls'", awqsr); history_push(rt, trgt); populate_page(); if (err) { history_back(1); history_reset(); populate_page(); tui_redraw(); tui_error(err_msg); return false; } page_top = 0; page_left = 0; page_flink = first_link(page, page_len, page_top, page_top + config.layout.main_height - 1); return true; } else { // User hit ESC or CTRL-C or pressed right mouse button; abort tui_redraw(); tui_error(L"Aborted"); return false; } } bool tui_index() { history_push(RT_INDEX, NULL); populate_page(); if (err) winddown(ES_OPER_ERROR, err_msg); page_top = 0; page_left = 0; page_flink = first_link(page, page_len, page_top, page_top + config.layout.main_height - 1); return true; } bool tui_back() { if (history_back(1)) { populate_page(); if (err) winddown(ES_OPER_ERROR, err_msg); return true; } else { tui_error(L"Already at the first page in history"); return false; } } bool tui_fwrd() { if (history_forward(1)) { populate_page(); if (err) winddown(ES_OPER_ERROR, err_msg); return true; } else { tui_error(L"Already at the last page in history"); return false; } } bool tui_history() { wchar_t help[BS_SHORT]; // help message swprintf(help, BS_SHORT, L"%ls/%ls: choose %ls: jump %ls/%ls: abort", ch2name(config.keys[PA_UP][0]), ch2name(config.keys[PA_DOWN][0]), ch2name(config.keys[PA_OPEN][0]), ch2name(KEY_BREAK), ch2name('\e')); int hinput; // keyboard/mouse input from the user mouse_t hms = MS_EMPTY; // mouse status corresponding to `hinput` action_t haction = PA_NULL; // program action corresponding to `hinput` unsigned height; // history window height unsigned top; // first history entry to be printed int focus = history_cur; // focused history entry // Create the history window, retrieve height, and calculate `top` draw_imm(true, false, config.colours.history_text, L"History", help); height = getmaxy(wimm); if (focus > height - 6) top = focus - height + 6; else top = 0; // Main loop while (true) { // Draw the history text in the history window draw_history(history, history_cur, history_top, top, focus); doupdate(); // Get user input hinput = cgetch(); hms = get_mouse_status(hinput); if ('\e' == hinput || KEY_BREAK == hinput || 0x03 == hinput || (BT_RIGHT == hms.button && hms.up)) { // User hit ESC or CTRL-C or pressed right mouse button; abort del_imm(); tui_error(L"Aborted"); tui_redraw(); return false; } haction = get_action(hinput); // Perform the requested action switch (haction) { case PA_UP: focus--; if (-1 == focus) focus = history_top; break; case PA_DOWN: focus++; if (history_top + 1 == focus) focus = 0; break; case PA_PGUP: focus -= MAX(1, height - 6); if (focus < 0) focus = history_top; break; case PA_PGDN: focus += MAX(1, height - 6); if (focus > history_top) focus = 0; break; case PA_OPEN: del_imm(); if (history_jump(focus)) populate_page(); if (err) winddown(ES_OPER_ERROR, err_msg); return true; break; case PA_NULL: default: if (WH_UP == hms.wheel) { // When mouse wheel scrolls up, select previous history entry focus--; if (-1 == focus) focus = history_top; } else if (WH_DOWN == hms.wheel) { // When mouse wheel scrolls down, select next history entry focus++; if (history_top + 1 == focus) focus = 0; } else if (BT_LEFT == hms.button && hms.up) { // On left button release, focus on the history entry under the cursor int iy = hms.y, ix = hms.x; unsigned ih = getmaxy(wimm); if (wmouse_trafo(wimm, &iy, &ix, false)) if (iy > 1 && iy < ih - 3 && history_top >= top + iy - 2) { focus = top + iy - 2; if (config.mouse.left_click_open) { // If the `left_click_open` option is set, go to the appropriate // history entry del_imm(); if (history_jump(focus)) populate_page(); if (err) winddown(ES_OPER_ERROR, err_msg); return true; } } } else if (BT_WHEEL == hms.button && hms.up) { // On mouse wheel click, go to the appropriate history entry del_imm(); if (history_jump(focus)) populate_page(); if (err) winddown(ES_OPER_ERROR, err_msg); return true; } break; } // Adjust `top` (in case the entire menu won't fit in the immediate window) if (focus < top) top = focus; else if (focus > top + height - 6) top = focus - height + 6; // If terminal size has changed, regenerate page and redraw everything if (termsize_changed()) { del_imm(); init_windows(); populate_page(); if (err) winddown(ES_OPER_ERROR, err_msg); termsize_adjust(); tui_redraw(); top = 0; focus = 0; draw_imm(true, false, config.colours.history_text, L"History", help); draw_history(history, history_cur, history_top, top, focus); doupdate(); height = getmaxy(wimm); } } return true; } bool tui_toc() { wchar_t help[BS_SHORT]; // help message swprintf(help, BS_SHORT, L"%ls/%ls: choose %ls: jump %ls/%ls: abort", ch2name(config.keys[PA_UP][0]), ch2name(config.keys[PA_DOWN][0]), ch2name(config.keys[PA_OPEN][0]), ch2name(KEY_BREAK), ch2name('\e')); int hinput; // keyboard/mouse input from the user mouse_t hms = MS_EMPTY; // mouse status corresponding to `hinput` action_t haction = PA_NULL; // program action corresponding to `hinput` unsigned height; // TOC window height unsigned top = 0; // first TOC entry to be printed int focus = 0; // focused TOC entry // Populate `toc` and `toc_len`, if necessary populate_toc(); // Create the TOC window, and retrieve height draw_imm(true, true, config.colours.toc_text, L"Table of Contents", help); height = getmaxy(wimm); // Main loop while (true) { // Draw the TOC text in the history window draw_toc(toc, toc_len, top, focus); doupdate(); // Get user input hinput = cgetch(); hms = get_mouse_status(hinput); if ('\e' == hinput || KEY_BREAK == hinput || 0x03 == hinput || (BT_RIGHT == hms.button && hms.up)) { // User hit ESC or CTRL-C or pressed right mouse button; abort del_imm(); tui_error(L"Aborted"); tui_redraw(); return false; } haction = get_action(hinput); // Perform the requested action switch (haction) { case PA_UP: focus--; if (-1 == focus) focus = toc_len - 1; break; case PA_DOWN: focus++; if (toc_len == focus) focus = 0; break; case PA_PGUP: focus -= MAX(1, height - 6); if (focus < 0) focus = toc_len - 1; break; case PA_PGDN: focus += MAX(1, height - 6); if (focus >= toc_len) focus = 0; break; case PA_OPEN: del_imm(); toc_jump(toc, focus); return true; break; case PA_NULL: default: if (WH_UP == hms.wheel) { // When mouse wheel scrolls up, select previous TOC entry focus--; if (-1 == focus) focus = toc_len - 1; } else if (WH_DOWN == hms.wheel) { // When mouse wheel scrolls down, select next TOC entry focus++; if (toc_len == focus) focus = 0; } else if (BT_LEFT == hms.button && hms.up) { // On left button release, focus on the TOC entry under the cursor int iy = hms.y, ix = hms.x; unsigned ih = getmaxy(wimm); if (wmouse_trafo(wimm, &iy, &ix, false)) if (iy > 1 && iy < ih - 3 && toc_len > top + iy - 2) { focus = top + iy - 2; if (config.mouse.left_click_open) { // If the `left_click_open` option is set, go to the appropriate // TOC entry del_imm(); toc_jump(toc, focus); return true; } } } else if (BT_WHEEL == hms.button && hms.up) { // On mouse wheel click, go to the appropriate TOC entry del_imm(); toc_jump(toc, focus); return true; } break; } // Adjust `top` (in case the entire menu won't fit in the immediate window) if (focus < top) top = focus; else if (focus > top + height - 6) top = focus - height + 6; // If terminal size has changed, regenerate page and redraw everything if (termsize_changed()) { del_imm(); init_windows(); populate_page(); if (err) winddown(ES_OPER_ERROR, err_msg); populate_toc(); termsize_adjust(); tui_redraw(); top = 0; focus = 0; draw_imm(true, true, config.colours.toc_text, L"Table of Contents", help); draw_toc(toc, toc_len, top, focus); doupdate(); height = getmaxy(wimm); } } return true; } bool tui_search(bool back) { wchar_t *prompt = back ? L"?" : L"/"; // search prompt wchar_t help[BS_SHORT]; // help message swprintf(help, BS_SHORT, L"Press %ls to search or %ls/%ls to abort", ch2name(KEY_ENTER), ch2name(KEY_BREAK), ch2name('\e')); wchar_t inpt[BS_SHORT - 2]; // search string wchar_t pout[BS_SHORT]; // search prompt and string printout const unsigned width = config.layout.width / 2 - 1; // search string width int got_inpt; // current return value of `get_str_next()` unsigned my_top = page_top; // temporary `page_top` that will be set to the line number of // the first search result, as the user types // Get search string swprintf(pout, BS_SHORT, prompt); draw_stat(L"SEARCH", page_title, page_len, page_top + 1, page_left / config.layout.tabstop + 1, pout, help, NULL); got_inpt = get_str_next(wstat, 1, 1, inpt, MIN(BS_SHORT - 3, width)); // As the user types something... while (got_inpt < 0) { // If terminal size has changed, regenerate page and redraw everything if (termsize_changed()) { init_windows(); populate_page(); if (err) winddown(ES_OPER_ERROR, err_msg); termsize_adjust(); tui_redraw(); doupdate(); } // Free previous `results` if (NULL != results && results_len > 0) free(results); // Populate `results` and `results_len` if (0 == wcslen(inpt)) { // Input is empty; set `results` to NULL, `results_len` to 0, and `my_top` // to `page_top` results = NULL; results_len = 0; my_top = page_top; } else { // Input is not empty; populate `results` and `results_len` from input, // and set `my_top` to the location of the first match results_len = search(&results, inpt, page, page_len, config.capabilities.icase_search); if (back) { const int tmp = search_prev(results, results_len, my_top); my_top = -1 == tmp ? my_top : tmp; } else { const int tmp = search_next(results, results_len, my_top); my_top = -1 == tmp ? my_top : tmp; } if (my_top + config.layout.main_height > page_len) { if (page_len >= config.layout.main_height) my_top = MIN(my_top, page_len - config.layout.main_height); else my_top = 0; } } // Redraw all windows, scrolling over to `my_top` draw_page(page, page_len, my_top, page_flink); draw_sbar(page_len, my_top); swprintf(pout, BS_SHORT, L"%ls%ls", prompt, inpt); if (0 == results_len) { draw_stat(L"SEARCH", page_title, page_len, my_top + 1, page_left / config.layout.tabstop + 1, pout, NULL, L"Search string not found"); cbeep(); } else { draw_stat(L"SEARCH", page_title, page_len, my_top + 1, page_left / config.layout.tabstop + 1, pout, help, NULL); } doupdate(); // Get next user input got_inpt = get_str_next(wstat, 1, 1, NULL, 0); } if (got_inpt > 0) { // User entered a string and hit ENTER; retain search results page_top = my_top; const link_loc_t fl = first_link(page, page_len, page_top, page_top + config.layout.main_height - 1); if (fl.ok) page_flink = fl; return true; } else { // User hit ESC or CTRL-C; clear search results if (NULL != results && results_len > 0) free(results); results = NULL; results_len = 0; tui_redraw(); tui_error(L"Aborted"); return false; } } bool tui_search_next(bool back) { unsigned my_top; // Store the previous/next search result into `my_top` if (back) my_top = search_prev(results, results_len, MAX(0, page_top > 0 ? page_top - 1 : 0)); else my_top = search_next(results, results_len, MIN(page_len - 1, page_top + 1)); // If result wasn't found, show error message if (-1 == my_top) { tui_redraw(); tui_error(L"No more search results"); return false; } // Massage `my_top` to avoid scrolling out of `page_len` if (my_top + config.layout.main_height > page_len) { if (page_len >= config.layout.main_height) my_top = MIN(my_top, page_len - config.layout.main_height); else my_top = 0; } // If result was found, but we have reached the end of page, show error // message if (page_top == my_top) { tui_redraw(); tui_error(L"No more search results"); return false; } // Set `page_top` and `page_flink` to the values necessary to jump to the // search result page_top = my_top; const link_loc_t fl = first_link(page, page_len, page_top, page_top + config.layout.main_height - 1); if (fl.ok) page_flink = fl; return true; } bool tui_help() { unsigned i, j, k; // iterators wchar_t *keys_names[PA_QUIT + 1]; // string representations of key character // mappings corresponding to all program // actions (as unified strings) unsigned keys_names_max = 0; // length of longest string in `keys_names` wchar_t *cur_key_names[8] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}; // string representations of key character mappings // corresponding to the current action (as array of // strings) wchar_t *tmp; // temporary wchar_t help[BS_SHORT]; // help message swprintf(help, BS_SHORT, L"%ls/%ls: choose action %ls: fire %ls/%ls: abort", ch2name(config.keys[PA_UP][0]), ch2name(config.keys[PA_DOWN][0]), ch2name(config.keys[PA_OPEN][0]), ch2name(KEY_BREAK), ch2name('\e')); int hinput; // keyboard/mouse input from the user mouse_t hms = MS_EMPTY; // mouse status corresponding to `hinput` action_t haction = PA_NULL; // program action corresponding to `hinput` unsigned top = 1; // first action to be printed int focus = 1; // focused action unsigned height; // help window height // For each action... for (i = 0; i <= PA_QUIT; i++) { // Populate `cur_key_names` k = 0; for (j = 0; j < 8 && 0 != config.keys[i][j]; j++) { tmp = ch2name(config.keys[i][j]); if (!in8(tmp, cur_key_names, wcsequal)) { cur_key_names[k] = tmp; k++; } } // Produce `keys_names[i]` and update `keys_names_max`, using // `cur_key_names` keys_names[i] = walloca(BS_SHORT); wcslcpy(keys_names[i], L"", BS_SHORT); for (j = 0; NULL != cur_key_names[j]; j++) { if (0 != j) wcslcat(keys_names[i], L", ", BS_SHORT); wcslcat(keys_names[i], cur_key_names[j], BS_SHORT); cur_key_names[j] = NULL; } keys_names_max = MAX(keys_names_max, wcslen(keys_names[i])); } // Create the help window, and retrieve its height draw_imm(true, true, config.colours.help_text, L"Program Actions and Keyboard Help", help); height = getmaxy(wimm); // Main loop while (true) { // Draw the help text in the help window draw_help((const wchar_t **)keys_names, keys_names_max, top, focus); doupdate(); // Get user input hinput = cgetch(); hms = get_mouse_status(hinput); if ('\e' == hinput || KEY_BREAK == hinput || 0x03 == hinput || (BT_RIGHT == hms.button && hms.up)) { // User hit ESC or CTRL-C or pressed right mouse button; abort del_imm(); tui_error(L"Aborted"); tui_redraw(); return false; } haction = get_action(hinput); // Perform the requested action switch (haction) { case PA_UP: focus--; if (0 == focus) focus = PA_QUIT; break; case PA_DOWN: focus++; if (PA_QUIT + 1 == focus) focus = 1; break; case PA_PGUP: focus -= MAX(1, height - 6); if (focus < 1) focus = PA_QUIT; break; case PA_PGDN: focus += MAX(1, height - 6); if (focus > PA_QUIT) focus = 1; break; case PA_OPEN: del_imm(); ungetch(config.keys[focus][0]); return true; break; case PA_NULL: default: if (WH_UP == hms.wheel) { // When mouse wheel scrolls up, select previous help entry focus--; if (0 == focus) focus = PA_QUIT; } else if (WH_DOWN == hms.wheel) { // When mouse wheel scrolls down, select next help entry focus++; if (PA_QUIT + 1 == focus) focus = 1; } else if (BT_LEFT == hms.button && hms.up) { // On left button release, focus on the help entry under the cursor int iy = hms.y, ix = hms.x; unsigned ih = getmaxy(wimm); if (wmouse_trafo(wimm, &iy, &ix, false)) if (iy > 1 && iy < ih - 3 && PA_QUIT >= top + iy - 2) { focus = top + iy - 2; if (config.mouse.left_click_open) { // If the `left_click_open` option is set, execute the entry's // program action del_imm(); ungetch(config.keys[focus][0]); return true; } } } else if (BT_WHEEL == hms.button && hms.up) { // On mouse wheel click, execute the focused entry's program action del_imm(); ungetch(config.keys[focus][0]); return true; } break; } // Adjust `top` (in case the entire menu won't fit in the immediate window) if (focus < top) top = focus; else if (focus > top + height - 6) top = focus - height + 6; // If terminal size has changed, regenerate page and redraw everything if (termsize_changed()) { del_imm(); init_windows(); populate_page(); if (err) winddown(ES_OPER_ERROR, err_msg); termsize_adjust(); tui_redraw(); top = 1; focus = 1; draw_imm(true, true, config.colours.help_text, L"Program Actions and Keyboard Help", help); draw_help((const wchar_t **)keys_names, keys_names_max, top, focus); doupdate(); height = getmaxy(wimm); } } return true; } bool tui_mouse_click(short y, short x) { int my = y, mx = x; // locations in `wmain` that correspond to `y` and `x` int sy = y, sx = x; // locations in `wsbar` that correspond to `y` and `x` // If text was being marked with `tui_mouse_dnd()`, copy it to clipboard and // clear the selection if (mark.enabled) { wchar_t *mt; get_mark(&mt, mark, page); editcopy(mt); free(mt); mark.enabled = false; tui_redraw(); tui_error(L"Copied to clipboard"); return false; } // If the cursor is on a link, make it the focused link if (wmouse_trafo(wmain, &my, &mx, false)) { unsigned ln = page_top + my; // line number that corresponds to `my` if (ln < page_len) { for (unsigned i = 0; i < page[ln].links_length; i++) { if (mx >= page[ln].links[i].start && mx < page[ln].links[i].end) { page_flink.ok = true; page_flink.line = ln; page_flink.link = i; if (config.mouse.left_click_open && mouse_status.up) { // If `left_click_open` is set, open the link as well return tui_open(); } else return true; } } } } // If the cursor is on the scrollbar, jump to the appropriate page position if (wmouse_trafo(wsbar, &sy, &sx, false)) { unsigned sh = getmaxy(wsbar); // scrollbar window height unsigned bp = (MAX( 1, MIN(sh - 2, sy))); // where the scrollbar knob should be repositioned page_top = bp == 1 ? 0 : (bp * (page_len - sh + 1) - 1) / (sh - 2); const link_loc_t fl = first_link(page, page_len, page_top, page_top + config.layout.main_height - 1); if (fl.ok && (page_flink.line != fl.line || page_flink.link != fl.link)) page_flink = fl; return true; } return false; } bool tui_mouse_dnd(short y, short x, short dy, short dx) { int my = y, mx = x; // locations in `wmain` that correspond to `y` and `x` int sy = y; // location in `wsbar` that corresponds to `y` int mdy = dy, mdx = dx; // locations in `wmain` that correspond to `dy` and `dx` int sdy = dy, sdx = dx; // locations in `wsbar` that correspond to `dy` and `dx` // If dragging was initiated on the main window, mark text if (wmouse_trafo(wmain, &mdy, &mdx, false)) { // Make sure `my` and `mx` are always within the confines of `wmain` if (my >= getmaxy(wmain)) { my = getmaxy(wmain) - 1; mx = getmaxx(wmain) - 1; } if (mx >= getmaxx(wmain)) mx = getmaxx(wmain) - 1; unsigned start_line = MIN(page_len - 1, page_top + mdy); unsigned start_char = MIN(page[start_line].length - 1, page_left + mdx); unsigned end_line = MIN(page_len - 1, page_top + my); unsigned end_char = MIN(page[end_line].length - 1, page_left + mx); // If drag was right-to-left and/or bottom-to-top, swap `start_char` with // `end_char` and/or `start_line` with `end_line` as needed if (start_line > end_line) { swap(start_line, end_line); swap(start_char, end_char); } else if (start_line == end_line && start_char > end_char) { swap(start_char, end_char); } // Mark text mark.enabled = true; mark.start_line = start_line; mark.start_char = start_char; mark.end_line = end_line; mark.end_char = end_char; return true; } // If dragging was initiated on the scrollbar, jump to the appropriate page // position if (wmouse_trafo(wsbar, &sdy, &sdx, false)) { unsigned sh = getmaxy(wsbar); // scrollbar window height unsigned bp = (MAX( 1, MIN(sh - 2, sy))); // where the scrollbar knob should be repositioned page_top = bp == 1 ? 0 : (bp * (page_len - sh + 1) - 1) / (sh - 2); const link_loc_t fl = first_link(page, page_len, page_top, page_top + config.layout.main_height - 1); if (fl.ok && (page_flink.line != fl.line || page_flink.link != fl.link)) page_flink = fl; return true; } return false; } void tui() { int input; // keyboard/mouse input from user bool redraw = true; // set this to true to redraw the screen wchar_t errmsg[BS_SHORT]; // error message swprintf(errmsg, BS_SHORT, L"Invalid keystroke; press %ls for help", ch2name(config.keys[PA_HELP][0])); // Reset config options that get set by command-line options but are ignored // when using the TUI config.misc.cli_force_color = false; config.misc.global_whatis = false; config.misc.global_apropos = false; // Initialize TUI init_tui(); configure(); init_tui_tcap(); if (-1 == config.tcap.colours || t_auto == config.tcap.rgb || t_auto == config.tcap.unicode || t_auto == config.tcap.clipboard) { // Options were defined in the `[pcap]` configuration section; we must run // `configure()` again, to re-initialize configuration options whose final // value might depend on terminal capabilities configure(); } late_init(); init_tui_colours(); init_tui_mouse(); termsize_changed(); init_windows(); // Initialize `page`, `page_len`, `page_title`, `page_top`, `page_left`, and // `page_flink` populate_page(); if (err) winddown(ES_NOT_FOUND, err_msg); page_top = 0; page_left = 0; page_flink = next_link(page, page_len, page_flink); // Initialize `action` action = PA_NULL; while (PA_QUIT != action) { // If terminal size has changed, regenerate `page` and ask for a redraw if (termsize_changed()) { init_windows(); populate_page(); if (err) winddown(ES_OPER_ERROR, err_msg); termsize_adjust(); redraw = true; } // If redraw is necessary, redraw if (redraw) { tui_redraw(); redraw = false; } doupdate(); // Get user input if (PA_NULL != first_action) { // Edge case: user used -A or --action to specify a program action to // perform upon startup action = first_action; first_action = PA_NULL; } else { input = cgetch(); action = get_action(input); mouse_status = get_mouse_status(input); } // Perform the requested action switch (action) { case PA_UP: redraw = tui_up(); break; case PA_DOWN: redraw = tui_down(); break; case PA_LEFT: redraw = tui_left(); break; case PA_RIGHT: redraw = tui_right(); break; case PA_PGUP: redraw = tui_pgup(); break; case PA_PGDN: redraw = tui_pgdn(); break; case PA_HOME: redraw = tui_home(); break; case PA_END: redraw = tui_end(); break; case PA_OPEN: redraw = tui_open(); break; case PA_OPEN_APROPOS: redraw = tui_open_apropos(); break; case PA_OPEN_WHATIS: redraw = tui_open_whatis(); break; case PA_SP_OPEN: redraw = tui_sp_open(RT_MAN); break; case PA_SP_APROPOS: redraw = tui_sp_open(RT_APROPOS); break; case PA_SP_WHATIS: redraw = tui_sp_open(RT_WHATIS); break; case PA_INDEX: redraw = tui_index(); break; case PA_BACK: redraw = tui_back(); break; case PA_FWRD: redraw = tui_fwrd(); break; case PA_HISTORY: redraw = tui_history(); break; case PA_TOC: redraw = tui_toc(); break; case PA_SEARCH: redraw = tui_search(false); break; case PA_SEARCH_BACK: redraw = tui_search(true); break; case PA_SEARCH_NEXT: redraw = tui_search_next(false); break; case PA_SEARCH_PREV: redraw = tui_search_next(true); break; case PA_HELP: redraw = tui_help(); break; case PA_QUIT: break; case PA_NULL: default: if (WH_UP == mouse_status.wheel) { // Mouse wheel scroll up causes `PA_UP` redraw = tui_up(); } else if (WH_DOWN == mouse_status.wheel) { // Mouse wheel scroll down causes `PA_DOWN` redraw = tui_down(); } else if (BT_WHEEL == mouse_status.button && mouse_status.up) { // Mouse wheel click causes `PA_OPEN` redraw = tui_open(); } else if (BT_RIGHT == mouse_status.button && mouse_status.up) { // Right mouse button click causes `PA_HELP` redraw = tui_help(); } else if (BT_LEFT == mouse_status.button && mouse_status.up) { // On left mouse button release, call `tui_mouse_click()` redraw = tui_mouse_click(mouse_status.y, mouse_status.x); } else if (mouse_status.dnd) { // On left mouse drag-and-drop, call `tui_mouse_dnd()` redraw = tui_mouse_dnd(mouse_status.y, mouse_status.x, mouse_status.dnd_y, mouse_status.dnd_x); } else redraw = true; break; } } } qman-1.5.1/src/tui.h000066400000000000000000000317051510660157000142220ustar00rootroot00000000000000// Text user interface (definition) #ifndef TUI_H #define TUI_H #include "lib.h" // // Types // // Terminal capabilities typedef struct { char *term; // contents of the TERM environment variable short colours; // number of colors supported by the terminal, or 0 if the // terminal is black and white bool rgb; // true if terminal colors can be re-defined bool unicode; // true if the terminal supports Unicode bool clipboard; // true if the terminal supports clipboard operations (OSC 52) unsigned escdelay; // terminal escape delay } tcap_t; // A mouse button typedef enum { BT_NONE, // n/a BT_LEFT, // left button BT_RIGHT, // right button BT_WHEEL // wheel button } mouse_button_t; // Mouse wheel activation typedef enum { WH_NONE, // n/a WH_UP, // up WH_DOWN // down } mouse_wheel_t; // Compiled mouse status (only includes parametres essential for us) typedef struct { mouse_button_t button; // which mouse button bool down; // the button was pressed bool up; // the button was released bool dnd; // we are in drag-and-drop (button was previously pressed but not // yet released) short dnd_y; // vertical position where drag-and-drop was initiated short dnd_x; // horizontal position where drag-and-drop was initiated mouse_wheel_t wheel; // activation of the mouse wheel short y; // cursor vertical position short x; // cursor horizontal position } mouse_t; // // Constants // // empty mouse status (used for initialization) #define MS_EMPTY {BT_NONE, false, false, false, -1, -1, WH_NONE, -1, -1} // Return values of `get_str_next()` (more info in its docstring) #define _GSN (1 << 24) #define GSN_WH_DOWN (_GSN) #define GSN_WH_UP (_GSN + 1) #define GSN_BT_LEFT (_GSN + 2) // // Global variables // // Terminal capabilities extern tcap_t tcap; // (ncurses windows) // Main window where the current page is displayed extern WINDOW *wmain; // Scrollbar window extern WINDOW *wsbar; // Status bar window extern WINDOW *wstat; // Immediate (popup) window extern WINDOW *wimm; // (program state) // Latest action extern action_t action; // Latest mouse status extern mouse_t mouse_status; // // Macros // // Initialize ncurses color pair in `col` (of type `colour_t`) #define init_colour(col) init_pair(col.pair, col.fg, col.bg); // Change the color for ncurses window `win` to `col` (of type `colour_t`) #define change_colour(win, col) \ { \ if (tcap.colours) { \ if (col.bold) \ wattr_set(win, WA_BOLD, col.pair, NULL); \ else \ wattr_set(win, WA_NORMAL, col.pair, NULL); \ } else if (COLOR_BLACK == col.fg && (wmain == win || wimm == win)) \ wattr_set(win, WA_REVERSE, config.colours.fallback.pair, NULL); \ else \ wattr_set(win, WA_NORMAL, config.colours.fallback.pair, NULL); \ } // Change the color for ncurses window `win` to `col` (of type `colour_t`), and // its text attribute to `attr` #define change_colour_attr(win, col, attr) \ { \ if (tcap.colours) \ wattr_set(win, attr, col.pair, NULL); \ else if (wmain == win || wimm == win) \ wattr_set(win, attr, config.colours.fallback.pair, NULL); \ } // Apply color `col` (of type `colour_t`) to `n` characters, starting at // location (`y`, `x`) in ncurses window `w` #define apply_colour(win, y, x, n, col) \ { \ if (tcap.colours) { \ if (col.bold) \ mvwchgat(win, y, x, n, WA_BOLD, col.pair, NULL); \ else \ mvwchgat(win, y, x, n, WA_NORMAL, col.pair, NULL); \ } else { \ if (COLOR_BLACK == col.fg && (wmain == win || wimm == win)) \ mvwchgat(win, y, x, n, WA_REVERSE, config.colours.fallback.pair, \ NULL); \ else \ mvwchgat(win, y, x, n, WA_NORMAL, config.colours.fallback.pair, NULL); \ } \ } // // Functions (generic) // // Initialize and set up ncurses extern void init_tui(); // Initialize `tcap` with the correct terminal capabilities. These are normally // sniffed, but can be overridden in the `[tcap]` configuration section. extern void init_tui_tcap(); // Initialize ncurses color pairs extern void init_tui_colours(); // Initialize ncurses mouse support extern void init_tui_mouse(); // Send escape secuense `s` to the terminal. This is done directly, bypassing // ncurses. `s` must not include the initial escape character. extern void sendescseq(char *s); // `init_windows()` and all `draw_...()` functions call `wnoutrefresh()` in // order to update the virtual screen before returning. It's your responsibility // to call `doupdate()` afterwards, to update the physical screen. // Delete and re-initialize all windows. After calling this function, you must // also call all `draw..()` functions as needed. extern void init_windows(); // If terminal width and/or height have changed, update `config.layout` and // return true. Otherwise, return false. extern bool termsize_changed(); // Wrapper for `getch()`. Makes the cursor visible right before `getch()` is // called, invisible right after. extern int cgetch(); // Return a (statically allocated) string representation of key character `k` extern wchar_t *ch2name(int k); // Corrects `page_top` and `page_flink` whenever the terminal has been resized. // Must be called whenever `termsize_changed()` returned true and right before // calling `tui_redraw()`. extern void termsize_adjust(); // Draw a box in `w`, starting at (`tl_y`, `tl_x`) and ending at // (`br_y`, `br_x`) extern void draw_box(WINDOW *w, unsigned tl_y, unsigned tl_x, unsigned br_y, unsigned br_x); // Draw the portion of a page the user is supposed to see in `wmain`. The page // is contained in `lines` and is `lines_len` long. `lines_top` specifies the // line where the portion begins. `flink` indicates the location of the focused // link. extern void draw_page(line_t *lines, unsigned lines_len, unsigned lines_top, link_loc_t flink); // Draw the scrollbar in `wsbar`. `lines_len` is total number of lines in the // page being displayed, and `lines_top` the line number where the visible // portion of said page begins. extern void draw_sbar(unsigned lines_len, unsigned lines_top); // Draw the status bar in `wstat`: // mode -- current mode of operation ("INDEX", "MAN", "APROPOS", "WHATIS", etc.) // name -- current page name // lines_len -- total number of lines in page // lines_pos -- focused line number in page // column -- column where the portion of the page the user sees begins // prompt -- cursor prompt // help -- help text // em -- error message // (Normally, we will display `help`. If, however, help is NULL, we'll display // `em`.) extern void draw_stat(const wchar_t *mode, const wchar_t *name, unsigned lines_len, unsigned lines_pos, unsigned column, const wchar_t *prompt, const wchar_t *help, const wchar_t *em); // Draw an immediate window. `is_long` specifies whether the window is long or // short. `is_wide` whether it is wide or narrow. `colour` specifies the window // color. The `title` and `help` strings is quite obvious what they are. void draw_imm(bool is_long, bool is_wide, colour_t colour, const wchar_t *title, const wchar_t *help); // Delete the immediate window previously drawn with `draw_imm()` void del_imm(); // Move to (`y`, `x`) in `w` and read a string into `trgt` (of length // `trgt_len`) extern bool get_str(WINDOW *w, unsigned y, unsigned x, wchar_t *trgt, unsigned trgt_len); // Interactive version of `get_str()` that returns after each keystroke. Use // like `strtok()`, i.e. specify `trgt` and `trgt_len` on first call, and set // them to NULL and 0 respectively on subsequent calls. The function updates // `trgt` and returns whenever the user types something. Return value varies // depending on the user's action: // - 0, if the user hit ESC or CTRL-C (or pressed left mouse) // - `n`, if the user hit ENTER (or pressed right mouse), where `n` is the total // number of typed characters // - `-KEY_UP`, if the user hit the UP arrow key // - `-KEY_DOWN`, if the user hit the DOWN arrow key // - `-KEY_PPAGE`, if the user hit PGUP // - `-KEY_NPAGE`, if the user hit PGDN // - `-KEY_HOME`, if the user hit HOME // - `-KEY_END`, if the user hit END // - -9 (TAB in ASCII), if the user hit TAB // - `-KEY_BACKSPACE`, if the user hit BACKSPACE // - `-GSN_WH_UP`, if the user scrolled the mouse wheel up // - `-GSN_WH_DOWN`, if the user scrolled the mouse wheel down // - `-GSN_BT_LEFT`, if the user clicked the left mouse button // - `-chr`, if the user typed any text character extern int get_str_next(WINDOW *w, unsigned y, unsigned x, wchar_t *trgt, unsigned trgt_len); // Return the program action number that corresponds to input character `chr`. // If no such action, return -1. extern action_t get_action(int chr); // Return the current compiled mouse status, after receiving input character // `chr` extern mouse_t get_mouse_status(int chr); // Beep if `config.layout.beep` is true extern void cbeep(); // Beep if `config.layout.beep` is true, and terminal size has not been changed extern void ctbeep(); // Set the terminal window title to `src` extern void entitle(wchar_t *src); // Copy `src` to clipboard. This is done using the escape code 52 (which may or // may not be supported by the user's terminal) and also via `xclip` (if running // in X11) or `wl-copy` (if running in Wayland), to ensure the maximum possible // success rate. extern void editcopy(wchar_t *src); // Delete all windows and wind down ncurses. No need to call this function // normally, as it's called by `winddown()`. extern void winddown_tui(); // // Functions (handlers) // // Redraw everythhing on the screen, calling `draw_page()`, `draw_sbar()` and // `draw_stat()` extern void tui_redraw(); // Error handler: display `em` in the status bar, and call `cbeep()` void tui_error(wchar_t *em); // Handler for `PA_UP` extern bool tui_up(); // Handler for `PA_DOWN` extern bool tui_down(); // Handler for `PA_LEFT` extern bool tui_left(); // Handler for `PA_RIGHT` extern bool tui_right(); // Handler for `PA_PGUP` extern bool tui_pgup(); // Handler for `PA_PGDN` extern bool tui_pgdn(); // Handler for `PA_HOME` extern bool tui_home(); // Handler for `PA_END` extern bool tui_end(); // Handler for `PA_OPEN` extern bool tui_open(); // Handler of `PA_OPEN_APROPOS` extern bool tui_open_apropos(); // Handler of `PA_OPEN_WHATIS` extern bool tui_open_whatis(); // Handler for `PA_SP_OPEN`, `PA_SP_APROPOS`, and `PA_SP_WHATIS`. // Opens a manual, apropos, or whatis page (depending on the value of `rt`) that // is specified by the user in an immediate (pop-up) window. extern bool tui_sp_open(request_type_t rt); // Handler for `PA_INDEX` extern bool tui_index(); // Handler for `PA_BACK` extern bool tui_back(); // Handler for `PA_FWRD` extern bool tui_fwrd(); // Handler for `PA_HISTORY` extern bool tui_history(); // Handler for `PA_TOC` extern bool tui_toc(); // Handler for `PA_SEARCH_BACK` (whenever `back` is set to true) or // `PA_SEARCH` (whenever `back` is set to false) extern bool tui_search(bool back); // Handler for `PA_SEARCH_PREV` (whenever back is set to true) or // `PA_SEARCH_NEXT` (whenever back is set to false) extern bool tui_search_next(bool back); // Handler for `PA_HELP` extern bool tui_help(); // Called whenever the left mouse button is pressed at position (`y`, `x`) extern bool tui_mouse_click(short y, short x); // Called whenever the mouse is left-button dragged to position (`y`, `x`). // (`dy`, `dx`) indicates the position the dragging was initiated. extern bool tui_mouse_dnd(short y, short x, short dy, short dx); // Main handler/loop for the TUI extern void tui(); #endif qman-1.5.1/src/util.c000066400000000000000000000562271510660157000143770ustar00rootroot00000000000000// Utility infrastructure, not program-specific (implementation) #include "lib.h" // // Functions // void serror(wchar_t *dst, const wchar_t *s) { if (NULL != s && L'\0' != s[0]) swprintf(dst, BS_SHORT, L"%ls: %s", s, strerror(errno)); else swprintf(dst, BS_SHORT, L"%s", strerror(errno)); } void is_executable(const char *path) { struct stat sb; if (stat(path, &sb) != 0 || !(sb.st_mode & S_IXUSR)) { static wchar_t errpre[BS_LINE]; swprintf(errpre, BS_LINE, L"Cannot execute '%s'", path); static wchar_t errmsg[BS_LINE]; serror(errmsg, errpre); winddown(ES_OPER_ERROR, errmsg); } } void is_readable(const char *path) { struct stat sb; if (stat(path, &sb) != 0 || !(sb.st_mode & S_IRUSR)) { static wchar_t errpre[BS_LINE]; swprintf(errpre, BS_LINE, L"Cannot read '%s'", path); static wchar_t errmsg[BS_LINE]; serror(errmsg, errpre); winddown(ES_OPER_ERROR, errmsg); } } void *xcalloc(size_t nmemb, size_t size) { void *const res = calloc(nmemb, size); if (NULL == res) { static wchar_t errmsg[BS_SHORT]; serror(errmsg, L"Unable to calloc()"); winddown(ES_OPER_ERROR, errmsg); } return res; } void *xreallocarray(void *ptr, size_t nmemb, size_t size) { #if defined(__GLIBC__) && (defined(_DEFAULT_SOURCE) || defined(_GNU_SOURCE)) void *const res = reallocarray(ptr, nmemb, size); #else size_t total = nmemb * size; void *res; if (0 != nmemb && total / nmemb != size) { // Overflow! res = NULL; } else res = realloc(ptr, total); #endif if (NULL == res) { static wchar_t errmsg[BS_SHORT]; serror(errmsg, L"Unable to reallocarray()"); winddown(ES_OPER_ERROR, errmsg); } return res; } FILE *xpopen(const char *command, const char *type) { FILE *const pipe = popen(command, type); if (NULL == pipe) { static wchar_t errpre[BS_LINE]; swprintf(errpre, BS_LINE, L"Unable to popen('%s')", command); static wchar_t errmsg[BS_LINE]; serror(errmsg, errpre); winddown(ES_OPER_ERROR, errmsg); } return pipe; } int xpclose(FILE *stream) { const int status = pclose(stream); if (-1 == status) { static wchar_t errmsg[BS_SHORT]; serror(errmsg, L"Unable to pclose()"); winddown(ES_OPER_ERROR, errmsg); } return status; } #ifdef QMAN_GZIP gzFile xgzopen(const char *path, const char *mode) { is_readable(path); gzFile gzfp = gzopen(path, mode); if (NULL == gzfp) { static wchar_t errpre[BS_LINE]; swprintf(errpre, BS_LINE, L"Unable to gzopen('%s')", path); static wchar_t errmsg[BS_LINE]; serror(errmsg, errpre); winddown(ES_OPER_ERROR, errmsg); } return gzfp; } #endif #ifdef QMAN_GZIP int xgzclose(gzFile file) { const int status = gzclose(file); if (Z_OK != status) { static wchar_t errmsg[BS_SHORT]; serror(errmsg, L"Unable to gzclose()"); winddown(ES_OPER_ERROR, errmsg); } return status; } #endif FILE *xfopen(const char *pathname, const char *mode) { is_readable(pathname); FILE *const file = fopen(pathname, mode); if (NULL == file) { static wchar_t errpre[BS_LINE]; swprintf(errpre, BS_LINE, L"Unable to xfopen('%s')", pathname); static wchar_t errmsg[BS_LINE]; serror(errmsg, errpre); winddown(ES_OPER_ERROR, errmsg); } return file; } int xfclose(FILE *stream) { const int status = fclose(stream); if (EOF == status) { static wchar_t errmsg[BS_SHORT]; serror(errmsg, L"Unable to fclose()"); winddown(ES_OPER_ERROR, errmsg); } return status; } FILE *xtmpfile() { FILE *const file = tmpfile(); if (NULL == file) { static wchar_t errmsg[BS_SHORT]; serror(errmsg, L"Unable to tmpfile()"); winddown(ES_OPER_ERROR, errmsg); } return file; } #ifdef QMAN_GZIP char *xgzgets(gzFile file, char *buf, int len) { char *res; while (true) { res = gzgets(file, buf, len); if (NULL == res && !gzeof(file)) { // There has been an error if (EINTR == errno) { // Sometimes ncurses rudely interrupts I/O. If that's the case, try // calling `gzgets()` again gzclearerr(file); } else { // Otherwise, fail gracefully static wchar_t errmsg[BS_SHORT]; serror(errmsg, L"Unable to gzgets()"); winddown(ES_OPER_ERROR, errmsg); } } else { // No error; return the result return res; } } } #endif char *xfgets(char *s, int size, FILE *stream) { char *res; while (true) { res = fgets(s, size, stream); if (ferror(stream) && !feof(stream)) { // There has been an error if (EINTR == errno) { // Sometimes ncurses rudely interrupts I/O. If that's the case, try // calling `fgets()` again clearerr(stream); } else { // Otherwise, fail gracefully static wchar_t errmsg[BS_SHORT]; serror(errmsg, L"Unable to fgets()"); winddown(ES_OPER_ERROR, errmsg); } } else { // No error; return the result return res; } } } int xfputs(const char *s, FILE *stream) { int res = fputs(s, stream); if (EOF == res) { static wchar_t errmsg[BS_SHORT]; serror(errmsg, L"Unable to fputs()"); winddown(ES_OPER_ERROR, errmsg); } return res; } size_t xfread(void *ptr, size_t size, size_t nmemb, FILE *stream) { const size_t cnt = fread(ptr, size, nmemb, stream); if (ferror(stream)) { static wchar_t errmsg[BS_SHORT]; serror(errmsg, L"Unable to read()"); winddown(ES_OPER_ERROR, errmsg); } return cnt; } size_t xfwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) { const size_t cnt = fwrite(ptr, size, nmemb, stream); if (ferror(stream)) { static wchar_t errmsg[BS_SHORT]; serror(errmsg, L"Unable to write()"); winddown(ES_OPER_ERROR, errmsg); } return cnt; } char *xbasename(const char *path) { static char pathc[BS_LINE]; strlcpy(pathc, path, BS_LINE); return basename(pathc); } char *xdirname(const char *path) { static char pathc[BS_LINE]; strlcpy(pathc, path, BS_LINE); return dirname(pathc); } char *xstrdup(const char *s) { char *const res = strdup(s); if (NULL == res) { static wchar_t errmsg[BS_SHORT]; serror(errmsg, L"Unable to strdup()"); winddown(ES_OPER_ERROR, errmsg); } return res; } wchar_t *xwcsdup(const wchar_t *s) { wchar_t *const res = wcsdup(s); if (NULL == res) { static wchar_t errmsg[BS_SHORT]; serror(errmsg, L"Unable to strdup()"); winddown(ES_OPER_ERROR, errmsg); } return res; } size_t xwcstombs(char *dest, const wchar_t *src, size_t n) { if (NULL == dest) return wcstombs(dest, src, n); size_t res = wcstombs(dest, src, n); if (-1 == res) winddown(ES_OPER_ERROR, L"Unable to wcstombs()"); else if (n == res) res--; dest[res] = '\0'; return res; } size_t xmbstowcs(wchar_t *dest, const char *src, size_t n) { if (NULL == dest) return mbstowcs(dest, src, n); size_t res = mbstowcs(dest, src, n); if (-1 == res) winddown(ES_OPER_ERROR, L"Unable to mbstowcs()"); else if (n == res) res--; dest[res] = L'\0'; return res; } int xsystem(const char *cmd, bool fail) { int res = system(cmd); if (fail && 0 != res) { static wchar_t errmsg[BS_SHORT]; swprintf(errmsg, BS_SHORT, L"Failed to execute: %s", cmd); winddown(ES_CHILD_ERROR, errmsg); } return res; } char *xtempnam(const char *dir, const char *pfx) { char *fn; int fd; if (NULL != getenv("TMPDIR")) dir = getenv("TMPDIR"); if (NULL == dir) dir = P_tmpdir; if (NULL == pfx) winddown(ES_OPER_ERROR, L"Unable to xtempnam(): prefix is NULL"); for (unsigned i = 0; i < strlen(pfx); i++) if ('X' == pfx[i]) winddown(ES_OPER_ERROR, L"Unable to xtempnam(): prefix contains 'X'"); if (strlen(dir) + strlen(pfx) + 8 > BS_SHORT) winddown(ES_OPER_ERROR, L"Unable to xtempnam(): prefix too long"); fn = salloc(BS_SHORT); snprintf(fn, BS_SHORT, "%s/%sXXXXXX", dir, pfx); fd = mkstemp(fn); if (-1 == fd) winddown(ES_OPER_ERROR, L"Unable to xtempnam(): mkstemp() failed"); if (-1 == close(fd)) winddown(ES_OPER_ERROR, L"Unable to xtempnam(): close() failed"); return fn; } int getenvi(const char *name) { const char *const val = getenv(name); if (NULL == val) return 0; else return atoi(val); } bool bget(const bitarr_t ba, unsigned i) { const unsigned seg = i / 8; const unsigned mask = 1 << (i % 8); return ba[seg] & mask; } void bset(bitarr_t ba, unsigned i) { const unsigned seg = i / 8; const unsigned mask = 1 << (i % 8); ba[seg] = ba[seg] | mask; } void bclear(bitarr_t ba, unsigned i) { const unsigned seg = i / 8; const unsigned mask = 1 << (i % 8); ba[seg] = ba[seg] & (0xff - mask); } void bclearall(bitarr_t ba, unsigned ba_len) { const unsigned ba_bytes = ba_len % 8 == 0 ? ba_len / 8 : 1 + ba_len / 8; for (unsigned i = 0; i < ba_bytes; i++) ba[i] = 0; } char *bzip2_decompress(const char *bzpath) { #ifdef QMAN_BZIP2 char *path; // Decompressed file pathname FILE *fp; // Decompressed file pointer BZFILE *bzhand; // Compressed file handle FILE *bzfp; // Compressed file pointer int bzerror; // Used for BZ2 library error reporting char buf[BS_LINE]; // Data buffer int len; // Bytes written into data buffer bzfp = xfopen(bzpath, "r"); bzhand = BZ2_bzReadOpen(&bzerror, bzfp, 0, 0, NULL, 0); if (BZ_OK != bzerror) { winddown(ES_OPER_ERROR, L"Unable to decompress Bzip2 archive: BZ2_bzReadOpen() failed"); } path = xtempnam(NULL, "qman"); fp = xfopen(path, "w"); while (true) { len = BZ2_bzRead(&bzerror, bzhand, buf, BS_LINE); if (BZ_OK == bzerror) xfwrite(buf, len, 1, fp); else if (BZ_STREAM_END == bzerror) { xfwrite(buf, len, 1, fp); break; } else winddown(ES_OPER_ERROR, L"Unable to decompress Bzip2 archive: BZ2Read() failed"); } BZ2_bzReadClose(&bzerror, bzhand); if (BZ_OK != bzerror) { winddown(ES_OPER_ERROR, L"Unable to decompress Bzip2 archive: BZ2_bzReadClose() failed"); } xfclose(bzfp); xfclose(fp); return path; #else winddown(ES_OPER_ERROR, L"Bzip2 archives are not supported"); return NULL; #endif } char *lzma_decompress(const char *pathname) { #ifdef QMAN_LZMA char *path; // Decompressed file pathname FILE *fp; // Decompressed file pointer lzma_ret lzret; // Lzma return status lzma_stream lzstrm = LZMA_STREAM_INIT; // Lzma stream FILE *lzfp; // Compressed file pointer uint8_t buf[BUFSIZ]; // Decompressed data buffer uint8_t lzbuf[BUFSIZ]; // Compressed data buffer lzfp = xfopen(pathname, "r"); lzret = lzma_stream_decoder(&lzstrm, UINT64_MAX, LZMA_CONCATENATED); if (LZMA_OK != lzret) { winddown(ES_OPER_ERROR, L"Unable to decompress XZ archive: lzma_stream_decoder() failed"); } path = xtempnam(NULL, "qman"); fp = xfopen(path, "w"); lzstrm.next_in = NULL; lzstrm.avail_in = 0; lzstrm.next_out = buf; lzstrm.avail_out = sizeof(buf); while (true) { if (0 == lzstrm.avail_in && !feof(lzfp)) { lzstrm.next_in = lzbuf; lzstrm.avail_in = xfread(lzbuf, 1, sizeof(lzbuf), lzfp); } if (!feof(lzfp)) lzret = lzma_code(&lzstrm, LZMA_RUN); else lzret = lzma_code(&lzstrm, LZMA_FINISH); if (0 == lzstrm.avail_out || LZMA_STREAM_END == lzret) { xfwrite(buf, 1, sizeof(buf) - lzstrm.avail_out, fp); lzstrm.next_out = buf; lzstrm.avail_out = sizeof(buf); } if (LZMA_STREAM_END == lzret) break; if (LZMA_OK != lzret) { winddown(ES_OPER_ERROR, L"Unable to decompress XZ archive: lzma_code() failed"); } } xfclose(fp); lzma_end(&lzstrm); xfclose(lzfp); return path; #else winddown(ES_OPER_ERROR, L"XZ archives are not supported"); return NULL; #endif } archive_t aropen(const char *pathname) { archive_t a; char *pathext = strrchr(pathname, '.'); if (NULL == pathext) a.type = AR_NONE; else if (0 == strcasecmp(".xz", pathext)) a.type = AR_LZMA; else if (0 == strcasecmp(".bz2", pathext)) a.type = AR_BZIP2; else if (0 == strcasecmp(".gz", pathext)) a.type = AR_GZIP; else a.type = AR_NONE; switch (a.type) { case AR_LZMA: a.path = lzma_decompress(pathname); a.fp_lzma = xfopen(a.path, "r"); break; case AR_BZIP2: a.path = bzip2_decompress(pathname); a.fp_bzip2 = xfopen(a.path, "r"); break; case AR_GZIP: #ifdef QMAN_GZIP a.path = xstrdup(pathname); a.fp_gzip = xgzopen(a.path, "rb"); #else winddown(ES_OPER_ERROR, L"Gzip archives are not supported"); #endif break; case AR_NONE: default: a.path = xstrdup(pathname); a.fp_none = xfopen(a.path, "r"); break; } return a; } void argets(archive_t ap, char *buf, int len) { switch (ap.type) { case AR_LZMA: xfgets(buf, len, ap.fp_lzma); break; case AR_BZIP2: xfgets(buf, len, ap.fp_bzip2); break; case AR_GZIP: #ifdef QMAN_GZIP xgzgets(ap.fp_gzip, buf, len); #endif break; case AR_NONE: default: xfgets(buf, len, ap.fp_none); } } bool areof(archive_t ap) { switch (ap.type) { case AR_LZMA: return feof(ap.fp_lzma); break; case AR_BZIP2: return feof(ap.fp_bzip2); break; case AR_GZIP: #ifdef QMAN_GZIP return gzeof(ap.fp_gzip); #else return false; #endif break; case AR_NONE: default: return feof(ap.fp_none); } } void arclose(archive_t ap) { switch (ap.type) { case AR_LZMA: xfclose(ap.fp_lzma); unlink(ap.path); break; case AR_BZIP2: xfclose(ap.fp_bzip2); unlink(ap.path); break; case AR_GZIP: #ifdef QMAN_GZIP xgzclose(ap.fp_gzip); #endif break; case AR_NONE: default: xfclose(ap.fp_none); break; } free(ap.path); } void wafree(wchar_t **buf, unsigned buf_len) { unsigned i; for (i = 0; i < buf_len; i++) free(buf[i]); free(buf); } void safree(char **buf, unsigned buf_len) { unsigned i; for (i = 0; i < buf_len; i++) free(buf[i]); free(buf); } // Test whether the character at `src[pos]` is escaped bool wescaped(wchar_t *src, unsigned pos) { int c = 0; // number of '\'s before `pos` int i = pos; // iterator while (i > 0) { i--; if (L'\\' == src[i]) c++; else break; } return c % 2; } void wunescape(wchar_t *src) { int i = 0, j = 0; // iterators while (L'\0' != src[i]) { if (L'\\' == src[i]) { switch (src[i + 1]) { case L'a': src[j++] = L'\a'; break; case L'b': src[j++] = L'\b'; break; case L't': src[j++] = L'\t'; break; case L'n': src[j++] = L'\n'; break; case L'v': src[j++] = L'\v'; break; case L'f': src[j++] = L'\f'; break; case L'r': src[j++] = L'\r'; break; case L'e': src[j++] = L'\e'; break; case L'\\': src[j++] = L'\\'; break; case L'"': src[j++] = L'"'; break; case L'\'': src[j++] = L'\''; break; } i += 2; } else { src[j++] = src[i]; i++; } } src[j] = L'\0'; } unsigned wccnt(const wchar_t *hayst, wchar_t needle) { unsigned cnt = 0; hayst = wcschr(hayst, needle); while (NULL != hayst) { cnt++; hayst = wcschr(hayst + 1, needle); } return cnt; } void wcrepl(wchar_t *dst, const wchar_t *hayst, wchar_t needle, const wchar_t *repl, unsigned dst_len) { const wchar_t *const hayst_start = (wchar_t *)hayst; unsigned offset = 0, repl_cnt = 0; const unsigned repl_len = wcslen(repl); wcslcpy(dst, hayst, dst_len); do { if (offset == 0) hayst = wcschr(hayst, needle); else { wcslcpy(&dst[offset], repl, dst_len - offset); wcslcpy(&dst[offset + repl_len], hayst + 1, dst_len - offset - repl_len); repl_cnt++; hayst = wcschr(hayst + 1, needle); } offset = hayst - hayst_start + repl_cnt * (repl_len - 1); } while (NULL != hayst); } void wwrap(wchar_t *trgt, unsigned cols) { const unsigned len = wcslen(trgt); unsigned line_start = 0, line_end; while (len > line_start + cols) { for (line_end = line_start + cols; line_end > line_start && trgt[line_end] != L' ' && trgt[line_end] != L'\t'; line_end--) ; if (line_end == line_start) break; trgt[line_end] = L'\n'; line_start = line_end + 1; } } bool wmemberof(const wchar_t *const *hayst, const wchar_t *needle, unsigned hayst_len) { unsigned i; for (i = 0; i < hayst_len; i++) { if (0 == wcscmp(hayst[i], needle)) return true; } return false; } bool wcasememberof(const wchar_t *const *hayst, const wchar_t *needle, unsigned hayst_len) { unsigned i; for (i = 0; i < hayst_len; i++) { if (0 == wcscasecmp(hayst[i], needle)) return true; } return false; } void wsort(wchar_t **trgt, unsigned trgt_len, bool rev) { unsigned i; int cur_cmp; bool sorted = false; wchar_t *tmp; if (0 == trgt_len) return; // This is a trivial bubble sort while (!sorted) { sorted = true; for (i = 0; i < trgt_len - 1; i++) { cur_cmp = wcscoll(trgt[i], trgt[i + 1]); if (rev) { if (cur_cmp < 0) { tmp = trgt[i]; trgt[i] = trgt[i + 1]; trgt[i + 1] = tmp; sorted = false; } } else { if (cur_cmp > 0) { tmp = trgt[i]; trgt[i] = trgt[i + 1]; trgt[i + 1] = tmp; sorted = false; } } } } } unsigned wmaxlen(const wchar_t *const *src, unsigned src_len) { unsigned maxlen = 0, i; for (i = 0; i < src_len; i++) maxlen = MAX(maxlen, wcslen(src[i])); return maxlen; } unsigned wsplit(wchar_t ***dst, unsigned dst_len, wchar_t *src, const wchar_t *extras, bool skipws) { wchar_t **res = *dst; // results unsigned res_cnt = 0; // number of results bool ws = true; // whether current character is whitespace or in `extras` bool pws; // whether previous character is whitespace or in `extras` unsigned i, j = 0; // iterators if (NULL == extras) extras = L""; for (i = 0; L'\0' != src[i]; i++) { pws = ws; ws = false; if (!skipws && iswspace(src[i])) ws = true; for (j = 0; L'\0' != extras[j]; j++) if (src[i] == extras[j]) ws = true; if (!ws) { if (i == 0 || pws) { if (res_cnt < dst_len) { res[res_cnt] = &src[i]; res_cnt++; } } } else src[i] = L'\0'; } return res_cnt; } unsigned wmargend(const wchar_t *src, const wchar_t *extras) { bool ws; // whether current character is whitespace or in extras unsigned i, j; // iterators if (NULL == extras) extras = L""; for (i = 0; L'\0' != src[i]; i++) { ws = false; if (iswspace(src[i])) ws = true; for (j = 0; L'\0' != extras[j]; j++) if (src[i] == extras[j]) ws = true; if (!ws) return i; } return 0; } unsigned wmargtrim(wchar_t *trgt, const wchar_t *extras) { int i; // iterator unsigned j; // iterator bool trim; // true if we'll be trimming `trgt[i]` if (NULL == extras) extras = L""; for (i = 0; L'\0' != trgt[i]; i++) ; i--; while (i >= 0) { trim = false; if (iswspace(trgt[i])) trim = true; else for (j = 0; L'\0' != extras[j]; j++) if (trgt[i] == extras[j]) trim = true; if (!trim) { trgt[i + 1] = L'\0'; return i + 1; } i--; } trgt[0] = L'\0'; return 0; } unsigned wbs(wchar_t *trgt) { unsigned i, j; // iterators j = 0; for (i = 0; L'\0' != trgt[i]; i++) { if (L'\b' == trgt[i]) { if (j > 0) j--; } else { trgt[j] = trgt[i]; j++; } } trgt[j] = L'\0'; return j; } wchar_t *wcscasestr(const wchar_t *haystack, const wchar_t *needle) { unsigned i = 0, j; wchar_t haystack_c, needle_c; if (L'\0' == needle[0]) return (wchar_t *)haystack; while (L'\0' != haystack[i]) { j = 0; while (TRUE) { haystack_c = towlower(haystack[i + j]); needle_c = towlower(needle[j]); if (L'\0' == needle_c) return (wchar_t *)&haystack[i]; else if (haystack_c != needle_c) break; else j++; } i++; } return NULL; } unsigned scopylines(FILE *source, FILE *trgt) { unsigned cnt = 0; char tmp[BS_LINE]; for (cnt = 0; !feof(source); cnt++) { xfgets(tmp, BS_LINE, source); xfwrite(tmp, sizeof(char), strlen(tmp), trgt); } return cnt - 1; } int sreadline(char *str, unsigned size, FILE *fp) { xfgets(str, size, fp); if (feof(fp)) { str[0] = L'\0'; return -1; } char *nlc = strrchr(str, '\n'); if (NULL != nlc) *nlc = '\0'; return nlc - str; } unsigned split_path(char ***dst, char *src) { char **res = *dst; // results unsigned res_cnt = 0; // number of results unsigned pos = 0; // starting position of last path found unsigned i; // iterator for (i = 0;; i++) { if (':' == src[i] || '\0' == src[i]) { res[res_cnt] = &src[pos]; res_cnt++; pos = i + 1; if ('\0' == src[i]) break; else src[i] = '\0'; } } return res_cnt; } void fr_init(full_regex_t *re, char *str, wchar_t *snpt) { re->str = str; re->snpt = snpt; int err = regcomp(&re->re, str, REG_EXTENDED); if (0 != err) { static wchar_t errmsg[BS_SHORT]; char err_str[BS_SHORT]; regerror(err, NULL, err_str, BS_SHORT); swprintf(errmsg, BS_SHORT, L"Unable to regcomp(): %s", err_str); winddown(ES_OPER_ERROR, errmsg); } } range_t fr_search(const full_regex_t *re, const wchar_t *src) { char ssrc[BS_LINE]; // `char*` version of `src` regmatch_t pmatch[1]; // regex match range_t res; // return value // If `re->snpt` isn't in `src`, return `{0, 0}` if (NULL != re->snpt && NULL == wcsstr(src, re->snpt)) { res.beg = 0; res.end = 0; return res; } // Convert `src` to `ssrc` and try to find a match in it xwcstombs(ssrc, src, BS_LINE); int err = regexec(&re->re, ssrc, 1, pmatch, 0); if (0 == err) { // A match was found in ssrc regoff_t sbeg = pmatch[0].rm_so; // match begin offset (in `ssrc`) regoff_t send = pmatch[0].rm_eo; // match end offset (in `ssrc`) regoff_t slen = send - sbeg; // match length (in `ssrc`) wchar_t *wmatch = walloca(slen); // the match as a `wchar_t*` unsigned wlen = xmbstowcs(wmatch, &ssrc[sbeg], slen + 1); // `wmatch` length wmatch[wlen] = L'\0'; wchar_t *wptr = wcsstr(src, wmatch); // match begin memory location (in `src`) if (NULL == wptr) { // Cannot replicate match in `src`; return `{0, 0}` res.beg = 0; res.end = 0; } else { // Match found in `src`; return its location res.beg = wptr - src; res.end = res.beg + wlen; } } else { // No match found, or an error has occured; return `{0, 0}` res.beg = 0; res.end = 0; } return res; } void loggit(const char *msg) { static FILE *lfp = NULL; time_t now; if (NULL == lfp) lfp = fopen(F_LOG, "w"); time(&now); fwprintf(lfp, L"[%s] %s\n", strtok(ctime(&now), "\n"), msg); fflush(lfp); } qman-1.5.1/src/util.h000066400000000000000000000372351510660157000144020ustar00rootroot00000000000000// Utility infrastructure, not program-specific (definition) #ifndef UTIL_H #define UTIL_H #include "lib.h" // // Compiler magic // // Macros used for silencing compiler warnings #ifdef __GNUC__ #define CC_IGNORE_UNUSED_PARAMETER \ _Pragma("GCC diagnostic push") \ _Pragma("GCC diagnostic ignored \"-Wunused-parameter\"") #define CC_IGNORE_FORMAT_TRUNCATION \ _Pragma("GCC diagnostic push") \ _Pragma("GCC diagnostic ignored \"-Wformat-truncation\"") #define CC_IGNORE_ENDS _Pragma("GCC diagnostic pop") #else #define CC_IGNORE_UNUSED_PARAMETER #define CC_IGNORE_FORMAT_TRUNCATION #define CC_IGNORE_ENDS #endif // // Types // // Array of bits typedef char *bitarr_t; // A full regular expression, i.e. one that is represented both as a string and // a `regex_t` typedef struct { char *str; // string version regex_t re; // `regex_t` version wchar_t *snpt; // a snippet of text that's always contained in matches (used // to improve performance, as `regexec()` is quite expensive) } full_regex_t; // A range typedef struct { unsigned beg; // beginning unsigned end; // end } range_t; // Compressed archive type typedef enum { AR_NONE, // no compression AR_GZIP, // gzip AR_BZIP2, // bzip2 AR_LZMA // xz } archive_type_t; // A "fat" file pointer to a compressed archive, that supports multiple // compression types typedef struct { archive_type_t type; // archive type char *path; // path to / filename of archive FILE *fp_none; // file pointer if uncompressed #ifdef QMAN_GZIP gzFile fp_gzip; // file pointer if gzip #endif FILE *fp_bzip2; // file pointer if bzip2 FILE *fp_lzma; // file pointer if xz } archive_t; // // Constants // // Buffer sizes #define BS_SHORT 128 // length of a short array #define BS_LINE 1024 // length of an array that is suitable for a line of text #define BS_LONG 131072 // length of a long array // Rudimentary logging, used for debugging #define F_LOG "./qman.log" // log file // // Macros // // Swap two integer values `a` and `b` (without using a third variable) #define swap(a, b) \ a = a ^ b; \ b = a ^ b; \ a = a ^ b; // If you get spurious `gcc` warnings about NULL string arguments being passed // to functions that require them to be non-NULL, wrap said strings in `nnl()` // or `wnnl()` to suppress them // If string `s` is NULL, replace it with "" #define nnl(s) ((s) ? (s) : "") // If wide string `w` is NULL, replace it with "" #define wnnl(w) (NULL != (w) ? (w) : L"") // Return the size of array `arr` #define asizeof(arr) (sizeof(arr) / sizeof(arr[0])) // Allocate heap memory for an array of type `artp` that is `len` elements long #define aalloc(len, artp) xcalloc(len, sizeof(artp)); // Allocate heap memory for a `char*` string that is `len` characters long #define salloc(len) xcalloc(len + 1, sizeof(char)) // Allocate heap memory for a `wchar_t*` string that is `len` characters long #define walloc(len) xcalloc(len + 1, sizeof(wchar_t)) // Allocate heap memory for a bit array `bitarr_t` that is `len` bits long #define balloc(len) xcalloc(len % 8 == 0 ? len / 8 : 1 + len / 8, 1) // Allocate stack memory for an array of type `artp` that is `len` elements long #define aalloca(len, artp) alloca(len * sizeof(artp)); // Allocate stack memory for a `char*` string that is `len` characters long #define salloca(len) alloca((len + 1) * sizeof(char)) // Allocate stack memory for a `wchar_t*` string that is `len` characters long #define walloca(len) alloca((len + 1) * sizeof(wchar_t)) // Allocate stack memory for a bit array `bitarr_t` that is `len` bits long #define balloca(len) alloca(len % 8 == 0 ? len / 8 : 1 + len / 8) // Assign the value `{ v0, v1, ..., v7 }` to 8-value array `trgt` #define arr8(trgt, v0, v1, v2, v3, v4, v5, v6, v7) \ trgt[0] = v0; \ trgt[1] = v1; \ trgt[2] = v2; \ trgt[3] = v3; \ trgt[4] = v4; \ trgt[5] = v5; \ trgt[6] = v6; \ trgt[7] = v7; // True if `v` is in array `va` (of length 8), false otherwise. `f` is the // comparison function/macro used to compare `v` with members of `va`. #define in8(v, va, f) \ (f(v, va[0]) || f(v, va[1]) || f(v, va[2]) || f(v, va[3]) || f(v, va[4]) || \ f(v, va[5]) || f(v, va[6]) || f(v, va[7])) // True if wide strings `w1` and `w2` are equal, false otherwise #define wcsequal(w1, w2) \ ((NULL == w1 && NULL == w2) || \ (NULL != w1 && NULL != w2 && 0 == wcscmp(w1, w2))) // Make wide string `w` lower-case #define wcslower(w) \ { \ unsigned i = 0; \ while (L'\0' != w[i]) { \ w[i] = towlower(w[i]); \ i++; \ } \ } // Log a message, together with a timestamp, into `F_LOG`. Use this function // like you would `printf()`, i.e. specifying a template followed by zero or // more values. To be used only temporarily for debugging, not in production. #define logprintf(...) \ { \ char ___[64 * BS_LINE]; \ sprintf(___, __VA_ARGS__); \ loggit(___); \ } // // Functions // // `x...()` functions, and also some other functions, will call `winddown()` to // fail gracefully in case of error // Perform the same function as `perror()` but, rather than printing the error // message, place it in `dst` void serror(wchar_t *dst, const wchar_t *s); // Fail and `winddown()` if `path` doesn't point to an executable file void is_executable(const char *path); // Fail and `winddown()` if `path` doesn't point to a readable file void is_readable(const char *path); // The purpose of all of all `x...()` functions is to fail gracefully using // `winddown()` whenever an error is detected. Otherwise, their behavior is // identical to that of the standard functions they replace. // Safely call `calloc()` extern void *xcalloc(size_t nmemb, size_t size); // Safely call `reallocarray()` extern void *xreallocarray(void *ptr, size_t nmemb, size_t size); // Safely call `popen()` extern FILE *xpopen(const char *command, const char *type); // Safely call `pclose()` extern int xpclose(FILE *stream); // Safely call `gzopen()` #ifdef QMAN_GZIP extern gzFile xgzopen(const char *path, const char *mode); #endif // Safely call `gzclose()` #ifdef QMAN_GZIP extern int xgzclose(gzFile file); #endif // Safely call `fopen()` extern FILE *xfopen(const char *pathname, const char *mode); // Safely call `fclose()` extern int xfclose(FILE *stream); // Safely call `tmpfile()` extern FILE *xtmpfile(); // Safely call `gzgets()` #ifdef QMAN_GZIP extern char *xgzgets(gzFile file, char *buf, int len); #endif // Safely call `fgets()` extern char *xfgets(char *s, int size, FILE *stream); // Safely call `fputs()` extern int xfputs(const char *s, FILE *stream); // Safely call `fread()` extern size_t xfread(void *ptr, size_t size, size_t nmemb, FILE *stream); // Safely call `fwrite()` extern size_t xfwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream); // `xbasename()` and `xdirname()` use a static string to guarantee that `path` // doesn't get modified // Safely call `basename()` extern char *xbasename(const char *path); // Safely call `dirname()` extern char *xdirname(const char *path); // Safely call `strdup()` extern char *xstrdup(const char *s); // Safely call `wcsdup()` extern wchar_t *xwcsdup(const wchar_t *s); // `xwcstombs()` and `xmbstowcs()` will always terminate the string in `dest`, // even when the length of `n` is exceeded. If you don't want this (e.g. because // you're converting/copying parts of strings), use their vanilla counterparts // instead. // Safely call wcstombs() extern size_t xwcstombs(char *dest, const wchar_t *src, size_t n); // Safely call mbstowcs() size_t xmbstowcs(wchar_t *dest, const char *src, size_t n); // Safely call `system(cmd)`, to execute `cmd` in a new shell. If `fail` is // true, and the return value of `system()` is non-zero, terminate. Otherwise // return said return value. extern int xsystem(const char *cmd, bool fail); // A safe version of `tempnam()`, that also creates the temporary file whose // name it returns, avoiding potential race conditions. Unlike with `tempnam()`, // `pfx` can be more than 5 characters long, although it cannot contain an `X`. // In case of error, `xtempnam()` will call `winddown()`. extern char *xtempnam(const char *dir, const char *pfx); // Return the value of environment variable `name` as an integer. Return 0 in // case of error. extern int getenvi(const char *name); // Return the value of the `i`th bit in `ba` extern bool bget(const bitarr_t ba, unsigned i); // Set the the `i`th bit of `ba` extern void bset(bitarr_t ba, unsigned i); // Clear the the `i`th bit of `ba` extern void bclear(bitarr_t ba, unsigned i); // Clear all bits of `ba`. `ba_len` is `ba`'s size. extern void bclearall(bitarr_t ba, unsigned ba_len); // Decompress the bzip2-compressed file at `pathname`, place the resulting data // into a temporary file, and return its path extern char *bzip2_decompress(const char *pathname); // Decompress the xz-compressed file at `pathname`, place the resulting data // into a temporary file, and return its path extern char *lzma_decompress(const char *pathname); // Open compressed archive at `pathname` for reading, and return the relevant // "fat" file pointer extern archive_t aropen(const char *pathname); // Read a line of text from "fat" file pointer `ap`, and place it into `buf`, // `len` being the length of `buf` extern void argets(archive_t ap, char *buf, int len); // Return true if "fat" file pointer `ap` has reached `EOF`, false otherwise extern bool areof(archive_t ap); // Close "fat" pointer `ap` extern void arclose(archive_t ap); // Free all memory in an array of (wide) strings `buf`. `buf_len` is the length // of `buf`. extern void wafree(wchar_t **buf, unsigned buf_len); // Free all memory in an array of (8-bit) strings `buf`. `buf_len` is the length // of `buf`. extern void safree(char **buf, unsigned buf_len); // All `w...()` and `s...()` functions that place their result in an argument // don't do any memory allocation. Said argument must be a pointer to a buffer // of already allocated memory. // Test whether the character at `src[pos]` is escaped extern bool wescaped(wchar_t *src, unsigned pos); // Unescape the string in `src`. `\a`, `\b`, `\t`, `\n`, `\v`, `\f`, and `\r` // are unescaped into character codes 7 to 13, `\e` to character code 27 (ESC), // `\\` to `\`, `\"` to `"`, and `\'` to `'`. All other escaped characters are // discarded. extern void wunescape(wchar_t *src); // Return the number of occurences of `needle` in `hayst` extern unsigned wccnt(const wchar_t *hayst, wchar_t needle); // Replace all occurences of `needle` in `hayst` with `repl`. Place the result // in `dst` (of size `dst_len`). extern void wcrepl(wchar_t *dst, const wchar_t *hayst, wchar_t needle, const wchar_t *repl, unsigned dst_len); // Insert newlines in `trgt` so that it word-wraps before it reaches `cols` // columns. extern void wwrap(wchar_t *trgt, unsigned cols); // Return true if `needle` is in array of (wide) strings `hayst`, false // otherwise. `hayst_length` is the length of `hayst`. extern bool wmemberof(const wchar_t *const *hayst, const wchar_t *needle, unsigned hayst_len); // Case-insensitive version of `wmemberof()` extern bool wcasememberof(const wchar_t *const *hayst, const wchar_t *needle, unsigned hayst_len); // Sort the strings in `trgt` alphanumerically. `trgt_len` is `trgt`'s length. // Setting `rev` to true causes reverse sorting. extern void wsort(wchar_t **trgt, unsigned trgt_len, bool rev); // Return the length of the longest (wide) string in `src`. `src_len` holds the // length of `src`. extern unsigned wmaxlen(const wchar_t *const *src, unsigned src_len); // In the following functions, `extras` is ignored if NULL // Split `src` into a list of words, and place said list in `dst` (of maximum // length `dst_len`). Words can be separated by either whitespace or any of the // characters in `extras` (only by those in `extras` if `skipws` is true). // Return the number of words. This function modifies `src`. extern unsigned wsplit(wchar_t ***dst, unsigned dst_len, wchar_t *src, const wchar_t *extras, bool skipws); // Return the position of the first character in `src` that is not whitespace, // and not one of the characters in `extras` extern unsigned wmargend(const wchar_t *src, const wchar_t *extras); // Trim all characters at the end of `trgt` that are either whitespace or one of // the charactes in `extras`. Trimming is done by inserting 0 or more NULL // characters at the end of `trgt`. Return the new length of `trgt`. extern unsigned wmargtrim(wchar_t *trgt, const wchar_t *extras); // Apply any backspace characters in `trgt` extern unsigned wbs(wchar_t *trgt); // Case-insensitive version of `wcsstr()` extern wchar_t *wcscasestr(const wchar_t *haystack, const wchar_t *needle); // Copy all data in `source` into `target`, line by line. Both `source` and // `target` must be text files. Return the number of lines copied. extern unsigned scopylines(FILE *source, FILE *trgt); // Read a line from file `fp`, and place the result in `str` (without the // trailing newline). `size` signifies the maximum number of characters to read. // If the read was succesful, return the resulting string's length. In case of // EOF, return -1. extern int sreadline(char *str, unsigned size, FILE *fp); // Split path environment variable `src` into a list of paths, placing them into // `dst` (of maximum length `dst_len`). Return the number of paths found. This // function modifes `src`. extern unsigned split_path(char ***dst, char *src); // Initialize full regular expression `re`, using `str` and `snpt` extern void fr_init(full_regex_t *re, char *str, wchar_t *snpt); // Search `src` for a string matching `re`. If found, return its location in // `src` as a `range_t`. If not, return `{ 0, 0 }`. This function uses libc // regular expressions, and has plumbing to make it work on `wchar_t*` strings. extern range_t fr_search(const full_regex_t *re, const wchar_t *src); // Log `msg`, together with a timestamp, into `F_LOG`. Use this function only // temporarily for debugging, not in production. extern void loggit(const char *msg); #endif

`MXg̈d$`⫼@< hɌzXíjl-/xxGLIڎY57,őPy_K ȖZcᶌ^{NP~--ˑe挸-͞f57+r ڎ[U?3nL{NP+y]%w>4mn=Pfp!y<${C uUƵj;f^4'?KZ_לXtUgy.$C<ljlƜ?;-]9 jN~МP5f(<xa|O`HLꗐPr@+u=.S/=}Qykg}W=1zcz)R3 r7 ڱ_yW 0s9-6=;U-}fsZ0/TjUn6<E lq@ -Y1 ?eZ0/U@?*5V ^/3lq@K q šƖؕ+oÂyA/xQ@_;f f}iA;^_H<&PP^7+j{̹-D4Ǣ9sCh Db~sDz.w/cUBgkc#?juC2ӣLꗐԖ>/ D\hN~ЌOKHG$1sfKc֘*F<4Ed ʕ`kC-X` UQnk􍧯IaTjI?jU%'I3.| ܀Ogzƿg<${ЙPx?knWRv,r@rPKߙa>ls^j]Z!ŋ:{N\'=o:j*<*^Ъb?EћxQ0(χ_h33F]/?j 7U~>O'{_/!aUɀee~=U?.e\;J˘R*W Cp*,_W^n(6FR! 9AeӑCP󡖝nz۱a<=VhмZ"ןsyHc֨!|:Okc:|j8=DWFĚ74S5ZG$9A~x!n33دe}&HkKDTl\;9C{ˈ;4@sޕx=6p˅z=iMעj~FĨ9c֧>jlЂy*/^x޿_xو\)/7P`mA=0D<sey<=W^mO!RR IDATMy{N#ZLD<$<}eLD}cxIvqd X7wOe4tw&5x"Q4}L"flKj[3eDB'l{h[xayN:ٕ!*zh)RkcX#7}h8jřԹS_۰~pˉ+#k#_Nv%tӸ|ZRݝI:{vA؏`/mFZäԻלQ.GT5Iyk =rb.Ms&x ꒷zɋrb|QOFttk4C/ֵlj2~!7ٚFj{V追d觍uڷ<7ף?q9T_(h̥o@]#O5Z7Ū<^S^FK1@~1v_&IҟDZ3Ӣ|8i|6 ^F~C@$HD~@ZqkQ¿p|4FfS4qݓw_Tzzb֌鰇`" LБ:i)wn]MP7f5`5tأks`?9\**Mޠ0'TP!H@` `+_>Sk7Fٗp+$tkޭj8(ڟfgU6O;:@֚?qmJh{IΤmM>SG+C|C{bxBVR̥hj5S}b.N?v `GSk;xxM: E& x@<@<@<M`/\ʺvGauzx @< xxeǞ^+`[RC'ji*.{nOU)ݯ3.3Gm~*şdN4fF鬝qkޝǜgX뺴Y4>Eaga+}fSoVzK*Y<;7Ǟgg`RC=I5M!{+ տ`:وGž{ na5N]kDB}dZly\!3 տ`*rϭϫ5x<$if&o<ʎ{]u'>Pۙ/4ԓL{_ԟ{ykM %L{^{rC 4[nwm__lCwJ+#kh*sHՃȚ9*2 5Z\POR_^\O%D-5y~H孓\XەQC>mxXS|Eγo/X y|TB&uQpm}e˹蝞{z)fClʻ.V~~jm>Kͦ;Gg'C-2ڗ@{&ʆg, 5xEޡh'\}^ &3z2R̥_کxkM;eh9j>*λz }+1dWHtkm{Rl<}z>nhm65xPYۼ?(xCf3 IV_u[ܳ^cdB<~g}Ww=H;po|gu=&oZߓoBnC,jcOES \Ur6>tNGb?nezf/^qRC9níyw]OYԄ r+덖uqrR=?Di(EԗO[ϸ 쩝zS*{jp[i2F)K169;2e+\C,ׁ=5;I3XkҧI{2vӐƪ}}=k}i mI %lSG]UYZxf$Jiv՜e$0Ul<5`kCxHm ֚'Kq nQnP@} 8mģs 5z=%Ok%jZ/=ʚ=5J::^3ּ;13{˵^a/a3knCk~}h-OoMӝ?(x(x?q9ɴWIuw&uZ;j͹x/@!l+mEz,GJMFZ~hm6$M=>T`jmPtRҨٽkTvs_(|;y#uֱd<R`Pc*I{z-HΤΝJX簧$&[+#֚:ٕЕ .#uɮĎKY3[۵u 5uVɾPRWҧ?pi|thUʿjr\%W="w 5tedMK+Ϫ4ԓ̺vWU4l{h|ּђ(y<{tg,}.Mޤ!_S6C7hFcn6Rs LEc.=f `D<^SHɛyşH;PKL->#D>`7alJ{BI6Z4[7 ⡀xNXILտ`5 Md qrbJzK .V|ŚgJ>xJ(ĥX ulK{X)ͨ%@epI2%Ôؗn=SԫjX>\gx4YD<^~~vUuZ_$yiQM/delPH@M# &>^UtgQ4P~H&mIK1fskj %$S>Li}$I^xӧOn( A* `U/GՊP @4UoBS}b[P.>CK$$$'O2cL54`@ߥK>4q= `O\ʺGauFx @< xݝI44y*G@(;lZrykM \\6zGN$d=G5>Uh,?gPg!}ҭywt^S_(7FBɴx{F>WI X_4zy´uaqS<嚆zi5Liik=I<}~P Gc.F<PAǃ=y8חuM|wgR}]ֳʑ:Ń=:x)kj2@.J~1\(gZK1&oT;PFeJZV;X4lM\ $IrԱNCkYNRJy䬭tHkR']Q{}Fh,3~`PORb ?öa;q[<ؿ6N}~@<䏇`[R H2ç`ґ4oN,Le3SO]C;u]סCFxVyTB|[5IX@.=ڭ@HcOf' e7_ݭ'ng?rϣ+ґ:A<ۍ# VQcA{jW̌U{JRW=w{ba[cSU:R'}<e%FWMB=u:|^UZxVK'.{hXm'C]㰧f=iӦuw&5kxxMVj *7~L{n'ZH5rmI Y#_05 qBs~T㋦rv(x>p/k {Τ}Rbe+XI]ԗϲ~οYiQxQ6P0P¾dOsi&M@zͷBIu;(X{ʞs)^qz4ޙcl+[}~+#z\/ZyBެ5 ?va'ثxI1 ,v]yݨsѿ[{;_A[9Gia;s4 a9#u_D>ࠠnN IDATʶB3SDcn}6]z_Y/]%'d8kqYUƚ&C_]\ݑ2lZx!Gn@<o9[ Yǜ;Pą=%f Y&{v*MFI n~ӝ;`/5x:``gܩ}"wΣWk)ұNC'XfCScwnߞ:7.P`8_)A/>4wO9#hSuw&i{Þ)O$t+1Zyƒd'f55gt̑X+xD6rpۊRđ=ec)݈="Hhx鵌dZ!rϣKͦuzRXV'.M\^2yZS'raۊΤBI=^~=V\N%TwgR~;fyhzbkcy+3d.Oe^>S}zLBK1+٣LnͻWLGI2XBgUIZn ֩<&oq4; 6g~/C#`MXuuЭ $^9DA>Szu+K~ (oI$IUU4bw_\?q%!(=[nMhw5zٰ*0k.y뤟62 }~#?x2*:?m4ih=[_֋Fi'K~h_\S7l*rϭ}aW>)oiFSK1hw58x~no#RɋҏdN {_<:Tme5G`UNB@C4lĭC5VSZ+4MvX[ 񩪼 ۩A%oɋiZ?{?'Cqpª~aǑ{Oԏd:7h+m2@ 5Kjmr_jj҂DY]LI:|0% 챛c3@xE%5I(?;}P&@} {]Wuk&u%l$b.W2__xXq͒vےhxMG+V'jHomNj|kTh\xFi;hP6@} !dV䭓ZRˆ^Paz@x~$Ǧt-Ik %)${rʅU5LM=̻.^;13uTB|^Ma<7E{kDRG72/0g(xU8;O[kٚf| %9qAK;ZS 5Y A?X$~=Z;할5n{}J]1^ 6KTKNqp|9Lͦ~vM-M{nOUQ_8 SGWuVzjlJ^XuFk}uZ#r5L9`' g:;z%ԑZ:w+rk Y%n1((/ğsg]؆X|fd(S -\\jm6uPkkb `cF$TkafɮZM-\zc:WsPw0Z~iK1=4KRPV#p`ےjz"}!axJ4>UtTB9 I >U9>C_ZkbLnڹ@i{bKcSUSZG ;Pǿcq}*lS.tg鵑C:>|H^> :=?g 2g],=O\zmI4ޙcl˾6]vSԩ ŏ^{;,@@} &dX+үǪӦ?_x=1뀥X4ZSDcn}y~~^P*-\j2sdvz~ހk-+&Pkx9=_[K$(h̕dfL! `X |HX/db?}I٧x֚:Rgw1Pцxn+0(3ZS/[ [o,F[^O1 /J)smTe}-+_~ur}[\@SZͬ ɗbtUΤ2s Aokjz"MȜpDB'2 %DW>^e(ɛ׭Km XmoqG\ ԗPix%1>^K>CIHfVa*SC=I $s)ޘckxE]uƛFSIw&|[|ɭyX)>jvޣjm6u7Ϝ[ZkŚV0ci)P|yL?8XdS䞛AqFח߷{R* |_Ξ=+I|^*IP x6>>Ǐ.]ܸ/ ڱРk׮eF+Ν;9cgW%I˺sfff~f[oeoCCm#)<5;;;+`Q(RKK^ѨѨᰮ_w"X)<^uuu9f4L$t=⢮_^X(~v `LGG hoo/3ޗ=< W^^z{{_O?-񵷷kttT^7c~_%  4::Bvz(n\{Q.w:U~~:::&XwS}˥C###eRԎ+1ѡ^z)g* `L{{{IߓOWWמ& vmIV,5600;wdѹkhhH#@7n7~J^__~;1IRK=v8Ѩ3yN_*BσmcbuUm_n߾PHynlUZwaaxY* `l[<uv~=Ԅ‚߅&ZZZH;a.]GIZZZ4>>ތP1wsq*ؖ}.g[x\/Y-//Mi Ygʥ YQ---I#m -bCKKKT~3"u%_w~_asZFbp0)lW4U<W}},q:‚$kbCCCA+~Ŵ$P544}<[odԑiIN̔]咚x}vFvqqqG׻.DjDžx<6_|wj}٪sz~Su㱅B!k~~^㒬|5??9`"Nag ӕnMMHg9HMfZi7&$K---jii}{m7.czxMN3+~we^z%翣Ѩ=zv;mzkkttT9 UOO74H$ѾNReɗ}0zw|v>$II<׫I?>grqMr^xQkIۧ~NuvvMH:>߯P(h44gϪ~ ;$Qv2I:K&z3x<$.vr^jhhPZwcҮ˖*3%m?ϟO{bFW.q}\ =/שRcDn#u}|~_uuu1i۷קs魷JrP8(Eq'97mYM_jGB#ֶۮ]y]vMgϞM`{|7H"FFFt匄;C^K&K߻qJ)\z5-S;~njFɤlzQKF׆a'Skub?A<[o1]s1Ǘ@Nb &R]zU}}}3c_ZNv,El岕pUuuu9q300P(h4O{uBPnNb8u]i8ov|V4M=zƮڸlck@ cʍ>Gittymx\###;ãG422Q{%MAo|.mgۮ\Rjr5,beܹsw1\JŞK.yc 'wmիWX_|EسG?oA._ϑƮJIjXhhŎ;337AF$񸖗u}i~Vys)~^3tff&oP(P(^zN<wuղNZmv}rY^^Аzzz ]}T3WFC{~ܹsWWW]\\ Q4u 0@n.I$>|B!gx߯yMLLT1ӣyrO(K$f4Jrϻ~XX%VzS^Xvz3UsUr\JJȬ59qT}}Ο?I ue0ފ䊹䊹*U7 z5%$d6Vqڎ\HuR8J%+ѣGwl~_d e"_sUKh2d5z*ho3d[=Z-=$kDp[D+IZ\\ܜpGGG _O?:{n߾s9OLL([---WKK$Ν;|r)~۫P(zIR4ܜfff[۫zKwQz{{ҥKWooFyS.ٞ}lBFGGm_/5??9==-߯nuuui``@~_hTpXW^zSo37_vφ={VεYx * `lKJ6J>pIurF5Y?z7c֚Zޞl*ќqPXMɏh3I:kͦNCkkP5j4RxS6ۉe;.Y d-Y gI2}Z36󁵟ɞU.k JvXooF ׫utt( %bS+8 BjiiH( ) LtuuIR΄KooΞ=h4h4@ lopp0k򣽽]zzYܟv li{6׫qutt8e!ߟO+O<utthdd$yJlw{] J\l: @ ܹsyB߽R_WŔgCC&''z5~>䓒_'8z@ mqFΧKk4Z՚]#sѾɶF ^TBf5zf-5w% Ik>C2}d9#6Ӻ3 I믧$oM)CWR kR U]~cniEV"(x(._p8lii:::ӓQ P4[oY;Ν;N"=c$ZKKx$ٳg:c'~2Iiɑ~gDp6[^_]^WZ\\L+ gf-O;y tjlw{[U]hv}'[V3z|^*)=_khrrRht{;Qly1u%'^PWT 2;ؖVqWC<׭iҌ$~ҷQM+ia:kw-O:\S.HW]{Rٷvg^.>gvիWuՌiX_HȞ"Ν;Y?+a'v}˽$̣G433#)(ρy^ݾ};-z%l{FFFҒXI}͞zVRwq<_[)Rlo^V'YSv"qYŔľ>ScҥK%=R\x@ G*:E's{fi5yS9IR_mmLn|}^9 myFN6O^]*;)K/A6N &`{ ҆IMlEdt}vF7{Mx<1*:@βJb{[UWzܝ;wz?(ŔB֩]۱g_g04-ٖT2/9۵وH.Z$=Usbz9ǙMʹsɬ3d-T7`wW---wgffF ֝;wtm}y=r֬ BN"]~_htgTVߜSDl6FFnNZK3~Jb{[UWR}.k[/ŔH*hڋx؉R3$-k\Sg}j$fsM\ddTGzp>gIԕ,ǹ28e; o٨ζV;7$+ٹ5500.B!')Fuҥ#fffӓ1%tѿ8:/$ܮFM;ȾbF nNoKW&󺺺;5sދx(E\kkrfk"{'.*;QݨۖCQ'.'i >>]<ٖJa ];Y9P +6!kTTϽlɥ횛$yzjooyhIF ng{v,[>;ql} |-fz3eny2z\'r;ǕݯP -{flruS|GJq֣&6F6[j_6A$2Ju2hMX җ&+/_Ҋ`<3g9眛0 +;vC L:={Fv Ϣw5_)/ֺ̟̆c+Hg>2}Xk"[kŬ>5]0 ca>:뗼SNA3Ѩx!i G(Ғ_5*J$bMi~p>W*`TUT*(#ǭ-T*D",--5Wu$KjKKK yںycH$K$v ;Ͻ=\Ha>B!<}@OކYp]ZZЗ< ;~7q$&I>Xڨ-`Y%/L;mvO&̟Lw_-/ gm8sN_!vQ_ZJڰY X n}l@~?0t0W$r7ϽDDD(J(D"X]]aT*P,ceed`ffayfEQJs8Y*|>WEwwwDzNǛsT0pmoߢ\.7(+^.C",x- @(,X[[C*jyQ̗ax9ɤ_Ѹ:(0vvvsUUȫIױߣab?p?e2mK^91>gϞpnðwSM!pcotwN>yygċӟOaXLDD7_8&* ?Cz Eؖ&<#"""""?7&g)?_?1 s+fUa "_""fqKEeD 2н,|I. p08 .+INJnt: ;nDDDDM4 ,0 yS8w߱7/Y oϗ?6xssO"""""""""""""0 `L4f8I\:X>1;P=x}u=ꎻ5 !P( NիW?BB$  lll\H? sP(t׻/e [~O""""" "r&Lwm֕n=k-Ōt δpEH$H{>\wbG&/' 0 aBR4MÇ9؜/870Ѹ¡δKt=#6𮷏ړ,ݭ8> `ߵaߵvǠ#ɄyDA> DDWP<r9d2T*0 A( @EM/E0&c\q'] 2~KY7> =UZA׌n0 qOx8Gnq@T븝\X;on|.8D|fDtmxanӸs`7g=^qO$"+ ;8_F`Y" Şa۰p~{{c嫷4Wi>ۧ_ ՙ'/OL;{~P/m0q';{>3ޟ=kz`➈vc5o3Rs V1tvK;X/XY*3sړOD)qp"ܹ7o "jgffopT]__X]!2 @>G6EZm۷oioPh\.۷UU? #H p+I.>}d2(MjٿxhcV /PD׫V.0e~%q<{ R DxR`LfdK^Լv~ӟ~9~ ͛7P?($Ei.rfffQ|>9O"""""\ i(VCDPhc՞1DL/Nݥ}L;p|y߄΁`uw>I;$|/_u #;ؙs`ۨ0bex2#Yo7ù6ֿk;PGif/X~ iug#giy~Yy෇`ss,{'*ծNu sd2 ]ױ*TUe{EQ rk޹Z}g<G*۩*t]G8nj3 1㼿P(W^5\Ke UUD<~aT*P?nT0e~Y+D"lEA$(# /j^;?}Gџ~9l bH$L&d2 MӰ8~fzeHHcqqc$"""""Wp6 ڳ6j 3jv50ba_W3j جvwyI/N90Mhgj_뎅rcG&lO8M=?`ϻzoAI߃_CYB8^< V6i_ v)us˙v |g"pfOD-IӐe|LWӧO: 2PORXZZjyZm؀,X__i_WXMӚ@IRXYY+[QDі^^~p8MSڠJ* gF4?)m+X,z=Gёa˰?#dY‚?>0s}>v~&I!DBǯZbmm |3"N# l~󓈈&4;7;_)~!zU8sNCh{76,?~(a^`'vC)/_|/#Ij_ t{H:ztuy6WpدD 0p뺿oe;Kr9W]^ҥxՇ R:diTj/߀T&Q=g?w]>Fz{wff[~Flmm_ϫIDDDDD7*.A*ҞPi9v^hߵ??DnlIh-wj]80G=y=[.[V൫D"qXwղR333r='+J˱YUնN͓۷o_pU z/s^y?4T*R@e=~|0DDDDDtq huǂ[p7{tL*PP3aѶ"?o)qCHgI{P-BvCiʃ̳yADt x﷬Һ}FsOM]V]v{b߳(-Û~%!H@UUyR b?~2a(śWEQ=g?w]>ze?M 2??'`J5an_n9z݂| :GΫ)ՙrSΏypW"cU]|wu#~fnv{ȗe//[X^vڏ֫[SVd2h4 ]?0 LCrks^Hn/=(-s:}dY<|rZ.Mui(gsw$7?IDDDDD4e)^{ۥ[ۺcm::]b; %kÞ^_ y ǯq>|X3T,|غgw8y݃f"oԤ-iZvwwHm1N^5V__R]6=#eYn9VK^Dk/U뗫8j湽*$4 ,R4'{m^N~~uk 8jOjgcw־k|`6\|~/+N,$<5?Q*ǡ* @>G6m\Ewox  T*!bH@ӴO"""""|w N^v0b7|`|d"@]JϳӟOa]f""""͛7P \*hH|oLNSx=Dm83i ..U}߄zĽ {ކXхaLԆ=kS.PoAw ΤvbDDDDDDDDDDDtqO\?_=u= Xbi `Vn|@gDDDDDÇ"""""kDDDDDDDDDDDDDD7`"""""""""""""0 8X>1;P=x}eҌ8>59$  lll}ixP(P(`iiJtBЅ>DDDDDDD!. gҁȄ}ƭo]ڳ6,݂X!~oC̨ KLYN'Ck7+f|dBz/A"pѵ 0 a& BHR4 >dэhinA8!ȭ cKw+O0wmwm8v"H02a7{.\Ra888x<rd2H ( @l1NDDDDDDtYY7> =UZA׌n0 qOx8UGnq`ggfffRHtßw""""""=s-lw܏5 _{"0X, ]JADDDDDDDDc `=mÞa߱q=r beI}w\oYO4〳ը{P/cԱWj>^jڟkb3x5iG փ{ l:Vz!X7!Τgw/0=A$pA> i܂uςsq8Oz/sov,]W^B$J %qlmma}}纮#!Ce|>l6jϞ=CTB"@<(T*G&iZP(4|_.733o69$t:mR"7o@QFH&Pe F( w?\.׵1l? 2GΙMӠ(J{|vnll@UU<{ KKKB(Jd25 "͎YH$cZb#=ۧO"L6CQs>̼?p8D"p8 ]1`mmKPQP凝¡д=oc◉Ǟ8DPܠԙwvA|ꆅqg{,ؿ1bs8^۾kL;_C4=};6p(s`ۨޟ=-^ 8-n ɤ}k;?b|%o]K;;;D"um0FEQL&:چI ˲Br EQD(JSR.j1@׼ru ~ҴDdUUL&iG֟P^\.Ce UUD:5KR~vO;"zeHğt:I]133UU~MR(Jz܆ig8J9 r=[gnߠT*~v"""""""`_.-4jڨ6̨T lFM8sng0l:ݲWs Kg=aD{50ba\3j6݀_N! |ka,^]i Y-+JϽ__u]S™v |Zs;?^o7{E=bD"BMᆦi~`z>${)t]aX^^ JDZ1l!2Z-^iMUTՆ ȲJ%?4pRtD2ښ_Zh%tJ* gN4? ,Mw,C$AR^ǤvVU!7ptHXeU꺎t:WJ%:UӴ3X |n ܄a=U3돯_affPh{QOP|YVzUQ <]8qΤW)ׇV Gn;I:sNپW$|DΙdPT뺿n+6(BaxANU* WU?.?%r4-\*뷺7kkk ,Jr=c?v6y}z5﫷DmwRv vy]Շ 0oryU-9zts:㼽hOB۠[վ{>WۓϼtMtpߏΝ|_kXړ*z{gasOm""+ 1;\mxVxO`*K* dY%?sT*^TUmC< ;UUc?~}[TJS9*}ens;yKT?DDDDDD.MCXt ΜqSݏr';'kuqDgI{pSx~+E:_9\.rjcP34FM9$"Ί"*J2?0}67hy^/욚jn執W~0iEaciY(J/jj}iRiD]G5!## 0I rH$PUo޼ATBXǏ; vy;::Q?Pj+,Om2 2 _I( VWW?eejvyMDDDDDD4j*ĦTsEp[R^em^_jnA޹s"]oׅ:73u.-'~7W /nQoivk{sP=*(۝oPޒ|)TeWffx𡿤v9?k""""""QcjBdp/nI9`8齻$}׆=m_l}qq=kcOnߜi*`=ľurQos ;DDtxK={A'о{o$iXW7oxT:F0 ̯cgAI ݳEPl>0aFͦѺcwav\Q/NG~5f_ǚLw9k|EZ̺VZ1aͨCz'=޾k|`6#{)/bSLDD׋@fkk TQ իu3_J ÀuJbql׋D"H$ }SwZZZZj5Mq=T*0#|6zPKKKD"6L;bXS0i 92[:wg}yMDDDDDD4J&I>Xڨ-`2SVݛמuX,?GpNoI߂i9߃p~w%nu)/6[1yٗ2= R{+$7-w? }xhG |d\X# R Jb*u(]ױ 0"*ss<dү0\^^|uwwwՃbT xa<2HPUo߾E\nv@uD"lnn6FJ%ED"sLQȲ$I(-=v*T*ϟ| yA֛\.׵}yMDDDDDD4J i(L|yδ|{g] wR^?w`=9&^NzoZn4#7t?Rѣ5ݾsCc5(H `߱L:=-5uᎃNjŸ7{ 9¡_"z=ADD7[2vww( * 2JR QB/XYGr9?_Rx<UUa1;P=x}eՌ7nz( MbH$( P(666P(iڵ^oTIDDDDDDDWG]@ԞA3ibgڰt bA)1&,rYN'n7+f|dBz/A"pBE?S,S.Q(B*ix!nVu0n-­[b>r+jz{ړ̟L8sCwmԖkcΕv$` 0 ."?~ǏT*CFR0 |(7OAVY]'_kނMA׌0r'K%oV]s;;;aG?Kh`^+mfVi\98XckEp+$""""""""""4 +j {w_WP^oߪ3-X+ S$}gA0tށ'"k}##>yyg'`ݳ`k c-_fm` g[\p(`DY&~yuǂଭ=@x!Xgҁ3玳מ | ¾V7Oz/a.]"dffx{]r9TզcB8(Er-+766*={%B!J%d2$ l6l6p7o( ~DQ$I(0f[qX#!Cuta`aap?O#YwffC4(EQPT|>߱tii xϞ=CTǠLBrǏӧOL&^S<[[[X__o{MӐH$R kkkMf 2_9sKDDDDDDDfqKL p8GnP{gS?> 90LwmLhy=/$4`8v#|?-$6b^?!'nX17(?J = ்}V{Rs. ;~9tŞQ 6S{`GƺgA]{,;I5G1~'=DDt%ht: YRR(HRBMU(«W*7eBUUD",//*]133UUQ.*RJM$H&0 2iX\\iN'^$t]o y<(t]G*B&i8_WhZ*',# @u,..v<,x"EQD(JS[oo;y׼u޸UU:p˰}y{0-`=mᯔn4~Ep=醶 za=o`*|Y*XړPs[VB`kp}m7Aރp( g=5_8;[DH?3@ 6U7x۞q>u{Vq+?FUk` p~wzݼqx(G{DD4>333~尶n% ^* IDAT0 Ϟ=CB/ubeWyUz՚Rɯ4eL&WnщDbdӧO: ߖP(T*x<; #T*!SUbm *֐p8t:H$X,ֱ,XXXhX,2XS5Mj6mUAs7+++yfff EQFG6a%""""""cACX ~pb>_xhY/Uړ 4Mڳbq@cicTዀv˙tR4#zٙll I[# 28"ۧ^v}-ݓ q}=y!i0)U%xs{DDWA4R=X+^UUmU*C+l޹J%T*ȲmH4oԻoYNN{{~@0S,Lnkޒ333-w ;W%""""""%i`Τu,ۭr"RCPoI^p(r܊?I>h@`߱XKrc"֯B}|X_K ~8َT`798ۉԳYDƽ~{/~y_e/ թgҎ+fs o]v%wmX,HT`߱aj5̆> @<2~Kw^c"",//#N##0 T*(Y[kkk}6TU۷oQ.!˲_nYaER)?dUUP.f;?BUUy_Ǐd2 ]__(u~y333_ X^^n~$4?~ Lƕ޵Q=kks_"T*aaad! ! 0 dٖjH$uR\.5[__GTB<0 |lMe"!CQK 'NCer9|۽.--5΃ CQB!J%dY#@Qh61^H*r8ɠR@cZewGy -A78&^L01 vw+=~?žLDDDy`aa>DDDDDDDDD19= O Ǧtn&aD4C]ȗ͞a "_"""""""""""4 -{\28 \ hh竿'{+"""""""""""X GDDDDDDDDDDDDDtC ~N Ç""""""""XLDDDDDDDDDDDDDtC0&"""""""""""""! 28>Iʵ$}cXwS{R1YC3jrRѵH$P( 4M8\BX,Ǝ!""""""DW=k-VÌt δ?I}`,LH%_+BEQ 2;#@8 |V֞`nűI 絃wiG ߃DDtmT*vZ[\\N:; 5ԼL y_kFM7Ʉ'B<Ϫ{ #8[UDDtm`ggq """""""10䅹ޖn6Nrρcn=^qO$"""""""""""$mXQ m8߻ |'/OL;{op(@رx{ᓀ[˷љt`{_Hyi  DqU,=ݗ3ޏמ | KA78'`۰m`offx{]r9TՆy~@4E2(0 |lOPh\.] F(\.7 ֙MӠ( EAR>|---!ٳg(JH$ d2-\wiD"p8 (JX[[ks+D"޷s]!rO_ôsqTUJe BH$=@Z>vwwHDDDDDD444뎅5`^8#v`>2|ּoŠY^8s_&Z§yg7Τ=r9^ƾcCy&^?{v=-8\uς8-n L:-98=DDD}4 t,pJEQJ ZyH$L&a2TUE2iX\\lBeߪP(W^/ːeBUUD",//O8ɤ""t]oY0;(D"P)f4M0 ]0q]FV7NEQL&zvkvb/ʠY1o0&""""""`=mᯔn5~Ep+VB`;;w*}epUZw,Ԗk=|d™s+[z=o`؊YW=m4} gځujy=Rso+k` p~wzx8H~J, WK/+/zuWB^yWinս\3Ǟ856H= .\p"""""""w(o.WiW;zgڎVK$I+jn[^jx|}^Cz  Ϻcyy/[vGQg&:M^mN{:SNñZvox~sU=yp'\~'"wORä~^mXղͽaTWk0%vs\CXaucNR.[^Y,\,bN(ygk:>lnnho2u) Dyy;s}:I"l^yM@j_[]@ q> <;v,ؾH?Lwu$"":N,zHmrӵU+shH$r i{ӲAt;+wF[~潗z Y+O/_D""""""!`LQ*\^m,9KN Ug%x_޽|kH%\V]xk_a}|t׳Z>.+j*j[׎u!5oP*#=Gf""f.ņF0H$Z?> ƍl6[[[޽Jkqq.D"ֆR8G"9 bqq~ØA﷛y%Bx<խT*,//7`X 2aͻC0⚉DN$-DXa\HįO/mQg" z ۰aQgd`U~.új6l=G!-f s /I+8pg];:f'tj| 9U lFu k۪?+Þ{}`LDD$`ii txxi\.Cuh6X-HR(~h_YY;wp$I)䥥ezWVVpa|7܄i~ee{Q*P,FPw"LBuLOOeAaPCmjX,~t]aX]]vGqks]p8'OK6|Ll6D"M74MAhRSuR)ܹs{r`QTY0Gޕ!?1x\`[ X꿨K? /v%.\H ]-#,h!yT]p?p.AU~x-?%8=kj 3@e,]-S.PxQ-RPu5Ό u`LDDTkgg\~e&k|8<<{ϧ~ MӰ4 0;; 4f__|,t]ᅬ}{CsG?fggx!oZ^ksy?~|}0rA08-|-篟z~(888i3ֆ9""""""":S!M7 X׹%x{=VNS.ƾjwułuՂXT=pxΜ@:;d@^b>ޫ5oa>yODD}y "F0Cөr'\TWq!1$Ό۰!dȯ[>q!t'j^+j DDD# 3V= IDATU;0*wʅm,YWZUX[pg]HHp.9.UGޝl($`}.`""auxGDDDDDDDaLt83Km_{@:q[[pFL۰LDDDDDDDDDDD4 *ϔʆśysσ}etk '"""""""""""08SyO?:9] 3JNZSv>s\?ޯ{MP]!9Z U sc_;;b86 w[X [nsw307 5/dUȻ!BT w֛+WW!mK^\\:uL3sG2O$sp8d2H$[n5Kos.kDDDDDDD`3ᯒS>X~GUysf~yiWxk)/X^,rg]`P `;fC}B}]ߝpq!YVCgqpH A;۶az{cC~US)C/@W{^ ?$^3 4p=we`wݎΏi?fXYY L2ݻwnzzu ^R r\]  NFv^v aaa[[[X!zecc?O(*Lg}qnܸ0`& HRX\\Pҏ~T*k$AT}(B8F\n&I`}}ݯjDCo=c0L͛7T¤b_I@~.#0>U ~`=#n,;+?BN?Wp'\W/0ycq'~0 r]+Pr}@wn䣎m;q<p륞1𙈈-dX,"4-64,l6 M󭯯7tnmmamm Vp]'lll4K/ߥ|* 2 r2ԃ変`YEϷޏX,ᯨ<Z=ŒϥR339'""""""0 ]*'r=n-^(,Ҧ|qJ]omeWX&>gIZwf7wԳ6w5&"":wDVYh'\/_&kX,%lwAҋh4 [J}Yq(2 K:hE(,iYgpTB\iӃS.\h%o'l+kvz/2ŻR۱ꎕv%ׁ{^xN8H4Q;I+jn;=8~>6*RϮLsED rFT$A<G(CzkF]zq^ѣLjzrrrhu9I;;;޽an$0M[_l&4Mg6E"@8Ɠ'OP*P,3]_""""""":;SjK?S`ZbIvݿ݌.ȝ|;!\<7nrWz-{5]oO""zv8cvnܸ/[.QTa2~7'fM:~cD6E8F,kX]o7VRJ$I0 i"4aLDDDDDDDT0'+XW-8bIfK%[{F*P1|4 n:&U)=ճ!"6T #C޽{n`SIEtQ=f\t: {g9pOj)q"":;*[vXҼ\!^z']ё\y}D4 bcj?ismW0빵u|'k-4v'xbg۰_%t|X*} W@{s.9p9_ }0y:~N]uK%?45lV+b#Vx rA"nlqh42ZV]Ae{-~qUGxօ}\H%vdzݾv[1y?TJ=[Okkk(ˈFX\\l @"ʵDHDD׃ nNI\oкVM:ȕJkkk`0X,禗U*`&0 @\FXh4ZW`07nh?xz& bD"~`]6=i ^7a{K'-< ?DmE) fݜ5${h.G2lûmCk~c/d>п7L^4)y%eJs8؆RֶUwoWje{g3aMDD劣,--!N##4MeM0mPR bh ׹{.$t]ra%"Ν;H&~l6mz}t]aX]]iYr|="R820`ss [O]בJpΝr2DDDDDDDD('*`ꏼ+C~&c/*Q!U[U\?C@EPPڕ` J60aҮ+@Yy@2%`h|?SX @'5mPm6C@?JxAR`\ [p\(ymk2ԇ*gY˙q`_!?|A.8 4Mi_~Սx<}]CP;;; 07}:t]8J~_~`vv Kg?C(BT_mSZ1G?xիWMC|>W^! Bu|m|wo~}ez?4M|A~ MӰ4 0;; 4f_eO={e@4?cmm < """"""s<ߞ}peY}[{J[řry)c_u/̺bjA}B}:PuX<}gA h S(*2>裶>ycaaK/_115[ xZ1}n[K7>U!J>d>KΜ 3%""4KDDDDDDDtpUz+93Λ8op.9p'ܮb> -]PB!DDDDDDDt1CS.YUP_g~k\HӘF8m*E] d~`QH$M`&r@^b>?Wּ9Dp}GP@P;_`0 P( N=.HP(ѣG|^û\QwTht U %XaC.Ȑ_ukނmp[~%Cy@yV^a]DDDDDD$p`"\YwK7[{Frj^b_G6^ LeHDt22#""""""">L9>rΏm KKSJ>{>Ci=gÞ87VOr.҃Yǽ=rB:ŽՇpʆ2vW{Q*:'ĝpz{z i[/P{pzڗm1o:C33Μg74.Z-) 1??]xfٶpy&J8t]G\2GqM,.." T*!u7ܣaD"u\8oܸd2Y( uC^9 ܈Umnn>^Za ! A4\.uT*a|>l6[AiM$HR(uО^A|?CB!$ B!^J|:>g>>`DJ[[[r?nDDDDDD0 ęrp>&N.U;O=8.ޕ m{v.9^[C/,7Nc-G۰a]YΜl}b,5 Þ8CWK6`Y S2g;6f8 璃/Ǻ E=[R`ssYuhVhAܿpzhp8p8h44 G4i܄Fu!hI0M0 LOO#csspT R [[[{ khh4h4 0.qP{ү~9kzz4Tu,//w մ*ԧ?_ua}lu-I?-JSѣG4 <踏l*B8iy0 ŶAҵkנiBX,4a N]RD"uT*XYYA. nB4(bX8k BX]]i]wz2h.C&ItO#Dr 4 JDZNOOfRwD"wy9QTCH$B!a塅Cm}޽߿똟׿K<%5}^=N3ݭ{;օW^s'\IK%Μwy'\ O]JNqf>Ѕv$O+wyjv|̓X6j1𙈈bZ KJ%N`8 ?ĹX,6&K "4>޵5z8kðL&3򽇻}^}J⏵vyg!LB4ņ{Ӱ>ϑv="h{/fݱb 3Iit[-2vPU+tW= jG"w^ZYۙzːאxj"8By稉\s >zLN2I4>G;;;نak$0MshŒ͖\>yxW~[d2d2B!]ױ_M;p`Z>'5Nw6vo٫70}׽Uoҿut 2DDt~p޹{sZ$Vs\C[}[)-vq:Js=^T.QEiP~f]O>0e؉;LMnӎNv"BVࠔg7K_{tq-{W8Ht"׃%H 5`lu؅3CoYyTǂS`vý)9jl| 9U lFu k۪v2lësm; ۯ#VVVpa|7܄i~[eORTBXD42LD\4 wE2똞nm6E<ǝ;wL&l6;{| L0 Hir]/?;w4tiii(?x0 s_[fvvvt:xIwy0 '.#JΝ;MߓN}"""""":= i 򮌱1XW-8S.] 꽣` o:J)::vo 3uOBG/=l`p~ݛ}>VQUHRnaP ՒʁHl~sS 9/ٝO2oծxVTp-$ p8r͑,cu`R B4D"-ǜdP.at]Öa-oK=wvvT*H$]a&tj6}h _R/{\T$" LߵJ/i{6\.7;: u?uf(y)gK"DDDDDDH\xX wułuՂXt4 9wwc@:1l&""") auur} BDDDDDD_+&f+<]k8fsuSҮcn?ƙq9 2_"""X<DDDDDDD.MDop.u ip'\U~m `"ɯ x""""ziLOO#ֆ2yщD"4 i", ѐ1&3~{E """z}G,шqM"""""""""""""s09`L#c[ۇ kE_b7^5;H`>@^b>?;;b ;]D"BG b3w.Ư{{^x)>VGk_{QB1.Y"0^Bږ KAwpW ;,J$ͫCB!$ B!@TJ%~a"t](B.k*uM,.." T*! H ױBP&>쳮kaGifT*>_N,Ý;wP.x>t]ifX__{h9 """"""@)C`S.KծB^H%o# L5C3EUo=PX~Gp3U W*Լ0}wʅ}_;f|=SUwCY_cׯw+8Pzq'\~qwօ2P%2ޓ=t;~"":?DPd@lqq=T*j$AT}(B8F\n"R)ܽ{E:Jr0 !N#"5 EaH~WpT7L&D`eDU=fYԅD>m_Lm{֭'9X,h4I<\MLZoΌ/!\޼ c6u+CyP?ޯ]v#uB4q<ۺ.OߌSzf^ ,g""zw@]+~.-+]0~' źmggl@.O r,X,6&u}(5M&4 b>Bz㎇2_YYSTGDDDDDDD`Vږ.+> ޸SJrjؓt;h;v.ꢼP:z!DDDwssR;{k0LD.0kl&K/_:A`[6\Qf{ 'I3 P//< \&VKʯd8s;f 7K'DZu鶼;BVҮw:z_0I~5"q[[[-jwvv=t H$]af`r{{ID  ޏx(CͳgJgaP.>#{`^`Y0S˿m{5]ԭS=ǏѻR햀tb1n;i֍{ ,//0 AT*lnn0:k1mЮb!Nq[ݻ\tynڏX.[@םp;.'NDDX~… M ھR0 hbt~rU*?TF|* ~_RTg$?5}Z1MDDDDDDDTi wm *ND*L=gc}L.;v,ؾXf{<mw@Wf"":Dx^H9RxmS'r}Etvyb^9 *??8+g$3""""""":SϮ쇃պбz"Hv~l?]y x!uɵ0kɟn;on_;f{Cy|sɩ;z @)]At, AX,..օW MD8a(9ekk H׆`~m7ru vP.Fj x!b"8E/I ʊ,..84v%xqnll0 DQbssAudYDDDDDDD[hhW›凥] t@o˚s̺pgݡ!P04%xA\cWcBvݴCQPR!m{stj^xoc՟7iW`˱svfS/ѻkgg ruM͛7y;=Ngnݺw]Q*.Qݻwa]b\li" u]YY֭[1-?OmObnښߙ x `QG{=VXZ^8t4S.ƾ(=u(/LDD BX]]E\G}Ăй~M'|‚~qﯘw͖;sF}BڕeG0839rAfKDDv1L6ۜDPߪg:v'ܺ% ӹr BUX[pg]HHp.9.UGޝl($`}.`""z{躎xT! }wqo+Gc >nN 7{J5?}iU.tn;GUHےd8i_aǼt3)8s9DD H$D"uPT|>\.Ww|:aX[[Ã3H JX,֭[]ƍH&u麎BPZX,P(M`&rQT}0n޼EAJ%d2$  uu.zx<7oT*cur[[[d2 83Ml-C~P(D"P((JXYYizڹ/J sN>lϋav02mvNA [t({3ͥ;vuΏ^;/B`""&x<4!24MC"h v"4Mi]T*^0 jg:k0 2,4M|ǰlee%8V4@Qj5(\.jàI/^ Lc&2$dYx<2Z $AQ(d2u\.OEQx2/C`<EPUyY[""""""o`:p6X$.G^enFϐԺoS-Z)g8y# WѠrיvprw^w֫lĂ`վmw5J`;m5޿V3O)McN> ۹Em4w?0[3ַp`CN( 'OZBD"ͪj6V)H$*ӡ D"uR4MaX^^·x<\.]ױ1+6P*YUաiǐ$ -mJ=:ΟA YTzVAr9<{,h !2RTvy][r9K_ynULZh`W %0k 89}fݶ}h{yi O#%1x}պ+">1C}0w·3hoԡL|=8:y}.y _o>ѷ_ʵZUu]]ox?h1R6j];~߭[zE!Z??L&xw `?i-mn~m}8o;}Je5yiU}_?(Jq,TPuxV="[""""""K@{ae`9SurwmD:! |>rSW sED-*d2P[[[VT*Cp^Aeat< ֭[ׯ_w<Ưljep<tžZn e^T{MZ_a$e~+NjgC?*m z W:cED-똟G6E*iAa/RtmINտYI|wY rX4{^Ǜ Iz˨˘Q_ 2|n:4Ngg&$ P7;sܥҷߵBSCDDϟH$*t],x%׿v,rH&Н=_>wccc(jb )</~疈4 (uwL;mi_ IDAT^j{?m>C[mlnp {ABVZ{Z^@IPTBAgYK7:J;9>yOnD_e3YǺy<~sKDDDDDDt1mDsi Cڷ;sRl:Ho;톪Ahl޿&cZ{*z~oÇK=TnoozaP}rL&GޝUi׫$IPUK_ `?(tOUU!ILlgw0-ѷ0 L"@Br#| +eۿ?G%o۰[A7#'xօi{ֹ.hUi%RVs8Xsd\Jb6˽f""2 t[jx5OUUEQiLDRN$}|-ԋHxťUj/--"@Зȿ2LK2 EudDZk{y[""""""o s3.9ǿ{K! <(YϏ٦Ev"1";6ĝ#¹l4>Z-"=zdlk+|p[簁1]?,#ӧ0 iB`R,MTB6U?qb]Sd٠*X,UAehWuE7oPo qP,d I޼y0!IVWWFrRr?aaX]]e-ѷ0 l)۫p`H"` X-8`obI F7ha_YM; ⎈pn;p'PK*~A(ķ"]oߜ]/@vg]" [4ԵiKD +0MD,CQ7lW,T*z|iB4ȲPee຦iVZUX^zEd2h_V_5zXZZB"@<`|>Jl6i\jT\2疈[!ph] # (oGGp]Lv}y8sDDDDDDDD㋩ sAc`_ 玃?{|};σوDBVʂ^D>E BSN۰Y߉y""^| 0 aKRA<Ȳt>x\Çc׾oe}hؚ `<+~} [CLt gyY6W Q;\q[뾅?c|_{i0 ?{b 4M,u}a0}+~y8sDDDDDDDD0 MP=˭/s nB_{e噭-Dv#fNw"G^q(333jz󶷷399"""""""K%cqY*wn{vrrޟ= _S}QDi """"""""L;8~~zcϽv)Οda_NXjh?}`ù-ٍ mVm;..7[^űZؾm_9'!jdg;I7~`;`)ӎkN{ "W|'™s|5333xM>nKB\ߏ͚!N#H@$RBz>1ua((ǡ:RdY)]+<_~ EQp=$ d2$ ^Ej f-ɲ6/X[[kt]Ǔ'OPVd:dYiC>o skk ,޽{HRfe}vy9zL׫C\FTU"""""""0sޞ'iBkk߶L5wཏȂk kk6G}¾wօ31-ᣰ'gv^;m_pMZq`ht(]۝vNiݷN;mù`◉P!?A{RQՂeY$I-躟iq{0 2,4MPC`UUIk Yx</^Q IE(H&X^^zM]ב)MӐH$gF9;>I $=eYF2,-ywQL&l6(fPUCA|k~y/n,~>Z9;"mYNg _$"Z1j=NGÝvaߵo9ป9qc ԯnewfBp L`~> ۹Ewpg]XPՑlׇ'"^T~$amm->U 4MaX^^/ruKKKC gffX,buu%d2AEp\.EQ`|VmKDu\ښ[.WVm"N_ߓL;ѫ:ppC̃+T͡DDDt $o!ϯX=/9K4͎t ;-/<333T*]uj 4!IRpԿ^[n]]\.;vr2:׭J*w6SW ADD֭[*ׯ_w<ƯP:xo`gzme{o>aT࿧$IײbL&EQjJ>\8+tᚃK?5 2s>U+|JoV:ADDc%I wy4W8^9̵{WRE9˰}u}d4>똟G6E*i4 DP} Ӆ;(Bor\;o iwbKokʞ}""f&`ccBmxog-Lx70F;y3<<TUe/__׮DDDDDDDLί4ָ~< ngM{~!\s{M#_N. NDD4jRj^B)_rԧ5mqvU7vvoϫ޿CPÇQ &""""""1mK!vʾ ]v =l:~xN/BwyτLKo^EA@{DDDUW.xal`nk{JUU~߼d+dTװ7rf I`f}o3a2N>|?DDDDDDDMӥߊWXs6oUVluiaLy!kVVG}~SV[eI/$j_+h&""goo/s,gi=z ˗/*84^x1>mll4M$I,--O4d2vERKXjpߗaB:g1lg2lx<{9, N͗HRA{%G{Cl͆'S-bIٰ~``9j$"ZH;"YG8 | kl,U,p8w#¹l4>'UWѯyy|Ȃy臹G!5;""X]]ӧOSd٠ryy뾠R ?( |˱kkkea}}aa(*I?e@u\SeH1`[]]ŭ[( ޼yZRAXmsP,va,~YT*ruiBQ@VCP<}.>e\O>J '""""""1K#l8woY?xK# cƼ?9^9_;?4vAjf7~m)h}n%c |`k׽xG !}z;Bwߢ >)B $k XZZA224dYijVRV1??l6 UUa BJzEd2hEQ63$4Mh2 տesmm jCQRBwYCb4ο^R" }GXYnF};x=?;bs?Ùs[ [[[e\Ҙ`r&;[m,#foo3U|ќ9_"""""""""""!DP1oY@_wEt3?BDDDDDDDDDDD4, ȧSW]0􎈈`0ٍnpFÇ""""""":V] DDDDDDDDDDDDDD`*㟏q?8pm\C87py+e "PU/^`ii8w_<?9L;;;x5o!d9а874W}|O[ى )g5[Nȧķ"]qtDQi# ;7 .H˗0`FiJ%-dY$Icݷx<\.UUCN7N?15U,〜ȫ 6~hs |)}"Z.n~`ݷ'瞈:X,"89^qt3Vz1;]AOš/al߶C圓53 w CG w"Rm7]v?2TՖ{|[{_'O`ii xj|>h+  K˼?b0 _o노[Casxӱ{am8r0DlX,} gAcvXG0a+nrn;vv眄8@%`ڈLG%i}k;?z6;&~(zZ,2$Ijy PxEO$AQ(d2t]B0$$4Mkٗ8_5ӹa麎\.0`EiH$&^r`^F! c( ,TUb[;)2,4M:gvpw PS\.u@^Ze$IȲx~9ZYY ^4@QrVۻ.`EG+Gp\D7-w[Μa_@ t'`/ LV$tnfѷ`>;ºoG忧> {,z-_$IX[[>\0 h0_<G.XZZvJL&BIUUr9;cHOmm92s|4 +++AUpZ oUUmiEeܟDDDDDDtЅs'R-/_c9_>}㾏%/tCn~O)NUî%ö3?2N{/OzxYtߏ8 ~LDD4n`-[V?^NuooTӡϟQ,tWWW[j7v6/[׃|5Թl~_K̴ǃw FUݭjiB`F9ϋּlw9=oӇP{CRa?̻iT#?7|˘?""""""޸4]8ya;h1~8-HT/I佷rjca_;zШ)DD4 ޖ,1Bu$ ;  IDAT+ i=7ϑ$I-phn s<555U*ٶ t0A3m˜?""""""ś՝r{TዀnΜӲ(~[Sս8h4n5dEop-&""S~`++OOW{w`*-zoƥ_u޻9:]x^}-IR% NV4eQ/|qy˘?""""""; m.;Μㅾ'?j?SpV|'vTVT]6)^H(HgZ~eǥӲF {*A[766/B\i4-x&FE<=+-@?GGFlܴWooOo;w]w ﶷ3eIWo^սR-mUڭr{w۟Կf< :ם/BTjY_Rlx޿#""""") ]8egڹkw`տW8Z9iԝvCU _ 4+|߽1-= q.^A3Ѩ{JOIjk h^/aۿBgߠ:$ٲ/w9y_n9Lv G}T*Qð˘?1 '| n{Alc>w҅po , -ua?G:>~X 4G}~SVt8XsY,bWLDD4*j 2:"`ii%lQULk3?HRU%HXZZB2;(%IB:>SJznX~s\K%iu}dsL&qtaa:]xcêA_|VIǑNŋ_{u]><vQðQ.Kg ]8s9>NnihqWDVcXq`ߵ#¹l4>Z-c}u}# f_\I20&""RǏCQlmmլ>|@>o9vuun݂(x j$I ;-\VQTL&K4!2$I³gϐf!2fff.[,:>}l6TŎKKnӧO]^^r4 d-{* rt]iPPP(:Y2sXdYiX__j2oJLմa/vYwQ'],ti&O~gN^4/t=+af7 =i7+R~A({@|+Bdwօ/ EC]۹v/]E,--AU ^cqqLAQZ3u,#ZP(`ood,CUծa&4M,AW0⿧4J4rqq ՑkkkVu=fTBP$:1ØX^^F\F:F",TЕgU.#5ú_.eEݟDDDDDDtq.|w 1b=`=݌"v48z~w n:3 6ՓH$ć= 2[%"""""""09}ߝ-czo(}} ;tn:pDv" )cDDDDDDDD0#oѱI׫RDDDWDkDL'(7&6Dc,iwE`sEDDt躎l6 4a$I - `LDDDDDBUU!2Eij(];ш09}ߝ-czoLDDDDDDDDDDDDDtM0&"""""""""""""&]Q }ۆsĒد7,"Z[ҝt!|FG+Gpg]VbwŁߧCfc D><GJ;],UUdH$ IX,"Ϸvgϰ=g:' ˡV￿>ȸQ;.44M@}|INAX|`[t=m◉㟎9c7wڅqc=mۯL+wչG } t]йh6}ew 1Man3.DDDDDDDDԎ0 MP=˭/s nB_{e噭-Dv#fNw"G^q(333jh=K[x`RGC/e ߅[ٺU ۭ=GQD{+| L]HDDΦir0 `3qh?Y,Io9f=k}bI\3sv;D:[v5t]n&n#Yؾm~`ù-ٍ Y뇨Hqtg /މKAv?܀}׆BwLռ;ћ9(""͛7m, }x#JAe>bk 4Me,4MT*uZ9;"mYNxGY4 NO 8sV[E?iֹ5q`ZϋMǿCoiWMןvpr wڅ}XT  {P=?!n0 ܌"kOs@oݷBUFG#޲S^¶zRkH( 'OjXUURz(J-D+++H&H-5ݛH$0VTUmgϞן:dYF*j_:F2iX\\gqVAj=H$( LfYP(h@@&i i r0.x\ciiCt}I ]}պ+"B4BӕO^X̍Oe#%~%r4-WSOvf}$s~LDD4*[Bj1  B{{{Jt?bs5_ݼ?4~Z.{?πy4y|iBӴ`jsZxt`&""""""":/te4/Yܩ֝uq =y!tvtp޻˘}Wl CpMXa쇋z|otTiy=m{~ݩ{֝ƥZ4MH#Zn;_֭[g΋K@ӕѯµӒmf{ܮXK5wɳ/k ͅ/rP5F>\)r[觪*t]G"@<꾸v:KM츗y/_޽eat kOH2n =nj?d"2 E** >|г}DDDDDDDDּ4qaho i;8F}eQ7!Aq=h4nN19_\뀷9v 9}~%ͅ`9`?(m;-K_eccc={?|>|>D"T˲/_k׊d"""""""Aq`2L;m_D_g'yد1DzcvVm.NAFۺۼ7nsupTj Uzکx]zTյ$R TO|߼/P(`Im"hХnabp6m\ϒy=} s6_h%|2> X"}xFG4vmp> +Xޫ$AUն7/\o0A^<燝~%Y7A_Y͝0}QU$4͖y2 Lv >DDDDDDD42 o]6t ./Ē~ZT NBN.?49yAqdkl3zdyϺ#GAUielVzsǁjSZ-}:Z,ؚ7~+|p[q$""TTǏ( j> Ϸ[nAQyZ $յyVT*H&x% Àie$ٳgfe333]!.uO>E6 _bU<}# MӐL&2.~Geq)JrjJ\.]a&Ej5 24Mz0L',#ӧ)J0_&jN":hbe}˫u/pN2T.86ȧ;v)w4idY0A~+IP` ՑKX RZkkkVu=cTBP ///\.#N#H@VRѧffpU*{I At X,X,D7g<v1Ĺ㟎9DDDtyDPñkiح-Ȳy.LDDDDDDD/l_sxx8{蚉Be'ݱmsӁ3 aKDD4}-8OKDDDDDDD-cLt CXU)or%z""qD"Z"@&0^Ak"`LDDDDDDDk(iwE`sEDD4Nt]G6i0 $P{ fff}7662uBBe(4QP,=mTU$0 J%q∈\8DDDDDDDDDDDDDD#Mwێ9<<轹05`LDDDDDDDDDDDDDtM0o8q1빓.7a߶>8E !UN۰Y߉<"""J,C$Jx<\.UUCh 05T,if$\VYp?49> qqr-ϋ-тuB1Ng& ϟǮm+++4De0?""""""1&Ws nB_{J,Rh!Ad4Nȫ>e0m0 =X\5ApK7[jaquh9{ϊY{/A)ksNL;8~~zcϧ>Z9;"."~oadhrč5`[>wakز, 1º7W9  | !tM_%ѷQ:}7yo۰pn:fg5Fv&ĝtzƍ> ^ >i7~ ;ul"W|'™s9@#Uk('O`ii xj|L  B4 tD$0 J% qd2 Yz{{{((JC;offȲ 4RԷYa" ~wHˠfff}R0 =oggZydYƽ{Jf1Ÿ 2]/ ˡR,O}gυdٖdYnnXZZx j=Q>oYoEZmWVVz?333u{:rb2y9ȸ\A"""""ٻ6mO \KF6tYJn)&Lآ5ߒ4kw&-IF3 &Q!,u)|w0I㺜K,AS;Qppұ.wE^?O W9׿tdqB3!x7Z^~d_y;qLvqnL&4* ,(FNQ.qxxtؓ4̀! IDATT a`qqekD8˲kk6D"Ii !0Aׯ 8.NCUU(ri/&E UUkkk_~JFHRuC~=0 6^XX.k4]k}Q%✪"AUա :2LԶ1N#ׯ^?h1I%Y%޴vnYඓ֙wPTrP>p1\ #\;3H0=Bu"3Qsnb'/A}ĉ;g3x3NzRSw+VAk`'}n_T\{S^ۏ vB!i ?'Q+*j+D5u ÀiX]] ~DNH$պkqDQϟׅ)[~T*X__GPh:& !7zxX eayy9hX[[kۗKDV(fIT3^FTAvj0AHRX__*#H%ɮ*ϸ uT4DQX5pݳY4lnn4ͮk={ `qqَC|uN&AEׯ^?f`bB7*뼞9>TjT`Rޗ!^. *FA{Ay<v,jۖ>Ko?%!YDDtsT*5&K~!+kC޲,,˪[U)Mtm~vc ޫ%ڷ^׾r|>ZK?D .?[58Rn9J)E.V\XD4m6֯T*EQP*QqrDDDDDDt30# O.~%^k ^*9{ {=t{Z]/Iۅ鍁n~8i8wckXޗ*zt"(Lmp(^ 0jEnX||MO!h]ÇmVZ2tAˊv9AǡUl\eYP|wAߪSp9R4яGu|%4*q\a?/퇂}-9'hmC"^Cõ*6%xӞ_DDt5o۷o[GkH&FA\FT‡. ]=D"MD.ݿ-j{_!%F-+Y18hiP-u k]ס*Ljh:hbQ_::>f`Lmz'}0: wޅ;WJo;jU(|to սg۵St[\넏 נJM:t _TT*i"Ͷ\81p蚦^,ܪv/h(w:0`q<(xӒìFz_snDCįp\\8oCu 'nNuY!hvɿ˭6u5!"K[[[}Uyttl6l6 MӂJMUUehi/_n4MfuZ-{]K.|f<Y btX HJ%Xʸٟ6H?DDDDDD=z{`>~ƝK9`!#[m&=>{N:;$ v@.O@vvq%*)_!rEQZv2>zٖ>W.T*RTg*R4@:JzTy?h<15GKi:J v:Mo q9ŗ3x]UK 4}?^Zs+zO tE|YLDDWX: Ueq*`,nU#Bh42uv0ǯUEQ`Y֥v{{-s"@0yOv[g"u^}ކA"""""" fN*T{u6)u;A)Z/JuOm36J ut4};q<=˂f""* kkkMaK$A<ׯM&MA@*8uah$JP*0Ku3 Dbҏ#J%J]߬t!,˂(~ObH&u}"6 @pqiF0 e}=L<A{H&uag2t?孭-XX,4GX·A}ޔA""""""0XrAc8pq8SۛE+}pчDDtlll@UUMUht:/^Jp "Nn7d7-յ9CC+bx<MӠ*,rDj|>˲GѠݞd2D"UUDP.pxxX,UUz90Fa&/ ~aqqtCUUU#*.QD)R;2DЧB\uyy+++uҊAƽ". #yOeY0 n V*,..bee!,`\.cqqT # 4Mr߽o DDDDDDt3H<{.{ sUtgl~l~j#Fhx3&(= Dǰ64-{ ; ;;;PU7fi[1ΖeOcjfճun]1GnS]ұQcs.yDDD_,Dw U"""""""Z F*95w΅0{Nmc{S_쉈[ZZiuid2 mi`""""""" q NNX+䱬^ }=u}""C"@*eY0MJ!`vv6_xkknd"""""""N- { d|􈈈\.]ס*(, !ˣ+Omȿː>K<"1ii4R*IUU(ŽD"i躎'OC8DDDDDDD`H傌_'nUۼ܊0{~Em]w'\>J4>p>p.cIޕah~dc'8xDDc(HG.?(ǽqK_6>dtRno HRA<Hd2PTpxxbB"""""")7zΛiԽ}sÁԆt,A:λޫbɖ^wq6sF}nIbg \Xj{֝w1d}׵<}}՟tN~v '/z]"X;ȡPX:ܛMy-i?/|?~~ZU*? EQ^vEёoi4MT*06J$Hqha@Ӵ% ,3MPX X a])0 "htrCk_}/}sy:2 E gYTUE:F$iL꺎T*:{gkbڊ N;|a0mN&8J:[Kׯ1 hSߤ ~oCx;\e6oA;,soƃiY+*|y?`UTܺX_ɯfݫ_֝sQU\ vŚsq6θA+d+TvP܊wzAsRSwbh?z|}Ij}ޔ/؏춁zq_|oCODDQT*߾} EQ>X]כmii a4Md$A:F" VWW[N &TUBSpUTBPWi2 bxKTL&Tۖ S`u_j4 0Mj X__ dPJ*i׽γxxhiMsTDDDDDDD䃮w_~9t\cQq?smi;?4lT } AuWj8Om<~k>>pq7=𙈈H$TֆAHfYXUs\۪TMRwA:ĸ׍{\"m5"T-KrJ%701_r9z\!""""""tޱA87&|>{Z=W3 {侎{/znU<N|床n ;6.,RQDlO`YajG9hCLU(wyDjuT_Feu~)˰, %=zVc0ZC\Vk!^/h[P+}8NmEop>gDD*1l'lU)(.:Q |p5GݾaUKkwN:WٗvmEFǛ\u<JHRXXXa=l6;VDDDDDDt;1[ϝs7&\׭/gC^^AණׄrMoku]%=}u*έ+SӴ |eݞ7}7_jCH$2v.%"4bX0bIVK<Җ*A#dYdYhT5|wm+{ӭ' 텚k?XQ .eA3<"?l$ Seg ]u_DmH,&ߘyE)*iG9A,H${nenڢ:EeYuy?J0[O} yS?T/t/ Cի;8+?TRgށI{60W:G@K 9_ĝ;߼)o/ wubnCXEQz D5aQJ[[[H$x<ׯ_=P^wuX^u_Dhsekk e!aeeid29VbtݸD"1ujY4Fa,BTx\,H$%<$IyzX׆DDDDDDD=֓e8?]>e}oƃ;^)p KKCx5OU8pfk+7o2.d?7,>K2߄?SsR.wN0nDDtŋxRTPavyBgϞ!bgg'l{766* &L ¹aWheJ%b1RU˗HRPUCO*wH$J>o&=::*2 DuEX8.0 X 888\Ө2^ IDATϭ X,v7sTB:F"eYFr="Nŋ-) OF0}&!.Чw* '~z/f׽?eH~t,AMYתw 9=տVwMy]-<Xvw2}c}?@y%BpWv q_"[HF"(eXYYA(*"84M, (ұðd2D"UUDP.pxxX,UUzWKv*wfaY è+킹rER)躎H$H$4*Ha^ڧKKK0 hib}}}p . ]]kccrD"hcP@.k [[[CaLDDDDDru"², cwww,Qu(4Q(#""""""jCݻwDDDDDDDDDDDDDD#W?{;gM9==`LDDDDDDDDDDDDDtK0&"""""""""""""%&w䂌_'.=Λ }Ʈ=_2_0/}U8ɟ'4߻l? #\G]]בL&iEydٶ$Ii￿{{{M|c/HJr珈&aCCιVұmxS6.tc8텺O!B0 wy,y""4M4M}XJ"@U dWHtɓ'$=DDDDDDD7`ptW+x3ù4$짶q }i}}{㍴:Wޕah~dc'8% +~Y4qtt3 >QUDb!m~nGDDDDDDt1 UQיwvi<~ _}-*`""rrq\B:oq¾߻[~W ˻=aJ%?Xֲ,vQXL}sg\:kzZE%‰ׇތӺ]9X˫/fIs;;~)g?~d՗ e6 3H'""jTT*v߾} EQ>X]כmii a4M_=NH$ՁUi܄i=W7?{ `qq1_MbRTBPjL&X,x<^J%@,C$i:j?}xhiMmAug~!""""""dnD=sE+s6 8 yC!= A{˘>S 6/۾/嚪fAnmElUwXKĒre[-Oo`L7c~Rk%gZ-C=('o $i6x"l=i8wc?kXޗ*z!+eŦ *{ATj{hmN>|"D%V!VV>Q7 -_h4O!`YbyYTqP~mh⊥iWNkwUKiϯMMs~8۷o[G]?nC~wEuD!@QǔJ%Xմ tύճ^ڗL&FrR>tƃ ^?YX,{wS}ۏl}yoN%;<pa?Go @.]C{~<qxx˲( xljM ø4HT*5UhF"q~zm!@u^׮bao"nug2D<o+aGDDDDDDDt p`hÉ;b>J2> . ys+pp *a7K~jaE+}pwux/^@* *DWWW[. ܳgF,dٺnll@UUMΣ`H$Mm-GR.Q*ŰMUU(/_"JAUUζgre!JRP:*4^xZB!j/>DDDDDDD=t&~N\?_7/\[[k0B:.yOFU=YRy׉9؋};ܱm !+oᮮczDDtOO"RmXYYAH*"84M, (m+;faY èk[c07~weyydD"\.#X BsXD"~|>˲DQXRvaKuGݻwD#`?a?#n4߹ ?OܞtwDfcLDDDDDDDDDDDDcjfճunX]ұ ot\.B{!DDDDDDDDDDDD7&e7!Fh !"""""""""""]ЧSWޗ}MR?"""""""""""""[DDDDDDDDDDDDDDD`"""""""""""""[0-i=}yۧp+iߗ=3y?Ta/#?""QD"]۷ۃ촯h܇uuk{2޾}q """""+gA(A('V9 BSw`S9gНaH6)GDD7F$ 677w>q """""5ӵewV9 [w_ G=ұ%\TW#Εwe` nUUH$w>#aYLǁT]@4~9G_gށc 2"/Bx4a p- A$""".vwwDDDDDDtXzI4D+.w~Qy+A 3xtKAK%{p:@"""""""""""k ` _wa9OZޔp<Sڙw`?JƉGWwtnh|]iW;GLD>G.?(ǽqd20 I&H(JX^^sb/ Ls* Q,Q(?n"""""{ i`g?Q}jpMy8,<{{6.&_M=1c G =?Lvyr!{߅?ޱ=wE^9tdq`h硃L("cٛMy-i?/SK_~_R(L"J4M "JAu,//7c}"q(bb0 .H}F5vt]4MDQMӰ6TH$H]OL&4* ,hЯtrM\S#J0Kw}2h*ׯ_#*bTUm:_|gvvPU mt:qOa ՚r9u.[ZZa0M"4VVVՌ e3(źm^ gWo>z]%ɠ"xXϻ/]ױS:~xX eayy9~IP.Uukh4 ˲چ~NqDQϟ7QT;&44'/U~ Zbg_BYޗ/{ZNU,!녎CA*v,kQe}rTyj)}_=𙈈RnJXR A05.S{tt|>jRqO,R5XCQYqf,nܯm{1FM~ZlγT*EQP*f\.wr><\O̳9Q.Ɓv[UP>'y|--esh0yS^2g&pWR~-Iޗt $i6]' nw-e~asWDDDԠUW\eYP%>|> CB,y:;;S9YA%~}6]>](=ޯm{1,JmyI:O>"HW:0U/ {o] Z+UV[=Iiϯ\4ěn⊥۶s|A^CܮOi>DDԻV~( TUm|]בH$i"Pl6 rW:o;7o߶|qŰy]/=g>oqǯ 0vsȲ{ػ0 u4KǨωA|>d2h4eJ%|9DDDDDDtSDP.l dW~v[=i?'55iwƪ~ u烈z)KA!&""""0 DޕS;?,u IOCKOp~ֹH7Q IDAT~dS+My|}Om3>>KAX>.hW:q.MAT,_4]&!L?G",--hRcuIT)r-eѾ^T*lmm֚*"8^~Վ{/]g-XX,07Z51t<3 DbdcsT.a&( ÀeY(JCK&MD &P1 wޅ/g~%_*B`yOȆw×} CBuzas.{^_B{!uh/GNN.BKXBx{|(}y@ޓC pP]hKMl}S~(r'b J%i$ Xh4 888@.{o\FTB,LӄeYPU˗HRPUmH$xRTPՖ绪JaPUa`ss3(#]J&{/]W#" H H4]W/^4P]X,MsLӨ `/b̽|N t:/^o(H$F0MB\e@d2D"UUDP.pxxX,UUz0"²,UUFzbx<MӠ*,r:w9c2J:""LD.k &l{Ue(ӥ%XܣPiP(`ccGDDDDD4B޽ """""""""""""?7f?_=kzi_DDDDDDDDDDDDDD`"""""""""""""[0-_2_p} 3y?Tq} w۶ 6NOa&44O)ٴsR/\iq 6ʴf{3)/f(krisirjҦ`!- EʵCq37wfZ΄ 3#y#/zB0s}]"ԗe3ꦞ'"""DQa ˚`& saL0U ߋ^K62(G`L37'#FH$`3foqƗIžO;ޝ+K(`c0JQih  ŽV9eT妇Cp7ȷNxl|i2 ؇}-|{E~idYKPZh4L&D"_V62JsssfEƆU,//ek||t"zsX.Q,}5znOܩT X ,y!""""""0#/vg rG89=Ž{̆urαxqπ2O?iLXf!u:oϚp=F}An[%CUU4M(fPU (`1m8>0ipyq{gþ}ri#44S&"/#va{G'm niLD RvƳ,`0Nn9ݿŸo /N^=fCx/ .u'""V*B2x18!b[!2fggs r84MãG UUER V6L&Ym=bY__7aeevc5>>bKKKsg2#׭N277UUiGQr9iK DDDDDDDt=0١)gˈ/(6%H'm v!h#VBN G#/}wA}!'z.p_nf7-3GŽf7|&""$wiޥ%_8VVQ,:G<eukޭV^8뾧*w~Y }9sZm,[<ȲJB Yh4}ξVP(@u߲DDDDDDDDg1#N{/qiОҦ\Bұl۪?k#l?s ۺ&""DQ/,7?jJV]9=`;{Cezn:y\_v֥~ϭ^"""""""4u >Tl+wLHW'}ـ]9>#gc-Be9 D=Zô:뵾cVQajY6^XD&A<ǫWPVQTݻ>4XQ[nyދ/~fFGԈ(`pa6O]-}aAw3ݽ Nq_usNDDv wlkWW0;;l6i UU8asPhد<ƺϧ,ޟ[,ԵVwۉV&T{}۶_WOt.!""7 [hu/.  b4E">ЎJ!p'ǘL]1to>; >Yڞl>u{}7k{m˫{Xo?Rs{3u]9]_3֎:}{-׉mޒnGeVZ慤av潛C&""""""AB`֔5m69ea k춺7VH]sLVyt;tbeD"t:GQR)<8(r֔뎅oQU*I ŷ"9ih)^zHe  ]FVڐ`ݶ`&a^= m8кsn`LDDԫud2lmmAe(bxii nB<J+d2e=4MC4,XZZB.k:nRA.C:^xݟ(rx 4M WVí'OfbXnt[],,, #N#N{( dY 𻽿^SPbee%palaH= #/#\[~{҆'@Z0pe#/#6iC{Y8Y>g6ķ"C# ,l9q_"":O?*4Mѥ%,--}Z0^4>}fggQT:(1;;Rre~84M*?~ܰt/"VWWQT(*JW((xLta{N_9R@|z0^qSF $"""ܥu]g1]zv#,&`V Gl 鞵ž$v aOڸG}ք7ED^F\>uBfwdi]msaذ'c;oR |v{̩yׄrB ^쨛Wz#`MY@'"84TUMP.Q,QFHӘ(1bi'{r[ש*RbdYi(JX[[ F:3 wZ ((J}onnl(𽶺^{8>Sb1d2b1NGRϟ?G2ӧOC;??t:Zn=GPVdN( t]6 Bv筭-|-桗gox$8TUjY_RԲcyVu{]L&\.J[֚`꙰sb;&:FOγ'=fØ1`nUG_y{ړ6I φTM3W=iÚpZ KKK(J H&HR s<=QV/?$b1q4DDDDDD4XLZBT|+b軡p5:qֿ)!B |ߊwOTrwv/ o)i)'pw/,uz[-'?ș#vx=_G|5l=gDDqfeJȺGݰjkkk{\XB!tOh4uև0/rԭV ہtwPrwwb@cdV=ۯy Nwnn<\5ruu7>sTf]DDDDDDtӅN~~xZdxړvx`7>5ㆻnt۩Puh t[nmSڔ|p涮74pæv{x̹{nmm.MML&vgurǹuVam/] zO=wsCfsk*Jgut"2yнc;Hᾇ.sg^r:\;Ö,:]9o.[yoߣq]W=W[as! Gm}5&zkR^~xv79k{{;0 uw/u=:bL IDAT&x/ݺy8/X >}۫=r\.o9""""""=ܹrǵ҆[]Y|+fnsR`ozBIm˫eX6rz{'KPռl+hNh}gwi߳=Qr Nloocmm <}i9u^J%2ϕJ%0P ҭ~KRC[gnۅv7cB}ㆄa`=wdsla ,ۍǹ27 ,]]_s8BOcmu /4v;) O== ȱ^σ7""ܥwSTǸ{LʲD"Kw﹡E<z :W5&I_(֫1^;ݝWmynpw-j,,ؽ pZ-,Hv.nOK=i7(d'"""""0=xi{ק]KsʄqƗ/L5o09/酥kξē6/|N2}1mx^ߧu͓=b; xsՊ۱,h&"muuʜo"TUE&Vռb~~% vwwQTǚ jwņh4T*ϟ7dJ+Hxc{2_?ao}poSRXXX@>G:F:iu@jii nB<-Ȳu-Z(UUH$i7NT \^^(PU+++5֏DQr9^XD:Ɠ'Ofnbطn^UU躎x<T*M[1y 'O~aaLEyVT*H&X\\lx.>}l6 EQ0>>KuPT*?G<ǫW߽{B=Q*=2J&"""""D$D"̂w{g _  f#RAD _6`¿  n(Lli҆5eABkj%m9׸iz⿋0O ,5/'9sg's6DD &x {I/m{Gj+ &,MoŶc""vwwQ*p DQDQȲ M9:::7crrˁcj5J%?M+>+\.FP/1G=?]qxxY^gG {'O> /i|'I?M+EQnՖK+w;X,jmoxAW榛DLužѰebMX,"_""""+&N4]\s;RU  ~*b .1Dא^ii mJ&犈G<ͽ.DDDDDDDR",4 R , %:v,GW@DDDDDtpM"""""""""""""k05`L}c7ps8rqm?<X}ژ68DD$H駟 7=&`cc/^RJ|>2_4凛$"""""":"{Ć1ccW7~5aTM"}Ř6`&1'ߋ^K6,G`L37'hbA4DWQ4E.C"X֓hSžao=fT͎8?c騍ncq,(`ݱ`ݱ`k#Rܯ3i]㞁 q(N" BMӰ"uyޟ(HIDDDDDDtnSrd!]ք ;B[ݿ酿C!ט6`Kqo0Ko$3Nqh||PV;:n}},`\zy!""""""{ѹs\M{K7naiݿs5f7v]HD4@DDDDDDDDD]`&gaGaOڸ}ք7ED^F9fcvҺ[㎾:5e5^ϸo1 1=;=ܟyׄr[vS&铚=gcw\O `5om͟Uh{Ć=܏?<#8-8kʂ5ee~e||}>%766|?omm/OUUyhYj5b1>%UUE*B,,4 R kkk 竿OwRxyyy`uFd2H$PPհrRx\L&\.=R si=xx~)b2 bS}ii9C6(JAud2HPX,bmm ?dYTƛG:ƣGPV}c뺎m |6V*<~{իWP~)f3Գ-Y giu2UƌlOڰ,Oca_8' cտ'N߅\I)U3ez`O0S&; ٻS& s=?Phkf7X>ͻ&1(;3pr#vCs]EV֖(e>[W*0== UUB_{MAQdY*cee,{{*Ł:ϟ?it](PUX,tN uv>tS^tst:\.]g<y:5M ۺ<dKerσ,+d2 EQzgXPU54%3 ٬w xlD?K/疈,3׼mxḣcoO,叜S~ak7GZww{)3kmveO>BU3e"2kg|{ZY|ǰ,{~;A{φu6`O:C!_jMX[Lm_hk_nfw /N^ o1{y">Qڽ~""jV:0_xY>Dk8LP@,C:FZB9qT*5777UUi rHӘoteR B ~~KR4 =oX URL7ճܟ+ӧ^Pޟ({ ]嚦6.T dqCezǻԏzVU/|M$ Sb8t] W, h j3LCu%"""""": ]V䄩v~|D܎z^o}lŷ:NXyGlo=n!`߹{_7$ߊ ]{lt>^=ɿGΜ>{fkvg""j׿F4E,C6AW4u UU}Ӏ /u^ұjr{{{KOkqq,cuu!\붞RB]Ew7[uq[ZZWVxxܞ}Ϟۑ[ UP?_jg8ze.  .>dsv꠵ 6%_'w=l!]~^w>w;`?s7ln뚈RdYF>G>]`ba]Vyr;έ[.,<(T*UHA}ۺDQ/@ 3Þ~CR7~uкpX@6jCeo?^y>DDDDDDt}p hPA]ny{鞱SԳyt.* Gm;!=f0x 㞳 o!nN7{qKӀ֏"Td2.uD"1b1t[np^x7mxݻwloov&X," իWVT*xݹtLƷn?y>g~ l~e ysUU' (MӚ^ŚAe(K=/sKDDDDDD `γ$4`NͺāX䎞mq / üo¼kškD4a|Qդ{W uuջyh$".ժ ˲oϭ[/lA,]0;;l6i̚P( pB\.Y7l^ycۺ{Џ}~X,"#J5, ݬ{r{E~naLԂF1c,,|%*uҺ՞;C `ݱ`N1/BPpBZtv4͌6X,慕ll` *EP@P@,C"@:(X\\g}حh4-Ӧ].3DC\F.C2D4EVnŏf/|]x-]Ok5aN(%[aຯ q$zd{Qϝ[ºnޡy|ź}<jѹ8VJ%({8wiس:=_7xK{iebm<*9e90tXVyݳnw,˨T*-հݚ5w=sKDDDDDDS 7| v8wgS5_zIռқXֶVS&=a]=f,|ح}Pŷb_!f""8ndXuV.(T*X__GPiPUTrL&C nD"qu ۋz#Lbkk BE=/pBY&ۺj5/|t;[=g=wt:ըjH$ 2t]u~n\ {Yx0wX'm:Kۓ&7] qƌuc/p;m룆qi!P5onƘ1'ḿ͝Ajgi/ht) nk6sHCcy'"󷽽 ]!r`[OUUi躎N957Z ņh4T*ϟ^ER@d2HR Y"f3t[ϋx^zv3V/uqr0z֫V4 xBuL2D&dnn@Գ[""""""">P/#04`|iL޾CφT`fXRIBqE8ك.Pcƀ:!#xf 2}s, }7묶l3=#n6KHe٣ iuIΞ 0v E4}: jz ]NKKKx p柗gl =0q߀1c 2|_p) CKIMDDDԎX,u>x࣯կ~^(DDDDDD4026+sppչLKWuž^ŗ5a.2DDDDJ$}v^""""""0Q 4.3엡!CRt)DDDt!^bd2>31&""""" &:=v.i]M+mJ&犈.t:l6 ]סidY G<}g""""""ˆ0Qm =E nE!"""Kimm D CulmmX,b}}I",4 R |PpMVhٿadlWg7ࠫss-["""""""""""""k05`L}c7pCqm?<X}Φ̘68DDRTF,fd/^,} IDATWЏ睈r1,MXw,c6{""/#>-a7`8ceבwn`& bL0Uӹ7{k Ҧ4_Z̔ cƀFT5$"UTRQȲh\D<`AY爈.?'ᦰw99㯎ѓkqaNlq,sR?硪jG+t: MX>Euh]|zqމ.Կh ksݥݐTAwnp[aGhל2w(?uӆ~i@! fyc>a0%uNDDDDDDD{GoNhuc`(m^J؜2aMY?޹$̕޴t-{#ߊ5qSF;g/|? ;n,hy=bøg @aGF!g&̻{ {ځ솄{ƌaO@uex0oξ@tn֍^!U {ҩ?<#8-}Cc6n< 3̡'@Q7F5e2?DDW8TUE"(Pc{{RsssfEƆU,//CUUR)b1Ȳ MP*Zx<4=zjL&t:B[BŋOŐdjKKKKvS^r}[[[/BH&xi5 yV4E&j Z ((J Ǽz O?4,Ei:\?;X,bmm ?dYT_揈*cL=s8{'0?dY{҆1φ}X0W 85g\qCu1l [7ۏeݶ`Lo/f{҆5ex_bm-؇\yׄ8&e'pNrӸg^sftB`󮇈t:텏akk ,#L"LBUU>p{}_=R5MiPlbvvi8'˲~ע( $E 4r7^<buS^tl3޵ryϽ4 CQoLl֫q<G6E"Ǐ[{/ϵ;dr9(Y2DDDDDDDW`k6qp1ƴ{Gk 5f3o8֔vBaOcoc07̆w=)zaLD=݋p?=fükvH{[[[{̆^ΗD^;S u.Rܣ={DDtj5,--T*X,|>d2T*՗NJcVVViZˮEUUaaa\.t:y,,,?,˘T*r9_8VVV( M={ }D-_TdhdY֖NNR)qhG5 dY,--ammͻN7d2 }t{yS$t]Ǐ#""""""ЅpCDu*@wg|_Xڔ=9~9^Zp xxCφ}8}#Z:veߗq>/DH%ɻfs! ݟș#coE/uq0MDDt5ammu{{uC^h4uևr UUFCkJ vwwQ,]zj52(sloj5aKϟN/.Jϵ[%_]ժw 揈*bLBC³u'm99lH% CYY8 {۩,Km-xr IB|6m?s]m9: ۺ&""޽{4Ĺ(Άj J%0AӺK1_znPg_ ;֭[]AWV:dY(_z q8a/mG~ HgyQ?vP9l=tF""4bh,ӷղ]W9;onVV5e"LA|/":_݀s?V{ZcV{x;=b7.,>i]ELMoܰ/,k GKH*y\o|u7gn/2371p5o8}%pr VAϻy߆[`]nN0^͂f""Z-cn0vvݖ턡rd24л..@pew޵|OPݠ[u>n"nvw{#""""""S1m4}q߀1m4m ;i'xJξƗ/5o09cJRxT 1 fYz#Ϙ1I}s`&|ֺcutfݟ1mx^ߟuǂqGlomw[q;DDtW"@"^FG2:tTU0eT{kVWW hT ϟ?.Aѱn؛Np/hߋL&T*\% zCܳ$2bq 硗㺙Nurt:=#""""""0zK :O4z6aΘ04OcoI Ҧx~k‚=iّ9.Rn| ]֔ mc* mW\7^< aVR<0+N$:D$Y:כhVӉ7c-܋'A]\v$xa&lEw0 UE*%R鯝.7QT:Ω298D6w; [3og]wl-` xh<s~rS\,.!^x]`rR huJBQD*_|ʫPUamm뫢(|UlVPJ%i$q d|~nmnnB4DQaggNj^1DDDDDDD@ \0N|'?S@?;?P ؀VJB/rNPqSe?s_  vOq[VH{ [gīsּ?q$iRQr弇W7i:x@uv̿1I v`Z0o߈'h|8>>PUW\A\ޙ[E3~>mg&,  > }޽{2)T,;Ȳ{{{t__# \.__;K"g}~)677M?i|gq[;ZptnU[??R`nn//X__jo`ii # ann#&1>?C/u:~׵u977j\.\.T*xY_揈hߤ11S@O;M1 g pRiz*#M 3n0lx5c6&vN95o! '"""/^@UU,,,p B^;w""""""~q~lIDƭ泙lj5knNDDDDk&ډL' :lON~&"""ܻw* L&8gT ywbO[3-ۜ+"""OM"@*BRPpOMDDDDDD`^.C$èT*A>&DDDDDDDW2DDDDDDDDDDDDDD,[/_4g `"""""""""""""K `"""""""""""""K `"""""""""""""K"P/6< P|K˸mk@peP40of-`yM*H> 4Ǚcs6 mԾLL|;x>3`|m\uMD4^{677OD2D:ˡDL& ( #~s!2~O"""""lD|#ž%)w֬R >L[b_#fLg߉^I=%}H0&'QJ%Ȳ PUK J(2@uS%24"ܹEyg?.0&'Mx>ּuy{$_55xTqpB:{ `ݰ`ݰ`?Z+mJ06`2m7>Q=xs&i 'R@uD"TUE"x;IDDDDD4&f)w `um:[aOל7om`b%`uXLDDgC{ffP. 8DDDDDDDt6! O8|c_wuq˩6{819 '?7M.N"" rR0DDDDDDDtFš`[[f;ծΙض8s {ƕ8g6a:N"3@ϐH W==w6]sqwaO+gO?i 'O>TC 5'm 3r1rټnv=nU:wPI37a\aOp[t<<>=̃yӄ8Ůyגf-{h@4D" UUQTBж" L& 8+++gneL&H$*t]G>G.Ï?EQ0??߲7UjL&|}~)# AQ躎B\.j9j{8cfff˦rvZe$ b1 ^LϚE$ oĝl6~,..BeedYZrr={!J5jӼcuu/7޷{LWkj8_z̈́qlXjs5L|;2w퉗$t3Nt}_&";g m}WknN'm|{=gØ3`ݰ0xh]`ͮx-IJ @Eql{چ=ilӸe|O3n:qn$;^hu;;;Phh5/t: ]ס:04MC(BΓ'OFk/NCUU(263ݸT*Můpt:j-7c>Me&-[{{𾱲8s {F`#аqv95 z15}S5oxc،]̓;::x_g  O}ܸe Dg;)g ZbeeB! dFViz?7 amm wTwzg_333^7ceeaɤWlJaQvpаUOwf=ᦸNkgc<wK~ЏxcHQJ%d٦D}.kY;\.V[#__Î ѸaoQ~HОdkuvnΞ3d>k{pA7~Vn9mԯV6M@uzm/0#Øu3w_>G2D8Ƌ/P.Q*ۮݸ=w{1&i$jy2C=vVIa[5TP `?wLJ-yXWi\N7ǝVzm&"YDŽg}⥗DOWo4A7Qdθ%;?ܱ5J y?K9ynnVXXX@*B,i̺#ua>w{1&iY㙼O3 IDAT gȺ~I;oa&EⰃqt$Vێ_7kuMymu\=uv;DD4ΏKY^hd- BSu+U=[ݙ~緟upCV?egZݜy=E.Ý;w-Oe ;.DDDDDDY 9[ZV&>͛:߰oyJ9o3 IAמ; ^߈])n8QoܪmC/9b]&Z%W[}V/bIvKJü{V(D"mH+Vq?tR]xx®ouއ""""" `bvW֙=7g]W5X7>$7iSw /8IOS3;;;K׈cwa|_ [ vS%=gümn֛sw}͸ٰf}FZ3~KAnYf""{&ig~&Z"HCEe,..zU{*_T3EۇJh4Ŧ瑦i^G9d2x<ԿH$>zQF:M?B_|0^xU}l{_\FTB42t]GRP=B*94 hkkkف(PU|mr5#LBQ|Ce(kz~BUUh5MA[YYÇCR)oiiitڵkxeC<5j;aஏscw 8 ǥ%d2$ $J{|"NÇ-BbM;(~g?BDDDDDt1L}5݄S{l3n; 9{~T^ aݰu bQ_~Us*lŏ L]x/81exá RGF_ gV%dhK =㚁ؕ^Isfm; dwߋ|mkY H$ҶB}_2D"er\FPUHo ޽{4 pceejZ 2vwwJ2pubxPR`ggrw1 $7Q(Hj՛ 7nL:I~fT*4a:Iu:%JD 2dYr^(K>GRWRqysO?"""""L`իW $Y\ 2$m](ǏaOۘv7'-3sDDi B^;wO"""""""":/ӳ?n#_R6gȺgp^ ζg=1k nLQ[y~E'0}2jm܎ښ`2lQ&NۓSwBPkPdZn ~01A S3aMlwTX9?SWږm9R* t](9|RO""""""""$ @`m? /%d L: ~?7ϕ+W077óg'uM?T?~0|}W2DDDDDDDDDDDDDD,[/_4g `"""""""""""""K `"""""""""""""K `"""""""""""""K `QF6p9>Ǐqqkbqb^7{W3|3""8dF$'O?bkk [[[X\\|!#""""1L=n7'}TဉQ2:W=j_`jNű'SuÂuÂF8Nj)ڀq@ANH$|l* t]P=UUH$|%=˾^볗uMQϳ\1"""""/b`B:5$n=_sLЫ5bڀ-B<.k ]8}UDD \.wu&677e_/D4:y3KJ;ۺٸT K=oNJyXm̛&'|sT* qKDDDDDt)Fhž+KW:ޜ7a2` l] jxfp @*H 0\{m[f̄5kSΖŶէǙcs6|u9[k"Uǚͮs}'m'0}U'8 - ).aO;q1o0x"`[ζEODĎw]ѵ!# AQ躎B\.j˗/>=?n+ͭ/<ϟ?G8P(d2P(ZYYiEeݻwT5UU>g}}e|pDX zsV`YL&D*vwwQ,Q(.{Y/~H$>2$TUER.l_6}TUX,T*UUϼhA} B]nC/[n["dYF\F6 \\ndwD"MӼĥ(m"@5\?#EHKktŰid2-k\w1""""t1L##}L Np @`05 NL"|{%%3kijV 3n4 kBmvu~Y-qܤ6QRM,vM3Ȟ[i2>ӝ]X333X[[(ޙ}byy/@3 4M|Q^JiXV*EixVg"@:iBPS?zk9>YɓEA8F8F4R_RߞT*PUջ__^z ('O zs*(TUٖdTk'#J!MH$${(FF4 (* >|V\^u>}vDDtB!>ݙ,{kIrܽ~Q;><ƅe;__be/xV"۸[eݎ?'Ar~mժVt`}}QC?~a+JMwQ_*((JMz?gݻsJÚ(u29FDDDDt1vҕ%/)Y-=i{I> @vKk[w >SKZN?ij|w:{'gwo:M6w'""K;;;-+U3o.^wZmna933s!=R+wpm۸ڵkcD\'Do7\.R@QoLx-9gy(8ͽ2s+OEܩb8g7'˲VtU8us?nMR l"'ܮڸudE~i&NmYv5ϟSS9z/۝X?fUU[&ѺK>G2D8Ƌ/P.Q*ۡ%Kwr}cPe?#BdY9Я焟y~g:|XW~t f5TT=&.w#"""" `Tl Y7.*) cRq I^kڵ獿1 Nrݭ4k]lk^[\DD]۽~(ʹIqKJrQ+؞pr+H5j HRb4%]בfG^qׯ߳{;jڐ@m<~?0篾Aat{ۍm8٘KUm&b?$M /mZ%n;z]+LDDoR %bDEZ:`yylYɓ{ww;p ?_cUUyolHdd2x<ޔD"^>Y9 KѨ/wxc_X&,cqqѫ;+w}vsݨj󷾾Jh4$[hkwui}2lx.%Ɂ<Fڒ`2`8ͱWu+|v _0wnqAsO&e(`[nX8ĩ`r^6 mlX;duc=wE MҖ\[-R ƞ@yĽ~/|w:MfX[[iD"uBQ SPUamm {_2wee>ÇJJ秽|>D"tM>oVVVp5a|;;; snYTUE:Ç[yP*GiqUTB:F"@RA;;;r -(JFX^^o=zT*UU133u~NQ>dH$H$/D y MFpq|d˗u,CQ N~;0w}Uuzί* ?V60&[?,FvMSsii bxPR`ggr~r/Dŭ(Ii/͢R@Ӵk:b*I+\d`6`5 j0ro'zJܞ|skB0<7LDDDDxbaa[ @(ܹÀY^whzёf}3k=ᓎCUl=9[[y /5e ɨl\ǚ`2,Y&NۓS쉈h<ܻwPP(d2 ⚈4fPajΙ8wvTXM @|7gJLDDDDD#H JR@u(9;:_Ogu݂3$H "o""""""'!@UUaT* css"""""pUFh~q~lLDDDDDDDDDDDDDtI0LDDDDDDDDDDDDDtI0LDDDDDDDDDDDDDtI0L=98jψ]}q3Cs/ٓXqGG0=}N6`Zc挘kŐL&ϟ]߶㜴SdYy B<2ڈD"x ~GX\\0x9~"P/7m`rӞa5`ݰp+r֬S3!nu!F̀߉^I=q]k {7" ETBQ,HӈD"sΥk BX^^]׽?]"""""L|7Xc IDAT>*G@p0Dif#`u*j:{,ԾԜcaO@qpiS㖁o.J]ױ?v}{L&M8auTUE"Zүy]DDf946ωO"""""v/b`QwXNV:5M/_#f8ٯ "ă2/`uXLDtlnnbss dffP.9DDDDDDDcg̕^wuq˩6{89 "07MN [W*h Fhž+K=Þa|m q[DY-KbƸj7&isM6 sn{F_=k `50ofmոnU:wBI37a\aOp[t>>=mWW`4aƝŮyyvj˶90߿EȲrl6d2mI}TUX,T*UU: rjǨi8BE9^秽6?sB!$IB!NeJVC*jxMUզ\__jk3334 HBUUT*P( =?%2bTUoVgfffsK>Ceff/_l `W-C~5a"i^b]uE}edһwZbwwbBaωQ<ąh>&܄b'jԜxk 9ž{Άq׀Flʸ5kۓ@ u f8lXjs5L|;2jZCteX!7M"PtN-4na̸ 놅&:J.p2 t]4 333A8F:F\nӵdT {ORD"xA_g9JA4,,,l8繦ip8 M scwz_sת7~(FF4^dYƓ'ORpphKKKm&EUU&]/j!BQC/s?O"2 EZT*4dYnJVjۓ07n-+OD3NODDɭD"MUgq+`5MC&fWDZ&SVVV DJ2[߽{it]ҒYNH$2Ig|t=*Db wgB!Aj*VVVP(*B2 (x40t]:MP*V"v^Bl6%~jϟCQvtO<~̌f>JCr2Lz\xe{=Śsb3?q!"""""$fL-g̺C[_}:JnV|'v-!+ NlU={ ݃ζ^ԇ~ϩOOm~nὀww+N}vDDqMR5VJ퓫ժWGez>䶗fQT{e|UG>}YmXwww^樸[@6mk\Ye Bg'+ݿ;eغg/REATjjӽ_ZU{}ϛrٽ>'<v\0]1m;x[Hnԧ?ϫorjc@=e; "OL7穞rEQjۤQ]IP<{T뵽vq9<<E"$ B!Ȳ}:.Q3?cn # vww[VIc [7;>~wH&x2J޾}rωa=F"""""0Lh Xyۄyӄ5owZoai~wWx/uuN֟+z䉈vX%Srߠge{1T0VՆDV?guZ+nŸR^g?/b}VU,,, J!A4/:l_+7 `DDaZnX05R 7B*q뒴kuMymu\=uv;DDDg9~T9 B^RѣG gt6~'"""""N `ahD^p+>h&"ǭRkV_G"(Jr湍X,p:4uR:DI7?w (H$ҶZ6Gz ~;>G_x׌lwf(x#.DDDDDD0o1m;+턁ɾCS3Oy[5wxqۀ3`^7Dmw `ʩ5o^֍́j_3n:[1 U3hOxHFv+J4ųYM"ďh4d2]eܻwϼMivfZb}}T9(28|"JyXKKK}=?T*!N#HR vvvμP(/@8Ƌ/U߾}l6U MӰ]׽ *^|>D"4w|a rRh4eBQlB̸<'֚`[[f;:g֊[+6M0Q]k^7a&q[D`#{ITqKh9'n¸U ž$Do+ӎÞq+0o0Zrt.$ hYX,"ϣZ6_4D" UUQTBͦ6ݻT*𚪪jxm}}-i8BE( rM}L&H$*t]G>G.Ï?EQ0??t,H$bPUՋI>o9>"߿rжl6}@&ig;L"NT*=q},..BeedYz^֙x:,#Lzcj]E >0-&i$I'ߞxD Y{Ά1gaaDk&jԀ) 'vӹfI6?}f5o5g pь;o'[03 kBmֶ=79C$nx?%',N@I8XIe-c?~qә:'4.H$L&EQ8IJUUN!rSb2Hx\]ױEQFFiZS}+@kZq{t]HR4 -OMejP(0}p[/ Mvv%nLMaö64!)% I;흝%$-y&؅IA!37 `{KC>:d0utr_Z!P\zbp_bj #hBѧ>Sj[{Gt*q@'"g͚5b(w꫒u۶mbf1꫰ld2 ׯGmm$lii6L8z(Os=ՊAݻW %sNa^mm-֯_Q%T-6B,7]mpTsD@jgt*OoXLW^c|u'<q O^X1 3-O۷oGvv6.]Gi'NZ)vww V+++K: P ~J ꫒q̙ n-.E^l/ ghs&.Ȼ4_t)B t=,LgmoozHDDDDDDDK><~P"n֨I`Zp-Uȇrz`i0"@UdX+S(}UĬJ$G'7žĐfqD0>cd*IEo"91ђ%zMGOO0Ug!^ @a ٕ!5sV^t)xghB+N(auxUY ]VVԽ \*A]P Si/o;1t'&ك(!Ъ9z$Yg>/ױ~߿&Ix6xWcELDDDDDDDK2j.50-x{ 3@r{ *ʈ7rctyKMnbz5G4P6P!VHknP_JKp""Zİ,|x6-" \{ ޮɞR7BBkȵBuP}K.-1uO9Kݍ'N`֭bp"(&$!]X/G|?` Tp=Oc" 1qxMiO4Vbh쯎~eRs/j<@W hyp6saN$ KJsׯ_/ oO,T&2NalTUUL홻G4MVam?}~ɜjUsDD<?~X~=vZVl۶MrLت$[VVv-Vy UqC1?~+DTgeezsNyVuuu1'wUUU|-v l6jbtt.]ZJ:sto۶m_UU @DDDDDDD &٨*!XIO ^SjJ1< i3gkckV:4k]g|Xթ zs$WV_GDҩL45~Kj._ʮJhМ$>9@(5Ck1*zb  h~:݋&աhDvvvDPގK.axW"^/c0XfMgΜA]]^|El߾] >sLDC`4aZqQ1[YՊѣͫ2fm`Ľv/\0{&*uO9KGg4sNQ1&&"""""""FZ,dxTV† @:>;UxVAwA (R@МļҩM B(t#BPSC:O* Ǧ UjiB, _)l? U *f^?}WAs\pŊaМWo}^kCA¥:NP~oAC :O>lN{PQC:G4kp*, ݩ4$9Pe2ׯfaBVV188~o63Ξ=IFF^կ~?֭Cii)z{{c裏j*h4⮻]w݅!ۅ ׇ,F]ۋg__p͈Ξ=+^ccc8qN8!G355%-u:t(|nذ& ϒ^A<BAᮻ‰'u}g066~[g!={,s|~7o(&''-wU?~|u'""""""tE| >OnPuyACJhXvM!` @ӤDD|L&x֭Kn\xᇹPDDDDDDDD`bb"y&ԭj(Pk]pɎ3P@ҮdKDD˞RUhK-cKDDDDDDDD`"ihzIA]0T|hx`2$L&m`i&02D>eZStrhy1::Adggh4^hMMMXf f3KDDDDDDDD0<;q`4a61::.9s---KbUUU l6:ą#"""""""Z,O8 DDDDDDDDDDD lÆ "S}}}Jq`"""""""""""""-)_ h[N x _|vqκYwWxq}k$tOSln|A<~/>xogqT^۲e *++zj@nn.ZmBHT:%_nyoY\ ?<LLL```v=b}2ˑSSUf=K''Ő7Y^0nu `n'tgi.nu E˨k|5?7Ieeefӧ?%Aqommmcfk֋7n^^2D""""""""""J`*)Z7Ƙ l耧yȲZGZ[ j@:ڊ^qn4:8u &{{q}ɜ v:n<jjB햬dobٷoB``}uyEȺ;ս8/tB_6`/0z3xשB́Sظ(ϣR7ܑ&'`{qS9gg#kkq*~E+sf͋qǺm=0>uP_ |pH~Bn*@{zz*qo===(,,DnnxLv/!>Z- 8)DDDDDDDDDD թ=gY׉T5Xakx,-67#6r'`1Pe}P ZDVhU Zd/R{pߓS~q^wmH{\U"Wއ=ky}~X}Ϸdi9>](񠸸^ "im6rK(++CII rrrxp8=SO=B8pX,ȟ헁\x1^yOhl2PWW7nرcs)VE~~ӽjTVVBrʕ+hkkî]j_1LD~~XB9##EEE/LLLp{E|.os<y0 1 =to>,WWh:vNdY(/NmT1 Xɾ#9(ػ7kUb詾Wc aĭ?sp*zww+KȼT<yWҊ̂ɞUww76mڄ\~ǃ?===]ab[.fMpYxꩧQVV&[en\ `ddD[nx[opqq1ceƍ0Lp\hiiƍQYY-[̙3+,,[o1V!P&""""""""O? Ao|vn--sV&Kp vpH ?>.`Z'p`qd+T6Gk-:Lb:ewOyn< N'ٷ0 N}Câ=K&Vߑ#V;.VۇKۨǍ<s'[ f3/T``& &iE===شiNrahh(>m1Z nGlK7<L&Zv@ 9o~"\.osSǃZcǺ8?j.:V`+b= ???"&"""""""""qLg`UI Ӊ1 EIh+*PĽV"RC힗8_M~Xy+T,OEmC w:0fa7!i鄧CKx,pp''S~~in԰8o0d]{kyϿEs2sܼ'~mߏ/;E>@C{ܑß@q7n܈OZ\\4\www[~ Qn]j\* Z6skfaft:0446 0B̀uUI P8+V &:;_CUFmb8tBg Bk|B+H{>bNz)~ {zz#X}ǒkMDDDDDDDDDsIX!pwZשSX*3KKijD,ӉեTB; mEE\p1ϻg&{{ohh=-T,O?>{::bBQ&#ƾ1\^:~c_>͙=eㅱ_,w{nuIߑ#ONsQTT1]`foX1,++K4c7F=P eX}b!T`[,IjuuuPquO%qFIEdBeee&&J [VWWcݺuW\\,YwȴIv:y2"?>9 N'kլ^#qfJw5*hs nn߂{:Q]-VYWFmodծY.qKsG }?^pי Cٌ<)9<6>$y3{ز/⇯-Xm^h-[;77W 7>L&1,7n@aa!~Νߏ~. ͅVٳgaXez*, Z-}Y\.ddd@?ĦMm+q^ ٌbر7n[_r%f|Ed2aǎ5sc#<n"""""""""Z>S{b^^ޜERn7FZ[1*ir81nohBJł,c6q8%с^ ,efØN'p-WBq-!ݸgOW `!QL56y<3bJxE{6KCc|ɤruw~iHPULWQMq }l{4Br044uB8,b[زe jwyӨFee%z=<`144zOLLرcزe 󑑑Á/bbb"j,8W:>}7nDYY rի1`8sX)/^ƍZ1LLL999(,,A?aLDDDDDDDDDDXUR,S}}:b`955 ڊ 7 _7KK1fUn,TnDDDDDDDDDD4>%:bix}@r}؃>lA/ѠOZ 1=ߦ»6FcZ`!qA IDAT`vp[^PzbQ˵ r*pz0'|g#GƁT1 l!:Y-~ztNbwB r\t͖}]<œ򭆗3&I\(9G4gj bm~]}3fWR6W}"²hᣰWZCh?Tv$5]^Nc  ld҄J,!zv*ɹ?u9Γ~a9_C@X?SI }y#n8zmy_D5!)\(s;xoXhNFC-o.#TFK5w<C <ۤ )UW`.  J‹'H#6-*VUu\]}J1 .Kh 7[P&v5B-<n"BC|3='xڟvr]D+jK w"fKx|W S>~Ku>.jS/|.9W!~߸QL5O <%w.̽ho"SJo$AàSfz&Du+0V<{QG[d-D[S [˶>Vd6[i?g >ry5|*|;˜+oBU<}hQ|T-F߱B׶N:cδjzBdKyG[߯.H^u}VaK}]`c>W : ߽A{!lnK-|fbCgrr3c}% %J`;MCDDDDDDDDDDkJ`. z/9AL8Y]ǎeyk\ ƒ{KQ#kfs/ٓs\]C~quAl+|_ t.\C~s!גh{ Y Ut7{bQSI@ #η0vt#^tO Y$ /R=sޮ9}muxǦKtz_3=ߵ$U+C$ 9jqbM%9BsnKMW@hk AqͫmRARRMFZh!BGOf>Ҝ٩aj]̿ihQ :i#3- *GL/FƁSj#yCFR7{:8LA纫O ׇ-c8v%Rv%_WTs 񥤭C)Yae1/Tk- 23|.9W!~߸ѢkT%!P5TOveDEKը.XS%l^y$AOYP]qz Y]u# :|@R{y^{85U\t$nWNlQS$@xIk `څ\TS؋=W::9{>@222 ǯwy捍̆{Sߵ0LDJI#"""""""""""""Z!i7.rpO~.ZC.6\pڟs/1|%>XLDDDDDDDDDDDDDB(9 DDDDDDDDDDDDDD+VDDDDDDDDDDDDDD+`"""""""""""""0 h`LDDDDDDDDDDDDDB0&"""""""""""""Z!s(ҥ|oIENDB`qman-1.5.1/screenshots/qman_man.png000066400000000000000000003275641510660157000173310ustar00rootroot00000000000000PNG  IHDRS׫iCCPICC profile(}=H@_[A;8dNvQjP! :\MGbYWWAqvpRtZxp܏wwT#eq!]0 Ab>'Ix{zY}JdO 1ݰ77->q%xܠ ?r]vsa? tEXtCommentCreated with GIMPW IDATx{xTսO&!@P0PaVX `-T->ZR=Um5c?Ǐ(@@FtCEEMMMd.~lJK,4 $d$)  _B??Yַe~*77_=fjjf͚׫JׯWAAAbm߾]7nhO?]/ /_pf͚C[_|0;O۷ougsݐbQcj?Ȥ!4]pf0jAgeeo߮yuϒ+-CZZyꦛnjsiӦizGm(Ϝ9Swu ^ziȐ!I]k1ѣG+==Sjy2drss^֭[n:M>=Æ wܡB]yAylƨP%0 2iԫWLLIɰo|CsN8gymz)577UW]wq$ri*.._<.Ew$I+WԾ}4sL]wu4hҔsjܹw׮]Zf$i֬YAy#I/?7!3o߾!4q 'j\Y,:uɰ2m4IkÇmmm?K: O7GDwӞ={c9r?%I|IqiСzz%I+Vڵk5sL}-Dջ$iԨQϗ$:tH^W'N t3%i(}z5 i| 2~zSN+";3N;4^x~ :T}Ç?Q-%I^{&O,ݮO?wyG:r9u:uuKnf~2dRSSv EjTF.ۭkҥjhh$l6g?ȑ#etQz'w^xCܹsL}裏T^^kךz뭚:urrrt!_^>ykђdq-N*ݮG?ԼytA[N_u_~!}1Ϛ;{i~+Bڱc~_o԰a4p@y<=ڶm~_QwT[[p={z^7ns9:~~׭s7g~w;QIZzƍt_ Zz8 O~IғO>J۶m̙3k.}9rƍ*544hΝ:v?@@7ɡW^:yd=ϗ4lذAz!jW<4A]vW{ڵknfIҎ;t-rssͿ S$;V]tQ."-YD\sMT#QO;4}g}>}'r\jꫯx=ܣ.HwzuQ3Ɯf_vnV|>s9zջwoX Ѐ~3_6C ь3K.IrKIko4<{dXt2~륗^ p%h{oKf̘ `:~*/\~M0!3fhΜ9iذaf 7H/b2* $I>3|>驧Raa^~eYV]uU:q|A[o#G#%t/ ?f޽cXk|/T#O[{!CD? :c vmvH/baX-Ir]'OTii}7ꫯ*%%E<^xg8n$ @זnjt{voG?jkk5|p=Os9G|Ifi`0DfIk„ kبk:pjէ~'N7#am6kcǎ飏>G}K#G԰aâJ/\wc6b 箭ծ]裏+Ԁte$ĉ:u Y >@cƌؘ29W\q,^ ]q$+ŢѣGk߾}>}{Ջ/;vFfs1ՙ_$#_i…:s_4֟N3יLO޽5{l͞= /\Pyyy>|$i۶m:-$edd(==hcFӤI$dNf<{W?̶ҁYbM`PVV$^7onw!?beᬬ,}я~Ѝ2pHz#gddur#=W$w^ 0@_Gin\l͘^bk_ZF2ԺI/."]qv-_$wQ5moѣKك]i}738ǣZS @MG؎:f$ۧhÆ MtN?ts޽{w^'0;ƒ!#hi***FjˠUVVV(O?4(TM>]C |:|t,#P}e3l_W4l0yfguѐmŊz7F(oٲHX_B9rJM0vKc%^x>C=f>iׯ61uAANƌc_áJ:묳=1}uJJ~a}_ȑ#)Ɏ;fn;qDl/5s7ިq)''Gg}f̘aN7nݻz!Y,mۦ~ucNK믷_,Lq̶/++Yg{{սޫ{jСzGcNS@@222$ 8p@=ugl'h1byƼo>Hgun6۷o׉'ԧO]Vǎ3mwѹ瞫?_Q/K]uU߿~{ހù@}^^9":]vi͚5}-`J~[6S7tjkktv/ŭ[n%\bvwkA߿_/$i̙:tۧ7zN_~Z%Io?8@7`vm-%_)4x^mgaȑ׿O%I{}рѦ0D --l5vڠ!33S4w\͙3G\r맆}ڵkW#0gϞջwoy<߿_ӟ$G\Ν;Ww}F ?~\w_WXK,Qff.r޽hСJII͛O#ɓ0at3r?{ժU߿>vڥ)S6?ϻkn[|FkFovޭs=Wgyw^\R.Kt5HϣVqqΝcǪW^zϪ?馛nRSS6m9>PaarrrبݻwO>hϞ=_?Ϻ4f 2DPee4l0Y,z _bMqLC|O\'4\x>QwuW\#2=\wQ}}J$6ώTaa|A?~\\sMA!ChڵJKKNbh͚5Zl-Zcꦛnҿ/|Q?dddiرcK␆6n|/}ݧ^f𷶶Vj[n>#۷ͩ%{#;kN/}~tFoQ??jjj8MMM3Ht9f3rzI>Iӧ]'bڏ) =`!]͛+((豟wڼyGMcAAAk***͛tv]jUW!/[`sa㥑@QUU%*Il=:rmN4zh3_<jjjTQQ!ŋ/˥Ґ-**RIInOm***T\\UVVupu v@}g09shƌ1cnڣ?Y$I+VhwiӦPSuu$)??_eee*++ g…ֲUTTdnV|rl6s{dx=υ/p yyy*++3wx<*))j &6\vZv]A?/VnnnPNG d`8nWqqNg U\\lS]]-ͦ|t-`TB<OBֳ3qعsg]. "WuuuTʨwH2믑*,,TaaY/UaaBc%Y^^n>p W6$%L,DK$}z w|0υP#.faV^^4Ɵ6ml6O^@AAAPVPP\n͞=;q8 !2k,9NnaZURRB͟??h:-YD.+(Oʔ6 h$=Z"Z㡽<...V~~<C( .ի)F$|x|Id@s \ihңbݘ~0tdNUUU?F6zyY/?E0F˜:(q$Sxǣb!?% IDAT}鵍@gz4ΨG+77Wf#FSOD$yx.5<B )hVkѨ… pB9nO?ɓ'3(t/_gy&Y?cAk38-[,5*rŨvegg]Âhɒ%dVˣD|Oɨ{}ΪGVVVDf=ۘb/d;+_z<<sa lvo-zOKn^M%윬 4f dggwxkjjb M2EWΗ ζs Ř"r-O Ѧ7eEDdթN˗/tX$V9e *\˨ǴΪGՙi6MUUU }k}򥫷@sK8<>@0Kee$ohhBXԾ+K ta]{ϏT($v{B*yyyACIIPeeBղ***n5&ǓUNM\XXhB=|%~h‰͗Xu<0xp;ΐ?Ə}QQQ@TTT!b (}yyyf"wb͗ Neϥ~:dZUPPŋyyyj^j^ؾNUUUf$|!+NU^^PSH 9Z`{=kdfR~~~VUf͒tQ"H.v+)c-;|~n‰͗Xu<0F\jkkUZZ2Pn[Gv]6,Z*//WQQl6V^--*ͦ%K?މbURR lf/*˕X%˥iӦ)77WV2{1ܹS . *vN-[3HTUU)??_O?tP{1]C!]fyx|0)I:c˗mݺU.ˬ,`: 9*×9s}ɒ%Z`,XbsJҐ3v՗bՙH3kUVVvH/Xʗhyx.|^sa JzH҈#Brw޲ZfvK/饗^RCCC> r\>|VzFSNաCBNvWph֭?Q:$ǣ'OfiĈZ|yȞ@/UVVnn+''Ggq|>_|Ԟ={5 rrr$IwOСC_^'O4ѻwomݺU?Oo_FݻwMu0ٳGrv̇Cz*''G'O4?p"9Nn'? {|6b[q8*..VUUVXMeԕ:L<OSܹSԈ#dug3vSNfw-m<֯_ҰXuUSJ`>Oeh‰˗x<0Q,Qzi$Ͼjݲ:h"'I}!$MQQJJJdɒ._xtjٌdC˖-ѤI0puSᒤWiӢiAۜ8q"c31ټy3]zAXB*** Z+q8r:LE0@0saF~{_=\ *//OVVUK,iwM tIӧE)spIͫiѴmN8ӱ =`!@Az4VqqdxvU[[J\W^ѱgϞ[|@NSC6Mn[n[.Kv7oTWWkƌ$ժ 6ѤI^Z*,,e%In[3tO8QuuuEEE*))$-YD+V:!8Nfdٔ+ө`ev8r8n`g멝Aݭ[W[[0t1sˀwW#f-6M˖- z-ծe:[)pm6[t]:"-,,Բe˴j*Dte˖iA͟??`쀿Vq[nے1G7 t?Kii,Y"nׂ tҰAxu)#M1 tyuFVX)SSuuu{*++ks*\ZЌ4. Fp_YDSEE***p84o3iZ]rp]]l6mKyy5~xUVVvu@`$\MMJKK^3pu2v=LA\9.quF̲þziVVV竭 F2-rgغuApmC1sv:]:"9NZJASij֬Y;-]SePfEqqong*]k#.v] ,Ђ T]]:i tΚ5+Z+VXxŊ?~9qqqNnVkB8Z?w)NpB󽚚\.s t:ҷbŊQYY tu@G *x֡m-???{FΙ3G/6:ЙH]nyN p۴.+p]]]@@?1:tjѲlx]EEE_? \QIӧE)spIͫiѴmN8ӱ-d/  =`!d:ܘ `0 =k ohۚQڛ AT^ٔ'_+:͇6\M5j}$u,fx|:ѽ2}M!#,?Օ4|۵N*gO0]{bM/Qk>?>ȫzu^3ȧ#R^l 8=e]Mf]~KӯodekӴlM[b͚2ޟ~Y)w6͢ek94:~l>MIc/>'I;_eTm؜1%ҊT-~WcNIsokҖ|bߍtNv6kf3)ZJ y?߄͚QЬAhŰ;EwNu@Ci͚~~IҐM G"3nS>؛.el uf6E+7Z}g?ozus\k36e/3Tb1COӺ73w'FֽCe4rh7390p䉳s5QKgPV?^=fzM?` xPjN%ta,y hҵy4H'{iڵ7]+7Z^Q'#FMq6랲^nФ):ÿ].ESskfN-3T^*W[]m [)4~.&3ΛXhrh?$K}0/G]UhcGܷ(&^ڬ7}7nIKXE{X3v?:k}"YdX; jYsokҾ)rHy#|tWh?LLlVb,i^IzV@( &]UΠ7§vkT`XZwj- :k(h˼! tuC^{It_Py+U.je^-~1Lc\Uݖ Hq7§F+opNI3 ߊF۱xGC߷Kؿ#Jw6X)e4d@NӼ_ԕc#7@ol+Iج!8M+7X} _r_V7ծavQr*lK  5hޒ36k԰F?m5iAQʍV`5ǽr?轰`@۴>W׌B%u,a԰F{k[Mo=a_)KUؾMz^ w΃SHi^ }@qc.Zfl>_,t,VUuՕE}bÖԄCb~E>=My}o0lk?_ﱶbbDvQ2!Q?%?{`t5 iXc)ZB6lOרx5y|SȞ[_~FȱxsnmԤK egim3$[<߳y߁S+^2t-my7U4)gOco ;kx~s[t=Yߛ[v49Y^85eMA=czzîG^93F͆5جuXm,fM?{3S^<-(ʦ,q/el’A]{̀rk>fϣ G/m۲rU,zfz4 XhyU`]2cp]nv﮽A(X5B^#hSVؑU>77:J_`-LI,&o 97`5r{G@ǎZNbˎ/ e2f?k)3v@2~Hl/`<_׏zhGǢ)o-8~Z˜ۚȯ{%hk~&ݏĴc-]Iv,LtGNeGt v+z5.[ozEK+=p2oTn39m>[J$y_ґzl>.& {e%n o;1=fT7nIMnG 緼ekz[k9h{rb͗d_t_#@[%{~,;f1,n$k}Uw,T{}"hCŽ]*]8J$2_?:uz%kq bL~SV^c3?/}BS'IR.r 9IhGKCfӺ~'|#|c97?!:!D}"v@~Hl/d]?u._DGъ|h2_ҝGXˣΨ$~k~&>] `t*PK4-0*6=U鑤# IEh J* m;p`O]);O }Oϗ  *>VR5z7k:-Z̆y[s&K)ƞ߬At?ݸafkc>'Ϟg/˧>U?_}}qEG k 9%{NSC `7/ʍVq/Mə3 ccT<d%iȀ{ҿ%5=M4p }t>G5zZ}0o<[vXt>x?o; Yh?${`:t/\(Q_,Q,)wGnߓkyYdbd'+!.וVUw,Eޏwz~-f_}Qa%j,Q74kfMkw E<W{ވ&M!hL O/qO _6z9vu'|Iu@/Fzs)$[ fx{?ʍV dج~4*1mI nցd234AhFi78fwz&p4hkѤKk5s2@!߳Duס#m%@JGRvv?_"+b-:Y<t%mK Xx&nt~VfzEr{58=z-musCٸ%Usnk tm=p6z{^=hX%ݓ  ԉuʙ[?nLk>Zfjj/jF TN9Zw; qKnun}Z_IIX$:{2l ih;AL=o(zkƩZ)Uzw7KmzFtԀi':~HD;~^(QX%|_'JV/ˇXˣdCB,.g(m7=ɤ77~1 7Fڳ)8^*S;$ɴ6?zhM00WTExгR4f?rC[v1IҶx&qu2O(pPBmgyȖ YLi:s{h[.(AQ;Y`< @z˧ vd;/'r:@c:QCWM(_oQ>\z~XєG/zH2sGɮtF,3lD}*F_{7eFkithilisy'oҳ?l[~C&o lvʖwS@ӤK:R Fw54^ƞ߬Gh(c/j Mۚaa3y|S^t?glEE/~66^MX'I䌠u,zeS-9#hߗ6ʦ}ѩdi[Mo=*ziCܡ TslPV; =u,͚~o^^51~s"=Wfxu5{ }r՟_\ct-#e")D_XMG,5l`yc0F3MT\Fssס;}/Vܷ(^ 8O| W.<|CK!(ΨŚ{5mly7U[v4k^=[ڨ}|_obF oBYb/+}-gS{ӔۚB~_lіwۮn\e%4>AN JgiߌͽISԟ)Z6CHjҏjҌfs ]Jн|og}>2Is4EW9r$$ͼJjO){`2?fQߓCZMO?>W9F́M*qXeKhݛZfގ X~#zzZj!sqRUشLeexG k mՈ3X˟~w濊jR?Xo""LGDOͿG_ï_W?g]??{}Wze'&wr'O2JIҧG ?j|5?(GU7^ʯ+#6}W'G_Ig̿;Uw;?l~6?rrQzWʗ{)6oiݧ?HG=w˱]?L%fYi纎ߏfqM,y?6;kqtiMy4~?n޼B!>|x}sNt:ZR3R=WVOr7*UǙT*jNd$ 8y$rR)zީrQ.#"OJr$ϟd{{׉!S/ɓ'v#"X,FP8u~?ArHf&vDmloӉN3o$Vty$LJr^xI3sf3&Ɔyw^ӓfcmmȿgv4oIr É3?0ז037jMrr#H˓4MzQ,HVv݉C> eDī5o~ތ=~?e>[0sB`NH `9! 0'$K.փX,=nݻH&qX\\r3Z1 w޹6~g潿.cϽ#؞0_r\ +J%FJl6\ F#VVV۷5@ΠVŷn`'snG.b&bee%*JܼyJokTGDDߏ~>z t_&U ~\8ܸqc|3E{jL?;Yzcc#jFP,^_$j^\M ~h 8 ``/Q˱Qq@?CA{j p BDtXwjT*Q,ӋpN'YR)z`0z^#fO>$|tݸ}>~x$N~>iնN.or#]q4Mܻw/{Uմo%zSǽljQ,whZggGx楟9/_>EyL?(B!zjZY~jR)|hZwXzjjsNt:h4iNcsss&Cg;K'GDX~;bii)gF(c޾ xEbCB_qtG}r9sƑ\.F6^G^Os=z'IZX__J+oR)FJxZ᾵e(i0́R)G\{_bzqr=Hb`eee3ɲ ~pȾ&y]V]E^/L%$F+++\.GTp}M_q$~ˊEKPds؈^{mYo?73ysyyI?\J%66661 X,Jr&'~?~XZZZnC^Oe~?nVQVV<18i!ybyrw^刈trV'."sRrKKKQT&ϒe6͚o8lSXLonzVyE=ncVRtdBvywbrƍ&Kgo+++itjp%wLrYDwj'?wq|r~&w'fOty򫫫c'gVw%=|> ‘Aٶy䉸_W*' xYwr#]Fm^7kcmllCYG\#LQ6VbD3γwlrt9v9~vQ Bh65r>o4i%,$#IX__Obee%8 ڊV5r,J؈jV{֭[#Ƀř?VVV\.Gߏ;w$jڱx]TKKK{{{#rFc,w,;WiT'V-^t6}Gc{{]]qtiʼnKfaaaiwV^/jZܸqĄrB7+飓LNs\i* b1)\khܽN>ВJұwr{Xa(?s\MBDc6麵RD^R4uQInUGG~\=9ugrQE_f4(t:nɓ'GyλӬ<#Lnzhy?y@ޝu򧙋h* 1v tXdZ+++l6Gb]50+-#e/Բ*Ո/(r(y7MǑ]he&~rx}ݬ7O~tr1%%lTXkY׋L|;˹6;`0HImvQ8ǵcRY{<Nx]~vy]yAlnnfY^bߏw}wqVM-JpJ% Y=I7"ˈ,f?oZĘ'\dSF.:{xZKKK#^/Xg{X^^w^!iA6`d}{{;߿~nk>}޽{}m6r³ôǑ]]tfeX,1Iֱ֗j{wG;6cj5]O2~ү?zb}g?ǻ~6Li?f_ڞKElww7Zjlmm$jZ c+:Np8XZZw\.3=e*JT*s\I=ͬ9םp8LոsNzT*4A{ewZF\.1,7|,..>QήK.#Ӟ{^jh4jl4dF^wgR ÿM{ޝv}m^-֗\c=c 0\sѳ9|є+Ht r`0bVl6X,F>RwrIpp^aIܯV;NlmmTbe[{^Z.}vEYaHhWqtv[[[G/;V%x1uټ3ers}vrt^.] z|ĄP6$#&777GN?Iו$:Vq{cii)Wv=gڊ7nD\FQ^v+++Qc0n;̻~$gқgզ!~iσf3EÇi~BXX[[xlZoD{M+I&?gDrf}[[[6v,__""^zI.h61#+J O~?bkk+~~o;Ήj__=^yl6>ӟg}_|E:1d?~~+~ӟlӴy7M8L{ՈE_"++~0/J|$oo׿^ox7ߌW^y%noHϳ]?~Lߴg/gmO%u͠jKZߏ}{}ĶOoF|II[rtH;'>쳑|_xW;~ğ>O~jR:qg<9m{ug9Γ^Go޾8|[ߊ|>m{Ҥ g__=boOә%D^7x#>gLqσ/jśo~z[V|gig} i?'{l9g}xJ͑NONs3˓'O_ȱq}9tT"l%^эñe~_NwEėZPF:qG?3DX[ntZhկ?{ ~{c|S_๐buu5"عwCA?CǏkz뭷4\3+Jb1qG?3`>IX; `Ν;lq?__sp-ya`{7op5|sBb<~86664sB`NH̉4̇B+++QT""rQcaa!bf=YQ,wߍc߷VFZX__  sP(N X,j\.݋rn7|(QVG^/b7nH_04́j͛qxwlFV;u+++Q.ǻoߎ7oƝ;wb0DVt$$wS*""kT*1ӿmnn`0ddlEoӉtdP(="I5vG*p`0L2tt\\.O`$\*bgg'vvvFvI5W,#"ɓ'~TnR'=[#y|>&tdh?\, `G ||>"bb&W*h1 dp2$QIi `$m='%wzm6I$u$oTNN'M'aC@\, `!az!;g%CDgnU*tnGZ\.r90<{p%ռIUaP|~2Z-"&0~T*h4F# AZ:^]]=rpf3].[[TDkdo^ODۍz%MfDVKrbhZi5a[[[qƍ(va[V{sB`NH `9! 0'$0sB`NH `9! 0'$0sB`NH `9! 0'$0sB`NH `9! 0'$0sB`NH̉4U(bii)*J  jnllDV~7oޜ~>L{{{#xc8o42\.z=X,l6ѣG'nG"ٿ'ODՊNsvIO?=A;^Gsj1\>|>r9jZ 4&qbjd^Oh6]ǒGrq޽(cZ.Z+z=vwwc{{\rq`>I3\.Gk4TfzhZiI'U*߬S'4WWWGv;r\\V^w%}]DRt:xvIdۢRD>ʽ^/"b=γ>0S[XXH nݺKR4erT*4yh4F䵥R)MT* C> Fqlxss3ݿRK^0m Ñ*{EZUEM^o$<>Mq‰YTǃ`dq>Y8^odBpv80$Z69[*T*\"[iTSW&CgG&uIۈ='}v80_$Z6cgg'VWWL@fn4gMxΓd+dIϝel`0I\t/Lp7iENN>]X__ޞ8|,'Ԏ&=<$kL![A\&.ЭT*cMW{U*AjxA,.. 8IsIsg|~dۖǃ`& n.K(kkkvc8FXVyգڑzj ᵵjFDۻvr?;uVK_;css'L_v0C;kp$;fJ4!ZVGjf]ڇl2w0%B|Lmoo/z^jqF1 jӽ|[ pn݊FVFH `9! 0'$0s%MT*~DD xw̶=x v;޽{R(Ç}888Ё8\.~i[nE0 `3݋ǏG}>'ǏcyyypM9S*""OsII+#Kj`9RTƒJ%i Wj677˱$G9Tpݎp8uN'z- 8rܑz) XpmllDVy.ǏGVhq݈x:79KrO#iwމFz=bގVu{JQTX,`0~l6g,JNwqq1F{!s\XXXHF.qs`J}6znѣG3ô뛅G>Lc 00|>i1"X,FCN7XYY{|>r9JR_~Mڧh6ǾT*Ž{ƒɾ-,,ݻwi8I`.,,LX&.#}&8>b1jZqv}h4Fn88VQVcyy9ZV4MU^pzhZvvZ_ՊV5Lt:c=z~=زJe,nOLR^$ nc0%-rH1y]N)˱1mr}QD^َÕbcۍv}d[]]I˟7ӬoVjک~XZZƽ{Fx: o\b1jIvᅳY`#*JXXX\ A0̉BV4NRvlÕr#=j7T][[S4k6l6OUU|8f3""bee%Ft:tI4调ގT*h4қA&U0$c$nܸQ(ҿ-..B{QW2^i|oGUr3˟^G.;U|BN[E09GVZ+++l6csssfq8dHZ&x~I5Vƞ+#U<<,杝Bp% Mk#;*x8vݷlܹz=IvT{]ۋT*Q*R^GOEβp'1?vr00&|ɶJ2248>7sOrydaz]f\vN':NlnnF^zb1|~V+fUN۞߽X\\Lv# YhR)z,,,Uswh6*{Q[o[oUj⭷ފ~;]fkk+]̷`dNݕjTFq{d\.=\̇^dOz]v奥V*byyydx7oތ;wlGX0m{ylCs;;;vc8FXbxlDĽ{ f}jQ**'fLu|>Ⱦ%1I^L]>*xq=ϣVR tl?FY>R)[r\Uy0M{Bj: =8e}M/'Q \i5ciIov.gaoo/:NT*Q,c0DO\=fj'&Jvtc-N֑}nd榓z!"xW3_ڛ7>{`NH `9! 0'$0sB`NH `9! 0'$0sB`NH `9! 0'$0sB`NH `9! 0'$0sB`NH `9! sRǏ'\zcuuU.ƅ2gPHQ(&.W*eu 03_GVO>$֎Lq1*Jj?#Eݎr: sOڍ7.$ɖ#"b0D ^ 󱲲AI IDAT{0FxNT*(tb8^Ӊ~z]0s%M[o!3z=}jbii)m0D6LK'|2q(m\.>ӈxZ;Dшzb1~looGyݽ{Z_ZǏzg^BňfsbkRGDDݎwb{| jQTX,U0:N4͑JR a:Gf뒹#b,^嗗diۍ۷oj;6MLtw}ZXX8UhDшpg^'\ ` |T؈~dJwX1G\{Cű}LޣX,HRz=ܹ3&I^Wbl;ϳR)}vOlN[RKW*jBO^'Alvuuulϝf=ݿlɓ''g6}m-\#V.'43"$id= `1f+/' {^h4hߏ;wAD<ى|>j5Jұʃ ޽;L6 |7ŃҊrHr֭[#INeיM%X.Q(e~?}>"V$ЍF#j5i[ r\U! Bp[[[>W ` ""憐Is^lzwww$xpp0RѺp{7isIusш؈lr8TNzO#?p8Igן}|7v=GF=i쳺qFx?mpx!Mj;7o4/׊ ` "bl8"[ukkkG.{RUh6yIsOkl+++h4fgڿl2?jվj5=z'-|ܓIӗ}S?{w Ț=90 . uUQ膻,膍;%\ٌ HlF|a+e`n)J'83, UTI$[ݥzW'<xLtd-өY*ʽnnZYh۶ PZՇ:q}5y7 }KR&I2/a9^1^>uO >YŠo4M-"RIݻw \ t:t:}_6 CqN3ϱlgx8 n\c1p-Z:dt:ɖv0 q}f(0[~: S<޼wt3֞buYw|X f}lu3ݝ\w_f ivJKYWz}r}?w$35/˹T*`|Vq[u%ͽ zggG׺yOT lx( 0x k5C:qtyy8hdu]qh C~ZV+w]Ih4`>q8Va.4-. |||v=qns|A*~Z4MH kWy>jZq#_F0kuťTojg<}R |驤x___˶mzˋ_~$R硫駟un:`{.{]T(HI,\}ٶ8  `枹aRIf ZKj$0ω%0Zʶ{- "Wm[ttt+ `t:t:Yb`!`C}FO6Ύj73l6RFOF;;;%6mۏ>Fzl`0!$| I :<&,K'''V^/}s޾gi4~_sũZC5A.|h]qՕ^~Fdc}%I0 zs(bvms?u;Lraɉ岤`lz'uEq6vTieǺ %kZVJ-7Knr'd2p8TޞZG lt/Ң`sotJ0 88Y.$\.fWh7oyl:vqy{}uݙ]4w69޽{ $K r' 0]U{$d2QE sC\_>3,gZ:(]IRP{W MX}uGk8f<$Iv; mu}?sۼfglz=c]^^qzjAlg{<Ӌ/亮*\וteVt= P0ٶrnf8=TE*˹%tg)J\T8뺽ù!iZbms_Z\Z8=6 Cdc @~j44Drҥݬ}W˅wtU@rYa.1Q+\.gƶmZ<%Iv|bv޼y7o+V:::ׯzJIqvYxL\V/BTU'B0ҥZgu.\x5BI\6ܒ0y8x,nk<4`T*YDZ@T*Bm\./[6INu.3˲tyyuY rK<=&mۖeYP3=W._.i]./[6y.K9kZ 0oZSX|f]U$uv0vݕyK/{@$I߿^欽ٙafAf\Aqj<g?/B,S]]TTl6l6:|N&\p1pL&t:SC Y$ NJqrp*btnV*{gggYǢ׽nժ>|0A3iʴ龪mkz݇Y:t]IZzE0k0oiEsեVɶm XI\.kggg>gSap:E{B*ϲ6`>:|Ң(8޹_;QT:Ӑ؎F;÷utfd$zA6;;;:|ߗ}_rYqs,Qq,cɹۓ1l O۬y{&?G]}$q6FSUթ}P7suliqtpxK@KZl ``Y(>4434r'XCfv}9X3 }O-Zz/ppNli0 x7kyeO;EӽeIסEFhchv.nnn}3pK;)S^ScR>3,wb(z<O @T*Ҏ8Wm۹e<92Lh4f{vvX}q(sT*I9<R_j}_MF0Aq3^+ ,x k5Yqtyy hƃ(vX&I22I\vlۖ8h4n  ìeH6 @ٵI:2S`g0ӼQeݳ{fYV.x5ø L&l9+zql6U*r4]igq^WS~H]Ca~FՋY_|nf޳g۷oA0a%`SrA¨u SK lu(RbjyK2Rwsh4eKJܵm;_qb`L&.EFfuy 7t V/.m+h9sY^o*~H]Z:tp82kՒt_^^\k餟' ^ suu#FGۋ55Ltppn8myV濿~ZV+W$I4vupp=Eq8Van垏n8v7s>3L[;z$ys0I mzjnd2ޞv<<::)es>gsB7&p)?\~1?ӽM0|޽{T*uzeYr]w`QeK* ˲j}WQdԾXlRZr{>sz%`Sx'qh4(/0^=`C  A 60l`!`C  A 60l`!`C  A 60l`!`C  A 60l(9|$)I|Iّy:>>djqyy)q~? txxl*'|J%}!իWSǹ Iё#xtʶG#]__^T*Qg $u:OIQi0Hժ,Al<`$A} Cz=z=qb_mgmin۶*l<``C%IE_zF_p8̾!](& u,zj9, }zRwme~tۍKU*a(qDZΦgONNT.W.ussẮ0rGI(c}uݵvZ0 -q$iXRIAdKM'áݮ(z:==$ jgg'޽zeY޿v;ʬ,,FzRuvZ*>v[p{k^*T*T*L&:>>^yL 0ٶZ$uGfSq -ZRնmٶ-亮Zr]W'''Se:Bj c90 upppg8Խ0QfGk}ߟ }^KNOOX0 gf=z}=͚y'˲cTʞ5۶?b`` Czy0TST*(RSVnߧSo 9eY7I  l6#IF}~ZӠXRv~qӽnf sR [TEB:3n۹ s<:hs]TTl6l6bhfh3,)idu]qu:ecIF#mczZVxnWx=z8nuxx [׽vV&GGG:<<\]y||Vݳ8utt5frttc|*FK7|C53u~~uxbegˇw݅_(mzܥX??$7_?uO?ts ݻwJBA HdE˶mqL l0 ÐHr]7Wj]*T$i=xN, aggGjUmkhy%mے#]]]QgCQӡ{  A  F777~qwvvT6Y NNN6i6OTTtss'rssKɶG#}Vmk0Pϐ @tfs}}-۶$^|9\RI>|$ ʲ, Q::ʂZժRdC.iio8*moo?y ``{{{V*a(qDZΦ$T.uss\h4қ7o<6{* C/qelZ; !{XRIAdKC4v3Ouzzc{ne}68(h4}`xf;ˢ\nz3i8vi@o۶fvƮK۷oeRZ窋eYv[\.Vpt?Idac5 ZN鞻h2}u:,^1`e=~O) 8 P1l}AK.T4nXfsZh{0ߵ\NtoYwuhFQh$r}YiPr9;T*r52H~DQ^n{á/%˃ommeuJDz]eG]&̽ztvv6=q<8EQvs(\Mϓ~8^K-Rw~n` lxD 0 `pq]^^F1!l$3;,$ tzz*6Իh4d2ɖ6ۻONNNEQv}n7 кݮ0mr'7t`ݧ~?p8yY ٫wYfynbi&{x,fAv$[.~_z}ktGfSR)׉>zz^+36tR>kag3FQ8!:ܥ"ٳ[yAb lt T\n0jRr9oTsrV6jQ.`LCm۹3N`5甎U..nsIk8FQto:L&ܵ-z65$*,];Ջm `*=::yu{{TFV^n}6.>$9E$Zʲ,>D{#po[[[Op8TSS}IR$v|G۶jJAF l$I?>>VPP/$Ʉ0 po_Q`s C}w0 ~QAnVal3+IJ,K?.Ǘ/_R( C98uvv6={rrrb7f՚8Q/s_su,l׃ wmNGId?K<2f5ު,^c3Lr!EuCokk+{@y2tY5뾿|R_f_$`\&{* r.Yfnbm.lVe?R1]wOy}9{ gﹿ|<CyK ?&+1oVlGhqko]=fXR)p1d}3+ynE|Ҋ!آ}Q?iw0)ZO6:5]TV5uUTy .fk\J%:+4MA #kU"|}$=~q}|̽ײ,ab޷efc<+, 0$ Zxf8.//qtmX8ggg:==tŅF&Ǒ8w<%DQev3ħK ,+v;;Br6%$I.]x^ɲ8({wq}|nfEr]w饮S{zn6z% G0avg h0 -x2j\./ՁEQ. m;7Uuץh/S7q^7JR՚ :}d2݃UYa]ݱU>GQN=[mOcxƋ$lWf``|Qӟ_B_?d_ߺݮ?Smٿ79_w_j7}~'vy]۶$~뷿eT?!ygպL&$g?_?7կ~5umwQL/_k4WUvއ>Lru]6{$˿9>VI~;8m[qjzgWoV˞Fp?I;>g?%I7χ8R IDATc^I-I| <ŋK-s%}?[x___˶mz>?\~1?ӽ'ݻuR Z$Ipy"c_0ɘ{aHA$+C;;;Vm^Fc.c۶$HWWW RQӡ A 60A|͍nnnt}}dVmD ///lD= xgdl6u|T*ɞ雛P|+Jl&۶} [ٶ`@ѩ] @tfs}}-۶$^|9\RI>|$ ʲ, Q; 8Fz}x>37t)qEQh=R+x9rGk8fX*I\v۶9vP.J @^OXrG^Z8~j6zL-\ŋrm=ř$p=)⚬Rp:3 Nƭj90 0M /*T |.ED7"jb7pnCd[g40,zɗ/e{V^mے?Tt~/>0GC @i련n}hqԴT*>Ez]fs|5Sm.HbYTfmg!ܪ&Em8 wknK8jOu,üC ðBX(y `Y4Y۶gsO$>YR?xViݮ8eYrukkk^#ןGj6JDIq/۶˹$kؿjyVA, Ak."%I4MKQKiybv6e똮SJrc8R<ޫSoXugC:v]:ɵ`i}?bnT/^˴x)k;dkf& Bz[]$)uӱbCɉ|ߗy2M3'4U)c;X[Ul6KSjW*ʲtFyx?Tf3@Jټ =2ũRNR8lk/a~ei4uݼbLѨT\ vvvij#۶UViR4Yl_ wwws+V=)4Rl{ϢMӔaP3{5MӵViWWՕM^J71%NGA={N3l,*ze2£M:szeMXd,D8 WfeCv]vǓסRcK PV4~>,M`0PEj<FQ4uEI( üN32e<]cxr'e1ym-ʟ~ocT$~zkz0 W闇[6s~ή<k6t~~o۷xP/S>y`Yׯ5mx.4M=\4LTQL}ٍU8Y?ìJ/w)O&>{a6+8rgض-˲E~W`mAILooϟ?nvwwHmŋt$ŗЏϒ?]w_~1kS x޼y?t۶0\85 Cmu=q6`q>r*TNs7ߗiS6U*<~5l#a9#˲j!`mXk  A 60l`!`C  A 60l`!`C  A 60l`!`C  A 60l`p]Wǒ4MŋiVq>8??eYSGQ_Bmc1J:>h4ζmJ^~ KPi{ݻw:88PR;+%InHRNJHl6e4`Kzl@a* C%IB<ّt]Y[fIJ>;;;j4 GOu8@y<s`$IdY Py/d0g?')q>aA^L xz ݻSb7_xz dY$ɉ0,wtt$^<]^^2lVr]We)MS%I~^Iuu||,IH{{{jyHR$z8^K TVKmz=]\\zgwW,޲ 45nӭVkjbp8}w4 ~SZ+:<<\M! 4_д,Kv[I!cSk)48lVZ{eMMֶeYkJ<,8 Tk۶Blj:se[mpx ]ם ]OV?ͺw^8ǑacR 43>Mߺ;&I(Jp5Y2JRX9ن8/cF)MTQ)~v{-fܾ=[KX&^HiN}h`ŶgUp* U.^TqbEdvrr?.NTfd4U*Muk۶o+Uh+ZWKan~nŪgt4eo$ͿWTtzz*4ylΏ}VU d AeYT*$IJǸ-sM/_h4a:==Bh4ʏRܹmɧ.A `*\ Wg*J)t:Sq|Wqb\GQT:n4MkR9J6moUa䏋md<BOV>mmm~~S@g곛t]xB9$o?ru+Vy:sž(,\vVU 3)Ū߻}+|@x=/'`Od)QʼϪ22?䓹)Y[T5Mөϯd̸ kx&CZr~Y9Rfd8oE[k[:48LӔmSS.?W~Y;2}?A l00^Jו+S2]U۝:Y}$ItzdVk-2`0(m&>J$)]Ϋ8&}p VZ}׹^lQVi6Sm۪s8Ks/*VJe^/UF1lN)T\U8s.u]7?4Mg>*mauU\yk޽{wޕ ѨTzpp J(VT ,$ɫ%[Z999i}OOO55eY,˺1̛oF?,˒iJDNG_}-WխUy_Z;Q??iF OIRzjoK?H/Iizm^9Ostxx޽i=/%I$UǎcZ#y':>99XǑmy`<$I+0vgg۶]r~Wz=Wur IDATMp@Z0GC llI5OA eYJD'''SՇ`<]^^"5}Y۳.m[Au]YOV纮KQ>7oZwW,޲ (㱨ZZ8KUǭVKaTjuh40Geu] |e4-YUPGQTKJJ"FeY>;}_v[a{foq=\m^˶mIt:sGߗ}! 4KՃuPnK>8y^ijY*Jizf9uٚmu,kOnUբ6Qۛ smԇmoY']y)tY5kqua)\FQ$ó i_۶gsO$>YR6DQTz]j4uUDz,Knmmͼߋc@fSI(I9#e۶^|9Wd6Z-oj=6׏7 m P$SQK_q0 a0Mߪ04R;\]]]ם $QEkveYy;EJR;ن8/cF)MTQ)~v{-x,R9BbqU|YZ^FPY>_xWf)q07;+tTl6k}g}4MeYYYx?Ol6PLW6@VZxQũRNR)X)N#+ia~ei4u<\;;;h4*jgg'ZV)0m{`gijooT8 -۟܊UϾyЗ$vwwU*4MyWZvVuWYTi2 jfUi ,L7_C,pT*LU qTw)[lsP1tnnWi_Q~gF6moU,0R!p8,Uef7}Q۬_iL`0j'ciZ mNOOKekӬ>;f otá:?0I~ӬkٔL8YV|P@@ު!w}71 #?櫫a~Lyc0𳳳i8K'gX(>뾧gU3n2χg... moo/!d<*-*='=p,VN/GϚBxP2穨Ft]隅DדiEcLTE:994yjSO캮(Ry]kB"c86<q,˲dYVfeYT*y8Y '×JQviݬJYd =oɪE[kSQeY+9Jk ߇~옛5yvfUZߴfcK^w:<<̏jXfsj,ܵm[nWX𺧀^X fƽV>,*YcYVib2bϺl_>%(̂'˶j6]gǛ-[|N 858R![ `0yS}.]ȡG)_8Vz{s0L)~ JT2 C(I'fL^7xHL lm)hu_Ӽfsuus,VFf~t=t^?Ǚ1=+z a8qјyNmkggڟ3d(h4lgMJRZ7IRYFh4-m2jf{rr$I"q亮$Qkd]j,M1$\q]W:?? ``FR (VT g-y)hZ+1i:r1MөDǒòS C|Z󓤣#q_כn=Da/"?cEQWHf&/{ i,'u~?wVb8ΝUaf8ɱeF)x-qx<Χ3M\ݲ,mU*R_fcx?0+u^_`0eY A ,{D}6egg'[^6? ``dSfih}/<EdГ}=Y8+ t:Sy\Yؖ1Mt~I{jJ{W (:l be}yޭL{x<.s*ɱ4$g1y,T]U?yܷ1MSO_^0 UeǖM\2OŃ۷zm}ݲz ˢ0Y[,k!ex<\וa^4jNVfݮ 뺲,KiSNeXTs4˗Iam} @j5'Y\]]) é`pV^_jzk:Y}\i{Y? nHזeuݕ_XڻqjM훅udq6BV8UK [A[^fUFQn{oa_}fs] y'KA?G{s[oQE3Cp8sn^j 8N=qnwq#m{)MSZ-FaW^4MX`ܛy >99Yx x ]\\ȶmz*=SRCɰtx8j{{[mHi4M5MZ{b0$T8+콫{ժ>7 ~D]4]DS!l*xJuݕzMSk ZZNNN:,^YU!ȶmn^[ZwmAd'|R^1\u0 Kh4>k[\x2LT*8Χ\c#U*_'Irg8u~~Z65pV+}=z8)}߶m}vc9;;ApoUOQZYb\׽xmZXvJR~Y^6;;;7vKÖe@Dz,kjZh4$aS|~fW97 J^6}??x=8a^{pp ݗDk@0Ms_sZnmաB4M(o28^xdռc(Vf=FrsQ g999Qך5MSl믿Zcvw_qڶO\|N{YV?F *LtYj5޼y(cy]>M,nWnWʶm+$]OMX緬8eYVv|]˲TT~)N{$+K{...4~_a_qkxX4 4 vU򩁃 (%u' a\RS@cFQZ{6c۶vvvTTVnXՙii6;;;r]w5MNjzgêYU+o~??٨z @iʲ,j8AmyUg߿u y qURIOJ_F4MK:o=k62MSijggGk1[/7;4MK[F7jn ȭٙjV18̂lM؛6M3ߦ(MSGLףHi>-`~C>" Fz2 CϞ=ӳgϔ?귿:~ߗ,K?_x f> tf)u!x(Ͳ,Ipk/} ܉xF# éǑtL,KA(IMTIh4ёXqݖt#CX ?}߳X7`=0,=g۶NOO?|~]\\₎?W6?~|X6$I^˶mI`0Pӹu*#Ud۶LT$ Pnwdža(UUY%IJD~_^of{X:D{{{j o޼Q~JEu]Y_45 Jٶ }4xM r|r?ҲE~moٸknǼyX/;?V29п<8eYr`kkk~~y+X{{1_c+f)˲}n^~Xt-/C?`j4`˲TVnggG+IZR0l6/٧#%9v}u'?^ ø쓓'8?SκoXNGam[v[Vfs";4UTnO⵸b8+/d^|YOZ6dٔ8JDu}*EOOd'IvB,z-[fgvYв.J%{Tek^?)h4tvC^#f0 ԇ,lΫsAPl6:<<|/g){{{3ߓr|r?Ҳ{E{aSﭮdL nǼyX庯2?V29<8ں^.V=[EuCZ{{gVyT-uee|ȟEFz?jF/^JӴ4*m#);$=n@gܝn๘D{3BAMoDXȭͳQGulț 3 Tb_;sr7 F&<%zI:]Ч\|Y,($ysN&vƆT*΀yH@OO?T]o ݽ{WonmmΝ;,j;^8nyy_ߟ HGGG]rYsf97(\Im)Vx\vfg{O>?b 0f3ÝGK3h2J95T*,~/žH$bUMkX,:3b{fеW]7h\z;oҴӮj^~wku.E׳,/N-;h/3]<:]ѯvGgvlIs114ab/Gz.J`=LAԽP!`k>;gA???o;f uj:&mV&vww5Vm6^+~^̌A(z[_~1gf+~\>+C J3o|m0iԻ&/ܺuk*if;2+=K*"H@(ĀZ3NE; Eb8֯~ݰ,(8},8˼x-.~f5zɟ߼K^ièţˤs`Y0|xx8=:;ǽf]6h+߿bӧOvCxy7Kiٶ,4F_~ٶ/̯8eYm_fYVWW%}A Q;??ޞNeY>|:=p^o eٶْɝ4s~]?z{ժH$d.7(ҸP(8ͺRO{=_N7nXL'''FV%x\GGGlYb<,JxM;β3/-z@nVQE)JO" `$&84} ̌\.@7BmrJJVp=>3 |A'?`3pbYVm:|02=F T/^E~ֻf?꣣#=~YՏՑHDDb =6{%_xH$b8L49oy{=ߙLݿ_f2̟V/My}N`#/_O_77J=}|(gEu떳w޽{ Êbm{/Dx}^Z%]릝?gf43;ؾg%yHO| FaL$S ;=;hTs Ͷ{LMg~|]Xk?^:bXχ^52if&ѳgϜ {z7÷ɧѽ4W um08.T;e͹RAuTT*}ft:I 9QٴAI/b.Gvy7a5lfٯe}6_{iWюM}Ǐ/K,Pîp8T*r\.5N%$͏}ݺuKXL|~˻r9e2E"}7mYN{kfu/\NtZ4f}ݻw;;;#eYfw^KQgigOjw=k }7Ţ٬*.]f5;Ba|[1i۶/'|4bgϞiooo(NwiO}9~YJ/ͲZOx~k/4ڱi?l]/-s)_&PR)*x^ZH\.f{yx͟t<99Q2T"A[>3~i,uC';;;* JRF,KJEggg*JdETҝ;w,s]Td۶={|>,smll(:ڶ|>#i' ǝp)W*txxp'I[[[d2JӲ,KpG\.+HȲ,q_:Բ,ٶI/[uvv 5hgg^UU'&Ig&j moo+*\.ѣGT*CTTL&vIs^f|765Mzʼn җJ%mllh}}]x\pXpXm\=Q*N}Ly,ԤSXsBACx<>%iej}}]ssȟ^sB ٯUz^ڕic(~F;=ziQ}n Ra^W?D'''zDWү?gFM''^zivڏ0tUѣG/dܭo$,ƆѨTTDhϏzꪾy'Xm[w!AX@տڍ?=ֿ|Ig^|o-3k7P`R.{ Nx+EQP<88P"f^hTLvxjuuه(0޽KHZ__WRmۊD"~\=yr J<W$mzP`!e})˲,b1U*)=$5%w%5`ӵ7%I~zꓮϼ|o0, $ K0, $ K0, $ K0, $ K0, $ K0, $ K0, $ K0, $oӮR;L&SrH8ٱSyXF\LǏuzzxS,NeYD"$(HfYqݹs@ DQiye|%ռT4͆ɺA<~ 5n6ԼєKz! *T)tΫ߿RテA]j߭}TS JaET]k }^NNNl6Bs x1 ,3jUXL:>>v֖>S}*J$ bY4 #3/O{9"ܔ$hWĚ7'랾[5vϗ}XS=YWPVAC_uw} >|}Z r>?CE"e22 }Fia*HhssS[[[$999oѨΘ ͆4!p_I C < (}L.>PvCjZ)R>*tz3{wku)xݮRVz/+C. fJ}W x0XbjyǏ_ZhTLYT*i[RݻJae2\Me y|uuUtZd ۶B\.loo+Nݻ*Jd2Jmi3}ɤRѨ"lV>֫YӶѣG=e4j/1L&'(RP(hL_7q7JyXve?7U__}~߮aMҋVr:ZMդ՝U7 <(i+zuݏNFfy` eZS[6o4[}\rӤVWfC:f{v SA捦^>yIHWJOǟxpJ/5d\Ϸ!5n~KPP2T2ufp8R=ZK[ZeK>/e~``ݺuKRko ӹm[gggD"J$J$J&8鴲٬lۖmۊbJ&Fz@s(9ZTdYs<*vwwDfv"1ikY,F3`e۶,dr |8;}sͱXLtZxOMQW]z'''L5shZ2n%=gqmUfQF_>[_/% '-#r@3 IDAT٬,r|sX,X,D"ܿQs7]zIϏs0`(yԯzQâ+|PF}>iN{--\OUOx 6ka:tx߿RテsZvy)]s7z_M]\\,}WV`yn>̞ <H_훪bpC{ڙl52녆Rkp}uk֜mKF)&]NI&Z]]U,so6UTZeK>iwyk9 ``Ia% eY/jUmh49J>xfٶihYֆz`ufnmmHRbm[w:WZ]]uks\כۙLe?E"mlluvRTϷՓɤlΎp8}թr{DQȶfQx=O|^{{{`'%NOw=joolTr:xkFR4ukzzg^ߴѸG܇b(Dz8t~Ӿ~(*G /hƩ?/s>|{>f=N&*6jsVy.㦋)q#3,(үzw f_McLVM@2]ʟV_Z >W.=]ku>:8Y}/핯8׋.eS,+WΩqw⋿oxЕ?^qγyy{EL›kl^)ߙ?g.HY\ä,Ѹi}Z_/R4 VKJ%gI f7t4?43eEy9"_sMphlq7w1]m֧Y"X4K$yO^:P>wσ Z3vhaf9zO oǝ~"L?82?OZٯ# qvvtz"z}٥u7a3MCj?7UQ,zͽOϛ_o^svvsZxyx\Nt}6_] ܰ(g@ag}o޽;w99Am^k:AзARrѽ=ׯ9asLY__Ut@=|1S7WMO}/lc_7w5wEFpe~K@Kdggk5F4՝;w|;V<w~7?-/."FmAard2b:>>VTRXԳg|_Jĝ5KYǏzy^,amۊD",3^%dqY%۶}oQ8eoVȏQA/X,Rt-^NeL#=}}~.,G^/֏2JܛJssq@wN+=1J>e?d߬eȟӬϼ.B2j|pu%yٿh Լl7kv~LW/3Y%ak[ =WrFS?mޞoo${˰53H>ySl.S,S*ZMO/yk~fE9^8T*)LoyNsW00h>x)~QKx59_}7{X{&?\: WM~WSZpV>o}\kxNvVm~2L?8oyor,˲GQg/h4\mۺ{ժH$d.x~~=):o[귿Hf !wϲӑ><<iϭi?iׯ8AdPP6meoyYߢCPpNwEIEn(Gq^˭eeˬ=bˠflZz!P%]=(tuoڣyxꪷV x/+OR7K8eϥA]mVテjմ!˖ ;$m%_u+NPy >x}}IӾf捦7]zkklr{nm+@^׻\oazzϙ~_L6'xvsG>L6}okeZl6;{rYGGGs玳_TU4=̀( y=O=s>FQmMe|,KI,H$b냧G{iC>o[,/.J,}T0/{.{~>x-~QK@8Lw>>̢2oQe礘%#My׍zoۣy~0:7n6T.]o-]k9浦f[ڷ^fk= v{9%|>ă'JZ'޹|}9ɟ`ײeIw JRz F"KŢ$uDW"hp8Ͷn2dc2TRq/8k3d2myw]9`=P/?2]F_{mYM#xm)~'./9K8L*N_Lb{{-_q9ͪ<̲2ϯt)wÖq'1̊׍ ;(ܮLCz3 ;|TVuPAC7? Qʓ'+0%\]wγڞk-8z%kT[uTם tg`=bkqZS^UafZ_W[)f6uE7/j f{(^&/h֦'">wگ[qiQ,gϴY,H$CٶJ/,D]V|5Zl6{9D;?GGkggGJJ]gѣG,KdR=`/)N޽{Z__w2r]o{9OIɤlv3Oly>o.3l۶/ u5='x-\NLFHD|lV8V$¦,7X,̟LQE^ۇiE,G/^ڇqʭK'''J&J$:88ٙsLi_nR,7|v<νݴì!^J}ݻwz7^RvC?s+|ٺ`M?Zk 93k+pE_6ո<{|2zjuBG ^x דv~.&_t?s$!OjnqMW:4=3e,&6^u6n3NbO,4Ksm*JrC=ommi{{[x|L-e2igɱR#e% Yx<>rCkwwWwq~s*Ѩ,R,sގTgT*iccC òm[GGG?P((J9YTtvvRq?ޞ*ɤ,r:x_|Uݯj[]s;wտ/Z3K$z/o߸ 5Mde`8<;W[3oyj !'eӹwAO}t[W}ޚe{C@͌ZywȡӐ.E5}V>}T{v+OVv+^{ɥFהb8β_H6'1IJ>O=_|!۶fU`$5%w%5C4*~ߐ hl֝;wH`e2eY.of۾;om:>qM+OV VA^vwwL&uݹY~`տڍ?=ֿ|Ig^|Sxe 48::md2]{玷sO޷ʟ[(>޻x͆}'*L=:# (1h4ծe25`0oh-ҸP{ӎ2+Z\ךYOFۆ=VWW}}kIJZ__WRmۊD"~a\4+VO )< ]WkZ&]VGSwB߇G^TB`Dd۶=zDё,R,SRٙrNNNH ceEj{V BV }~:x;$5%w%5`ӵ7%I~zꓮϼ|o0, $ K0, $ K0, $ K0, $ K0, $ K0, $ K0, $ K0, $VHcYb-0w K@RIrYF{&`syssS$ `4, fFNeY*lVPP.SZXpXtZkkk×kuuUd9p8,IV*Jrβnx\>$Emmm)J)N=?iO>U$ٙ>Ӂ===mXd2fmD"D"bFXhT𿻗+ټ3Z?ߺuc`,=~3>|&*x8j:WZ:Ah4p8,˲& gr `,J﫫 "v=սmRU,|iW0teY+kYVWWs#I=^ONNggg~R,_XK 4JR6mVj-Ad;źl4VWWgp )Jӧ:>>V<={-3޸gк`x[ѣGz֞:;;SZu%v:e's",j;cQ IDAT ٠BZ*YXLlTRI~ifDDO? V*egX,&|r?0oRb1%\/r-DH$L&L&ۖ=??N޵XDRm߱,93ŶO ɽۮsgB_IZYa20ۿ!͞JE?I=ҫW~/~+ ???W.SZU8;Cwy9??k_|Z*~_wޑmr4g˲_q믿9}*Ozw$I80=?%Z6iF{IٹO?'/IR?ӿMgjHjJһKJ*~ߐw_ݸ)IcWt}˗~%8R7eX$qeYU*vP&Ç%I;;;:??'Q I\.+k/# @R}K@ K0, [:==U<_k;>>i)mg\;L``XLzjVMTR\$EQYE }Yt:-۶GnRm:??'!֖ϻJ&vzGI܇x8|+5n7>}ܚQˇk|<H[ 5>hzWwuB߷7}20: jtp}" ,|>|>h4Am vsyssSd0''':99!!@~\iln?.+I|H' nv]_qw5 ): 5< vn qMd]+Ya0c``X2d]R+:J m4P^W5ml>BZyrDfGQiqY,Y(|=f8V:ښeZ]]U2tTVU*;ÇZ3mmm)J)N=?4iY.L{b~_+_VWW}VhⳋKPnH^/͢RѾs8z{0q˶mٶX,d2h4{ =˲d2{^A H$H$X,h4_FE"b1\^;O)8섚P#0Nίm:;;S$Q"P"P28PNf/:88P$qeÇĥ𮮮}|6|spgYͼ\U*i<z !:zÏ}ԶKeHsMfg2gF,s7N7iI G5gF./my@Wx N65d/> 5c5xl 6n6t.ZA̵e޶W-(Z[ukZ]ٽ{ 0{^vOz!9镯WWӒtтAZmfюyh9kM0s0Z\\Nbm-;oOښd 8677vvv: bd2 D"h4vfAp8cgGz 4nmmuzQϿe޽{J&};2'ԕL^ٙ3PmΛ~:??oY~Ó|o>sb]z y v.S*tttt=J95Rl)˾~5L='wvSyԃpE<&u}ivZѣGz/`|ޙҙGMPoT?Qx̢H$b3Ki?Kץw?7ټtf񺃿RkI+__QWu5n7w T]%5fgIZSRȡCjMpWw@pԽjTP>ПCgܗIS7_/J4vmetzo~܇Qy$ 0nA8,3a>;ն]rٷ}wқHwCN``>md2vwwf\6bf :^3 fK繻,Oh$6b8J3o.}t Qrw֭0(eѬ ESyԃjUJyk(?v{;M>n>FQ*Ke6yg1lPt{ثxF)GԻ\NLFXL*J*zoe2hh[]9hi8zk=h֖Zye2J%e&q}id$v۶{sr2t(,˒m۾(_ݏtߚfzNSZ :NcߴMssz= W ~]dx7>,WrL\捦?v^Sof3wP02ӐBou]׋ޯ{{rՋ2ٝldNP/M[l"qۿi=qFy`>غF>\کĵL&>y^essT*V}YJ^Anf?4aio4l2lmxU\NXLT Oj$~h˴_=&ws܉כ}h T# =w]3]z}4ymmFkAk:|C!5ZKC >kCB}\ڃy4'Eݎ-{}6}84'}yL ˅0CߖxĂsrwj˯U*ݿ_bͧOE":/kh4_k;M,jH6U˲ME|/:eZ,=AժH$dz.5t>jzHGGGNy0K~iٶ,v&}dpfGL+ fJ$ êVNdK^/Gä<紸k_W5ÕָfʟVml^~g^$<~ ? > Sg&YNyƍF׬Z iIPvC|חy}|mi=_{mox0`#1N׫s+wu*GqZfzs~c+ m.Y%6z?&_gggX;yN7+ /,~ֻfˣ#=~Y:ҏfU Le|ܿ_fβ|Ke1Bj֪{* ִM<@f6Kunٙgmq&efa+Sf l |c*IZ@$[ Џ|ݒ韼_U.ӭ>ʮuqs}ei>8]}|iY~q g0AjsՎMLLhppP~_;w۷t:500`냌>/Y~ubokll\v=3J#Yg&%jgkn~O{g>K̀몿]?=ӋClLQj,Ke˹9Mݕf {MkW*̴Tr^*=˵/ )% Oؘc}+Ckkk\vܼd/O?X}Ғn[9'vƼ刈:,Z`t z<^Eah6PrE9˟ &*S-|ԸNrNؗL˘n5? Ȯ|OAsj^{-b|n[9߿?%s >>4lyԤ3gĉJt^WNSH$\Vdc{v hv^ZlrבaSSSg[%i ˿aLnkvlLuIKL<뛵5M umddYWbYv2 x{Rؠʾ*\s~jzyٔZzdR61;gk+_ӳXH$ c$Iv8jjjRWWmیtGGUWWN8E/^tuuK船5/].W̶t%b7zщ'[\.D3n@^oq;5tttT춶6G. E‘8mmm1^ De9{Zw(N3囘P(d>tλjjjzfGNB9=fGߟR奻[pXGmmm9MtyСC:s挹GUGGG\9N'n)g;@ )˥gnll99sF[VFgzppl~"Y!vK:בV;vLHDqPX>@{Xگ[fu/g|3Kg좁˒;%Zq@h}3phiQtod*t/Oc,ٲv_lMg9?rܓ1ݕ*+湤A;%*eZnY:=͙ߌ9wEpEL`v3Ϙh_%iϦ7F,lr^f;f=Xi@&14>|؜Gpēăq`0h>}hLSbU{{:::̋lرcڹsc};i~Ą흶Vr``@:t萙w.KNSZZZu>S===z4N3&_Yztt,R(g[x<444snI6Toot:(t.dz{{tA˙[n{{-yrUL`0p B9d= ϛ!2<<Ό G@ ..VgVq\x~6D"}|ӉiyP`0fo8Vwww޵Vdc{vc__:/nZ~ziG5ga`'irj[S%cSCϭV/\ѿB6s]siR:VizNu{miu+~B3f5=6+^kZ}wf7jnuo>ɦNNVJ~|O3&\cwE n̶^-3t{ƚK₼ `'yoWhFYMCo=nd#h_َu>}J,|2i+I+W ȗ Ǐ׽{~6֩S.6o,߯7o&ӕ+Wp8r#H._SN?7ov\}>cI_D>|xc5.X֭[QgKLoo&&&p8TVV2s{|򉺻gߙP0Ժun:)WoF\'Sb.92r)ݽ{,++oF|nݪ͛71Z1.oFPHtʕEw~8bvk͒O>,Oy5c13ºu<|9i`0M6 ޮP(g}6롇2?~XW\Y2H:<N^z%aP0T{{; pQ$ѓO>I3ԴLk+t4ժU G4U$I} >355eYg'1$,lz5smvӬf}I kv!eN# XUoYU}5swWhH0. W^/$;v|+qk]!0@8s挜Nᰂ>L(k3@<$EP@ E0Pd߯G1Df/I 1 9Q[n=zTz$Z֣B9/A+׉'t3?Ϝ9S].nw+&=h8_}^ryFy))o$ 仁"rt((rp8*׫gyzT7?<`A&OBvСCp8p8l (bB(2HDpXEsL0AG(\.S ;`z[ɻp8P($I ,^uvvrd?*Ãp=QN@9yNpX}}}In[NSpX`PǏOZ~3M\."BO>)W^ࠚb~3TWc#>Ѳf%vip8ބyQy<+jkk:;;4Ǐ1=q\.x ܹS---r\Jl%=W;4?TS.jmm@̴vR^OdK_~_D"z'~7]?Y#y900d>(%j9}V_J%=ss|V7Ň0P$p9PSS<pܺrn إּxUwwwEgssD/߯p8vpU@@mmmq7=V0K566iр?/ө{555% je? 47Qo.󯵵5a93nf~QBƓHiAiZכƳE7Ͷ=h`%2F7eڷZ^4o^oUn[GHĶNtʋ_ѱrsN[_tLe?餧4Gix<e`G>d)GÇ\wю`GVg<_B!~/ym="**T˧be+=퐍?9CC.Y^i\݇jKgۿt/PXxqPZZZt:500s}a6tfMq٩H$3›Dir1r1'n @{VIKK;vƔS~Ei۸{] FuCN9+I2; yf϶L}3;::^^担ӄ-w+~NLLrnZZZDllg])6vZ8FlkkS[[97zb#p"ݫ_|QЋ/{|9f޽{u8p@O?N766L=Cfs?GLp;O<񄺻uyg/#|.zPڣB8ׇx]ǣ?cg^nZR>s.閗l]2}}Nm6 ~:,Wꗲ)v:(K}'̸=h,sdQ+CCCI;/5K1F-u300Nitm}'gt E"d=O2hx}#n&088H$"O,_'ɼILqitK|7 ;8s)Q<~"߭g -өuttHx㍼,rەbcG}O5m 03eyXh P(^tرc11g\~NLLĴ Z;w@b h۫fy<8qBUFGvѣG~Ƹ8_zu߼^nw̾/r~%Ҙ-gX$IѼpMdlp8p \|ߞZO~,zr\hGyIoλoQ3n%=Ǐt_/[XJ/W620]Z/z4L2#+<&le^sUkkNɧVv|Xv+ #0 nw'vtId#=,wٺrzBv9}x6_J٪GvP| ݻW---ڹs~yie\,;%/XƸhqZt9=t3Ebg;}^;ƓV Nӎ@Yۋ)x sii^KwYSUs̗ :tכ΁nsJc?V策\K&ˋ]陭sKc+\\܇g_ʮTzB/0Ugg:;;͛@ ˥C駟^T.G;Čcǎ$1S&-Wi|/MA gb7˹9MOZͿBٞOjll4ߘ].K>Ub?nZ[[mmmڻwo^`ەB+٪PH.+&]mmm3,ߡEq2mu?^yi<GBQ(3#xxtInsJr׫Ǐ1ձVg%WUٺ?R*9~R(ӴcKe)((^u?GSqgt:ؘQ]F'e`0>v=1iu?NVϸIK6e3vw'[;g5 e{?88(߯;wr:|(/,Wt8溿֦`ەBnFtp\i8}[;sppP:~̩@Ai |fL^__/+izA9y<a[cRZ>.Q.R)B_*KٮG>>@*% b<zrOԔ3ؘ9{ iZx< o25r(*әpvDyetvE"EGxeE[vny˜9h䲼XJeX=ծXm.>dG_a3l'3-%aGsZ'̻gP=,iLxz |iW}U.ru]}NCP˃Ԏ/eGR>)ԅbss.@^jW4?-S$Qcc͎n~k;vLtСMá&uuu%Qz17JCmmm洆vM eu?GGGͧe[[[Ffభ-7N1p8~IK[r0/2Tc{~_H,vey*y"O߯@ H$b0ںhC6yЮvJM{ٮ h3:ȣ;9;F}.K===:zե3gΨG---9f2:tΜ9c~ѣH~#}>=J|,[knߣR XVLjYO|ڑ.,/HB^rcW>d>dP˃ЎY헲)ۿlB1&Pww<koot\jmm:`0hv u#ޮsmH$"%ӹ H0?/ǣ'NÇi{zzcN566СCq믫\/ЎNb+)I773 TV}}<> ŕLL900V3dt -9eB qu6tvl/[=/#O窼#y"۬gmm^{5.WPHǎSKK:::/4jWҩVx=::jQɾiˊF;OOcz…"H^[N{:g8_Mcc0rs{_eyӮtfyFz;!!GR^/eGR><>@" !Ѹ5.Ng̅1vr#b2v3088{E^WCCpXǏ_rd$8p@mmmzKvROMMMqF" ippМVg777+rpڅB!566rږFVsttT{Ukk^\.9b.7VobbLSoxa *A?~|YLHD~?&Kw{_9gj\tI\I[}fjjo0XcmL=i H`$M k:::T[[kYk:@# zr: :|0y0<3$|I>5H"A`(H"A`(H"A`(H"A`(H"A`(H"A`(H"A`(H"$;q\.W:p@VIGWGG$)'zg(g3ADC~_N8>BHbppPPHv̔z9΢Mb?> \! $=]BrZ)IŁxny^\.E"aWlСC8p@MMM pXo9oWW~Q1|9ܹ3f:y{r\OI`0gS^Ǘ gΜА^|E?k쳑30jmmyttv\.)mrtСCqtEkǣ^:.fQ(Rcc|rF9 _\.גtDА&&&p8xb> @6D4886:::ba`` fGmmmINS~L Y^:Ǘ-fz֚λa AD"joo nܹ3cۏD":p@(LÇoKKb#F~LW^1-z4WwwwҠfTSƹw IDAT ;Nܹiu{V/.Kzcǎitt4fp8QHjӷg{F{6KIvژ@RwwwHP(8[۴cZ@̱?~\H|=BǏ7=88!utٵ|=?xGyH9-v7 d췣G&:xa0Q0ѼƾG5]__3DEtƼN65m&Ekhc[߳k{hbb n9\L |(z G9 e [,@p8b[۵| rr̀1r<0rBW>{*MFEO+I^7˷цAD´=ձ4 aD pziA9荎jhh|rjnnN&LZj}Ӿ>ߍ1ѓ`0D1_G][-Ԥ3gĉiY^vΝ{F-LYq3 S@pa:tHt===Ą9bA蠠$uuu) S#D=˥'N(koo7 ϛCi``@#&ۻčv#HL0Ύr| ttjzm-+ HDPȜ8H$w|)g*F088<520 NQ@B1oll p8`0hn'Zwwwn/K&zv^7h:g9o%iJ}g%ͯt:Dte:uJֽ{~ynݺ@\__\bv\g>rHJz=}*++3ׂ-++K{:u$顇RYY޽˗/ȑ#z7mf, zH6mRYYo9hHD[n5?/-+4?{ۭ͛7K>$Ԕ14$I P ((^WD" " `477СCv(QVHrJR@^+++SYY5<WH#,瞳="ψsيuUcߑ(do~MMMI֭['MH#H0#mmmq:uJ/^$qlk.544Gׯ_趶nݪݻwg5T]] I҅ ti2z[ [W~Z5χ?֧o6qo,߉vRc"~ǒG#'uVߍ{IO&mFFFTVV&IZvC6lؠB.^(ϧ۷kxx؜%g,?>>n֫:ꫯf\ TV]]tԍ7tB(/@u}WTg65پ`P߸!I*ۼYkzJ[d8'/]\^JxKyX:7n?KSieVUWMTgOdCFFגχ$\,f?#[u<@ 6ھ}$?kݻtܹnA#~Smۦˇ֮]:) (Phe&|mM3ok%M^ugX\^U]͛~omMi .i75{J++ߺ^={r >+3p;>񲾓sѿOAvUWWqUUUHņ TWWk׮euam߾][nUFG]VhT х GŕImʷnݚ)YBc|]~l;fwC{9w"ͷͷV7U=λ/k%\>.\KKڳG?&H3O$9cϗ<3M  \I#v1FfrDtUUTTe;S) r!_ŋ> tI!($wu_kz*cSnNיTG߿q & ᇚsGkzJkұb˖M,<=*IyU9-<|*ѿogzwiUM*=o| HO:+ B|1@{<kddDjڵצMfUUUkJ %I /Fo6l ϧ/*zΝ;q{、خ]wyǖ̶^zIUUUz7U__/ϧ*kxx8騹to۶mjhh0u?^?UQQ΄sjhhPuu***O qF!)ݸqCPhAP($-ck]V/r:dSBk֭rݺuK.\Xt?wڥNDQN>>IR]]JN<٩mCCU^^nM(ŋmZө䟝kS.,ymݽ|YWӛo͛USAg7t_)| ^Ŗ- G)_Syϥv`?L|PXwz1(௻{?[nڵkzϋcI])iqnݪ{Nk֬ѭ[TQQ!ۭg} !6ϧݻwZUU%ϗ4]9{N;vPUU]&Iڱcvڥ  Ԕ]fi_xᅤaUTThrrr`Qg}V>O555ҭ[T^^.ۭ|ٿc8mHI3/3mjǎѭ[455޽[@`헗yilWF_WUUYM]]^xa#׮];vؾVʵTj=JfӦM7nļo<\QUUe7xxٳڏL?P}ᇚӺ}RjzlLcc޽w$Ŭk:o~S4=6۷3zg^cD^;wTyV^;{M]ͷRv>|WK<`?~o w]s}߹O |4[NjS_m+ iǎZv6nh,799gjxx8Æ jjjR]]ݢkJرCN2vZ R}}m#l|:{9ܹs֭[UWWIfpnѠv5>>3j\۷oWCCvڥ޸lݺU555wC q-MNNB6lmT^xA \MNMMMZu۶m*//WOOO1mݺ5J:|kתIpΝ;s,۶m[!TY-v_R?+(Y|><_ӧOZ 1Gvdd$fx;_* ~ߘ3֭K/X˗Ň狙nƚ¥G޹_/T3oATGN^1VVk۶p\^7~܎a"Tϧ}׿;vjUI'oܪʵXhkkQ7>}?Ο?7f a5%GFFb"n2_v\g- LMM飏>4ѓΝ瑑sMЅѐRSSS:}&''v>8PUUer߹zjc\_͖rs-׿93$SSSp /.Z?#MNNj||***422ӧOBϟ?r/V˵TJ=2l۶Mmmmjkk/]pANߛɓ'%͏-//7LG? IR՞=_gJ++rEƨ^#;{玤_ovkoweMZSz=zֿJ++u_olѪʵgk$|tט>bݣX7?[C]sIا?|A . 4 KNcdښ5P|rlٖ(]FFFbFΥ{|f)Q>'=mիWc>pRjL\]]mwޕi.y9990͍YGFF,f[oym6t/柕zd^h}ETՋW_gϪB@@MMMZHu2 ZS ״]-[oVJ1 8tFܾmN\dI耶XZ+VVgnsi3me&~-<4ozSqo#?xQ͠3kchKSCCKeJ/@-̶D"\'yڵqTONN& $ FA"c~;QJŋ/^+Wƍi-\g*#0l$g}*Te8ǖnN1Svu} n[wۛymڴ _paYmD>? fn?ْ#w=ų4?U a";Rvy޹'&;z~+}>9Հ{:25Hܯ颟OX>_墿S/k_hOm. |Z2(}vsT#Jgg;Ger?3au -50*** r% JX_󩾾^n\kc||\:/5aߋ1XDk6)rm%R B*++ݻ/Խrͧ?9;wn߾詠K++@񾔹$K韗nGNO?Pt"9UR[J<>S?{\@nݺzkk@JҩSb5wޜOg:BǷT)-jLj֭[:}N> 6hƍjhhPUU{9'?Yzƶ&#={H>Hc-//[-׹:XG[WUUiڵ ҆ !y睔& w/_$}ΤkŇj"TŖ-Zo_Z3;W| O@MD01Ulٲ4ՉܿqLD#{ dʌo,p5wUZ}1 ~Vgq|c9ا6/+T( zD=[|&[c33c1X=>7,MxJehƚik['OJJooŖ-5O/4svF^,h?nO`%%v}g4Ur hx<۷_FqSSgj?QnF"<O\0N X=)JqKڽ{꒎\UUUqFJSxQkGEEʵ>f|͛s`y[:Lԣ7~uAطo߮*ŋVuunnݚ0]`)'B"vJHw/_V՞=f6wߍ1W~n*ۼYw/_֝w%)Vؘ6o˝yUuu-L??/i>(dtpΎogDK5#6n3B\v2[j=T=}>_m۶% ڵF`>㣅m۶}}%).ВyR߾}{Gۭ655e~g1Y^^[K}#-;s۶mںuk\ՙ I1iLykSSSpႤ)uu]]9~MNNNvSOҩVu.΃VꑑF8nm߾]t…q>4/۾}{^1?䥯(|ᇖNfQieD?bw sr΄^op{}B&o:MwWX7c~hddDuuuz]k׮UEEN:%Ϸ蚒x|>***/k||\媨ٳgc֧{?C]KnܸӧO۞;vPCCkŋxTWW{ڵk.\H>w֮]+ۭ{یu1.\P]]nFvVUUAwNP(7r6㘌k>8wUSS_~9&[T}Gjjj [nɓjjj2G/,Ks*JyJ=*//7prrc?׮]~'O_~|>555w)7fȺuΜB՞={MVV.d5 zG6ou-:r&/]˗rzKQ˙Sϧ;aNgmLy]yY^,?N]8ZG{ァm۶AUUUիW߯ׯkӦMƍm |LMMwѮ]T]]rݸqCΝTk׮]ڸqcJܹsڸqTSSq ?ᴩ{ァ۷ٳguŤ`I5GVWW۽v횮^h@* irrR7n\ƨ 6h͚5FFF4444Ԕ}|>3pBƂ|sȈy|>֭[_VڤRolԣ={V6mҚ5kRIpB‡,sUMMvڵ0ZBUe6.S͚͵r+lњ}gcRX'2svW_D0hؘ^SoIs>WK/*<@asOS۶mڱcΞ=_οi@@n[޲G ,c=#ݽ|Y?J++[o4jd_.b lܸQM5>>.ϗ51U.'l#LQd%I o߮P(3xÆ }9'&,ῼuW{R㇨X;G"1$m~~y(ғ0 e[+ЕRTIJsbӌ$k~ٿo/{7֬`R 9= lffhYu3|Y9DZIĝh_*?TΏs GxfS p0ӓ0 m'GhWftW\ /wRxf6z(}q0 mבfϳiVGQQOg#)Fȵ]o)vjp7wȻ[ɛ+RR-5]8=o'%͏~z?c Y+#Csz?'~W E=fF۶s4_*}+m^.}j>-Y?+Q׻+3R|5mi$I r|ZSoFirz_Η\by)K'?soO|lO~tO۶įmˬ>}w*oe3==f&Qf֙wN7K] w\i>뷞QEGtUz;szzNCWzoi=mFeZŏ__ariS1>~N%9YZ?ߏ{gj9v>X-iki#=81(͑.pZ魲VJ.Is!RKTi#)!VVjpIɅBSAN|b&3{HG<~7p}u>8kV;;ٺ?SOnv?F@B/lg?/W 1J4l++THs;Gm>u0օaY&yń8:d[?R;^-:*=Z2}q_O%3>[wWURijaܣnezֵ\hon8~p'}k\V m^|leԲyTX< *Oij^_?ju(;fi8aJ dC7'Z1KO'"Z^^Q;PqGv]r`']|ju^(>쏯@QDwHNל"ńiJYP>wwKOk*U\~KnIl˷yԷwRw1aųfbs{};^p/@/GLzE̛N u39ɋHАΘz*xchׁ\|nٖdk'izԒ$ij%U>way2ΈV 9ӚJ ЯSm8vax#b++NvX,F~xfsס5~-K9ܢyU66 rO >US˦wa݁z硖} }TsIZ]3gPkzꏦ+:3zBW4Vm7q]ҋ Kפ>.=uOcvBCI֮u_㎨Mˉ{omdg}Qc-ʚŀfצf[45ۢ`^}s 嵑qF:!>+)s1ӻSV c_ת3j0)nѲ][?(e_ J?$9ވљZ(,MJ]{e(_[:ԞwwLrblA+؟v ?5x6{C]/}6_{cCqڔ};Ϯ=T4֫hW#s*:Ɨ@k=uǂ_uuO|#FjYNV #عE']@8ȍB<+!|!rue(s띿j㹽-LwFm]0 |'ޖ8fDty(vvfxcG?ﵼb\*on|VvOo?:vvxQ:gn1K9/R$3cA~Rkhήޮ~> t[.?7 oxɮv{NMI5l/~lkXg:ct1a)}w̿s_QYOe=f̺Vg錩Vme 賝]ŋn }U5НWԒS0꺩WKw^L8:[Yբ(JtKho9f#%jW'Ij Ϳ_ZYjE}{xKٌl.o>pF`P^cڝBV:chuܢYo-:Esᵑ1Z2dvj!\錩w4z)yKݟ{ZV7s:ҙmJoyV M}עNP^=1[CO^DZ6OC7'Zuc$yKgCk뙿j_79ݢ5