Merge branch 'nsxiv-master'
This commit is contained in:
commit
d566ca84e8
|
|
@ -1,7 +1,9 @@
|
||||||
# EditorConfig
|
# EditorConfig
|
||||||
|
# See this if your editor doesn't have built-in editorconfig support:
|
||||||
|
# https://editorconfig.org/#download
|
||||||
|
|
||||||
# apply to all files
|
# apply to all .c and .h files
|
||||||
[*]
|
[*.{c,h}]
|
||||||
|
|
||||||
# top-most EditorConfig file
|
# top-most EditorConfig file
|
||||||
root = true
|
root = true
|
||||||
|
|
|
||||||
139
README.md
139
README.md
|
|
@ -1,137 +1,2 @@
|
||||||
Dependencies
|
## Nsxiv
|
||||||
------------
|
This is my fork of Nsxiv
|
||||||
|
|
||||||
nsxiv requires the following software to be installed:
|
|
||||||
|
|
||||||
* Imlib2
|
|
||||||
* X11
|
|
||||||
|
|
||||||
The following dependencies are optional.
|
|
||||||
|
|
||||||
* `inotify`<sup>\*</sup>: 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).
|
|
||||||
|
|
||||||
\* [inotify][] is a Linux-specific API for monitoring filesystem changes.
|
|
||||||
It's not natively available on `*BSD` systems but can be enabed via installing
|
|
||||||
and linking against [libinotify-kqueue][].
|
|
||||||
|
|
||||||
[inotify]: https://www.man7.org/linux/man-pages/man7/inotify.7.html
|
|
||||||
[libinotify-kqueue]: https://github.com/libinotify-kqueue/libinotify-kqueue
|
|
||||||
|
|
||||||
|
|
||||||
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
|
|
||||||
`config.mk`. `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
|
|
||||||
-----
|
|
||||||
|
|
||||||
Refer to the man-page for the documentation:
|
|
||||||
|
|
||||||
$ man nsxiv
|
|
||||||
|
|
||||||
You may also view the man-page [online](https://nsxiv.codeberg.page/man/).
|
|
||||||
However, note that the online man-page might not accurately represent your local
|
|
||||||
copy.
|
|
||||||
|
|
||||||
|
|
||||||
F.A.Q.
|
|
||||||
------
|
|
||||||
|
|
||||||
* Can I open remote urls with nsxiv? <br>
|
|
||||||
Yes, see [nsxiv-url](https://codeberg.org/nsxiv/nsxiv-extra/src/branch/master/scripts/nsxiv-url)
|
|
||||||
|
|
||||||
* Can I open all the images in a directory? <br>
|
|
||||||
Yes, see [nsxiv-rifle](https://codeberg.org/nsxiv/nsxiv-extra/src/branch/master/scripts/nsxiv-rifle)
|
|
||||||
|
|
||||||
* Can I set default arguments for nsxiv? <br>
|
|
||||||
Yes, see [nsxiv-env](https://codeberg.org/nsxiv/nsxiv-extra/src/branch/master/scripts/nsxiv-env)
|
|
||||||
|
|
||||||
* Can I pipe images into nsxiv? <br>
|
|
||||||
Yes, see [nsxiv-pipe](https://codeberg.org/nsxiv/nsxiv-extra/src/branch/master/scripts/nsxiv-pipe)
|
|
||||||
|
|
||||||
You may also wish to see the [known issues](https://codeberg.org/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://codeberg.org/nsxiv/nsxiv-extra/src/branch/master/CUSTOMIZATION.md).
|
|
||||||
|
|
||||||
Due to our limited [project scope](etc/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://codeberg.org/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://codeberg.org/nsxiv/nsxiv-extra).
|
|
||||||
|
|
|
||||||
20
autoreload.c
20
autoreload.c
|
|
@ -28,7 +28,10 @@
|
||||||
#include <sys/inotify.h>
|
#include <sys/inotify.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
static struct { char *buf; size_t len; } scratch;
|
static struct {
|
||||||
|
char *buf;
|
||||||
|
size_t len;
|
||||||
|
} scratch;
|
||||||
|
|
||||||
void arl_init(arl_t *arl)
|
void arl_init(arl_t *arl)
|
||||||
{
|
{
|
||||||
|
|
@ -94,7 +97,10 @@ bool arl_handle(arl_t *arl)
|
||||||
char *ptr;
|
char *ptr;
|
||||||
const struct inotify_event *e;
|
const struct inotify_event *e;
|
||||||
/* inotify_event aligned buffer */
|
/* inotify_event aligned buffer */
|
||||||
static union { char d[4096]; struct inotify_event e; } buf;
|
static union {
|
||||||
|
char d[4096];
|
||||||
|
struct inotify_event e;
|
||||||
|
} buf;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
ssize_t len = read(arl->fd, buf.d, sizeof(buf.d));
|
ssize_t len = read(arl->fd, buf.d, sizeof(buf.d));
|
||||||
|
|
@ -105,7 +111,7 @@ bool arl_handle(arl_t *arl)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
for (ptr = buf.d; ptr < buf.d + len; ptr += sizeof(*e) + e->len) {
|
for (ptr = buf.d; ptr < buf.d + len; ptr += sizeof(*e) + e->len) {
|
||||||
e = (const struct inotify_event*) ptr;
|
e = (const struct inotify_event *)ptr;
|
||||||
if (e->wd == arl->wd_file && (e->mask & IN_CLOSE_WRITE)) {
|
if (e->wd == arl->wd_file && (e->mask & IN_CLOSE_WRITE)) {
|
||||||
reload = true;
|
reload = true;
|
||||||
} else if (e->wd == arl->wd_file && (e->mask & IN_DELETE_SELF)) {
|
} else if (e->wd == arl->wd_file && (e->mask & IN_DELETE_SELF)) {
|
||||||
|
|
@ -128,18 +134,18 @@ void arl_init(arl_t *arl)
|
||||||
|
|
||||||
void arl_cleanup(arl_t *arl)
|
void arl_cleanup(arl_t *arl)
|
||||||
{
|
{
|
||||||
(void) arl;
|
(void)arl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void arl_add(arl_t *arl, const char *filepath)
|
void arl_add(arl_t *arl, const char *filepath)
|
||||||
{
|
{
|
||||||
(void) arl;
|
(void)arl;
|
||||||
(void) filepath;
|
(void)filepath;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool arl_handle(arl_t *arl)
|
bool arl_handle(arl_t *arl)
|
||||||
{
|
{
|
||||||
(void) arl;
|
(void)arl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
21
commands.c
21
commands.c
|
|
@ -59,6 +59,13 @@ bool cg_quit(arg_t status)
|
||||||
return None; /* silence tcc warning */
|
return None; /* silence tcc warning */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool cg_pick_quit(arg_t status)
|
||||||
|
{
|
||||||
|
if (options->to_stdout && markcnt == 0)
|
||||||
|
printf("%s%c", files[fileidx].name, options->using_null ? '\0' : '\n');
|
||||||
|
return cg_quit(status);
|
||||||
|
}
|
||||||
|
|
||||||
bool cg_switch_mode(arg_t _)
|
bool cg_switch_mode(arg_t _)
|
||||||
{
|
{
|
||||||
if (mode == MODE_IMAGE) {
|
if (mode == MODE_IMAGE) {
|
||||||
|
|
@ -326,10 +333,10 @@ bool ci_drag(arg_t drag_mode)
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
if (drag_mode == DRAG_ABSOLUTE) {
|
if (drag_mode == DRAG_ABSOLUTE) {
|
||||||
px = MIN(MAX(0.0, x - win.w*0.1), win.w*0.8) / (win.w*0.8)
|
px = MIN(MAX(0.0, x - win.w * 0.1), win.w * 0.8) /
|
||||||
* (win.w - img.w * img.zoom);
|
(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)
|
py = MIN(MAX(0.0, y - win.h * 0.1), win.h * 0.8) /
|
||||||
* (win.h - img.h * img.zoom);
|
(win.h * 0.8) * (win.h - img.h * img.zoom);
|
||||||
} else {
|
} else {
|
||||||
px = img.x + x - ox;
|
px = img.x + x - ox;
|
||||||
py = img.y + y - oy;
|
py = img.y + y - oy;
|
||||||
|
|
@ -343,7 +350,8 @@ bool ci_drag(arg_t drag_mode)
|
||||||
ButtonPressMask | ButtonReleaseMask | PointerMotionMask, &e);
|
ButtonPressMask | ButtonReleaseMask | PointerMotionMask, &e);
|
||||||
if (e.type == ButtonPress || e.type == ButtonRelease)
|
if (e.type == ButtonPress || e.type == ButtonRelease)
|
||||||
break;
|
break;
|
||||||
while (XCheckTypedEvent(win.env.dpy, MotionNotify, &e));
|
while (XCheckTypedEvent(win.env.dpy, MotionNotify, &e))
|
||||||
|
;
|
||||||
ox = x;
|
ox = x;
|
||||||
oy = y;
|
oy = y;
|
||||||
x = e.xmotion.x;
|
x = e.xmotion.x;
|
||||||
|
|
@ -443,7 +451,8 @@ bool ct_drag_mark_image(arg_t _)
|
||||||
ButtonPressMask | ButtonReleaseMask | PointerMotionMask, &e);
|
ButtonPressMask | ButtonReleaseMask | PointerMotionMask, &e);
|
||||||
if (e.type == ButtonPress || e.type == ButtonRelease)
|
if (e.type == ButtonPress || e.type == ButtonRelease)
|
||||||
break;
|
break;
|
||||||
while (XCheckTypedEvent(win.env.dpy, MotionNotify, &e));
|
while (XCheckTypedEvent(win.env.dpy, MotionNotify, &e))
|
||||||
|
;
|
||||||
sel = tns_translate(&tns, e.xbutton.x, e.xbutton.y);
|
sel = tns_translate(&tns, e.xbutton.x, e.xbutton.y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ bool cg_n_or_last(arg_t);
|
||||||
bool cg_navigate_marked(arg_t);
|
bool cg_navigate_marked(arg_t);
|
||||||
bool cg_prefix_external(arg_t);
|
bool cg_prefix_external(arg_t);
|
||||||
bool cg_quit(arg_t);
|
bool cg_quit(arg_t);
|
||||||
|
bool cg_pick_quit(arg_t);
|
||||||
bool cg_reload_image(arg_t);
|
bool cg_reload_image(arg_t);
|
||||||
bool cg_remove_image(arg_t);
|
bool cg_remove_image(arg_t);
|
||||||
bool cg_reverse_marks(arg_t);
|
bool cg_reverse_marks(arg_t);
|
||||||
|
|
@ -57,6 +58,7 @@ bool ct_select(arg_t);
|
||||||
#define g_navigate_marked { cg_navigate_marked, MODE_ALL }
|
#define g_navigate_marked { cg_navigate_marked, MODE_ALL }
|
||||||
#define g_prefix_external { cg_prefix_external, MODE_ALL }
|
#define g_prefix_external { cg_prefix_external, MODE_ALL }
|
||||||
#define g_quit { cg_quit, MODE_ALL }
|
#define g_quit { cg_quit, MODE_ALL }
|
||||||
|
#define g_pick_quit { cg_pick_quit, MODE_ALL }
|
||||||
#define g_reload_image { cg_reload_image, MODE_ALL }
|
#define g_reload_image { cg_reload_image, MODE_ALL }
|
||||||
#define g_remove_image { cg_remove_image, MODE_ALL }
|
#define g_remove_image { cg_remove_image, MODE_ALL }
|
||||||
#define g_reverse_marks { cg_reverse_marks, MODE_ALL }
|
#define g_reverse_marks { cg_reverse_marks, MODE_ALL }
|
||||||
|
|
|
||||||
1
config.h
1
config.h
|
|
@ -92,6 +92,7 @@ static const KeySym KEYHANDLER_ABORT = XK_Escape;
|
||||||
static const keymap_t keys[] = {
|
static const keymap_t keys[] = {
|
||||||
/* modifiers key function argument */
|
/* modifiers key function argument */
|
||||||
{ 0, XK_q, g_quit, 0 },
|
{ 0, XK_q, g_quit, 0 },
|
||||||
|
{ 0, XK_Q, g_pick_quit, 0 },
|
||||||
{ 0, XK_Return, g_switch_mode, None },
|
{ 0, XK_Return, g_switch_mode, None },
|
||||||
{ 0, XK_f, g_toggle_fullscreen, None },
|
{ 0, XK_f, g_toggle_fullscreen, None },
|
||||||
{ 0, XK_b, g_toggle_bar, None },
|
{ 0, XK_b, g_toggle_bar, None },
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,11 @@ HAVE_LIBWEBP = $(OPT_DEP_DEFAULT)
|
||||||
|
|
||||||
# Compiler and linker
|
# Compiler and linker
|
||||||
CC = c99
|
CC = c99
|
||||||
# CFLAGS, any optimization flags goes here
|
# CFLAGS, any additional compiler flags goes here
|
||||||
CFLAGS = -Wall -pedantic
|
CFLAGS = -Wall -pedantic -O2 -DNDEBUG
|
||||||
|
# Uncomment for a debug build using gcc/clang
|
||||||
|
# CFLAGS = -Wall -pedantic -DDEBUG -g3 -fsanitize=address,undefined
|
||||||
|
# LDFLAGS = $(CFLAGS)
|
||||||
|
|
||||||
# icons that will be installed via `make icon`
|
# icons that will be installed via `make icon`
|
||||||
ICONS = 16x16.png 32x32.png 48x48.png 64x64.png 128x128.png
|
ICONS = 16x16.png 32x32.png 48x48.png 64x64.png 128x128.png
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,82 @@
|
||||||
|
# clang-format doesn't dictate the project's code style and can mess up a
|
||||||
|
# couple edge cases. However it comes quite close and can be used for fixing
|
||||||
|
# most style issues automatically on new changes via `git-clang-format`.
|
||||||
|
---
|
||||||
|
|
||||||
|
Standard: c++03
|
||||||
|
|
||||||
|
ColumnLimit: 0
|
||||||
|
|
||||||
|
AccessModifierOffset: -8
|
||||||
|
ConstructorInitializerIndentWidth: 8
|
||||||
|
ContinuationIndentWidth: 8
|
||||||
|
IndentCaseLabels: false
|
||||||
|
IndentGotoLabels: false
|
||||||
|
IndentPPDirectives: None
|
||||||
|
IndentWidth: 8
|
||||||
|
IndentWrappedFunctionNames: false
|
||||||
|
NamespaceIndentation: None
|
||||||
|
TabWidth: 8
|
||||||
|
UseTab: AlignWithSpaces
|
||||||
|
|
||||||
|
AlignAfterOpenBracket: true
|
||||||
|
AlignConsecutiveAssignments: false
|
||||||
|
AlignConsecutiveDeclarations: false
|
||||||
|
AlignEscapedNewlines: false
|
||||||
|
AlignOperands: true
|
||||||
|
AlignTrailingComments: false
|
||||||
|
DerivePointerAlignment: true
|
||||||
|
PointerAlignment: true
|
||||||
|
|
||||||
|
AllowAllParametersOfDeclarationOnNextLine: false
|
||||||
|
AllowShortBlocksOnASingleLine: true
|
||||||
|
AllowShortCaseLabelsOnASingleLine: false
|
||||||
|
AllowShortFunctionsOnASingleLine: None
|
||||||
|
AllowShortIfStatementsOnASingleLine: false
|
||||||
|
AllowShortLoopsOnASingleLine: false
|
||||||
|
|
||||||
|
AlwaysBreakAfterDefinitionReturnType: None
|
||||||
|
AlwaysBreakAfterReturnType: None
|
||||||
|
AlwaysBreakBeforeMultilineStrings: false
|
||||||
|
AlwaysBreakTemplateDeclarations: false
|
||||||
|
|
||||||
|
BinPackArguments: true
|
||||||
|
BinPackParameters: true
|
||||||
|
|
||||||
|
BreakBeforeBraces: Custom
|
||||||
|
BraceWrapping:
|
||||||
|
AfterControlStatement: MultiLine
|
||||||
|
AfterEnum: false
|
||||||
|
AfterExternBlock: false
|
||||||
|
AfterFunction: true
|
||||||
|
AfterStruct: false
|
||||||
|
AfterUnion: false
|
||||||
|
BeforeElse: false
|
||||||
|
IndentBraces: false
|
||||||
|
SplitEmptyFunction: true
|
||||||
|
|
||||||
|
BreakBeforeBinaryOperators: None
|
||||||
|
BreakBeforeInheritanceComma: false
|
||||||
|
BreakBeforeTernaryOperators: false
|
||||||
|
BreakConstructorInitializers: BeforeComma
|
||||||
|
BreakConstructorInitializersBeforeComma: false
|
||||||
|
BreakStringLiterals: true
|
||||||
|
|
||||||
|
Cpp11BracedListStyle: false
|
||||||
|
MaxEmptyLinesToKeep: 1
|
||||||
|
|
||||||
|
ReflowComments: false
|
||||||
|
|
||||||
|
SortIncludes: true
|
||||||
|
|
||||||
|
SpaceAfterCStyleCast: false
|
||||||
|
SpaceBeforeAssignmentOperators: true
|
||||||
|
SpaceBeforeParens: ControlStatements
|
||||||
|
SpaceInEmptyParentheses: false
|
||||||
|
SpacesBeforeTrailingComments: 1
|
||||||
|
SpacesInAngles: false
|
||||||
|
SpacesInCStyleCastParentheses: false
|
||||||
|
SpacesInParentheses: false
|
||||||
|
SpacesInSquareBrackets: false
|
||||||
|
|
||||||
|
...
|
||||||
|
|
@ -116,7 +116,7 @@ references *above* can be found on the new main nsxiv repository on CodeBerg.
|
||||||
|
|
||||||
* Changes:
|
* Changes:
|
||||||
|
|
||||||
* Window title is now customizeable via `win-title`, cli flag `-T` and related
|
* Window title is now customizable via `win-title`, cli flag `-T` and related
|
||||||
config.h options are removed. See `WINDOW TITLE` section of the manpage for
|
config.h options are removed. See `WINDOW TITLE` section of the manpage for
|
||||||
more info. [#213]
|
more info. [#213]
|
||||||
* Imlib2 cache size is now set based on total memory percentage, by default
|
* Imlib2 cache size is now set based on total memory percentage, by default
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ Contribution Guideline
|
||||||
When contributing, make sure:
|
When contributing, make sure:
|
||||||
|
|
||||||
* Your contribution falls under nsxiv's scope and aim
|
* Your contribution falls under nsxiv's scope and aim
|
||||||
* You follow the existing code style (see [.editorconfig](../.editorconfig))
|
* You follow the existing code style (see the "Code Style" section below)
|
||||||
* You open the pull request from a new branch, not from master
|
* You open the pull request from a new branch, not from master
|
||||||
* To avoid using force pushes, especially for bigger patches. Only use them
|
* To avoid using force pushes, especially for bigger patches. Only use them
|
||||||
when there's merge conflicts.
|
when there's merge conflicts.
|
||||||
|
|
@ -44,6 +44,21 @@ to work on. You can also filter the issues via label:
|
||||||
(Intermediate/Experienced) Issues where we require some help.
|
(Intermediate/Experienced) Issues where we require some help.
|
||||||
|
|
||||||
|
|
||||||
|
Code Style
|
||||||
|
----------
|
||||||
|
|
||||||
|
`nsxiv` mostly follows the [suckless code-style][sl], with a few exceptions.
|
||||||
|
If your editor supports [.editorconfig](../.editorconfig) then you'll already be
|
||||||
|
off to a good start without needing much manual intervention. Additionally we
|
||||||
|
provide a [clang-format](./.clang-format) configuration for reference, which you
|
||||||
|
may use via [`git-clang-format`][cf] to format the changes you've made (please
|
||||||
|
do not run it globally on the entire code-base since clang-format gets a decent
|
||||||
|
amount of edge cases wrong).
|
||||||
|
|
||||||
|
[sl]: https://suckless.org/coding_style/
|
||||||
|
[cf]: https://clang.llvm.org/docs/ClangFormat.html#git-integration
|
||||||
|
|
||||||
|
|
||||||
Development workflow for maintainers
|
Development workflow for maintainers
|
||||||
------------------------------------
|
------------------------------------
|
||||||
|
|
||||||
|
|
|
||||||
12
etc/nsxiv.1
12
etc/nsxiv.1
|
|
@ -135,6 +135,10 @@ Prefix the next command with a number (denoted via
|
||||||
.B q
|
.B q
|
||||||
Quit nsxiv.
|
Quit nsxiv.
|
||||||
.TP
|
.TP
|
||||||
|
.B Q
|
||||||
|
Quit nsxiv, but additionally print the current filename when \-o is active and
|
||||||
|
no files have been marked.
|
||||||
|
.TP
|
||||||
.B Return
|
.B Return
|
||||||
Switch to thumbnail mode / open selected image in image mode.
|
Switch to thumbnail mode / open selected image in image mode.
|
||||||
.TP
|
.TP
|
||||||
|
|
@ -457,6 +461,9 @@ Color of the bar foreground. Defaults to window.foreground
|
||||||
Color of the mark foreground. Defaults to window.foreground
|
Color of the mark foreground. Defaults to window.foreground
|
||||||
.TP
|
.TP
|
||||||
Please see xrdb(1) on how to change them.
|
Please see xrdb(1) on how to change them.
|
||||||
|
.LP
|
||||||
|
An X resources entry with an empty value means the default
|
||||||
|
(defined in config.h) will be used.
|
||||||
.SH WINDOW TITLE
|
.SH WINDOW TITLE
|
||||||
The window title can be replaced with the output of a user-provided script,
|
The window title can be replaced with the output of a user-provided script,
|
||||||
which is called by nsxiv whenever any of the relevant information changes.
|
which is called by nsxiv whenever any of the relevant information changes.
|
||||||
|
|
@ -562,11 +569,6 @@ TAAPArthur <taaparthur at gmail.com>
|
||||||
eylles <ed.ylles1997 at gmail.com>
|
eylles <ed.ylles1997 at gmail.com>
|
||||||
Stein Gunnar Bakkeby <bakkeby at gmail.com>
|
Stein Gunnar Bakkeby <bakkeby at gmail.com>
|
||||||
explosion-mental <explosion0mental at gmail.com>
|
explosion-mental <explosion0mental at gmail.com>
|
||||||
mamg22 <marcomonizg at gmail.com>
|
|
||||||
LuXu
|
|
||||||
Guilherme Freire
|
|
||||||
Sam Whitehead
|
|
||||||
Kian Kasad <kian at kasad.com>
|
|
||||||
.EE
|
.EE
|
||||||
.SH CONTRIBUTORS
|
.SH CONTRIBUTORS
|
||||||
.EX
|
.EX
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ misc-*,android-cloexec-*,llvm-include-order
|
||||||
-bugprone-implicit-widening-of-multiplication-result,-bugprone-integer-division
|
-bugprone-implicit-widening-of-multiplication-result,-bugprone-integer-division
|
||||||
-android-cloexec-fopen,-android-cloexec-pipe,-cert-err33-c
|
-android-cloexec-fopen,-android-cloexec-pipe,-cert-err33-c
|
||||||
-bugprone-assignment-in-if-condition
|
-bugprone-assignment-in-if-condition
|
||||||
|
-bugprone-suspicious-realloc-usage
|
||||||
|
|
||||||
# false positive warnings
|
# false positive warnings
|
||||||
-clang-analyzer-valist.Uninitialized
|
-clang-analyzer-valist.Uninitialized
|
||||||
|
|
|
||||||
66
image.c
66
image.c
|
|
@ -54,8 +54,12 @@ enum { DEF_GIF_DELAY = 75 };
|
||||||
enum { DEF_WEBP_DELAY = 75 };
|
enum { DEF_WEBP_DELAY = 75 };
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if HAVE_IMLIB2_MULTI_FRAME
|
||||||
|
enum { DEF_ANIM_DELAY = 75 };
|
||||||
|
#endif
|
||||||
|
|
||||||
#define ZOOM_MIN (zoom_levels[0] / 100)
|
#define ZOOM_MIN (zoom_levels[0] / 100)
|
||||||
#define ZOOM_MAX (zoom_levels[ARRLEN(zoom_levels)-1] / 100)
|
#define ZOOM_MAX (zoom_levels[ARRLEN(zoom_levels) - 1] / 100)
|
||||||
|
|
||||||
static int calc_cache_size(void)
|
static int calc_cache_size(void)
|
||||||
{
|
{
|
||||||
|
|
@ -69,7 +73,7 @@ static int calc_cache_size(void)
|
||||||
#endif
|
#endif
|
||||||
if (pages < 0 || page_size < 0)
|
if (pages < 0 || page_size < 0)
|
||||||
return CACHE_SIZE_FALLBACK;
|
return CACHE_SIZE_FALLBACK;
|
||||||
cache = (pages/100) * CACHE_SIZE_MEM_PERCENTAGE;
|
cache = (pages / 100) * CACHE_SIZE_MEM_PERCENTAGE;
|
||||||
cache *= page_size;
|
cache *= page_size;
|
||||||
|
|
||||||
return MIN(cache, CACHE_SIZE_LIMIT);
|
return MIN(cache, CACHE_SIZE_LIMIT);
|
||||||
|
|
@ -234,12 +238,12 @@ static bool img_load_gif(img_t *img, const fileinfo_t *file)
|
||||||
while (ext) {
|
while (ext) {
|
||||||
if (ext_code == GRAPHICS_EXT_FUNC_CODE) {
|
if (ext_code == GRAPHICS_EXT_FUNC_CODE) {
|
||||||
if (ext[1] & 1)
|
if (ext[1] & 1)
|
||||||
transp = (int) ext[4];
|
transp = (int)ext[4];
|
||||||
else
|
else
|
||||||
transp = -1;
|
transp = -1;
|
||||||
|
|
||||||
delay = 10 * ((unsigned int) ext[3] << 8 | (unsigned int) ext[2]);
|
delay = 10 * ((unsigned int)ext[3] << 8 | (unsigned int)ext[2]);
|
||||||
disposal = (unsigned int) ext[1] >> 2 & 0x7;
|
disposal = (unsigned int)ext[1] >> 2 & 0x7;
|
||||||
}
|
}
|
||||||
ext = NULL;
|
ext = NULL;
|
||||||
DGifGetExtensionNext(gif, &ext);
|
DGifGetExtensionNext(gif, &ext);
|
||||||
|
|
@ -280,10 +284,11 @@ static bool img_load_gif(img_t *img, const fileinfo_t *file)
|
||||||
for (i = 0; i < sh; i++) {
|
for (i = 0; i < sh; i++) {
|
||||||
for (j = 0; j < sw; j++) {
|
for (j = 0; j < sw; j++) {
|
||||||
if (i < y || i >= y + h || j < x || j >= x + w ||
|
if (i < y || i >= y + h || j < x || j >= x + w ||
|
||||||
rows[i-y][j-x] == transp)
|
rows[i - y][j - x] == transp)
|
||||||
{
|
{
|
||||||
if (prev_frame != NULL && (prev_disposal != 2 ||
|
if (prev_frame != NULL &&
|
||||||
i < py || i >= py + ph || j < px || j >= px + pw))
|
(prev_disposal != 2 || i < py || i >= py + ph ||
|
||||||
|
j < px || j >= px + pw))
|
||||||
{
|
{
|
||||||
*ptr = prev_frame[i * sw + j];
|
*ptr = prev_frame[i * sw + j];
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -291,9 +296,9 @@ static bool img_load_gif(img_t *img, const fileinfo_t *file)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
assert(cmap != NULL);
|
assert(cmap != NULL);
|
||||||
r = cmap->Colors[rows[i-y][j-x]].Red;
|
r = cmap->Colors[rows[i - y][j - x]].Red;
|
||||||
g = cmap->Colors[rows[i-y][j-x]].Green;
|
g = cmap->Colors[rows[i - y][j - x]].Green;
|
||||||
b = cmap->Colors[rows[i-y][j-x]].Blue;
|
b = cmap->Colors[rows[i - y][j - x]].Blue;
|
||||||
*ptr = 0xffu << 24 | r << 16 | g << 8 | b;
|
*ptr = 0xffu << 24 | r << 16 | g << 8 | b;
|
||||||
}
|
}
|
||||||
ptr++;
|
ptr++;
|
||||||
|
|
@ -412,12 +417,12 @@ static bool img_load_webp(img_t *img, const fileinfo_t *file)
|
||||||
/* Load and decode frames (also works on images with only 1 frame) */
|
/* Load and decode frames (also works on images with only 1 frame) */
|
||||||
m->length = m->cnt = m->sel = 0;
|
m->length = m->cnt = m->sel = 0;
|
||||||
while (WebPAnimDecoderGetNext(dec, &buf, &ts)) {
|
while (WebPAnimDecoderGetNext(dec, &buf, &ts)) {
|
||||||
im = imlib_create_image_using_copied_data(
|
im = imlib_create_image_using_copied_data(info.canvas_width, info.canvas_height,
|
||||||
info.canvas_width, info.canvas_height, (uint32_t *)buf);
|
(uint32_t *)buf);
|
||||||
imlib_context_set_image(im);
|
imlib_context_set_image(im);
|
||||||
imlib_image_set_format("webp");
|
imlib_image_set_format("webp");
|
||||||
/* Get an iterator of this frame - used for frame info (duration, etc.) */
|
/* Get an iterator of this frame - used for frame info (duration, etc.) */
|
||||||
WebPDemuxGetFrame(demux, m->cnt+1, &iter);
|
WebPDemuxGetFrame(demux, m->cnt + 1, &iter);
|
||||||
imlib_image_set_has_alpha((flags & ALPHA_FLAG) == ALPHA_FLAG);
|
imlib_image_set_has_alpha((flags & ALPHA_FLAG) == ALPHA_FLAG);
|
||||||
/* Store info for this frame */
|
/* Store info for this frame */
|
||||||
m->frames[m->cnt].im = im;
|
m->frames[m->cnt].im = im;
|
||||||
|
|
@ -469,11 +474,6 @@ static bool img_load_multiframe(img_t *img, const fileinfo_t *file)
|
||||||
m->frames = erealloc(m->frames, m->cap * sizeof(*m->frames));
|
m->frames = erealloc(m->frames, m->cap * sizeof(*m->frames));
|
||||||
}
|
}
|
||||||
|
|
||||||
imlib_context_set_dither(0);
|
|
||||||
imlib_context_set_anti_alias(0);
|
|
||||||
imlib_context_set_color_modifier(NULL);
|
|
||||||
imlib_context_set_operation(IMLIB_OP_COPY);
|
|
||||||
|
|
||||||
if ((blank = imlib_create_image(img->w, img->h)) == NULL) {
|
if ((blank = imlib_create_image(img->w, img->h)) == NULL) {
|
||||||
error(0, 0, "%s: couldn't create image", file->name);
|
error(0, 0, "%s: couldn't create image", file->name);
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -481,6 +481,11 @@ static bool img_load_multiframe(img_t *img, const fileinfo_t *file)
|
||||||
imlib_context_set_image(blank);
|
imlib_context_set_image(blank);
|
||||||
img_area_clear(0, 0, img->w, img->h);
|
img_area_clear(0, 0, img->w, img->h);
|
||||||
|
|
||||||
|
imlib_context_set_dither(0);
|
||||||
|
imlib_context_set_anti_alias(0);
|
||||||
|
imlib_context_set_color_modifier(NULL);
|
||||||
|
imlib_context_set_operation(IMLIB_OP_COPY);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Imlib2 gives back a "raw frame", we need to blend it on top of the
|
* Imlib2 gives back a "raw frame", we need to blend it on top of the
|
||||||
* previous frame ourselves if necessary to get the fully decoded frame.
|
* previous frame ourselves if necessary to get the fully decoded frame.
|
||||||
|
|
@ -505,6 +510,7 @@ static bool img_load_multiframe(img_t *img, const fileinfo_t *file)
|
||||||
}
|
}
|
||||||
|
|
||||||
imlib_context_set_image(frame);
|
imlib_context_set_image(frame);
|
||||||
|
imlib_image_set_changes_on_disk(); /* see img_load() for rationale */
|
||||||
imlib_image_get_frame_info(&finfo);
|
imlib_image_get_frame_info(&finfo);
|
||||||
assert(finfo.frame_count == (int)fcnt);
|
assert(finfo.frame_count == (int)fcnt);
|
||||||
assert(finfo.canvas_w == img->w && finfo.canvas_h == img->h);
|
assert(finfo.canvas_w == img->w && finfo.canvas_h == img->h);
|
||||||
|
|
@ -537,7 +543,7 @@ static bool img_load_multiframe(img_t *img, const fileinfo_t *file)
|
||||||
imlib_context_set_blend(!!(finfo.frame_flags & IMLIB_FRAME_BLEND));
|
imlib_context_set_blend(!!(finfo.frame_flags & IMLIB_FRAME_BLEND));
|
||||||
imlib_blend_image_onto_image(frame, has_alpha, 0, 0, sw, sh, sx, sy, sw, sh);
|
imlib_blend_image_onto_image(frame, has_alpha, 0, 0, sw, sh, sx, sy, sw, sh);
|
||||||
m->frames[m->cnt].im = canvas;
|
m->frames[m->cnt].im = canvas;
|
||||||
m->frames[m->cnt].delay = finfo.frame_delay;
|
m->frames[m->cnt].delay = finfo.frame_delay ? finfo.frame_delay : DEF_ANIM_DELAY;
|
||||||
m->length += m->frames[m->cnt].delay;
|
m->length += m->frames[m->cnt].delay;
|
||||||
m->cnt++;
|
m->cnt++;
|
||||||
imlib_context_set_image(frame);
|
imlib_context_set_image(frame);
|
||||||
|
|
@ -546,6 +552,7 @@ static bool img_load_multiframe(img_t *img, const fileinfo_t *file)
|
||||||
imlib_context_set_image(blank);
|
imlib_context_set_image(blank);
|
||||||
imlib_free_image();
|
imlib_free_image();
|
||||||
img_multiframe_context_set(img);
|
img_multiframe_context_set(img);
|
||||||
|
imlib_context_set_color_modifier(img->cmod); /* restore cmod */
|
||||||
return m->cnt > 0;
|
return m->cnt > 0;
|
||||||
}
|
}
|
||||||
#endif /* HAVE_IMLIB2_MULTI_FRAME */
|
#endif /* HAVE_IMLIB2_MULTI_FRAME */
|
||||||
|
|
@ -578,6 +585,9 @@ bool img_load(img_t *img, const fileinfo_t *file)
|
||||||
if ((img->im = img_open(file)) == NULL)
|
if ((img->im = img_open(file)) == NULL)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
/* ensure that the image's timestamp is checked when loading from cache
|
||||||
|
* to avoid issues like: https://codeberg.org/nsxiv/nsxiv/issues/436
|
||||||
|
*/
|
||||||
imlib_image_set_changes_on_disk();
|
imlib_image_set_changes_on_disk();
|
||||||
|
|
||||||
/* since v1.7.5, Imlib2 can parse exif orientation from jpeg files.
|
/* since v1.7.5, Imlib2 can parse exif orientation from jpeg files.
|
||||||
|
|
@ -673,8 +683,8 @@ static bool img_fit(img_t *img)
|
||||||
if (img->scalemode == SCALE_ZOOM)
|
if (img->scalemode == SCALE_ZOOM)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
zw = (float) img->win->w / (float) img->w;
|
zw = (float)img->win->w / (float)img->w;
|
||||||
zh = (float) img->win->h / (float) img->h;
|
zh = (float)img->win->h / (float)img->h;
|
||||||
|
|
||||||
switch (img->scalemode) {
|
switch (img->scalemode) {
|
||||||
case SCALE_FILL:
|
case SCALE_FILL:
|
||||||
|
|
@ -692,7 +702,7 @@ static bool img_fit(img_t *img)
|
||||||
}
|
}
|
||||||
z = MIN(z, img->scalemode == SCALE_DOWN ? 1.0 : ZOOM_MAX);
|
z = MIN(z, img->scalemode == SCALE_DOWN ? 1.0 : ZOOM_MAX);
|
||||||
|
|
||||||
if (ABS(img->zoom - z) > 1.0/MAX(img->w, img->h)) {
|
if (ABS(img->zoom - z) > 1.0 / MAX(img->w, img->h)) {
|
||||||
img->zoom = z;
|
img->zoom = z;
|
||||||
img->dirty = title_dirty = true;
|
img->dirty = title_dirty = true;
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -838,14 +848,14 @@ bool img_zoom_to(img_t *img, float z)
|
||||||
|
|
||||||
bool img_zoom(img_t *img, int d)
|
bool img_zoom(img_t *img, int d)
|
||||||
{
|
{
|
||||||
int i = d > 0 ? 0 : (int)ARRLEN(zoom_levels)-1;
|
int i = d > 0 ? 0 : (int)ARRLEN(zoom_levels) - 1;
|
||||||
while (i >= 0 && i < (int)ARRLEN(zoom_levels) &&
|
while (i >= 0 && i < (int)ARRLEN(zoom_levels) &&
|
||||||
(d > 0 ? zoom_levels[i]/100 <= img->zoom : zoom_levels[i]/100 >= img->zoom))
|
(d > 0 ? zoom_levels[i] / 100 <= img->zoom : zoom_levels[i] / 100 >= img->zoom))
|
||||||
{
|
{
|
||||||
i += d;
|
i += d;
|
||||||
}
|
}
|
||||||
i = MIN(MAX(i, 0), (int)ARRLEN(zoom_levels)-1);
|
i = MIN(MAX(i, 0), (int)ARRLEN(zoom_levels) - 1);
|
||||||
return img_zoom_to(img, zoom_levels[i]/100);
|
return img_zoom_to(img, zoom_levels[i] / 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool img_pos(img_t *img, float x, float y)
|
bool img_pos(img_t *img, float x, float y)
|
||||||
|
|
@ -882,7 +892,7 @@ bool img_pan(img_t *img, direction_t dir, int d)
|
||||||
float x, y;
|
float x, y;
|
||||||
|
|
||||||
if (d > 0) {
|
if (d > 0) {
|
||||||
x = y = MAX(1, (float) d * img->zoom);
|
x = y = MAX(1, (float)d * img->zoom);
|
||||||
} else {
|
} else {
|
||||||
x = img->win->w / (d < 0 ? 1 : PAN_FRACTION);
|
x = img->win->w / (d < 0 ? 1 : PAN_FRACTION);
|
||||||
y = img->win->h / (d < 0 ? 1 : PAN_FRACTION);
|
y = img->win->h / (d < 0 ? 1 : PAN_FRACTION);
|
||||||
|
|
|
||||||
70
main.c
70
main.c
|
|
@ -40,15 +40,16 @@
|
||||||
#include <X11/XF86keysym.h>
|
#include <X11/XF86keysym.h>
|
||||||
#include <X11/keysym.h>
|
#include <X11/keysym.h>
|
||||||
|
|
||||||
#define MODMASK(mask) ((mask) & USED_MODMASK)
|
#define MODMASK(mask) (USED_MODMASK & (mask))
|
||||||
#define BAR_SEP " "
|
#define BAR_SEP " "
|
||||||
|
|
||||||
#define TV_DIFF(t1,t2) (((t1)->tv_sec - (t2)->tv_sec ) * 1000 + \
|
#define TV_DIFF(t1,t2) (((t1)->tv_sec - (t2)->tv_sec ) * 1000 + \
|
||||||
((t1)->tv_usec - (t2)->tv_usec) / 1000)
|
((t1)->tv_usec - (t2)->tv_usec) / 1000)
|
||||||
#define TV_ADD_MSEC(tv,t) { \
|
#define TV_ADD_MSEC(tv, t) \
|
||||||
|
do { \
|
||||||
(tv)->tv_sec += (t) / 1000; \
|
(tv)->tv_sec += (t) / 1000; \
|
||||||
(tv)->tv_usec += (t) % 1000 * 1000; \
|
(tv)->tv_usec += (t) % 1000 * 1000; \
|
||||||
}
|
} while (0)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int err;
|
int err;
|
||||||
|
|
@ -112,8 +113,8 @@ static void cleanup(void)
|
||||||
static bool xgetline(char **lineptr, size_t *n)
|
static bool xgetline(char **lineptr, size_t *n)
|
||||||
{
|
{
|
||||||
ssize_t len = getdelim(lineptr, n, options->using_null ? '\0' : '\n', stdin);
|
ssize_t len = getdelim(lineptr, n, options->using_null ? '\0' : '\n', stdin);
|
||||||
if (!options->using_null && len > 0 && (*lineptr)[len-1] == '\n')
|
if (!options->using_null && len > 0 && (*lineptr)[len - 1] == '\n')
|
||||||
(*lineptr)[len-1] = '\0';
|
(*lineptr)[len - 1] = '\0';
|
||||||
return len > 0;
|
return len > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -140,7 +141,7 @@ static void check_add_file(const char *filename, bool given)
|
||||||
if (fileidx == filecnt) {
|
if (fileidx == filecnt) {
|
||||||
filecnt *= 2;
|
filecnt *= 2;
|
||||||
files = erealloc(files, filecnt * sizeof(*files));
|
files = erealloc(files, filecnt * sizeof(*files));
|
||||||
memset(&files[filecnt/2], 0, filecnt/2 * sizeof(*files));
|
memset(&files[filecnt / 2], 0, filecnt / 2 * sizeof(*files));
|
||||||
}
|
}
|
||||||
|
|
||||||
files[fileidx].name = estrdup(filename);
|
files[fileidx].name = estrdup(filename);
|
||||||
|
|
@ -193,15 +194,15 @@ void remove_file(int n, bool manual)
|
||||||
markcnt--;
|
markcnt--;
|
||||||
|
|
||||||
if (files[n].path != files[n].name)
|
if (files[n].path != files[n].name)
|
||||||
free((void*) files[n].path);
|
free((void *)files[n].path);
|
||||||
free((void*) files[n].name);
|
free((void *)files[n].name);
|
||||||
if (tns.thumbs != NULL)
|
if (tns.thumbs != NULL)
|
||||||
tns_unload(&tns, n);
|
tns_unload(&tns, n);
|
||||||
|
|
||||||
if (n + 1 < filecnt) {
|
if (n + 1 < filecnt) {
|
||||||
if (tns.thumbs != NULL) {
|
if (tns.thumbs != NULL) {
|
||||||
memmove(tns.thumbs + n, tns.thumbs + n + 1, (filecnt - n - 1) *
|
memmove(tns.thumbs + n, tns.thumbs + n + 1,
|
||||||
sizeof(*tns.thumbs));
|
(filecnt - n - 1) * sizeof(*tns.thumbs));
|
||||||
memset(tns.thumbs + filecnt - 1, 0, sizeof(*tns.thumbs));
|
memset(tns.thumbs + filecnt - 1, 0, sizeof(*tns.thumbs));
|
||||||
}
|
}
|
||||||
memmove(files + n, files + n + 1, (filecnt - n - 1) * sizeof(*files));
|
memmove(files + n, files + n + 1, (filecnt - n - 1) * sizeof(*files));
|
||||||
|
|
@ -287,7 +288,7 @@ static void read_title(void)
|
||||||
ssize_t n;
|
ssize_t n;
|
||||||
char buf[512];
|
char buf[512];
|
||||||
|
|
||||||
if ((n = read(wintitle.fd, buf, sizeof(buf)-1)) > 0) {
|
if ((n = read(wintitle.fd, buf, sizeof(buf) - 1)) > 0) {
|
||||||
buf[n] = '\0';
|
buf[n] = '\0';
|
||||||
win_set_title(&win, buf, n);
|
win_set_title(&win, buf, n);
|
||||||
}
|
}
|
||||||
|
|
@ -308,7 +309,7 @@ static void open_title(void)
|
||||||
snprintf(h, ARRLEN(h), "%d", img.h);
|
snprintf(h, ARRLEN(h), "%d", img.h);
|
||||||
snprintf(z, ARRLEN(z), "%d", (int)(img.zoom * 100));
|
snprintf(z, ARRLEN(z), "%d", (int)(img.zoom * 100));
|
||||||
}
|
}
|
||||||
snprintf(fidx, ARRLEN(fidx), "%d", fileidx+1);
|
snprintf(fidx, ARRLEN(fidx), "%d", fileidx + 1);
|
||||||
snprintf(fcnt, ARRLEN(fcnt), "%d", filecnt);
|
snprintf(fcnt, ARRLEN(fcnt), "%d", filecnt);
|
||||||
construct_argv(argv, ARRLEN(argv), wintitle.f.cmd, files[fileidx].path,
|
construct_argv(argv, ARRLEN(argv), wintitle.f.cmd, files[fileidx].path,
|
||||||
fidx, fcnt, w, h, z, NULL);
|
fidx, fcnt, w, h, z, NULL);
|
||||||
|
|
@ -377,7 +378,7 @@ void load_image(int new)
|
||||||
if (new >= filecnt)
|
if (new >= filecnt)
|
||||||
new = filecnt - 1;
|
new = filecnt - 1;
|
||||||
else if (new > 0 && prev)
|
else if (new > 0 && prev)
|
||||||
new--;
|
new -= 1;
|
||||||
}
|
}
|
||||||
files[new].flags &= ~FF_WARN;
|
files[new].flags &= ~FF_WARN;
|
||||||
fileidx = current = new;
|
fileidx = current = new;
|
||||||
|
|
@ -426,18 +427,19 @@ static void update_info(void)
|
||||||
/* update bar contents */
|
/* update bar contents */
|
||||||
if (win.bar.h == 0 || extprefix)
|
if (win.bar.h == 0 || extprefix)
|
||||||
return;
|
return;
|
||||||
for (fw = 0, i = filecnt; i > 0; fw++, i /= 10);
|
for (fw = 0, i = filecnt; i > 0; fw++, i /= 10)
|
||||||
|
;
|
||||||
mark = files[fileidx].flags & FF_MARK ? "* " : "";
|
mark = files[fileidx].flags & FF_MARK ? "* " : "";
|
||||||
l->p = l->buf;
|
l->p = l->buf;
|
||||||
r->p = r->buf;
|
r->p = r->buf;
|
||||||
if (mode == MODE_THUMB) {
|
if (mode == MODE_THUMB) {
|
||||||
if (tns.loadnext < tns.end)
|
if (tns.loadnext < tns.end)
|
||||||
bar_put(l, "Loading... %0*d", fw, tns.loadnext + 1);
|
bar_put(r, "Loading... %0*d | ", fw, tns.loadnext + 1);
|
||||||
else if (tns.initnext < filecnt)
|
else if (tns.initnext < filecnt)
|
||||||
bar_put(l, "Caching... %0*d", fw, tns.initnext + 1);
|
bar_put(r, "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);
|
bar_put(r, "%s%0*d/%d", mark, fw, fileidx + 1, filecnt);
|
||||||
|
if (info.ft.err)
|
||||||
|
strncpy(l->buf, files[fileidx].name, l->size);
|
||||||
} else {
|
} else {
|
||||||
bar_put(r, "%s", mark);
|
bar_put(r, "%s", mark);
|
||||||
if (img.ss.on) {
|
if (img.ss.on) {
|
||||||
|
|
@ -452,9 +454,10 @@ static void update_info(void)
|
||||||
bar_put(r, "B%+d" BAR_SEP, img.brightness);
|
bar_put(r, "B%+d" BAR_SEP, img.brightness);
|
||||||
if (img.contrast)
|
if (img.contrast)
|
||||||
bar_put(r, "C%+d" BAR_SEP, img.contrast);
|
bar_put(r, "C%+d" BAR_SEP, img.contrast);
|
||||||
bar_put(r, "%3d%%" BAR_SEP, (int) (img.zoom * 100.0));
|
bar_put(r, "%3d%%" BAR_SEP, (int)(img.zoom * 100.0));
|
||||||
if (img.multi.cnt > 0) {
|
if (img.multi.cnt > 0) {
|
||||||
for (fn = 0, i = img.multi.cnt; i > 0; fn++, i /= 10);
|
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" BAR_SEP, fn, img.multi.sel + 1, img.multi.cnt);
|
||||||
}
|
}
|
||||||
bar_put(r, "%0*d/%d", fw, fileidx + 1, filecnt);
|
bar_put(r, "%0*d/%d", fw, fileidx + 1, filecnt);
|
||||||
|
|
@ -562,8 +565,9 @@ void handle_key_handler(bool init)
|
||||||
return;
|
return;
|
||||||
if (init) {
|
if (init) {
|
||||||
close_info();
|
close_info();
|
||||||
snprintf(win.bar.l.buf, win.bar.l.size, "Getting key handler input "
|
snprintf(win.bar.l.buf, win.bar.l.size,
|
||||||
"(%s to abort)...", XKeysymToString(KEYHANDLER_ABORT));
|
"Getting key handler input (%s to abort)...",
|
||||||
|
XKeysymToString(KEYHANDLER_ABORT));
|
||||||
} else { /* abort */
|
} else { /* abort */
|
||||||
open_info();
|
open_info();
|
||||||
update_info();
|
update_info();
|
||||||
|
|
@ -622,7 +626,8 @@ static bool run_key_handler(const char *key, unsigned int mask)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fclose(pfs);
|
fclose(pfs);
|
||||||
while (waitpid(pid, NULL, 0) == -1 && errno == EINTR);
|
while (waitpid(pid, NULL, 0) == -1 && errno == EINTR)
|
||||||
|
;
|
||||||
|
|
||||||
for (f = i = 0; f < fcnt; i++) {
|
for (f = i = 0; f < fcnt; i++) {
|
||||||
if ((marked && (files[i].flags & FF_MARK)) || (!marked && i == fileidx)) {
|
if ((marked && (files[i].flags & FF_MARK)) || (!marked && i == fileidx)) {
|
||||||
|
|
@ -639,7 +644,8 @@ static bool run_key_handler(const char *key, unsigned int mask)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* drop user input events that occurred while running the key handler */
|
/* drop user input events that occurred while running the key handler */
|
||||||
while (XCheckIfEvent(win.env.dpy, &dump, is_input_ev, NULL));
|
while (XCheckIfEvent(win.env.dpy, &dump, is_input_ev, NULL))
|
||||||
|
;
|
||||||
|
|
||||||
if (mode == MODE_IMAGE && changed) {
|
if (mode == MODE_IMAGE && changed) {
|
||||||
img_close(&img, true);
|
img_close(&img, true);
|
||||||
|
|
@ -698,7 +704,7 @@ static void on_keypress(XKeyEvent *kev)
|
||||||
handle_key_handler(false);
|
handle_key_handler(false);
|
||||||
} else if (key >= '0' && key <= '9') {
|
} else if (key >= '0' && key <= '9') {
|
||||||
/* number prefix for commands */
|
/* number prefix for commands */
|
||||||
prefix = prefix * 10 + (int) (key - '0');
|
prefix = prefix * 10 + (int)(key - '0');
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
dirty = process_bindings(keys, ARRLEN(keys), ksym, kev->state, sh);
|
dirty = process_bindings(keys, ARRLEN(keys), ksym, kev->state, sh);
|
||||||
|
|
@ -729,7 +735,7 @@ static void run(void)
|
||||||
enum { FD_X, FD_INFO, FD_TITLE, FD_ARL, FD_CNT };
|
enum { FD_X, FD_INFO, FD_TITLE, FD_ARL, FD_CNT };
|
||||||
struct pollfd pfd[FD_CNT];
|
struct pollfd pfd[FD_CNT];
|
||||||
int timeout = 0;
|
int timeout = 0;
|
||||||
const struct timespec ten_ms = {0, 10000000};
|
const struct timespec ten_ms = { 0, 10000000 };
|
||||||
bool discard, init_thumb, load_thumb, to_set;
|
bool discard, init_thumb, load_thumb, to_set;
|
||||||
XEvent ev, nextev;
|
XEvent ev, nextev;
|
||||||
|
|
||||||
|
|
@ -739,8 +745,8 @@ static void run(void)
|
||||||
init_thumb = mode == MODE_THUMB && tns.initnext < filecnt;
|
init_thumb = mode == MODE_THUMB && tns.initnext < filecnt;
|
||||||
load_thumb = mode == MODE_THUMB && tns.loadnext < tns.end;
|
load_thumb = mode == MODE_THUMB && tns.loadnext < tns.end;
|
||||||
|
|
||||||
if ((init_thumb || load_thumb || to_set || info.fd != -1 ||
|
if ((init_thumb || load_thumb || to_set || info.fd != -1 || arl.fd != -1) &&
|
||||||
arl.fd != -1) && XPending(win.env.dpy) == 0)
|
XPending(win.env.dpy) == 0)
|
||||||
{
|
{
|
||||||
if (load_thumb) {
|
if (load_thumb) {
|
||||||
set_timeout(redraw, TO_REDRAW_THUMBS, false);
|
set_timeout(redraw, TO_REDRAW_THUMBS, false);
|
||||||
|
|
@ -793,8 +799,8 @@ static void run(void)
|
||||||
discard = ev.type == nextev.type;
|
discard = ev.type == nextev.type;
|
||||||
break;
|
break;
|
||||||
case KeyPress:
|
case KeyPress:
|
||||||
discard = (nextev.type == KeyPress || nextev.type == KeyRelease)
|
discard = (nextev.type == KeyPress || nextev.type == KeyRelease) &&
|
||||||
&& ev.xkey.keycode == nextev.xkey.keycode;
|
ev.xkey.keycode == nextev.xkey.keycode;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -805,7 +811,7 @@ static void run(void)
|
||||||
on_buttonpress(&ev.xbutton);
|
on_buttonpress(&ev.xbutton);
|
||||||
break;
|
break;
|
||||||
case ClientMessage:
|
case ClientMessage:
|
||||||
if ((Atom) ev.xclient.data.l[0] == atoms[ATOM_WM_DELETE_WINDOW])
|
if ((Atom)ev.xclient.data.l[0] == atoms[ATOM_WM_DELETE_WINDOW])
|
||||||
cg_quit(EXIT_SUCCESS);
|
cg_quit(EXIT_SUCCESS);
|
||||||
break;
|
break;
|
||||||
case DestroyNotify:
|
case DestroyNotify:
|
||||||
|
|
@ -858,7 +864,7 @@ int main(int argc, char *argv[])
|
||||||
size_t n;
|
size_t n;
|
||||||
const char *homedir, *dsuffix = "";
|
const char *homedir, *dsuffix = "";
|
||||||
|
|
||||||
setup_signal(SIGCHLD, SIG_DFL, SA_RESTART|SA_NOCLDSTOP|SA_NOCLDWAIT);
|
setup_signal(SIGCHLD, SIG_DFL, SA_RESTART | SA_NOCLDSTOP | SA_NOCLDWAIT);
|
||||||
setup_signal(SIGPIPE, SIG_IGN, 0);
|
setup_signal(SIGPIPE, SIG_IGN, 0);
|
||||||
|
|
||||||
setlocale(LC_COLLATE, "");
|
setlocale(LC_COLLATE, "");
|
||||||
|
|
|
||||||
4
nsxiv.h
4
nsxiv.h
|
|
@ -20,6 +20,10 @@
|
||||||
#ifndef NSXIV_H
|
#ifndef NSXIV_H
|
||||||
#define NSXIV_H
|
#define NSXIV_H
|
||||||
|
|
||||||
|
#if !defined(DEBUG) && !defined(NDEBUG)
|
||||||
|
#define NDEBUG
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,8 @@ void print_usage(void)
|
||||||
{
|
{
|
||||||
printf("usage: %s [-abcfhiopqrtvZ0] [-A FRAMERATE] [-e WID] [-G GAMMA] "
|
printf("usage: %s [-abcfhiopqrtvZ0] [-A FRAMERATE] [-e WID] [-G GAMMA] "
|
||||||
"[-g GEOMETRY] [-N NAME] [-n NUM] [-S DELAY] [-s MODE] "
|
"[-g GEOMETRY] [-N NAME] [-n NUM] [-S DELAY] [-s MODE] "
|
||||||
"[-z ZOOM] FILES...\n", progname);
|
"[-z ZOOM] FILES...\n",
|
||||||
|
progname);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_version(void)
|
static void print_version(void)
|
||||||
|
|
@ -227,7 +228,7 @@ void parse_options(int argc, char **argv)
|
||||||
if (*end != '\0' || n <= 0)
|
if (*end != '\0' || n <= 0)
|
||||||
error(EXIT_FAILURE, 0, "Invalid zoom level: %s", op.optarg);
|
error(EXIT_FAILURE, 0, "Invalid zoom level: %s", op.optarg);
|
||||||
_options.scalemode = SCALE_ZOOM;
|
_options.scalemode = SCALE_ZOOM;
|
||||||
_options.zoom = (float) n / 100.0f;
|
_options.zoom = (float)n / 100.0f;
|
||||||
break;
|
break;
|
||||||
case '0':
|
case '0':
|
||||||
_options.using_null = true;
|
_options.using_null = true;
|
||||||
|
|
|
||||||
26
thumbs.c
26
thumbs.c
|
|
@ -36,7 +36,7 @@
|
||||||
|
|
||||||
static char *cache_dir;
|
static char *cache_dir;
|
||||||
|
|
||||||
static char* tns_cache_filepath(const char *filepath)
|
static char *tns_cache_filepath(const char *filepath)
|
||||||
{
|
{
|
||||||
size_t len;
|
size_t len;
|
||||||
char *cfile = NULL;
|
char *cfile = NULL;
|
||||||
|
|
@ -201,8 +201,8 @@ static Imlib_Image tns_scale_down(Imlib_Image im, int dim)
|
||||||
imlib_context_set_image(im);
|
imlib_context_set_image(im);
|
||||||
w = imlib_image_get_width();
|
w = imlib_image_get_width();
|
||||||
h = imlib_image_get_height();
|
h = imlib_image_get_height();
|
||||||
zw = (float) dim / (float) w;
|
zw = (float)dim / (float)w;
|
||||||
zh = (float) dim / (float) h;
|
zh = (float)dim / (float)h;
|
||||||
z = MIN(zw, zh);
|
z = MIN(zw, zh);
|
||||||
z = MIN(z, 1.0);
|
z = MIN(z, 1.0);
|
||||||
|
|
||||||
|
|
@ -219,7 +219,7 @@ static Imlib_Image tns_scale_down(Imlib_Image im, int dim)
|
||||||
|
|
||||||
bool tns_load(tns_t *tns, int n, bool force, bool cache_only)
|
bool tns_load(tns_t *tns, int n, bool force, bool cache_only)
|
||||||
{
|
{
|
||||||
int maxwh = thumb_sizes[ARRLEN(thumb_sizes)-1];
|
int maxwh = thumb_sizes[ARRLEN(thumb_sizes) - 1];
|
||||||
bool cache_hit = false;
|
bool cache_hit = false;
|
||||||
char *cfile;
|
char *cfile;
|
||||||
thumb_t *t;
|
thumb_t *t;
|
||||||
|
|
@ -290,8 +290,8 @@ bool tns_load(tns_t *tns, int n, bool force, bool cache_only)
|
||||||
h = imlib_image_get_height();
|
h = imlib_image_get_height();
|
||||||
|
|
||||||
if (pw > w && ph > h && (pw - ph >= 0) == (w - h >= 0)) {
|
if (pw > w && ph > h && (pw - ph >= 0) == (w - h >= 0)) {
|
||||||
zw = (float) pw / (float) w;
|
zw = (float)pw / (float)w;
|
||||||
zh = (float) ph / (float) h;
|
zh = (float)ph / (float)h;
|
||||||
if (zw < zh) {
|
if (zw < zh) {
|
||||||
pw /= zh;
|
pw /= zh;
|
||||||
x = (w - pw) / 2;
|
x = (w - pw) / 2;
|
||||||
|
|
@ -343,10 +343,14 @@ bool tns_load(tns_t *tns, int n, bool force, bool cache_only)
|
||||||
}
|
}
|
||||||
file->flags |= FF_TN_INIT;
|
file->flags |= FF_TN_INIT;
|
||||||
|
|
||||||
if (n == tns->initnext)
|
if (n == tns->initnext) {
|
||||||
while (++tns->initnext < *tns->cnt && ((++file)->flags & FF_TN_INIT));
|
while (++tns->initnext < *tns->cnt && ((++file)->flags & FF_TN_INIT))
|
||||||
if (n == tns->loadnext && !cache_only)
|
;
|
||||||
while (++tns->loadnext < tns->end && (++t)->im != NULL);
|
}
|
||||||
|
if (n == tns->loadnext && !cache_only) {
|
||||||
|
while (++tns->loadnext < tns->end && (++t)->im != NULL)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -557,7 +561,7 @@ bool tns_zoom(tns_t *tns, int d)
|
||||||
oldzl = tns->zl;
|
oldzl = tns->zl;
|
||||||
tns->zl += -(d < 0) + (d > 0);
|
tns->zl += -(d < 0) + (d > 0);
|
||||||
tns->zl = MAX(tns->zl, 0);
|
tns->zl = MAX(tns->zl, 0);
|
||||||
tns->zl = MIN(tns->zl, (int)ARRLEN(thumb_sizes)-1);
|
tns->zl = MIN(tns->zl, (int)ARRLEN(thumb_sizes) - 1);
|
||||||
|
|
||||||
tns->bw = ((thumb_sizes[tns->zl] - 1) >> 5) + 1;
|
tns->bw = ((thumb_sizes[tns->zl] - 1) >> 5) + 1;
|
||||||
tns->bw = MIN(tns->bw, 4);
|
tns->bw = MIN(tns->bw, 4);
|
||||||
|
|
|
||||||
21
util.c
21
util.c
|
|
@ -32,7 +32,7 @@
|
||||||
extern char **environ;
|
extern char **environ;
|
||||||
const char *progname = "nsxiv";
|
const char *progname = "nsxiv";
|
||||||
|
|
||||||
void* emalloc(size_t size)
|
void *emalloc(size_t size)
|
||||||
{
|
{
|
||||||
void *ptr;
|
void *ptr;
|
||||||
|
|
||||||
|
|
@ -42,7 +42,7 @@ void* emalloc(size_t size)
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* ecalloc(size_t nmemb, size_t size)
|
void *ecalloc(size_t nmemb, size_t size)
|
||||||
{
|
{
|
||||||
void *ptr;
|
void *ptr;
|
||||||
|
|
||||||
|
|
@ -52,7 +52,7 @@ void* ecalloc(size_t nmemb, size_t size)
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* erealloc(void *ptr, size_t size)
|
void *erealloc(void *ptr, size_t size)
|
||||||
{
|
{
|
||||||
ptr = realloc(ptr, size);
|
ptr = realloc(ptr, size);
|
||||||
if (ptr == NULL)
|
if (ptr == NULL)
|
||||||
|
|
@ -60,13 +60,13 @@ void* erealloc(void *ptr, size_t size)
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* estrdup(const char *s)
|
char *estrdup(const char *s)
|
||||||
{
|
{
|
||||||
size_t n = strlen(s) + 1;
|
size_t n = strlen(s) + 1;
|
||||||
return memcpy(emalloc(n), s, n);
|
return memcpy(emalloc(n), s, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
void error(int eval, int err, const char* fmt, ...)
|
void error(int eval, int err, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
|
|
@ -102,7 +102,7 @@ int r_opendir(r_dir_t *rdir, const char *dirname, bool recursive)
|
||||||
rdir->stack = emalloc(rdir->stcap * sizeof(*rdir->stack));
|
rdir->stack = emalloc(rdir->stcap * sizeof(*rdir->stack));
|
||||||
rdir->stlen = 0;
|
rdir->stlen = 0;
|
||||||
|
|
||||||
rdir->name = (char*) dirname;
|
rdir->name = (char *)dirname;
|
||||||
rdir->d = 0;
|
rdir->d = 0;
|
||||||
rdir->recursive = recursive;
|
rdir->recursive = recursive;
|
||||||
|
|
||||||
|
|
@ -133,7 +133,7 @@ int r_closedir(r_dir_t *rdir)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* r_readdir(r_dir_t *rdir, bool skip_dotfiles)
|
char *r_readdir(r_dir_t *rdir, bool skip_dotfiles)
|
||||||
{
|
{
|
||||||
size_t len;
|
size_t len;
|
||||||
char *filename;
|
char *filename;
|
||||||
|
|
@ -154,7 +154,7 @@ char* r_readdir(r_dir_t *rdir, bool skip_dotfiles)
|
||||||
len = strlen(rdir->name) + strlen(dentry->d_name) + 2;
|
len = strlen(rdir->name) + strlen(dentry->d_name) + 2;
|
||||||
filename = emalloc(len);
|
filename = emalloc(len);
|
||||||
snprintf(filename, len, "%s%s%s", rdir->name,
|
snprintf(filename, len, "%s%s%s", rdir->name,
|
||||||
rdir->name[strlen(rdir->name)-1] == '/' ? "" : "/",
|
rdir->name[strlen(rdir->name) - 1] == '/' ? "" : "/",
|
||||||
dentry->d_name);
|
dentry->d_name);
|
||||||
|
|
||||||
if (stat(filename, &fstats) < 0) {
|
if (stat(filename, &fstats) < 0) {
|
||||||
|
|
@ -203,7 +203,8 @@ int r_mkdir(char *path)
|
||||||
s++;
|
s++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for (; *s != '\0' && *s != '/'; s++);
|
for (; *s != '\0' && *s != '/'; s++)
|
||||||
|
;
|
||||||
c = *s;
|
c = *s;
|
||||||
*s = '\0';
|
*s = '\0';
|
||||||
if (mkdir(path, 0755) == -1) {
|
if (mkdir(path, 0755) == -1) {
|
||||||
|
|
@ -226,7 +227,7 @@ void construct_argv(char **argv, unsigned int len, ...)
|
||||||
for (i = 0; i < len; ++i)
|
for (i = 0; i < len; ++i)
|
||||||
argv[i] = va_arg(args, char *);
|
argv[i] = va_arg(args, char *);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
assert(argv[len-1] == NULL && "argv should be NULL terminated");
|
assert(argv[len - 1] == NULL && "argv should be NULL terminated");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mkspawn_pipe(posix_spawn_file_actions_t *fa, const char *cmd, int *pfd, int dupidx)
|
static int mkspawn_pipe(posix_spawn_file_actions_t *fa, const char *cmd, int *pfd, int dupidx)
|
||||||
|
|
|
||||||
34
window.c
34
window.c
|
|
@ -56,8 +56,12 @@ static struct {
|
||||||
int name;
|
int name;
|
||||||
Cursor icon;
|
Cursor icon;
|
||||||
} cursors[CURSOR_COUNT] = {
|
} cursors[CURSOR_COUNT] = {
|
||||||
{ XC_left_ptr }, { XC_dotbox }, { XC_fleur }, { XC_watch },
|
{ XC_left_ptr },
|
||||||
{ XC_sb_left_arrow }, { XC_sb_right_arrow }
|
{ XC_dotbox },
|
||||||
|
{ XC_fleur },
|
||||||
|
{ XC_watch },
|
||||||
|
{ XC_sb_left_arrow },
|
||||||
|
{ XC_sb_right_arrow }
|
||||||
};
|
};
|
||||||
|
|
||||||
#if HAVE_LIBFONTS
|
#if HAVE_LIBFONTS
|
||||||
|
|
@ -90,7 +94,7 @@ static void win_alloc_color(const win_env_t *e, const char *name, XColor *col)
|
||||||
error(EXIT_FAILURE, 0, "Error allocating color '%s'", name);
|
error(EXIT_FAILURE, 0, "Error allocating color '%s'", name);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char* win_res(XrmDatabase db, const char *name, const char *def)
|
static const char *win_res(XrmDatabase db, const char *name, const char *def)
|
||||||
{
|
{
|
||||||
char *type;
|
char *type;
|
||||||
XrmValue ret;
|
XrmValue ret;
|
||||||
|
|
@ -226,8 +230,8 @@ void win_open(win_t *win)
|
||||||
if (gmask & YValue) {
|
if (gmask & YValue) {
|
||||||
if (gmask & YNegative) {
|
if (gmask & YNegative) {
|
||||||
win->y += e->scrh - win->h;
|
win->y += e->scrh - win->h;
|
||||||
sizehints.win_gravity = sizehints.win_gravity == NorthEastGravity
|
sizehints.win_gravity = sizehints.win_gravity == NorthEastGravity ?
|
||||||
? SouthEastGravity : SouthWestGravity;
|
SouthEastGravity : SouthWestGravity;
|
||||||
}
|
}
|
||||||
sizehints.flags |= USPosition;
|
sizehints.flags |= USPosition;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -246,7 +250,7 @@ void win_open(win_t *win)
|
||||||
/* set the _NET_WM_PID */
|
/* set the _NET_WM_PID */
|
||||||
pid = getpid();
|
pid = getpid();
|
||||||
XChangeProperty(e->dpy, win->xwin, atoms[ATOM__NET_WM_PID], XA_CARDINAL,
|
XChangeProperty(e->dpy, win->xwin, atoms[ATOM__NET_WM_PID], XA_CARDINAL,
|
||||||
32, PropModeReplace, (unsigned char *) &pid, 1);
|
32, PropModeReplace, (unsigned char *)&pid, 1);
|
||||||
if (gethostname(hostname, ARRLEN(hostname)) == 0) {
|
if (gethostname(hostname, ARRLEN(hostname)) == 0) {
|
||||||
XTextProperty tp;
|
XTextProperty tp;
|
||||||
tp.value = (unsigned char *)hostname;
|
tp.value = (unsigned char *)hostname;
|
||||||
|
|
@ -272,7 +276,7 @@ void win_open(win_t *win)
|
||||||
|
|
||||||
gc = XCreateGC(e->dpy, win->xwin, 0, None);
|
gc = XCreateGC(e->dpy, win->xwin, 0, None);
|
||||||
|
|
||||||
n = icons[ARRLEN(icons)-1].size;
|
n = icons[ARRLEN(icons) - 1].size;
|
||||||
icon_data = emalloc((n * n + 2) * sizeof(*icon_data));
|
icon_data = emalloc((n * n + 2) * sizeof(*icon_data));
|
||||||
|
|
||||||
for (i = 0; i < (int)ARRLEN(icons); i++) {
|
for (i = 0; i < (int)ARRLEN(icons); i++) {
|
||||||
|
|
@ -286,7 +290,7 @@ void win_open(win_t *win)
|
||||||
}
|
}
|
||||||
XChangeProperty(e->dpy, win->xwin, atoms[ATOM__NET_WM_ICON], XA_CARDINAL, 32,
|
XChangeProperty(e->dpy, win->xwin, atoms[ATOM__NET_WM_ICON], XA_CARDINAL, 32,
|
||||||
i == 0 ? PropModeReplace : PropModeAppend,
|
i == 0 ? PropModeReplace : PropModeAppend,
|
||||||
(unsigned char *) icon_data, n);
|
(unsigned char *)icon_data, n);
|
||||||
}
|
}
|
||||||
free(icon_data);
|
free(icon_data);
|
||||||
|
|
||||||
|
|
@ -311,7 +315,7 @@ void win_open(win_t *win)
|
||||||
if (options->fullscreen) {
|
if (options->fullscreen) {
|
||||||
XChangeProperty(e->dpy, win->xwin, atoms[ATOM__NET_WM_STATE],
|
XChangeProperty(e->dpy, win->xwin, atoms[ATOM__NET_WM_STATE],
|
||||||
XA_ATOM, 32, PropModeReplace,
|
XA_ATOM, 32, PropModeReplace,
|
||||||
(unsigned char *) &atoms[ATOM__NET_WM_STATE_FULLSCREEN], 1);
|
(unsigned char *)&atoms[ATOM__NET_WM_STATE_FULLSCREEN], 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
win->h -= win->bar.h;
|
win->h -= win->bar.h;
|
||||||
|
|
@ -432,10 +436,10 @@ static int win_draw_text(win_t *win, XftDraw *d, const XftColor *color,
|
||||||
FC_SIZE, FcTypeDouble, fontsize, NULL);
|
FC_SIZE, FcTypeDouble, fontsize, NULL);
|
||||||
FcCharSetDestroy(fccharset);
|
FcCharSetDestroy(fccharset);
|
||||||
}
|
}
|
||||||
XftTextExtentsUtf8(win->env.dpy, f, (XftChar8*)t, next - t, &ext);
|
XftTextExtentsUtf8(win->env.dpy, f, (XftChar8 *)t, next - t, &ext);
|
||||||
tw += ext.xOff;
|
tw += ext.xOff;
|
||||||
if (tw <= w) {
|
if (tw <= w) {
|
||||||
XftDrawStringUtf8(d, color, f, x, y, (XftChar8*)t, next - t);
|
XftDrawStringUtf8(d, color, f, x, y, (XftChar8 *)t, next - t);
|
||||||
x += ext.xOff;
|
x += ext.xOff;
|
||||||
}
|
}
|
||||||
if (f != font)
|
if (f != font)
|
||||||
|
|
@ -456,7 +460,7 @@ static void win_draw_bar(win_t *win)
|
||||||
r = &win->bar.r;
|
r = &win->bar.r;
|
||||||
assert(l->buf != NULL && r->buf != NULL);
|
assert(l->buf != NULL && r->buf != NULL);
|
||||||
y = (win->bar.top ? 0 : win->h) + font->ascent + V_TEXT_PAD;
|
y = (win->bar.top ? 0 : win->h) + font->ascent + V_TEXT_PAD;
|
||||||
w = win->w - 2*H_TEXT_PAD;
|
w = win->w - 2 * H_TEXT_PAD;
|
||||||
d = XftDrawCreate(e->dpy, win->buf.pm, e->vis, e->cmap);
|
d = XftDrawCreate(e->dpy, win->buf.pm, e->vis, e->cmap);
|
||||||
|
|
||||||
XSetForeground(e->dpy, gc, win->bar_bg.pixel);
|
XSetForeground(e->dpy, gc, win->bar_bg.pixel);
|
||||||
|
|
@ -466,8 +470,10 @@ static void win_draw_bar(win_t *win)
|
||||||
XSetBackground(e->dpy, gc, win->bar_bg.pixel);
|
XSetBackground(e->dpy, gc, win->bar_bg.pixel);
|
||||||
|
|
||||||
if ((len = strlen(r->buf)) > 0) {
|
if ((len = strlen(r->buf)) > 0) {
|
||||||
if ((tw = TEXTWIDTH(win, r->buf, len)) > w)
|
if ((tw = TEXTWIDTH(win, r->buf, len)) > w) {
|
||||||
|
XftDrawDestroy(d);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
x = win->w - tw - H_TEXT_PAD;
|
x = win->w - tw - H_TEXT_PAD;
|
||||||
w -= tw;
|
w -= tw;
|
||||||
win_draw_text(win, d, &win->bar_fg, x, y, r->buf, len, tw);
|
win_draw_text(win, d, &win->bar_fg, x, y, r->buf, len, tw);
|
||||||
|
|
@ -482,7 +488,7 @@ static void win_draw_bar(win_t *win)
|
||||||
#else
|
#else
|
||||||
static void win_draw_bar(win_t *win)
|
static void win_draw_bar(win_t *win)
|
||||||
{
|
{
|
||||||
(void) win;
|
(void)win;
|
||||||
}
|
}
|
||||||
#endif /* HAVE_LIBFONTS */
|
#endif /* HAVE_LIBFONTS */
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue