diff options
Diffstat (limited to 'utils/nsxiv')
35 files changed, 0 insertions, 7242 deletions
diff --git a/utils/nsxiv/.editorconfig b/utils/nsxiv/.editorconfig deleted file mode 100644 index 72b2e5e..0000000 --- a/utils/nsxiv/.editorconfig +++ /dev/null @@ -1,28 +0,0 @@ -# EditorConfig - -# apply to all files -[*] - -# top-most EditorConfig file -root = true - -# Set default charset -charset = utf-8 - -# Indentation -# indent with tabs -indent_style = tab -# same tab size as kernel style -indent_size = 8 - -# no trailing spaces -trim_trailing_whitespace = true - -# line lenght, same as kernel stipulated -max_line_length = 100 - -# all files have a final line -insert_final_newline = true - -# end of line -end_of_line = lf diff --git a/utils/nsxiv/.github/workflows/build.yml b/utils/nsxiv/.github/workflows/build.yml deleted file mode 100644 index 69fcaea..0000000 --- a/utils/nsxiv/.github/workflows/build.yml +++ /dev/null @@ -1,67 +0,0 @@ -name: Build - -on: - push: - branches: [ master ] - pull_request: - branches: [ master ] - -# NOTE: "stable" tcc is too old and fails at linking. instead fetching a recent known working commit. -jobs: - full-build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: dep - run: | - sudo apt-get update - sudo apt-get install libimlib2 libimlib2-dev xserver-xorg-core xserver-xorg-dev \ - libxft2 libxft-dev libexif12 libexif-dev \ - gcc clang git - TCC_SHA="027b8fb9b88fe137447fb8bb1b61079be9702472" - wget "https://github.com/TinyCC/tinycc/archive/${TCC_SHA}.tar.gz" && tar xzf "${TCC_SHA}.tar.gz" - ( cd "tinycc-$TCC_SHA" && ./configure && make && sudo make install; ) - - name: build - run: | - # vanilla flags - CFLAGS="-std=c99 -Wall -pedantic" - # extra flags - CFLAGS+=" -O3 -flto" - CFLAGS+=" -Werror -Wextra -Wshadow -Wvla -Wpointer-arith" - CFLAGS+=" -Wundef -Wstrict-overflow=4 -Wwrite-strings -Wunreachable-code" - CFLAGS+=" -Wbad-function-cast -Wdeclaration-after-statement" - CFLAGS+=" -Wmissing-prototypes -Wstrict-prototypes" - # silence - CFLAGS+=" -Wno-sign-compare -Wno-unused-parameter -Wno-missing-field-initializers" - echo "### GCC BUILD ###" && make clean && make -s CC=gcc CFLAGS="$CFLAGS" LDFLAGS="$CFLAGS" OPT_DEP_DEFAULT=1 - echo "### CLANG BUILD ###" && make clean && make -s CC=clang CFLAGS="$CFLAGS" LDFLAGS="$CFLAGS" OPT_DEP_DEFAULT=1 - echo "### TCC BUILD ###" && make clean && make -s CC=tcc CFLAGS="$CFLAGS" LDFLAGS="$CFLAGS" OPT_DEP_DEFAULT=1 - - minimal-build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: dep - run: | - sudo apt-get update - sudo apt-get install libimlib2 libimlib2-dev xserver-xorg-core xserver-xorg-dev \ - gcc clang git - sudo apt-get remove libxft2 libxft-dev libexif12 libexif-dev - TCC_SHA="027b8fb9b88fe137447fb8bb1b61079be9702472" - wget "https://github.com/TinyCC/tinycc/archive/${TCC_SHA}.tar.gz" && tar xzf "${TCC_SHA}.tar.gz" - ( cd "tinycc-$TCC_SHA" && ./configure && make && sudo make install; ) - - name: build - run: | - # vanilla flags - CFLAGS="-std=c99 -Wall -pedantic" - # extra flags - CFLAGS+=" -O3 -flto" - CFLAGS+=" -Werror -Wextra -Wshadow -Wvla -Wpointer-arith" - CFLAGS+=" -Wundef -Wstrict-overflow=4 -Wwrite-strings -Wunreachable-code" - CFLAGS+=" -Wbad-function-cast -Wdeclaration-after-statement" - CFLAGS+=" -Wmissing-prototypes -Wstrict-prototypes" - # silence - CFLAGS+=" -Wno-sign-compare -Wno-unused-parameter -Wno-missing-field-initializers" - echo "### GCC BUILD ###" && make clean && make -s CC=gcc CFLAGS="$CFLAGS" LDFLAGS="$CFLAGS" OPT_DEP_DEFAULT=0 - echo "### CLANG BUILD ###" && make clean && make -s CC=clang CFLAGS="$CFLAGS" LDFLAGS="$CFLAGS" OPT_DEP_DEFAULT=0 - echo "### TCC BUILD ###" && make clean && make -s CC=tcc CFLAGS="$CFLAGS" LDFLAGS="$CFLAGS" OPT_DEP_DEFAULT=0 diff --git a/utils/nsxiv/.gitignore b/utils/nsxiv/.gitignore deleted file mode 100644 index b0c0928..0000000 --- a/utils/nsxiv/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -config.h -version.h -*.d -*.o -nsxiv -icon/img2data diff --git a/utils/nsxiv/CHANGELOG.md b/utils/nsxiv/CHANGELOG.md deleted file mode 100644 index 96cad92..0000000 --- a/utils/nsxiv/CHANGELOG.md +++ /dev/null @@ -1,285 +0,0 @@ -nsxiv ------ - -**[git](https://github.com/nsxiv/nsxiv.git)** - -Changes will only be documented on stable releases. If you're on git/master then -there may be more changes. Please use `git log` to view them. - -- - - - -**[v29](https://github.com/nsxiv/nsxiv/archive/v29.tar.gz)** -*(March 03, 2022)* - -* Changes: - - * Window title is now customizeable via `win-title`, cli flag `-T` and related - config.h options are removed. See `WINDOW TITLE` section of the manpage for - more info. (#213) - * Imlib2 cache size is now set based on total memory percentage, by default - set to 3%. (#184) - * Removed some non-POSIX extensions in the Makefile. (#225) - -* Added: - - * Ability to customize thumbnail mode mouse-bindings via `config.h`. (#167) - * Option to set statusbar position to top via `config.h`. (#231) - * New keybinding <kbd>z</kbd> to scroll to center. (#203) - -* Fixes: - - * Manpage cleanup: avoid confusing wording and document thumbnail mode - mouse-bindings. (#186) - * Wrong jpeg exif orientation with Imlib2 v1.7.5 (and above). (#188) - * Animation slowdown when zoomed in. (#200) - * Reset statusbar after failed keyhandler. (#191) - * Window title not working on certain WMs. (#234) - * Various compiler warnings. (#197) - -- - - - -**[v28](https://github.com/nsxiv/nsxiv/archive/v28.tar.gz)** -*(December 12, 2021)* - -* Changes: - - * Statusbar made optional via `HAVE_LIBFONTS`. (#95) - * Remove library auto-detection, use `OPT_DEP_DEFAULT` instead. (#71) - * Example scripts will now be installed into `EGPREFIX` - (`$(PREFIX)/share/doc/nsxiv/examples` by default). See README for more - info. (#86) - -* Added: - - * Animated webp support (optional via `HAVE_LIBWEBP`). (#20) - * New mouse-binding <kbd>Ctrl-Button1</kbd> for relative drag. (#117) - * Ability to configure colors and fonts in `config.h`. (#115) - * Ability to configure navigation width area in `config.h`. (#155) - * Ability to customize the set of modifers used when processing keybindings - in `config.h` via `USED_MODMASK`. (#150) - * Ability to configure Imlib2's cache size for better image (re)loading - performance in `config.h`. (#171) - * Cli flag `-0` for sending null-seperated file-list to standard out (`-o`), - and key-handler and recieving null-seperated file-list via stdin (`-i`). - (#68) (#141) (#164) - * Export environment variable `NSXIV_USING_NULL` to key-handler. (#164) - * Embed new nsxiv icon. (#163) - * `make install-icon` to install icons. (#80) (#96) - * `make install-desktop` to install .desktop entry. (#80) (#96) - * `make install-all` to install everything. (#80) (#96) - * Configurable `KEYHANDLER_ABORT` in `config.h`. (#91) (#172) - * Statusbar message upon key-handler activation. (#98) - * Ability to write custom C functions in `config.h` and use them via - keybindings. (#76) - -* Fixes: - - * Not able to use `KEYHANDLER_ABORT` key (<kbd>Escape</kbd> by default) in - regular keybindings. (#91) - * Memory leak related to Xresources. (#134) - * Memory leak in gif loader. (#165) - * Better handle gif colormap and prevent out-of-bound access. (#165) - * Prevent crash when zooming out in very small images. (#178) - * Removed non-POSIX commands and extensions from `Makefile`. (#71) - * Regression where nsxiv wouldn't run on non-TrueColor X server. (#114) - * Wrong comments in `config.h` and description in `manpage`. - (#105) (#106) (#152) - -- - - - -**[v27.1](https://github.com/nsxiv/nsxiv/archive/v27.1.tar.gz)** -*(September 16, 2021)* - -* Fixes: - - * Source tarball failing build ([#66](https://github.com/nsxiv/nsxiv/pull/66)) - -- - - - -**[v27](https://github.com/nsxiv/nsxiv/archive/v27.tar.gz)** -*(September 16, 2021)* - -* Changes: - - * Re-release under the name nsxiv - * Xresources `Sxiv.foreground` and `Sxiv.background` changed - to `Nsxiv.window.foreground` and `Nsxiv.window.background` - * Xresources `Sxiv.font` changed to `Nsxiv.bar.font` - * Rework the build system ([#19](https://github.com/nsxiv/nsxiv/pull/19)). Now by default we'll build - with only optional dependencies that are already installed - -* Added: - - * Fill scale mode ([#2](https://github.com/nsxiv/nsxiv/pull/2)) - * Configurable X window title (via `config.h` and the `-T` flag) ([#23](https://github.com/nsxiv/nsxiv/pull/23)) - * Support custom bar colors via Xresources ([#19](https://github.com/nsxiv/nsxiv/pull/19)) - * Support custom mark color via Xresources ([#51](https://github.com/nsxiv/nsxiv/pull/51)) - * Toggle animation playback with <kbd>Ctrl-a</kbd> ([#33](https://github.com/nsxiv/nsxiv/pull/33)) - * Set `_NET_WM_PID` and `WM_CLIENT_MACHINE` X properties ([#13](https://github.com/nsxiv/nsxiv/pull/13)) - * Set `ICCCM WM manager` hints ([#12](https://github.com/nsxiv/nsxiv/pull/12)) - -* Fixes: - - * Cli flag `-G` not initially setting gamma ([#31](https://github.com/nsxiv/nsxiv/pull/31)) - * Wrong keybinding description in the manpage ([#14](https://github.com/nsxiv/nsxiv/pull/14)) - * .desktop entry not advertising webp support ([#15](https://github.com/nsxiv/nsxiv/pull/15)) - * Prevent crash when embedded into transparent window ([#3](https://github.com/nsxiv/nsxiv/pull/3)) - * Small memory leak ([#57](https://github.com/nsxiv/nsxiv/pull/57)) - * Rare crash when showing some GIFs ([#41](https://github.com/nsxiv/nsxiv/pull/41)) - * Rare event where nsxiv wouldn't close after window being destroyed ([#53](https://github.com/nsxiv/nsxiv/pull/53)) - - -sxiv ----- - -**Stable releases** - -**[v26](https://github.com/nsxiv/nsxiv/archive/v26.tar.gz)** -*(January 16, 2020)* - - * Maintenance release - -**[v25](https://github.com/nsxiv/nsxiv/archive/v25.tar.gz)** -*(January 26, 2019)* - - * Support font fallback for missing glyphs - * Fix busy loop when built without inotify - * Use background/foreground colors from X resource database - -**[v24](https://github.com/nsxiv/nsxiv/archive/v24.tar.gz)** -*(October 27, 2017)* - - * Automatically reload the current image whenever it changes - * Support embedding into other X windows with -e (e.g. tabbed) - * New option -p prevents sxiv from creating cache and temporary files - * Simpler mouse mappings, the most basic features are accessible with the - mouse only (navigate, zoom, pan) - -**[v1.3.2](https://github.com/nsxiv/nsxiv/archive/v1.3.2.tar.gz)** -*(December 20, 2015)* - - * external key handler gets file paths on stdin, not as arguments - * Cache out-of-view thumbnails in the background - * Apply gamma correction to thumbnails - -**[v1.3.1](https://github.com/nsxiv/nsxiv/archive/v1.3.1.tar.gz)** -*(November 16, 2014)* - - * Fixed build error, caused by delayed config.h creation - * Fixed segfault when run with -c - -**[v1.3](https://github.com/nsxiv/nsxiv/archive/v1.3.tar.gz)** -*(October 24, 2014)* - - * Extract thumbnails from EXIF tags (requires libexif) - * Zoomable thumbnails, supported sizes defined in config.h - * Fixed build error with giflib version >= 5.1.0 - -**[v1.2](https://github.com/nsxiv/nsxiv/archive/v1.2.tar.gz)** -*(April 24, 2014)* - - * Added external key handler, called on keys prefixed with `Ctrl-x` - * New keybinding `{`/`}` to change gamma (by AndrĂ¡s Mohari) - * Support for slideshows, enabled with `-S` option & toggled with `s` - * Added application icon (created by 0ion9) - * Checkerboard background for alpha layer - * Option `-o` only prints files marked with `m` key - * Fixed rotation/flipping of multi-frame images (gifs) - -**[v1.1.1](https://github.com/nsxiv/nsxiv/archive/v1.1.1.tar.gz)** -*(June 2, 2013)* - - * Various bug fixes - -**[v1.1](https://github.com/nsxiv/nsxiv/archive/v1.1.tar.gz)** -*(March 30, 2013)* - - * Added status bar on bottom of window with customizable content - * New keyboard shortcuts `\`/`|`: flip image vertically/horizontally - * New keyboard shortcut `Ctrl-6`: go to last/alternate image - * Added own EXIF orientation handling, removed dependency on libexif - * Fixed various bugs - -**[v1.0](https://github.com/nsxiv/nsxiv/archive/v1.0.tar.gz)** -*(October 31, 2011)* - - * Support for multi-frame images & GIF animations - * POSIX compliant (IEEE Std 1003.1-2001) - -**[v0.9](https://github.com/nsxiv/nsxiv/archive/v0.9.tar.gz)** -*(August 17, 2011)* - - * Made key and mouse mappings fully configurable in config.h - * Complete code refactoring - -**[v0.8.2](https://github.com/nsxiv/nsxiv/archive/v0.8.2.tar.gz)** -*(June 29, 2011)* - - * POSIX-compliant Makefile; compiles under NetBSD - -**[v0.8.1](https://github.com/nsxiv/nsxiv/archive/v0.8.1.tar.gz)** -*(May 8, 2011)* - - * Fixed fullscreen under window managers, which are not fully EWMH-compliant - -**[v0.8](https://github.com/nsxiv/nsxiv/archive/v0.8.tar.gz)** -*(April 18, 2011)* - - * Support for thumbnail caching - * Ability to run external commands (e.g. jpegtran, convert) on current image - -**[v0.7](https://github.com/nsxiv/nsxiv/archive/v0.7.tar.gz)** -*(February 26, 2011)* - - * Sort directory entries when using `-r` command line option - * Hide cursor in image mode - * Full functional thumbnail mode, use Return key to switch between image and - thumbnail mode - -**[v0.6](https://github.com/nsxiv/nsxiv/archive/v0.6.tar.gz)** -*(February 16, 2011)* - - * Bug fix: Correctly display filenames with umlauts in window title - * Basic support of thumbnails - -**[v0.5](https://github.com/nsxiv/nsxiv/archive/v0.5.tar.gz)** -*(February 6, 2011)* - - * New command line option: `-r`: open all images in given directories - * New key shortcuts: `w`: resize image to fit into window; `W`: resize window - to fit to image - -**[v0.4](https://github.com/nsxiv/nsxiv/archive/v0.4.tar.gz)** -*(February 1, 2011)* - - * New command line option: `-F`, `-g`: use fixed window dimensions and apply - a given window geometry - * New key shortcut: `r`: reload current image - -**[v0.3.1](https://github.com/nsxiv/nsxiv/archive/v0.3.1.tar.gz)** -*(January 30, 2011)* - - * Bug fix: Do not set setuid bit on executable when using `make install` - * Pan image with mouse while pressing middle mouse button - -**[v0.3](https://github.com/nsxiv/nsxiv/archive/v0.3.tar.gz)** -*(January 29, 2011)* - - * New command line options: `-d`, `-f`, `-p`, `-s`, `-v`, `-w`, `-Z`, `-z` - * More mouse mappings: Go to next/previous image with left/right click, - scroll image with mouse wheel (horizontally if Shift key is pressed), - zoom image with mouse wheel if Ctrl key is pressed - -**[v0.2](https://github.com/nsxiv/nsxiv/archive/v0.2.tar.gz)** -*(January 23, 2011)* - - * Bug fix: Handle window resizes correctly - * New keyboard shortcuts: `g`/`G`: go to first/last image; `[`/`]`: go 10 - images back/forward - * Support for mouse wheel zooming (by Dave Reisner) - * Added fullscreen mode - -**[v0.1](https://github.com/nsxiv/nsxiv/archive/v0.1.tar.gz)** -*(January 21, 2011)* - - * Initial release diff --git a/utils/nsxiv/CONTRIBUTING.md b/utils/nsxiv/CONTRIBUTING.md deleted file mode 100644 index 05331c3..0000000 --- a/utils/nsxiv/CONTRIBUTING.md +++ /dev/null @@ -1,74 +0,0 @@ -Project Scope -------------- - - * Bug fixes and maintenance - * Prioritize extensibility and simplicity - * Do not make the codebase more complex, keep it simple to hack on - * Do not add extra dependency (if we do, add compile time switch to disable it) - * New features may be added if it cannot be achieved (easily) via a shell script, - doesn't break backwards compatibility and doesn't violate any of the above rules. - -Note: Since we aim to be a drop-in replacement for sxiv, we intend to keep all -sxiv's behaviors/features even in cases where removing them would make the -code-base simpler. - - -Contribution Guideline ----------------------- - -When contributing, make sure: - - * Your contribution falls under nsxiv's scope and aim - * You follow the existing code style (see [.editorconfig](.editorconfig)) - * You open the pull request from a new branch, not from master - * To avoid using force pushes, especially for bigger patches. Only use them - when there's merge conflicts. - -If your contribution is not suitable for general use, it will not be included in nsxiv. -For changes that are very much up to preference, such as changing values in config.h, -please do not open a pull request unless you have an objective explanation. - -See the [open issues](https://github.com/nsxiv/nsxiv/issues) to find something -to work on. You can also filter the issues via label: - -* [Good first issue](https://github.com/nsxiv/nsxiv/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22): - (Easy) Issues which do not require much if any experience. -* [Up for grabs](https://github.com/nsxiv/nsxiv/issues?q=is%3Aissue+is%3Aopen+label%3A%22up+for+grabs%22): - (Intermediate) Issues which are free for anyone who wants to pick it up. - Might require some experience. -* [Help wanted](https://github.com/nsxiv/nsxiv/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22): - (Intermediate/Experienced) Issues where we require some help. - -Development workflow for maintainers ------------------------------------- - -If we notice you contributing and/or showing interest in issues/pull requests, -we may invite you to join the nsxiv org as a member. Being a member simply means -you will be able to approve, disapprove and merge pull requests. - -Our workflow regarding pull requests is the following: - - * Code related changes require two approvals, but documentation related - changes (e.g. typo) can be merged with just one. - * Always prefer squashing when merging. In the case a PR makes more than one - significant change, use the "don't squash" tag and rebase instead. - * When merging, make sure the commit message is cleaned up properly so that - it reflects the current intention of the PR. - -For releases, the process is the following: - - * Tag the release with a "vN" tag, where N is the version number. Also set - the commit message and tag description for the release commit to "Release - version N". Make sure to use an annotated tag. - * Update `VERSION` macro in the `Makefile`. - * Update the changelog (`CHANGELOG.md`): - * Include link to the release tarball and add the release date. - * Document only the changes or fixes between releases. Don't document - changes which never made it into a release. - * Use the "Changes" section to document behavior changes since the last - release, the "Added" section for new features, and the "Fixes" section - for fixed bugs or regressions. Include pull request IDs. - -For mundane development related talks which don't warrant their own issue, use -the [general-dev](https://github.com/nsxiv/nsxiv/discussions/119) discussion -thread. diff --git a/utils/nsxiv/LICENSE b/utils/nsxiv/LICENSE deleted file mode 100644 index d159169..0000000 --- a/utils/nsxiv/LICENSE +++ /dev/null @@ -1,339 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - <one line to give the program's name and a brief idea of what it does.> - Copyright (C) <year> <name of author> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - <signature of Ty Coon>, 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. diff --git a/utils/nsxiv/Makefile b/utils/nsxiv/Makefile deleted file mode 100644 index 1e51e69..0000000 --- a/utils/nsxiv/Makefile +++ /dev/null @@ -1,132 +0,0 @@ -include ../../config.mk -.POSIX: - -# nsxiv version -VERSION = 29 - -# PREFIX for install -MANPREFIX = $(PREFIX)/share/man -EGPREFIX = $(PREFIX)/share/doc/nsxiv/examples - -# default value for optional dependencies. 1 = enabled, 0 = disabled -OPT_DEP_DEFAULT = 1 - -# autoreload backend: 1 = inotify, 0 = none -HAVE_INOTIFY = $(OPT_DEP_DEFAULT) - -# optional dependencies, see README for more info -HAVE_LIBFONTS = $(OPT_DEP_DEFAULT) -HAVE_LIBGIF = $(OPT_DEP_DEFAULT) -HAVE_LIBEXIF = $(OPT_DEP_DEFAULT) -HAVE_LIBWEBP = $(OPT_DEP_DEFAULT) - -# CFLAGS, any optimization flags goes here -CFLAGS = -std=c99 -Wall -pedantic - -# icons that will be installed via `make icon` -ICONS = 16x16.png 32x32.png 48x48.png 64x64.png 128x128.png - -inc_fonts_0 = -inc_fonts_1 = -I/usr/include/freetype2 -I$(PREFIX)/include/freetype2 - -CPPFLAGS = -D_XOPEN_SOURCE=700 \ - -DHAVE_LIBGIF=$(HAVE_LIBGIF) -DHAVE_LIBEXIF=$(HAVE_LIBEXIF) \ - -DHAVE_LIBWEBP=$(HAVE_LIBWEBP) -DHAVE_LIBFONTS=$(HAVE_LIBFONTS) \ - -DHAVE_INOTIFY=$(HAVE_INOTIFY) $(inc_fonts_$(HAVE_LIBFONTS)) - -lib_fonts_0 = -lib_fonts_1 = -lXft -lfontconfig -lib_exif_0 = -lib_exif_1 = -lexif -lib_gif_0 = -lib_gif_1 = -lgif -lib_webp_0 = -lib_webp_1 = -lwebpdemux -lwebp - -NSXIV_LDLIBS = -lImlib2 -lX11 \ - $(lib_exif_$(HAVE_LIBEXIF)) $(lib_gif_$(HAVE_LIBGIF)) \ - $(lib_webp_$(HAVE_LIBWEBP)) $(lib_fonts_$(HAVE_LIBFONTS)) - -OBJS = autoreload.o commands.o image.o main.o options.o \ - thumbs.o util.o window.o - -.SUFFIXES: -.SUFFIXES: .c .o - -all: nsxiv -c: clean -nsxiv: $(OBJS) - @echo "LINK $@" - $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LDLIBS) $(NSXIV_LDLIBS) - -.c.o: - @echo "CC $@" - $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $< - -$(OBJS): Makefile nsxiv.h config.h commands.h -options.o: version.h -window.o: icon/data.h - -config.h: - @echo "GEN $@" - cp config.def.h $@ - -version.h: Makefile .git/index - @echo "GEN $@" - v="$$(git describe 2>/dev/null || true)"; \ - echo "#define VERSION \"$${v:-$(VERSION)}\"" >$@ - -.git/index: - -clean: - rm -f *.o nsxiv version.h - -install-all: install install-desktop install-icon - -install-desktop: - @echo "INSTALL nsxiv.desktop" - mkdir -p $(DESTDIR)$(PREFIX)/share/applications - cp nsxiv.desktop $(DESTDIR)$(PREFIX)/share/applications - -install-icon: - @echo "INSTALL icon" - for f in $(ICONS); do \ - dir="$(DESTDIR)$(PREFIX)/share/icons/hicolor/$${f%.png}/apps"; \ - mkdir -p "$$dir"; \ - cp "icon/$$f" "$$dir/nsxiv.png"; \ - chmod 644 "$$dir/nsxiv.png"; \ - done - -uninstall-icon: - @echo "REMOVE icon" - for f in $(ICONS); do \ - dir="$(DESTDIR)$(PREFIX)/share/icons/hicolor/$${f%.png}/apps"; \ - rm -f "$$dir/nsxiv.png"; \ - done - -install: all - @echo "INSTALL bin/nsxiv" - mkdir -p $(DESTDIR)$(PREFIX)/bin - cp nsxiv $(DESTDIR)$(PREFIX)/bin/ - chmod 755 $(DESTDIR)$(PREFIX)/bin/nsxiv - ln -f $(DESTDIR)$(PREFIX)/bin/nsxiv $(DESTDIR)$(PREFIX)/bin/sxiv - @echo "INSTALL nsxiv.1" - mkdir -p $(DESTDIR)$(MANPREFIX)/man1 - sed "s!EGPREFIX!$(EGPREFIX)!g; s!PREFIX!$(PREFIX)!g; s!VERSION!$(VERSION)!g" nsxiv.1 \ - >$(DESTDIR)$(MANPREFIX)/man1/nsxiv.1 - chmod 644 $(DESTDIR)$(MANPREFIX)/man1/nsxiv.1 - @echo "INSTALL share/nsxiv/" - mkdir -p $(DESTDIR)$(EGPREFIX) - cp examples/* $(DESTDIR)$(EGPREFIX) - chmod 755 $(DESTDIR)$(EGPREFIX)/* - -uninstall: uninstall-icon - @echo "REMOVE bin/nsxiv" - rm -f $(DESTDIR)$(PREFIX)/bin/nsxiv - @echo "REMOVE nsxiv.1" - rm -f $(DESTDIR)$(MANPREFIX)/man1/nsxiv.1 - @echo "REMOVE nsxiv.desktop" - rm -f $(DESTDIR)$(PREFIX)/share/applications/nsxiv.desktop - @echo "REMOVE share/nsxiv/" - rm -rf $(DESTDIR)$(EGPREFIX) - diff --git a/utils/nsxiv/README.md b/utils/nsxiv/README.md deleted file mode 100644 index 4857866..0000000 --- a/utils/nsxiv/README.md +++ /dev/null @@ -1,216 +0,0 @@ -[](https://github.com/nsxiv/nsxiv) - -[](https://github.com/nsxiv/nsxiv/tags) -[](https://github.com/nsxiv/nsxiv/blob/master/LICENSE) -[](https://github.com/nsxiv/nsxiv) - -**Neo (or New or Not) Simple (or Small or Suckless) X Image Viewer** --------------------------------------------------------------------- - -nsxiv is a fork of now unmaintained [sxiv](https://github.com/muennich/sxiv) -with the purpose of being a drop-in replacement of sxiv, maintaining it and -adding simple, sensible features. nsxiv is free software licensed under GPLv2 -and aims to be easy to modify and customize. - -Please file a bug report if something does not work as documented or -expected in *this* repository, after making sure you are using the latest -release of nsxiv. Contributions are welcome, see -[CONTRIBUTING.md](CONTRIBUTING.md#Contribution-Guideline) for details. - - -Features --------- - -* Basic image operations, e.g. zooming, panning, rotating -* Customizable key and mouse button mappings (in *config.h*) -* Script-ability via `key-handler` -* Thumbnail mode: grid of selectable previews of all images -* Ability to cache thumbnails for fast re-loading -* Basic support for animated/multi-frame images (GIF/WebP) -* Display image information in status bar -* Customizable window title - - -Screenshots ------------ - -**Image mode: (Default colors)** - - - -**Thumbnail mode: (Custom colors)** - - - - -Installing via package manager ------------------------------- - -<a href="https://repology.org/project/nsxiv/versions"> - <img align="right" width="192" src="https://repology.org/badge/vertical-allrepos/nsxiv.svg"> -</a> - -nsxiv is available on the following distributions/repositories. If you don't see -your distro listed here, either contact your distro's package maintainer or -consider packaging it yourself and adding it to the respective community repo. - -Repos not tracked by repology: - -* Fedora: Enable the copr repo via `dnf copr enable mamg22/nsxiv`. - - -Dependencies ------------- - -nsxiv requires the following software to be installed: - - * Imlib2 - * X11 - -The following dependencies are optional. - - * inotify : Used for auto-reloading images on change. - Disabled via `HAVE_INOTIFY=0` - * libXft, freetype2, fontconfig : Used for the status bar. - Disabled via `HAVE_LIBFONTS=0` - * giflib : Used for animated gif playback. - Disabled via `HAVE_LIBGIF=0`. - * libexif : Used for auto-orientation and exif thumbnails. - Disable via `HAVE_LIBEXIF=0` - * libwebp : Used for animated webp playback. - (NOTE: animated webp also requires Imlib2 v1.7.5 or above) - Disabled via `HAVE_LIBWEBP=0`. - -Please make sure to install the corresponding development packages in case that -you want to build nsxiv on a distribution with separate runtime and development -packages (e.g. \*-dev on Debian). - - -Building --------- - -nsxiv is built using the commands: - - $ make - -You can pass `HAVE_X=0` to `make` to disable an optional dependency. -For example: - - $ make HAVE_LIBEXIF=0 - -will disable `libexif` support. Alternatively they can be disabled via editing -the `Makefile` directly. `OPT_DEP_DEFAULT=0` can be used to disable all -optional dependencies. - -Installing nsxiv: - - # make install - -Installing desktop entry: - - # make install-desktop - -Installing icons: - - # make install-icon - -Installing all of the above: - - # make install-all - -Please note, that these requires root privileges. -By default, nsxiv is installed using the prefix `/usr/local`, so the full path -of the executable will be `/usr/local/bin/nsxiv`, the `.desktop` entry will be -`/usr/local/share/applications/nsxiv.desktop` and the icon path will be -`/usr/local/share/icons/hicolor/{size}/apps/nsxiv.png`. - -You can install nsxiv into a directory of your choice by changing this command to: - - $ make PREFIX="/your/dir" install - -Example scripts are installed using `EGPREFIX` which defaults to -`/usr/local/share/doc/nsxiv/examples`. You can change `EGPREFIX` the same way -you can change `PREFIX` shown above. - -The build-time specific settings of nsxiv can be found in the file *config.h*. -Please check and change them, so that they fit your needs. -If the file *config.h* does not already exist, then you have to create it with -the following command: - - $ make config.h - - -Usage ------ - -Please see man page for information on how to use nsxiv. To do so, execute the -following after the installation: - - $ man nsxiv - - -F.A.Q ------ - -* Can I open remote urls with nsxiv? <br> -Yes, see [nsxiv-url](https://github.com/nsxiv/nsxiv-extra/tree/master/scripts/nsxiv-url) - -* Can I open all the images in a directory? <br> -Yes, see [nsxiv-rifle](https://github.com/nsxiv/nsxiv-extra/tree/master/scripts/nsxiv-rifle) - -* Can I set default arguments for nsxiv? <br> -Yes, see [nsxiv-env](https://github.com/nsxiv/nsxiv-extra/tree/master/scripts/nsxiv-env) - -* Can I pipe images into nsxiv? <br> -Yes, see [nsxiv-pipe](https://github.com/nsxiv/nsxiv-extra/tree/master/scripts/nsxiv-pipe) - -You may also wish to see the [known issues](https://github.com/nsxiv/nsxiv/issues/242). - - -Customization -------------- - -The main method of customizing nsxiv is by setting values for the variables in *config.h*, -or by using Xresources as explained in the manual. If these options are not sufficient, -you may implement your own features by following -[this guide](https://github.com/nsxiv/nsxiv-extra/blob/master/CUSTOMIZATION.md). - -Due to our limited [project scope](CONTRIBUTING.md#Project-Scope), certain features or -customization cannot be merged into nsxiv mainline. Following the spirit of suckless -software, we host the [nsxiv-extra](https://github.com/nsxiv/nsxiv-extra) repo where users -are free to submit whatever patches or scripts they wish. - -If you think your custom features can be beneficial for the general user base and is within -our project scope, please submit it as a pull request on this repository, then we *may* -merge it to mainline. - -Description on how to use or submit patches can be found on -nsxiv-extra's [README](https://github.com/nsxiv/nsxiv-extra). - - -Download --------- - -You can [browse](https://github.com/nsxiv/nsxiv) the source code repository -on GitHub or get a copy using git with the following command: - - $ git clone https://github.com/nsxiv/nsxiv.git - -You can view the changelog [here](CHANGELOG.md) - -Similar projects ----------------- - -If nsxiv isn't able to fit your needs, check out the image viewer section of -**[suckless rocks](https://suckless.org/rocks)** to find other minimal image -viewers to try out. - -Below are a couple other lesser known projects not listed in suckless rocks. - -* [MAGE](https://github.com/explosion-mental/mage) : - A smaller/more-suckless version of sxiv. -* [div](https://github.com/TAAPArthur/div) : - Minimal and extensive, aimed at C devs willing to build their own features. -* [mpv-image-viewer](https://github.com/occivink/mpv-image-viewer) : - Lua script to turn mpv into an image viewer. Supports thumbnails via - [mpv-gallery-view](https://github.com/occivink/mpv-gallery-view). diff --git a/utils/nsxiv/autoreload.c b/utils/nsxiv/autoreload.c deleted file mode 100644 index d51e008..0000000 --- a/utils/nsxiv/autoreload.c +++ /dev/null @@ -1,139 +0,0 @@ -/* Copyright 2017 Max Voit, Bert Muennich - * - * This file is a part of nsxiv. - * - * nsxiv is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, - * or (at your option) any later version. - * - * nsxiv is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with nsxiv. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "nsxiv.h" - -#if HAVE_INOTIFY - -#include <errno.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <sys/inotify.h> - -static union { - char d[4096]; /* aligned buffer */ - struct inotify_event e; -} buf; - -void arl_init(arl_t *arl) -{ - arl->fd = inotify_init1(IN_CLOEXEC | IN_NONBLOCK); - arl->wd_dir = arl->wd_file = -1; - if (arl->fd == -1) - error(0, 0, "Could not initialize inotify, no automatic image reloading"); -} - -CLEANUP void arl_cleanup(arl_t *arl) -{ - if (arl->fd != -1) - close(arl->fd); - free(arl->filename); -} - -static void rm_watch(int fd, int *wd) -{ - if (*wd != -1) { - inotify_rm_watch(fd, *wd); - *wd = -1; - } -} - -static void add_watch(int fd, int *wd, const char *path, uint32_t mask) -{ - *wd = inotify_add_watch(fd, path, mask); - if (*wd == -1) - error(0, errno, "inotify: %s", path); -} - -void arl_setup(arl_t *arl, const char *filepath) -{ - char *base = strrchr(filepath, '/'); - - if (arl->fd == -1) - return; - - rm_watch(arl->fd, &arl->wd_dir); - rm_watch(arl->fd, &arl->wd_file); - - add_watch(arl->fd, &arl->wd_file, filepath, IN_CLOSE_WRITE | IN_DELETE_SELF); - - free(arl->filename); - arl->filename = estrdup(filepath); - - if (base != NULL) { - arl->filename[++base - filepath] = '\0'; - add_watch(arl->fd, &arl->wd_dir, arl->filename, IN_CREATE | IN_MOVED_TO); - strcpy(arl->filename, base); - } -} - -bool arl_handle(arl_t *arl) -{ - bool reload = false; - char *ptr; - const struct inotify_event *e; - - while (true) { - ssize_t len = read(arl->fd, buf.d, sizeof(buf.d)); - - if (len == -1) { - if (errno == EINTR) - continue; - break; - } - for (ptr = buf.d; ptr < buf.d + len; ptr += sizeof(*e) + e->len) { - e = (const struct inotify_event*) ptr; - if (e->wd == arl->wd_file && (e->mask & IN_CLOSE_WRITE)) { - reload = true; - } else if (e->wd == arl->wd_file && (e->mask & IN_DELETE_SELF)) { - rm_watch(arl->fd, &arl->wd_file); - } else if (e->wd == arl->wd_dir && (e->mask & (IN_CREATE | IN_MOVED_TO))) { - if (STREQ(e->name, arl->filename)) - reload = true; - } - } - } - return reload; -} - -#else - -void arl_init(arl_t *arl) -{ - arl->fd = -1; -} - -void arl_cleanup(arl_t *arl) -{ - (void) arl; -} - -void arl_setup(arl_t *arl, const char *filepath) -{ - (void) arl; - (void) filepath; -} - -bool arl_handle(arl_t *arl) -{ - (void) arl; - return false; -} - -#endif /* HAVE_INOTIFY */ diff --git a/utils/nsxiv/commands.c b/utils/nsxiv/commands.c deleted file mode 100644 index 9ee83ec..0000000 --- a/utils/nsxiv/commands.c +++ /dev/null @@ -1,479 +0,0 @@ -/* Copyright 2011-2020 Bert Muennich - * Copyright 2021-2022 nsxiv contributors - * - * This file is a part of nsxiv. - * - * nsxiv is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, - * or (at your option) any later version. - * - * nsxiv is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with nsxiv. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "nsxiv.h" - -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <sys/wait.h> - -#include "commands.h" - -extern img_t img; -extern tns_t tns; -extern win_t win; - -bool cg_quit(arg_t status) -{ - unsigned int i; - - if (options->to_stdout && markcnt > 0) { - for (i = 0; i < filecnt; i++) { - if (files[i].flags & FF_MARK) - printf("%s%c", files[i].name, options->using_null ? '\0' : '\n'); - } - } - exit(status); - return None; /* silence tcc warning */ -} - -bool cg_switch_mode(arg_t _) -{ - if (mode == MODE_IMAGE) { - if (tns.thumbs == NULL) - tns_init(&tns, files, &filecnt, &fileidx, &win); - img_close(&img, false); - reset_timeout(reset_cursor); - if (img.ss.on) { - img.ss.on = false; - reset_timeout(slideshow); - } - tns.dirty = true; - mode = MODE_THUMB; - } else { - load_image(fileidx); - mode = MODE_IMAGE; - } - close_info(); - open_info(); - return true; -} - -bool cg_toggle_fullscreen(arg_t _) -{ - win_toggle_fullscreen(&win); - /* redraw after next ConfigureNotify event */ - set_timeout(redraw, TO_REDRAW_RESIZE, false); - if (mode == MODE_IMAGE) - img.checkpan = img.dirty = true; - else - tns.dirty = true; - return false; -} - -bool cg_toggle_bar(arg_t _) -{ - win_toggle_bar(&win); - if (mode == MODE_IMAGE) { - if (win.bar.h > 0) - open_info(); - else - close_info(); - img.checkpan = img.dirty = true; - } else { - tns.dirty = true; - } - return true; -} - -bool cg_prefix_external(arg_t _) -{ - handle_key_handler(true); - return false; -} - -bool cg_reload_image(arg_t _) -{ - if (mode == MODE_IMAGE) { - load_image(fileidx); - } else { - win_set_cursor(&win, CURSOR_WATCH); - if (!tns_load(&tns, fileidx, true, false)) { - remove_file(fileidx, false); - tns.dirty = true; - } - } - return true; -} - -bool cg_remove_image(arg_t _) -{ - remove_file(fileidx, true); - if (mode == MODE_IMAGE) - load_image(fileidx); - else - tns.dirty = true; - return true; -} - -bool cg_first(arg_t _) -{ - if (mode == MODE_IMAGE && fileidx != 0) { - load_image(0); - return true; - } else if (mode == MODE_THUMB && fileidx != 0) { - fileidx = 0; - tns.dirty = true; - return true; - } else { - return false; - } -} - -bool cg_n_or_last(arg_t _) -{ - int n = prefix != 0 && prefix - 1 < filecnt ? prefix - 1 : filecnt - 1; - - if (mode == MODE_IMAGE && fileidx != n) { - load_image(n); - return true; - } else if (mode == MODE_THUMB && fileidx != n) { - fileidx = n; - tns.dirty = true; - return true; - } else { - return false; - } -} - -bool cg_scroll_screen(arg_t dir) -{ - if (mode == MODE_IMAGE) - return img_pan(&img, dir, -1); - else - return tns_scroll(&tns, dir, true); -} - -bool cg_zoom(arg_t d) -{ - if (mode == MODE_THUMB) - return tns_zoom(&tns, d); - else - return img_zoom(&img, d); -} - -bool cg_toggle_image_mark(arg_t _) -{ - return mark_image(fileidx, !(files[fileidx].flags & FF_MARK)); -} - -bool cg_reverse_marks(arg_t _) -{ - int i; - - for (i = 0; i < filecnt; i++) { - files[i].flags ^= FF_MARK; - markcnt += files[i].flags & FF_MARK ? 1 : -1; - } - if (mode == MODE_THUMB) - tns.dirty = true; - return true; -} - -bool cg_mark_range(arg_t _) -{ - int d = markidx < fileidx ? 1 : -1, end, i; - bool dirty = false, on = !!(files[markidx].flags & FF_MARK); - - for (i = markidx + d, end = fileidx + d; i != end; i += d) - dirty |= mark_image(i, on); - return dirty; -} - -bool cg_unmark_all(arg_t _) -{ - int i; - - for (i = 0; i < filecnt; i++) - files[i].flags &= ~FF_MARK; - markcnt = 0; - if (mode == MODE_THUMB) - tns.dirty = true; - return true; -} - -bool cg_navigate_marked(arg_t n) -{ - int d, i; - int new = fileidx; - - if (prefix > 0) - n *= prefix; - d = n > 0 ? 1 : -1; - for (i = fileidx + d; n != 0 && i >= 0 && i < filecnt; i += d) { - if (files[i].flags & FF_MARK) { - n -= d; - new = i; - } - } - if (new != fileidx) { - if (mode == MODE_IMAGE) { - load_image(new); - } else { - fileidx = new; - tns.dirty = true; - } - return true; - } else { - return false; - } -} - -bool cg_change_gamma(arg_t d) -{ - if (img_change_gamma(&img, d * (prefix > 0 ? prefix : 1))) { - if (mode == MODE_THUMB) - tns.dirty = true; - return true; - } else { - return false; - } -} - -bool ci_navigate(arg_t n) -{ - if (prefix > 0) - n *= prefix; - n += fileidx; - n = MAX(0, MIN(n, filecnt - 1)); - - if (n != fileidx) { - load_image(n); - return true; - } else { - return false; - } -} - -bool ci_cursor_navigate(arg_t _) -{ - return ci_navigate(nav_button() - 1); -} - -bool ci_alternate(arg_t _) -{ - load_image(alternate); - return true; -} - -bool ci_navigate_frame(arg_t d) -{ - if (prefix > 0) - d *= prefix; - return !img.multi.animate && img_frame_navigate(&img, d); -} - -bool ci_toggle_animation(arg_t _) -{ - bool dirty = false; - - if (img.multi.cnt > 0) { - img.multi.animate = !img.multi.animate; - if (img.multi.animate) { - dirty = img_frame_animate(&img); - set_timeout(animate, img.multi.frames[img.multi.sel].delay, true); - } else { - reset_timeout(animate); - } - } - return dirty; -} - -bool ci_scroll(arg_t dir) -{ - return img_pan(&img, dir, prefix); -} - -bool ci_scroll_to_center(arg_t _) -{ - return img_pan_center(&img); -} - -bool ci_scroll_to_edge(arg_t dir) -{ - return img_pan_edge(&img, dir); -} - -bool ci_drag(arg_t drag_mode) -{ - int x, y, ox, oy; - float px, py; - XEvent e; - - if ((int)(img.w * img.zoom) <= win.w && (int)(img.h * img.zoom) <= win.h) - return false; - - win_set_cursor(&win, drag_mode == DRAG_ABSOLUTE ? CURSOR_DRAG_ABSOLUTE : CURSOR_DRAG_RELATIVE); - win_cursor_pos(&win, &x, &y); - ox = x; - oy = y; - - while (true) { - if (drag_mode == DRAG_ABSOLUTE) { - px = MIN(MAX(0.0, x - win.w*0.1), win.w*0.8) / (win.w*0.8) - * (win.w - img.w * img.zoom); - py = MIN(MAX(0.0, y - win.h*0.1), win.h*0.8) / (win.h*0.8) - * (win.h - img.h * img.zoom); - } else { - px = img.x + x - ox; - py = img.y + y - oy; - } - - if (img_pos(&img, px, py)) { - img_render(&img); - win_draw(&win); - } - XMaskEvent(win.env.dpy, - ButtonPressMask | ButtonReleaseMask | PointerMotionMask, &e); - if (e.type == ButtonPress || e.type == ButtonRelease) - break; - while (XCheckTypedEvent(win.env.dpy, MotionNotify, &e)); - ox = x; - oy = y; - x = e.xmotion.x; - y = e.xmotion.y; - } - set_timeout(reset_cursor, TO_CURSOR_HIDE, true); - reset_cursor(); - - return true; -} - -bool ci_set_zoom(arg_t zl) -{ - return img_zoom_to(&img, (prefix ? prefix : zl) / 100.0); -} - -bool ci_fit_to_win(arg_t sm) -{ - return img_fit_win(&img, sm); -} - -bool ci_rotate(arg_t degree) -{ - img_rotate(&img, degree); - return true; -} - -bool ci_flip(arg_t dir) -{ - img_flip(&img, dir); - return true; -} - -bool ci_toggle_antialias(arg_t _) -{ - img_toggle_antialias(&img); - return true; -} - -bool ci_toggle_alpha(arg_t _) -{ - img.alpha = !img.alpha; - img.dirty = true; - return true; -} - -bool ci_slideshow(arg_t _) -{ - if (prefix > 0) { - img.ss.on = true; - img.ss.delay = prefix * 10; - set_timeout(slideshow, img.ss.delay * 100, true); - } else if (img.ss.on) { - img.ss.on = false; - reset_timeout(slideshow); - } else { - img.ss.on = true; - } - return true; -} - -bool ct_move_sel(arg_t dir) -{ - bool dirty = tns_move_selection(&tns, dir, prefix); - if (dirty) { - close_info(); - open_info(); - } - return dirty; -} - -bool ct_reload_all(arg_t _) -{ - tns_free(&tns); - tns_init(&tns, files, &filecnt, &fileidx, &win); - tns.dirty = true; - return true; -} - -bool ct_scroll(arg_t dir) -{ - return tns_scroll(&tns, dir, false); -} - -bool ct_drag_mark_image(arg_t _) -{ - int sel; - - if ((sel = tns_translate(&tns, xbutton_ev->x, xbutton_ev->y)) >= 0) { - XEvent e; - bool on = !(files[sel].flags & FF_MARK); - - while (true) { - if (sel >= 0 && mark_image(sel, on)) - redraw(); - XMaskEvent(win.env.dpy, - ButtonPressMask | ButtonReleaseMask | PointerMotionMask, &e); - if (e.type == ButtonPress || e.type == ButtonRelease) - break; - while (XCheckTypedEvent(win.env.dpy, MotionNotify, &e)); - sel = tns_translate(&tns, e.xbutton.x, e.xbutton.y); - } - } - - return false; -} - -bool ct_select(arg_t _) -{ - int sel; - bool dirty = false; - static Time firstclick; - - if ((sel = tns_translate(&tns, xbutton_ev->x, xbutton_ev->y)) >= 0) { - if (sel != fileidx) { - tns_highlight(&tns, fileidx, false); - tns_highlight(&tns, sel, true); - fileidx = sel; - firstclick = xbutton_ev->time; - dirty = true; - } else if (xbutton_ev->time - firstclick <= TO_DOUBLE_CLICK) { - mode = MODE_IMAGE; - set_timeout(reset_cursor, TO_CURSOR_HIDE, true); - load_image(fileidx); - dirty = true; - } else { - firstclick = xbutton_ev->time; - } - } - - return dirty; -} diff --git a/utils/nsxiv/commands.h b/utils/nsxiv/commands.h deleted file mode 100644 index 74e2638..0000000 --- a/utils/nsxiv/commands.h +++ /dev/null @@ -1,93 +0,0 @@ -#ifndef COMMANDS_H -#define COMMANDS_H -#include <stdbool.h> - -/* global */ -bool cg_change_gamma(arg_t); -bool cg_first(arg_t); -bool cg_mark_range(arg_t); -bool cg_n_or_last(arg_t); -bool cg_navigate_marked(arg_t); -bool cg_prefix_external(arg_t); -bool cg_quit(arg_t); -bool cg_reload_image(arg_t); -bool cg_remove_image(arg_t); -bool cg_reverse_marks(arg_t); -bool cg_scroll_screen(arg_t); -bool cg_switch_mode(arg_t); -bool cg_toggle_bar(arg_t); -bool cg_toggle_fullscreen(arg_t); -bool cg_toggle_image_mark(arg_t); -bool cg_unmark_all(arg_t); -bool cg_zoom(arg_t); -/* image mode */ -bool ci_alternate(arg_t); -bool ci_cursor_navigate(arg_t); -bool ci_drag(arg_t); -bool ci_fit_to_win(arg_t); -bool ci_flip(arg_t); -bool ci_navigate(arg_t); -bool ci_navigate_frame(arg_t); -bool ci_rotate(arg_t); -bool ci_scroll(arg_t); -bool ci_scroll_to_center(arg_t); -bool ci_scroll_to_edge(arg_t); -bool ci_set_zoom(arg_t); -bool ci_slideshow(arg_t); -bool ci_toggle_alpha(arg_t); -bool ci_toggle_animation(arg_t); -bool ci_toggle_antialias(arg_t); -/* thumbnails mode */ -bool ct_move_sel(arg_t); -bool ct_reload_all(arg_t); -bool ct_scroll(arg_t); -bool ct_drag_mark_image(arg_t); -bool ct_select(arg_t); - -#ifdef _MAPPINGS_CONFIG -/* global */ -#define g_change_gamma { cg_change_gamma, MODE_ALL } -#define g_first { cg_first, MODE_ALL } -#define g_mark_range { cg_mark_range, MODE_ALL } -#define g_n_or_last { cg_n_or_last, MODE_ALL } -#define g_navigate_marked { cg_navigate_marked, MODE_ALL } -#define g_prefix_external { cg_prefix_external, MODE_ALL } -#define g_quit { cg_quit, MODE_ALL } -#define g_reload_image { cg_reload_image, MODE_ALL } -#define g_remove_image { cg_remove_image, MODE_ALL } -#define g_reverse_marks { cg_reverse_marks, MODE_ALL } -#define g_scroll_screen { cg_scroll_screen, MODE_ALL } -#define g_switch_mode { cg_switch_mode, MODE_ALL } -#define g_toggle_bar { cg_toggle_bar, MODE_ALL } -#define g_toggle_fullscreen { cg_toggle_fullscreen, MODE_ALL } -#define g_toggle_image_mark { cg_toggle_image_mark, MODE_ALL } -#define g_unmark_all { cg_unmark_all, MODE_ALL } -#define g_zoom { cg_zoom, MODE_ALL } - -/* image mode */ -#define i_alternate { ci_alternate, MODE_IMAGE } -#define i_cursor_navigate { ci_cursor_navigate, MODE_IMAGE } -#define i_drag { ci_drag, MODE_IMAGE } -#define i_fit_to_win { ci_fit_to_win, MODE_IMAGE } -#define i_flip { ci_flip, MODE_IMAGE } -#define i_navigate { ci_navigate, MODE_IMAGE } -#define i_navigate_frame { ci_navigate_frame, MODE_IMAGE } -#define i_rotate { ci_rotate, MODE_IMAGE } -#define i_scroll { ci_scroll, MODE_IMAGE } -#define i_scroll_to_center { ci_scroll_to_center, MODE_IMAGE } -#define i_scroll_to_edge { ci_scroll_to_edge, MODE_IMAGE } -#define i_set_zoom { ci_set_zoom, MODE_IMAGE } -#define i_slideshow { ci_slideshow, MODE_IMAGE } -#define i_toggle_alpha { ci_toggle_alpha, MODE_IMAGE } -#define i_toggle_animation { ci_toggle_animation, MODE_IMAGE } -#define i_toggle_antialias { ci_toggle_antialias, MODE_IMAGE } - -/* thumbnails mode */ -#define t_move_sel { ct_move_sel, MODE_THUMB } -#define t_reload_all { ct_reload_all, MODE_THUMB } -#define t_scroll { ct_scroll, MODE_THUMB } -#define t_drag_mark_image { ct_drag_mark_image, MODE_THUMB } -#define t_select { ct_select, MODE_THUMB } - -#endif /* _MAPPINGS_CONFIG */ -#endif /* COMMANDS_H */ diff --git a/utils/nsxiv/config.def.h b/utils/nsxiv/config.def.h deleted file mode 100644 index 1e102fe..0000000 --- a/utils/nsxiv/config.def.h +++ /dev/null @@ -1,200 +0,0 @@ -#ifdef _WINDOW_CONFIG - -/* default window dimensions (overwritten via -g option): */ -static const int WIN_WIDTH = 800; -static const int WIN_HEIGHT = 600; - -/* colors and font can be overwritten via X resource properties. - * See nsxiv(1), X(7) section Resources and xrdb(1) for more information. - */ -static const char *DEFAULT_WIN_BG = "white"; -static const char *DEFAULT_WIN_FG = "black"; -static const char *DEFAULT_MARK_COLOR = NULL; /* NULL means it will default to window foreground */ -#if HAVE_LIBFONTS -static const char *DEFAULT_BAR_BG = NULL; /* NULL means it will default to window background */ -static const char *DEFAULT_BAR_FG = NULL; /* NULL means it will default to window foreground */ -static const char *DEFAULT_FONT = "monospace-8"; - -/* if true, statusbar appears on top of the window */ -static const bool TOP_STATUSBAR = false; -#endif /* HAVE_LIBFONTS */ - -#endif -#ifdef _IMAGE_CONFIG - -/* levels (in percent) to use when zooming via '-' and '+': - * (first/last value is used as min/max zoom level) - */ -static const float zoom_levels[] = { - 12.5, 25.0, 50.0, 75.0, - 100.0, 150.0, 200.0, 400.0, 800.0 -}; - -/* default slideshow delay (in sec, overwritten via -S option): */ -static const int SLIDESHOW_DELAY = 5; - -/* gamma correction: the user-visible ranges [-GAMMA_RANGE, 0] and - * (0, GAMMA_RANGE] are mapped to the ranges [0, 1], and (1, GAMMA_MAX]. - */ -static const double GAMMA_MAX = 10.0; -static const int GAMMA_RANGE = 32; - -/* command i_scroll pans image 1/PAN_FRACTION of screen width/height */ -static const int PAN_FRACTION = 5; - -/* if false, pixelate images at zoom level != 100%, - * toggled with 'a' key binding - */ -static const bool ANTI_ALIAS = true; - -/* if true, use a checkerboard background for alpha layer, - * toggled with 'A' key binding - */ -static const bool ALPHA_LAYER = false; - -/* percentage of memory to use for imlib2's cache size. - * 3 means use 3% of total memory which is about 245MiB on 8GiB machine. - * 0 or less means disable cache. - * 100 means use all available memory (but not above CACHE_SIZE_LIMIT). - */ -static const int CACHE_SIZE_MEM_PERCENTAGE = 3; /* use 3% of total memory for cache */ -static const int CACHE_SIZE_LIMIT = 256 * 1024 * 1024; /* but not above 256MiB */ -static const int CACHE_SIZE_FALLBACK = 32 * 1024 * 1024; /* fallback to 32MiB if we can't determine total memory */ - -#endif -#ifdef _THUMBS_CONFIG - -/* thumbnail sizes in pixels (width == height): */ -static const int thumb_sizes[] = { 32, 64, 96, 128, 160 }; - -/* thumbnail size at startup, index into thumb_sizes[]: */ -static const int THUMB_SIZE = 3; - -#endif -#ifdef _MAPPINGS_CONFIG - -/* these modifiers will be used when processing keybindings */ -static const unsigned int USED_MODMASK = ShiftMask | ControlMask | Mod1Mask; - -/* abort the keyhandler */ -static const KeySym KEYHANDLER_ABORT = XK_Escape; - -/* keyboard mappings for image and thumbnail mode: */ -static const keymap_t keys[] = { - /* modifiers key function argument */ - { 0, XK_q, g_quit, 0 }, - { 0, XK_Return, g_switch_mode, None }, - { 0, XK_f, g_toggle_fullscreen, None }, - { 0, XK_b, g_toggle_bar, None }, - { ControlMask, XK_x, g_prefix_external, None }, - { 0, XK_g, g_first, None }, - { 0, XK_G, g_n_or_last, None }, - { 0, XK_r, g_reload_image, None }, - { 0, XK_D, g_remove_image, None }, - { ControlMask, XK_h, g_scroll_screen, DIR_LEFT }, - { ControlMask, XK_Left, g_scroll_screen, DIR_LEFT }, - { ControlMask, XK_j, g_scroll_screen, DIR_DOWN }, - { ControlMask, XK_Down, g_scroll_screen, DIR_DOWN }, - { ControlMask, XK_k, g_scroll_screen, DIR_UP }, - { ControlMask, XK_Up, g_scroll_screen, DIR_UP }, - { ControlMask, XK_l, g_scroll_screen, DIR_RIGHT }, - { ControlMask, XK_Right, g_scroll_screen, DIR_RIGHT }, - { 0, XK_plus, g_zoom, +1 }, - { 0, XK_KP_Add, g_zoom, +1 }, - { 0, XK_minus, g_zoom, -1 }, - { 0, XK_KP_Subtract, g_zoom, -1 }, - { 0, XK_m, g_toggle_image_mark, None }, - { 0, XK_M, g_mark_range, None }, - { ControlMask, XK_m, g_reverse_marks, None }, - { ControlMask, XK_u, g_unmark_all, None }, - { 0, XK_N, g_navigate_marked, +1 }, - { 0, XK_P, g_navigate_marked, -1 }, - { 0, XK_braceleft, g_change_gamma, -1 }, - { 0, XK_braceright, g_change_gamma, +1 }, - { ControlMask, XK_g, g_change_gamma, 0 }, - - { 0, XK_h, t_move_sel, DIR_LEFT }, - { 0, XK_Left, t_move_sel, DIR_LEFT }, - { 0, XK_j, t_move_sel, DIR_DOWN }, - { 0, XK_Down, t_move_sel, DIR_DOWN }, - { 0, XK_k, t_move_sel, DIR_UP }, - { 0, XK_Up, t_move_sel, DIR_UP }, - { 0, XK_l, t_move_sel, DIR_RIGHT }, - { 0, XK_Right, t_move_sel, DIR_RIGHT }, - { 0, XK_R, t_reload_all, None }, - - { 0, XK_n, i_navigate, +1 }, - { 0, XK_n, i_scroll_to_edge, DIR_LEFT | DIR_UP }, - { 0, XK_space, i_navigate, +1 }, - { 0, XK_p, i_navigate, -1 }, - { 0, XK_p, i_scroll_to_edge, DIR_LEFT | DIR_UP }, - { 0, XK_BackSpace, i_navigate, -1 }, - { 0, XK_bracketright, i_navigate, +10 }, - { 0, XK_bracketleft, i_navigate, -10 }, - { ControlMask, XK_6, i_alternate, None }, - { ControlMask, XK_n, i_navigate_frame, +1 }, - { ControlMask, XK_p, i_navigate_frame, -1 }, - { ControlMask, XK_space, i_toggle_animation, None }, - { ControlMask, XK_a, i_toggle_animation, None }, - { 0, XK_h, i_scroll, DIR_LEFT }, - { 0, XK_Left, i_scroll, DIR_LEFT }, - { 0, XK_j, i_scroll, DIR_DOWN }, - { 0, XK_Down, i_scroll, DIR_DOWN }, - { 0, XK_k, i_scroll, DIR_UP }, - { 0, XK_Up, i_scroll, DIR_UP }, - { 0, XK_l, i_scroll, DIR_RIGHT }, - { 0, XK_Right, i_scroll, DIR_RIGHT }, - { 0, XK_H, i_scroll_to_edge, DIR_LEFT }, - { 0, XK_J, i_scroll_to_edge, DIR_DOWN }, - { 0, XK_K, i_scroll_to_edge, DIR_UP }, - { 0, XK_L, i_scroll_to_edge, DIR_RIGHT }, - { 0, XK_z, i_scroll_to_center, None }, - { 0, XK_equal, i_set_zoom, 100 }, - { 0, XK_w, i_fit_to_win, SCALE_DOWN }, - { 0, XK_W, i_fit_to_win, SCALE_FIT }, - { 0, XK_F, i_fit_to_win, SCALE_FILL }, - { 0, XK_e, i_fit_to_win, SCALE_WIDTH }, - { 0, XK_E, i_fit_to_win, SCALE_HEIGHT }, - { 0, XK_less, i_rotate, DEGREE_270 }, - { 0, XK_greater, i_rotate, DEGREE_90 }, - { 0, XK_question, i_rotate, DEGREE_180 }, - { 0, XK_bar, i_flip, FLIP_HORIZONTAL }, - { 0, XK_underscore, i_flip, FLIP_VERTICAL }, - { 0, XK_a, i_toggle_antialias, None }, - { 0, XK_A, i_toggle_alpha, None }, - { 0, XK_s, i_slideshow, None }, -}; - -/* mouse button mappings for image mode: */ -static const button_t buttons_img[] = { - /* modifiers button function argument */ - { 0, 1, i_cursor_navigate, None }, - { ControlMask, 1, i_drag, DRAG_RELATIVE }, - { 0, 2, i_drag, DRAG_ABSOLUTE }, - { 0, 3, g_switch_mode, None }, - { 0, 4, g_zoom, +1 }, - { 0, 5, g_zoom, -1 }, -}; - -/* mouse button mappings for thumbnail mode: */ -static const button_t buttons_tns[] = { - /* modifiers button function argument */ - { 0, 1, t_select, None }, - { 0, 3, t_drag_mark_image, None }, - { 0, 4, t_scroll, DIR_UP }, - { 0, 5, t_scroll, DIR_DOWN }, - { ControlMask, 4, g_scroll_screen, DIR_UP }, - { ControlMask, 5, g_scroll_screen, DIR_DOWN }, -}; - -/* true means NAV_WIDTH is relative (33%), false means absolute (33 pixels) */ -static const bool NAV_IS_REL = true; -/* width of navigation area, 0 disables cursor navigation, */ -static const unsigned int NAV_WIDTH = 33; - -/* mouse cursor on left, middle and right part of the window */ -static const cursor_t imgcursor[3] = { - CURSOR_LEFT, CURSOR_ARROW, CURSOR_RIGHT -}; - -#endif diff --git a/utils/nsxiv/examples/image-info b/utils/nsxiv/examples/image-info deleted file mode 100755 index 5f06123..0000000 --- a/utils/nsxiv/examples/image-info +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh - -# Example for $XDG_CONFIG_HOME/nsxiv/exec/image-info -# Called by nsxiv(1) whenever an image gets loaded. -# The output is displayed in nsxiv's status bar. -# Arguments: -# $1: path to image file (as provided by the user) -# $2: image width -# $3: image height -# $4: fully resolved path to the image file - -s=" " # field separator - -exec 2>/dev/null - -filename=$(basename -- "$1") -filesize=$(du -Hh -- "$1" | cut -f 1) -geometry="${2}x${3}" - -echo "${filesize}${s}${geometry}${s}${filename}" - diff --git a/utils/nsxiv/examples/key-handler b/utils/nsxiv/examples/key-handler deleted file mode 100755 index 3fe741d..0000000 --- a/utils/nsxiv/examples/key-handler +++ /dev/null @@ -1,41 +0,0 @@ -#!/bin/sh - -# Example for $XDG_CONFIG_HOME/nsxiv/exec/key-handler -# Called by nsxiv(1) after the external prefix key (C-x by default) is pressed. -# The next key combo is passed as its first argument. Passed via stdin are the -# images to act upon: all marked images, if in thumbnail mode and at least one -# image has been marked, otherwise the current image. nsxiv(1) will block until -# the handler terminates. It then checks which images have been modified and -# reloads them. - -# By default nsxiv(1) will send one image per-line to stdin, however when using -# -0 the image list will be NULL separated and the environment variable -# "$NSXIV_USING_NULL" will be set to 1. - -# The key combo argument has the following form: "[C-][M-][S-]KEY", -# where C/M/S indicate Ctrl/Meta(Alt)/Shift modifier states and KEY is the X -# keysym as listed in /usr/include/X11/keysymdef.h without the "XK_" prefix. -# If KEY has an uppercase equivalent, S-KEY is resolved into it. For instance, -# K replaces S-k and Scedilla replaces S-scedilla, but S-Delete is sent as-is. - -rotate() { - degree="$1" - tr '\n' '\0' | xargs -0 realpath | sort | uniq | while read file; do - case "$(file -b -i "$file")" in - image/jpeg*) jpegtran -rotate "$degree" -copy all -outfile "$file" "$file" ;; - *) mogrify -rotate "$degree" "$file" ;; - esac - done -} - -case "$1" in -"C-x") xclip -in -filter | tr '\n' ' ' | xclip -in -selection clipboard ;; -"C-c") while read file; do xclip -selection clipboard -target image/png "$file"; done ;; -"C-e") while read file; do urxvt -bg "#444" -fg "#eee" -sl 0 -title "$file" -e sh -c "exiv2 pr -q -pa '$file' | less" & done ;; -"C-g") tr '\n' '\0' | xargs -0 gimp & ;; -"C-r") while read file; do rawtherapee "$file" & done ;; -"C-comma") rotate 270 ;; -"C-period") rotate 90 ;; -"C-slash") rotate 180 ;; -esac - diff --git a/utils/nsxiv/examples/thumb-info b/utils/nsxiv/examples/thumb-info deleted file mode 100755 index b422f9c..0000000 --- a/utils/nsxiv/examples/thumb-info +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/sh - -# Example for $XDG_CONFIG_HOME/nsxiv/exec/thumb-info -# Called by nsxiv(1) whenever the selected thumbnail changes. -# The output is displayed in nsxiv's status bar. -# Arguments: -# $1: path to image file (as provided by the user) -# $2: empty -# $3: empty -# $4: fully resolved path to the image file - -s=" " # field separator - -exec 2>/dev/null - -filename=$(basename -- "$4") -filesize=$(du -Hh -- "$4" | cut -f 1) - -echo "${filesize}${s}${filename}" - diff --git a/utils/nsxiv/examples/win-title b/utils/nsxiv/examples/win-title deleted file mode 100755 index ac7b982..0000000 --- a/utils/nsxiv/examples/win-title +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/sh - -# Example for $XDG_CONFIG_HOME/nsxiv/exec/win-title -# Called by nsxiv(1) on each redraw. -# The output is set as nsxiv's window title. -# -# Arguments, "Optional" arguments might be empty: -# $1: resolved absolute path of the current file -# $2: current file number -# $3: total file number -# $4: image width (Optional: Disabled on thumbnails mode) -# $5: image height (Optional: Disabled on thumbnails mode) -# $6: current zoom (Optional: Disabled on thumbnails mode) -# -# The term file is used rather than image as nsxiv does not -# precheck that the input files are valid images. Total file -# count may be different from the actual count of valid images. - -exec 2>/dev/null - -filename="${1##*/}" - -if [ -n "$4" ]; then # image mode - printf "%s" "nsxiv - ${filename} | ${4}x${5} ${6}% [${2}/${3}]" -else - printf "%s" "nsxiv - ${filename} [${2}/${3}]" -fi diff --git a/utils/nsxiv/icon/128x128.png b/utils/nsxiv/icon/128x128.png Binary files differdeleted file mode 100644 index d45250b..0000000 --- a/utils/nsxiv/icon/128x128.png +++ /dev/null diff --git a/utils/nsxiv/icon/16x16.png b/utils/nsxiv/icon/16x16.png Binary files differdeleted file mode 100644 index a19074a..0000000 --- a/utils/nsxiv/icon/16x16.png +++ /dev/null diff --git a/utils/nsxiv/icon/32x32.png b/utils/nsxiv/icon/32x32.png Binary files differdeleted file mode 100644 index e18ccf8..0000000 --- a/utils/nsxiv/icon/32x32.png +++ /dev/null diff --git a/utils/nsxiv/icon/48x48.png b/utils/nsxiv/icon/48x48.png Binary files differdeleted file mode 100644 index 442a96c..0000000 --- a/utils/nsxiv/icon/48x48.png +++ /dev/null diff --git a/utils/nsxiv/icon/64x64.png b/utils/nsxiv/icon/64x64.png Binary files differdeleted file mode 100644 index 3ce0d27..0000000 --- a/utils/nsxiv/icon/64x64.png +++ /dev/null diff --git a/utils/nsxiv/icon/README.md b/utils/nsxiv/icon/README.md deleted file mode 100644 index 3ddd7f8..0000000 --- a/utils/nsxiv/icon/README.md +++ /dev/null @@ -1,43 +0,0 @@ -img2data --------- - -img2data is a helper program to convert images to binary data for embedding in -software. The generated data is used in nsxiv to set the window icons. - - -How It Works ------------- - -Each given image is compressed using run-length encoding and a data array is -generated. In these arrays, the four high bits of each byte are the run length -minus one and the lowest four bits are the data, which are indices for the -color array. - -See `data.gen.h` or the output of img2data for a better understanding. - - -Dependencies ------------- - -img2data requires Imlib2 to be installed. - - -Building --------- - -img2data is built using the command: - - $ CC -Wall -std=c89 -pedantic -lImlib2 img2data.c -o img2data - -where `CC` is a C compiler such as `gcc`. - - -Usage ------ - -img2data is used as the following: - - $ ./img2data 16x16.png 32x32.png 48x48.png 64x64.png 128x128.png - -You may replace or omit any image, but you must have a `data.gen.h` with at -least 1 image for nsxiv to compile. diff --git a/utils/nsxiv/icon/data.gen.h b/utils/nsxiv/icon/data.gen.h deleted file mode 100644 index 0bb7a84..0000000 --- a/utils/nsxiv/icon/data.gen.h +++ /dev/null @@ -1,255 +0,0 @@ -static const unsigned char icon_data_16[] = { - 0xa0, 0x01, 0xe0, 0x01, 0xf0, 0x40, 0x21, 0x00, 0x21, 0x00, 0x01, 0x00, - 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x21, 0x00, 0x21, 0x00, 0x01, 0x00, - 0x01, 0x00, 0x01, 0x02, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x10, - 0x01, 0x10, 0x01, 0x02, 0x01, 0x02, 0x01, 0x00, 0x01, 0x00, 0x21, 0x00, - 0x01, 0x00, 0x51, 0x02, 0x00, 0x01, 0x00, 0x21, 0x00, 0x01, 0x00, 0x51, - 0x02, 0x80, 0x03, 0x52, 0x04, 0x50, 0x43, 0x05, 0x22, 0x14, 0x06, 0x10, - 0x47, 0x35, 0x08, 0x02, 0x14, 0x06, 0x09, 0x22, 0x47, 0x25, 0x08, 0x14, - 0x06, 0x09, 0x32, 0x47, 0x08, 0x05, 0x08, 0x04, 0x16, 0x19, 0x32, 0x47, - 0x18, 0x16, 0x29, 0x32, 0x47, 0x18, 0x16, 0x29, 0x42, 0x47, 0x08, -}; - -static const unsigned char icon_data_32[] = { - 0xf0, 0x40, 0x11, 0xf0, 0xd0, 0x11, 0xf0, 0xd0, 0x11, 0xf0, 0xf0, 0xf0, - 0xf0, 0xf0, 0xf0, 0x90, 0x51, 0x10, 0x51, 0x10, 0x11, 0x10, 0x11, 0x10, - 0x11, 0x10, 0x11, 0x10, 0x51, 0x10, 0x51, 0x10, 0x11, 0x10, 0x11, 0x10, - 0x11, 0x10, 0x11, 0x10, 0x51, 0x10, 0x51, 0x10, 0x11, 0x10, 0x11, 0x10, - 0x11, 0x10, 0x11, 0x02, 0x00, 0x11, 0x10, 0x11, 0x10, 0x11, 0x30, 0x11, - 0x30, 0x11, 0x10, 0x11, 0x12, 0x11, 0x02, 0x00, 0x11, 0x10, 0x11, 0x10, - 0x11, 0x30, 0x11, 0x30, 0x11, 0x10, 0x11, 0x12, 0x11, 0x02, 0x00, 0x11, - 0x10, 0x11, 0x10, 0x11, 0x30, 0x11, 0x30, 0x11, 0x12, 0x11, 0x12, 0x11, - 0x02, 0x00, 0x11, 0x10, 0x51, 0x10, 0x11, 0x10, 0xb1, 0x22, 0x00, 0x11, - 0x10, 0x51, 0x10, 0x11, 0x10, 0xb1, 0x22, 0x00, 0x11, 0x10, 0x51, 0x10, - 0x11, 0x10, 0xb1, 0x22, 0xf0, 0x10, 0xd2, 0xf0, 0x00, 0xe2, 0xf0, 0x53, - 0x92, 0x14, 0xc0, 0x83, 0x05, 0x62, 0x24, 0x06, 0x80, 0x93, 0x35, 0x42, - 0x34, 0x06, 0x02, 0x30, 0x77, 0x95, 0x08, 0x22, 0x34, 0x16, 0x12, 0xc7, - 0x75, 0x08, 0x12, 0x34, 0x16, 0x09, 0x52, 0x97, 0x65, 0x08, 0x02, 0x34, - 0x16, 0x19, 0x62, 0x97, 0x45, 0x18, 0x24, 0x26, 0x19, 0x72, 0x97, 0x08, - 0x25, 0x18, 0x24, 0x26, 0x29, 0x72, 0x97, 0x48, 0x14, 0x36, 0x29, 0x72, - 0x97, 0x48, 0x04, 0x36, 0x39, 0x82, 0x97, 0x38, 0x46, 0x39, 0x82, 0x97, - 0x38, 0x36, 0x59, 0x82, 0x97, 0x28, 0x26, 0x69, 0x82, 0x97, 0x28, 0x26, - 0x69, 0x82, 0x97, 0x28, -}; - -static const unsigned char icon_data_48[] = { - 0xf0, 0xf0, 0x21, 0xf0, 0xf0, 0xc0, 0x21, 0xf0, 0xf0, 0xc0, 0x21, 0xf0, - 0xf0, 0xc0, 0x21, 0xf0, 0xf0, 0xc0, 0x21, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, - 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xe0, 0x81, 0x20, 0x81, 0x20, - 0x21, 0x20, 0x21, 0x20, 0x21, 0x20, 0x21, 0x20, 0x81, 0x20, 0x81, 0x20, - 0x21, 0x20, 0x21, 0x20, 0x21, 0x20, 0x21, 0x20, 0x81, 0x20, 0x81, 0x20, - 0x21, 0x20, 0x21, 0x20, 0x21, 0x20, 0x21, 0x20, 0x81, 0x20, 0x81, 0x20, - 0x21, 0x20, 0x21, 0x20, 0x21, 0x20, 0x21, 0x02, 0x10, 0x81, 0x20, 0x81, - 0x20, 0x21, 0x20, 0x21, 0x20, 0x21, 0x00, 0x0a, 0x02, 0x21, 0x02, 0x10, - 0x21, 0x20, 0x21, 0x20, 0x21, 0x50, 0x21, 0x50, 0x21, 0x20, 0x21, 0x22, - 0x21, 0x02, 0x10, 0x21, 0x20, 0x21, 0x20, 0x21, 0x50, 0x21, 0x50, 0x21, - 0x10, 0x02, 0x21, 0x22, 0x21, 0x02, 0x10, 0x21, 0x20, 0x21, 0x20, 0x21, - 0x50, 0x21, 0x50, 0x21, 0x00, 0x12, 0x21, 0x22, 0x21, 0x02, 0x10, 0x21, - 0x20, 0x21, 0x20, 0x21, 0x50, 0x21, 0x50, 0x21, 0x22, 0x21, 0x22, 0x21, - 0x02, 0x10, 0x21, 0x20, 0x81, 0x20, 0x21, 0x20, 0xf1, 0x11, 0x32, 0x10, - 0x21, 0x20, 0x81, 0x20, 0x21, 0x20, 0xf1, 0x11, 0x32, 0x10, 0x21, 0x20, - 0x81, 0x20, 0x21, 0x20, 0xf1, 0x11, 0x32, 0x10, 0x21, 0x20, 0x81, 0x20, - 0x21, 0x20, 0xf1, 0x11, 0x32, 0x10, 0x21, 0x20, 0x81, 0x20, 0x21, 0x20, - 0xf1, 0x11, 0x32, 0xf0, 0xa0, 0xf2, 0x42, 0xf0, 0x90, 0xf2, 0x52, 0xf0, - 0x90, 0x33, 0xf2, 0x12, 0xf0, 0x70, 0x93, 0xd2, 0x24, 0xf0, 0x20, 0xc3, - 0x15, 0xa2, 0x34, 0xf0, 0x00, 0xd3, 0x35, 0x82, 0x44, 0x06, 0xb0, 0xe3, - 0x75, 0x62, 0x54, 0x16, 0x02, 0x50, 0xb7, 0xe5, 0x08, 0x42, 0x54, 0x16, - 0x09, 0x02, 0x30, 0xe7, 0xd5, 0x08, 0x32, 0x54, 0x26, 0x09, 0x22, 0xf7, - 0x37, 0xa5, 0x18, 0x12, 0x54, 0x26, 0x19, 0x72, 0xf7, 0x85, 0x28, 0x02, - 0x54, 0x26, 0x19, 0x92, 0xe7, 0x85, 0x28, 0x54, 0x26, 0x29, 0xa2, 0xe7, - 0x65, 0x28, 0x44, 0x36, 0x29, 0xb2, 0xe7, 0x18, 0x35, 0x28, 0x44, 0x36, - 0x39, 0xa2, 0xe7, 0x28, 0x15, 0x38, 0x34, 0x46, 0x39, 0xb2, 0xe7, 0x78, - 0x24, 0x56, 0x49, 0xb2, 0xe7, 0x68, 0x14, 0x56, 0x59, 0xb2, 0xe7, 0x68, - 0x04, 0x66, 0x59, 0xc2, 0xe7, 0x58, 0x66, 0x69, 0xc2, 0xe7, 0x58, 0x66, - 0x69, 0xc2, 0xe7, 0x58, 0x56, 0x79, 0xd2, 0xe7, 0x48, 0x46, 0x89, 0xd2, - 0xe7, 0x48, 0x46, 0x89, 0xe2, 0xe7, 0x38, 0x46, 0x89, 0xe2, 0xe7, 0x38, - -}; - -static const unsigned char icon_data_64[] = { - 0xf0, 0xf0, 0x90, 0x31, 0xf0, 0xf0, 0xf0, 0xb0, 0x31, 0xf0, 0xf0, 0xf0, - 0xb0, 0x31, 0xf0, 0xf0, 0xf0, 0xb0, 0x31, 0xf0, 0xf0, 0xf0, 0xb0, 0x31, - 0xf0, 0xf0, 0xf0, 0xb0, 0x31, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, - 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, - 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0x30, 0xb1, 0x30, 0xb1, 0x30, 0x31, - 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0xb1, 0x30, 0xb1, 0x30, 0x31, - 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0xb1, 0x30, 0xb1, 0x30, 0x31, - 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0xb1, 0x30, 0xb1, 0x30, 0x31, - 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0xb1, 0x30, 0xb1, 0x30, 0x31, - 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x00, 0x0b, 0x10, 0xb1, 0x30, 0xb1, - 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x12, 0x10, 0x31, 0x30, - 0x31, 0x30, 0x31, 0x70, 0x31, 0x70, 0x31, 0x30, 0x31, 0x10, 0x12, 0x31, - 0x12, 0x10, 0x31, 0x30, 0x31, 0x30, 0x31, 0x70, 0x31, 0x70, 0x31, 0x30, - 0x31, 0x32, 0x31, 0x12, 0x10, 0x31, 0x30, 0x31, 0x30, 0x31, 0x70, 0x31, - 0x70, 0x31, 0x30, 0x31, 0x32, 0x31, 0x12, 0x10, 0x31, 0x30, 0x31, 0x30, - 0x31, 0x70, 0x31, 0x70, 0x31, 0x20, 0x02, 0x31, 0x32, 0x31, 0x12, 0x10, - 0x31, 0x30, 0x31, 0x30, 0x31, 0x70, 0x31, 0x70, 0x31, 0x00, 0x22, 0x31, - 0x32, 0x31, 0x12, 0x10, 0x31, 0x30, 0x31, 0x30, 0x31, 0x70, 0x31, 0x70, - 0x31, 0x32, 0x31, 0x32, 0x31, 0x12, 0x10, 0x31, 0x30, 0xb1, 0x30, 0x31, - 0x30, 0xf1, 0x71, 0x52, 0x10, 0x31, 0x30, 0xb1, 0x30, 0x31, 0x30, 0xf1, - 0x71, 0x52, 0x10, 0x31, 0x30, 0xb1, 0x30, 0x31, 0x30, 0xf1, 0x71, 0x52, - 0x10, 0x31, 0x30, 0xb1, 0x30, 0x31, 0x30, 0xf1, 0x71, 0x52, 0x10, 0x31, - 0x30, 0xb1, 0x30, 0x31, 0x30, 0xf1, 0x71, 0x52, 0x10, 0x31, 0x30, 0xb1, - 0x30, 0x31, 0x30, 0xf1, 0x71, 0x52, 0xf0, 0xf0, 0x40, 0xf2, 0xa2, 0xf0, - 0xf0, 0x30, 0xf2, 0xb2, 0xf0, 0xf0, 0x20, 0xf2, 0xc2, 0xf0, 0xf0, 0x10, - 0xf2, 0xd2, 0xf0, 0xf0, 0x10, 0x83, 0xf2, 0x42, 0xf0, 0xf0, 0xd3, 0xf2, - 0x12, 0x24, 0xf0, 0xa0, 0xf3, 0x03, 0x15, 0xe2, 0x44, 0xf0, 0x70, 0xf3, - 0x13, 0x35, 0xc2, 0x54, 0x06, 0xf0, 0x40, 0xf3, 0x13, 0x65, 0xa2, 0x64, - 0x16, 0xf0, 0xf3, 0x33, 0x95, 0x82, 0x64, 0x26, 0x02, 0xa0, 0x77, 0xb3, - 0xd5, 0x08, 0x62, 0x74, 0x26, 0x12, 0x60, 0xf7, 0x17, 0xf5, 0x25, 0x08, - 0x52, 0x74, 0x26, 0x09, 0x32, 0xf7, 0x87, 0xf5, 0x05, 0x18, 0x32, 0x74, - 0x36, 0x09, 0x42, 0xf7, 0x97, 0xe5, 0x18, 0x22, 0x74, 0x36, 0x19, 0x92, - 0xf7, 0x57, 0xc5, 0x28, 0x12, 0x74, 0x46, 0x19, 0xb2, 0xf7, 0x47, 0xa5, - 0x38, 0x02, 0x74, 0x46, 0x19, 0xd2, 0xf7, 0x37, 0x08, 0x95, 0x38, 0x74, - 0x46, 0x29, 0xd2, 0xf7, 0x37, 0x08, 0x85, 0x38, 0x64, 0x56, 0x29, 0xe2, - 0xf7, 0x37, 0x18, 0x65, 0x38, 0x64, 0x56, 0x39, 0xe2, 0xf7, 0x37, 0x28, - 0x45, 0x38, 0x54, 0x66, 0x39, 0xf2, 0xf7, 0x37, 0x38, 0x15, 0x48, 0x44, - 0x66, 0x59, 0xf2, 0xf7, 0x37, 0x98, 0x34, 0x76, 0x59, 0xf2, 0xf7, 0x37, - 0x98, 0x24, 0x86, 0x59, 0xf2, 0x02, 0xf7, 0x37, 0x88, 0x14, 0x86, 0x79, - 0xf2, 0xf7, 0x37, 0x88, 0x04, 0x96, 0x79, 0xf2, 0x02, 0xf7, 0x37, 0x78, - 0x96, 0x89, 0xf2, 0x02, 0xf7, 0x37, 0x78, 0x96, 0x89, 0xf2, 0x12, 0xf7, - 0x37, 0x68, 0x86, 0x99, 0xf2, 0x12, 0xf7, 0x37, 0x68, 0x76, 0xa9, 0xf2, - 0x12, 0xf7, 0x37, 0x68, 0x66, 0xb9, 0xf2, 0x22, 0xf7, 0x37, 0x58, 0x66, - 0xb9, 0xf2, 0x22, 0xf7, 0x37, 0x58, 0x56, 0xc9, 0xf2, 0x22, 0xf7, 0x37, - 0x58, 0x56, 0xc9, 0xf2, 0x22, 0xf7, 0x37, 0x58, -}; - -static const unsigned char icon_data_128[] = { - 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0x30, 0x71, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, - 0xf0, 0xf0, 0x70, 0x71, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0x70, - 0x71, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0x70, 0x71, 0xf0, 0xf0, - 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0x70, 0x71, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, - 0xf0, 0xf0, 0x70, 0x71, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0x70, - 0x71, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0x70, 0x71, 0xf0, 0xf0, - 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0x70, 0x71, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, - 0xf0, 0xf0, 0x70, 0x71, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0x70, - 0x71, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0x70, 0x71, 0xf0, 0xf0, - 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, - 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, - 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, - 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, - 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, - 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, - 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, - 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, - 0x70, 0xf1, 0x71, 0x70, 0xf1, 0x71, 0x70, 0x71, 0x70, 0x71, 0x70, 0x71, - 0x70, 0x71, 0x70, 0xf1, 0x71, 0x70, 0xf1, 0x71, 0x70, 0x71, 0x70, 0x71, - 0x70, 0x71, 0x70, 0x71, 0x70, 0xf1, 0x71, 0x70, 0xf1, 0x71, 0x70, 0x71, - 0x70, 0x71, 0x70, 0x71, 0x70, 0x71, 0x70, 0xf1, 0x71, 0x70, 0xf1, 0x71, - 0x70, 0x71, 0x70, 0x71, 0x70, 0x71, 0x70, 0x71, 0x70, 0xf1, 0x71, 0x70, - 0xf1, 0x71, 0x70, 0x71, 0x70, 0x71, 0x70, 0x71, 0x70, 0x71, 0x70, 0xf1, - 0x71, 0x70, 0xf1, 0x71, 0x70, 0x71, 0x70, 0x71, 0x70, 0x71, 0x70, 0x71, - 0x70, 0xf1, 0x71, 0x70, 0xf1, 0x71, 0x70, 0x71, 0x70, 0x71, 0x70, 0x71, - 0x70, 0x71, 0x70, 0xf1, 0x71, 0x70, 0xf1, 0x71, 0x70, 0x71, 0x70, 0x71, - 0x70, 0x71, 0x70, 0x71, 0x70, 0xf1, 0x71, 0x70, 0xf1, 0x71, 0x70, 0x71, - 0x70, 0x71, 0x70, 0x71, 0x70, 0x71, 0x10, 0x0b, 0x0a, 0x30, 0xf1, 0x71, - 0x70, 0xf1, 0x71, 0x70, 0x71, 0x70, 0x71, 0x70, 0x71, 0x70, 0x71, 0x32, - 0x30, 0xf1, 0x71, 0x70, 0xf1, 0x71, 0x70, 0x71, 0x70, 0x71, 0x70, 0x71, - 0x70, 0x71, 0x32, 0x30, 0xf1, 0x71, 0x70, 0xf1, 0x71, 0x70, 0x71, 0x70, - 0x71, 0x70, 0x71, 0x40, 0x0a, 0x12, 0x71, 0x32, 0x30, 0x71, 0x70, 0x71, - 0x70, 0x71, 0xf0, 0x71, 0xf0, 0x71, 0x70, 0x71, 0x20, 0x42, 0x71, 0x32, - 0x30, 0x71, 0x70, 0x71, 0x70, 0x71, 0xf0, 0x71, 0xf0, 0x71, 0x70, 0x71, - 0x00, 0x62, 0x71, 0x32, 0x30, 0x71, 0x70, 0x71, 0x70, 0x71, 0xf0, 0x71, - 0xf0, 0x71, 0x70, 0x71, 0x72, 0x71, 0x32, 0x30, 0x71, 0x70, 0x71, 0x70, - 0x71, 0xf0, 0x71, 0xf0, 0x71, 0x70, 0x71, 0x72, 0x71, 0x32, 0x30, 0x71, - 0x70, 0x71, 0x70, 0x71, 0xf0, 0x71, 0xf0, 0x71, 0x70, 0x71, 0x72, 0x71, - 0x32, 0x30, 0x71, 0x70, 0x71, 0x70, 0x71, 0xf0, 0x71, 0xf0, 0x71, 0x60, - 0x02, 0x71, 0x72, 0x71, 0x32, 0x30, 0x71, 0x70, 0x71, 0x70, 0x71, 0xf0, - 0x71, 0xf0, 0x71, 0x40, 0x22, 0x71, 0x72, 0x71, 0x32, 0x30, 0x71, 0x70, - 0x71, 0x70, 0x71, 0xf0, 0x71, 0xf0, 0x71, 0x20, 0x42, 0x71, 0x72, 0x71, - 0x32, 0x30, 0x71, 0x70, 0x71, 0x70, 0x71, 0xf0, 0x71, 0xf0, 0x71, 0x00, - 0x62, 0x71, 0x72, 0x71, 0x32, 0x30, 0x71, 0x70, 0x71, 0x70, 0x71, 0xf0, - 0x71, 0xf0, 0x71, 0x72, 0x71, 0x72, 0x71, 0x32, 0x30, 0x71, 0x70, 0x71, - 0x70, 0x71, 0xf0, 0x71, 0xf0, 0x71, 0x72, 0x71, 0x72, 0x71, 0x32, 0x30, - 0x71, 0x70, 0x71, 0x70, 0x71, 0xf0, 0x71, 0xf0, 0x71, 0x72, 0x71, 0x72, - 0x71, 0x32, 0x30, 0x71, 0x70, 0xf1, 0x71, 0x70, 0x71, 0x70, 0xf1, 0xf1, - 0xf1, 0xb2, 0x30, 0x71, 0x70, 0xf1, 0x71, 0x70, 0x71, 0x70, 0xf1, 0xf1, - 0xf1, 0xb2, 0x30, 0x71, 0x70, 0xf1, 0x71, 0x70, 0x71, 0x70, 0xf1, 0xf1, - 0xf1, 0xb2, 0x30, 0x71, 0x70, 0xf1, 0x71, 0x70, 0x71, 0x70, 0xf1, 0xf1, - 0xf1, 0xb2, 0x30, 0x71, 0x70, 0xf1, 0x71, 0x70, 0x71, 0x70, 0xf1, 0xf1, - 0xf1, 0xb2, 0x30, 0x71, 0x70, 0xf1, 0x71, 0x70, 0x71, 0x70, 0xf1, 0xf1, - 0xf1, 0xb2, 0x30, 0x71, 0x70, 0xf1, 0x71, 0x70, 0x71, 0x70, 0xf1, 0xf1, - 0xf1, 0xb2, 0x30, 0x71, 0x70, 0xf1, 0x71, 0x70, 0x71, 0x70, 0xf1, 0xf1, - 0xf1, 0xb2, 0x30, 0x71, 0x70, 0xf1, 0x71, 0x70, 0x71, 0x70, 0xf1, 0xf1, - 0xf1, 0xb2, 0x30, 0x71, 0x70, 0xf1, 0x71, 0x70, 0x71, 0x70, 0xf1, 0xf1, - 0xf1, 0xb2, 0x30, 0x71, 0x70, 0xf1, 0x71, 0x70, 0x71, 0x70, 0xf1, 0xf1, - 0xf1, 0xb2, 0x30, 0x71, 0x70, 0xf1, 0x71, 0x70, 0x71, 0x70, 0xf1, 0xf1, - 0xf1, 0xb2, 0xf0, 0xf0, 0xf0, 0xf0, 0x90, 0xf2, 0xf2, 0xf2, 0x52, 0xf0, - 0xf0, 0xf0, 0xf0, 0x80, 0xf2, 0xf2, 0xf2, 0x62, 0xf0, 0xf0, 0xf0, 0xf0, - 0x70, 0xf2, 0xf2, 0xf2, 0x72, 0xf0, 0xf0, 0xf0, 0xf0, 0x60, 0xf2, 0xf2, - 0xf2, 0x82, 0xf0, 0xf0, 0xf0, 0xf0, 0x50, 0xf2, 0xf2, 0xf2, 0x92, 0xf0, - 0xf0, 0xf0, 0xf0, 0x40, 0xf2, 0xf2, 0xf2, 0xa2, 0xf0, 0xf0, 0xf0, 0xf0, - 0x30, 0xf2, 0xf2, 0xf2, 0xb2, 0xf0, 0xf0, 0xf0, 0xf0, 0x30, 0x12, 0xa3, - 0xf2, 0xf2, 0xe2, 0xf0, 0xf0, 0xf0, 0xf0, 0x20, 0xf3, 0x13, 0xf2, 0xf2, - 0xa2, 0xf0, 0xf0, 0xf0, 0xf0, 0x00, 0xf3, 0x63, 0xf2, 0xf2, 0x72, 0xf0, - 0xf0, 0xf0, 0xe0, 0xf3, 0xb3, 0xf2, 0xf2, 0x42, 0xf0, 0xf0, 0xf0, 0xd0, - 0xf3, 0xd3, 0x15, 0xf2, 0xf2, 0x12, 0x44, 0xf0, 0xf0, 0xf0, 0x60, 0xf3, - 0xf3, 0x03, 0x35, 0xf2, 0xe2, 0x64, 0xf0, 0xf0, 0xf0, 0x30, 0xf3, 0xf3, - 0x23, 0x45, 0xf2, 0xc2, 0x84, 0xf0, 0xf0, 0xf0, 0x00, 0xf3, 0xf3, 0x33, - 0x65, 0xf2, 0xa2, 0x94, 0xf0, 0xf0, 0xe0, 0xf3, 0xf3, 0x33, 0x95, 0xf2, - 0x82, 0xa4, 0x16, 0xf0, 0xf0, 0x90, 0xf3, 0xf3, 0x43, 0xc5, 0xf2, 0x62, - 0xb4, 0x26, 0xf0, 0xf0, 0x40, 0xf3, 0xf3, 0x63, 0xf5, 0xf2, 0x42, 0xc4, - 0x36, 0xf0, 0xf0, 0xf3, 0xf3, 0x73, 0xf5, 0x35, 0xf2, 0x22, 0xd4, 0x46, - 0xf0, 0xa0, 0xf3, 0xf3, 0x83, 0xf5, 0x75, 0xf2, 0x02, 0xd4, 0x56, 0x02, - 0xf0, 0x50, 0xf7, 0x07, 0xf3, 0x73, 0xf5, 0xb5, 0x08, 0xe2, 0xe4, 0x56, - 0x12, 0xf0, 0x10, 0xf7, 0xd7, 0xf5, 0xf5, 0x95, 0x18, 0xc2, 0xe4, 0x56, - 0x09, 0x22, 0xd0, 0xf7, 0xf7, 0x37, 0xf5, 0xf5, 0x65, 0x18, 0xb2, 0xf4, - 0x56, 0x09, 0x32, 0x80, 0xf7, 0xf7, 0x97, 0xf5, 0xf5, 0x45, 0x18, 0xa2, - 0xf4, 0x56, 0x19, 0x72, 0xf7, 0xf7, 0xf7, 0x07, 0xf5, 0xf5, 0x25, 0x28, - 0x82, 0xf4, 0x66, 0x19, 0x72, 0xf7, 0xf7, 0xf7, 0x27, 0xf5, 0xf5, 0x05, - 0x38, 0x62, 0xf4, 0x66, 0x29, 0x82, 0xf7, 0xf7, 0xf7, 0x37, 0xf5, 0xd5, - 0x48, 0x52, 0xf4, 0x76, 0x29, 0xc2, 0xf7, 0xf7, 0xf7, 0x07, 0xf5, 0xb5, - 0x58, 0x42, 0xf4, 0x76, 0x39, 0xf2, 0x22, 0xf7, 0xf7, 0xb7, 0xf5, 0xa5, - 0x58, 0x32, 0xf4, 0x76, 0x49, 0xf2, 0x52, 0xf7, 0xf7, 0x97, 0xf5, 0x85, - 0x68, 0x22, 0xf4, 0x86, 0x39, 0xf2, 0x72, 0xf7, 0xf7, 0x97, 0xf5, 0x65, - 0x78, 0x12, 0xf4, 0x86, 0x49, 0xf2, 0x82, 0xf7, 0xf7, 0x97, 0xf5, 0x55, - 0x78, 0x02, 0xf4, 0x86, 0x49, 0xf2, 0xa2, 0xf7, 0xf7, 0x87, 0x08, 0xf5, - 0x35, 0x88, 0xe4, 0x96, 0x59, 0xf2, 0xb2, 0xf7, 0xf7, 0x77, 0x08, 0xf5, - 0x25, 0x88, 0xe4, 0x96, 0x59, 0xf2, 0xc2, 0xf7, 0xf7, 0x77, 0x18, 0xf5, - 0x05, 0x88, 0xd4, 0xa6, 0x69, 0xf2, 0xc2, 0xf7, 0xf7, 0x77, 0x28, 0xf5, - 0x78, 0xd4, 0xa6, 0x69, 0xf2, 0xd2, 0xf7, 0xf7, 0x77, 0x38, 0xd5, 0x78, - 0xc4, 0xb6, 0x79, 0xf2, 0xd2, 0xf7, 0xf7, 0x77, 0x48, 0xa5, 0x88, 0xc4, - 0xb6, 0x79, 0xf2, 0xe2, 0xf7, 0xf7, 0x77, 0x58, 0x85, 0x88, 0xb4, 0xc6, - 0x89, 0xf2, 0xe2, 0xf7, 0xf7, 0x77, 0x68, 0x55, 0x98, 0xb4, 0xc6, 0x89, - 0xf2, 0xf2, 0xf7, 0xf7, 0x77, 0x78, 0x25, 0xa8, 0xa4, 0xc6, 0xa9, 0xf2, - 0xf2, 0xf7, 0xf7, 0x77, 0xf8, 0x48, 0x94, 0xd6, 0xa9, 0xf2, 0xf2, 0xf7, - 0xf7, 0x77, 0xf8, 0x48, 0x84, 0xe6, 0xb9, 0xf2, 0xf2, 0xf7, 0xf7, 0x77, - 0xf8, 0x38, 0x74, 0xf6, 0xb9, 0xf2, 0xf2, 0xf7, 0xf7, 0x77, 0xf8, 0x38, - 0x64, 0xf6, 0xc9, 0xf2, 0xf2, 0x02, 0xf7, 0xf7, 0x77, 0xf8, 0x28, 0x54, - 0xf6, 0x06, 0xc9, 0xf2, 0xf2, 0x02, 0xf7, 0xf7, 0x77, 0xf8, 0x28, 0x44, - 0xf6, 0x06, 0xe9, 0xf2, 0xf2, 0x02, 0xf7, 0xf7, 0x77, 0xf8, 0x18, 0x34, - 0xf6, 0x16, 0xe9, 0xf2, 0xf2, 0x02, 0xf7, 0xf7, 0x77, 0xf8, 0x18, 0x24, - 0xf6, 0x16, 0xf9, 0xf2, 0xf2, 0x12, 0xf7, 0xf7, 0x77, 0xf8, 0x08, 0x14, - 0xf6, 0x26, 0xf9, 0xf2, 0xf2, 0x12, 0xf7, 0xf7, 0x77, 0xf8, 0x08, 0x04, - 0xf6, 0x26, 0xf9, 0x09, 0xf2, 0xf2, 0x22, 0xf7, 0xf7, 0x77, 0xf8, 0xf6, - 0x36, 0xf9, 0x09, 0xf2, 0xf2, 0x22, 0xf7, 0xf7, 0x77, 0xf8, 0xf6, 0x26, - 0xf9, 0x19, 0xf2, 0xf2, 0x22, 0xf7, 0xf7, 0x77, 0xf8, 0xf6, 0x26, 0xf9, - 0x19, 0xf2, 0xf2, 0x32, 0xf7, 0xf7, 0x77, 0xe8, 0xf6, 0x16, 0xf9, 0x29, - 0xf2, 0xf2, 0x32, 0xf7, 0xf7, 0x77, 0xe8, 0xf6, 0x06, 0xf9, 0x39, 0xf2, - 0xf2, 0x32, 0xf7, 0xf7, 0x77, 0xe8, 0xf6, 0xf9, 0x59, 0xf2, 0xf2, 0x32, - 0xf7, 0xf7, 0x77, 0xd8, 0xe6, 0xf9, 0x69, 0xf2, 0xf2, 0x32, 0xf7, 0xf7, - 0x77, 0xd8, 0xd6, 0xf9, 0x79, 0xf2, 0xf2, 0x32, 0xf7, 0xf7, 0x77, 0xd8, - 0xd6, 0xf9, 0x79, 0xf2, 0xf2, 0x42, 0xf7, 0xf7, 0x77, 0xc8, 0xc6, 0xf9, - 0x89, 0xf2, 0xf2, 0x42, 0xf7, 0xf7, 0x77, 0xc8, 0xc6, 0xf9, 0x89, 0xf2, - 0xf2, 0x42, 0xf7, 0xf7, 0x77, 0xc8, 0xb6, 0xf9, 0x99, 0xf2, 0xf2, 0x52, - 0xf7, 0xf7, 0x77, 0xb8, 0xb6, 0xf9, 0x99, 0xf2, 0xf2, 0x52, 0xf7, 0xf7, - 0x77, 0xb8, 0xb6, 0xf9, 0x99, 0xf2, 0xf2, 0x52, 0xf7, 0xf7, 0x77, 0xb8, - 0xb6, 0xf9, 0x99, 0xf2, 0xf2, 0x52, 0xf7, 0xf7, 0x77, 0xb8, 0xb6, 0xf9, - 0x99, 0xf2, 0xf2, 0x52, 0xf7, 0xf7, 0x77, 0xb8, -}; - -static const unsigned long icon_colors[] = { - 0xff222034, 0xffffffff, 0xff306082, 0xfffbf236, - 0xff76428a, 0xff99e550, 0xffac3232, 0xff37946e, - 0xff6abe30, 0xffd95763, 0xff26324a, 0xff23253a, - -}; - -static const icon_data_t icons[] = { - ICON_(16), - ICON_(32), - ICON_(48), - ICON_(64), - ICON_(128), -}; - diff --git a/utils/nsxiv/icon/data.h b/utils/nsxiv/icon/data.h deleted file mode 100644 index 98ac5f3..0000000 --- a/utils/nsxiv/icon/data.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef ICON_DATA_H -#define ICON_DATA_H - -typedef struct { - unsigned int size; - unsigned int cnt; - const unsigned char *data; -} icon_data_t; - -#define ICON_(s) { s, ARRLEN(icon_data_##s), icon_data_##s } - -#include "data.gen.h" - -#endif /* ICON_DATA_H */ diff --git a/utils/nsxiv/icon/img2data.c b/utils/nsxiv/icon/img2data.c deleted file mode 100644 index 2223bf0..0000000 --- a/utils/nsxiv/icon/img2data.c +++ /dev/null @@ -1,157 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <stdarg.h> -#include <string.h> -#include <Imlib2.h> - -/* macros */ -#define ARRLEN(a) (sizeof(a) / sizeof((a)[0])) - -/* globals */ -static unsigned long palette[16] = {0}; -static unsigned int palette_size = 0; -static unsigned int run_column = 0; -static unsigned int icon_sizes[16] = {0}; -static unsigned int icon_sizes_size = 0; - -/* functions */ -static void error(int eval, int err, const char *fmt, ...) -{ - va_list ap; - - fflush(stdout); - va_start(ap, fmt); - if (fmt) - vfprintf(stderr, fmt, ap); - va_end(ap); - if (err) - fprintf(stderr, "%s%s", fmt ? ": " : "", strerror(err)); - fputc('\n', stderr); - - if (eval) - exit(eval); -} - -static unsigned long color_to_ulong(Imlib_Color color) -{ - return (color.alpha << 24 & 0xff000000) | - (color.red << 16 & 0x00ff0000) | - (color.green << 8 & 0x0000ff00) | - (color.blue & 0x000000ff); -} - -static int to_palette(unsigned long color) -{ - unsigned int i; - - for (i = 0; i < palette_size; i++) { - if (palette[i] == color) - return i; - } - if (palette_size + 1 == 16) - error(EXIT_FAILURE, 0, "Error: More than 16 colors in palette"); - palette[palette_size] = color; - - return palette_size++; -} - -static void print_run(int color, unsigned int run_length) -{ - while (run_length > 0) { - int x = run_length / 16 >= 1 ? 16 : run_length; - - printf("0x%02x, ", (x - 1) << 4 | color); - run_length -= x; - if (++run_column % 12 == 0) - printf("\n\t"); - } -} - -static void print_palette(void) -{ - unsigned int i; - - printf("static const unsigned long icon_colors[] = {\n\t"); - for (i = 0; i < palette_size; i++) { - printf("0x%08lx, ", palette[i]); - if (i % 4 == 3) - printf("\n\t"); - } - printf("\n};\n\n"); -} - -static void print_icon_array(void) -{ - unsigned int i; - - printf("static const icon_data_t icons[] = {\n"); - for (i = 0; i < icon_sizes_size; i++) - printf("\tICON_(%d),\n", icon_sizes[i]); - printf("};\n\n"); -} - -static unsigned int print_encoded_image(const char *path) -{ - Imlib_Image image; - Imlib_Color color; - unsigned int width, height, x, y; - unsigned int run_length = 1; - int currentcolor = 0; - int lastcolor = -1; - - image = imlib_load_image(path); - - if (image == NULL) - error(EXIT_FAILURE, 0, "Error loading image: %s", path); - - imlib_context_set_image(image); - - width = imlib_image_get_width(); - height = imlib_image_get_height(); - - if (width != height) - error(EXIT_FAILURE, 0, "Image is not square: %s", path); - - printf("static const unsigned char icon_data_%d[] = {\n\t", width); - for (y = 0; y < height; y++) { - for (x = 0; x < width; x++) { - imlib_image_query_pixel(x, y, &color); - currentcolor = to_palette(color_to_ulong(color)); - if (currentcolor != lastcolor) { - if (lastcolor != -1) - print_run(lastcolor, run_length); - run_length = 1; - } else { - run_length++; - } - lastcolor = currentcolor; - } - } - print_run(lastcolor, run_length); - printf("\n};\n\n"); - - imlib_free_image(); - - return width; -} - -int main(int argc, char **argv) -{ - unsigned int img_size = 0; - unsigned int i; - - if (argc < 2) - error(EXIT_FAILURE, 0, "No icons provided"); - else if (argc-1 > ARRLEN(icon_sizes)) - error(EXIT_FAILURE, 0, "Too many icons"); - - for (i = 1; i < argc; i++) { - img_size = print_encoded_image(argv[i]); - run_column = 0; - icon_sizes[icon_sizes_size++] = img_size; - } - print_palette(); - print_icon_array(); - - return EXIT_SUCCESS; -} diff --git a/utils/nsxiv/image.c b/utils/nsxiv/image.c deleted file mode 100644 index 2904887..0000000 --- a/utils/nsxiv/image.c +++ /dev/null @@ -1,912 +0,0 @@ -/* Copyright 2011-2020 Bert Muennich - * Copyright 2021-2022 nsxiv contributors - * - * This file is a part of nsxiv. - * - * nsxiv is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, - * or (at your option) any later version. - * - * nsxiv is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with nsxiv. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "nsxiv.h" -#define _IMAGE_CONFIG -#include "config.h" - -#include <errno.h> -#include <stdlib.h> -#include <string.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <unistd.h> - -#if HAVE_LIBEXIF -#include <libexif/exif-data.h> -#endif - -#if HAVE_LIBGIF -#include <gif_lib.h> -enum { DEF_GIF_DELAY = 75 }; -#endif - -#if HAVE_LIBWEBP -#include <webp/decode.h> -#include <webp/demux.h> -enum { DEF_WEBP_DELAY = 75 }; -#endif - -#define ZOOM_MIN (zoom_levels[0] / 100) -#define ZOOM_MAX (zoom_levels[ARRLEN(zoom_levels)-1] / 100) - -static int calc_cache_size(void) -{ - int cache; - long pages, page_size; - - if (CACHE_SIZE_MEM_PERCENTAGE <= 0) - return 0; - - pages = sysconf(_SC_PHYS_PAGES); - page_size = sysconf(_SC_PAGE_SIZE); - if (pages < 0 || page_size < 0) - return CACHE_SIZE_FALLBACK; - cache = (pages/100) * CACHE_SIZE_MEM_PERCENTAGE; - cache *= page_size; - - return MIN(cache, CACHE_SIZE_LIMIT); -} - -void img_init(img_t *img, win_t *win) -{ - imlib_context_set_display(win->env.dpy); - imlib_context_set_visual(win->env.vis); - imlib_context_set_colormap(win->env.cmap); - imlib_set_cache_size(calc_cache_size()); - - img->im = NULL; - img->win = win; - img->scalemode = options->scalemode; - img->zoom = options->zoom; - img->zoom = MAX(img->zoom, ZOOM_MIN); - img->zoom = MIN(img->zoom, ZOOM_MAX); - img->checkpan = false; - img->dirty = false; - img->aa = ANTI_ALIAS; - img->alpha = ALPHA_LAYER; - img->multi.cap = img->multi.cnt = 0; - img->multi.animate = options->animate; - img->multi.framedelay = options->framerate > 0 ? 1000 / options->framerate : 0; - img->multi.length = 0; - - img->cmod = imlib_create_color_modifier(); - imlib_context_set_color_modifier(img->cmod); - img_change_gamma(img, options->gamma); - - img->ss.on = options->slideshow > 0; - img->ss.delay = options->slideshow > 0 ? options->slideshow : SLIDESHOW_DELAY * 10; -} - -#if HAVE_LIBEXIF -void exif_auto_orientate(const fileinfo_t *file) -{ - ExifData *ed; - ExifEntry *entry; - int byte_order, orientation = 0; - - if ((ed = exif_data_new_from_file(file->path)) == NULL) - return; - byte_order = exif_data_get_byte_order(ed); - entry = exif_content_get_entry(ed->ifd[EXIF_IFD_0], EXIF_TAG_ORIENTATION); - if (entry != NULL) - orientation = exif_get_short(entry->data, byte_order); - exif_data_unref(ed); - - switch (orientation) { - case 5: - imlib_image_orientate(1); - /* fall through */ - case 2: - imlib_image_flip_vertical(); - break; - case 3: - imlib_image_orientate(2); - break; - case 7: - imlib_image_orientate(1); - /* fall through */ - case 4: - imlib_image_flip_horizontal(); - break; - case 6: - imlib_image_orientate(1); - break; - case 8: - imlib_image_orientate(3); - break; - } -} -#endif - -#if HAVE_LIBGIF || HAVE_LIBWEBP -static void img_multiframe_context_set(img_t *img) -{ - if (img->multi.cnt > 1) { - imlib_context_set_image(img->im); - imlib_free_image(); - img->im = img->multi.frames[0].im; - } else if (img->multi.cnt == 1) { - imlib_context_set_image(img->multi.frames[0].im); - imlib_free_image(); - img->multi.cnt = 0; - } - - imlib_context_set_image(img->im); -} -#endif - -#if HAVE_LIBGIF -static bool img_load_gif(img_t *img, const fileinfo_t *file) -{ - GifFileType *gif; - GifRowType *rows = NULL; - GifRecordType rec; - ColorMapObject *cmap; - DATA32 bgpixel = 0, *data, *ptr; - DATA32 *prev_frame = NULL; - Imlib_Image im; - int i, j, bg, r, g, b; - int x, y, w, h, sw, sh; - int px, py, pw, ph; - int intoffset[] = { 0, 4, 2, 1 }; - int intjump[] = { 8, 8, 4, 2 }; - int transp = -1; - unsigned int disposal = 0, prev_disposal = 0; - unsigned int delay = 0; - bool err = false; - - if (img->multi.cap == 0) { - img->multi.cap = 8; - img->multi.frames = emalloc(img->multi.cap * sizeof(img_frame_t)); - } - img->multi.cnt = img->multi.sel = 0; - img->multi.length = 0; - -#if defined(GIFLIB_MAJOR) && GIFLIB_MAJOR >= 5 - gif = DGifOpenFileName(file->path, NULL); -#else - gif = DGifOpenFileName(file->path); -#endif - if (gif == NULL) { - error(0, 0, "%s: Error opening gif image", file->name); - return false; - } - bg = gif->SBackGroundColor; - sw = gif->SWidth; - sh = gif->SHeight; - px = py = pw = ph = 0; - - do { - if (DGifGetRecordType(gif, &rec) == GIF_ERROR) { - err = true; - break; - } - if (rec == EXTENSION_RECORD_TYPE) { - int ext_code; - GifByteType *ext = NULL; - - DGifGetExtension(gif, &ext_code, &ext); - while (ext) { - if (ext_code == GRAPHICS_EXT_FUNC_CODE) { - if (ext[1] & 1) - transp = (int) ext[4]; - else - transp = -1; - - delay = 10 * ((unsigned int) ext[3] << 8 | (unsigned int) ext[2]); - disposal = (unsigned int) ext[1] >> 2 & 0x7; - } - ext = NULL; - DGifGetExtensionNext(gif, &ext); - } - } else if (rec == IMAGE_DESC_RECORD_TYPE) { - if (DGifGetImageDesc(gif) == GIF_ERROR) { - err = true; - break; - } - x = gif->Image.Left; - y = gif->Image.Top; - w = gif->Image.Width; - h = gif->Image.Height; - - rows = emalloc(h * sizeof(GifRowType)); - for (i = 0; i < h; i++) - rows[i] = emalloc(w * sizeof(GifPixelType)); - if (gif->Image.Interlace) { - for (i = 0; i < 4; i++) { - for (j = intoffset[i]; j < h; j += intjump[i]) - DGifGetLine(gif, rows[j], w); - } - } else { - for (i = 0; i < h; i++) - DGifGetLine(gif, rows[i], w); - } - - ptr = data = emalloc(sw * sh * sizeof(DATA32)); - cmap = gif->Image.ColorMap ? gif->Image.ColorMap : gif->SColorMap; - /* if bg > cmap->ColorCount, it is transparent black already */ - if (cmap && bg >= 0 && bg < cmap->ColorCount) { - r = cmap->Colors[bg].Red; - g = cmap->Colors[bg].Green; - b = cmap->Colors[bg].Blue; - bgpixel = 0x00ffffff & (r << 16 | g << 8 | b); - } - - for (i = 0; i < sh; i++) { - for (j = 0; j < sw; j++) { - if (i < y || i >= y + h || j < x || j >= x + w || - rows[i-y][j-x] == transp) - { - if (prev_frame != NULL && (prev_disposal != 2 || - i < py || i >= py + ph || j < px || j >= px + pw)) - { - *ptr = prev_frame[i * sw + j]; - } else { - *ptr = bgpixel; - } - } else { - r = cmap->Colors[rows[i-y][j-x]].Red; - g = cmap->Colors[rows[i-y][j-x]].Green; - b = cmap->Colors[rows[i-y][j-x]].Blue; - *ptr = 0xffu << 24 | r << 16 | g << 8 | b; - } - ptr++; - } - } - - im = imlib_create_image_using_copied_data(sw, sh, data); - - for (i = 0; i < h; i++) - free(rows[i]); - free(rows); - free(data); - - if (im == NULL) { - err = true; - break; - } - - imlib_context_set_image(im); - imlib_image_set_format("gif"); - if (transp >= 0) - imlib_image_set_has_alpha(1); - - if (disposal != 3) - prev_frame = imlib_image_get_data_for_reading_only(); - prev_disposal = disposal; - px = x, py = y, pw = w, ph = h; - - if (img->multi.cnt == img->multi.cap) { - img->multi.cap *= 2; - img->multi.frames = erealloc(img->multi.frames, - img->multi.cap * sizeof(img_frame_t)); - } - img->multi.frames[img->multi.cnt].im = im; - delay = img->multi.framedelay > 0 ? img->multi.framedelay : delay; - img->multi.frames[img->multi.cnt].delay = delay > 0 ? delay : DEF_GIF_DELAY; - img->multi.length += img->multi.frames[img->multi.cnt].delay; - img->multi.cnt++; - } - } while (rec != TERMINATE_RECORD_TYPE); - -#if defined(GIFLIB_MAJOR) && GIFLIB_MAJOR >= 5 && GIFLIB_MINOR >= 1 - DGifCloseFile(gif, NULL); -#else - DGifCloseFile(gif); -#endif - - if (err && (file->flags & FF_WARN)) - error(0, 0, "%s: Corrupted gif file", file->name); - - img_multiframe_context_set(img); - - return !err; -} -#endif /* HAVE_LIBGIF */ - - -#if HAVE_LIBWEBP -static bool img_load_webp(img_t *img, const fileinfo_t *file) -{ - FILE *webp_file; - WebPData data; - Imlib_Image im = NULL; - struct WebPAnimDecoderOptions opts; - WebPAnimDecoder *dec = NULL; - struct WebPAnimInfo info; - unsigned char *buf = NULL, *bytes = NULL; - int ts; - const WebPDemuxer *demux; - WebPIterator iter; - unsigned long flags; - unsigned int delay; - bool err = false; - - if ((webp_file = fopen(file->path, "rb")) == NULL) { - error(0, errno, "%s: Error opening webp image", file->name); - return false; - } - fseek(webp_file, 0L, SEEK_END); - data.size = ftell(webp_file); - rewind(webp_file); - bytes = emalloc(data.size); - if ((err = fread(bytes, 1, data.size, webp_file) != data.size)) { - error(0, 0, "%s: Error reading webp image", file->name); - goto fail; - } - data.bytes = bytes; - - /* Setup the WebP Animation Decoder */ - if ((err = !WebPAnimDecoderOptionsInit(&opts))) { - error(0, 0, "%s: WebP library version mismatch", file->name); - goto fail; - } - opts.color_mode = MODE_BGRA; - /* NOTE: Multi-threaded decoding may cause problems on some system */ - opts.use_threads = true; - dec = WebPAnimDecoderNew(&data, &opts); - if ((err = (dec == NULL) || !WebPAnimDecoderGetInfo(dec, &info))) { - error(0, 0, "%s: WebP parsing or memory error (file is corrupt?)", file->name); - goto fail; - } - demux = WebPAnimDecoderGetDemuxer(dec); - - /* Get global information for the image */ - flags = WebPDemuxGetI(demux, WEBP_FF_FORMAT_FLAGS); - img->w = WebPDemuxGetI(demux, WEBP_FF_CANVAS_WIDTH); - img->h = WebPDemuxGetI(demux, WEBP_FF_CANVAS_HEIGHT); - - if (info.frame_count > img->multi.cap) { - img->multi.cap = info.frame_count; - img->multi.frames = erealloc(img->multi.frames, - img->multi.cap * sizeof(img_frame_t)); - } - - /* Load and decode frames (also works on images with only 1 frame) */ - img->multi.cnt = img->multi.sel = 0; - while (WebPAnimDecoderGetNext(dec, &buf, &ts)) { - im = imlib_create_image_using_copied_data( - info.canvas_width, info.canvas_height, (DATA32*)buf); - imlib_context_set_image(im); - imlib_image_set_format("webp"); - /* Get an iterator of this frame - used for frame info (duration, etc.) */ - WebPDemuxGetFrame(demux, img->multi.cnt+1, &iter); - imlib_image_set_has_alpha((flags & ALPHA_FLAG) == ALPHA_FLAG); - /* Store info for this frame */ - img->multi.frames[img->multi.cnt].im = im; - delay = iter.duration > 0 ? iter.duration : DEF_WEBP_DELAY; - img->multi.frames[img->multi.cnt].delay = delay; - img->multi.length += img->multi.frames[img->multi.cnt].delay; - img->multi.cnt++; - } - WebPDemuxReleaseIterator(&iter); - - img_multiframe_context_set(img); -fail: - if (dec != NULL) - WebPAnimDecoderDelete(dec); - free(bytes); - fclose(webp_file); - return !err; -} -#endif /* HAVE_LIBWEBP */ - -Imlib_Image img_open(const fileinfo_t *file) -{ - struct stat st; - Imlib_Image im = NULL; - - if (access(file->path, R_OK) == 0 && - stat(file->path, &st) == 0 && S_ISREG(st.st_mode)) - { - im = imlib_load_image(file->path); - if (im != NULL) { - imlib_context_set_image(im); - if (imlib_image_get_data_for_reading_only() == NULL) { - imlib_free_image(); - im = NULL; - } - } - } - if (im == NULL && (file->flags & FF_WARN)) - error(0, 0, "%s: Error opening image", file->name); - return im; -} - -bool img_load(img_t *img, const fileinfo_t *file) -{ - const char *fmt; - - if ((img->im = img_open(file)) == NULL) - return false; - - imlib_image_set_changes_on_disk(); - -/* since v1.7.5, Imlib2 can parse exif orientation from jpeg files. - * this version also happens to be the first one which defines the - * IMLIB2_VERSION macro. - */ -#if HAVE_LIBEXIF && !defined(IMLIB2_VERSION) - exif_auto_orientate(file); -#endif - - if ((fmt = imlib_image_format()) != NULL) { -#if HAVE_LIBGIF - if (STREQ(fmt, "gif")) - img_load_gif(img, file); -#endif -#if HAVE_LIBWEBP - if (STREQ(fmt, "webp")) - img_load_webp(img, file); -#endif -#if HAVE_LIBEXIF && defined(IMLIB2_VERSION) - if (!STREQ(fmt, "jpeg") && !STREQ(fmt, "jpg")) - exif_auto_orientate(file); -#endif - } - img->w = imlib_image_get_width(); - img->h = imlib_image_get_height(); - img->checkpan = true; - img->dirty = true; - - return true; -} - -CLEANUP void img_close(img_t *img, bool decache) -{ - int i; - - if (img->multi.cnt > 0) { - for (i = 0; i < img->multi.cnt; i++) { - imlib_context_set_image(img->multi.frames[i].im); - imlib_free_image(); - } - img->multi.cnt = 0; - img->im = NULL; - } else if (img->im != NULL) { - imlib_context_set_image(img->im); - if (decache) - imlib_free_image_and_decache(); - else - imlib_free_image(); - img->im = NULL; - } -} - -static void img_check_pan(img_t *img, bool moved) -{ - win_t *win; - float w, h, ox, oy; - - win = img->win; - w = img->w * img->zoom; - h = img->h * img->zoom; - ox = img->x; - oy = img->y; - - if (w < win->w) - img->x = (win->w - w) / 2; - else if (img->x > 0) - img->x = 0; - else if (img->x + w < win->w) - img->x = win->w - w; - if (h < win->h) - img->y = (win->h - h) / 2; - else if (img->y > 0) - img->y = 0; - else if (img->y + h < win->h) - img->y = win->h - h; - - if (!moved && (ox != img->x || oy != img->y)) - img->dirty = true; -} - -static bool img_fit(img_t *img) -{ - float z, zw, zh; - - if (img->scalemode == SCALE_ZOOM) - return false; - - zw = (float) img->win->w / (float) img->w; - zh = (float) img->win->h / (float) img->h; - - switch (img->scalemode) { - case SCALE_FILL: - z = MAX(zw, zh); - break; - case SCALE_WIDTH: - z = zw; - break; - case SCALE_HEIGHT: - z = zh; - break; - default: - z = MIN(zw, zh); - break; - } - z = MIN(z, img->scalemode == SCALE_DOWN ? 1.0 : ZOOM_MAX); - - if (ABS(img->zoom - z) > 1.0/MAX(img->w, img->h)) { - img->zoom = z; - img->dirty = true; - return true; - } else { - return false; - } -} - -void img_render(img_t *img) -{ - win_t *win; - int sx, sy, sw, sh; - int dx, dy, dw, dh; - Imlib_Image bg; - - win = img->win; - img_fit(img); - - if (img->checkpan) { - img_check_pan(img, false); - img->checkpan = false; - } - - if (!img->dirty) - return; - - /* calculate source and destination offsets: - * - part of image drawn on full window, or - * - full image drawn on part of window - */ - if (img->x <= 0) { - sx = -img->x / img->zoom + 0.5; - sw = win->w / img->zoom; - dx = 0; - dw = win->w; - } else { - sx = 0; - sw = img->w; - dx = img->x; - dw = MAX(img->w * img->zoom, 1); - } - if (img->y <= 0) { - sy = -img->y / img->zoom + 0.5; - sh = win->h / img->zoom; - dy = win->bar.top ? win->bar.h : 0; - dh = win->h; - } else { - sy = 0; - sh = img->h; - dy = img->y + (win->bar.top ? win->bar.h : 0); - dh = MAX(img->h * img->zoom, 1); - } - - win_clear(win); - - imlib_context_set_image(img->im); - imlib_context_set_anti_alias(img->aa); - imlib_context_set_drawable(win->buf.pm); - - /* manual blending, for performance reasons. - * see https://phab.enlightenment.org/T8969#156167 for more details. - */ - if (imlib_image_has_alpha()) { - if ((bg = imlib_create_image(dw, dh)) == NULL) { - error(0, ENOMEM, "Failed to create image"); - goto fallback; - } - imlib_context_set_image(bg); - imlib_image_set_has_alpha(0); - - if (img->alpha) { - int i, c, r; - DATA32 col[2] = { 0xFF666666, 0xFF999999 }; - DATA32 * data = imlib_image_get_data(); - - for (r = 0; r < dh; r++) { - i = r * dw; - if (r == 0 || r == 8) { - for (c = 0; c < dw; c++) - data[i++] = col[!(c & 8) ^ !r]; - } else { - memcpy(&data[i], &data[(r & 8) * dw], dw * sizeof(data[0])); - } - } - imlib_image_put_back_data(data); - } else { - XColor c = win->win_bg; - imlib_context_set_color(c.red >> 8, c.green >> 8, c.blue >> 8, 0xFF); - imlib_image_fill_rectangle(0, 0, dw, dh); - } - imlib_blend_image_onto_image(img->im, 0, sx, sy, sw, sh, 0, 0, dw, dh); - imlib_context_set_color_modifier(NULL); - imlib_render_image_on_drawable(dx, dy); - imlib_free_image(); - imlib_context_set_color_modifier(img->cmod); - } else { -fallback: - imlib_render_image_part_on_drawable_at_size(sx, sy, sw, sh, dx, dy, dw, dh); - } - img->dirty = false; -} - -bool img_fit_win(img_t *img, scalemode_t sm) -{ - float oz; - - oz = img->zoom; - img->scalemode = sm; - - if (img_fit(img)) { - img->x = img->win->w / 2 - (img->win->w / 2 - img->x) * img->zoom / oz; - img->y = img->win->h / 2 - (img->win->h / 2 - img->y) * img->zoom / oz; - img->checkpan = true; - return true; - } else { - return false; - } -} - -bool img_zoom_to(img_t *img, float z) -{ - int x, y; - if (ZOOM_MIN <= z && z <= ZOOM_MAX) { - win_cursor_pos(img->win, &x, &y); - if (x < 0 || x >= img->win->w || y < 0 || y >= img->win->h) { - x = img->win->w / 2; - y = img->win->h / 2; - } - img->x = x - (x - img->x) * z / img->zoom; - img->y = y - (y - img->y) * z / img->zoom; - img->zoom = z; - img->scalemode = SCALE_ZOOM; - img->checkpan = true; - img->dirty = true; - return true; - } else { - return false; - } -} - -bool img_zoom(img_t *img, int d) -{ - int i = d > 0 ? 0 : ARRLEN(zoom_levels)-1; - while (i >= 0 && i < ARRLEN(zoom_levels) && (d > 0 ? - zoom_levels[i]/100 <= img->zoom : zoom_levels[i]/100 >= img->zoom)) - { - i += d; - } - i = MIN(MAX(i, 0), ARRLEN(zoom_levels)-1); - return img_zoom_to(img, zoom_levels[i]/100); -} - -bool img_pos(img_t *img, float x, float y) -{ - float ox, oy; - - ox = img->x; - oy = img->y; - - img->x = x; - img->y = y; - - img_check_pan(img, true); - - if (ox != img->x || oy != img->y) { - img->dirty = true; - return true; - } else { - return false; - } -} - -static bool img_move(img_t *img, float dx, float dy) -{ - return img_pos(img, img->x + dx, img->y + dy); -} - -bool img_pan(img_t *img, direction_t dir, int d) -{ - /* d < 0: screen-wise - * d = 0: 1/PAN_FRACTION of screen - * d > 0: num of pixels - */ - float x, y; - - if (d > 0) { - x = y = MAX(1, (float) d * img->zoom); - } else { - x = img->win->w / (d < 0 ? 1 : PAN_FRACTION); - y = img->win->h / (d < 0 ? 1 : PAN_FRACTION); - } - - switch (dir) { - case DIR_LEFT: - return img_move(img, x, 0.0); - case DIR_RIGHT: - return img_move(img, -x, 0.0); - case DIR_UP: - return img_move(img, 0.0, y); - case DIR_DOWN: - return img_move(img, 0.0, -y); - } - return false; -} - -bool img_pan_center(img_t *img) -{ - float x, y; - x = (img->win->w - img->w * img->zoom) / 2.0; - y = (img->win->h - img->h * img->zoom) / 2.0; - return img_pos(img, x, y); -} - -bool img_pan_edge(img_t *img, direction_t dir) -{ - float ox, oy; - - ox = img->x; - oy = img->y; - - if (dir & DIR_LEFT) - img->x = 0; - if (dir & DIR_RIGHT) - img->x = img->win->w - img->w * img->zoom; - if (dir & DIR_UP) - img->y = 0; - if (dir & DIR_DOWN) - img->y = img->win->h - img->h * img->zoom; - - img_check_pan(img, true); - - if (ox != img->x || oy != img->y) { - img->dirty = true; - return true; - } else { - return false; - } -} - -void img_rotate(img_t *img, degree_t d) -{ - int i, tmp; - float ox, oy; - - imlib_context_set_image(img->im); - imlib_image_orientate(d); - - for (i = 0; i < img->multi.cnt; i++) { - if (i != img->multi.sel) { - imlib_context_set_image(img->multi.frames[i].im); - imlib_image_orientate(d); - } - } - if (d == DEGREE_90 || d == DEGREE_270) { - ox = d == DEGREE_90 ? img->x : img->win->w - img->x - img->w * img->zoom; - oy = d == DEGREE_270 ? img->y : img->win->h - img->y - img->h * img->zoom; - - img->x = oy + (img->win->w - img->win->h) / 2; - img->y = ox + (img->win->h - img->win->w) / 2; - - tmp = img->w; - img->w = img->h; - img->h = tmp; - img->checkpan = true; - } - img->dirty = true; -} - -void img_flip(img_t *img, flipdir_t d) -{ - int i; - void (*imlib_flip_op[3])(void) = { - imlib_image_flip_horizontal, - imlib_image_flip_vertical, - imlib_image_flip_diagonal - }; - - d = (d & (FLIP_HORIZONTAL | FLIP_VERTICAL)) - 1; - - if (d < 0 || d >= ARRLEN(imlib_flip_op)) - return; - - imlib_context_set_image(img->im); - imlib_flip_op[d](); - - for (i = 0; i < img->multi.cnt; i++) { - if (i != img->multi.sel) { - imlib_context_set_image(img->multi.frames[i].im); - imlib_flip_op[d](); - } - } - img->dirty = true; -} - -void img_toggle_antialias(img_t *img) -{ - img->aa = !img->aa; - imlib_context_set_image(img->im); - imlib_context_set_anti_alias(img->aa); - img->dirty = true; -} - -bool img_change_gamma(img_t *img, int d) -{ - /* d < 0: decrease gamma - * d = 0: reset gamma - * d > 0: increase gamma - */ - int gamma; - double range; - - if (d == 0) - gamma = 0; - else - gamma = MIN(MAX(img->gamma + d, -GAMMA_RANGE), GAMMA_RANGE); - - if (img->gamma != gamma) { - imlib_reset_color_modifier(); - if (gamma) { - range = gamma <= 0 ? 1.0 : GAMMA_MAX - 1.0; - imlib_modify_color_modifier_gamma(1.0 + gamma * (range / GAMMA_RANGE)); - } - img->gamma = gamma; - img->dirty = true; - return true; - } else { - return false; - } -} - -static bool img_frame_goto(img_t *img, int n) -{ - if (n < 0 || n >= img->multi.cnt || n == img->multi.sel) - return false; - - img->multi.sel = n; - img->im = img->multi.frames[n].im; - - imlib_context_set_image(img->im); - img->w = imlib_image_get_width(); - img->h = imlib_image_get_height(); - img->checkpan = true; - img->dirty = true; - - return true; -} - -bool img_frame_navigate(img_t *img, int d) -{ - if (img->multi.cnt == 0 || d == 0) - return false; - - d += img->multi.sel; - d = MAX(0, MIN(d, img->multi.cnt - 1)); - - return img_frame_goto(img, d); -} - -bool img_frame_animate(img_t *img) -{ - if (img->multi.cnt > 0) - return img_frame_goto(img, (img->multi.sel + 1) % img->multi.cnt); - else - return false; -} diff --git a/utils/nsxiv/main.c b/utils/nsxiv/main.c deleted file mode 100644 index 976bd5f..0000000 --- a/utils/nsxiv/main.c +++ /dev/null @@ -1,955 +0,0 @@ -/* Copyright 2011-2020 Bert Muennich - * Copyright 2021-2022 nsxiv contributors - * - * This file is a part of nsxiv. - * - * nsxiv is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, - * or (at your option) any later version. - * - * nsxiv is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with nsxiv. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "nsxiv.h" -#define _MAPPINGS_CONFIG -#include "commands.h" -#include "config.h" - -#include <stdlib.h> -#include <string.h> -#include <fcntl.h> -#include <unistd.h> -#include <errno.h> -#include <locale.h> -#include <signal.h> -#include <poll.h> -#include <sys/stat.h> -#include <sys/wait.h> -#include <time.h> -#include <X11/keysym.h> -#include <X11/XF86keysym.h> - -#define MODMASK(mask) ((mask) & USED_MODMASK) -#define BAR_SEP " " - -typedef struct { - struct timeval when; - bool active; - timeout_f handler; -} timeout_t; - -typedef struct { - int err; - char *cmd; -} extcmd_t; - -/* these are not declared in nsxiv.h, as it causes too many -Wshadow warnings */ -arl_t arl; -img_t img; -tns_t tns; -win_t win; - -appmode_t mode; -const XButtonEvent *xbutton_ev; - -fileinfo_t *files; -int filecnt, fileidx; -int alternate; -int markcnt; -int markidx; - -int prefix; -static bool extprefix; - -static bool resized = false; - -static struct { - extcmd_t f, ft; - int fd; - unsigned int i, lastsep; - pid_t pid; -} info; - -static struct { - extcmd_t f; - bool warned; -} keyhandler; - -static struct { - extcmd_t f; -} wintitle; - -static timeout_t timeouts[] = { - { { 0, 0 }, false, redraw }, - { { 0, 0 }, false, reset_cursor }, - { { 0, 0 }, false, animate }, - { { 0, 0 }, false, slideshow }, - { { 0, 0 }, false, clear_resize }, -}; - -/************************** - function implementations - **************************/ -static void cleanup(void) -{ - img_close(&img, false); - arl_cleanup(&arl); - tns_free(&tns); - win_close(&win); -} - -static bool xgetline(char **lineptr, size_t *n) -{ - ssize_t len = getdelim(lineptr, n, options->using_null ? '\0' : '\n', stdin); - if (!options->using_null && len > 0 && (*lineptr)[len-1] == '\n') - (*lineptr)[len-1] = '\0'; - return len > 0; -} - -static void check_add_file(char *filename, bool given) -{ - char *path; - - if (*filename == '\0') - return; - - if (access(filename, R_OK) < 0 || - (path = realpath(filename, NULL)) == NULL) - { - if (given) - error(0, errno, "%s", filename); - return; - } - - if (fileidx == filecnt) { - filecnt *= 2; - files = erealloc(files, filecnt * sizeof(*files)); - memset(&files[filecnt/2], 0, filecnt/2 * sizeof(*files)); - } - - files[fileidx].name = estrdup(filename); - files[fileidx].path = path; - if (given) - files[fileidx].flags |= FF_WARN; - fileidx++; -} - -void remove_file(int n, bool manual) -{ - if (n < 0 || n >= filecnt) - return; - - if (filecnt == 1) { - if (!manual) - fprintf(stderr, "nsxiv: no more files to display, aborting\n"); - exit(manual ? EXIT_SUCCESS : EXIT_FAILURE); - } - if (files[n].flags & FF_MARK) - markcnt--; - - if (files[n].path != files[n].name) - free((void*) files[n].path); - free((void*) files[n].name); - - if (n + 1 < filecnt) { - if (tns.thumbs != NULL) { - if (tns.thumbs[n].im != NULL) { - imlib_context_set_image(tns.thumbs[n].im); - imlib_free_image_and_decache(); - } - memmove(tns.thumbs + n, tns.thumbs + n + 1, (filecnt - n - 1) * - sizeof(*tns.thumbs)); - memset(tns.thumbs + filecnt - 1, 0, sizeof(*tns.thumbs)); - } - memmove(files + n, files + n + 1, (filecnt - n - 1) * sizeof(*files)); - } - filecnt--; - if (fileidx > n || fileidx == filecnt) - fileidx--; - if (alternate > n || alternate == filecnt) - alternate--; - if (markidx > n || markidx == filecnt) - markidx--; -} - -void set_timeout(timeout_f handler, int time, bool overwrite) -{ - unsigned int i; - - for (i = 0; i < ARRLEN(timeouts); i++) { - if (timeouts[i].handler == handler) { - if (!timeouts[i].active || overwrite) { - gettimeofday(&timeouts[i].when, 0); - TV_ADD_MSEC(&timeouts[i].when, time); - timeouts[i].active = true; - } - return; - } - } -} - -void reset_timeout(timeout_f handler) -{ - unsigned int i; - - for (i = 0; i < ARRLEN(timeouts); i++) { - if (timeouts[i].handler == handler) { - timeouts[i].active = false; - return; - } - } -} - -static bool check_timeouts(struct timeval *t) -{ - int i = 0, tdiff, tmin = -1; - struct timeval now; - - while (i < ARRLEN(timeouts)) { - if (timeouts[i].active) { - gettimeofday(&now, 0); - tdiff = TV_DIFF(&timeouts[i].when, &now); - if (tdiff <= 0) { - timeouts[i].active = false; - if (timeouts[i].handler != NULL) - timeouts[i].handler(); - i = tmin = -1; - } else if (tmin < 0 || tdiff < tmin) { - tmin = tdiff; - } - } - i++; - } - if (tmin > 0 && t != NULL) - TV_SET_MSEC(t, tmin); - return tmin > 0; -} - -size_t get_win_title(unsigned char *buf, int len, bool init) -{ - char *argv[8]; - spawn_t pfd; - char w[12] = "", h[12] = "", z[12] = "", fidx[12], fcnt[12]; - ssize_t n = -1; - - if (buf == NULL || len <= 0) - return 0; - - if (init) { - n = snprintf((char *)buf, len, "%s", options->res_name != NULL ? - options->res_name : "nsxiv"); - } else if (!wintitle.f.err) { - if (mode == MODE_IMAGE) { - snprintf(w, ARRLEN(w), "%d", img.w); - snprintf(h, ARRLEN(h), "%d", img.h); - snprintf(z, ARRLEN(z), "%d", (int)(img.zoom * 100)); - } - snprintf(fidx, ARRLEN(fidx), "%d", fileidx+1); - snprintf(fcnt, ARRLEN(fcnt), "%d", filecnt); - construct_argv(argv, ARRLEN(argv), wintitle.f.cmd, files[fileidx].path, - fidx, fcnt, w, h, z, NULL); - pfd = spawn(wintitle.f.cmd, argv, X_READ); - if (pfd.readfd >= 0) { - if ((n = read(pfd.readfd, buf, len-1)) > 0) - buf[n] = '\0'; - close(pfd.readfd); - } - } - - return MAX(0, n); -} - -void close_info(void) -{ - if (info.fd != -1) { - kill(info.pid, SIGTERM); - close(info.fd); - info.fd = -1; - } -} - -void open_info(void) -{ - spawn_t pfd; - char w[12] = "", h[12] = ""; - char *argv[6]; - char *cmd = mode == MODE_IMAGE ? info.f.cmd : info.ft.cmd; - bool ferr = mode == MODE_IMAGE ? info.f.err : info.ft.err; - - if (ferr || info.fd >= 0 || win.bar.h == 0) - return; - win.bar.l.buf[0] = '\0'; - if (mode == MODE_IMAGE) { - snprintf(w, sizeof(w), "%d", img.w); - snprintf(h, sizeof(h), "%d", img.h); - } - construct_argv(argv, ARRLEN(argv), cmd, files[fileidx].name, w, h, - files[fileidx].path, NULL); - pfd = spawn(cmd, argv, X_READ); - if (pfd.readfd >= 0) { - fcntl(pfd.readfd, F_SETFL, O_NONBLOCK); - info.fd = pfd.readfd; - info.i = info.lastsep = 0; - info.pid = pfd.pid; - } -} - -static void read_info(void) -{ - ssize_t i, n; - char buf[BAR_L_LEN]; - - while (true) { - n = read(info.fd, buf, sizeof(buf)); - if (n < 0 && errno == EAGAIN) - return; - else if (n == 0) - goto end; - for (i = 0; i < n; i++) { - if (buf[i] == '\n') { - if (info.lastsep == 0) { - win.bar.l.buf[info.i++] = ' '; - info.lastsep = 1; - } - } else { - win.bar.l.buf[info.i++] = buf[i]; - info.lastsep = 0; - } - if (info.i + 1 == win.bar.l.size) - goto end; - } - } -end: - info.i -= info.lastsep; - win.bar.l.buf[info.i] = '\0'; - win_draw(&win); - close_info(); -} - -void load_image(int new) -{ - bool prev = new < fileidx; - static int current; - - if (new < 0 || new >= filecnt) - return; - - if (win.xwin != None) - win_set_cursor(&win, CURSOR_WATCH); - reset_timeout(slideshow); - - if (new != current) - alternate = current; - - img_close(&img, false); - while (!img_load(&img, &files[new])) { - remove_file(new, false); - if (new >= filecnt) - new = filecnt - 1; - else if (new > 0 && prev) - new--; - } - files[new].flags &= ~FF_WARN; - fileidx = current = new; - - close_info(); - open_info(); - arl_setup(&arl, files[fileidx].path); - - if (img.multi.cnt > 0 && img.multi.animate) - set_timeout(animate, img.multi.frames[img.multi.sel].delay, true); - else - reset_timeout(animate); -} - -bool mark_image(int n, bool on) -{ - markidx = n; - if (!!(files[n].flags & FF_MARK) != on) { - files[n].flags ^= FF_MARK; - markcnt += on ? 1 : -1; - if (mode == MODE_THUMB) - tns_mark(&tns, n, on); - return true; - } - return false; -} - -static void bar_put(win_bar_t *bar, const char *fmt, ...) -{ - size_t len = bar->size - (bar->p - bar->buf), n; - va_list ap; - - va_start(ap, fmt); - n = vsnprintf(bar->p, len, fmt, ap); - bar->p += MIN(len, n); - va_end(ap); -} - -static void update_info(void) -{ - unsigned int i, fn, fw; - const char *mark; - win_bar_t *l = &win.bar.l, *r = &win.bar.r; - - /* update bar contents */ - if (win.bar.h == 0) - return; - for (fw = 0, i = filecnt; i > 0; fw++, i /= 10); - mark = files[fileidx].flags & FF_MARK ? "* " : ""; - l->p = l->buf; - r->p = r->buf; - if (mode == MODE_THUMB) { - if (tns.loadnext < tns.end) - bar_put(l, "Loading... %0*d", fw, tns.loadnext + 1); - else if (tns.initnext < filecnt) - bar_put(l, "Caching... %0*d", fw, tns.initnext + 1); - else if (info.ft.err) - strncpy(l->buf, files[fileidx].name, l->size); - bar_put(r, "%s%0*d/%d", mark, fw, fileidx + 1, filecnt); - } else { - bar_put(r, "%s", mark); - if (img.ss.on) { - if (img.ss.delay % 10 != 0) - bar_put(r, "%2.1fs" BAR_SEP, (float)img.ss.delay / 10); - else - bar_put(r, "%ds" BAR_SEP, img.ss.delay / 10); - } - if (img.gamma) - bar_put(r, "G%+d" BAR_SEP, img.gamma); - bar_put(r, "%3d%%" BAR_SEP, (int) (img.zoom * 100.0)); - if (img.multi.cnt > 0) { - for (fn = 0, i = img.multi.cnt; i > 0; fn++, i /= 10); - bar_put(r, "%0*d/%d" BAR_SEP, fn, img.multi.sel + 1, img.multi.cnt); - } - bar_put(r, "%0*d/%d", fw, fileidx + 1, filecnt); - if (info.f.err) - strncpy(l->buf, files[fileidx].name, l->size); - } -} - -int nav_button(void) -{ - int x, y, nw; - - if (NAV_WIDTH == 0) - return 1; - - win_cursor_pos(&win, &x, &y); - nw = NAV_IS_REL ? win.w * NAV_WIDTH / 100 : NAV_WIDTH; - nw = MIN(nw, (win.w + 1) / 2); - - if (x < nw) - return 0; - else if (x < win.w-nw) - return 1; - else - return 2; -} - -void redraw(void) -{ - int t; - - if (mode == MODE_IMAGE) { - img_render(&img); - if (img.ss.on) { - t = img.ss.delay * 100; - if (img.multi.cnt > 0 && img.multi.animate) - t = MAX(t, img.multi.length); - set_timeout(slideshow, t, false); - } - } else { - tns_render(&tns); - } - update_info(); - win_set_title(&win, false); - win_draw(&win); - reset_timeout(redraw); - reset_cursor(); -} - -void reset_cursor(void) -{ - int c; - unsigned int i; - cursor_t cursor = CURSOR_NONE; - - if (mode == MODE_IMAGE) { - for (i = 0; i < ARRLEN(timeouts); i++) { - if (timeouts[i].handler == reset_cursor) { - if (timeouts[i].active) { - c = nav_button(); - c = MAX(fileidx > 0 ? 0 : 1, c); - c = MIN(fileidx + 1 < filecnt ? 2 : 1, c); - cursor = imgcursor[c]; - } - break; - } - } - } else { - if (tns.loadnext < tns.end || tns.initnext < filecnt) - cursor = CURSOR_WATCH; - else - cursor = CURSOR_ARROW; - } - win_set_cursor(&win, cursor); -} - -void animate(void) -{ - if (img_frame_animate(&img)) { - set_timeout(animate, img.multi.frames[img.multi.sel].delay, true); - redraw(); - } -} - -void slideshow(void) -{ - load_image(fileidx + 1 < filecnt ? fileidx + 1 : 0); - redraw(); -} - -void clear_resize(void) -{ - resized = false; -} - -static Bool is_input_ev(Display *dpy, XEvent *ev, XPointer arg) -{ - return ev->type == ButtonPress || ev->type == KeyPress; -} - -void handle_key_handler(bool init) -{ - extprefix = init; - if (win.bar.h == 0) - return; - if (init) { - close_info(); - snprintf(win.bar.l.buf, win.bar.l.size, "Getting key handler input " - "(%s to abort)...", XKeysymToString(KEYHANDLER_ABORT)); - } else { /* abort */ - open_info(); - update_info(); - } - win_draw(&win); -} - -static bool run_key_handler(const char *key, unsigned int mask) -{ - FILE *pfs; - bool marked = mode == MODE_THUMB && markcnt > 0; - bool changed = false; - int f, i; - int fcnt = marked ? markcnt : 1; - char kstr[32]; - struct stat *oldst, st; - XEvent dump; - char *argv[3]; - spawn_t pfd; - - if (keyhandler.f.err) { - if (!keyhandler.warned) { - error(0, keyhandler.f.err, "%s", keyhandler.f.cmd); - keyhandler.warned = true; - } - return false; - } - if (key == NULL) - return false; - - close_info(); - strncpy(win.bar.l.buf, "Running key handler...", win.bar.l.size); - win_draw(&win); - win_set_cursor(&win, CURSOR_WATCH); - setenv("NSXIV_USING_NULL", options->using_null ? "1" : "0", 1); - - snprintf(kstr, sizeof(kstr), "%s%s%s%s", - mask & ControlMask ? "C-" : "", - mask & Mod1Mask ? "M-" : "", - mask & ShiftMask ? "S-" : "", key); - construct_argv(argv, ARRLEN(argv), keyhandler.f.cmd, kstr, NULL); - pfd = spawn(keyhandler.f.cmd, argv, X_WRITE); - if (pfd.writefd < 0) - return false; - if ((pfs = fdopen(pfd.writefd, "w")) == NULL) { - close(pfd.writefd); - error(0, errno, "open pipe"); - return false; - } - - oldst = emalloc(fcnt * sizeof(*oldst)); - for (f = i = 0; f < fcnt; i++) { - if ((marked && (files[i].flags & FF_MARK)) || (!marked && i == fileidx)) { - stat(files[i].path, &oldst[f]); - fprintf(pfs, "%s%c", files[i].name, options->using_null ? '\0' : '\n'); - f++; - } - } - fclose(pfs); - while (waitpid(pfd.pid, NULL, 0) == -1 && errno == EINTR); - - for (f = i = 0; f < fcnt; i++) { - if ((marked && (files[i].flags & FF_MARK)) || (!marked && i == fileidx)) { - if (stat(files[i].path, &st) != 0 || - memcmp(&oldst[f].st_mtime, &st.st_mtime, sizeof(st.st_mtime)) != 0) - { - if (tns.thumbs != NULL) { - tns_unload(&tns, i); - tns.loadnext = MIN(tns.loadnext, i); - } - changed = true; - } - f++; - } - } - /* drop user input events that occurred while running the key handler */ - while (XCheckIfEvent(win.env.dpy, &dump, is_input_ev, NULL)); - - if (mode == MODE_IMAGE) { - if (changed) { - img_close(&img, true); - load_image(fileidx); - } else { - open_info(); - } - } - free(oldst); - reset_cursor(); - return true; -} - -static bool process_bindings(const keymap_t *bindings, unsigned int len, KeySym ksym_or_button, - unsigned int state, unsigned int implicit_mod) -{ - unsigned int i; - bool dirty = false; - - for (i = 0; i < len; i++) { - if (bindings[i].ksym_or_button == ksym_or_button && - MODMASK(bindings[i].mask | implicit_mod) == MODMASK(state) && - bindings[i].cmd.func && - (bindings[i].cmd.mode == MODE_ALL || bindings[i].cmd.mode == mode)) - { - if (bindings[i].cmd.func(bindings[i].arg)) - dirty = true; - } - } - return dirty; -} - -static void on_keypress(XKeyEvent *kev) -{ - unsigned int sh = 0; - KeySym ksym, shksym; - char dummy, key; - bool dirty = false; - - XLookupString(kev, &key, 1, &ksym, NULL); - - if (kev->state & ShiftMask) { - kev->state &= ~ShiftMask; - XLookupString(kev, &dummy, 1, &shksym, NULL); - kev->state |= ShiftMask; - if (ksym != shksym) - sh = ShiftMask; - } - if (IsModifierKey(ksym)) - return; - if (extprefix && ksym == KEYHANDLER_ABORT && MODMASK(kev->state) == 0) { - handle_key_handler(false); - } else if (extprefix) { - if ((dirty = run_key_handler(XKeysymToString(ksym), kev->state & ~sh))) - extprefix = false; - else - handle_key_handler(false); - } else if (key >= '0' && key <= '9') { - /* number prefix for commands */ - prefix = prefix * 10 + (int) (key - '0'); - return; - } else { - dirty = process_bindings(keys, ARRLEN(keys), ksym, kev->state, sh); - } - if (dirty) - redraw(); - prefix = 0; -} - -static void on_buttonpress(const XButtonEvent *bev) -{ - bool dirty = false; - - if (mode == MODE_IMAGE) { - set_timeout(reset_cursor, TO_CURSOR_HIDE, true); - reset_cursor(); - dirty = process_bindings(buttons_img, ARRLEN(buttons_img), bev->button, bev->state, 0); - } else { /* thumbnail mode */ - dirty = process_bindings(buttons_tns, ARRLEN(buttons_tns), bev->button, bev->state, 0); - } - if (dirty) - redraw(); - prefix = 0; -} - -static void run(void) -{ - enum { FD_X, FD_INFO, FD_ARL, FD_CNT }; - struct pollfd pfd[FD_CNT]; - struct timeval timeout = {0}; - const struct timespec ten_ms = {0, 10000000}; - bool discard, init_thumb, load_thumb, to_set; - XEvent ev, nextev; - - xbutton_ev = &ev.xbutton; - while (true) { - to_set = check_timeouts(&timeout); - init_thumb = mode == MODE_THUMB && tns.initnext < filecnt; - load_thumb = mode == MODE_THUMB && tns.loadnext < tns.end; - - if ((init_thumb || load_thumb || to_set || info.fd != -1 || - arl.fd != -1) && XPending(win.env.dpy) == 0) - { - if (load_thumb) { - set_timeout(redraw, TO_REDRAW_THUMBS, false); - if (!tns_load(&tns, tns.loadnext, false, false)) { - remove_file(tns.loadnext, false); - tns.dirty = true; - } - if (tns.loadnext >= tns.end) - redraw(); - } else if (init_thumb) { - set_timeout(redraw, TO_REDRAW_THUMBS, false); - if (!tns_load(&tns, tns.initnext, false, true)) - remove_file(tns.initnext, false); - } else { - pfd[FD_X].fd = ConnectionNumber(win.env.dpy); - pfd[FD_INFO].fd = info.fd; - pfd[FD_ARL].fd = arl.fd; - pfd[FD_X].events = pfd[FD_INFO].events = pfd[FD_ARL].events = POLLIN; - - if (poll(pfd, ARRLEN(pfd), to_set ? TV_TO_MS(&timeout) : -1) < 0) - continue; - if (pfd[FD_INFO].revents & POLLIN) - read_info(); - if (pfd[FD_ARL].revents & POLLIN) { - if (arl_handle(&arl)) { - /* when too fast, imlib2 can't load the image */ - nanosleep(&ten_ms, NULL); - img_close(&img, true); - load_image(fileidx); - redraw(); - } - } - } - continue; - } - - do { - XNextEvent(win.env.dpy, &ev); - discard = false; - if (XEventsQueued(win.env.dpy, QueuedAlready) > 0) { - XPeekEvent(win.env.dpy, &nextev); - switch (ev.type) { - case ConfigureNotify: - case MotionNotify: - discard = ev.type == nextev.type; - break; - case KeyPress: - discard = (nextev.type == KeyPress || nextev.type == KeyRelease) - && ev.xkey.keycode == nextev.xkey.keycode; - break; - } - } - } while (discard); - - switch (ev.type) { - /* handle events */ - case ButtonPress: - on_buttonpress(&ev.xbutton); - break; - case ClientMessage: - if ((Atom) ev.xclient.data.l[0] == atoms[ATOM_WM_DELETE_WINDOW]) - cg_quit(EXIT_SUCCESS); - break; - case DestroyNotify: - cg_quit(EXIT_FAILURE); - break; - case ConfigureNotify: - if (win_configure(&win, &ev.xconfigure)) { - if (mode == MODE_IMAGE) { - img.dirty = true; - img.checkpan = true; - } else { - tns.dirty = true; - } - if (!resized) { - redraw(); - set_timeout(clear_resize, TO_REDRAW_RESIZE, false); - resized = true; - } else { - set_timeout(redraw, TO_REDRAW_RESIZE, false); - } - } - break; - case KeyPress: - on_keypress(&ev.xkey); - break; - case MotionNotify: - if (mode == MODE_IMAGE) { - set_timeout(reset_cursor, TO_CURSOR_HIDE, true); - reset_cursor(); - } - break; - } - } -} - -static int fncmp(const void *a, const void *b) -{ - return strcoll(((fileinfo_t*) a)->name, ((fileinfo_t*) b)->name); -} - -static void sigchld(int sig) -{ - while (waitpid(-1, NULL, WNOHANG) > 0); -} - -static void setup_signal(int sig, void (*handler)(int sig)) -{ - struct sigaction sa; - - sa.sa_handler = handler; - sigemptyset(&sa.sa_mask); - sa.sa_flags = SA_RESTART | SA_NOCLDSTOP; - if (sigaction(sig, &sa, 0) == -1) - error(EXIT_FAILURE, errno, "signal %d", sig); -} - -int main(int argc, char *argv[]) -{ - int i, start; - size_t n; - char *filename; - const char *homedir, *dsuffix = ""; - struct stat fstats; - r_dir_t dir; - - setup_signal(SIGCHLD, sigchld); - setup_signal(SIGPIPE, SIG_IGN); - - setlocale(LC_COLLATE, ""); - - parse_options(argc, argv); - - if (options->clean_cache) { - tns_init(&tns, NULL, NULL, NULL, NULL); - tns_clean_cache(); - exit(EXIT_SUCCESS); - } - - if (options->filecnt == 0 && !options->from_stdin) { - print_usage(); - exit(EXIT_FAILURE); - } - - if (options->recursive || options->from_stdin) - filecnt = 1024; - else - filecnt = options->filecnt; - - files = ecalloc(filecnt, sizeof(*files)); - fileidx = 0; - - if (options->from_stdin) { - n = 0; - filename = NULL; - while (xgetline(&filename, &n)) - check_add_file(filename, true); - free(filename); - } - - for (i = 0; i < options->filecnt; i++) { - filename = options->filenames[i]; - - if (stat(filename, &fstats) < 0) { - error(0, errno, "%s", filename); - continue; - } - if (!S_ISDIR(fstats.st_mode)) { - check_add_file(filename, true); - } else { - if (r_opendir(&dir, filename, options->recursive) < 0) { - error(0, errno, "%s", filename); - continue; - } - start = fileidx; - while ((filename = r_readdir(&dir, true)) != NULL) { - check_add_file(filename, false); - free((void*) filename); - } - r_closedir(&dir); - if (fileidx - start > 1) - qsort(files + start, fileidx - start, sizeof(fileinfo_t), fncmp); - } - } - - if (fileidx == 0) - error(EXIT_FAILURE, 0, "No valid image file given, aborting"); - - filecnt = fileidx; - fileidx = options->startnum < filecnt ? options->startnum : 0; - - win_init(&win); - img_init(&img, &win); - arl_init(&arl); - - if ((homedir = getenv("XDG_CONFIG_HOME")) == NULL || homedir[0] == '\0') { - homedir = getenv("HOME"); - dsuffix = "/.config"; - } - if (homedir != NULL) { - extcmd_t *cmd[] = { &info.f, &info.ft, &keyhandler.f, &wintitle.f }; - const char *name[] = { "image-info", "thumb-info", "key-handler", "win-title" }; - const char *s = "/nsxiv/exec/"; - - for (i = 0; i < ARRLEN(cmd); i++) { - n = strlen(homedir) + strlen(dsuffix) + strlen(s) + strlen(name[i]) + 1; - cmd[i]->cmd = emalloc(n); - snprintf(cmd[i]->cmd, n, "%s%s%s%s", homedir, dsuffix, s, name[i]); - if (access(cmd[i]->cmd, X_OK) != 0) - cmd[i]->err = errno; - } - } else { - error(0, 0, "Exec directory not found"); - } - info.fd = -1; - - if (options->thumb_mode) { - mode = MODE_THUMB; - tns_init(&tns, files, &filecnt, &fileidx, &win); - while (!tns_load(&tns, fileidx, false, false)) - remove_file(fileidx, false); - } else { - mode = MODE_IMAGE; - tns.thumbs = NULL; - load_image(fileidx); - } - win_open(&win); - win_set_cursor(&win, CURSOR_WATCH); - - atexit(cleanup); - - set_timeout(redraw, 25, false); - - run(); - - return 0; -} diff --git a/utils/nsxiv/nsxiv.1 b/utils/nsxiv/nsxiv.1 deleted file mode 100644 index 4488146..0000000 --- a/utils/nsxiv/nsxiv.1 +++ /dev/null @@ -1,561 +0,0 @@ -.TH NSXIV 1 nsxiv\-VERSION -.SH NAME -nsxiv \- Neo Simple X Image Viewer -.SH SYNOPSIS -.B nsxiv -.RB [ \-abcfhiopqrtvZ0 ] -.RB [ \-A -.IR FRAMERATE ] -.RB [ \-e -.IR WID ] -.RB [ \-G -.IR GAMMA ] -.RB [ \-g -.IR GEOMETRY ] -.RB [ \-N -.IR NAME ] -.RB [ \-n -.IR NUM ] -.RB [ \-S -.IR DELAY ] -.RB [ \-s -.IR MODE ] -.RB [ \-z -.IR ZOOM ] -.IR FILE ... -.SH DESCRIPTION -nsxiv is a simple image viewer for X. -.P -It has two modes of operation: image and thumbnail mode. The default is image -mode, in which only the current image is shown. In thumbnail mode a grid of -small previews is displayed, making it easy to choose an image to open. -.P -Please note, that the fullscreen mode requires an EWMH/NetWM-compliant window -manager. -.SH OPTIONS -.TP -.BI "\-A " FRAMERATE -Play animations with a constant frame rate set to -.IR FRAMERATE . -.TP -.B \-a -Play animations of multi-frame images. -.TP -.B \-b -Do not show statusbar at the bottom of the window. -.TP -.B \-c -Remove all orphaned cache files from the thumbnail cache directory and exit. -.TP -.BI "\-e " WID -Embed nsxiv's window into window whose ID is -.IR WID . -.TP -.B \-f -Start in fullscreen mode. -.TP -.BI "\-G " GAMMA -Set image gamma to GAMMA (\-32..32). -.TP -.BI "\-g " GEOMETRY -Set window position and size. See section GEOMETRY SPECIFICATIONS of X(7) for -more information on GEOMETRY argument. -.TP -.BI "\-N " NAME -Set the resource name of nsxiv's X window to NAME. -.TP -.BI "\-n " NUM -Start at picture number NUM. -.TP -.B \-h -Print brief usage information to standard output and exit. -.TP -.B \-i -Read names of files to open from standard input. Also done if FILE is `-'. -.TP -.B \-o -Write list of all marked files to standard output when quitting. In combination -with -.B \-i -nsxiv can be used as a visual filter/pipe. -.TP -.B \-p -Enable private mode, in which nsxiv does not write any cache or temporary files. -.TP -.B \-q -Be quiet, and disable warnings to standard error stream. -.TP -.B \-r -Search the given directories recursively for images to view. -.TP -.BI "\-S " DELAY -Start in slideshow mode. Set the delay between images to -.I DELAY -seconds. -.I DELAY -may be a floating-point number. -.TP -.BI "\-s " MODE -Set scale mode according to MODE character. Supported modes are: [d]own, -[f]it, [F]ill, [w]idth, [h]eight. -.TP -.B \-t -Start in thumbnail mode. -.TP -.B \-v -Print version information to standard output and exit. -.TP -.B \-Z -The same as `\-z 100'. -.TP -.BI "\-z " ZOOM -Set zoom level to ZOOM percent. -.TP -.B \-0 -Use NULL-separator. With this option, output of \-o and file-list sent to the -key-handler and the input of \-i will be separated by a NULL character. -.SH KEYBOARD COMMANDS -.SS General -The following keyboard commands are available in both image and thumbnail modes: -.TP -.BR 0 \- 9 -Prefix the next command with a number (denoted via -.IR count ). -.TP -.B q -Quit nsxiv. -.TP -.B Return -Switch to thumbnail mode / open selected image in image mode. -.TP -.B f -Toggle fullscreen mode. -.TP -.B b -Toggle visibility of statusbar at the bottom of the window. -.TP -.B Ctrl-x -Send the next key to the external key-handler. See section EXTERNAL KEY HANDLER -for more information. -.TP -.B g -Go to the first image. -.TP -.B G -Go to the last image, or image number -.IR count . -.TP -.B r -Reload image. -.TP -.B D -Remove current image from file list and go to next image. -.TP -.BR Ctrl-h ", " Ctrl-Left -Scroll left one screen width. -.TP -.BR Ctrl-j ", " Ctrl-Down -Scroll down one screen height. -.TP -.BR Ctrl-k ", " Ctrl-Up -Scroll up one screen height. -.TP -.BR Ctrl-l ", " Ctrl-Right -Scroll right one screen width. -.TP -.BR + -Zoom in. -.TP -.B \- -Zoom out. -.TP -.B m -Mark/unmark the current image. -.TP -.B M -Mark/unmark all images starting from the last marked/unmarked image up to the -current one. -.TP -.B Ctrl-m -Reverse all image marks. -.TP -.B Ctrl-u -Remove all image marks. -.TP -.B N -Go -.I count -marked images forward. -.TP -.B P -Go -.I count -marked images backward. -.TP -.B { -Decrease gamma correction by -.I count -steps. -.TP -.B } -Increase gamma correction by -.I count -steps. -.TP -.B Ctrl-g -Reset gamma correction. -.SS Thumbnail mode -The following keyboard commands are only available in thumbnail mode: -.TP -.BR h ", " Left -Move selection left -.I count -times. -.TP -.BR j ", " Down -Move selection down -.I count -times. -.TP -.BR k ", " Up -Move selection up -.I count -times. -.TP -.BR l ", " Right -Move selection right -.I count -times. -.TP -.B R -Reload all thumbnails. -.SS Image mode -The following keyboard commands are only available in image mode: -.TP -Navigate image list: -.TP -.BR n ", " Space -Go -.I count -images forward. -.TP -.BR p ", " Backspace -Go -.I count -images backward. -.TP -.B [ -Go -.I count -* 10 images backward. -.TP -.B ] -Go -.I count -* 10 images forward. -.TP -Handle multi-frame images: -.TP -.B Ctrl-n -Go -.I count -frames of a multi-frame image forward. -.TP -.B Ctrl-p -Go -.I count -frames of a multi-frame image backward. -.TP -.BR Ctrl-a ", " Ctrl-Space -Play/stop animations of multi-frame images. -.TP -Panning: -.TP -.BR h ", " Left -Scroll image 1/5 of window width or -.I count -pixels left. -.TP -.BR j ", " Down -Scroll image 1/5 of window height or -.I count -pixels down. -.TP -.BR k ", " Up -Scroll image 1/5 of window height or -.I count -pixels up. -.TP -.BR l ", " Right -Scroll image 1/5 of window width or -.I count -pixels right. -.TP -.B H -Scroll to left image edge. -.TP -.B J -Scroll to bottom image edge. -.TP -.B K -Scroll to top image edge. -.TP -.B L -Scroll to right image edge. -.TP -.B z -Scroll to image center. -.TP -Zooming: -.TP -.B = -Set zoom level to 100%, or -.IR count %. -.TP -.B w -Set zoom level to 100%, but fit large images into window. -.TP -.B W -Fit image to window. -.TP -.B F -Fill image to window. -.TP -.B e -Fit image to window width. -.TP -.B E -Fit image to window height. -.TP -Rotation: -.TP -.B < -Rotate image counter-clockwise by 90 degrees. -.TP -.B > -Rotate image clockwise by 90 degrees. -.TP -.B ? -Rotate image by 180 degrees. -.TP -Flipping: -.TP -.B | -Flip image horizontally. -.TP -.B _ -Flip image vertically. -.TP -Miscellaneous: -.TP -.B a -Toggle anti-aliasing. -.TP -.B A -Toggle visibility of alpha-channel, i.e. image transparency. -.TP -.B s -Toggle slideshow mode and/or set the delay between images to -.I count -seconds. -.SH MOUSE COMMANDS -.SS Thumbnail mode -The following mouse mappings are available in thumbnail mode: -.TP -.B Button1 -Select the image. Goes into image mode if double\-clicked. -.TP -.B Button3 -Mark/unmark the image. Dragging while holding down Button3 will mark/unmark -multiple images. -.TP -.B Button4 -Scroll up by one row. -.TP -.B Button5 -Scroll down by one row. -.TP -.B Ctrl-Button4 -Scroll up by one page. -.TP -.B Ctrl-Button5 -Scroll down by one page. -.SS Image mode -The following mouse mappings are available in image mode: -.TP -.B Button1 -Go to the next image if the mouse cursor is in the right part of the window or -to the previous image if it is in the left part. -.TP -.B Ctrl-Button1 -Pan the image relative to the mouse cursor. -.TP -.B Button2 -Pan the image according to the mouse cursor position in the window while -keeping this button pressed down. -.TP -.B Button3 -Switch to thumbnail mode. -.TP -.B Button4 -Zoom in. -.TP -.B Button5 -Zoom out. -.SH CONFIGURATION -The following X resources are supported: -.TP -.B window.background -Color of the window background -.TP -.B window.foreground -Color of the window foreground -.TP -.B bar.font -Name of Xft bar font -.TP -.B bar.background -Color of the bar background. Defaults to window.background -.TP -.B bar.foreground -Color of the bar foreground. Defaults to window.foreground -.TP -.B mark.foreground -Color of the mark foreground. Defaults to window.foreground -.TP -Please see xrdb(1) on how to change them. -.SH WINDOW TITLE -The window title can be replaced with the output of a user-provided script, -which is called by nsxiv whenever there's a redraw. The path of this script is -.I $XDG_CONFIG_HOME/nsxiv/exec/win-title -and the arguments given to it (where "Optional" arguments might be empty) are: -.IP $1 4 -resolved absolute path of the current file -.IP $2 4 -current file number -.IP $3 4 -total file count -.IP $4 4 -image width (Optional: Disabled on thumbnails mode) -.IP $5 4 -image height (Optional: Disabled on thumbnails mode) -.IP $6 4 -current zoom (Optional: Disabled on thumbnails mode) -.P -The term file is used rather than image as nsxiv does not precheck that the -input files are valid images. Total file count may be different from the actual -count of valid images. -.P -There is also an example script installed together with nsxiv as -.IR EGPREFIX/win-title . -.SH STATUS BAR -The information displayed on the left side of the status bar can be replaced -with the output of user-provided script. -.P -The script that is called by nsxiv whenever an image gets loaded is located at -.I $XDG_CONFIG_HOME/nsxiv/exec/image-info -and the arguments given to it are: -.IP $1 4 -path to image file (as provided by the user) -.IP $2 4 -image width -.IP $3 4 -image height -.IP $4 4 -fully resolved path to the image file -.P -In thumbnail mode, the script that is called is located at -.I $XDG_CONFIG_HOME/nsxiv/exec/thumb-info -and the arguments given to it are: -.IP $1 4 -path to image file (as provided by the user) -.IP $2 4 -empty -.IP $3 4 -empty -.IP $4 4 -fully resolved path to the image file -.P -There are also example scripts installed together with nsxiv as -.IR EGPREFIX/image-info -and -.IR EGPREFIX/thumb-info . -.SH EXTERNAL KEY HANDLER -Additional external keyboard commands can be defined using a handler program -located in -.IR $XDG_CONFIG_HOME/nsxiv/exec/key-handler . -The handler is invoked by pressing -.BR Ctrl-x . -The next key combo is passed as its first argument. Passed via stdin are the -images to act upon: all marked images, if in thumbnail mode and at least one -image has been marked, otherwise the current image. nsxiv(1) will block until -the handler terminates. It then checks which images have been modified and -reloads them. - -By default nsxiv(1) will send one image per-line to stdin, however when using -\-0 the image list will be NULL separated and the environment variable -"$NSXIV_USING_NULL" will be set to 1. - -The key combo argument has the following form: "[C-][M-][S-]KEY", -where C/M/S indicate Ctrl/Meta(Alt)/Shift modifier states and KEY is the X -keysym as listed in /usr/include/X11/keysymdef.h without the "XK_" prefix. -If KEY has an uppercase equivalent, S-KEY is resolved into it. For instance, -K replaces S-k and Scedilla replaces S-scedilla, but S-Delete is sent as-is. - -There is also an example script installed together with nsxiv as -.IR EGPREFIX/key-handler . -.SH THUMBNAIL CACHING -nsxiv stores all thumbnails under -.IR $XDG_CACHE_HOME/nsxiv/ . -.P -Use the command line option -.I \-c -to remove all orphaned cache files. Additionally, run the following command -afterwards inside the cache directory to remove empty subdirectories: -.P -.RS -find . \-depth \-type d \-empty ! \-name '.' \-exec rmdir {} \\; -.RE -.SH ORIGINAL AUTHOR -.EX -Bert Muennich <ber.t at posteo.de> -.EE -.SH CURRENT MAINTAINERS -.EX -N-R-K <nrk at disroot.org> -Berke KocaoÄŸlu <berke.kocaoglu at metu.edu.tr> -TAAPArthur <taaparthur at gmail.com> -eylles <ed.ylles1997 at gmail.com> -mamg22 <marcomonizg at gmail.com> -LuXu -explosion-mental <explosion0mental at gmail.com> -Guilherme Freire -Stein Gunnar Bakkeby <bakkeby at gmail.com> -Anupam Ashish Minz -Sam Whitehead -Kian Kasad <kian at kasad.com> -qsmodo -.EE -.SH CONTRIBUTORS -.EX -Bastien Dejean <nihilhill at gmail.com> -Dave Reisner <d at falconindy.com> -Fung SzeTat <sthorde at gmail.com> -Max Voit <mvdev at with-eyes.net> - -For additional contributors, run `git shortlog -s` in the nsxiv repository. -.EE -.SH HOMEPAGE -.TP -Website: -.EE -https://nsxiv.github.io/nsxiv/ -.EX -.TP -Source code: -.EE -https://github.com/nsxiv/nsxiv -.EX -.SH SEE ALSO -.BR X (7), -.BR xrdb (1) diff --git a/utils/nsxiv/nsxiv.desktop b/utils/nsxiv/nsxiv.desktop deleted file mode 100644 index de90437..0000000 --- a/utils/nsxiv/nsxiv.desktop +++ /dev/null @@ -1,8 +0,0 @@ -[Desktop Entry] -Type=Application -Name=nsxiv -GenericName=Image Viewer -Exec=nsxiv %F -MimeType=image/bmp;image/gif;image/jpeg;image/jpg;image/png;image/tiff;image/x-bmp;image/x-portable-anymap;image/x-portable-bitmap;image/x-portable-graymap;image/x-tga;image/x-xpixmap;image/webp;image/heic;image/svg+xml;application/postscript;image/jp2;image/jxl;image/avif;image/heif; -NoDisplay=true -Icon=nsxiv diff --git a/utils/nsxiv/nsxiv.h b/utils/nsxiv/nsxiv.h deleted file mode 100644 index f9f5600..0000000 --- a/utils/nsxiv/nsxiv.h +++ /dev/null @@ -1,485 +0,0 @@ -/* Copyright 2011-2020 Bert Muennich - * Copyright 2021-2022 nsxiv contributors - * - * This file is a part of nsxiv. - * - * nsxiv is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, - * or (at your option) any later version. - * - * nsxiv is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with nsxiv. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef NSXIV_H -#define NSXIV_H - -#include <stdarg.h> -#include <stdbool.h> -#include <stdio.h> -#include <sys/time.h> -#include <sys/types.h> -#include <Imlib2.h> -#include <X11/Xlib.h> - -/* - * Annotation for functions called in cleanup(). - * These functions are not allowed to call error(!0, ...) or exit(). - */ -#define CLEANUP - -#define MIN(a,b) ((a) < (b) ? (a) : (b)) -#define MAX(a,b) ((a) > (b) ? (a) : (b)) -#define ABS(a) ((a) > 0 ? (a) : -(a)) - -#define ARRLEN(a) (sizeof(a) / sizeof((a)[0])) - -#define STREQ(s1,s2) (strcmp((s1), (s2)) == 0) - -#define TV_DIFF(t1,t2) (((t1)->tv_sec - (t2)->tv_sec ) * 1000 + \ - ((t1)->tv_usec - (t2)->tv_usec) / 1000) -#define TV_TO_MS(tv) (((tv)->tv_sec * 1000) + ((tv)->tv_usec / 1000)) - -#define TV_SET_MSEC(tv,t) { \ - (tv)->tv_sec = (t) / 1000; \ - (tv)->tv_usec = (t) % 1000 * 1000; \ -} - -#define TV_ADD_MSEC(tv,t) { \ - (tv)->tv_sec += (t) / 1000; \ - (tv)->tv_usec += (t) % 1000 * 1000; \ -} - -typedef enum { - MODE_ALL, - MODE_IMAGE, - MODE_THUMB -} appmode_t; - -typedef enum { - DIR_LEFT = 1, - DIR_RIGHT = 2, - DIR_UP = 4, - DIR_DOWN = 8 -} direction_t; - -typedef enum { - DEGREE_90 = 1, - DEGREE_180 = 2, - DEGREE_270 = 3 -} degree_t; - -typedef enum { - FLIP_HORIZONTAL = 1, - FLIP_VERTICAL = 2 -} flipdir_t; - -typedef enum { - SCALE_DOWN, - SCALE_FIT, - SCALE_FILL, - SCALE_WIDTH, - SCALE_HEIGHT, - SCALE_ZOOM -} scalemode_t; - -typedef enum { - DRAG_RELATIVE, - DRAG_ABSOLUTE -} dragmode_t; - -typedef enum { - CURSOR_ARROW, - CURSOR_DRAG_ABSOLUTE, - CURSOR_DRAG_RELATIVE, - CURSOR_WATCH, - CURSOR_LEFT, - CURSOR_RIGHT, - CURSOR_NONE, - - CURSOR_COUNT -} cursor_t; - -typedef enum { - FF_WARN = 1, - FF_MARK = 2, - FF_TN_INIT = 4 -} fileflags_t; - -typedef struct { - const char *name; /* as given by user */ - const char *path; /* always absolute */ - fileflags_t flags; -} fileinfo_t; - -/* timeouts in milliseconds: */ -enum { - TO_REDRAW_RESIZE = 75, - TO_REDRAW_THUMBS = 200, - TO_CURSOR_HIDE = 1200, - TO_DOUBLE_CLICK = 300 -}; - -typedef void (*timeout_f)(void); - -typedef struct arl arl_t; -typedef struct img img_t; -typedef struct opt opt_t; -typedef struct tns tns_t; -typedef struct win win_t; - - -/* autoreload.c */ - -struct arl { - int fd; - int wd_dir; - int wd_file; - char *filename; -}; - -void arl_init(arl_t*); -void arl_cleanup(arl_t*); -void arl_setup(arl_t*, const char* /* result of realpath(3) */); -bool arl_handle(arl_t*); - - -/* commands.c */ - -typedef int arg_t; -typedef bool (*cmd_f)(arg_t); - -typedef struct { - cmd_f func; - appmode_t mode; -} cmd_t; - -typedef struct { - unsigned int mask; - KeySym ksym_or_button; - cmd_t cmd; - arg_t arg; -} keymap_t; - -typedef keymap_t button_t; - - -/* image.c */ - -typedef struct { - Imlib_Image im; - unsigned int delay; -} img_frame_t; - -typedef struct { - img_frame_t *frames; - int cap; - int cnt; - int sel; - bool animate; - unsigned int framedelay; - int length; -} multi_img_t; - -struct img { - Imlib_Image im; - int w; - int h; - - win_t *win; - float x; - float y; - - Imlib_Color_Modifier cmod; - int gamma; - - scalemode_t scalemode; - float zoom; - - bool checkpan; - bool dirty; - bool aa; - bool alpha; - - struct { - bool on; - int delay; - } ss; - - multi_img_t multi; -}; - -void img_init(img_t*, win_t*); -bool img_load(img_t*, const fileinfo_t*); -CLEANUP void img_close(img_t*, bool); -void img_render(img_t*); -bool img_fit_win(img_t*, scalemode_t); -bool img_zoom(img_t*, int); -bool img_zoom_to(img_t*, float); -bool img_pos(img_t*, float, float); -bool img_pan(img_t*, direction_t, int); -bool img_pan_center(img_t*); -bool img_pan_edge(img_t*, direction_t); -void img_rotate(img_t*, degree_t); -void img_flip(img_t*, flipdir_t); -void img_toggle_antialias(img_t*); -bool img_change_gamma(img_t*, int); -bool img_frame_navigate(img_t*, int); -bool img_frame_animate(img_t*); -Imlib_Image img_open(const fileinfo_t*); -#if HAVE_LIBEXIF -void exif_auto_orientate(const fileinfo_t*); -#endif - - -/* options.c */ - -struct opt { - /* file list: */ - char **filenames; - bool from_stdin; - bool to_stdout; - bool using_null; - bool recursive; - int filecnt; - int startnum; - - /* image: */ - scalemode_t scalemode; - float zoom; - bool animate; - int gamma; - int slideshow; - int framerate; - - /* window: */ - bool fullscreen; - bool hide_bar; - Window embed; /* unsigned long */ - char *geometry; - char *res_name; - - /* misc flags: */ - bool quiet; - bool thumb_mode; - bool clean_cache; - bool private_mode; -}; - -extern const opt_t *options; - -void print_usage(void); -void parse_options(int, char**); - - -/* thumbs.c */ - -typedef struct { - Imlib_Image im; - int w; - int h; - int x; - int y; -} thumb_t; - -struct tns { - fileinfo_t *files; - thumb_t *thumbs; - const int *cnt; - int *sel; - int initnext; - int loadnext; - int first, end; - int r_first, r_end; - - win_t *win; - int x; - int y; - int cols; - int rows; - int zl; - int bw; - int dim; - - bool dirty; -}; - -void tns_clean_cache(void); -void tns_init(tns_t*, fileinfo_t*, const int*, int*, win_t*); -CLEANUP void tns_free(tns_t*); -bool tns_load(tns_t*, int, bool, bool); -void tns_unload(tns_t*, int); -void tns_render(tns_t*); -void tns_mark(tns_t*, int, bool); -void tns_highlight(tns_t*, int, bool); -bool tns_move_selection(tns_t*, direction_t, int); -bool tns_scroll(tns_t*, direction_t, bool); -bool tns_zoom(tns_t*, int); -int tns_translate(tns_t*, int, int); - - -/* util.c */ - -#include <dirent.h> - -typedef struct { - DIR *dir; - char *name; - int d; - bool recursive; - - char **stack; - int stcap; - int stlen; -} r_dir_t; - -typedef struct { - int readfd; - int writefd; - pid_t pid; -} spawn_t; - -enum { - X_READ = (1 << 0), - X_WRITE = (1 << 1) -}; - -extern const char *progname; - -void* emalloc(size_t); -void* ecalloc(size_t, size_t); -void* erealloc(void*, size_t); -char* estrdup(const char*); -void error(int, int, const char*, ...); -int r_opendir(r_dir_t*, const char*, bool); -int r_closedir(r_dir_t*); -char* r_readdir(r_dir_t*, bool); -int r_mkdir(char*); -void construct_argv(char**, unsigned int, ...); -spawn_t spawn(const char*, char *const [], unsigned int); - - -/* window.c */ - -#include <X11/Xutil.h> -#if HAVE_LIBFONTS -#include <X11/Xft/Xft.h> -#endif - -enum { - BAR_L_LEN = 512, - BAR_R_LEN = 64 -}; - -enum { - ATOM_WM_DELETE_WINDOW, - ATOM__NET_WM_NAME, - ATOM__NET_WM_ICON_NAME, - ATOM__NET_WM_ICON, - ATOM__NET_WM_STATE, - ATOM__NET_WM_PID, - ATOM__NET_WM_STATE_FULLSCREEN, - ATOM_UTF8_STRING, - ATOM_WM_NAME, - ATOM_WM_ICON_NAME, - ATOM_COUNT -}; - -typedef struct { - Display *dpy; - int scr; - int scrw, scrh; - Visual *vis; - Colormap cmap; - int depth; -} win_env_t; - -typedef struct { - size_t size; - char *p; - char *buf; -} win_bar_t; - -struct win { - Window xwin; - win_env_t env; - - XColor win_bg; - XColor win_fg; - XColor mrk_fg; -#if HAVE_LIBFONTS - XftColor bar_bg; - XftColor bar_fg; -#endif - - int x; - int y; - unsigned int w; - unsigned int h; /* = win height - bar height */ - unsigned int bw; - - struct { - int w; - int h; - Pixmap pm; - } buf; - - struct { - unsigned int h; - bool top; - win_bar_t l; - win_bar_t r; - } bar; -}; - -extern Atom atoms[ATOM_COUNT]; - -void win_init(win_t*); -void win_open(win_t*); -CLEANUP void win_close(win_t*); -bool win_configure(win_t*, XConfigureEvent*); -void win_toggle_fullscreen(win_t*); -void win_toggle_bar(win_t*); -void win_clear(win_t*); -void win_draw(win_t*); -void win_draw_rect(win_t*, int, int, int, int, bool, int, unsigned long); -void win_set_title(win_t*, bool); -void win_set_cursor(win_t*, cursor_t); -void win_cursor_pos(win_t*, int*, int*); - -/* main.c */ - -/* timeout handler functions: */ -void redraw(void); -void reset_cursor(void); -void animate(void); -void slideshow(void); -void clear_resize(void); - -void remove_file(int, bool); -void set_timeout(timeout_f, int, bool); -void reset_timeout(timeout_f); -size_t get_win_title(unsigned char*, int, bool); -void close_info(void); -void open_info(void); -void load_image(int); -bool mark_image(int, bool); -int nav_button(void); -void handle_key_handler(bool); - -extern appmode_t mode; -extern const XButtonEvent *xbutton_ev; -extern fileinfo_t *files; -extern int filecnt, fileidx; -extern int alternate; -extern int markcnt; -extern int markidx; -extern int prefix; - -#endif /* NSXIV_H */ diff --git a/utils/nsxiv/options.c b/utils/nsxiv/options.c deleted file mode 100644 index 96cf092..0000000 --- a/utils/nsxiv/options.c +++ /dev/null @@ -1,200 +0,0 @@ -/* Copyright 2011-2020 Bert Muennich - * Copyright 2021-2022 nsxiv contributors - * - * This file is a part of nsxiv. - * - * nsxiv is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, - * or (at your option) any later version. - * - * nsxiv is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with nsxiv. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "nsxiv.h" -#include "version.h" - -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -const opt_t *options; - -void print_usage(void) -{ - printf("usage: nsxiv [-abcfhiopqrtvZ0] [-A FRAMERATE] [-e WID] [-G GAMMA] " - "[-g GEOMETRY] [-N NAME] [-n NUM] [-S DELAY] [-s MODE] " - "[-z ZOOM] FILES...\n"); -} - -static void title_deprecation_notice(void) -{ - error(EXIT_FAILURE, 0, "\n" - "################################################################\n" - "# DEPRECATION NOTICE #\n" - "################################################################\n" - "# `-T` option has been deprecated in favour of `win-title`. #\n" - "# Please read the `WINDOW TITLE` section of the manpage for #\n" - "# more info. #\n" - "################################################################" - ); -} - -static void print_version(void) -{ - puts("nsxiv " VERSION); -} - -void parse_options(int argc, char **argv) -{ - int n, opt; - char *end, *s; - const char *scalemodes = "dfFwh"; - static opt_t _options; - options = &_options; - - progname = strrchr(argv[0], '/'); - progname = progname ? progname + 1 : argv[0]; - - _options.from_stdin = false; - _options.to_stdout = false; - _options.using_null = false; - _options.recursive = false; - _options.startnum = 0; - - _options.scalemode = SCALE_DOWN; - _options.zoom = 1.0; - _options.animate = false; - _options.gamma = 0; - _options.slideshow = 0; - _options.framerate = 0; - - _options.fullscreen = false; - _options.embed = 0; - _options.hide_bar = false; - _options.geometry = NULL; - _options.res_name = NULL; - - _options.quiet = false; - _options.thumb_mode = false; - _options.clean_cache = false; - _options.private_mode = false; - - while ((opt = getopt(argc, argv, "A:abce:fG:g:hin:N:opqrS:s:T:tvZz:0")) != -1) { - switch (opt) { - case '?': - print_usage(); - exit(EXIT_FAILURE); - case 'A': - n = strtol(optarg, &end, 0); - if (*end != '\0' || n <= 0) - error(EXIT_FAILURE, 0, "Invalid argument for option -A: %s", optarg); - _options.framerate = n; - /* fall through */ - case 'a': - _options.animate = true; - break; - case 'b': - _options.hide_bar = true; - break; - case 'c': - _options.clean_cache = true; - break; - case 'e': - n = strtol(optarg, &end, 0); - if (*end != '\0') - error(EXIT_FAILURE, 0, "Invalid argument for option -e: %s", optarg); - _options.embed = n; - break; - case 'f': - _options.fullscreen = true; - break; - case 'G': - n = strtol(optarg, &end, 0); - if (*end != '\0') - error(EXIT_FAILURE, 0, "Invalid argument for option -G: %s", optarg); - _options.gamma = n; - break; - case 'g': - _options.geometry = optarg; - break; - case 'h': - print_usage(); - exit(EXIT_SUCCESS); - case 'i': - _options.from_stdin = true; - break; - case 'n': - n = strtol(optarg, &end, 0); - if (*end != '\0' || n <= 0) - error(EXIT_FAILURE, 0, "Invalid argument for option -n: %s", optarg); - _options.startnum = n - 1; - break; - case 'N': - _options.res_name = optarg; - break; - case 'o': - _options.to_stdout = true; - break; - case 'p': - _options.private_mode = true; - break; - case 'q': - _options.quiet = true; - break; - case 'r': - _options.recursive = true; - break; - case 'S': - n = strtof(optarg, &end) * 10; - if (*end != '\0' || n <= 0) - error(EXIT_FAILURE, 0, "Invalid argument for option -S: %s", optarg); - _options.slideshow = n; - break; - case 's': - s = strchr(scalemodes, optarg[0]); - if (s == NULL || *s == '\0' || strlen(optarg) != 1) - error(EXIT_FAILURE, 0, "Invalid argument for option -s: %s", optarg); - _options.scalemode = s - scalemodes; - break; - case 'T': - title_deprecation_notice(); /* TODO(v30): remove this option */ - break; - case 't': - _options.thumb_mode = true; - break; - case 'v': - print_version(); - exit(EXIT_SUCCESS); - case 'Z': - _options.scalemode = SCALE_ZOOM; - _options.zoom = 1.0; - break; - case 'z': - n = strtol(optarg, &end, 0); - if (*end != '\0' || n <= 0) - error(EXIT_FAILURE, 0, "Invalid argument for option -z: %s", optarg); - _options.scalemode = SCALE_ZOOM; - _options.zoom = (float) n / 100.0; - break; - case '0': - _options.using_null = true; - break; - } - } - - _options.filenames = argv + optind; - _options.filecnt = argc - optind; - - if (_options.filecnt == 1 && STREQ(_options.filenames[0], "-")) { - _options.filenames++; - _options.filecnt--; - _options.from_stdin = true; - } -} diff --git a/utils/nsxiv/thumbs.c b/utils/nsxiv/thumbs.c deleted file mode 100644 index 52820d4..0000000 --- a/utils/nsxiv/thumbs.c +++ /dev/null @@ -1,591 +0,0 @@ -/* Copyright 2011-2020 Bert Muennich - * Copyright 2021-2022 nsxiv contributors - * - * This file is a part of nsxiv. - * - * nsxiv is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, - * or (at your option) any later version. - * - * nsxiv is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with nsxiv. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "nsxiv.h" -#define _THUMBS_CONFIG -#include "config.h" - -#include <errno.h> -#include <stdlib.h> -#include <string.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <utime.h> - -#if HAVE_LIBEXIF -#include <libexif/exif-data.h> -#endif - -static char *cache_dir; - -static char* tns_cache_filepath(const char *filepath) -{ - size_t len; - char *cfile = NULL; - - if (*filepath != '/') - return NULL; - - if (strncmp(filepath, cache_dir, strlen(cache_dir)) != 0) { - /* don't cache images inside the cache directory! */ - len = strlen(cache_dir) + strlen(filepath) + 2; - cfile = emalloc(len); - snprintf(cfile, len, "%s/%s", cache_dir, filepath + 1); - } - return cfile; -} - -static Imlib_Image tns_cache_load(const char *filepath, bool *outdated) -{ - char *cfile; - struct stat cstats, fstats; - Imlib_Image im = NULL; - - if (stat(filepath, &fstats) < 0) - return NULL; - - if ((cfile = tns_cache_filepath(filepath)) != NULL) { - if (stat(cfile, &cstats) == 0) { - if (cstats.st_mtime == fstats.st_mtime) - im = imlib_load_image(cfile); - else - *outdated = true; - } - free(cfile); - } - return im; -} - -static void tns_cache_write(Imlib_Image im, const char *filepath, bool force) -{ - char *cfile, *dirend; - struct stat cstats, fstats; - struct utimbuf times; - Imlib_Load_Error err; - - if (options->private_mode) - return; - - if (stat(filepath, &fstats) < 0) - return; - - if ((cfile = tns_cache_filepath(filepath)) != NULL) { - if (force || stat(cfile, &cstats) < 0 || - cstats.st_mtime != fstats.st_mtime) - { - if ((dirend = strrchr(cfile, '/')) != NULL) { - *dirend = '\0'; - if (r_mkdir(cfile) == -1) { - error(0, errno, "%s", cfile); - goto end; - } - *dirend = '/'; - } - imlib_context_set_image(im); - if (imlib_image_has_alpha()) { - imlib_image_set_format("png"); - } else { - imlib_image_set_format("jpg"); - imlib_image_attach_data_value("quality", NULL, 90, NULL); - } - imlib_save_image_with_error_return(cfile, &err); - if (err) - goto end; - times.actime = fstats.st_atime; - times.modtime = fstats.st_mtime; - utime(cfile, ×); - } -end: - free(cfile); - } -} - -void tns_clean_cache(void) -{ - int dirlen; - char *cfile, *filename; - r_dir_t dir; - - if (r_opendir(&dir, cache_dir, true) < 0) { - error(0, errno, "%s", cache_dir); - return; - } - - dirlen = strlen(cache_dir); - - while ((cfile = r_readdir(&dir, false)) != NULL) { - filename = cfile + dirlen; - if (access(filename, F_OK) < 0) { - if (unlink(cfile) < 0) - error(0, errno, "%s", cfile); - } - free(cfile); - } - r_closedir(&dir); -} - -void tns_init(tns_t *tns, fileinfo_t *tns_files, const int *cnt, int *sel, win_t *win) -{ - int len; - const char *homedir, *dsuffix = ""; - - if (cnt != NULL && *cnt > 0) - tns->thumbs = ecalloc(*cnt, sizeof(thumb_t)); - else - tns->thumbs = NULL; - tns->files = tns_files; - tns->cnt = cnt; - tns->initnext = tns->loadnext = 0; - tns->first = tns->end = tns->r_first = tns->r_end = 0; - tns->sel = sel; - tns->win = win; - tns->dirty = false; - - tns->zl = THUMB_SIZE; - tns_zoom(tns, 0); - - if ((homedir = getenv("XDG_CACHE_HOME")) == NULL || homedir[0] == '\0') { - homedir = getenv("HOME"); - dsuffix = "/.cache"; - } - if (homedir != NULL) { - const char *s = "/nsxiv"; - free(cache_dir); - len = strlen(homedir) + strlen(dsuffix) + strlen(s) + 1; - cache_dir = emalloc(len); - snprintf(cache_dir, len, "%s%s%s", homedir, dsuffix, s); - } else { - error(0, 0, "Cache directory not found"); - } -} - -CLEANUP void tns_free(tns_t *tns) -{ - int i; - - if (tns->thumbs != NULL) { - for (i = 0; i < *tns->cnt; i++) { - if (tns->thumbs[i].im != NULL) { - imlib_context_set_image(tns->thumbs[i].im); - imlib_free_image(); - } - } - free(tns->thumbs); - tns->thumbs = NULL; - } - - free(cache_dir); - cache_dir = NULL; -} - -static Imlib_Image tns_scale_down(Imlib_Image im, int dim) -{ - int w, h; - float z, zw, zh; - - imlib_context_set_image(im); - w = imlib_image_get_width(); - h = imlib_image_get_height(); - zw = (float) dim / (float) w; - zh = (float) dim / (float) h; - z = MIN(zw, zh); - z = MIN(z, 1.0); - - if (z < 1.0) { - imlib_context_set_anti_alias(1); - im = imlib_create_cropped_scaled_image(0, 0, w, h, - MAX(z * w, 1), MAX(z * h, 1)); - if (im == NULL) - error(EXIT_FAILURE, ENOMEM, NULL); - imlib_free_image_and_decache(); - } - return im; -} - -bool tns_load(tns_t *tns, int n, bool force, bool cache_only) -{ - int maxwh = thumb_sizes[ARRLEN(thumb_sizes)-1]; - bool cache_hit = false; - char *cfile; - thumb_t *t; - fileinfo_t *file; - Imlib_Image im = NULL; - - if (n < 0 || n >= *tns->cnt) - return false; - file = &tns->files[n]; - if (file->name == NULL || file->path == NULL) - return false; - - t = &tns->thumbs[n]; - - if (t->im != NULL) { - imlib_context_set_image(t->im); - imlib_free_image(); - t->im = NULL; - } - - if (!force) { - if ((im = tns_cache_load(file->path, &force)) != NULL) { - imlib_context_set_image(im); - if (imlib_image_get_width() < maxwh && - imlib_image_get_height() < maxwh) - { - if ((cfile = tns_cache_filepath(file->path)) != NULL) { - unlink(cfile); - free(cfile); - } - imlib_free_image_and_decache(); - im = NULL; - } else { - cache_hit = true; - } -#if HAVE_LIBEXIF - } else if (!force && !options->private_mode) { - int pw = 0, ph = 0, w, h, x = 0, y = 0; - bool err; - float zw, zh; - ExifData *ed; - ExifEntry *entry; - ExifContent *ifd; - ExifByteOrder byte_order; - int tmpfd; - char tmppath[] = "/tmp/nsxiv-XXXXXX"; - Imlib_Image tmpim; - - if ((ed = exif_data_new_from_file(file->path)) != NULL) { - if (ed->data != NULL && ed->size > 0 && - (tmpfd = mkstemp(tmppath)) >= 0) - { - err = write(tmpfd, ed->data, ed->size) != ed->size; - close(tmpfd); - - if (!err && (tmpim = imlib_load_image(tmppath)) != NULL) { - byte_order = exif_data_get_byte_order(ed); - ifd = ed->ifd[EXIF_IFD_EXIF]; - entry = exif_content_get_entry(ifd, EXIF_TAG_PIXEL_X_DIMENSION); - if (entry != NULL) - pw = exif_get_long(entry->data, byte_order); - entry = exif_content_get_entry(ifd, EXIF_TAG_PIXEL_Y_DIMENSION); - if (entry != NULL) - ph = exif_get_long(entry->data, byte_order); - - imlib_context_set_image(tmpim); - w = imlib_image_get_width(); - h = imlib_image_get_height(); - - if (pw > w && ph > h && (pw - ph >= 0) == (w - h >= 0)) { - zw = (float) pw / (float) w; - zh = (float) ph / (float) h; - if (zw < zh) { - pw /= zh; - x = (w - pw) / 2; - w = pw; - } else if (zw > zh) { - ph /= zw; - y = (h - ph) / 2; - h = ph; - } - } - if (w >= maxwh || h >= maxwh) { - if ((im = imlib_create_cropped_image(x, y, w, h)) == NULL) - error(0, 0, "%s: error generating thumbnail", file->name); - } - imlib_free_image_and_decache(); - } - unlink(tmppath); - } - exif_data_unref(ed); - } -#endif /* HAVE_LIBEXIF */ - } - } - - if (im == NULL) { - if ((im = img_open(file)) == NULL) - return false; - } - imlib_context_set_image(im); - - if (!cache_hit) { -#if HAVE_LIBEXIF - exif_auto_orientate(file); -#endif - im = tns_scale_down(im, maxwh); - imlib_context_set_image(im); - if (imlib_image_get_width() == maxwh || imlib_image_get_height() == maxwh) - tns_cache_write(im, file->path, true); - } - - if (cache_only) { - imlib_free_image_and_decache(); - } else { - t->im = tns_scale_down(im, thumb_sizes[tns->zl]); - imlib_context_set_image(t->im); - t->w = imlib_image_get_width(); - t->h = imlib_image_get_height(); - tns->dirty = true; - } - file->flags |= FF_TN_INIT; - - if (n == tns->initnext) - while (++tns->initnext < *tns->cnt && ((++file)->flags & FF_TN_INIT)); - if (n == tns->loadnext && !cache_only) - while (++tns->loadnext < tns->end && (++t)->im != NULL); - - return true; -} - -void tns_unload(tns_t *tns, int n) -{ - thumb_t *t; - - if (n < 0 || n >= *tns->cnt) - return; - - t = &tns->thumbs[n]; - - if (t->im != NULL) { - imlib_context_set_image(t->im); - imlib_free_image(); - t->im = NULL; - } -} - -static void tns_check_view(tns_t *tns, bool scrolled) -{ - int r; - - if (tns == NULL) - return; - - tns->first -= tns->first % tns->cols; - r = *tns->sel % tns->cols; - - if (scrolled) { - /* move selection into visible area */ - if (*tns->sel >= tns->first + tns->cols * tns->rows) - *tns->sel = tns->first + r + tns->cols * (tns->rows - 1); - else if (*tns->sel < tns->first) - *tns->sel = tns->first + r; - } else { - /* scroll to selection */ - if (tns->first + tns->cols * tns->rows <= *tns->sel) { - tns->first = *tns->sel - r - tns->cols * (tns->rows - 1); - tns->dirty = true; - } else if (tns->first > *tns->sel) { - tns->first = *tns->sel - r; - tns->dirty = true; - } - } -} - -void tns_render(tns_t *tns) -{ - thumb_t *t; - win_t *win; - int i, cnt, r, x, y; - - if (!tns->dirty) - return; - - win = tns->win; - win_clear(win); - imlib_context_set_drawable(win->buf.pm); - - tns->cols = MAX(1, win->w / tns->dim); - tns->rows = MAX(1, win->h / tns->dim); - - if (*tns->cnt < tns->cols * tns->rows) { - tns->first = 0; - cnt = *tns->cnt; - } else { - tns_check_view(tns, false); - cnt = tns->cols * tns->rows; - if ((r = tns->first + cnt - *tns->cnt) >= tns->cols) - tns->first -= r - r % tns->cols; - if (r > 0) - cnt -= r % tns->cols; - } - r = cnt % tns->cols ? 1 : 0; - tns->x = x = (win->w - MIN(cnt, tns->cols) * tns->dim) / 2 + tns->bw + 3; - tns->y = y = (win->h - (cnt / tns->cols + r) * tns->dim) / 2 + tns->bw + 3 + - (win->bar.top ? win->bar.h : 0); - tns->loadnext = *tns->cnt; - tns->end = tns->first + cnt; - - for (i = tns->r_first; i < tns->r_end; i++) { - if ((i < tns->first || i >= tns->end) && tns->thumbs[i].im != NULL) - tns_unload(tns, i); - } - tns->r_first = tns->first; - tns->r_end = tns->end; - - for (i = tns->first; i < tns->end; i++) { - t = &tns->thumbs[i]; - if (t->im != NULL) { - t->x = x + (thumb_sizes[tns->zl] - t->w) / 2; - t->y = y + (thumb_sizes[tns->zl] - t->h) / 2; - imlib_context_set_image(t->im); - imlib_render_image_on_drawable_at_size(t->x, t->y, t->w, t->h); - if (tns->files[i].flags & FF_MARK) - tns_mark(tns, i, true); - } else { - tns->loadnext = MIN(tns->loadnext, i); - } - if ((i + 1) % tns->cols == 0) { - x = tns->x; - y += tns->dim; - } else { - x += tns->dim; - } - } - tns->dirty = false; - tns_highlight(tns, *tns->sel, true); -} - -void tns_mark(tns_t *tns, int n, bool mark) -{ - if (n >= 0 && n < *tns->cnt && tns->thumbs[n].im != NULL) { - win_t *win = tns->win; - thumb_t *t = &tns->thumbs[n]; - unsigned long col = win->win_bg.pixel; - int x = t->x + t->w, y = t->y + t->h; - - win_draw_rect(win, x - 1, y + 1, 1, tns->bw, true, 1, col); - win_draw_rect(win, x + 1, y - 1, tns->bw, 1, true, 1, col); - - if (mark) - col = win->mrk_fg.pixel; - - win_draw_rect(win, x, y, tns->bw + 2, tns->bw + 2, true, 1, col); - - if (!mark && n == *tns->sel) - tns_highlight(tns, n, true); - } -} - -void tns_highlight(tns_t *tns, int n, bool hl) -{ - if (n >= 0 && n < *tns->cnt && tns->thumbs[n].im != NULL) { - win_t *win = tns->win; - thumb_t *t = &tns->thumbs[n]; - unsigned long col = hl ? win->win_fg.pixel : win->win_bg.pixel; - int oxy = (tns->bw + 1) / 2 + 1, owh = tns->bw + 2; - - win_draw_rect(win, t->x - oxy, t->y - oxy, t->w + owh, t->h + owh, - false, tns->bw, col); - - if (tns->files[n].flags & FF_MARK) - tns_mark(tns, n, true); - } -} - -bool tns_move_selection(tns_t *tns, direction_t dir, int cnt) -{ - int old, max; - - old = *tns->sel; - cnt = cnt > 1 ? cnt : 1; - - switch (dir) { - case DIR_UP: - *tns->sel = MAX(*tns->sel - cnt * tns->cols, *tns->sel % tns->cols); - break; - case DIR_DOWN: - max = tns->cols * ((*tns->cnt - 1) / tns->cols) + - MIN((*tns->cnt - 1) % tns->cols, *tns->sel % tns->cols); - *tns->sel = MIN(*tns->sel + cnt * tns->cols, max); - break; - case DIR_LEFT: - *tns->sel = MAX(*tns->sel - cnt, 0); - break; - case DIR_RIGHT: - *tns->sel = MIN(*tns->sel + cnt, *tns->cnt - 1); - break; - } - - if (*tns->sel != old) { - tns_highlight(tns, old, false); - tns_check_view(tns, false); - if (!tns->dirty) - tns_highlight(tns, *tns->sel, true); - } - return *tns->sel != old; -} - -bool tns_scroll(tns_t *tns, direction_t dir, bool screen) -{ - int d, max, old; - - old = tns->first; - d = tns->cols * (screen ? tns->rows : 1); - - if (dir == DIR_DOWN) { - max = *tns->cnt - tns->cols * tns->rows; - if (*tns->cnt % tns->cols != 0) - max += tns->cols - *tns->cnt % tns->cols; - tns->first = MIN(tns->first + d, max); - } else if (dir == DIR_UP) { - tns->first = MAX(tns->first - d, 0); - } - - if (tns->first != old) { - tns_check_view(tns, true); - tns->dirty = true; - } - return tns->first != old; -} - -bool tns_zoom(tns_t *tns, int d) -{ - int i, oldzl; - - oldzl = tns->zl; - tns->zl += -(d < 0) + (d > 0); - tns->zl = MAX(tns->zl, 0); - tns->zl = MIN(tns->zl, ARRLEN(thumb_sizes)-1); - - tns->bw = ((thumb_sizes[tns->zl] - 1) >> 5) + 1; - tns->bw = MIN(tns->bw, 4); - tns->dim = thumb_sizes[tns->zl] + 2 * tns->bw + 6; - - if (tns->zl != oldzl) { - for (i = 0; i < *tns->cnt; i++) - tns_unload(tns, i); - tns->dirty = true; - } - return tns->zl != oldzl; -} - -int tns_translate(tns_t *tns, int x, int y) -{ - int n; - - if (x < tns->x || y < tns->y) - return -1; - - n = tns->first + (y - tns->y) / tns->dim * tns->cols + - (x - tns->x) / tns->dim; - if (n >= *tns->cnt) - n = -1; - - return n; -} diff --git a/utils/nsxiv/utf8.h b/utils/nsxiv/utf8.h deleted file mode 100644 index a9be2d4..0000000 --- a/utils/nsxiv/utf8.h +++ /dev/null @@ -1,68 +0,0 @@ -/* Branchless UTF-8 decoder - * - * This is free and unencumbered software released into the public domain. - */ -#ifndef UTF8_H -#define UTF8_H - -#include <stdint.h> - -/* Decode the next character, C, from BUF, reporting errors in E. - * - * Since this is a branchless decoder, four bytes will be read from the - * buffer regardless of the actual length of the next character. This - * means the buffer _must_ have at least three bytes of zero padding - * following the end of the data stream. - * - * Errors are reported in E, which will be non-zero if the parsed - * character was somehow invalid: invalid byte sequence, non-canonical - * encoding, or a surrogate half. - * - * The function returns a pointer to the next character. When an error - * occurs, this pointer will be a guess that depends on the particular - * error, but it will always advance at least one byte. - */ -static void * -utf8_decode(void *buf, uint32_t *c, int *e) -{ - static const char lengths[] = { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 3, 3, 4, 0 - }; - static const int masks[] = {0x00, 0x7f, 0x1f, 0x0f, 0x07}; - static const uint32_t mins[] = {4194304, 0, 128, 2048, 65536}; - static const int shiftc[] = {0, 18, 12, 6, 0}; - static const int shifte[] = {0, 6, 4, 2, 0}; - - unsigned char *s = buf; - int len = lengths[s[0] >> 3]; - - /* Compute the pointer to the next character early so that the next - * iteration can start working on the next character. Neither Clang - * nor GCC figure out this reordering on their own. - */ - unsigned char *next = s + len + !len; - - /* Assume a four-byte character and load four bytes. Unused bits are - * shifted out. - */ - *c = (uint32_t)(s[0] & masks[len]) << 18; - *c |= (uint32_t)(s[1] & 0x3f) << 12; - *c |= (uint32_t)(s[2] & 0x3f) << 6; - *c |= (uint32_t)(s[3] & 0x3f) << 0; - *c >>= shiftc[len]; - - /* Accumulate the various error conditions. */ - *e = (*c < mins[len]) << 6; /* non-canonical encoding */ - *e |= ((*c >> 11) == 0x1b) << 7; /* surrogate half? */ - *e |= (*c > 0x10FFFF) << 8; /* out of range? */ - *e |= (s[1] & 0xc0) >> 2; - *e |= (s[2] & 0xc0) >> 4; - *e |= (s[3] ) >> 6; - *e ^= 0x2a; /* top two bits of each tail byte correct? */ - *e >>= shifte[len]; - - return next; -} - -#endif diff --git a/utils/nsxiv/util.c b/utils/nsxiv/util.c deleted file mode 100644 index d580839..0000000 --- a/utils/nsxiv/util.c +++ /dev/null @@ -1,289 +0,0 @@ -/* Copyright 2011-2020 Bert Muennich - * Copyright 2021-2022 nsxiv contributors - * - * This file is a part of nsxiv. - * - * nsxiv is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, - * or (at your option) any later version. - * - * nsxiv is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with nsxiv. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "nsxiv.h" - -#include <stdlib.h> -#include <string.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <errno.h> - -const char *progname; - -void* emalloc(size_t size) -{ - void *ptr; - - ptr = malloc(size); - if (ptr == NULL) - error(EXIT_FAILURE, errno, NULL); - return ptr; -} - -void* ecalloc(size_t nmemb, size_t size) -{ - void *ptr; - - ptr = calloc(nmemb, size); - if (ptr == NULL) - error(EXIT_FAILURE, errno, NULL); - return ptr; -} - -void* erealloc(void *ptr, size_t size) -{ - ptr = realloc(ptr, size); - if (ptr == NULL) - error(EXIT_FAILURE, errno, NULL); - return ptr; -} - -char* estrdup(const char *s) -{ - char *d; - size_t n = strlen(s) + 1; - - d = malloc(n); - if (d == NULL) - error(EXIT_FAILURE, errno, NULL); - memcpy(d, s, n); - return d; -} - -void error(int eval, int err, const char* fmt, ...) -{ - va_list ap; - - if (eval == 0 && options->quiet) - return; - - fflush(stdout); - fprintf(stderr, "%s: ", progname); - va_start(ap, fmt); - if (fmt != NULL) - vfprintf(stderr, fmt, ap); - va_end(ap); - if (err != 0) - fprintf(stderr, "%s%s", fmt != NULL ? ": " : "", strerror(err)); - fputc('\n', stderr); - - if (eval != 0) - exit(eval); -} - -int r_opendir(r_dir_t *rdir, const char *dirname, bool recursive) -{ - if (*dirname == '\0') - return -1; - - if ((rdir->dir = opendir(dirname)) == NULL) { - rdir->name = NULL; - rdir->stack = NULL; - return -1; - } - - rdir->stcap = 512; - rdir->stack = emalloc(rdir->stcap * sizeof(char*)); - rdir->stlen = 0; - - rdir->name = (char*) dirname; - rdir->d = 0; - rdir->recursive = recursive; - - return 0; -} - -int r_closedir(r_dir_t *rdir) -{ - int ret = 0; - - if (rdir->stack != NULL) { - while (rdir->stlen > 0) - free(rdir->stack[--rdir->stlen]); - free(rdir->stack); - rdir->stack = NULL; - } - - if (rdir->dir != NULL) { - if ((ret = closedir(rdir->dir)) == 0) - rdir->dir = NULL; - } - - if (rdir->d != 0) { - free(rdir->name); - rdir->name = NULL; - } - - return ret; -} - -char* r_readdir(r_dir_t *rdir, bool skip_dotfiles) -{ - size_t len; - char *filename; - struct dirent *dentry; - struct stat fstats; - - while (true) { - if (rdir->dir != NULL && (dentry = readdir(rdir->dir)) != NULL) { - if (dentry->d_name[0] == '.') { - if (skip_dotfiles) - continue; - if (dentry->d_name[1] == '\0') - continue; - if (dentry->d_name[1] == '.' && dentry->d_name[2] == '\0') - continue; - } - - len = strlen(rdir->name) + strlen(dentry->d_name) + 2; - filename = emalloc(len); - snprintf(filename, len, "%s%s%s", rdir->name, - rdir->name[strlen(rdir->name)-1] == '/' ? "" : "/", - dentry->d_name); - - if (stat(filename, &fstats) < 0) - continue; - if (S_ISDIR(fstats.st_mode)) { - /* put subdirectory on the stack */ - if (rdir->stlen == rdir->stcap) { - rdir->stcap *= 2; - rdir->stack = erealloc(rdir->stack, - rdir->stcap * sizeof(char*)); - } - rdir->stack[rdir->stlen++] = filename; - continue; - } - return filename; - } - - if (rdir->recursive && rdir->stlen > 0) { - /* open next subdirectory */ - closedir(rdir->dir); - if (rdir->d != 0) - free(rdir->name); - rdir->name = rdir->stack[--rdir->stlen]; - rdir->d = 1; - if ((rdir->dir = opendir(rdir->name)) == NULL) - error(0, errno, "%s", rdir->name); - continue; - } - /* no more entries */ - break; - } - return NULL; -} - -int r_mkdir(char *path) -{ - char c, *s = path; - struct stat st; - - while (*s != '\0') { - if (*s == '/') { - s++; - continue; - } - for (; *s != '\0' && *s != '/'; s++); - c = *s; - *s = '\0'; - if (mkdir(path, 0755) == -1) - if (errno != EEXIST || stat(path, &st) == -1 || !S_ISDIR(st.st_mode)) - return -1; - *s = c; - } - return 0; -} - -void construct_argv(char **argv, unsigned int len, ...) -{ - unsigned int i; - va_list args; - - va_start(args, len); - for (i = 0; i < len; ++i) - argv[i] = va_arg(args, char *); - va_end(args); - if (argv[len-1] != NULL) - error(EXIT_FAILURE, 0, "argv not NULL terminated"); -} - -spawn_t spawn(const char *cmd, char *const argv[], unsigned int flags) -{ - pid_t pid; - spawn_t status = { -1, -1, -1 }; - int pfd_read[2] = { -1, -1 }; - int pfd_write[2] = { -1, -1 }; - const bool r = flags & X_READ; - const bool w = flags & X_WRITE; - - if (cmd == NULL || argv == NULL || flags == 0) - return status; - - if (r && pipe(pfd_read) < 0) { - error(0, errno, "pipe: %s", cmd); - return status; - } - - if (w && pipe(pfd_write) < 0) { - if (r) { - close(pfd_read[0]); - close(pfd_read[1]); - } - error(0, errno, "pipe: %s", cmd); - return status; - } - - if ((pid = fork()) == 0) { - bool err = (r && dup2(pfd_read[1], 1) < 0) || (w && dup2(pfd_write[0], 0) < 0); - if (r) { - close(pfd_read[0]); - close(pfd_read[1]); - } - if (w) { - close(pfd_write[0]); - close(pfd_write[1]); - } - - if (err) - error(EXIT_FAILURE, errno, "dup2: %s", cmd); - execv(cmd, argv); - error(EXIT_FAILURE, errno, "exec: %s", cmd); - } - - if (r) - close(pfd_read[1]); - if (w) - close(pfd_write[0]); - - if (pid < 0) { - if (r) - close(pfd_read[0]); - if (w) - close(pfd_write[1]); - error(0, errno, "fork: %s", cmd); - return status; - } - - status.pid = pid; - status.readfd = pfd_read[0]; - status.writefd = pfd_write[1]; - return status; -} diff --git a/utils/nsxiv/window.c b/utils/nsxiv/window.c deleted file mode 100644 index 69c7b66..0000000 --- a/utils/nsxiv/window.c +++ /dev/null @@ -1,537 +0,0 @@ -/* Copyright 2011-2020 Bert Muennich - * Copyright 2021-2022 nsxiv contributors - * - * This file is a part of nsxiv. - * - * nsxiv is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, - * or (at your option) any later version. - * - * nsxiv is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with nsxiv. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "nsxiv.h" -#define _WINDOW_CONFIG -#include "config.h" -#include "icon/data.h" - -#include <stdlib.h> -#include <string.h> -#include <locale.h> -#include <unistd.h> -#include <X11/cursorfont.h> -#include <X11/Xatom.h> -#include <X11/Xresource.h> - -#if HAVE_LIBFONTS -#include "utf8.h" -static XftFont *font; -static double fontsize; -#define TEXTWIDTH(win, text, len) \ - win_draw_text(win, NULL, NULL, 0, 0, text, len, 0) -#endif - -#define RES_CLASS "Nsxiv" - -#define INIT_ATOM_(atom) \ - atoms[ATOM_##atom] = XInternAtom(e->dpy, #atom, False); - -enum { - H_TEXT_PAD = 5, - V_TEXT_PAD = 1 -}; - -static struct { - int name; - Cursor icon; -} cursors[CURSOR_COUNT] = { - { XC_left_ptr }, { XC_dotbox }, { XC_fleur }, { XC_watch }, - { XC_sb_left_arrow }, { XC_sb_right_arrow } -}; - -static GC gc; - -static int barheight; - -Atom atoms[ATOM_COUNT]; - -#if HAVE_LIBFONTS -static void win_init_font(const win_env_t *e, const char *fontstr) -{ - int fontheight = 0; - if ((font = XftFontOpenName(e->dpy, e->scr, fontstr)) == NULL) - error(EXIT_FAILURE, 0, "Error loading font '%s'", fontstr); - fontheight = font->ascent + font->descent; - FcPatternGetDouble(font->pattern, FC_SIZE, 0, &fontsize); - barheight = fontheight + 2 * V_TEXT_PAD; -} - -static void xft_alloc_color(const win_env_t *e, const char *name, XftColor *col) -{ - if (!XftColorAllocName(e->dpy, e->vis, e->cmap, name, col)) - error(EXIT_FAILURE, 0, "Error allocating color '%s'", name); -} -#endif /* HAVE_LIBFONTS */ - -static void win_alloc_color(const win_env_t *e, const char *name, XColor *col) -{ - XColor screen; - if (!XAllocNamedColor(e->dpy, e->cmap, name, &screen, col)) - error(EXIT_FAILURE, 0, "Error allocating color '%s'", name); -} - -static const char* win_res(XrmDatabase db, const char *name, const char *def) -{ - char *type; - XrmValue ret; - - if (db != NULL && - XrmGetResource(db, name, name, &type, &ret) && - STREQ(type, "String")) - { - return ret.addr; - } else { - return def; - } -} - -void win_init(win_t *win) -{ - win_env_t *e; - const char *win_bg, *win_fg, *mrk_fg; -#if HAVE_LIBFONTS - const char *bar_fg, *bar_bg, *f; -#endif - char *res_man; - XrmDatabase db; - - memset(win, 0, sizeof(win_t)); - - e = &win->env; - if ((e->dpy = XOpenDisplay(NULL)) == NULL) - error(EXIT_FAILURE, 0, "Error opening X display"); - - e->scr = DefaultScreen(e->dpy); - e->scrw = DisplayWidth(e->dpy, e->scr); - e->scrh = DisplayHeight(e->dpy, e->scr); - e->depth = DefaultDepth(e->dpy, e->scr); - e->vis = DefaultVisual(e->dpy, e->scr); - e->cmap = DefaultColormap(e->dpy, e->scr); - - if (setlocale(LC_CTYPE, "") == NULL || XSupportsLocale() == 0) - error(0, 0, "No locale support"); - - XrmInitialize(); - res_man = XResourceManagerString(e->dpy); - db = res_man == NULL ? NULL : XrmGetStringDatabase(res_man); - - win_bg = win_res(db, RES_CLASS ".window.background", DEFAULT_WIN_BG); - win_fg = win_res(db, RES_CLASS ".window.foreground", DEFAULT_WIN_FG); - mrk_fg = win_res(db, RES_CLASS ".mark.foreground", DEFAULT_MARK_COLOR ? DEFAULT_MARK_COLOR : win_fg); - win_alloc_color(e, win_bg, &win->win_bg); - win_alloc_color(e, win_fg, &win->win_fg); - win_alloc_color(e, mrk_fg, &win->mrk_fg); - -#if HAVE_LIBFONTS - bar_bg = win_res(db, RES_CLASS ".bar.background", DEFAULT_BAR_BG ? DEFAULT_BAR_BG : win_bg); - bar_fg = win_res(db, RES_CLASS ".bar.foreground", DEFAULT_BAR_FG ? DEFAULT_BAR_FG : win_fg); - xft_alloc_color(e, bar_bg, &win->bar_bg); - xft_alloc_color(e, bar_fg, &win->bar_fg); - - f = win_res(db, RES_CLASS ".bar.font", DEFAULT_FONT); - win_init_font(e, f); - - win->bar.l.size = BAR_L_LEN; - win->bar.r.size = BAR_R_LEN; - /* 3 padding bytes needed by utf8_decode */ - win->bar.l.buf = emalloc(win->bar.l.size + 3); - win->bar.l.buf[0] = '\0'; - win->bar.r.buf = emalloc(win->bar.r.size + 3); - win->bar.r.buf[0] = '\0'; - win->bar.h = options->hide_bar ? 0 : barheight; - win->bar.top = TOP_STATUSBAR; -#endif /* HAVE_LIBFONTS */ - - XrmDestroyDatabase(db); - INIT_ATOM_(WM_DELETE_WINDOW); - INIT_ATOM_(_NET_WM_NAME); - INIT_ATOM_(_NET_WM_ICON_NAME); - INIT_ATOM_(_NET_WM_ICON); - INIT_ATOM_(_NET_WM_STATE); - INIT_ATOM_(_NET_WM_PID); - INIT_ATOM_(_NET_WM_STATE_FULLSCREEN); - INIT_ATOM_(UTF8_STRING); - INIT_ATOM_(WM_NAME); - INIT_ATOM_(WM_ICON_NAME); -} - -void win_open(win_t *win) -{ - int c, i, j, n; - Window parent; - win_env_t *e; - XClassHint classhint; - unsigned long *icon_data; - XColor col; - Cursor *cnone = &cursors[CURSOR_NONE].icon; - char none_data[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - Pixmap none; - int gmask; - XSizeHints sizehints; - XWMHints hints; - long pid; - char hostname[256]; - XSetWindowAttributes attrs; - char res_class[] = RES_CLASS; - char res_name[] = "nsxiv"; - - e = &win->env; - parent = options->embed ? options->embed : RootWindow(e->dpy, e->scr); - - sizehints.flags = PWinGravity; - sizehints.win_gravity = NorthWestGravity; - - /* determine window offsets, width & height */ - if (options->geometry == NULL) - gmask = 0; - else - gmask = XParseGeometry(options->geometry, &win->x, &win->y, - &win->w, &win->h); - if (gmask & WidthValue) - sizehints.flags |= USSize; - else - win->w = WIN_WIDTH; - if (gmask & HeightValue) - sizehints.flags |= USSize; - else - win->h = WIN_HEIGHT; - if (gmask & XValue) { - if (gmask & XNegative) { - win->x += e->scrw - win->w; - sizehints.win_gravity = NorthEastGravity; - } - sizehints.flags |= USPosition; - } else { - win->x = 0; - } - if (gmask & YValue) { - if (gmask & YNegative) { - win->y += e->scrh - win->h; - sizehints.win_gravity = sizehints.win_gravity == NorthEastGravity - ? SouthEastGravity : SouthWestGravity; - } - sizehints.flags |= USPosition; - } else { - win->y = 0; - } - - attrs.colormap = e->cmap; - attrs.border_pixel = 0; - - win->xwin = XCreateWindow(e->dpy, parent, win->x, win->y, win->w, win->h, 0, - e->depth, InputOutput, e->vis, - CWColormap | CWBorderPixel, &attrs); - if (win->xwin == None) - error(EXIT_FAILURE, 0, "Error creating X window"); - - /* set the _NET_WM_PID */ - pid = getpid(); - XChangeProperty(e->dpy, win->xwin, atoms[ATOM__NET_WM_PID], XA_CARDINAL, - 32, PropModeReplace, (unsigned char *) &pid, 1); - if (gethostname(hostname, ARRLEN(hostname)) == 0) { - XTextProperty tp; - tp.value = (unsigned char *)hostname; - tp.nitems = strnlen(hostname, ARRLEN(hostname)); - tp.encoding = XA_STRING; - tp.format = 8; - XSetWMClientMachine(e->dpy, win->xwin, &tp); - } - - XSelectInput(e->dpy, win->xwin, - ButtonReleaseMask | ButtonPressMask | KeyPressMask | - PointerMotionMask | StructureNotifyMask); - - for (i = 0; i < ARRLEN(cursors); i++) { - if (i != CURSOR_NONE) - cursors[i].icon = XCreateFontCursor(e->dpy, cursors[i].name); - } - if (XAllocNamedColor(e->dpy, e->cmap, "black", &col, &col) == 0) - error(EXIT_FAILURE, 0, "Error allocating color 'black'"); - - none = XCreateBitmapFromData(e->dpy, win->xwin, none_data, 8, 8); - *cnone = XCreatePixmapCursor(e->dpy, none, none, &col, &col, 0, 0); - - gc = XCreateGC(e->dpy, win->xwin, 0, None); - - n = icons[ARRLEN(icons)-1].size; - icon_data = emalloc((n * n + 2) * sizeof(*icon_data)); - - for (i = 0; i < ARRLEN(icons); i++) { - n = 0; - icon_data[n++] = icons[i].size; - icon_data[n++] = icons[i].size; - - for (j = 0; j < icons[i].cnt; j++) { - for (c = icons[i].data[j] >> 4; c >= 0; c--) - icon_data[n++] = icon_colors[icons[i].data[j] & 0x0F]; - } - XChangeProperty(e->dpy, win->xwin, atoms[ATOM__NET_WM_ICON], XA_CARDINAL, 32, - i == 0 ? PropModeReplace : PropModeAppend, - (unsigned char *) icon_data, n); - } - free(icon_data); - - win_set_title(win, true); - classhint.res_class = res_class; - classhint.res_name = options->res_name != NULL ? options->res_name : res_name; - XSetClassHint(e->dpy, win->xwin, &classhint); - - XSetWMProtocols(e->dpy, win->xwin, &atoms[ATOM_WM_DELETE_WINDOW], 1); - - sizehints.width = win->w; - sizehints.height = win->h; - sizehints.x = win->x; - sizehints.y = win->y; - XSetWMNormalHints(win->env.dpy, win->xwin, &sizehints); - - hints.flags = InputHint | StateHint; - hints.input = 1; - hints.initial_state = NormalState; - XSetWMHints(win->env.dpy, win->xwin, &hints); - - if (options->fullscreen) { - XChangeProperty(e->dpy, win->xwin, atoms[ATOM__NET_WM_STATE], - XA_ATOM, 32, PropModeReplace, - (unsigned char *) &atoms[ATOM__NET_WM_STATE_FULLSCREEN], 1); - } - - win->h -= win->bar.h; - - win->buf.w = e->scrw; - win->buf.h = e->scrh; - win->buf.pm = XCreatePixmap(e->dpy, win->xwin, win->buf.w, win->buf.h, e->depth); - - XSetForeground(e->dpy, gc, win->win_bg.pixel); - XFillRectangle(e->dpy, win->buf.pm, gc, 0, 0, win->buf.w, win->buf.h); - XSetWindowBackgroundPixmap(e->dpy, win->xwin, win->buf.pm); - XMapWindow(e->dpy, win->xwin); - XFlush(e->dpy); -} - -CLEANUP void win_close(win_t *win) -{ - unsigned int i; - - for (i = 0; i < ARRLEN(cursors); i++) - XFreeCursor(win->env.dpy, cursors[i].icon); - - XFreeGC(win->env.dpy, gc); -#if HAVE_LIBFONTS - XftFontClose(win->env.dpy, font); -#endif - XDestroyWindow(win->env.dpy, win->xwin); - XCloseDisplay(win->env.dpy); -} - -bool win_configure(win_t *win, XConfigureEvent *c) -{ - bool changed; - - changed = win->w != c->width || win->h + win->bar.h != c->height; - - win->x = c->x; - win->y = c->y; - win->w = c->width; - win->h = c->height - win->bar.h; - win->bw = c->border_width; - - return changed; -} - -void win_toggle_fullscreen(win_t *win) -{ - XEvent ev; - XClientMessageEvent *cm; - - memset(&ev, 0, sizeof(ev)); - ev.type = ClientMessage; - - cm = &ev.xclient; - cm->window = win->xwin; - cm->message_type = atoms[ATOM__NET_WM_STATE]; - cm->format = 32; - cm->data.l[0] = 2; /* toggle */ - cm->data.l[1] = atoms[ATOM__NET_WM_STATE_FULLSCREEN]; - - XSendEvent(win->env.dpy, DefaultRootWindow(win->env.dpy), False, - SubstructureNotifyMask | SubstructureRedirectMask, &ev); -} - -void win_toggle_bar(win_t *win) -{ - if (win->bar.h != 0) { - win->h += win->bar.h; - win->bar.h = 0; - } else { - win->bar.h = barheight; - win->h -= win->bar.h; - } -} - -void win_clear(win_t *win) -{ - win_env_t *e; - - e = &win->env; - - if (win->w > win->buf.w || win->h + win->bar.h > win->buf.h) { - XFreePixmap(e->dpy, win->buf.pm); - win->buf.w = MAX(win->buf.w, win->w); - win->buf.h = MAX(win->buf.h, win->h + win->bar.h); - win->buf.pm = XCreatePixmap(e->dpy, win->xwin, - win->buf.w, win->buf.h, e->depth); - } - XSetForeground(e->dpy, gc, win->win_bg.pixel); - XFillRectangle(e->dpy, win->buf.pm, gc, 0, 0, win->buf.w, win->buf.h); -} - -#if HAVE_LIBFONTS -static int win_draw_text(win_t *win, XftDraw *d, const XftColor *color, - int x, int y, char *text, int len, int w) -{ - int err, tw = 0; - char *t, *next; - uint32_t rune; - XftFont *f; - FcCharSet *fccharset; - XGlyphInfo ext; - - for (t = text; t - text < len; t = next) { - next = utf8_decode(t, &rune, &err); - if (XftCharExists(win->env.dpy, font, rune)) { - f = font; - } else { /* fallback font */ - fccharset = FcCharSetCreate(); - FcCharSetAddChar(fccharset, rune); - f = XftFontOpen(win->env.dpy, win->env.scr, FC_CHARSET, FcTypeCharSet, - fccharset, FC_SCALABLE, FcTypeBool, FcTrue, - FC_SIZE, FcTypeDouble, fontsize, NULL); - FcCharSetDestroy(fccharset); - } - XftTextExtentsUtf8(win->env.dpy, f, (XftChar8*)t, next - t, &ext); - tw += ext.xOff; - if (tw <= w) { - XftDrawStringUtf8(d, color, f, x, y, (XftChar8*)t, next - t); - x += ext.xOff; - } - if (f != font) - XftFontClose(win->env.dpy, f); - } - return tw; -} - -static void win_draw_bar(win_t *win) -{ - int len, x, y, w, tw; - win_env_t *e; - win_bar_t *l, *r; - XftDraw *d; - - if ((l = &win->bar.l)->buf == NULL || (r = &win->bar.r)->buf == NULL) - return; - - e = &win->env; - y = (win->bar.top ? 0 : win->h) + font->ascent + V_TEXT_PAD; - w = win->w - 2*H_TEXT_PAD; - d = XftDrawCreate(e->dpy, win->buf.pm, e->vis, e->cmap); - - XSetForeground(e->dpy, gc, win->bar_bg.pixel); - XFillRectangle(e->dpy, win->buf.pm, gc, 0, win->bar.top ? 0 : win->h, win->w, win->bar.h); - - XSetForeground(e->dpy, gc, win->win_bg.pixel); - XSetBackground(e->dpy, gc, win->bar_bg.pixel); - - if ((len = strlen(r->buf)) > 0) { - if ((tw = TEXTWIDTH(win, r->buf, len)) > w) - return; - x = win->w - tw - H_TEXT_PAD; - w -= tw; - win_draw_text(win, d, &win->bar_fg, x, y, r->buf, len, tw); - } - if ((len = strlen(l->buf)) > 0) { - x = H_TEXT_PAD; - w -= 2 * H_TEXT_PAD; /* gap between left and right parts */ - win_draw_text(win, d, &win->bar_fg, x, y, l->buf, len, w); - } - XftDrawDestroy(d); -} -#else -static void win_draw_bar(win_t *win) -{ - (void) win; -} -#endif /* HAVE_LIBFONTS */ - -void win_draw(win_t *win) -{ - if (win->bar.h > 0) - win_draw_bar(win); - - XSetWindowBackgroundPixmap(win->env.dpy, win->xwin, win->buf.pm); - XClearWindow(win->env.dpy, win->xwin); - XFlush(win->env.dpy); -} - -void win_draw_rect(win_t *win, int x, int y, int w, int h, bool fill, int lw, - unsigned long col) -{ - XGCValues gcval; - - gcval.line_width = lw; - gcval.foreground = col; - XChangeGC(win->env.dpy, gc, GCForeground | GCLineWidth, &gcval); - - if (fill) - XFillRectangle(win->env.dpy, win->buf.pm, gc, x, y, w, h); - else - XDrawRectangle(win->env.dpy, win->buf.pm, gc, x, y, w, h); -} - -void win_set_title(win_t *win, bool init) -{ - size_t len, i; - unsigned char title[512]; - int targets[] = { ATOM_WM_NAME, ATOM_WM_ICON_NAME, ATOM__NET_WM_NAME, ATOM__NET_WM_ICON_NAME }; - - if ((len = get_win_title(title, ARRLEN(title), init)) > 0) { - for (i = 0; i < ARRLEN(targets); ++i) { - XChangeProperty(win->env.dpy, win->xwin, atoms[targets[i]], - atoms[ATOM_UTF8_STRING], 8, PropModeReplace, title, len); - } - } -} - -void win_set_cursor(win_t *win, cursor_t cursor) -{ - if (cursor >= 0 && cursor < ARRLEN(cursors)) { - XDefineCursor(win->env.dpy, win->xwin, cursors[cursor].icon); - XFlush(win->env.dpy); - } -} - -void win_cursor_pos(win_t *win, int *x, int *y) -{ - int i; - unsigned int ui; - Window w; - - if (!XQueryPointer(win->env.dpy, win->xwin, &w, &w, &i, &i, x, y, &ui)) - *x = *y = 0; -} |