diff options
| author | stkhan <personal@slickd.xyz> | 2023-03-27 20:57:44 -0500 |
|---|---|---|
| committer | stkhan <personal@slickd.xyz> | 2023-03-27 20:57:44 -0500 |
| commit | e58dcfbcd127e00bec22141387037bc58ce8bec8 (patch) | |
| tree | 4adc1f6694654b9fe83fa49c18b38dcef9f02e7d /utils | |
| parent | a327f64412c10b04832fa5ba7c34cf494e291c19 (diff) | |
initwayland
Diffstat (limited to 'utils')
81 files changed, 0 insertions, 20944 deletions
diff --git a/utils/farbfeld/2ff b/utils/farbfeld/2ff deleted file mode 100755 index 6ce91b9..0000000 --- a/utils/farbfeld/2ff +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/sh - -# arguments -if [ "$#" -ne 0 ]; then - echo "usage: $0" >&2 - exit 1 -fi - -# write input into temporary file -TMP=$(mktemp) -trap 'rm "$TMP"' EXIT -cat > "$TMP" - -# determine the mime-type -if [ "$(dd if="$TMP" bs=1 count=8 2>/dev/null | tr -d '\0')" = "farbfeld" ]; then - cat "$TMP" -else - MIME=$(file -ib "$TMP" | cut -d ";" -f 1) - - case "$MIME" in - image/png) - png2ff < "$TMP" - ;; - image/jpeg) - jpg2ff < "$TMP" - ;; - *) - convert "$TMP" png:- | png2ff - ;; - esac -fi - -# errors -if [ $? -ne 0 ]; then - exit 1 -else - exit 0 -fi diff --git a/utils/farbfeld/2ff.1 b/utils/farbfeld/2ff.1 deleted file mode 100644 index 426e3fd..0000000 --- a/utils/farbfeld/2ff.1 +++ /dev/null @@ -1,45 +0,0 @@ -.Dd 2018-04-11 -.Dt 2FF 1 -.Os suckless.org -.Sh NAME -.Nm 2ff -.Nd convert image to farbfeld -.Sh SYNOPSIS -.Nm -.Sh DESCRIPTION -.Nm -reads an image from stdin, converts it to -.Xr farbfeld 5 -and writes the result to stdout. -.Pp -.Nm -is a wrapper script around the farbfeld conversion tools -with a fallback to obtaining a PNG using -.Xr ImageMagick 1 -and passing it through -.Xr png2ff 1 . -.Pp -In case of an error -.Nm -writes a diagnostic message to stderr. -.Sh EXIT STATUS -.Bl -tag -width Ds -.It 0 -Image processed successfully. -.It 1 -An error occurred. -.El -.Sh EXAMPLES -$ -.Nm -< image.* > image.ff -.Pp -$ -.Nm -< image.* | bzip2 > image.ff.bz2 -.Sh SEE ALSO -.Xr bzip2 1 , -.Xr ImageMagick 1 , -.Xr farbfeld 5 -.Sh AUTHORS -.An Laslo Hunhold Aq Mt dev@frign.de diff --git a/utils/farbfeld/FORMAT b/utils/farbfeld/FORMAT deleted file mode 100644 index 0c082ea..0000000 --- a/utils/farbfeld/FORMAT +++ /dev/null @@ -1,14 +0,0 @@ - - FARBFELD IMAGE FORMAT SPECIFICATION - - ╔════════╤═════════════════════════════════════════════════════════╗ - ║ Bytes │ Description ║ - ╠════════╪═════════════════════════════════════════════════════════╣ - ║ 8 │ "farbfeld" magic value ║ - ╟────────┼─────────────────────────────────────────────────────────╢ - ║ 4 │ 32-Bit BE unsigned integer (width) ║ - ╟────────┼─────────────────────────────────────────────────────────╢ - ║ 4 │ 32-Bit BE unsigned integer (height) ║ - ╟────────┼─────────────────────────────────────────────────────────╢ - ║ [2222] │ 4⋅16-Bit BE unsigned integers [RGBA] / pixel, row-major ║ - ╚════════╧═════════════════════════════════════════════════════════╝ diff --git a/utils/farbfeld/LICENSE b/utils/farbfeld/LICENSE deleted file mode 100644 index 05640a5..0000000 --- a/utils/farbfeld/LICENSE +++ /dev/null @@ -1,24 +0,0 @@ -ISC-License - -Copyright 2014-2018 Laslo Hunhold <dev@frign.de> - -Copyright 2004 Ted Unangst <tedu@openbsd.org> -Copyright 2004 Todd C. Miller <Todd.Miller@courtesan.com> -Copyright 2008 Otto Moerbeek <otto@drijf.net> -Copyright 2014-2015 Dimitris Papastamos <sin@2f30.org> -Copyright 2014-2016 Hiltjo Posthuma <hiltjo@codemadness.org> -Copyright 2015 Willy Goiffon <willy@mailoo.org> -Copyright 2016 Alexander Krotov <ilabdsf@yandex.ru> -Copyright 2017 Mattias Andrée <maandree@kth.se> - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/utils/farbfeld/Makefile b/utils/farbfeld/Makefile deleted file mode 100644 index 354509b..0000000 --- a/utils/farbfeld/Makefile +++ /dev/null @@ -1,68 +0,0 @@ -# See LICENSE file for copyright and license details -# farbfeld - suckless image format with conversion tools -.POSIX: - -include config.mk -include ../../config.mk - -REQ = util -HDR = arg.h -BIN = png2ff ff2png jpg2ff ff2jpg ff2pam ff2ppm -SCR = 2ff -MAN1 = 2ff.1 $(BIN:=.1) -MAN5 = farbfeld.5 - -all: $(BIN) - -png2ff-LDLIBS = $(PNG-LDLIBS) -ff2png-LDLIBS = $(PNG-LDLIBS) -jpg2ff-LDLIBS = $(JPG-LDLIBS) -ff2jpg-LDLIBS = $(JPG-LDLIBS) - -png2ff: png2ff.o $(REQ:=.o) -ff2png: ff2png.o $(REQ:=.o) -jpg2ff: jpg2ff.o $(REQ:=.o) -ff2jpg: ff2jpg.o $(REQ:=.o) -ff2pam: ff2pam.o $(REQ:=.o) -ff2ppm: ff2ppm.o $(REQ:=.o) - -png2ff.o: png2ff.c config.mk $(HDR) $(REQ:=.h) -ff2png.o: ff2png.c config.mk $(HDR) $(REQ:=.h) -jpg2ff.o: jpg2ff.c config.mk $(HDR) $(REQ:=.h) -ff2jpg.o: ff2jpg.c config.mk $(HDR) $(REQ:=.h) -ff2pam.o: ff2pam.c config.mk $(HDR) $(REQ:=.h) -ff2ppm.o: ff2ppm.c config.mk $(HDR) $(REQ:=.h) - -.o: - $(CC) -o $@ $(LDFLAGS) $< $(REQ:=.o) $($*-LDLIBS) - -.c.o: - $(CC) -c $(CPPFLAGS) $(CFLAGS) $< - -clean: - rm -f $(BIN) $(BIN:=.o) $(REQ:=.o) - -dist: - rm -rf "farbfeld-$(VERSION)" - mkdir -p "farbfeld-$(VERSION)" - cp -R FORMAT LICENSE Makefile README config.mk $(SCR) \ - $(HDR) $(BIN:=.c) $(REQ:=.c) $(REQ:=.h) \ - $(MAN1) $(MAN5) "farbfeld-$(VERSION)" - tar -cf - "farbfeld-$(VERSION)" | gzip -c > "farbfeld-$(VERSION).tar.gz" - rm -rf "farbfeld-$(VERSION)" - -install: all - mkdir -p "$(DESTDIR)$(PREFIX)/bin" - cp -f $(SCR) $(BIN) "$(DESTDIR)$(PREFIX)/bin" - for f in $(BIN) $(SCR); do chmod 755 "$(DESTDIR)$(PREFIX)/bin/$$f"; done - mkdir -p "$(DESTDIR)$(MANPREFIX)/man1" - cp -f $(MAN1) "$(DESTDIR)$(MANPREFIX)/man1" - for m in $(MAN1); do chmod 644 "$(DESTDIR)$(MANPREFIX)/man1/$$m"; done - mkdir -p "$(DESTDIR)$(MANPREFIX)/man5" - cp -f $(MAN5) "$(DESTDIR)$(MANPREFIX)/man5" - for m in $(MAN5); do chmod 644 "$(DESTDIR)$(MANPREFIX)/man5/$$m"; done - -uninstall: - for f in $(BIN) $(SCR); do rm -f "$(DESTDIR)$(PREFIX)/bin/$$f"; done - for m in $(MAN1); do rm -f "$(DESTDIR)$(MANPREFIX)/man1/$$m"; done - for m in $(MAN5); do rm -f "$(DESTDIR)$(MANPREFIX)/man5/$$m"; done diff --git a/utils/farbfeld/README b/utils/farbfeld/README deleted file mode 100644 index 1fe1125..0000000 --- a/utils/farbfeld/README +++ /dev/null @@ -1,74 +0,0 @@ - - ███ ███ ██ ██ ███ ███ █ ██ - █ █ █ █ █ █ █ █ █ █ █ █ - ██ ███ ██ ███ ██ ██ █ █ █ - █ █ █ █ █ █ █ █ █ █ █ █ - █ █ █ █ █ ██ █ ███ ███ ██ - - -WHAT IS FARBFELD? - Farbfeld is a lossless image-format designed to be - parsed and piped easily. It is probably the simplest - image-format you can find (see FORMAT). - It does not have integrated compression, but allows - compression algorithms to work with it easily by adding - little entropy to the image data itself. This beats PNG - in many cases. - Given the free choice of compression algorithms, it - is trivial to switch to better and faster ones as they - show up in the future. - -HOW DO I USE THE TOOLS? - encoding: - png2ff < example.png > example.ff - png2ff < example.png | bzip2 > example.ff.bz2 - - decoding: - ff2png < example.ff > example.png - bzcat example.ff.bz2 | ff2png > example.png - - bzip2 is used in this example and a recommended - compression algorithm. Of course you are free - to use something else. - -WHY FARBFELD? - Current image-formats have integrated compression, - making it complicated to read the image data. - One is forced to use complex libraries like libpng, - libjpeg, libjpeg-turbo, giflib and others, read the - documentation and write a lot of boilerplate in order - to get started. - Farbfeld leaves this behind and is designed to be as - simple as possible, leaving the task of compression - to outside tools. - The simple design, which was the primary objective, - implicitly lead to the very good compression - characteristics, as it often happens when you go with - the UNIX philosophy. - Reading farbfeld images doesn't require any special - libraries. The tools in this folder are just a toolbox - to make it easy to convert between common image formats - and farbfeld. - -HOW DOES IT WORK? - In farbfeld, pattern resolution is not done while - converting, but while compressing the image. - For example, farbfeld always stores the alpha-channel, - even if the image doesn't have alpha-variation. - This may sound like a big waste at first, but as - soon as you compress an image of this kind, the - compression-algorithm (e.g. bzip2) recognizes the - pattern that every 48 bits the 16 bits store the - same information. - And the compression-algorithms get better and better - at this. - Same applies to the idea of having 16 bits per channel. - It sounds excessive, but if you for instance only have - a greyscale image, the R, G and B channels will store - the same value, which is recognized by the compression - algorithm easily. - This effectively leads to filesizes you'd normally only - reach with paletted images, and in some cases bzip2 even - beats png's compression, for instance when you're dealing - with grayscale data, line drawings, decals and even - photographs. diff --git a/utils/farbfeld/arg.h b/utils/farbfeld/arg.h deleted file mode 100644 index 7f503ec..0000000 --- a/utils/farbfeld/arg.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * ISC-License - * - * Copyright 2017 Laslo Hunhold <dev@frign.de> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -#ifndef ARG_H -#define ARG_H - -extern char *argv0; - -/* int main(int argc, char *argv[]) */ -#define ARGBEGIN for (argv0 = *argv, *argv ? (argc--, argv++) : ((void *)0); \ - *argv && (*argv)[0] == '-' && (*argv)[1]; argc--, argv++) { \ - int i_, argused_; \ - if ((*argv)[1] == '-' && !(*argv)[2]) { \ - argc--, argv++; \ - break; \ - } \ - for (i_ = 1, argused_ = 0; (*argv)[i_]; i_++) { \ - switch((*argv)[i_]) -#define ARGEND if (argused_) { \ - if ((*argv)[i_ + 1]) { \ - break; \ - } else { \ - argc--, argv++; \ - break; \ - } \ - } \ - } \ - } -#define ARGC() ((*argv)[i_]) -#define ARGF_(x) (((*argv)[i_ + 1]) ? (argused_ = 1, &((*argv)[i_ + 1])) : \ - (*(argv + 1)) ? (argused_ = 1, *(argv + 1)) : (x)) -#define EARGF(x) ARGF_(((x), exit(1), (char *)0)) -#define ARGF() ARGF_((char *)0) - -#endif diff --git a/utils/farbfeld/config.mk b/utils/farbfeld/config.mk deleted file mode 100644 index 8ba827a..0000000 --- a/utils/farbfeld/config.mk +++ /dev/null @@ -1,17 +0,0 @@ -# farbfeld version -VERSION = 4 - -# Customize below to fit your system - -# paths -MANPREFIX = $(PREFIX)/share/man - -# flags -CPPFLAGS = -D_DEFAULT_SOURCE -CFLAGS = -std=c99 -pedantic -Wall -Wextra -Os -LDFLAGS = -s -PNG-LDLIBS = -lpng -JPG-LDLIBS = -ljpeg - -# compiler and linker -CC = cc diff --git a/utils/farbfeld/farbfeld.5 b/utils/farbfeld/farbfeld.5 deleted file mode 100644 index 55dc47c..0000000 --- a/utils/farbfeld/farbfeld.5 +++ /dev/null @@ -1,177 +0,0 @@ -.Dd 2018-04-11 -.Dt FARBFELD 5 -.Os suckless.org -.Sh NAME -.Nm farbfeld -.Nd suckless image format -.Sh DESCRIPTION -.Nm -is a -.Em lossless -image format which is easy to parse, pipe and compress. -It has the following format: -.Bd -literal -offset left -BYTES DESCRIPTION -8 "farbfeld" magic value -4 32-Bit BE unsigned integer (width) -4 32-Bit BE unsigned integer (height) -[2222] 4*16-Bit BE unsigned integers [RGBA] / pixel, row-major -.Ed -.Pp -The RGB-data should be sRGB for best interoperability and not -alpha-premultiplied. -.Sh USAGE -.Nm -provides the tools -.Xr 2ff 1 , -.Xr jpg2ff 1 , -.Xr png2ff 1 -and -.Xr ff2jpg 1 , -.Xr ff2pam 1 , -.Xr ff2png 1 , -.Xr ff2ppm 1 -to -.Em convert -to and from farbfeld images respectively. -.Pp -.Xr bzip2 1 -is recommended for -.Em compression , -giving results comparable with PNG for photographs and much better results -for other image types. -.sp -The -.Em file extension -is ".ff" and compression extensions shall be -appended (e.g. ".ff.bz2"). -.Sh MOTIVATION -.Nm -was created because the author was not satisfied with the boilerplate -and inherent complexity involved in handling common image formats -(PNG, JPEG, GIF,...), having to rely on bloated libraries while not being -able to focus on the task at hand for a given image processing problem. -.Sh EXAMPLES -The following code listing -.Em invert.c -is a ready-to-use color inverter with all necessary error handling and -reporting. This program can be integrated into a farbfeld pipeline as -follows: -.Pp -$ png2ff < image.png | invert | ff2png > image-inverted.png -.Pp -It shall be noted here that due to the simplicity of the format no -external libraries are needed to handle the farbfeld image data. The -0BSD-License gives you the freedom to throw away the license block and -just use the code as you wish. Happy hacking! -.Bd -literal -offset left -/* - * 0BSD-License - * - * (c) 2017 Laslo Hunhold <dev@frign.de> - * - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ -#include <arpa/inet.h> - -#include <errno.h> -#include <stdint.h> -#include <stdio.h> -#include <string.h> - -#define LEN(x) (sizeof (x) / sizeof *(x)) - -static void -invert(uint16_t rgba[4]) -{ - rgba[0] = UINT16_MAX - rgba[0]; - rgba[1] = UINT16_MAX - rgba[1]; - rgba[2] = UINT16_MAX - rgba[2]; -} - -int -main(int argc, char *argv[]) -{ - uint32_t hdr[4], width, height, i, j, k; - uint16_t rgba[4]; - - /* arguments */ - if (argc != 1) { - fprintf(stderr, "usage: %s\\n", argv[0]); - return 1; - } - - /* read header */ - if (fread(hdr, sizeof(*hdr), LEN(hdr), stdin) != LEN(hdr)) { - goto readerr; - } - if (memcmp("farbfeld", hdr, sizeof("farbfeld") - 1)) { - fprintf(stderr, "%s: invalid magic value\\n", argv[0]); - return 1; - } - width = ntohl(hdr[2]); - height = ntohl(hdr[3]); - - /* write data */ - if (fwrite(hdr, sizeof(*hdr), LEN(hdr), stdout) != 4) { - goto writerr; - } - - for (i = 0; i < height; i++) { - for (j = 0; j < width; j++) { - if (fread(rgba, sizeof(*rgba), LEN(rgba), - stdin) != LEN(rgba)) { - goto readerr; - } - for (k = 0; k < 4; k++) { - rgba[k] = ntohs(rgba[k]); - } - - invert(rgba); - - for (k = 0; k < 4; k++) { - rgba[k] = htons(rgba[k]); - } - if (fwrite(rgba, sizeof(*rgba), LEN(rgba), - stdout) != LEN(rgba)) { - goto writerr; - } - } - } - - /* clean up */ - if (fclose(stdout)) { - fprintf(stderr, "%s: fclose: %s\\n", argv[0], - strerror(errno)); - return 1; - } - - return 0; -readerr: - fprintf(stderr, "%s: fread: Unexpected EOF\\n", argv[0]); - return 1; -writerr: - fprintf(stderr, "%s: fwrite: %s\\n", argv[0], strerror(errno)); - return 1; -} -.Ed -.Sh SEE ALSO -.Xr 2ff 1 , -.Xr ff2jpg 1 , -.Xr ff2pam 1 , -.Xr ff2png 1 , -.Xr ff2ppm 1 , -.Xr jpg2ff 1 , -.Xr png2ff 1 -.Sh AUTHORS -.An Laslo Hunhold Aq Mt dev@frign.de diff --git a/utils/farbfeld/ff2jpg.1 b/utils/farbfeld/ff2jpg.1 deleted file mode 100644 index 745ae6e..0000000 --- a/utils/farbfeld/ff2jpg.1 +++ /dev/null @@ -1,54 +0,0 @@ -.Dd 2018-04-11 -.Dt FF2JPG 1 -.Os suckless.org -.Sh NAME -.Nm ff2jpg -.Nd convert farbfeld to JPG -.Sh SYNOPSIS -.Nm -.Op Fl b Ar colour -.Op Fl o -.Op Fl q Ar quality -.Sh DESCRIPTION -.Nm -reads a -.Xr farbfeld 5 -image from stdin, converts it to JPG (8-bit RGB) and writes the result to -stdout. -.Pp -In case of an error -.Nm -writes a diagnostic message to stderr. -.Sh OPTIONS -.Bl -tag -width Ds -.It Fl b Ar colour -Blend the transparent colours with -.Ar colour -specified as rgb, rrggbb or rrrrggggbbbb. The default is fff. -.It Fl o -Optimize the Huffman table, which reduces the file size but takes longer. -.It Fl q Ar quality -Set the output -.Ar quality -ranging from 0 to 100. The default is 85. -.El -.Sh EXIT STATUS -.Bl -tag -width Ds -.It 0 -Image processed successfully. -.It 1 -An error occurred. -.El -.Sh EXAMPLES -$ -.Nm -< image.ff > image.jpg -.Pp -$ bunzip2 < image.ff.bz2 | -.Nm --b 0f0 -q 90 > image.jpg -.Sh SEE ALSO -.Xr bzip2 1 , -.Xr farbfeld 5 -.Sh AUTHORS -.An Hiltjo Posthuma Aq Mt hiltjo@codemadness.org diff --git a/utils/farbfeld/ff2jpg.c b/utils/farbfeld/ff2jpg.c deleted file mode 100644 index f4514b8..0000000 --- a/utils/farbfeld/ff2jpg.c +++ /dev/null @@ -1,114 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include <arpa/inet.h> - -#include <errno.h> -#include <inttypes.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include <jpeglib.h> - -#include "arg.h" -#include "util.h" - -static void -jpeg_error(j_common_ptr js) -{ - fprintf(stderr, "%s: libjpeg: ", argv0); - (*js->err->output_message)(js); - exit(1); -} - -static void -jpeg_setup_writer(struct jpeg_compress_struct *s, struct jpeg_error_mgr *e, - uint32_t w, uint32_t h, int quality, int opt) -{ - jpeg_create_compress(s); - e->error_exit = jpeg_error; - s->err = jpeg_std_error(e); - - jpeg_stdio_dest(s, stdout); - s->image_width = w; - s->image_height = h; - s->input_components = 3; /* color components per pixel */ - s->in_color_space = JCS_RGB; /* output color space */ - jpeg_set_defaults(s); - - if (opt) { - s->optimize_coding = 1; - } - jpeg_set_quality(s, quality, 1); - - jpeg_start_compress(s, 1); -} - -static void -usage(void) -{ - die("usage: %s [-b colour] [-o] [-q quality]", argv0); -} - -int -main(int argc, char *argv[]) -{ - struct jpeg_compress_struct jcomp; - struct jpeg_error_mgr jerr; - size_t rowlen; - uint64_t a; - uint32_t width, height, i, j, k, l; - uint16_t *row, mask[3] = { 0xffff, 0xffff, 0xffff }; - uint8_t *rowout; - int optimize = 0, quality = 85; - - /* arguments */ - ARGBEGIN { - case 'b': - if (parse_mask(EARGF(usage()), mask)) { - usage(); - } - break; - case 'o': - optimize = 1; - break; - case 'q': - quality = estrtonum(EARGF(usage()), 0, 100); - break; - default: - usage(); - } ARGEND - - if (argc) { - usage(); - } - - /* prepare */ - ff_read_header(&width, &height); - jpeg_setup_writer(&jcomp, &jerr, width, height, quality, optimize); - row = ereallocarray(NULL, width, (sizeof("RGBA") - 1) * sizeof(uint16_t)); - rowlen = width * (sizeof("RGBA") - 1); - rowout = ereallocarray(NULL, width, (sizeof("RGB") - 1) * sizeof(uint8_t)); - - /* write data */ - for (i = 0; i < height; ++i) { - efread(row, sizeof(uint16_t), rowlen, stdin); - for (j = 0, k = 0; j < rowlen; j += 4, k += 3) { - a = ntohs(row[j + 3]); - for (l = 0; l < 3; l++) { - /* alpha blending and 8-bit-reduction */ - rowout[k + l] = (a * ntohs(row[j + l]) + - (UINT16_MAX - a) * mask[l]) / - (UINT16_MAX * - (UINT16_MAX / UINT8_MAX)); - } - } - jpeg_write_scanlines(&jcomp, &rowout, 1); - } - - /* clean up */ - jpeg_finish_compress(&jcomp); - jpeg_destroy_compress(&jcomp); - - return fshut(stdout, "<stdout>"); -} diff --git a/utils/farbfeld/ff2pam.1 b/utils/farbfeld/ff2pam.1 deleted file mode 100644 index 3f4acfe..0000000 --- a/utils/farbfeld/ff2pam.1 +++ /dev/null @@ -1,38 +0,0 @@ -.Dd 2018-04-11 -.Dt FF2PAM 1 -.Os suckless.org -.Sh NAME -.Nm ff2pam -.Nd convert farbfeld to PAM -.Sh SYNOPSIS -.Nm -.Sh DESCRIPTION -.Nm -reads a -.Xr farbfeld 5 -image from stdin, converts it to PAM (16-bit RGBA) and writes the result -to stdout. -.Pp -In case of an error -.Nm -writes a diagnostic message to stderr. -.Sh EXIT STATUS -.Bl -tag -width Ds -.It 0 -Image processed successfully. -.It 1 -An error occurred. -.El -.Sh EXAMPLES -$ -.Nm -< image.ff > image.pam -.Pp -$ bunzip2 < image.ff.bz2 | -.Nm -> image.pam -.Sh SEE ALSO -.Xr bzip2 1 , -.Xr farbfeld 5 -.Sh AUTHORS -.An Mattias Andrée Aq Mt maandree@kth.se diff --git a/utils/farbfeld/ff2pam.c b/utils/farbfeld/ff2pam.c deleted file mode 100644 index fca5c6f..0000000 --- a/utils/farbfeld/ff2pam.c +++ /dev/null @@ -1,55 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include <arpa/inet.h> - -#include <errno.h> -#include <inttypes.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#include "util.h" - -static void -usage(void) -{ - die("usage: %s", argv0); -} - -int -main(int argc, char *argv[]) -{ - size_t rowlen; - uint32_t width, height, i; - uint16_t *row; - - /* arguments */ - argv0 = argv[0], argc--, argv++; - - if (argc) { - usage(); - } - - /* prepare */ - ff_read_header(&width, &height); - row = ereallocarray(NULL, width, (sizeof("RGBA") - 1) * sizeof(uint16_t)); - rowlen = width * (sizeof("RGBA") - 1); - - /* write data */ - printf("P7\n" - "WIDTH %" PRIu32 "\n" - "HEIGHT %" PRIu32 "\n" - "DEPTH 4\n" /* number of channels */ - "MAXVAL 65535\n" - "TUPLTYPE RGB_ALPHA\n" - "ENDHDR\n", - width, height); - - for (i = 0; i < height; i++) { - efread(row, sizeof(uint16_t), rowlen, stdin); - efwrite(row, sizeof(uint16_t), rowlen, stdout); - } - - return fshut(stdout, "<stdout>"); -} diff --git a/utils/farbfeld/ff2png.1 b/utils/farbfeld/ff2png.1 deleted file mode 100644 index d8e1fab..0000000 --- a/utils/farbfeld/ff2png.1 +++ /dev/null @@ -1,38 +0,0 @@ -.Dd 2018-04-11 -.Dt FF2PNG 1 -.Os suckless.org -.Sh NAME -.Nm ff2png -.Nd convert farbfeld to PNG -.Sh SYNOPSIS -.Nm -.Sh DESCRIPTION -.Nm -reads a -.Xr farbfeld 5 -image from stdin, converts it to PNG (16-bit RGBA) and writes the result -to stdout. -.Pp -In case of an error -.Nm -writes a diagnostic message to stderr. -.Sh EXIT STATUS -.Bl -tag -width Ds -.It 0 -Image processed successfully. -.It 1 -An error occurred. -.El -.Sh EXAMPLES -$ -.Nm -< image.ff > image.png -.Pp -$ bunzip2 < image.ff.bz2 | -.Nm -> image.png -.Sh SEE ALSO -.Xr bzip2 1 , -.Xr farbfeld 5 -.Sh AUTHORS -.An Laslo Hunhold Aq Mt dev@frign.de diff --git a/utils/farbfeld/ff2png.c b/utils/farbfeld/ff2png.c deleted file mode 100644 index 193b375..0000000 --- a/utils/farbfeld/ff2png.c +++ /dev/null @@ -1,77 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include <arpa/inet.h> - -#include <errno.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include <png.h> - -#include "util.h" - -static void -png_err(png_struct *pngs, const char *msg) -{ - (void)pngs; - die("libpng: %s", msg); -} - -static void -png_setup_writer(png_struct **s, png_info **i, uint32_t w, uint32_t h) -{ - *s = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, png_err, NULL); - *i = png_create_info_struct(*s); - - if (!*s || !*i) { - die("Failed to initialize libpng"); - } - - png_init_io(*s, stdout); - png_set_IHDR(*s, *i, w, h, 16, PNG_COLOR_TYPE_RGB_ALPHA, - PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, - PNG_FILTER_TYPE_BASE); - png_write_info(*s, *i); -} - -static void -usage(void) -{ - die("usage: %s", argv0); -} - -int -main(int argc, char *argv[]) -{ - png_struct *pngs; - png_info *pngi; - size_t rowlen; - uint32_t width, height, i; - uint16_t *row; - - /* arguments */ - argv0 = argv[0], argc--, argv++; - - if (argc) { - usage(); - } - - /* prepare */ - ff_read_header(&width, &height); - png_setup_writer(&pngs, &pngi, width, height); - row = ereallocarray(NULL, width, (sizeof("RGBA") - 1) * sizeof(uint16_t)); - rowlen = width * (sizeof("RGBA") - 1); - - /* write data */ - for (i = 0; i < height; ++i) { - efread(row, sizeof(uint16_t), rowlen, stdin); - png_write_row(pngs, (uint8_t *)row); - } - - /* clean up */ - png_write_end(pngs, NULL); - png_destroy_write_struct(&pngs, NULL); - - return fshut(stdout, "<stdout>"); -} diff --git a/utils/farbfeld/ff2ppm.1 b/utils/farbfeld/ff2ppm.1 deleted file mode 100644 index 1687346..0000000 --- a/utils/farbfeld/ff2ppm.1 +++ /dev/null @@ -1,46 +0,0 @@ -.Dd 2018-04-11 -.Dt FF2PPM 1 -.Os suckless.org -.Sh NAME -.Nm ff2ppm -.Nd convert farbfeld to PPM -.Sh SYNOPSIS -.Nm -.Op Fl b Ar colour -.Sh DESCRIPTION -.Nm -reads a -.Xr farbfeld 5 -image from stdin, converts it to PPM (16-Bit RGB P6 binary format) and -writes the result to stdout. -.Pp -In case of an error -.Nm -writes a diagnostic message to stderr. -.Sh OPTIONS -.Bl -tag -width Ds -.It Fl b Ar colour -Blend the transparent colours with -.Ar colour -specified as rgb, rrggbb or rrrrggggbbbb. The default is fff. -.El -.Sh EXIT STATUS -.Bl -tag -width Ds -.It 0 -Image processed successfully. -.It 1 -An error occurred. -.El -.Sh EXAMPLES -$ -.Nm -< image.ff > image.ppm -.Pp -$ bunzip2 < image.ff.bz2 | -.Nm --b 0f0 > image.ppm -.Sh SEE ALSO -.Xr bzip2 1 , -.Xr farbfeld 5 -.Sh AUTHORS -.An Hiltjo Posthuma Aq Mt hiltjo@codemadness.org diff --git a/utils/farbfeld/ff2ppm.c b/utils/farbfeld/ff2ppm.c deleted file mode 100644 index 9b82d9c..0000000 --- a/utils/farbfeld/ff2ppm.c +++ /dev/null @@ -1,72 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include <arpa/inet.h> - -#include <errno.h> -#include <inttypes.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "arg.h" -#include "util.h" - -static void -usage(void) -{ - die("usage: %s [-b colour]", argv0); -} - -int -main(int argc, char *argv[]) -{ - size_t rowlen, rowoutlen; - uint64_t a; - uint32_t width, height, i, j, k, l; - uint16_t *row, mask[3] = { 0xffff, 0xffff, 0xffff }; - uint8_t *rowout; - - /* arguments */ - ARGBEGIN { - case 'b': - if (parse_mask(EARGF(usage()), mask)) { - usage(); - } - break; - default: - usage(); - } ARGEND - - if (argc) { - usage(); - } - - /* prepare */ - ff_read_header(&width, &height); - row = ereallocarray(NULL, width, (sizeof("RGBA") - 1) * sizeof(uint16_t)); - rowout = ereallocarray(NULL, width, (sizeof("RGB") - 1) * sizeof(uint8_t)); - rowlen = width * (sizeof("RGBA") - 1); - rowoutlen = width * (sizeof("RGB") - 1); - - /* write data */ - printf("P6\n%" PRIu32 " %" PRIu32 "\n255\n", width, height); - - for (i = 0; i < height; ++i) { - efread(row, sizeof(uint16_t), rowlen, stdin); - - for (j = 0, k = 0; j < rowlen; j += 4, k += 3) { - a = ntohs(row[j + 3]); - for (l = 0; l < 3; l++) { - /* alpha blending and 8-bit-reduction */ - rowout[k + l] = (a * ntohs(row[j + l]) + - (UINT16_MAX - a) * mask[l]) / - (UINT16_MAX * - (UINT16_MAX / UINT8_MAX)); - } - } - - efwrite(rowout, sizeof(uint8_t), rowoutlen, stdout); - } - - return fshut(stdout, "<stdout>"); -} diff --git a/utils/farbfeld/jpg2ff.1 b/utils/farbfeld/jpg2ff.1 deleted file mode 100644 index 6ae67e2..0000000 --- a/utils/farbfeld/jpg2ff.1 +++ /dev/null @@ -1,38 +0,0 @@ -.Dd 2018-04-11 -.Dt JPG2FF 1 -.Os suckless.org -.Sh NAME -.Nm jpg2ff -.Nd convert JPG to farbfeld -.Sh SYNOPSIS -.Nm -.Sh DESCRIPTION -.Nm -reads a JPG image from stdin, converts it to -.Xr farbfeld 5 -and writes the result to stdout. -.Pp -In case of an error -.Nm -writes a diagnostic message to stderr. -.Sh EXIT STATUS -.Bl -tag -width Ds -.It 0 -Image processed successfully. -.It 1 -An error occurred. -.El -.Sh EXAMPLES -$ -.Nm -< image.jpg > image.ff -.Pp -$ -.Nm -< image.jpg | bzip2 > image.ff.bz2 -.Sh SEE ALSO -.Xr 2ff 1 , -.Xr bzip2 1 , -.Xr farbfeld 5 -.Sh AUTHORS -.An Laslo Hunhold Aq Mt dev@frign.de diff --git a/utils/farbfeld/jpg2ff.c b/utils/farbfeld/jpg2ff.c deleted file mode 100644 index 360ace4..0000000 --- a/utils/farbfeld/jpg2ff.c +++ /dev/null @@ -1,90 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include <arpa/inet.h> - -#include <errno.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include <jpeglib.h> - -#include "util.h" - -static void -jpeg_error(j_common_ptr js) -{ - fprintf(stderr, "%s: libjpeg: ", argv0); - (*js->err->output_message)(js); - exit(1); -} - -static void -jpeg_setup_reader(struct jpeg_decompress_struct *s, struct jpeg_error_mgr *e, - uint32_t *w, uint32_t *h) -{ - jpeg_create_decompress(s); - e->error_exit = jpeg_error; - s->err = jpeg_std_error(e); - - jpeg_stdio_src(s, stdin); - jpeg_read_header(s, 1); - *w = s->image_width; - *h = s->image_height; - s->output_components = 3; /* color components per pixel */ - s->out_color_space = JCS_RGB; /* input color space */ - - jpeg_start_decompress(s); -} - -static void -usage(void) -{ - die("usage: %s", argv0); -} - -int -main(int argc, char *argv[]) -{ - struct jpeg_decompress_struct js; - struct jpeg_error_mgr jerr; - uint32_t width, height; - uint16_t *row; - uint8_t *rowin; - size_t rowlen, i; - - /* arguments */ - argv0 = argv[0], argc--, argv++; - - if (argc) { - usage(); - } - - /* prepare */ - jpeg_setup_reader(&js, &jerr, &width, &height); - row = ereallocarray(NULL, width, (sizeof("RGBA") - 1) * sizeof(uint16_t)); - rowlen = width * (sizeof("RGBA") - 1); - rowin = ereallocarray(NULL, width, (sizeof("RGB") - 1) * sizeof(uint8_t)); - - /* write data */ - ff_write_header(width, height); - - while (js.output_scanline < js.output_height) { - jpeg_read_scanlines(&js, &rowin, 1); - - for (i = 0; i < width; ++i) { - row[4 * i + 0] = htons(rowin[3 * i + 0] * 257); - row[4 * i + 1] = htons(rowin[3 * i + 1] * 257); - row[4 * i + 2] = htons(rowin[3 * i + 2] * 257); - row[4 * i + 3] = htons(65535); - } - - efwrite(row, sizeof(uint16_t), rowlen, stdout); - } - - /* clean up */ - jpeg_finish_decompress(&js); - jpeg_destroy_decompress(&js); - - return fshut(stdout, "<stdout>"); -} diff --git a/utils/farbfeld/png2ff.1 b/utils/farbfeld/png2ff.1 deleted file mode 100644 index 5ede5c9..0000000 --- a/utils/farbfeld/png2ff.1 +++ /dev/null @@ -1,38 +0,0 @@ -.Dd 2018-04-11 -.Dt PNG2FF 1 -.Os suckless.org -.Sh NAME -.Nm png2ff -.Nd convert PNG to farbfeld -.Sh SYNOPSIS -.Nm -.Sh DESCRIPTION -.Nm -reads a PNG image from stdin, converts it to -.Xr farbfeld 5 -and writes the result to stdout. -.Pp -In case of an error -.Nm -writes a diagnostic message to stderr. -.Sh EXIT STATUS -.Bl -tag -width Ds -.It 0 -Image processed successfully. -.It 1 -An error occurred. -.El -.Sh EXAMPLES -$ -.Nm -< image.png > image.ff -.Pp -$ -.Nm -< image.png | bzip2 > image.ff.bz2 -.Sh SEE ALSO -.Xr 2ff 1 , -.Xr bzip2 1 , -.Xr farbfeld 5 -.Sh AUTHORS -.An Laslo Hunhold Aq Mt dev@frign.de diff --git a/utils/farbfeld/png2ff.c b/utils/farbfeld/png2ff.c deleted file mode 100644 index 74109d8..0000000 --- a/utils/farbfeld/png2ff.c +++ /dev/null @@ -1,97 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include <arpa/inet.h> - -#include <errno.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include <png.h> - -#include "util.h" - -static void -png_err(png_struct *pngs, const char *msg) -{ - (void)pngs; - die("libpng: %s", msg); -} - -static void -png_setup_reader(png_struct **s, png_info **i, uint32_t *w, uint32_t *h) -{ - *s = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, png_err, NULL); - *i = png_create_info_struct(*s); - - if (!*s || !*i) { - die("Failed to initialize libpng"); - } - - png_init_io(*s, stdin); - if (png_get_valid(*s, *i, PNG_INFO_tRNS)) { - png_set_tRNS_to_alpha(*s); - } - png_set_add_alpha(*s, 255*257, PNG_FILLER_AFTER); - png_set_expand_gray_1_2_4_to_8(*s); - png_set_gray_to_rgb(*s); - png_set_packing(*s); - png_read_png(*s, *i, PNG_TRANSFORM_PACKING | PNG_TRANSFORM_EXPAND, NULL); - *w = png_get_image_width(*s, *i); - *h = png_get_image_height(*s, *i); -} - -static void -usage(void) -{ - die("usage: %s", argv0); -} - -int -main(int argc, char *argv[]) -{ - png_struct *pngs; - png_info *pngi; - uint32_t width, height, rowlen, r, i; - uint16_t *row; - uint8_t **pngrows; - - /* arguments */ - argv0 = argv[0], argc--, argv++; - - if (argc) { - usage(); - } - - /* prepare */ - png_setup_reader(&pngs, &pngi, &width, &height); - row = ereallocarray(NULL, width, (sizeof("RGBA") - 1) * sizeof(uint16_t)); - rowlen = width * (sizeof("RGBA") - 1); - pngrows = png_get_rows(pngs, pngi); - - /* write data */ - ff_write_header(width, height); - - switch(png_get_bit_depth(pngs, pngi)) { - case 8: - for (r = 0; r < height; ++r) { - for (i = 0; i < rowlen; i++) { - row[i] = htons(257 * pngrows[r][i]); - } - efwrite(row, sizeof(uint16_t), rowlen, stdout); - } - break; - case 16: - for (r = 0; r < height; ++r) { - efwrite(pngrows[r], sizeof(uint16_t), rowlen, stdout); - } - break; - default: - die("Invalid bit-depth"); - } - - /* clean up */ - png_destroy_read_struct(&pngs, &pngi, NULL); - - return fshut(stdout, "<stdout>"); -} diff --git a/utils/farbfeld/util.c b/utils/farbfeld/util.c deleted file mode 100644 index 6418bc9..0000000 --- a/utils/farbfeld/util.c +++ /dev/null @@ -1,242 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include <arpa/inet.h> - -#include <errno.h> -#include <limits.h> -#include <stdarg.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/types.h> - -#include "util.h" - -char *argv0; - -static void -verr(const char *fmt, va_list ap) -{ - if (argv0 && strncmp(fmt, "usage", sizeof("usage") - 1)) { - fprintf(stderr, "%s: ", argv0); - } - - vfprintf(stderr, fmt, ap); - - if (fmt[0] && fmt[strlen(fmt) - 1] == ':') { - fputc(' ', stderr); - perror(NULL); - } else { - fputc('\n', stderr); - } -} - -void -warn(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - verr(fmt, ap); - va_end(ap); -} - -void -die(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - verr(fmt, ap); - va_end(ap); - - exit(1); -} - -void -ff_read_header(uint32_t *width, uint32_t *height) -{ - uint32_t hdr[4]; - - efread(hdr, sizeof(*hdr), LEN(hdr), stdin); - - if (memcmp("farbfeld", hdr, sizeof("farbfeld") - 1)) { - die("Invalid magic value"); - } - - *width = ntohl(hdr[2]); - *height = ntohl(hdr[3]); -} - -void -ff_write_header(uint32_t width, uint32_t height) -{ - uint32_t tmp; - - fputs("farbfeld", stdout); - - tmp = htonl(width); - efwrite(&tmp, sizeof(tmp), 1, stdout); - - tmp = htonl(height); - efwrite(&tmp, sizeof(tmp), 1, stdout); -} - -int -parse_mask(const char *s, uint16_t mask[3]) -{ - size_t slen, i; - unsigned int col[3], colfac; - char fmt[] = "%#x%#x%#x"; - - slen = strlen(s); - if (slen != 3 && slen != 6 && slen != 12) { - return 1; - } - - fmt[1] = fmt[4] = fmt[7] = ((slen / 3) + '0'); - if (sscanf(s, fmt, col, col + 1, col + 2) != 3) { - return 1; - } - - colfac = (slen == 3) ? UINT16_MAX / 0xf : - (slen == 6) ? UINT16_MAX / 0xff : - UINT16_MAX / 0xffff; - - for (i = 0; i < 3; i++) { - mask[i] = col[i] * colfac; - } - - return 0; -} - -int -fshut(FILE *fp, const char *fname) -{ - int ret = 0; - - /* fflush() is undefined for input streams by ISO C, - * but not POSIX 2008 if you ignore ISO C overrides. - * Leave it unchecked and rely on the following - * functions to detect errors. - */ - fflush(fp); - - if (ferror(fp) && !ret) { - warn("ferror '%s':", fname); - ret = 1; - } - - if (fclose(fp) && !ret) { - warn("fclose '%s':", fname); - ret = 1; - } - - return ret; -} - -void -efread(void *p, size_t s, size_t n, FILE *f) -{ - if (fread(p, s, n, f) != n) { - if (ferror(f)) { - die("fread:"); - } else { - die("fread: Unexpected end of file"); - } - } -} - -void -efwrite(const void *p, size_t s, size_t n, FILE *f) -{ - if (fwrite(p, s, n, f) != n) { - die("fwrite:"); - } -} - -void * -ereallocarray(void *optr, size_t nmemb, size_t size) -{ - void *p; - - if (!(p = reallocarray(optr, nmemb, size))) { - die("reallocarray: Out of memory"); - } - - return p; -} - -long long -estrtonum(const char *numstr, long long minval, long long maxval) -{ - const char *errstr; - long long ll; - - ll = strtonum(numstr, minval, maxval, &errstr); - if (errstr) { - die("strtonum '%s': %s", numstr, errstr); - } - - return ll; -} - -/* - * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX - * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW - */ -#define MUL_NO_OVERFLOW (1UL << (sizeof(size_t) * 4)) - -void * -reallocarray(void *optr, size_t nmemb, size_t size) -{ - if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && - nmemb > 0 && SIZE_MAX / nmemb < size) { - errno = ENOMEM; - return NULL; - } - return realloc(optr, size * nmemb); -} - -#define INVALID 1 -#define TOOSMALL 2 -#define TOOLARGE 3 - -long long -strtonum(const char *numstr, long long minval, long long maxval, - const char **errstrp) -{ - long long ll = 0; - int error = 0; - char *ep; - struct errval { - const char *errstr; - int err; - } ev[4] = { - { NULL, 0 }, - { "invalid", EINVAL }, - { "too small", ERANGE }, - { "too large", ERANGE }, - }; - - ev[0].err = errno; - errno = 0; - if (minval > maxval) { - error = INVALID; - } else { - ll = strtoll(numstr, &ep, 10); - if (numstr == ep || *ep != '\0') - error = INVALID; - else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval) - error = TOOSMALL; - else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval) - error = TOOLARGE; - } - if (errstrp != NULL) - *errstrp = ev[error].errstr; - errno = ev[error].err; - if (error) - ll = 0; - - return (ll); -} diff --git a/utils/farbfeld/util.h b/utils/farbfeld/util.h deleted file mode 100644 index f6e32c6..0000000 --- a/utils/farbfeld/util.h +++ /dev/null @@ -1,28 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include <stdint.h> -#include <stdio.h> - -#define LEN(x) (sizeof (x) / sizeof *(x)) - -extern char *argv0; - -void warn(const char *, ...); -void die(const char *, ...); - -void ff_read_header(uint32_t *width, uint32_t *height); -void ff_write_header(uint32_t width, uint32_t height); - -int parse_mask(const char *, uint16_t mask[3]); - -int fshut(FILE *, const char *); - -void efread(void *, size_t, size_t, FILE *); -void efwrite(const void *, size_t, size_t, FILE *); - -#undef reallocarray -void *reallocarray(void *, size_t, size_t); -void *ereallocarray(void *optr, size_t nmemb, size_t size); - -#undef strtonum -long long strtonum(const char *, long long, long long, const char **); -long long estrtonum(const char *, long long, long long); 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; -} diff --git a/utils/st-0.9/FAQ b/utils/st-0.9/FAQ deleted file mode 100644 index 6287a27..0000000 --- a/utils/st-0.9/FAQ +++ /dev/null @@ -1,253 +0,0 @@ -## Why does st not handle utmp entries? - -Use the excellent tool of [utmp](https://git.suckless.org/utmp/) for this task. - - -## Some _random program_ complains that st is unknown/not recognised/unsupported/whatever! - -It means that st doesn’t have any terminfo entry on your system. Chances are -you did not `make install`. If you just want to test it without installing it, -you can manually run `tic -sx st.info`. - - -## Nothing works, and nothing is said about an unknown terminal! - -* Some programs just assume they’re running in xterm i.e. they don’t rely on - terminfo. What you see is the current state of the “xterm compliance”. -* Some programs don’t complain about the lacking st description and default to - another terminal. In that case see the question about terminfo. - - -## How do I scroll back up? - -* Using a terminal multiplexer. - * `st -e tmux` using C-b [ - * `st -e screen` using C-a ESC -* Using the excellent tool of [scroll](https://git.suckless.org/scroll/). -* Using the scrollback [patch](https://st.suckless.org/patches/scrollback/). - - -## I would like to have utmp and/or scroll functionality by default - -You can add the absolute path of both programs in your config.h file. You only -have to modify the value of utmp and scroll variables. - - -## Why doesn't the Del key work in some programs? - -Taken from the terminfo manpage: - - If the terminal has a keypad that transmits codes when the keys - are pressed, this information can be given. Note that it is not - possible to handle terminals where the keypad only works in - local (this applies, for example, to the unshifted HP 2621 keys). - If the keypad can be set to transmit or not transmit, give these - codes as smkx and rmkx. Otherwise the keypad is assumed to - always transmit. - -In the st case smkx=E[?1hE= and rmkx=E[?1lE>, so it is mandatory that -applications which want to test against keypad keys send these -sequences. - -But buggy applications (like bash and irssi, for example) don't do this. A fast -solution for them is to use the following command: - - $ printf '\033[?1h\033=' >/dev/tty - -or - $ tput smkx - -In the case of bash, readline is used. Readline has a different note in its -manpage about this issue: - - enable-keypad (Off) - When set to On, readline will try to enable the - application keypad when it is called. Some systems - need this to enable arrow keys. - -Adding this option to your .inputrc will fix the keypad problem for all -applications using readline. - -If you are using zsh, then read the zsh FAQ -<http://zsh.sourceforge.net/FAQ/zshfaq03.html#l25>: - - It should be noted that the O / [ confusion can occur with other keys - such as Home and End. Some systems let you query the key sequences - sent by these keys from the system's terminal database, terminfo. - Unfortunately, the key sequences given there typically apply to the - mode that is not the one zsh uses by default (it's the "application" - mode rather than the "raw" mode). Explaining the use of terminfo is - outside of the scope of this FAQ, but if you wish to use the key - sequences given there you can tell the line editor to turn on - "application" mode when it starts and turn it off when it stops: - - function zle-line-init () { echoti smkx } - function zle-line-finish () { echoti rmkx } - zle -N zle-line-init - zle -N zle-line-finish - -Putting these lines into your .zshrc will fix the problems. - - -## How can I use meta in 8bit mode? - -St supports meta in 8bit mode, but the default terminfo entry doesn't -use this capability. If you want it, you have to use the 'st-meta' value -in TERM. - - -## I cannot compile st in OpenBSD - -OpenBSD lacks librt, despite it being mandatory in POSIX -<http://pubs.opengroup.org/onlinepubs/9699919799/utilities/c99.html#tag_20_11_13>. -If you want to compile st for OpenBSD you have to remove -lrt from config.mk, and -st will compile without any loss of functionality, because all the functions are -included in libc on this platform. - - -## The Backspace Case - -St is emulating the Linux way of handling backspace being delete and delete being -backspace. - -This is an issue that was discussed in suckless mailing list -<https://lists.suckless.org/dev/1404/20697.html>. Here is why some old grumpy -terminal users wants its backspace to be how he feels it: - - Well, I am going to comment why I want to change the behaviour - of this key. When ASCII was defined in 1968, communication - with computers was done using punched cards, or hardcopy - terminals (basically a typewriter machine connected with the - computer using a serial port). ASCII defines DELETE as 7F, - because, in punched-card terms, it means all the holes of the - card punched; it is thus a kind of 'physical delete'. In the - same way, the BACKSPACE key was a non-destructive backspace, - as on a typewriter. So, if you wanted to delete a character, - you had to BACKSPACE and then DELETE. Another use of BACKSPACE - was to type accented characters, for example 'a BACKSPACE `'. - The VT100 had no BACKSPACE key; it was generated using the - CONTROL key as another control character (CONTROL key sets to - 0 b7 b6 b5, so it converts H (code 0x48) into BACKSPACE (code - 0x08)), but it had a DELETE key in a similar position where - the BACKSPACE key is located today on common PC keyboards. - All the terminal emulators emulated the difference between - these keys correctly: the backspace key generated a BACKSPACE - (^H) and delete key generated a DELETE (^?). - - But a problem arose when Linus Torvalds wrote Linux. Unlike - earlier terminals, the Linux virtual terminal (the terminal - emulator integrated in the kernel) returned a DELETE when - backspace was pressed, due to the VT100 having a DELETE key in - the same position. This created a lot of problems (see [1] - and [2]). Since Linux has become the king, a lot of terminal - emulators today generate a DELETE when the backspace key is - pressed in order to avoid problems with Linux. The result is - that the only way of generating a BACKSPACE on these systems - is by using CONTROL + H. (I also think that emacs had an - important point here because the CONTROL + H prefix is used - in emacs in some commands (help commands).) - - From point of view of the kernel, you can change the key - for deleting a previous character with stty erase. When you - connect a real terminal into a machine you describe the type - of terminal, so getty configures the correct value of stty - erase for this terminal. In the case of terminal emulators, - however, you don't have any getty that can set the correct - value of stty erase, so you always get the default value. - For this reason, it is necessary to add 'stty erase ^H' to your - profile if you have changed the value of the backspace key. - Of course, another solution is for st itself to modify the - value of stty erase. I usually have the inverse problem: - when I connect to non-Unix machines, I have to press CONTROL + - h to get a BACKSPACE. The inverse problem occurs when a user - connects to my Unix machines from a different system with a - correct backspace key. - - [1] http://www.ibb.net/~anne/keyboard.html - [2] http://www.tldp.org/HOWTO/Keyboard-and-Console-HOWTO-5.html - - -## But I really want the old grumpy behaviour of my terminal - -Apply [1]. - -[1] https://st.suckless.org/patches/delkey - - -## Why do images not work in st using the w3m image hack? - -w3mimg uses a hack that draws an image on top of the terminal emulator Drawable -window. The hack relies on the terminal to use a single buffer to draw its -contents directly. - -st uses double-buffered drawing so the image is quickly replaced and may show a -short flicker effect. - -Below is a patch example to change st double-buffering to a single Drawable -buffer. - -diff --git a/x.c b/x.c ---- a/x.c -+++ b/x.c -@@ -732,10 +732,6 @@ xresize(int col, int row) - win.tw = col * win.cw; - win.th = row * win.ch; - -- XFreePixmap(xw.dpy, xw.buf); -- xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, -- DefaultDepth(xw.dpy, xw.scr)); -- XftDrawChange(xw.draw, xw.buf); - xclear(0, 0, win.w, win.h); - - /* resize to new width */ -@@ -1148,8 +1144,7 @@ xinit(int cols, int rows) - gcvalues.graphics_exposures = False; - dc.gc = XCreateGC(xw.dpy, parent, GCGraphicsExposures, - &gcvalues); -- xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, -- DefaultDepth(xw.dpy, xw.scr)); -+ xw.buf = xw.win; - XSetForeground(xw.dpy, dc.gc, dc.col[defaultbg].pixel); - XFillRectangle(xw.dpy, xw.buf, dc.gc, 0, 0, win.w, win.h); - -@@ -1632,8 +1627,6 @@ xdrawline(Line line, int x1, int y1, int x2) - void - xfinishdraw(void) - { -- XCopyArea(xw.dpy, xw.buf, xw.win, dc.gc, 0, 0, win.w, -- win.h, 0, 0); - XSetForeground(xw.dpy, dc.gc, - dc.col[IS_SET(MODE_REVERSE)? - defaultfg : defaultbg].pixel); - - -## BadLength X error in Xft when trying to render emoji - -Xft makes st crash when rendering color emojis with the following error: - -"X Error of failed request: BadLength (poly request too large or internal Xlib length error)" - Major opcode of failed request: 139 (RENDER) - Minor opcode of failed request: 20 (RenderAddGlyphs) - Serial number of failed request: 1595 - Current serial number in output stream: 1818" - -This is a known bug in Xft (not st) which happens on some platforms and -combination of particular fonts and fontconfig settings. - -See also: -https://gitlab.freedesktop.org/xorg/lib/libxft/issues/6 -https://bugs.freedesktop.org/show_bug.cgi?id=107534 -https://bugzilla.redhat.com/show_bug.cgi?id=1498269 - -The solution is to remove color emoji fonts or disable this in the fontconfig -XML configuration. As an ugly workaround (which may work only on newer -fontconfig versions (FC_COLOR)), the following code can be used to mask color -fonts: - - FcPatternAddBool(fcpattern, FC_COLOR, FcFalse); - -Please don't bother reporting this bug to st, but notify the upstream Xft -developers about fixing this bug. - -As of 2022-09-05 this now seems to be finally fixed in libXft 2.3.5: -https://gitlab.freedesktop.org/xorg/lib/libxft/-/blob/libXft-2.3.5/NEWS diff --git a/utils/st-0.9/LEGACY b/utils/st-0.9/LEGACY deleted file mode 100644 index bf28b1e..0000000 --- a/utils/st-0.9/LEGACY +++ /dev/null @@ -1,17 +0,0 @@ -A STATEMENT ON LEGACY SUPPORT - -In the terminal world there is much cruft that comes from old and unsup‐ -ported terminals that inherit incompatible modes and escape sequences -which noone is able to know, except when he/she comes from that time and -developed a graphical vt100 emulator at that time. - -One goal of st is to only support what is really needed. When you en‐ -counter a sequence which you really need, implement it. But while you -are at it, do not add the other cruft you might encounter while sneek‐ -ing at other terminal emulators. History has bloated them and there is -no real evidence that most of the sequences are used today. - - -Christoph Lohmann <20h@r-36.net> -2012-09-13T07:00:36.081271045+02:00 - diff --git a/utils/st-0.9/LICENSE b/utils/st-0.9/LICENSE deleted file mode 100644 index 3cbf420..0000000 --- a/utils/st-0.9/LICENSE +++ /dev/null @@ -1,34 +0,0 @@ -MIT/X Consortium License - -© 2014-2022 Hiltjo Posthuma <hiltjo at codemadness dot org> -© 2018 Devin J. Pohly <djpohly at gmail dot com> -© 2014-2017 Quentin Rameau <quinq at fifth dot space> -© 2009-2012 Aurélien APTEL <aurelien dot aptel at gmail dot com> -© 2008-2017 Anselm R Garbe <garbeam at gmail dot com> -© 2012-2017 Roberto E. Vargas Caballero <k0ga at shike2 dot com> -© 2012-2016 Christoph Lohmann <20h at r-36 dot net> -© 2013 Eon S. Jeon <esjeon at hyunmu dot am> -© 2013 Alexander Sedov <alex0player at gmail dot com> -© 2013 Mark Edgar <medgar123 at gmail dot com> -© 2013-2014 Eric Pruitt <eric.pruitt at gmail dot com> -© 2013 Michael Forney <mforney at mforney dot org> -© 2013-2014 Markus Teich <markus dot teich at stusta dot mhn dot de> -© 2014-2015 Laslo Hunhold <dev at frign dot de> - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the "Software"), -to deal in the Software without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/utils/st-0.9/Makefile b/utils/st-0.9/Makefile deleted file mode 100644 index 470ac86..0000000 --- a/utils/st-0.9/Makefile +++ /dev/null @@ -1,57 +0,0 @@ -# st - simple terminal -# See LICENSE file for copyright and license details. -.POSIX: - -include config.mk - -SRC = st.c x.c -OBJ = $(SRC:.c=.o) - -all: options st - -options: - @echo st build options: - @echo "CFLAGS = $(STCFLAGS)" - @echo "LDFLAGS = $(STLDFLAGS)" - @echo "CC = $(CC)" - -config.h: - cp config.def.h config.h - -.c.o: - $(CC) $(STCFLAGS) -c $< - -st.o: config.h st.h win.h -x.o: arg.h config.h st.h win.h - -$(OBJ): config.h config.mk - -st: $(OBJ) - $(CC) -o $@ $(OBJ) $(STLDFLAGS) - -clean: - rm -f st $(OBJ) st-$(VERSION).tar.gz - -dist: clean - mkdir -p st-$(VERSION) - cp -R FAQ LEGACY TODO LICENSE Makefile README config.mk\ - config.def.h st.info st.1 arg.h st.h win.h $(SRC)\ - st-$(VERSION) - tar -cf - st-$(VERSION) | gzip > st-$(VERSION).tar.gz - rm -rf st-$(VERSION) - -install: st - mkdir -p $(DESTDIR)$(PREFIX)/bin - cp -f st $(DESTDIR)$(PREFIX)/bin - chmod 755 $(DESTDIR)$(PREFIX)/bin/st - mkdir -p $(DESTDIR)$(MANPREFIX)/man1 - sed "s/VERSION/$(VERSION)/g" < st.1 > $(DESTDIR)$(MANPREFIX)/man1/st.1 - chmod 644 $(DESTDIR)$(MANPREFIX)/man1/st.1 - tic -sx st.info - @echo Please see the README file regarding the terminfo entry of st. - -uninstall: - rm -f $(DESTDIR)$(PREFIX)/bin/st - rm -f $(DESTDIR)$(MANPREFIX)/man1/st.1 - -.PHONY: all options clean dist install uninstall diff --git a/utils/st-0.9/README b/utils/st-0.9/README deleted file mode 100644 index 6a846ed..0000000 --- a/utils/st-0.9/README +++ /dev/null @@ -1,34 +0,0 @@ -st - simple terminal --------------------- -st is a simple terminal emulator for X which sucks less. - - -Requirements ------------- -In order to build st you need the Xlib header files. - - -Installation ------------- -Edit config.mk to match your local setup (st is installed into -the /usr/local namespace by default). - -Afterwards enter the following command to build and install st (if -necessary as root): - - make clean install - - -Running st ----------- -If you did not install st with make clean install, you must compile -the st terminfo entry with the following command: - - tic -sx st.info - -See the man page for additional details. - -Credits -------- -Based on Aurélien APTEL <aurelien dot aptel at gmail dot com> bt source code. - diff --git a/utils/st-0.9/TODO b/utils/st-0.9/TODO deleted file mode 100644 index 5f74cd5..0000000 --- a/utils/st-0.9/TODO +++ /dev/null @@ -1,28 +0,0 @@ -vt emulation ------------- - -* double-height support - -code & interface ----------------- - -* add a simple way to do multiplexing - -drawing -------- -* add diacritics support to xdraws() - * switch to a suckless font drawing library -* make the font cache simpler -* add better support for brightening of the upper colors - -bugs ----- - -* fix shift up/down (shift selection in emacs) -* remove DEC test sequence when appropriate - -misc ----- - - $ grep -nE 'XXX|TODO' st.c - diff --git a/utils/st-0.9/arg.h b/utils/st-0.9/arg.h deleted file mode 100644 index a22e019..0000000 --- a/utils/st-0.9/arg.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copy me if you can. - * by 20h - */ - -#ifndef ARG_H__ -#define ARG_H__ - -extern char *argv0; - -/* use main(int argc, char *argv[]) */ -#define ARGBEGIN for (argv0 = *argv, argv++, argc--;\ - argv[0] && argv[0][0] == '-'\ - && argv[0][1];\ - argc--, argv++) {\ - char argc_;\ - char **argv_;\ - int brk_;\ - if (argv[0][1] == '-' && argv[0][2] == '\0') {\ - argv++;\ - argc--;\ - break;\ - }\ - int i_;\ - for (i_ = 1, brk_ = 0, argv_ = argv;\ - argv[0][i_] && !brk_;\ - i_++) {\ - if (argv_ != argv)\ - break;\ - argc_ = argv[0][i_];\ - switch (argc_) - -#define ARGEND }\ - } - -#define ARGC() argc_ - -#define EARGF(x) ((argv[0][i_+1] == '\0' && argv[1] == NULL)?\ - ((x), abort(), (char *)0) :\ - (brk_ = 1, (argv[0][i_+1] != '\0')?\ - (&argv[0][i_+1]) :\ - (argc--, argv++, argv[0]))) - -#define ARGF() ((argv[0][i_+1] == '\0' && argv[1] == NULL)?\ - (char *)0 :\ - (brk_ = 1, (argv[0][i_+1] != '\0')?\ - (&argv[0][i_+1]) :\ - (argc--, argv++, argv[0]))) - -#endif diff --git a/utils/st-0.9/config.def.h b/utils/st-0.9/config.def.h deleted file mode 100644 index 279890f..0000000 --- a/utils/st-0.9/config.def.h +++ /dev/null @@ -1,479 +0,0 @@ -/* See LICENSE file for copyright and license details. */ - -/* - * appearance - * - * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html - */ -static char *font = "Liberation Mono:pixelsize=12:antialias=true:autohint=true"; -static int borderpx = 2; - -/* - * What program is execed by st depends of these precedence rules: - * 1: program passed with -e - * 2: scroll and/or utmp - * 3: SHELL environment variable - * 4: value of shell in /etc/passwd - * 5: value of shell in config.h - */ -static char *shell = "/bin/sh"; -char *utmp = NULL; -/* scroll program: to enable use a string like "scroll" */ -char *scroll = NULL; -char *stty_args = "stty raw pass8 nl -echo -iexten -cstopb 38400"; - -/* identification sequence returned in DA and DECID */ -char *vtiden = "\033[?6c"; - -/* Kerning / character bounding-box multipliers */ -static float cwscale = 1.0; -static float chscale = 1.0; - -/* - * word delimiter string - * - * More advanced example: L" `'\"()[]{}" - */ -wchar_t *worddelimiters = L" "; - -/* selection timeouts (in milliseconds) */ -static unsigned int doubleclicktimeout = 300; -static unsigned int tripleclicktimeout = 600; - -/* alt screens */ -int allowaltscreen = 1; - -/* allow certain non-interactive (insecure) window operations such as: - setting the clipboard text */ -int allowwindowops = 0; - -/* - * draw latency range in ms - from new content/keypress/etc until drawing. - * within this range, st draws when content stops arriving (idle). mostly it's - * near minlatency, but it waits longer for slow updates to avoid partial draw. - * low minlatency will tear/flicker more, as it can "detect" idle too early. - */ -static double minlatency = 8; -static double maxlatency = 33; - -/* - * blinking timeout (set to 0 to disable blinking) for the terminal blinking - * attribute. - */ -static unsigned int blinktimeout = 800; - -/* - * thickness of underline and bar cursors - */ -static unsigned int cursorthickness = 2; - -/* - * bell volume. It must be a value between -100 and 100. Use 0 for disabling - * it - */ -static int bellvolume = 0; - -/* default TERM value */ -char *termname = "st-256color"; - -/* - * spaces per tab - * - * When you are changing this value, don't forget to adapt the »it« value in - * the st.info and appropriately install the st.info in the environment where - * you use this st version. - * - * it#$tabspaces, - * - * Secondly make sure your kernel is not expanding tabs. When running `stty - * -a` »tab0« should appear. You can tell the terminal to not expand tabs by - * running following command: - * - * stty tabs - */ -unsigned int tabspaces = 8; - -/* bg opacity */ -float alpha = 0.8; - -/* Terminal colors (16 first used in escape sequence) */ -static const char *colorname[] = { - /* 8 normal colors */ - "black", - "red3", - "green3", - "yellow3", - "blue2", - "magenta3", - "cyan3", - "gray90", - - /* 8 bright colors */ - "gray50", - "red", - "green", - "yellow", - "#5c5cff", - "magenta", - "cyan", - "white", - - [255] = 0, - - /* more colors can be added after 255 to use with DefaultXX */ - "#cccccc", - "#555555", - "gray90", /* default foreground colour */ - "black", /* default background colour */ -}; - - -/* - * Default colors (colorname index) - * foreground, background, cursor, reverse cursor - */ -unsigned int defaultfg = 258; -unsigned int defaultbg = 259; -unsigned int defaultcs = 256; -static unsigned int defaultrcs = 257; - -/* - * Default shape of cursor - * 2: Block ("█") - * 4: Underline ("_") - * 6: Bar ("|") - * 7: Snowman ("☃") - */ -static unsigned int cursorshape = 2; - -/* - * Default columns and rows numbers - */ - -static unsigned int cols = 80; -static unsigned int rows = 24; - -/* - * Default colour and shape of the mouse cursor - */ -static unsigned int mouseshape = XC_xterm; -static unsigned int mousefg = 7; -static unsigned int mousebg = 0; - -/* - * Color used to display font attributes when fontconfig selected a font which - * doesn't match the ones requested. - */ -static unsigned int defaultattr = 11; - -/* - * Force mouse select/shortcuts while mask is active (when MODE_MOUSE is set). - * Note that if you want to use ShiftMask with selmasks, set this to an other - * modifier, set to 0 to not use it. - */ -static uint forcemousemod = ShiftMask; - -/* - * Internal mouse shortcuts. - * Beware that overloading Button1 will disable the selection. - */ -static MouseShortcut mshortcuts[] = { - /* mask button function argument release */ - { XK_ANY_MOD, Button2, selpaste, {.i = 0}, 1 }, - { ShiftMask, Button4, ttysend, {.s = "\033[5;2~"} }, - { XK_ANY_MOD, Button4, ttysend, {.s = "\031"} }, - { ShiftMask, Button5, ttysend, {.s = "\033[6;2~"} }, - { XK_ANY_MOD, Button5, ttysend, {.s = "\005"} }, -}; - -/* Internal keyboard shortcuts. */ -#define MODKEY Mod1Mask -#define TERMMOD (ControlMask|ShiftMask) - -static Shortcut shortcuts[] = { - /* mask keysym function argument */ - { XK_ANY_MOD, XK_Break, sendbreak, {.i = 0} }, - { ControlMask, XK_Print, toggleprinter, {.i = 0} }, - { ShiftMask, XK_Print, printscreen, {.i = 0} }, - { XK_ANY_MOD, XK_Print, printsel, {.i = 0} }, - { TERMMOD, XK_Prior, zoom, {.f = +1} }, - { TERMMOD, XK_Next, zoom, {.f = -1} }, - { TERMMOD, XK_Home, zoomreset, {.f = 0} }, - { TERMMOD, XK_C, clipcopy, {.i = 0} }, - { TERMMOD, XK_V, clippaste, {.i = 0} }, - { TERMMOD, XK_Y, selpaste, {.i = 0} }, - { ShiftMask, XK_Insert, selpaste, {.i = 0} }, - { TERMMOD, XK_Num_Lock, numlock, {.i = 0} }, - { ShiftMask, XK_Page_Up, kscrollup, {.i = -1} }, - { ShiftMask, XK_Page_Down, kscrolldown, {.i = -1} }, -}; - -/* - * Special keys (change & recompile st.info accordingly) - * - * Mask value: - * * Use XK_ANY_MOD to match the key no matter modifiers state - * * Use XK_NO_MOD to match the key alone (no modifiers) - * appkey value: - * * 0: no value - * * > 0: keypad application mode enabled - * * = 2: term.numlock = 1 - * * < 0: keypad application mode disabled - * appcursor value: - * * 0: no value - * * > 0: cursor application mode enabled - * * < 0: cursor application mode disabled - * - * Be careful with the order of the definitions because st searches in - * this table sequentially, so any XK_ANY_MOD must be in the last - * position for a key. - */ - -/* - * If you want keys other than the X11 function keys (0xFD00 - 0xFFFF) - * to be mapped below, add them to this array. - */ -static KeySym mappedkeys[] = { -1 }; - -/* - * State bits to ignore when matching key or button events. By default, - * numlock (Mod2Mask) and keyboard layout (XK_SWITCH_MOD) are ignored. - */ -static uint ignoremod = Mod2Mask|XK_SWITCH_MOD; - -/* - * This is the huge key array which defines all compatibility to the Linux - * world. Please decide about changes wisely. - */ -static Key key[] = { - /* keysym mask string appkey appcursor */ - { XK_KP_Home, ShiftMask, "\033[2J", 0, -1}, - { XK_KP_Home, ShiftMask, "\033[1;2H", 0, +1}, - { XK_KP_Home, XK_ANY_MOD, "\033[H", 0, -1}, - { XK_KP_Home, XK_ANY_MOD, "\033[1~", 0, +1}, - { XK_KP_Up, XK_ANY_MOD, "\033Ox", +1, 0}, - { XK_KP_Up, XK_ANY_MOD, "\033[A", 0, -1}, - { XK_KP_Up, XK_ANY_MOD, "\033OA", 0, +1}, - { XK_KP_Down, XK_ANY_MOD, "\033Or", +1, 0}, - { XK_KP_Down, XK_ANY_MOD, "\033[B", 0, -1}, - { XK_KP_Down, XK_ANY_MOD, "\033OB", 0, +1}, - { XK_KP_Left, XK_ANY_MOD, "\033Ot", +1, 0}, - { XK_KP_Left, XK_ANY_MOD, "\033[D", 0, -1}, - { XK_KP_Left, XK_ANY_MOD, "\033OD", 0, +1}, - { XK_KP_Right, XK_ANY_MOD, "\033Ov", +1, 0}, - { XK_KP_Right, XK_ANY_MOD, "\033[C", 0, -1}, - { XK_KP_Right, XK_ANY_MOD, "\033OC", 0, +1}, - { XK_KP_Prior, ShiftMask, "\033[5;2~", 0, 0}, - { XK_KP_Prior, XK_ANY_MOD, "\033[5~", 0, 0}, - { XK_KP_Begin, XK_ANY_MOD, "\033[E", 0, 0}, - { XK_KP_End, ControlMask, "\033[J", -1, 0}, - { XK_KP_End, ControlMask, "\033[1;5F", +1, 0}, - { XK_KP_End, ShiftMask, "\033[K", -1, 0}, - { XK_KP_End, ShiftMask, "\033[1;2F", +1, 0}, - { XK_KP_End, XK_ANY_MOD, "\033[4~", 0, 0}, - { XK_KP_Next, ShiftMask, "\033[6;2~", 0, 0}, - { XK_KP_Next, XK_ANY_MOD, "\033[6~", 0, 0}, - { XK_KP_Insert, ShiftMask, "\033[2;2~", +1, 0}, - { XK_KP_Insert, ShiftMask, "\033[4l", -1, 0}, - { XK_KP_Insert, ControlMask, "\033[L", -1, 0}, - { XK_KP_Insert, ControlMask, "\033[2;5~", +1, 0}, - { XK_KP_Insert, XK_ANY_MOD, "\033[4h", -1, 0}, - { XK_KP_Insert, XK_ANY_MOD, "\033[2~", +1, 0}, - { XK_KP_Delete, ControlMask, "\033[M", -1, 0}, - { XK_KP_Delete, ControlMask, "\033[3;5~", +1, 0}, - { XK_KP_Delete, ShiftMask, "\033[2K", -1, 0}, - { XK_KP_Delete, ShiftMask, "\033[3;2~", +1, 0}, - { XK_KP_Delete, XK_ANY_MOD, "\033[P", -1, 0}, - { XK_KP_Delete, XK_ANY_MOD, "\033[3~", +1, 0}, - { XK_KP_Multiply, XK_ANY_MOD, "\033Oj", +2, 0}, - { XK_KP_Add, XK_ANY_MOD, "\033Ok", +2, 0}, - { XK_KP_Enter, XK_ANY_MOD, "\033OM", +2, 0}, - { XK_KP_Enter, XK_ANY_MOD, "\r", -1, 0}, - { XK_KP_Subtract, XK_ANY_MOD, "\033Om", +2, 0}, - { XK_KP_Decimal, XK_ANY_MOD, "\033On", +2, 0}, - { XK_KP_Divide, XK_ANY_MOD, "\033Oo", +2, 0}, - { XK_KP_0, XK_ANY_MOD, "\033Op", +2, 0}, - { XK_KP_1, XK_ANY_MOD, "\033Oq", +2, 0}, - { XK_KP_2, XK_ANY_MOD, "\033Or", +2, 0}, - { XK_KP_3, XK_ANY_MOD, "\033Os", +2, 0}, - { XK_KP_4, XK_ANY_MOD, "\033Ot", +2, 0}, - { XK_KP_5, XK_ANY_MOD, "\033Ou", +2, 0}, - { XK_KP_6, XK_ANY_MOD, "\033Ov", +2, 0}, - { XK_KP_7, XK_ANY_MOD, "\033Ow", +2, 0}, - { XK_KP_8, XK_ANY_MOD, "\033Ox", +2, 0}, - { XK_KP_9, XK_ANY_MOD, "\033Oy", +2, 0}, - { XK_Up, ShiftMask, "\033[1;2A", 0, 0}, - { XK_Up, Mod1Mask, "\033[1;3A", 0, 0}, - { XK_Up, ShiftMask|Mod1Mask,"\033[1;4A", 0, 0}, - { XK_Up, ControlMask, "\033[1;5A", 0, 0}, - { XK_Up, ShiftMask|ControlMask,"\033[1;6A", 0, 0}, - { XK_Up, ControlMask|Mod1Mask,"\033[1;7A", 0, 0}, - { XK_Up,ShiftMask|ControlMask|Mod1Mask,"\033[1;8A", 0, 0}, - { XK_Up, XK_ANY_MOD, "\033[A", 0, -1}, - { XK_Up, XK_ANY_MOD, "\033OA", 0, +1}, - { XK_Down, ShiftMask, "\033[1;2B", 0, 0}, - { XK_Down, Mod1Mask, "\033[1;3B", 0, 0}, - { XK_Down, ShiftMask|Mod1Mask,"\033[1;4B", 0, 0}, - { XK_Down, ControlMask, "\033[1;5B", 0, 0}, - { XK_Down, ShiftMask|ControlMask,"\033[1;6B", 0, 0}, - { XK_Down, ControlMask|Mod1Mask,"\033[1;7B", 0, 0}, - { XK_Down,ShiftMask|ControlMask|Mod1Mask,"\033[1;8B",0, 0}, - { XK_Down, XK_ANY_MOD, "\033[B", 0, -1}, - { XK_Down, XK_ANY_MOD, "\033OB", 0, +1}, - { XK_Left, ShiftMask, "\033[1;2D", 0, 0}, - { XK_Left, Mod1Mask, "\033[1;3D", 0, 0}, - { XK_Left, ShiftMask|Mod1Mask,"\033[1;4D", 0, 0}, - { XK_Left, ControlMask, "\033[1;5D", 0, 0}, - { XK_Left, ShiftMask|ControlMask,"\033[1;6D", 0, 0}, - { XK_Left, ControlMask|Mod1Mask,"\033[1;7D", 0, 0}, - { XK_Left,ShiftMask|ControlMask|Mod1Mask,"\033[1;8D",0, 0}, - { XK_Left, XK_ANY_MOD, "\033[D", 0, -1}, - { XK_Left, XK_ANY_MOD, "\033OD", 0, +1}, - { XK_Right, ShiftMask, "\033[1;2C", 0, 0}, - { XK_Right, Mod1Mask, "\033[1;3C", 0, 0}, - { XK_Right, ShiftMask|Mod1Mask,"\033[1;4C", 0, 0}, - { XK_Right, ControlMask, "\033[1;5C", 0, 0}, - { XK_Right, ShiftMask|ControlMask,"\033[1;6C", 0, 0}, - { XK_Right, ControlMask|Mod1Mask,"\033[1;7C", 0, 0}, - { XK_Right,ShiftMask|ControlMask|Mod1Mask,"\033[1;8C",0, 0}, - { XK_Right, XK_ANY_MOD, "\033[C", 0, -1}, - { XK_Right, XK_ANY_MOD, "\033OC", 0, +1}, - { XK_ISO_Left_Tab, ShiftMask, "\033[Z", 0, 0}, - { XK_Return, Mod1Mask, "\033\r", 0, 0}, - { XK_Return, XK_ANY_MOD, "\r", 0, 0}, - { XK_Insert, ShiftMask, "\033[4l", -1, 0}, - { XK_Insert, ShiftMask, "\033[2;2~", +1, 0}, - { XK_Insert, ControlMask, "\033[L", -1, 0}, - { XK_Insert, ControlMask, "\033[2;5~", +1, 0}, - { XK_Insert, XK_ANY_MOD, "\033[4h", -1, 0}, - { XK_Insert, XK_ANY_MOD, "\033[2~", +1, 0}, - { XK_Delete, ControlMask, "\033[M", -1, 0}, - { XK_Delete, ControlMask, "\033[3;5~", +1, 0}, - { XK_Delete, ShiftMask, "\033[2K", -1, 0}, - { XK_Delete, ShiftMask, "\033[3;2~", +1, 0}, - { XK_Delete, XK_ANY_MOD, "\033[P", -1, 0}, - { XK_Delete, XK_ANY_MOD, "\033[3~", +1, 0}, - { XK_BackSpace, XK_NO_MOD, "\177", 0, 0}, - { XK_BackSpace, Mod1Mask, "\033\177", 0, 0}, - { XK_Home, ShiftMask, "\033[2J", 0, -1}, - { XK_Home, ShiftMask, "\033[1;2H", 0, +1}, - { XK_Home, XK_ANY_MOD, "\033[H", 0, -1}, - { XK_Home, XK_ANY_MOD, "\033[1~", 0, +1}, - { XK_End, ControlMask, "\033[J", -1, 0}, - { XK_End, ControlMask, "\033[1;5F", +1, 0}, - { XK_End, ShiftMask, "\033[K", -1, 0}, - { XK_End, ShiftMask, "\033[1;2F", +1, 0}, - { XK_End, XK_ANY_MOD, "\033[4~", 0, 0}, - { XK_Prior, ControlMask, "\033[5;5~", 0, 0}, - { XK_Prior, ShiftMask, "\033[5;2~", 0, 0}, - { XK_Prior, XK_ANY_MOD, "\033[5~", 0, 0}, - { XK_Next, ControlMask, "\033[6;5~", 0, 0}, - { XK_Next, ShiftMask, "\033[6;2~", 0, 0}, - { XK_Next, XK_ANY_MOD, "\033[6~", 0, 0}, - { XK_F1, XK_NO_MOD, "\033OP" , 0, 0}, - { XK_F1, /* F13 */ ShiftMask, "\033[1;2P", 0, 0}, - { XK_F1, /* F25 */ ControlMask, "\033[1;5P", 0, 0}, - { XK_F1, /* F37 */ Mod4Mask, "\033[1;6P", 0, 0}, - { XK_F1, /* F49 */ Mod1Mask, "\033[1;3P", 0, 0}, - { XK_F1, /* F61 */ Mod3Mask, "\033[1;4P", 0, 0}, - { XK_F2, XK_NO_MOD, "\033OQ" , 0, 0}, - { XK_F2, /* F14 */ ShiftMask, "\033[1;2Q", 0, 0}, - { XK_F2, /* F26 */ ControlMask, "\033[1;5Q", 0, 0}, - { XK_F2, /* F38 */ Mod4Mask, "\033[1;6Q", 0, 0}, - { XK_F2, /* F50 */ Mod1Mask, "\033[1;3Q", 0, 0}, - { XK_F2, /* F62 */ Mod3Mask, "\033[1;4Q", 0, 0}, - { XK_F3, XK_NO_MOD, "\033OR" , 0, 0}, - { XK_F3, /* F15 */ ShiftMask, "\033[1;2R", 0, 0}, - { XK_F3, /* F27 */ ControlMask, "\033[1;5R", 0, 0}, - { XK_F3, /* F39 */ Mod4Mask, "\033[1;6R", 0, 0}, - { XK_F3, /* F51 */ Mod1Mask, "\033[1;3R", 0, 0}, - { XK_F3, /* F63 */ Mod3Mask, "\033[1;4R", 0, 0}, - { XK_F4, XK_NO_MOD, "\033OS" , 0, 0}, - { XK_F4, /* F16 */ ShiftMask, "\033[1;2S", 0, 0}, - { XK_F4, /* F28 */ ControlMask, "\033[1;5S", 0, 0}, - { XK_F4, /* F40 */ Mod4Mask, "\033[1;6S", 0, 0}, - { XK_F4, /* F52 */ Mod1Mask, "\033[1;3S", 0, 0}, - { XK_F5, XK_NO_MOD, "\033[15~", 0, 0}, - { XK_F5, /* F17 */ ShiftMask, "\033[15;2~", 0, 0}, - { XK_F5, /* F29 */ ControlMask, "\033[15;5~", 0, 0}, - { XK_F5, /* F41 */ Mod4Mask, "\033[15;6~", 0, 0}, - { XK_F5, /* F53 */ Mod1Mask, "\033[15;3~", 0, 0}, - { XK_F6, XK_NO_MOD, "\033[17~", 0, 0}, - { XK_F6, /* F18 */ ShiftMask, "\033[17;2~", 0, 0}, - { XK_F6, /* F30 */ ControlMask, "\033[17;5~", 0, 0}, - { XK_F6, /* F42 */ Mod4Mask, "\033[17;6~", 0, 0}, - { XK_F6, /* F54 */ Mod1Mask, "\033[17;3~", 0, 0}, - { XK_F7, XK_NO_MOD, "\033[18~", 0, 0}, - { XK_F7, /* F19 */ ShiftMask, "\033[18;2~", 0, 0}, - { XK_F7, /* F31 */ ControlMask, "\033[18;5~", 0, 0}, - { XK_F7, /* F43 */ Mod4Mask, "\033[18;6~", 0, 0}, - { XK_F7, /* F55 */ Mod1Mask, "\033[18;3~", 0, 0}, - { XK_F8, XK_NO_MOD, "\033[19~", 0, 0}, - { XK_F8, /* F20 */ ShiftMask, "\033[19;2~", 0, 0}, - { XK_F8, /* F32 */ ControlMask, "\033[19;5~", 0, 0}, - { XK_F8, /* F44 */ Mod4Mask, "\033[19;6~", 0, 0}, - { XK_F8, /* F56 */ Mod1Mask, "\033[19;3~", 0, 0}, - { XK_F9, XK_NO_MOD, "\033[20~", 0, 0}, - { XK_F9, /* F21 */ ShiftMask, "\033[20;2~", 0, 0}, - { XK_F9, /* F33 */ ControlMask, "\033[20;5~", 0, 0}, - { XK_F9, /* F45 */ Mod4Mask, "\033[20;6~", 0, 0}, - { XK_F9, /* F57 */ Mod1Mask, "\033[20;3~", 0, 0}, - { XK_F10, XK_NO_MOD, "\033[21~", 0, 0}, - { XK_F10, /* F22 */ ShiftMask, "\033[21;2~", 0, 0}, - { XK_F10, /* F34 */ ControlMask, "\033[21;5~", 0, 0}, - { XK_F10, /* F46 */ Mod4Mask, "\033[21;6~", 0, 0}, - { XK_F10, /* F58 */ Mod1Mask, "\033[21;3~", 0, 0}, - { XK_F11, XK_NO_MOD, "\033[23~", 0, 0}, - { XK_F11, /* F23 */ ShiftMask, "\033[23;2~", 0, 0}, - { XK_F11, /* F35 */ ControlMask, "\033[23;5~", 0, 0}, - { XK_F11, /* F47 */ Mod4Mask, "\033[23;6~", 0, 0}, - { XK_F11, /* F59 */ Mod1Mask, "\033[23;3~", 0, 0}, - { XK_F12, XK_NO_MOD, "\033[24~", 0, 0}, - { XK_F12, /* F24 */ ShiftMask, "\033[24;2~", 0, 0}, - { XK_F12, /* F36 */ ControlMask, "\033[24;5~", 0, 0}, - { XK_F12, /* F48 */ Mod4Mask, "\033[24;6~", 0, 0}, - { XK_F12, /* F60 */ Mod1Mask, "\033[24;3~", 0, 0}, - { XK_F13, XK_NO_MOD, "\033[1;2P", 0, 0}, - { XK_F14, XK_NO_MOD, "\033[1;2Q", 0, 0}, - { XK_F15, XK_NO_MOD, "\033[1;2R", 0, 0}, - { XK_F16, XK_NO_MOD, "\033[1;2S", 0, 0}, - { XK_F17, XK_NO_MOD, "\033[15;2~", 0, 0}, - { XK_F18, XK_NO_MOD, "\033[17;2~", 0, 0}, - { XK_F19, XK_NO_MOD, "\033[18;2~", 0, 0}, - { XK_F20, XK_NO_MOD, "\033[19;2~", 0, 0}, - { XK_F21, XK_NO_MOD, "\033[20;2~", 0, 0}, - { XK_F22, XK_NO_MOD, "\033[21;2~", 0, 0}, - { XK_F23, XK_NO_MOD, "\033[23;2~", 0, 0}, - { XK_F24, XK_NO_MOD, "\033[24;2~", 0, 0}, - { XK_F25, XK_NO_MOD, "\033[1;5P", 0, 0}, - { XK_F26, XK_NO_MOD, "\033[1;5Q", 0, 0}, - { XK_F27, XK_NO_MOD, "\033[1;5R", 0, 0}, - { XK_F28, XK_NO_MOD, "\033[1;5S", 0, 0}, - { XK_F29, XK_NO_MOD, "\033[15;5~", 0, 0}, - { XK_F30, XK_NO_MOD, "\033[17;5~", 0, 0}, - { XK_F31, XK_NO_MOD, "\033[18;5~", 0, 0}, - { XK_F32, XK_NO_MOD, "\033[19;5~", 0, 0}, - { XK_F33, XK_NO_MOD, "\033[20;5~", 0, 0}, - { XK_F34, XK_NO_MOD, "\033[21;5~", 0, 0}, - { XK_F35, XK_NO_MOD, "\033[23;5~", 0, 0}, -}; - -/* - * Selection types' masks. - * Use the same masks as usual. - * Button1Mask is always unset, to make masks match between ButtonPress. - * ButtonRelease and MotionNotify. - * If no match is found, regular selection is used. - */ -static uint selmasks[] = { - [SEL_RECTANGULAR] = Mod1Mask, -}; - -/* - * Printable characters in ASCII, used to estimate the advance width - * of single wide characters. - */ -static char ascii_printable[] = - " !\"#$%&'()*+,-./0123456789:;<=>?" - "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" - "`abcdefghijklmnopqrstuvwxyz{|}~"; diff --git a/utils/st-0.9/config.h b/utils/st-0.9/config.h deleted file mode 100644 index 8914d0e..0000000 --- a/utils/st-0.9/config.h +++ /dev/null @@ -1,445 +0,0 @@ -#include "../../colors.h" -/* See LICENSE file for copyright and license details. */ - -/* - * appearance - * - * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html - */ -static char *font = "Source Code Pro:pixelsize=12:antialias=true:autohint=true"; -static int borderpx = 2; - -/* - * What program is execed by st depends of these precedence rules: - * 1: program passed with -e - * 2: scroll and/or utmp - * 3: SHELL environment variable - * 4: value of shell in /etc/passwd - * 5: value of shell in config.h - */ -static char *shell = "/bin/sh"; -char *utmp = NULL; -/* scroll program: to enable use a string like "scroll" */ -char *scroll = NULL; -char *stty_args = "stty raw pass8 nl -echo -iexten -cstopb 38400"; - -/* identification sequence returned in DA and DECID */ -char *vtiden = "\033[?6c"; - -/* Kerning / character bounding-box multipliers */ -static float cwscale = 1.0; -static float chscale = 1.0; - -/* - * word delimiter string - * - * More advanced example: L" `'\"()[]{}" - */ -wchar_t *worddelimiters = L" "; - -/* selection timeouts (in milliseconds) */ -static unsigned int doubleclicktimeout = 300; -static unsigned int tripleclicktimeout = 600; - -/* alt screens */ -int allowaltscreen = 1; - -/* allow certain non-interactive (insecure) window operations such as: - setting the clipboard text */ -int allowwindowops = 0; - -/* - * draw latency range in ms - from new content/keypress/etc until drawing. - * within this range, st draws when content stops arriving (idle). mostly it's - * near minlatency, but it waits longer for slow updates to avoid partial draw. - * low minlatency will tear/flicker more, as it can "detect" idle too early. - */ -static double minlatency = 8; -static double maxlatency = 33; - -/* - * blinking timeout (set to 0 to disable blinking) for the terminal blinking - * attribute. - */ -static unsigned int blinktimeout = 800; - -/* - * thickness of underline and bar cursors - */ -static unsigned int cursorthickness = 2; - -/* - * bell volume. It must be a value between -100 and 100. Use 0 for disabling - * it - */ -static int bellvolume = 0; - -/* default TERM value */ -char *termname = "st-256color"; - -/* - * spaces per tab - * - * When you are changing this value, don't forget to adapt the »it« value in - * the st.info and appropriately install the st.info in the environment where - * you use this st version. - * - * it#$tabspaces, - * - * Secondly make sure your kernel is not expanding tabs. When running `stty - * -a` »tab0« should appear. You can tell the terminal to not expand tabs by - * running following command: - * - * stty tabs - */ -unsigned int tabspaces = 8; - -/* - * Default colors (colorname index) - * foreground, background, cursor, reverse cursor - */ -unsigned int defaultfg = 7; -unsigned int defaultbg = 258; -unsigned int defaultcs = 256; -static unsigned int defaultrcs = 257; - -/* - * Default shape of cursor - * 2: Block ("█") - * 4: Underline ("_") - * 6: Bar ("|") - * 7: Snowman ("☃") - */ -static unsigned int cursorshape = 5; - -/* - * Default columns and rows numbers - */ - -static unsigned int cols = 80; -static unsigned int rows = 24; - -/* - * Default colour and shape of the mouse cursor - */ -static unsigned int mouseshape = XC_xterm; -static unsigned int mousefg = 7; -static unsigned int mousebg = 0; - -/* - * Color used to display font attributes when fontconfig selected a font which - * doesn't match the ones requested. - */ -static unsigned int defaultattr = 11; - -/* - * Force mouse select/shortcuts while mask is active (when MODE_MOUSE is set). - * Note that if you want to use ShiftMask with selmasks, set this to an other - * modifier, set to 0 to not use it. - */ -static uint forcemousemod = ShiftMask; - -/* - * Internal mouse shortcuts. - * Beware that overloading Button1 will disable the selection. - */ -static MouseShortcut mshortcuts[] = { - /* mask button function argument release */ - { XK_ANY_MOD, Button2, selpaste, {.i = 0}, 1 }, - { ShiftMask, Button4, ttysend, {.s = "\033[5;2~"} }, - { XK_ANY_MOD, Button4, ttysend, {.s = "\031"} }, - { ShiftMask, Button5, ttysend, {.s = "\033[6;2~"} }, - { XK_ANY_MOD, Button5, ttysend, {.s = "\005"} }, -}; - -/* Internal keyboard shortcuts. */ -#define MODKEY Mod1Mask -#define TERMMOD (ControlMask|ShiftMask) - -static Shortcut shortcuts[] = { - /* mask keysym function argument */ - { XK_ANY_MOD, XK_Break, sendbreak, {.i = 0} }, - { ControlMask, XK_Print, toggleprinter, {.i = 0} }, - { ShiftMask, XK_Print, printscreen, {.i = 0} }, - { XK_ANY_MOD, XK_Print, printsel, {.i = 0} }, - { TERMMOD, XK_Prior, zoom, {.f = +1} }, - { TERMMOD, XK_Next, zoom, {.f = -1} }, - { TERMMOD, XK_Home, zoomreset, {.f = 0} }, - { MODKEY, XK_c, clipcopy, {.i = 0} }, - { MODKEY, XK_v, clippaste, {.i = 0} }, - { TERMMOD, XK_Y, selpaste, {.i = 0} }, - { ShiftMask, XK_Insert, selpaste, {.i = 0} }, - { TERMMOD, XK_Num_Lock, numlock, {.i = 0} }, - { ShiftMask, XK_Page_Up, kscrollup, {.i = -1} }, - { ShiftMask, XK_Page_Down, kscrolldown, {.i = -1} }, -}; - -/* - * Special keys (change & recompile st.info accordingly) - * - * Mask value: - * * Use XK_ANY_MOD to match the key no matter modifiers state - * * Use XK_NO_MOD to match the key alone (no modifiers) - * appkey value: - * * 0: no value - * * > 0: keypad application mode enabled - * * = 2: term.numlock = 1 - * * < 0: keypad application mode disabled - * appcursor value: - * * 0: no value - * * > 0: cursor application mode enabled - * * < 0: cursor application mode disabled - * - * Be careful with the order of the definitions because st searches in - * this table sequentially, so any XK_ANY_MOD must be in the last - * position for a key. - */ - -/* - * If you want keys other than the X11 function keys (0xFD00 - 0xFFFF) - * to be mapped below, add them to this array. - */ -static KeySym mappedkeys[] = { -1 }; - -/* - * State bits to ignore when matching key or button events. By default, - * numlock (Mod2Mask) and keyboard layout (XK_SWITCH_MOD) are ignored. - */ -static uint ignoremod = Mod2Mask|XK_SWITCH_MOD; - -/* - * This is the huge key array which defines all compatibility to the Linux - * world. Please decide about changes wisely. - */ -static Key key[] = { - /* keysym mask string appkey appcursor */ - { XK_KP_Home, ShiftMask, "\033[2J", 0, -1}, - { XK_KP_Home, ShiftMask, "\033[1;2H", 0, +1}, - { XK_KP_Home, XK_ANY_MOD, "\033[H", 0, -1}, - { XK_KP_Home, XK_ANY_MOD, "\033[1~", 0, +1}, - { XK_KP_Up, XK_ANY_MOD, "\033Ox", +1, 0}, - { XK_KP_Up, XK_ANY_MOD, "\033[A", 0, -1}, - { XK_KP_Up, XK_ANY_MOD, "\033OA", 0, +1}, - { XK_KP_Down, XK_ANY_MOD, "\033Or", +1, 0}, - { XK_KP_Down, XK_ANY_MOD, "\033[B", 0, -1}, - { XK_KP_Down, XK_ANY_MOD, "\033OB", 0, +1}, - { XK_KP_Left, XK_ANY_MOD, "\033Ot", +1, 0}, - { XK_KP_Left, XK_ANY_MOD, "\033[D", 0, -1}, - { XK_KP_Left, XK_ANY_MOD, "\033OD", 0, +1}, - { XK_KP_Right, XK_ANY_MOD, "\033Ov", +1, 0}, - { XK_KP_Right, XK_ANY_MOD, "\033[C", 0, -1}, - { XK_KP_Right, XK_ANY_MOD, "\033OC", 0, +1}, - { XK_KP_Prior, ShiftMask, "\033[5;2~", 0, 0}, - { XK_KP_Prior, XK_ANY_MOD, "\033[5~", 0, 0}, - { XK_KP_Begin, XK_ANY_MOD, "\033[E", 0, 0}, - { XK_KP_End, ControlMask, "\033[J", -1, 0}, - { XK_KP_End, ControlMask, "\033[1;5F", +1, 0}, - { XK_KP_End, ShiftMask, "\033[K", -1, 0}, - { XK_KP_End, ShiftMask, "\033[1;2F", +1, 0}, - { XK_KP_End, XK_ANY_MOD, "\033[4~", 0, 0}, - { XK_KP_Next, ShiftMask, "\033[6;2~", 0, 0}, - { XK_KP_Next, XK_ANY_MOD, "\033[6~", 0, 0}, - { XK_KP_Insert, ShiftMask, "\033[2;2~", +1, 0}, - { XK_KP_Insert, ShiftMask, "\033[4l", -1, 0}, - { XK_KP_Insert, ControlMask, "\033[L", -1, 0}, - { XK_KP_Insert, ControlMask, "\033[2;5~", +1, 0}, - { XK_KP_Insert, XK_ANY_MOD, "\033[4h", -1, 0}, - { XK_KP_Insert, XK_ANY_MOD, "\033[2~", +1, 0}, - { XK_KP_Delete, ControlMask, "\033[M", -1, 0}, - { XK_KP_Delete, ControlMask, "\033[3;5~", +1, 0}, - { XK_KP_Delete, ShiftMask, "\033[2K", -1, 0}, - { XK_KP_Delete, ShiftMask, "\033[3;2~", +1, 0}, - { XK_KP_Delete, XK_ANY_MOD, "\033[P", -1, 0}, - { XK_KP_Delete, XK_ANY_MOD, "\033[3~", +1, 0}, - { XK_KP_Multiply, XK_ANY_MOD, "\033Oj", +2, 0}, - { XK_KP_Add, XK_ANY_MOD, "\033Ok", +2, 0}, - { XK_KP_Enter, XK_ANY_MOD, "\033OM", +2, 0}, - { XK_KP_Enter, XK_ANY_MOD, "\r", -1, 0}, - { XK_KP_Subtract, XK_ANY_MOD, "\033Om", +2, 0}, - { XK_KP_Decimal, XK_ANY_MOD, "\033On", +2, 0}, - { XK_KP_Divide, XK_ANY_MOD, "\033Oo", +2, 0}, - { XK_KP_0, XK_ANY_MOD, "\033Op", +2, 0}, - { XK_KP_1, XK_ANY_MOD, "\033Oq", +2, 0}, - { XK_KP_2, XK_ANY_MOD, "\033Or", +2, 0}, - { XK_KP_3, XK_ANY_MOD, "\033Os", +2, 0}, - { XK_KP_4, XK_ANY_MOD, "\033Ot", +2, 0}, - { XK_KP_5, XK_ANY_MOD, "\033Ou", +2, 0}, - { XK_KP_6, XK_ANY_MOD, "\033Ov", +2, 0}, - { XK_KP_7, XK_ANY_MOD, "\033Ow", +2, 0}, - { XK_KP_8, XK_ANY_MOD, "\033Ox", +2, 0}, - { XK_KP_9, XK_ANY_MOD, "\033Oy", +2, 0}, - { XK_Up, ShiftMask, "\033[1;2A", 0, 0}, - { XK_Up, Mod1Mask, "\033[1;3A", 0, 0}, - { XK_Up, ShiftMask|Mod1Mask,"\033[1;4A", 0, 0}, - { XK_Up, ControlMask, "\033[1;5A", 0, 0}, - { XK_Up, ShiftMask|ControlMask,"\033[1;6A", 0, 0}, - { XK_Up, ControlMask|Mod1Mask,"\033[1;7A", 0, 0}, - { XK_Up,ShiftMask|ControlMask|Mod1Mask,"\033[1;8A", 0, 0}, - { XK_Up, XK_ANY_MOD, "\033[A", 0, -1}, - { XK_Up, XK_ANY_MOD, "\033OA", 0, +1}, - { XK_Down, ShiftMask, "\033[1;2B", 0, 0}, - { XK_Down, Mod1Mask, "\033[1;3B", 0, 0}, - { XK_Down, ShiftMask|Mod1Mask,"\033[1;4B", 0, 0}, - { XK_Down, ControlMask, "\033[1;5B", 0, 0}, - { XK_Down, ShiftMask|ControlMask,"\033[1;6B", 0, 0}, - { XK_Down, ControlMask|Mod1Mask,"\033[1;7B", 0, 0}, - { XK_Down,ShiftMask|ControlMask|Mod1Mask,"\033[1;8B",0, 0}, - { XK_Down, XK_ANY_MOD, "\033[B", 0, -1}, - { XK_Down, XK_ANY_MOD, "\033OB", 0, +1}, - { XK_Left, ShiftMask, "\033[1;2D", 0, 0}, - { XK_Left, Mod1Mask, "\033[1;3D", 0, 0}, - { XK_Left, ShiftMask|Mod1Mask,"\033[1;4D", 0, 0}, - { XK_Left, ControlMask, "\033[1;5D", 0, 0}, - { XK_Left, ShiftMask|ControlMask,"\033[1;6D", 0, 0}, - { XK_Left, ControlMask|Mod1Mask,"\033[1;7D", 0, 0}, - { XK_Left,ShiftMask|ControlMask|Mod1Mask,"\033[1;8D",0, 0}, - { XK_Left, XK_ANY_MOD, "\033[D", 0, -1}, - { XK_Left, XK_ANY_MOD, "\033OD", 0, +1}, - { XK_Right, ShiftMask, "\033[1;2C", 0, 0}, - { XK_Right, Mod1Mask, "\033[1;3C", 0, 0}, - { XK_Right, ShiftMask|Mod1Mask,"\033[1;4C", 0, 0}, - { XK_Right, ControlMask, "\033[1;5C", 0, 0}, - { XK_Right, ShiftMask|ControlMask,"\033[1;6C", 0, 0}, - { XK_Right, ControlMask|Mod1Mask,"\033[1;7C", 0, 0}, - { XK_Right,ShiftMask|ControlMask|Mod1Mask,"\033[1;8C",0, 0}, - { XK_Right, XK_ANY_MOD, "\033[C", 0, -1}, - { XK_Right, XK_ANY_MOD, "\033OC", 0, +1}, - { XK_ISO_Left_Tab, ShiftMask, "\033[Z", 0, 0}, - { XK_Return, Mod1Mask, "\033\r", 0, 0}, - { XK_Return, XK_ANY_MOD, "\r", 0, 0}, - { XK_Insert, ShiftMask, "\033[4l", -1, 0}, - { XK_Insert, ShiftMask, "\033[2;2~", +1, 0}, - { XK_Insert, ControlMask, "\033[L", -1, 0}, - { XK_Insert, ControlMask, "\033[2;5~", +1, 0}, - { XK_Insert, XK_ANY_MOD, "\033[4h", -1, 0}, - { XK_Insert, XK_ANY_MOD, "\033[2~", +1, 0}, - { XK_Delete, ControlMask, "\033[M", -1, 0}, - { XK_Delete, ControlMask, "\033[3;5~", +1, 0}, - { XK_Delete, ShiftMask, "\033[2K", -1, 0}, - { XK_Delete, ShiftMask, "\033[3;2~", +1, 0}, - { XK_Delete, XK_ANY_MOD, "\033[P", -1, 0}, - { XK_Delete, XK_ANY_MOD, "\033[3~", +1, 0}, - { XK_BackSpace, XK_NO_MOD, "\177", 0, 0}, - { XK_BackSpace, Mod1Mask, "\033\177", 0, 0}, - { XK_Home, ShiftMask, "\033[2J", 0, -1}, - { XK_Home, ShiftMask, "\033[1;2H", 0, +1}, - { XK_Home, XK_ANY_MOD, "\033[H", 0, -1}, - { XK_Home, XK_ANY_MOD, "\033[1~", 0, +1}, - { XK_End, ControlMask, "\033[J", -1, 0}, - { XK_End, ControlMask, "\033[1;5F", +1, 0}, - { XK_End, ShiftMask, "\033[K", -1, 0}, - { XK_End, ShiftMask, "\033[1;2F", +1, 0}, - { XK_End, XK_ANY_MOD, "\033[4~", 0, 0}, - { XK_Prior, ControlMask, "\033[5;5~", 0, 0}, - { XK_Prior, ShiftMask, "\033[5;2~", 0, 0}, - { XK_Prior, XK_ANY_MOD, "\033[5~", 0, 0}, - { XK_Next, ControlMask, "\033[6;5~", 0, 0}, - { XK_Next, ShiftMask, "\033[6;2~", 0, 0}, - { XK_Next, XK_ANY_MOD, "\033[6~", 0, 0}, - { XK_F1, XK_NO_MOD, "\033OP" , 0, 0}, - { XK_F1, /* F13 */ ShiftMask, "\033[1;2P", 0, 0}, - { XK_F1, /* F25 */ ControlMask, "\033[1;5P", 0, 0}, - { XK_F1, /* F37 */ Mod4Mask, "\033[1;6P", 0, 0}, - { XK_F1, /* F49 */ Mod1Mask, "\033[1;3P", 0, 0}, - { XK_F1, /* F61 */ Mod3Mask, "\033[1;4P", 0, 0}, - { XK_F2, XK_NO_MOD, "\033OQ" , 0, 0}, - { XK_F2, /* F14 */ ShiftMask, "\033[1;2Q", 0, 0}, - { XK_F2, /* F26 */ ControlMask, "\033[1;5Q", 0, 0}, - { XK_F2, /* F38 */ Mod4Mask, "\033[1;6Q", 0, 0}, - { XK_F2, /* F50 */ Mod1Mask, "\033[1;3Q", 0, 0}, - { XK_F2, /* F62 */ Mod3Mask, "\033[1;4Q", 0, 0}, - { XK_F3, XK_NO_MOD, "\033OR" , 0, 0}, - { XK_F3, /* F15 */ ShiftMask, "\033[1;2R", 0, 0}, - { XK_F3, /* F27 */ ControlMask, "\033[1;5R", 0, 0}, - { XK_F3, /* F39 */ Mod4Mask, "\033[1;6R", 0, 0}, - { XK_F3, /* F51 */ Mod1Mask, "\033[1;3R", 0, 0}, - { XK_F3, /* F63 */ Mod3Mask, "\033[1;4R", 0, 0}, - { XK_F4, XK_NO_MOD, "\033OS" , 0, 0}, - { XK_F4, /* F16 */ ShiftMask, "\033[1;2S", 0, 0}, - { XK_F4, /* F28 */ ControlMask, "\033[1;5S", 0, 0}, - { XK_F4, /* F40 */ Mod4Mask, "\033[1;6S", 0, 0}, - { XK_F4, /* F52 */ Mod1Mask, "\033[1;3S", 0, 0}, - { XK_F5, XK_NO_MOD, "\033[15~", 0, 0}, - { XK_F5, /* F17 */ ShiftMask, "\033[15;2~", 0, 0}, - { XK_F5, /* F29 */ ControlMask, "\033[15;5~", 0, 0}, - { XK_F5, /* F41 */ Mod4Mask, "\033[15;6~", 0, 0}, - { XK_F5, /* F53 */ Mod1Mask, "\033[15;3~", 0, 0}, - { XK_F6, XK_NO_MOD, "\033[17~", 0, 0}, - { XK_F6, /* F18 */ ShiftMask, "\033[17;2~", 0, 0}, - { XK_F6, /* F30 */ ControlMask, "\033[17;5~", 0, 0}, - { XK_F6, /* F42 */ Mod4Mask, "\033[17;6~", 0, 0}, - { XK_F6, /* F54 */ Mod1Mask, "\033[17;3~", 0, 0}, - { XK_F7, XK_NO_MOD, "\033[18~", 0, 0}, - { XK_F7, /* F19 */ ShiftMask, "\033[18;2~", 0, 0}, - { XK_F7, /* F31 */ ControlMask, "\033[18;5~", 0, 0}, - { XK_F7, /* F43 */ Mod4Mask, "\033[18;6~", 0, 0}, - { XK_F7, /* F55 */ Mod1Mask, "\033[18;3~", 0, 0}, - { XK_F8, XK_NO_MOD, "\033[19~", 0, 0}, - { XK_F8, /* F20 */ ShiftMask, "\033[19;2~", 0, 0}, - { XK_F8, /* F32 */ ControlMask, "\033[19;5~", 0, 0}, - { XK_F8, /* F44 */ Mod4Mask, "\033[19;6~", 0, 0}, - { XK_F8, /* F56 */ Mod1Mask, "\033[19;3~", 0, 0}, - { XK_F9, XK_NO_MOD, "\033[20~", 0, 0}, - { XK_F9, /* F21 */ ShiftMask, "\033[20;2~", 0, 0}, - { XK_F9, /* F33 */ ControlMask, "\033[20;5~", 0, 0}, - { XK_F9, /* F45 */ Mod4Mask, "\033[20;6~", 0, 0}, - { XK_F9, /* F57 */ Mod1Mask, "\033[20;3~", 0, 0}, - { XK_F10, XK_NO_MOD, "\033[21~", 0, 0}, - { XK_F10, /* F22 */ ShiftMask, "\033[21;2~", 0, 0}, - { XK_F10, /* F34 */ ControlMask, "\033[21;5~", 0, 0}, - { XK_F10, /* F46 */ Mod4Mask, "\033[21;6~", 0, 0}, - { XK_F10, /* F58 */ Mod1Mask, "\033[21;3~", 0, 0}, - { XK_F11, XK_NO_MOD, "\033[23~", 0, 0}, - { XK_F11, /* F23 */ ShiftMask, "\033[23;2~", 0, 0}, - { XK_F11, /* F35 */ ControlMask, "\033[23;5~", 0, 0}, - { XK_F11, /* F47 */ Mod4Mask, "\033[23;6~", 0, 0}, - { XK_F11, /* F59 */ Mod1Mask, "\033[23;3~", 0, 0}, - { XK_F12, XK_NO_MOD, "\033[24~", 0, 0}, - { XK_F12, /* F24 */ ShiftMask, "\033[24;2~", 0, 0}, - { XK_F12, /* F36 */ ControlMask, "\033[24;5~", 0, 0}, - { XK_F12, /* F48 */ Mod4Mask, "\033[24;6~", 0, 0}, - { XK_F12, /* F60 */ Mod1Mask, "\033[24;3~", 0, 0}, - { XK_F13, XK_NO_MOD, "\033[1;2P", 0, 0}, - { XK_F14, XK_NO_MOD, "\033[1;2Q", 0, 0}, - { XK_F15, XK_NO_MOD, "\033[1;2R", 0, 0}, - { XK_F16, XK_NO_MOD, "\033[1;2S", 0, 0}, - { XK_F17, XK_NO_MOD, "\033[15;2~", 0, 0}, - { XK_F18, XK_NO_MOD, "\033[17;2~", 0, 0}, - { XK_F19, XK_NO_MOD, "\033[18;2~", 0, 0}, - { XK_F20, XK_NO_MOD, "\033[19;2~", 0, 0}, - { XK_F21, XK_NO_MOD, "\033[20;2~", 0, 0}, - { XK_F22, XK_NO_MOD, "\033[21;2~", 0, 0}, - { XK_F23, XK_NO_MOD, "\033[23;2~", 0, 0}, - { XK_F24, XK_NO_MOD, "\033[24;2~", 0, 0}, - { XK_F25, XK_NO_MOD, "\033[1;5P", 0, 0}, - { XK_F26, XK_NO_MOD, "\033[1;5Q", 0, 0}, - { XK_F27, XK_NO_MOD, "\033[1;5R", 0, 0}, - { XK_F28, XK_NO_MOD, "\033[1;5S", 0, 0}, - { XK_F29, XK_NO_MOD, "\033[15;5~", 0, 0}, - { XK_F30, XK_NO_MOD, "\033[17;5~", 0, 0}, - { XK_F31, XK_NO_MOD, "\033[18;5~", 0, 0}, - { XK_F32, XK_NO_MOD, "\033[19;5~", 0, 0}, - { XK_F33, XK_NO_MOD, "\033[20;5~", 0, 0}, - { XK_F34, XK_NO_MOD, "\033[21;5~", 0, 0}, - { XK_F35, XK_NO_MOD, "\033[23;5~", 0, 0}, -}; - -/* - * Selection types' masks. - * Use the same masks as usual. - * Button1Mask is always unset, to make masks match between ButtonPress. - * ButtonRelease and MotionNotify. - * If no match is found, regular selection is used. - */ -static uint selmasks[] = { - [SEL_RECTANGULAR] = Mod1Mask, -}; - -/* - * Printable characters in ASCII, used to estimate the advance width - * of single wide characters. - */ -static char ascii_printable[] = - " !\"#$%&'()*+,-./0123456789:;<=>?" - "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" - "`abcdefghijklmnopqrstuvwxyz{|}~"; diff --git a/utils/st-0.9/config.mk b/utils/st-0.9/config.mk deleted file mode 100644 index 47c615e..0000000 --- a/utils/st-0.9/config.mk +++ /dev/null @@ -1,36 +0,0 @@ -# st version -VERSION = 0.9 - -# Customize below to fit your system - -# paths -PREFIX = /usr/local -MANPREFIX = $(PREFIX)/share/man - -X11INC = /usr/X11R6/include -X11LIB = /usr/X11R6/lib - -PKG_CONFIG = pkg-config - -# includes and libs -INCS = -I$(X11INC) \ - `$(PKG_CONFIG) --cflags fontconfig` \ - `$(PKG_CONFIG) --cflags freetype2` -LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft -lXrender\ - `$(PKG_CONFIG) --libs fontconfig` \ - `$(PKG_CONFIG) --libs freetype2` - -# flags -STCPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600 -STCFLAGS = $(INCS) $(STCPPFLAGS) $(CPPFLAGS) $(CFLAGS) -STLDFLAGS = $(LIBS) $(LDFLAGS) - -# OpenBSD: -#CPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600 -D_BSD_SOURCE -#LIBS = -L$(X11LIB) -lm -lX11 -lutil -lXft \ -# `$(PKG_CONFIG) --libs fontconfig` \ -# `$(PKG_CONFIG) --libs freetype2` -#MANPREFIX = ${PREFIX}/man - -# compiler and linker -# CC = c99 diff --git a/utils/st-0.9/st-alpha-20220206-0.8.5.diff b/utils/st-0.9/st-alpha-20220206-0.8.5.diff deleted file mode 100644 index ab029f6..0000000 --- a/utils/st-0.9/st-alpha-20220206-0.8.5.diff +++ /dev/null @@ -1,146 +0,0 @@ -diff --git a/config.def.h b/config.def.h -index 91ab8ca..6af616e 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -93,6 +93,9 @@ char *termname = "st-256color"; - */ - unsigned int tabspaces = 8; - -+/* bg opacity */ -+float alpha = 0.8; -+ - /* Terminal colors (16 first used in escape sequence) */ - static const char *colorname[] = { - /* 8 normal colors */ -diff --git a/config.mk b/config.mk -index 4c4c5d5..0114bad 100644 ---- a/config.mk -+++ b/config.mk -@@ -16,7 +16,7 @@ PKG_CONFIG = pkg-config - INCS = -I$(X11INC) \ - `$(PKG_CONFIG) --cflags fontconfig` \ - `$(PKG_CONFIG) --cflags freetype2` --LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft \ -+LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft -lXrender\ - `$(PKG_CONFIG) --libs fontconfig` \ - `$(PKG_CONFIG) --libs freetype2` - -diff --git a/st.h b/st.h -index 519b9bd..8bb533d 100644 ---- a/st.h -+++ b/st.h -@@ -126,3 +126,4 @@ extern unsigned int tabspaces; - extern unsigned int defaultfg; - extern unsigned int defaultbg; - extern unsigned int defaultcs; -+extern float alpha; -diff --git a/x.c b/x.c -index 8a16faa..ddf4178 100644 ---- a/x.c -+++ b/x.c -@@ -105,6 +105,7 @@ typedef struct { - XSetWindowAttributes attrs; - int scr; - int isfixed; /* is fixed geometry? */ -+ int depth; /* bit depth */ - int l, t; /* left and top offset */ - int gm; /* geometry mask */ - } XWindow; -@@ -243,6 +244,7 @@ static char *usedfont = NULL; - static double usedfontsize = 0; - static double defaultfontsize = 0; - -+static char *opt_alpha = NULL; - static char *opt_class = NULL; - static char **opt_cmd = NULL; - static char *opt_embed = NULL; -@@ -736,7 +738,7 @@ xresize(int col, int row) - - XFreePixmap(xw.dpy, xw.buf); - xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, -- DefaultDepth(xw.dpy, xw.scr)); -+ xw.depth); - XftDrawChange(xw.draw, xw.buf); - xclear(0, 0, win.w, win.h); - -@@ -796,6 +798,13 @@ xloadcols(void) - else - die("could not allocate color %d\n", i); - } -+ -+ /* set alpha value of bg color */ -+ if (opt_alpha) -+ alpha = strtof(opt_alpha, NULL); -+ dc.col[defaultbg].color.alpha = (unsigned short)(0xffff * alpha); -+ dc.col[defaultbg].pixel &= 0x00FFFFFF; -+ dc.col[defaultbg].pixel |= (unsigned char)(0xff * alpha) << 24; - loaded = 1; - } - -@@ -1118,11 +1127,23 @@ xinit(int cols, int rows) - Window parent; - pid_t thispid = getpid(); - XColor xmousefg, xmousebg; -+ XWindowAttributes attr; -+ XVisualInfo vis; - - if (!(xw.dpy = XOpenDisplay(NULL))) - die("can't open display\n"); - xw.scr = XDefaultScreen(xw.dpy); -- xw.vis = XDefaultVisual(xw.dpy, xw.scr); -+ -+ if (!(opt_embed && (parent = strtol(opt_embed, NULL, 0)))) { -+ parent = XRootWindow(xw.dpy, xw.scr); -+ xw.depth = 32; -+ } else { -+ XGetWindowAttributes(xw.dpy, parent, &attr); -+ xw.depth = attr.depth; -+ } -+ -+ XMatchVisualInfo(xw.dpy, xw.scr, xw.depth, TrueColor, &vis); -+ xw.vis = vis.visual; - - /* font */ - if (!FcInit()) -@@ -1132,7 +1153,7 @@ xinit(int cols, int rows) - xloadfonts(usedfont, 0); - - /* colors */ -- xw.cmap = XDefaultColormap(xw.dpy, xw.scr); -+ xw.cmap = XCreateColormap(xw.dpy, parent, xw.vis, None); - xloadcols(); - - /* adjust fixed window geometry */ -@@ -1152,19 +1173,15 @@ xinit(int cols, int rows) - | ButtonMotionMask | ButtonPressMask | ButtonReleaseMask; - xw.attrs.colormap = xw.cmap; - -- if (!(opt_embed && (parent = strtol(opt_embed, NULL, 0)))) -- parent = XRootWindow(xw.dpy, xw.scr); - xw.win = XCreateWindow(xw.dpy, parent, xw.l, xw.t, -- win.w, win.h, 0, XDefaultDepth(xw.dpy, xw.scr), InputOutput, -+ win.w, win.h, 0, xw.depth, InputOutput, - xw.vis, CWBackPixel | CWBorderPixel | CWBitGravity - | CWEventMask | CWColormap, &xw.attrs); - - memset(&gcvalues, 0, sizeof(gcvalues)); - gcvalues.graphics_exposures = False; -- dc.gc = XCreateGC(xw.dpy, parent, GCGraphicsExposures, -- &gcvalues); -- xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, -- DefaultDepth(xw.dpy, xw.scr)); -+ xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, xw.depth); -+ dc.gc = XCreateGC(xw.dpy, xw.buf, GCGraphicsExposures, &gcvalues); - XSetForeground(xw.dpy, dc.gc, dc.col[defaultbg].pixel); - XFillRectangle(xw.dpy, xw.buf, dc.gc, 0, 0, win.w, win.h); - -@@ -2019,6 +2036,9 @@ main(int argc, char *argv[]) - case 'a': - allowaltscreen = 0; - break; -+ case 'A': -+ opt_alpha = EARGF(usage()); -+ break; - case 'c': - opt_class = EARGF(usage()); - break; diff --git a/utils/st-0.9/st-rightclickpaste-0.8.2.diff b/utils/st-0.9/st-rightclickpaste-0.8.2.diff deleted file mode 100644 index d959417..0000000 --- a/utils/st-0.9/st-rightclickpaste-0.8.2.diff +++ /dev/null @@ -1,28 +0,0 @@ -From 111e5d0311f174592ccecee2af11067103abaee7 Mon Sep 17 00:00:00 2001 -From: aleks <aleks.stier@icloud.com> -Date: Sun, 11 Aug 2019 03:15:26 +0200 -Subject: [PATCH] Make right-click paste - -Pressing right-click pastes from the primary-selection. -If combined with the clipboard-patch right-click pastes from the clipboard. -Middle-click does nothing. ---- - x.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/x.c b/x.c -index 0422421..13a5849 100644 ---- a/x.c -+++ b/x.c -@@ -643,7 +643,7 @@ brelease(XEvent *e) - return; - } - -- if (e->xbutton.button == Button2) -+ if (e->xbutton.button == Button3) - selpaste(NULL); - else if (e->xbutton.button == Button1) - mousesel(e, 1); --- -2.22.0 - diff --git a/utils/st-0.9/st-scrollback-0.8.5.diff b/utils/st-0.9/st-scrollback-0.8.5.diff deleted file mode 100644 index 750111d..0000000 --- a/utils/st-0.9/st-scrollback-0.8.5.diff +++ /dev/null @@ -1,350 +0,0 @@ -diff --git a/config.def.h b/config.def.h -index 91ab8ca..e3b469b 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -201,6 +201,8 @@ static Shortcut shortcuts[] = { - { TERMMOD, XK_Y, selpaste, {.i = 0} }, - { ShiftMask, XK_Insert, selpaste, {.i = 0} }, - { TERMMOD, XK_Num_Lock, numlock, {.i = 0} }, -+ { ShiftMask, XK_Page_Up, kscrollup, {.i = -1} }, -+ { ShiftMask, XK_Page_Down, kscrolldown, {.i = -1} }, - }; - - /* -diff --git a/st.c b/st.c -index 51049ba..cd750f2 100644 ---- a/st.c -+++ b/st.c -@@ -35,6 +35,7 @@ - #define ESC_ARG_SIZ 16 - #define STR_BUF_SIZ ESC_BUF_SIZ - #define STR_ARG_SIZ ESC_ARG_SIZ -+#define HISTSIZE 2000 - - /* macros */ - #define IS_SET(flag) ((term.mode & (flag)) != 0) -@@ -42,6 +43,9 @@ - #define ISCONTROLC1(c) (BETWEEN(c, 0x80, 0x9f)) - #define ISCONTROL(c) (ISCONTROLC0(c) || ISCONTROLC1(c)) - #define ISDELIM(u) (u && wcschr(worddelimiters, u)) -+#define TLINE(y) ((y) < term.scr ? term.hist[((y) + term.histi - \ -+ term.scr + HISTSIZE + 1) % HISTSIZE] : \ -+ term.line[(y) - term.scr]) - - enum term_mode { - MODE_WRAP = 1 << 0, -@@ -115,6 +119,9 @@ typedef struct { - int col; /* nb col */ - Line *line; /* screen */ - Line *alt; /* alternate screen */ -+ Line hist[HISTSIZE]; /* history buffer */ -+ int histi; /* history index */ -+ int scr; /* scroll back */ - int *dirty; /* dirtyness of lines */ - TCursor c; /* cursor */ - int ocx; /* old cursor col */ -@@ -184,8 +191,8 @@ static void tnewline(int); - static void tputtab(int); - static void tputc(Rune); - static void treset(void); --static void tscrollup(int, int); --static void tscrolldown(int, int); -+static void tscrollup(int, int, int); -+static void tscrolldown(int, int, int); - static void tsetattr(const int *, int); - static void tsetchar(Rune, const Glyph *, int, int); - static void tsetdirt(int, int); -@@ -416,10 +423,10 @@ tlinelen(int y) - { - int i = term.col; - -- if (term.line[y][i - 1].mode & ATTR_WRAP) -+ if (TLINE(y)[i - 1].mode & ATTR_WRAP) - return i; - -- while (i > 0 && term.line[y][i - 1].u == ' ') -+ while (i > 0 && TLINE(y)[i - 1].u == ' ') - --i; - - return i; -@@ -528,7 +535,7 @@ selsnap(int *x, int *y, int direction) - * Snap around if the word wraps around at the end or - * beginning of a line. - */ -- prevgp = &term.line[*y][*x]; -+ prevgp = &TLINE(*y)[*x]; - prevdelim = ISDELIM(prevgp->u); - for (;;) { - newx = *x + direction; -@@ -543,14 +550,14 @@ selsnap(int *x, int *y, int direction) - yt = *y, xt = *x; - else - yt = newy, xt = newx; -- if (!(term.line[yt][xt].mode & ATTR_WRAP)) -+ if (!(TLINE(yt)[xt].mode & ATTR_WRAP)) - break; - } - - if (newx >= tlinelen(newy)) - break; - -- gp = &term.line[newy][newx]; -+ gp = &TLINE(newy)[newx]; - delim = ISDELIM(gp->u); - if (!(gp->mode & ATTR_WDUMMY) && (delim != prevdelim - || (delim && gp->u != prevgp->u))) -@@ -571,14 +578,14 @@ selsnap(int *x, int *y, int direction) - *x = (direction < 0) ? 0 : term.col - 1; - if (direction < 0) { - for (; *y > 0; *y += direction) { -- if (!(term.line[*y-1][term.col-1].mode -+ if (!(TLINE(*y-1)[term.col-1].mode - & ATTR_WRAP)) { - break; - } - } - } else if (direction > 0) { - for (; *y < term.row-1; *y += direction) { -- if (!(term.line[*y][term.col-1].mode -+ if (!(TLINE(*y)[term.col-1].mode - & ATTR_WRAP)) { - break; - } -@@ -609,13 +616,13 @@ getsel(void) - } - - if (sel.type == SEL_RECTANGULAR) { -- gp = &term.line[y][sel.nb.x]; -+ gp = &TLINE(y)[sel.nb.x]; - lastx = sel.ne.x; - } else { -- gp = &term.line[y][sel.nb.y == y ? sel.nb.x : 0]; -+ gp = &TLINE(y)[sel.nb.y == y ? sel.nb.x : 0]; - lastx = (sel.ne.y == y) ? sel.ne.x : term.col-1; - } -- last = &term.line[y][MIN(lastx, linelen-1)]; -+ last = &TLINE(y)[MIN(lastx, linelen-1)]; - while (last >= gp && last->u == ' ') - --last; - -@@ -851,6 +858,9 @@ void - ttywrite(const char *s, size_t n, int may_echo) - { - const char *next; -+ Arg arg = (Arg) { .i = term.scr }; -+ -+ kscrolldown(&arg); - - if (may_echo && IS_SET(MODE_ECHO)) - twrite(s, n, 1); -@@ -1062,12 +1072,52 @@ tswapscreen(void) - } - - void --tscrolldown(int orig, int n) -+kscrolldown(const Arg* a) -+{ -+ int n = a->i; -+ -+ if (n < 0) -+ n = term.row + n; -+ -+ if (n > term.scr) -+ n = term.scr; -+ -+ if (term.scr > 0) { -+ term.scr -= n; -+ selscroll(0, -n); -+ tfulldirt(); -+ } -+} -+ -+void -+kscrollup(const Arg* a) -+{ -+ int n = a->i; -+ -+ if (n < 0) -+ n = term.row + n; -+ -+ if (term.scr <= HISTSIZE-n) { -+ term.scr += n; -+ selscroll(0, n); -+ tfulldirt(); -+ } -+} -+ -+void -+tscrolldown(int orig, int n, int copyhist) - { - int i; - Line temp; - - LIMIT(n, 0, term.bot-orig+1); -+ if (copyhist) { -+ term.histi = (term.histi - 1 + HISTSIZE) % HISTSIZE; -+ temp = term.hist[term.histi]; -+ term.hist[term.histi] = term.line[term.bot]; -+ term.line[term.bot] = temp; -+ } -+ - - tsetdirt(orig, term.bot-n); - tclearregion(0, term.bot-n+1, term.col-1, term.bot); -@@ -1078,17 +1128,28 @@ tscrolldown(int orig, int n) - term.line[i-n] = temp; - } - -- selscroll(orig, n); -+ if (term.scr == 0) -+ selscroll(orig, n); - } - - void --tscrollup(int orig, int n) -+tscrollup(int orig, int n, int copyhist) - { - int i; - Line temp; - - LIMIT(n, 0, term.bot-orig+1); - -+ if (copyhist) { -+ term.histi = (term.histi + 1) % HISTSIZE; -+ temp = term.hist[term.histi]; -+ term.hist[term.histi] = term.line[orig]; -+ term.line[orig] = temp; -+ } -+ -+ if (term.scr > 0 && term.scr < HISTSIZE) -+ term.scr = MIN(term.scr + n, HISTSIZE-1); -+ - tclearregion(0, orig, term.col-1, orig+n-1); - tsetdirt(orig+n, term.bot); - -@@ -1098,7 +1159,8 @@ tscrollup(int orig, int n) - term.line[i+n] = temp; - } - -- selscroll(orig, -n); -+ if (term.scr == 0) -+ selscroll(orig, -n); - } - - void -@@ -1127,7 +1189,7 @@ tnewline(int first_col) - int y = term.c.y; - - if (y == term.bot) { -- tscrollup(term.top, 1); -+ tscrollup(term.top, 1, 1); - } else { - y++; - } -@@ -1292,14 +1354,14 @@ void - tinsertblankline(int n) - { - if (BETWEEN(term.c.y, term.top, term.bot)) -- tscrolldown(term.c.y, n); -+ tscrolldown(term.c.y, n, 0); - } - - void - tdeleteline(int n) - { - if (BETWEEN(term.c.y, term.top, term.bot)) -- tscrollup(term.c.y, n); -+ tscrollup(term.c.y, n, 0); - } - - int32_t -@@ -1736,11 +1798,11 @@ csihandle(void) - break; - case 'S': /* SU -- Scroll <n> line up */ - DEFAULT(csiescseq.arg[0], 1); -- tscrollup(term.top, csiescseq.arg[0]); -+ tscrollup(term.top, csiescseq.arg[0], 0); - break; - case 'T': /* SD -- Scroll <n> line down */ - DEFAULT(csiescseq.arg[0], 1); -- tscrolldown(term.top, csiescseq.arg[0]); -+ tscrolldown(term.top, csiescseq.arg[0], 0); - break; - case 'L': /* IL -- Insert <n> blank lines */ - DEFAULT(csiescseq.arg[0], 1); -@@ -2330,7 +2392,7 @@ eschandle(uchar ascii) - return 0; - case 'D': /* IND -- Linefeed */ - if (term.c.y == term.bot) { -- tscrollup(term.top, 1); -+ tscrollup(term.top, 1, 1); - } else { - tmoveto(term.c.x, term.c.y+1); - } -@@ -2343,7 +2405,7 @@ eschandle(uchar ascii) - break; - case 'M': /* RI -- Reverse index */ - if (term.c.y == term.top) { -- tscrolldown(term.top, 1); -+ tscrolldown(term.top, 1, 1); - } else { - tmoveto(term.c.x, term.c.y-1); - } -@@ -2557,7 +2619,7 @@ twrite(const char *buf, int buflen, int show_ctrl) - void - tresize(int col, int row) - { -- int i; -+ int i, j; - int minrow = MIN(row, term.row); - int mincol = MIN(col, term.col); - int *bp; -@@ -2594,6 +2656,14 @@ tresize(int col, int row) - term.dirty = xrealloc(term.dirty, row * sizeof(*term.dirty)); - term.tabs = xrealloc(term.tabs, col * sizeof(*term.tabs)); - -+ for (i = 0; i < HISTSIZE; i++) { -+ term.hist[i] = xrealloc(term.hist[i], col * sizeof(Glyph)); -+ for (j = mincol; j < col; j++) { -+ term.hist[i][j] = term.c.attr; -+ term.hist[i][j].u = ' '; -+ } -+ } -+ - /* resize each row to new width, zero-pad if needed */ - for (i = 0; i < minrow; i++) { - term.line[i] = xrealloc(term.line[i], col * sizeof(Glyph)); -@@ -2652,7 +2722,7 @@ drawregion(int x1, int y1, int x2, int y2) - continue; - - term.dirty[y] = 0; -- xdrawline(term.line[y], x1, y, x2); -+ xdrawline(TLINE(y), x1, y, x2); - } - } - -@@ -2673,8 +2743,9 @@ draw(void) - cx--; - - drawregion(0, 0, term.col, term.row); -- xdrawcursor(cx, term.c.y, term.line[term.c.y][cx], -- term.ocx, term.ocy, term.line[term.ocy][term.ocx]); -+ if (term.scr == 0) -+ xdrawcursor(cx, term.c.y, term.line[term.c.y][cx], -+ term.ocx, term.ocy, term.line[term.ocy][term.ocx]); - term.ocx = cx; - term.ocy = term.c.y; - xfinishdraw(); -diff --git a/st.h b/st.h -index 519b9bd..da36b34 100644 ---- a/st.h -+++ b/st.h -@@ -81,6 +81,8 @@ void die(const char *, ...); - void redraw(void); - void draw(void); - -+void kscrolldown(const Arg *); -+void kscrollup(const Arg *); - void printscreen(const Arg *); - void printsel(const Arg *); - void sendbreak(const Arg *); diff --git a/utils/st-0.9/st.1 b/utils/st-0.9/st.1 deleted file mode 100644 index 39120b4..0000000 --- a/utils/st-0.9/st.1 +++ /dev/null @@ -1,177 +0,0 @@ -.TH ST 1 st\-VERSION -.SH NAME -st \- simple terminal -.SH SYNOPSIS -.B st -.RB [ \-aiv ] -.RB [ \-c -.IR class ] -.RB [ \-f -.IR font ] -.RB [ \-g -.IR geometry ] -.RB [ \-n -.IR name ] -.RB [ \-o -.IR iofile ] -.RB [ \-T -.IR title ] -.RB [ \-t -.IR title ] -.RB [ \-l -.IR line ] -.RB [ \-w -.IR windowid ] -.RB [[ \-e ] -.IR command -.RI [ arguments ...]] -.PP -.B st -.RB [ \-aiv ] -.RB [ \-c -.IR class ] -.RB [ \-f -.IR font ] -.RB [ \-g -.IR geometry ] -.RB [ \-n -.IR name ] -.RB [ \-o -.IR iofile ] -.RB [ \-T -.IR title ] -.RB [ \-t -.IR title ] -.RB [ \-w -.IR windowid ] -.RB \-l -.IR line -.RI [ stty_args ...] -.SH DESCRIPTION -.B st -is a simple terminal emulator. -.SH OPTIONS -.TP -.B \-a -disable alternate screens in terminal -.TP -.BI \-c " class" -defines the window class (default $TERM). -.TP -.BI \-f " font" -defines the -.I font -to use when st is run. -.TP -.BI \-g " geometry" -defines the X11 geometry string. -The form is [=][<cols>{xX}<rows>][{+-}<xoffset>{+-}<yoffset>]. See -.BR XParseGeometry (3) -for further details. -.TP -.B \-i -will fixate the position given with the -g option. -.TP -.BI \-n " name" -defines the window instance name (default $TERM). -.TP -.BI \-o " iofile" -writes all the I/O to -.I iofile. -This feature is useful when recording st sessions. A value of "-" means -standard output. -.TP -.BI \-T " title" -defines the window title (default 'st'). -.TP -.BI \-t " title" -defines the window title (default 'st'). -.TP -.BI \-w " windowid" -embeds st within the window identified by -.I windowid -.TP -.BI \-l " line" -use a tty -.I line -instead of a pseudo terminal. -.I line -should be a (pseudo-)serial device (e.g. /dev/ttyS0 on Linux for serial port -0). -When this flag is given -remaining arguments are used as flags for -.BR stty(1). -By default st initializes the serial line to 8 bits, no parity, 1 stop bit -and a 38400 baud rate. The speed is set by appending it as last argument -(e.g. 'st -l /dev/ttyS0 115200'). Arguments before the last one are -.BR stty(1) -flags. If you want to set odd parity on 115200 baud use for example 'st -l -/dev/ttyS0 parenb parodd 115200'. Set the number of bits by using for -example 'st -l /dev/ttyS0 cs7 115200'. See -.BR stty(1) -for more arguments and cases. -.TP -.B \-v -prints version information to stderr, then exits. -.TP -.BI \-e " command " [ " arguments " "... ]" -st executes -.I command -instead of the shell. If this is used it -.B must be the last option -on the command line, as in xterm / rxvt. -This option is only intended for compatibility, -and all the remaining arguments are used as a command -even without it. -.SH SHORTCUTS -.TP -.B Break -Send a break in the serial line. -Break key is obtained in PC keyboards -pressing at the same time control and pause. -.TP -.B Ctrl-Print Screen -Toggle if st should print to the -.I iofile. -.TP -.B Shift-Print Screen -Print the full screen to the -.I iofile. -.TP -.B Print Screen -Print the selection to the -.I iofile. -.TP -.B Ctrl-Shift-Page Up -Increase font size. -.TP -.B Ctrl-Shift-Page Down -Decrease font size. -.TP -.B Ctrl-Shift-Home -Reset to default font size. -.TP -.B Ctrl-Shift-y -Paste from primary selection (middle mouse button). -.TP -.B Ctrl-Shift-c -Copy the selected text to the clipboard selection. -.TP -.B Ctrl-Shift-v -Paste from the clipboard selection. -.SH CUSTOMIZATION -.B st -can be customized by creating a custom config.h and (re)compiling the source -code. This keeps it fast, secure and simple. -.SH AUTHORS -See the LICENSE file for the authors. -.SH LICENSE -See the LICENSE file for the terms of redistribution. -.SH SEE ALSO -.BR tabbed (1), -.BR utmp (1), -.BR stty (1), -.BR scroll (1) -.SH BUGS -See the TODO file in the distribution. - diff --git a/utils/st-0.9/st.c b/utils/st-0.9/st.c deleted file mode 100644 index 79ee9ba..0000000 --- a/utils/st-0.9/st.c +++ /dev/null @@ -1,2727 +0,0 @@ -/* See LICENSE for license details. */ -#include <ctype.h> -#include <errno.h> -#include <fcntl.h> -#include <limits.h> -#include <pwd.h> -#include <stdarg.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <signal.h> -#include <sys/ioctl.h> -#include <sys/select.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <termios.h> -#include <unistd.h> -#include <wchar.h> - -#include "st.h" -#include "win.h" - -#if defined(__linux) - #include <pty.h> -#elif defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__) - #include <util.h> -#elif defined(__FreeBSD__) || defined(__DragonFly__) - #include <libutil.h> -#endif - -/* Arbitrary sizes */ -#define UTF_INVALID 0xFFFD -#define UTF_SIZ 4 -#define ESC_BUF_SIZ (128*UTF_SIZ) -#define ESC_ARG_SIZ 16 -#define STR_BUF_SIZ ESC_BUF_SIZ -#define STR_ARG_SIZ ESC_ARG_SIZ -#define HISTSIZE 2000 - -/* macros */ -#define IS_SET(flag) ((term.mode & (flag)) != 0) -#define ISCONTROLC0(c) (BETWEEN(c, 0, 0x1f) || (c) == 0x7f) -#define ISCONTROLC1(c) (BETWEEN(c, 0x80, 0x9f)) -#define ISCONTROL(c) (ISCONTROLC0(c) || ISCONTROLC1(c)) -#define ISDELIM(u) (u && wcschr(worddelimiters, u)) -#define TLINE(y) ((y) < term.scr ? term.hist[((y) + term.histi - \ - term.scr + HISTSIZE + 1) % HISTSIZE] : \ - term.line[(y) - term.scr]) - -enum term_mode { - MODE_WRAP = 1 << 0, - MODE_INSERT = 1 << 1, - MODE_ALTSCREEN = 1 << 2, - MODE_CRLF = 1 << 3, - MODE_ECHO = 1 << 4, - MODE_PRINT = 1 << 5, - MODE_UTF8 = 1 << 6, -}; - -enum cursor_movement { - CURSOR_SAVE, - CURSOR_LOAD -}; - -enum cursor_state { - CURSOR_DEFAULT = 0, - CURSOR_WRAPNEXT = 1, - CURSOR_ORIGIN = 2 -}; - -enum charset { - CS_GRAPHIC0, - CS_GRAPHIC1, - CS_UK, - CS_USA, - CS_MULTI, - CS_GER, - CS_FIN -}; - -enum escape_state { - ESC_START = 1, - ESC_CSI = 2, - ESC_STR = 4, /* DCS, OSC, PM, APC */ - ESC_ALTCHARSET = 8, - ESC_STR_END = 16, /* a final string was encountered */ - ESC_TEST = 32, /* Enter in test mode */ - ESC_UTF8 = 64, -}; - -typedef struct { - Glyph attr; /* current char attributes */ - int x; - int y; - char state; -} TCursor; - -typedef struct { - int mode; - int type; - int snap; - /* - * Selection variables: - * nb – normalized coordinates of the beginning of the selection - * ne – normalized coordinates of the end of the selection - * ob – original coordinates of the beginning of the selection - * oe – original coordinates of the end of the selection - */ - struct { - int x, y; - } nb, ne, ob, oe; - - int alt; -} Selection; - -/* Internal representation of the screen */ -typedef struct { - int row; /* nb row */ - int col; /* nb col */ - Line *line; /* screen */ - Line *alt; /* alternate screen */ - Line hist[HISTSIZE]; /* history buffer */ - int histi; /* history index */ - int scr; /* scroll back */ - int *dirty; /* dirtyness of lines */ - TCursor c; /* cursor */ - int ocx; /* old cursor col */ - int ocy; /* old cursor row */ - int top; /* top scroll limit */ - int bot; /* bottom scroll limit */ - int mode; /* terminal mode flags */ - int esc; /* escape state flags */ - char trantbl[4]; /* charset table translation */ - int charset; /* current charset */ - int icharset; /* selected charset for sequence */ - int *tabs; - Rune lastc; /* last printed char outside of sequence, 0 if control */ -} Term; - -/* CSI Escape sequence structs */ -/* ESC '[' [[ [<priv>] <arg> [;]] <mode> [<mode>]] */ -typedef struct { - char buf[ESC_BUF_SIZ]; /* raw string */ - size_t len; /* raw string length */ - char priv; - int arg[ESC_ARG_SIZ]; - int narg; /* nb of args */ - char mode[2]; -} CSIEscape; - -/* STR Escape sequence structs */ -/* ESC type [[ [<priv>] <arg> [;]] <mode>] ESC '\' */ -typedef struct { - char type; /* ESC type ... */ - char *buf; /* allocated raw string */ - size_t siz; /* allocation size */ - size_t len; /* raw string length */ - char *args[STR_ARG_SIZ]; - int narg; /* nb of args */ -} STREscape; - -static void execsh(char *, char **); -static void stty(char **); -static void sigchld(int); -static void ttywriteraw(const char *, size_t); - -static void csidump(void); -static void csihandle(void); -static void csiparse(void); -static void csireset(void); -static void osc_color_response(int, int, int); -static int eschandle(uchar); -static void strdump(void); -static void strhandle(void); -static void strparse(void); -static void strreset(void); - -static void tprinter(char *, size_t); -static void tdumpsel(void); -static void tdumpline(int); -static void tdump(void); -static void tclearregion(int, int, int, int); -static void tcursor(int); -static void tdeletechar(int); -static void tdeleteline(int); -static void tinsertblank(int); -static void tinsertblankline(int); -static int tlinelen(int); -static void tmoveto(int, int); -static void tmoveato(int, int); -static void tnewline(int); -static void tputtab(int); -static void tputc(Rune); -static void treset(void); -static void tscrollup(int, int, int); -static void tscrolldown(int, int, int); -static void tsetattr(const int *, int); -static void tsetchar(Rune, const Glyph *, int, int); -static void tsetdirt(int, int); -static void tsetscroll(int, int); -static void tswapscreen(void); -static void tsetmode(int, int, const int *, int); -static int twrite(const char *, int, int); -static void tfulldirt(void); -static void tcontrolcode(uchar ); -static void tdectest(char ); -static void tdefutf8(char); -static int32_t tdefcolor(const int *, int *, int); -static void tdeftran(char); -static void tstrsequence(uchar); - -static void drawregion(int, int, int, int); - -static void selnormalize(void); -static void selscroll(int, int); -static void selsnap(int *, int *, int); - -static size_t utf8decode(const char *, Rune *, size_t); -static Rune utf8decodebyte(char, size_t *); -static char utf8encodebyte(Rune, size_t); -static size_t utf8validate(Rune *, size_t); - -static char *base64dec(const char *); -static char base64dec_getc(const char **); - -static ssize_t xwrite(int, const char *, size_t); - -/* Globals */ -static Term term; -static Selection sel; -static CSIEscape csiescseq; -static STREscape strescseq; -static int iofd = 1; -static int cmdfd; -static pid_t pid; - -static const uchar utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0}; -static const uchar utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; -static const Rune utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000}; -static const Rune utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; - -ssize_t -xwrite(int fd, const char *s, size_t len) -{ - size_t aux = len; - ssize_t r; - - while (len > 0) { - r = write(fd, s, len); - if (r < 0) - return r; - len -= r; - s += r; - } - - return aux; -} - -void * -xmalloc(size_t len) -{ - void *p; - - if (!(p = malloc(len))) - die("malloc: %s\n", strerror(errno)); - - return p; -} - -void * -xrealloc(void *p, size_t len) -{ - if ((p = realloc(p, len)) == NULL) - die("realloc: %s\n", strerror(errno)); - - return p; -} - -char * -xstrdup(const char *s) -{ - char *p; - - if ((p = strdup(s)) == NULL) - die("strdup: %s\n", strerror(errno)); - - return p; -} - -size_t -utf8decode(const char *c, Rune *u, size_t clen) -{ - size_t i, j, len, type; - Rune udecoded; - - *u = UTF_INVALID; - if (!clen) - return 0; - udecoded = utf8decodebyte(c[0], &len); - if (!BETWEEN(len, 1, UTF_SIZ)) - return 1; - for (i = 1, j = 1; i < clen && j < len; ++i, ++j) { - udecoded = (udecoded << 6) | utf8decodebyte(c[i], &type); - if (type != 0) - return j; - } - if (j < len) - return 0; - *u = udecoded; - utf8validate(u, len); - - return len; -} - -Rune -utf8decodebyte(char c, size_t *i) -{ - for (*i = 0; *i < LEN(utfmask); ++(*i)) - if (((uchar)c & utfmask[*i]) == utfbyte[*i]) - return (uchar)c & ~utfmask[*i]; - - return 0; -} - -size_t -utf8encode(Rune u, char *c) -{ - size_t len, i; - - len = utf8validate(&u, 0); - if (len > UTF_SIZ) - return 0; - - for (i = len - 1; i != 0; --i) { - c[i] = utf8encodebyte(u, 0); - u >>= 6; - } - c[0] = utf8encodebyte(u, len); - - return len; -} - -char -utf8encodebyte(Rune u, size_t i) -{ - return utfbyte[i] | (u & ~utfmask[i]); -} - -size_t -utf8validate(Rune *u, size_t i) -{ - if (!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF)) - *u = UTF_INVALID; - for (i = 1; *u > utfmax[i]; ++i) - ; - - return i; -} - -char -base64dec_getc(const char **src) -{ - while (**src && !isprint((unsigned char)**src)) - (*src)++; - return **src ? *((*src)++) : '='; /* emulate padding if string ends */ -} - -char * -base64dec(const char *src) -{ - size_t in_len = strlen(src); - char *result, *dst; - static const char base64_digits[256] = { - [43] = 62, 0, 0, 0, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, - 0, 0, 0, -1, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, - 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, - 0, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, - 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 - }; - - if (in_len % 4) - in_len += 4 - (in_len % 4); - result = dst = xmalloc(in_len / 4 * 3 + 1); - while (*src) { - int a = base64_digits[(unsigned char) base64dec_getc(&src)]; - int b = base64_digits[(unsigned char) base64dec_getc(&src)]; - int c = base64_digits[(unsigned char) base64dec_getc(&src)]; - int d = base64_digits[(unsigned char) base64dec_getc(&src)]; - - /* invalid input. 'a' can be -1, e.g. if src is "\n" (c-str) */ - if (a == -1 || b == -1) - break; - - *dst++ = (a << 2) | ((b & 0x30) >> 4); - if (c == -1) - break; - *dst++ = ((b & 0x0f) << 4) | ((c & 0x3c) >> 2); - if (d == -1) - break; - *dst++ = ((c & 0x03) << 6) | d; - } - *dst = '\0'; - return result; -} - -void -selinit(void) -{ - sel.mode = SEL_IDLE; - sel.snap = 0; - sel.ob.x = -1; -} - -int -tlinelen(int y) -{ - int i = term.col; - - if (TLINE(y)[i - 1].mode & ATTR_WRAP) - return i; - - while (i > 0 && TLINE(y)[i - 1].u == ' ') - --i; - - return i; -} - -void -selstart(int col, int row, int snap) -{ - selclear(); - sel.mode = SEL_EMPTY; - sel.type = SEL_REGULAR; - sel.alt = IS_SET(MODE_ALTSCREEN); - sel.snap = snap; - sel.oe.x = sel.ob.x = col; - sel.oe.y = sel.ob.y = row; - selnormalize(); - - if (sel.snap != 0) - sel.mode = SEL_READY; - tsetdirt(sel.nb.y, sel.ne.y); -} - -void -selextend(int col, int row, int type, int done) -{ - int oldey, oldex, oldsby, oldsey, oldtype; - - if (sel.mode == SEL_IDLE) - return; - if (done && sel.mode == SEL_EMPTY) { - selclear(); - return; - } - - oldey = sel.oe.y; - oldex = sel.oe.x; - oldsby = sel.nb.y; - oldsey = sel.ne.y; - oldtype = sel.type; - - sel.oe.x = col; - sel.oe.y = row; - selnormalize(); - sel.type = type; - - if (oldey != sel.oe.y || oldex != sel.oe.x || oldtype != sel.type || sel.mode == SEL_EMPTY) - tsetdirt(MIN(sel.nb.y, oldsby), MAX(sel.ne.y, oldsey)); - - sel.mode = done ? SEL_IDLE : SEL_READY; -} - -void -selnormalize(void) -{ - int i; - - if (sel.type == SEL_REGULAR && sel.ob.y != sel.oe.y) { - sel.nb.x = sel.ob.y < sel.oe.y ? sel.ob.x : sel.oe.x; - sel.ne.x = sel.ob.y < sel.oe.y ? sel.oe.x : sel.ob.x; - } else { - sel.nb.x = MIN(sel.ob.x, sel.oe.x); - sel.ne.x = MAX(sel.ob.x, sel.oe.x); - } - sel.nb.y = MIN(sel.ob.y, sel.oe.y); - sel.ne.y = MAX(sel.ob.y, sel.oe.y); - - selsnap(&sel.nb.x, &sel.nb.y, -1); - selsnap(&sel.ne.x, &sel.ne.y, +1); - - /* expand selection over line breaks */ - if (sel.type == SEL_RECTANGULAR) - return; - i = tlinelen(sel.nb.y); - if (i < sel.nb.x) - sel.nb.x = i; - if (tlinelen(sel.ne.y) <= sel.ne.x) - sel.ne.x = term.col - 1; -} - -int -selected(int x, int y) -{ - if (sel.mode == SEL_EMPTY || sel.ob.x == -1 || - sel.alt != IS_SET(MODE_ALTSCREEN)) - return 0; - - if (sel.type == SEL_RECTANGULAR) - return BETWEEN(y, sel.nb.y, sel.ne.y) - && BETWEEN(x, sel.nb.x, sel.ne.x); - - return BETWEEN(y, sel.nb.y, sel.ne.y) - && (y != sel.nb.y || x >= sel.nb.x) - && (y != sel.ne.y || x <= sel.ne.x); -} - -void -selsnap(int *x, int *y, int direction) -{ - int newx, newy, xt, yt; - int delim, prevdelim; - const Glyph *gp, *prevgp; - - switch (sel.snap) { - case SNAP_WORD: - /* - * Snap around if the word wraps around at the end or - * beginning of a line. - */ - prevgp = &TLINE(*y)[*x]; - prevdelim = ISDELIM(prevgp->u); - for (;;) { - newx = *x + direction; - newy = *y; - if (!BETWEEN(newx, 0, term.col - 1)) { - newy += direction; - newx = (newx + term.col) % term.col; - if (!BETWEEN(newy, 0, term.row - 1)) - break; - - if (direction > 0) - yt = *y, xt = *x; - else - yt = newy, xt = newx; - if (!(TLINE(yt)[xt].mode & ATTR_WRAP)) - break; - } - - if (newx >= tlinelen(newy)) - break; - - gp = &TLINE(newy)[newx]; - delim = ISDELIM(gp->u); - if (!(gp->mode & ATTR_WDUMMY) && (delim != prevdelim - || (delim && gp->u != prevgp->u))) - break; - - *x = newx; - *y = newy; - prevgp = gp; - prevdelim = delim; - } - break; - case SNAP_LINE: - /* - * Snap around if the the previous line or the current one - * has set ATTR_WRAP at its end. Then the whole next or - * previous line will be selected. - */ - *x = (direction < 0) ? 0 : term.col - 1; - if (direction < 0) { - for (; *y > 0; *y += direction) { - if (!(TLINE(*y-1)[term.col-1].mode - & ATTR_WRAP)) { - break; - } - } - } else if (direction > 0) { - for (; *y < term.row-1; *y += direction) { - if (!(TLINE(*y)[term.col-1].mode - & ATTR_WRAP)) { - break; - } - } - } - break; - } -} - -char * -getsel(void) -{ - char *str, *ptr; - int y, bufsize, lastx, linelen; - const Glyph *gp, *last; - - if (sel.ob.x == -1) - return NULL; - - bufsize = (term.col+1) * (sel.ne.y-sel.nb.y+1) * UTF_SIZ; - ptr = str = xmalloc(bufsize); - - /* append every set & selected glyph to the selection */ - for (y = sel.nb.y; y <= sel.ne.y; y++) { - if ((linelen = tlinelen(y)) == 0) { - *ptr++ = '\n'; - continue; - } - - if (sel.type == SEL_RECTANGULAR) { - gp = &TLINE(y)[sel.nb.x]; - lastx = sel.ne.x; - } else { - gp = &TLINE(y)[sel.nb.y == y ? sel.nb.x : 0]; - lastx = (sel.ne.y == y) ? sel.ne.x : term.col-1; - } - last = &TLINE(y)[MIN(lastx, linelen-1)]; - while (last >= gp && last->u == ' ') - --last; - - for ( ; gp <= last; ++gp) { - if (gp->mode & ATTR_WDUMMY) - continue; - - ptr += utf8encode(gp->u, ptr); - } - - /* - * Copy and pasting of line endings is inconsistent - * in the inconsistent terminal and GUI world. - * The best solution seems like to produce '\n' when - * something is copied from st and convert '\n' to - * '\r', when something to be pasted is received by - * st. - * FIXME: Fix the computer world. - */ - if ((y < sel.ne.y || lastx >= linelen) && - (!(last->mode & ATTR_WRAP) || sel.type == SEL_RECTANGULAR)) - *ptr++ = '\n'; - } - *ptr = 0; - return str; -} - -void -selclear(void) -{ - if (sel.ob.x == -1) - return; - sel.mode = SEL_IDLE; - sel.ob.x = -1; - tsetdirt(sel.nb.y, sel.ne.y); -} - -void -die(const char *errstr, ...) -{ - va_list ap; - - va_start(ap, errstr); - vfprintf(stderr, errstr, ap); - va_end(ap); - exit(1); -} - -void -execsh(char *cmd, char **args) -{ - char *sh, *prog, *arg; - const struct passwd *pw; - - errno = 0; - if ((pw = getpwuid(getuid())) == NULL) { - if (errno) - die("getpwuid: %s\n", strerror(errno)); - else - die("who are you?\n"); - } - - if ((sh = getenv("SHELL")) == NULL) - sh = (pw->pw_shell[0]) ? pw->pw_shell : cmd; - - if (args) { - prog = args[0]; - arg = NULL; - } else if (scroll) { - prog = scroll; - arg = utmp ? utmp : sh; - } else if (utmp) { - prog = utmp; - arg = NULL; - } else { - prog = sh; - arg = NULL; - } - DEFAULT(args, ((char *[]) {prog, arg, NULL})); - - unsetenv("COLUMNS"); - unsetenv("LINES"); - unsetenv("TERMCAP"); - setenv("LOGNAME", pw->pw_name, 1); - setenv("USER", pw->pw_name, 1); - setenv("SHELL", sh, 1); - setenv("HOME", pw->pw_dir, 1); - setenv("TERM", termname, 1); - - signal(SIGCHLD, SIG_DFL); - signal(SIGHUP, SIG_DFL); - signal(SIGINT, SIG_DFL); - signal(SIGQUIT, SIG_DFL); - signal(SIGTERM, SIG_DFL); - signal(SIGALRM, SIG_DFL); - - execvp(prog, args); - _exit(1); -} - -void -sigchld(int a) -{ - int stat; - pid_t p; - - if ((p = waitpid(pid, &stat, WNOHANG)) < 0) - die("waiting for pid %hd failed: %s\n", pid, strerror(errno)); - - if (pid != p) - return; - - if (WIFEXITED(stat) && WEXITSTATUS(stat)) - die("child exited with status %d\n", WEXITSTATUS(stat)); - else if (WIFSIGNALED(stat)) - die("child terminated due to signal %d\n", WTERMSIG(stat)); - _exit(0); -} - -void -stty(char **args) -{ - char cmd[_POSIX_ARG_MAX], **p, *q, *s; - size_t n, siz; - - if ((n = strlen(stty_args)) > sizeof(cmd)-1) - die("incorrect stty parameters\n"); - memcpy(cmd, stty_args, n); - q = cmd + n; - siz = sizeof(cmd) - n; - for (p = args; p && (s = *p); ++p) { - if ((n = strlen(s)) > siz-1) - die("stty parameter length too long\n"); - *q++ = ' '; - memcpy(q, s, n); - q += n; - siz -= n + 1; - } - *q = '\0'; - if (system(cmd) != 0) - perror("Couldn't call stty"); -} - -int -ttynew(const char *line, char *cmd, const char *out, char **args) -{ - int m, s; - - if (out) { - term.mode |= MODE_PRINT; - iofd = (!strcmp(out, "-")) ? - 1 : open(out, O_WRONLY | O_CREAT, 0666); - if (iofd < 0) { - fprintf(stderr, "Error opening %s:%s\n", - out, strerror(errno)); - } - } - - if (line) { - if ((cmdfd = open(line, O_RDWR)) < 0) - die("open line '%s' failed: %s\n", - line, strerror(errno)); - dup2(cmdfd, 0); - stty(args); - return cmdfd; - } - - /* seems to work fine on linux, openbsd and freebsd */ - if (openpty(&m, &s, NULL, NULL, NULL) < 0) - die("openpty failed: %s\n", strerror(errno)); - - switch (pid = fork()) { - case -1: - die("fork failed: %s\n", strerror(errno)); - break; - case 0: - close(iofd); - close(m); - setsid(); /* create a new process group */ - dup2(s, 0); - dup2(s, 1); - dup2(s, 2); - if (ioctl(s, TIOCSCTTY, NULL) < 0) - die("ioctl TIOCSCTTY failed: %s\n", strerror(errno)); - if (s > 2) - close(s); -#ifdef __OpenBSD__ - if (pledge("stdio getpw proc exec", NULL) == -1) - die("pledge\n"); -#endif - execsh(cmd, args); - break; - default: -#ifdef __OpenBSD__ - if (pledge("stdio rpath tty proc", NULL) == -1) - die("pledge\n"); -#endif - close(s); - cmdfd = m; - signal(SIGCHLD, sigchld); - break; - } - return cmdfd; -} - -size_t -ttyread(void) -{ - static char buf[BUFSIZ]; - static int buflen = 0; - int ret, written; - - /* append read bytes to unprocessed bytes */ - ret = read(cmdfd, buf+buflen, LEN(buf)-buflen); - - switch (ret) { - case 0: - exit(0); - case -1: - die("couldn't read from shell: %s\n", strerror(errno)); - default: - buflen += ret; - written = twrite(buf, buflen, 0); - buflen -= written; - /* keep any incomplete UTF-8 byte sequence for the next call */ - if (buflen > 0) - memmove(buf, buf + written, buflen); - return ret; - } -} - -void -ttywrite(const char *s, size_t n, int may_echo) -{ - const char *next; - Arg arg = (Arg) { .i = term.scr }; - - kscrolldown(&arg); - - if (may_echo && IS_SET(MODE_ECHO)) - twrite(s, n, 1); - - if (!IS_SET(MODE_CRLF)) { - ttywriteraw(s, n); - return; - } - - /* This is similar to how the kernel handles ONLCR for ttys */ - while (n > 0) { - if (*s == '\r') { - next = s + 1; - ttywriteraw("\r\n", 2); - } else { - next = memchr(s, '\r', n); - DEFAULT(next, s + n); - ttywriteraw(s, next - s); - } - n -= next - s; - s = next; - } -} - -void -ttywriteraw(const char *s, size_t n) -{ - fd_set wfd, rfd; - ssize_t r; - size_t lim = 256; - - /* - * Remember that we are using a pty, which might be a modem line. - * Writing too much will clog the line. That's why we are doing this - * dance. - * FIXME: Migrate the world to Plan 9. - */ - while (n > 0) { - FD_ZERO(&wfd); - FD_ZERO(&rfd); - FD_SET(cmdfd, &wfd); - FD_SET(cmdfd, &rfd); - - /* Check if we can write. */ - if (pselect(cmdfd+1, &rfd, &wfd, NULL, NULL, NULL) < 0) { - if (errno == EINTR) - continue; - die("select failed: %s\n", strerror(errno)); - } - if (FD_ISSET(cmdfd, &wfd)) { - /* - * Only write the bytes written by ttywrite() or the - * default of 256. This seems to be a reasonable value - * for a serial line. Bigger values might clog the I/O. - */ - if ((r = write(cmdfd, s, (n < lim)? n : lim)) < 0) - goto write_error; - if (r < n) { - /* - * We weren't able to write out everything. - * This means the buffer is getting full - * again. Empty it. - */ - if (n < lim) - lim = ttyread(); - n -= r; - s += r; - } else { - /* All bytes have been written. */ - break; - } - } - if (FD_ISSET(cmdfd, &rfd)) - lim = ttyread(); - } - return; - -write_error: - die("write error on tty: %s\n", strerror(errno)); -} - -void -ttyresize(int tw, int th) -{ - struct winsize w; - - w.ws_row = term.row; - w.ws_col = term.col; - w.ws_xpixel = tw; - w.ws_ypixel = th; - if (ioctl(cmdfd, TIOCSWINSZ, &w) < 0) - fprintf(stderr, "Couldn't set window size: %s\n", strerror(errno)); -} - -void -ttyhangup(void) -{ - /* Send SIGHUP to shell */ - kill(pid, SIGHUP); -} - -int -tattrset(int attr) -{ - int i, j; - - for (i = 0; i < term.row-1; i++) { - for (j = 0; j < term.col-1; j++) { - if (term.line[i][j].mode & attr) - return 1; - } - } - - return 0; -} - -void -tsetdirt(int top, int bot) -{ - int i; - - LIMIT(top, 0, term.row-1); - LIMIT(bot, 0, term.row-1); - - for (i = top; i <= bot; i++) - term.dirty[i] = 1; -} - -void -tsetdirtattr(int attr) -{ - int i, j; - - for (i = 0; i < term.row-1; i++) { - for (j = 0; j < term.col-1; j++) { - if (term.line[i][j].mode & attr) { - tsetdirt(i, i); - break; - } - } - } -} - -void -tfulldirt(void) -{ - tsetdirt(0, term.row-1); -} - -void -tcursor(int mode) -{ - static TCursor c[2]; - int alt = IS_SET(MODE_ALTSCREEN); - - if (mode == CURSOR_SAVE) { - c[alt] = term.c; - } else if (mode == CURSOR_LOAD) { - term.c = c[alt]; - tmoveto(c[alt].x, c[alt].y); - } -} - -void -treset(void) -{ - uint i; - - term.c = (TCursor){{ - .mode = ATTR_NULL, - .fg = defaultfg, - .bg = defaultbg - }, .x = 0, .y = 0, .state = CURSOR_DEFAULT}; - - memset(term.tabs, 0, term.col * sizeof(*term.tabs)); - for (i = tabspaces; i < term.col; i += tabspaces) - term.tabs[i] = 1; - term.top = 0; - term.bot = term.row - 1; - term.mode = MODE_WRAP|MODE_UTF8; - memset(term.trantbl, CS_USA, sizeof(term.trantbl)); - term.charset = 0; - - for (i = 0; i < 2; i++) { - tmoveto(0, 0); - tcursor(CURSOR_SAVE); - tclearregion(0, 0, term.col-1, term.row-1); - tswapscreen(); - } -} - -void -tnew(int col, int row) -{ - term = (Term){ .c = { .attr = { .fg = defaultfg, .bg = defaultbg } } }; - tresize(col, row); - treset(); -} - -void -tswapscreen(void) -{ - Line *tmp = term.line; - - term.line = term.alt; - term.alt = tmp; - term.mode ^= MODE_ALTSCREEN; - tfulldirt(); -} - -void -kscrolldown(const Arg* a) -{ - int n = a->i; - - if (n < 0) - n = term.row + n; - - if (n > term.scr) - n = term.scr; - - if (term.scr > 0) { - term.scr -= n; - selscroll(0, -n); - tfulldirt(); - } -} - -void -kscrollup(const Arg* a) -{ - int n = a->i; - - if (n < 0) - n = term.row + n; - - if (term.scr <= HISTSIZE-n) { - term.scr += n; - selscroll(0, n); - tfulldirt(); - } -} - -void -tscrolldown(int orig, int n, int copyhist) -{ - int i; - Line temp; - - LIMIT(n, 0, term.bot-orig+1); - if (copyhist) { - term.histi = (term.histi - 1 + HISTSIZE) % HISTSIZE; - temp = term.hist[term.histi]; - term.hist[term.histi] = term.line[term.bot]; - term.line[term.bot] = temp; - } - - - tsetdirt(orig, term.bot-n); - tclearregion(0, term.bot-n+1, term.col-1, term.bot); - - for (i = term.bot; i >= orig+n; i--) { - temp = term.line[i]; - term.line[i] = term.line[i-n]; - term.line[i-n] = temp; - } - - if (term.scr == 0) - selscroll(orig, n); -} - -void -tscrollup(int orig, int n, int copyhist) -{ - int i; - Line temp; - - LIMIT(n, 0, term.bot-orig+1); - - if (copyhist) { - term.histi = (term.histi + 1) % HISTSIZE; - temp = term.hist[term.histi]; - term.hist[term.histi] = term.line[orig]; - term.line[orig] = temp; - } - - if (term.scr > 0 && term.scr < HISTSIZE) - term.scr = MIN(term.scr + n, HISTSIZE-1); - - tclearregion(0, orig, term.col-1, orig+n-1); - tsetdirt(orig+n, term.bot); - - for (i = orig; i <= term.bot-n; i++) { - temp = term.line[i]; - term.line[i] = term.line[i+n]; - term.line[i+n] = temp; - } - - if (term.scr == 0) - selscroll(orig, -n); -} - -void -selscroll(int orig, int n) -{ - if (sel.ob.x == -1) - return; - - if (BETWEEN(sel.nb.y, orig, term.bot) != BETWEEN(sel.ne.y, orig, term.bot)) { - selclear(); - } else if (BETWEEN(sel.nb.y, orig, term.bot)) { - sel.ob.y += n; - sel.oe.y += n; - if (sel.ob.y < term.top || sel.ob.y > term.bot || - sel.oe.y < term.top || sel.oe.y > term.bot) { - selclear(); - } else { - selnormalize(); - } - } -} - -void -tnewline(int first_col) -{ - int y = term.c.y; - - if (y == term.bot) { - tscrollup(term.top, 1, 1); - } else { - y++; - } - tmoveto(first_col ? 0 : term.c.x, y); -} - -void -csiparse(void) -{ - char *p = csiescseq.buf, *np; - long int v; - - csiescseq.narg = 0; - if (*p == '?') { - csiescseq.priv = 1; - p++; - } - - csiescseq.buf[csiescseq.len] = '\0'; - while (p < csiescseq.buf+csiescseq.len) { - np = NULL; - v = strtol(p, &np, 10); - if (np == p) - v = 0; - if (v == LONG_MAX || v == LONG_MIN) - v = -1; - csiescseq.arg[csiescseq.narg++] = v; - p = np; - if (*p != ';' || csiescseq.narg == ESC_ARG_SIZ) - break; - p++; - } - csiescseq.mode[0] = *p++; - csiescseq.mode[1] = (p < csiescseq.buf+csiescseq.len) ? *p : '\0'; -} - -/* for absolute user moves, when decom is set */ -void -tmoveato(int x, int y) -{ - tmoveto(x, y + ((term.c.state & CURSOR_ORIGIN) ? term.top: 0)); -} - -void -tmoveto(int x, int y) -{ - int miny, maxy; - - if (term.c.state & CURSOR_ORIGIN) { - miny = term.top; - maxy = term.bot; - } else { - miny = 0; - maxy = term.row - 1; - } - term.c.state &= ~CURSOR_WRAPNEXT; - term.c.x = LIMIT(x, 0, term.col-1); - term.c.y = LIMIT(y, miny, maxy); -} - -void -tsetchar(Rune u, const Glyph *attr, int x, int y) -{ - static const char *vt100_0[62] = { /* 0x41 - 0x7e */ - "↑", "↓", "→", "←", "█", "▚", "☃", /* A - G */ - 0, 0, 0, 0, 0, 0, 0, 0, /* H - O */ - 0, 0, 0, 0, 0, 0, 0, 0, /* P - W */ - 0, 0, 0, 0, 0, 0, 0, " ", /* X - _ */ - "◆", "▒", "␉", "␌", "␍", "␊", "°", "±", /* ` - g */ - "", "␋", "┘", "┐", "┌", "└", "┼", "⎺", /* h - o */ - "⎻", "─", "⎼", "⎽", "├", "┤", "┴", "┬", /* p - w */ - "│", "≤", "≥", "π", "≠", "£", "·", /* x - ~ */ - }; - - /* - * The table is proudly stolen from rxvt. - */ - if (term.trantbl[term.charset] == CS_GRAPHIC0 && - BETWEEN(u, 0x41, 0x7e) && vt100_0[u - 0x41]) - utf8decode(vt100_0[u - 0x41], &u, UTF_SIZ); - - if (term.line[y][x].mode & ATTR_WIDE) { - if (x+1 < term.col) { - term.line[y][x+1].u = ' '; - term.line[y][x+1].mode &= ~ATTR_WDUMMY; - } - } else if (term.line[y][x].mode & ATTR_WDUMMY) { - term.line[y][x-1].u = ' '; - term.line[y][x-1].mode &= ~ATTR_WIDE; - } - - term.dirty[y] = 1; - term.line[y][x] = *attr; - term.line[y][x].u = u; -} - -void -tclearregion(int x1, int y1, int x2, int y2) -{ - int x, y, temp; - Glyph *gp; - - if (x1 > x2) - temp = x1, x1 = x2, x2 = temp; - if (y1 > y2) - temp = y1, y1 = y2, y2 = temp; - - LIMIT(x1, 0, term.col-1); - LIMIT(x2, 0, term.col-1); - LIMIT(y1, 0, term.row-1); - LIMIT(y2, 0, term.row-1); - - for (y = y1; y <= y2; y++) { - term.dirty[y] = 1; - for (x = x1; x <= x2; x++) { - gp = &term.line[y][x]; - if (selected(x, y)) - selclear(); - gp->fg = term.c.attr.fg; - gp->bg = term.c.attr.bg; - gp->mode = 0; - gp->u = ' '; - } - } -} - -void -tdeletechar(int n) -{ - int dst, src, size; - Glyph *line; - - LIMIT(n, 0, term.col - term.c.x); - - dst = term.c.x; - src = term.c.x + n; - size = term.col - src; - line = term.line[term.c.y]; - - memmove(&line[dst], &line[src], size * sizeof(Glyph)); - tclearregion(term.col-n, term.c.y, term.col-1, term.c.y); -} - -void -tinsertblank(int n) -{ - int dst, src, size; - Glyph *line; - - LIMIT(n, 0, term.col - term.c.x); - - dst = term.c.x + n; - src = term.c.x; - size = term.col - dst; - line = term.line[term.c.y]; - - memmove(&line[dst], &line[src], size * sizeof(Glyph)); - tclearregion(src, term.c.y, dst - 1, term.c.y); -} - -void -tinsertblankline(int n) -{ - if (BETWEEN(term.c.y, term.top, term.bot)) - tscrolldown(term.c.y, n, 0); -} - -void -tdeleteline(int n) -{ - if (BETWEEN(term.c.y, term.top, term.bot)) - tscrollup(term.c.y, n, 0); -} - -int32_t -tdefcolor(const int *attr, int *npar, int l) -{ - int32_t idx = -1; - uint r, g, b; - - switch (attr[*npar + 1]) { - case 2: /* direct color in RGB space */ - if (*npar + 4 >= l) { - fprintf(stderr, - "erresc(38): Incorrect number of parameters (%d)\n", - *npar); - break; - } - r = attr[*npar + 2]; - g = attr[*npar + 3]; - b = attr[*npar + 4]; - *npar += 4; - if (!BETWEEN(r, 0, 255) || !BETWEEN(g, 0, 255) || !BETWEEN(b, 0, 255)) - fprintf(stderr, "erresc: bad rgb color (%u,%u,%u)\n", - r, g, b); - else - idx = TRUECOLOR(r, g, b); - break; - case 5: /* indexed color */ - if (*npar + 2 >= l) { - fprintf(stderr, - "erresc(38): Incorrect number of parameters (%d)\n", - *npar); - break; - } - *npar += 2; - if (!BETWEEN(attr[*npar], 0, 255)) - fprintf(stderr, "erresc: bad fgcolor %d\n", attr[*npar]); - else - idx = attr[*npar]; - break; - case 0: /* implemented defined (only foreground) */ - case 1: /* transparent */ - case 3: /* direct color in CMY space */ - case 4: /* direct color in CMYK space */ - default: - fprintf(stderr, - "erresc(38): gfx attr %d unknown\n", attr[*npar]); - break; - } - - return idx; -} - -void -tsetattr(const int *attr, int l) -{ - int i; - int32_t idx; - - for (i = 0; i < l; i++) { - switch (attr[i]) { - case 0: - term.c.attr.mode &= ~( - ATTR_BOLD | - ATTR_FAINT | - ATTR_ITALIC | - ATTR_UNDERLINE | - ATTR_BLINK | - ATTR_REVERSE | - ATTR_INVISIBLE | - ATTR_STRUCK ); - term.c.attr.fg = defaultfg; - term.c.attr.bg = defaultbg; - break; - case 1: - term.c.attr.mode |= ATTR_BOLD; - break; - case 2: - term.c.attr.mode |= ATTR_FAINT; - break; - case 3: - term.c.attr.mode |= ATTR_ITALIC; - break; - case 4: - term.c.attr.mode |= ATTR_UNDERLINE; - break; - case 5: /* slow blink */ - /* FALLTHROUGH */ - case 6: /* rapid blink */ - term.c.attr.mode |= ATTR_BLINK; - break; - case 7: - term.c.attr.mode |= ATTR_REVERSE; - break; - case 8: - term.c.attr.mode |= ATTR_INVISIBLE; - break; - case 9: - term.c.attr.mode |= ATTR_STRUCK; - break; - case 22: - term.c.attr.mode &= ~(ATTR_BOLD | ATTR_FAINT); - break; - case 23: - term.c.attr.mode &= ~ATTR_ITALIC; - break; - case 24: - term.c.attr.mode &= ~ATTR_UNDERLINE; - break; - case 25: - term.c.attr.mode &= ~ATTR_BLINK; - break; - case 27: - term.c.attr.mode &= ~ATTR_REVERSE; - break; - case 28: - term.c.attr.mode &= ~ATTR_INVISIBLE; - break; - case 29: - term.c.attr.mode &= ~ATTR_STRUCK; - break; - case 38: - if ((idx = tdefcolor(attr, &i, l)) >= 0) - term.c.attr.fg = idx; - break; - case 39: - term.c.attr.fg = defaultfg; - break; - case 48: - if ((idx = tdefcolor(attr, &i, l)) >= 0) - term.c.attr.bg = idx; - break; - case 49: - term.c.attr.bg = defaultbg; - break; - default: - if (BETWEEN(attr[i], 30, 37)) { - term.c.attr.fg = attr[i] - 30; - } else if (BETWEEN(attr[i], 40, 47)) { - term.c.attr.bg = attr[i] - 40; - } else if (BETWEEN(attr[i], 90, 97)) { - term.c.attr.fg = attr[i] - 90 + 8; - } else if (BETWEEN(attr[i], 100, 107)) { - term.c.attr.bg = attr[i] - 100 + 8; - } else { - fprintf(stderr, - "erresc(default): gfx attr %d unknown\n", - attr[i]); - csidump(); - } - break; - } - } -} - -void -tsetscroll(int t, int b) -{ - int temp; - - LIMIT(t, 0, term.row-1); - LIMIT(b, 0, term.row-1); - if (t > b) { - temp = t; - t = b; - b = temp; - } - term.top = t; - term.bot = b; -} - -void -tsetmode(int priv, int set, const int *args, int narg) -{ - int alt; const int *lim; - - for (lim = args + narg; args < lim; ++args) { - if (priv) { - switch (*args) { - case 1: /* DECCKM -- Cursor key */ - xsetmode(set, MODE_APPCURSOR); - break; - case 5: /* DECSCNM -- Reverse video */ - xsetmode(set, MODE_REVERSE); - break; - case 6: /* DECOM -- Origin */ - MODBIT(term.c.state, set, CURSOR_ORIGIN); - tmoveato(0, 0); - break; - case 7: /* DECAWM -- Auto wrap */ - MODBIT(term.mode, set, MODE_WRAP); - break; - case 0: /* Error (IGNORED) */ - case 2: /* DECANM -- ANSI/VT52 (IGNORED) */ - case 3: /* DECCOLM -- Column (IGNORED) */ - case 4: /* DECSCLM -- Scroll (IGNORED) */ - case 8: /* DECARM -- Auto repeat (IGNORED) */ - case 18: /* DECPFF -- Printer feed (IGNORED) */ - case 19: /* DECPEX -- Printer extent (IGNORED) */ - case 42: /* DECNRCM -- National characters (IGNORED) */ - case 12: /* att610 -- Start blinking cursor (IGNORED) */ - break; - case 25: /* DECTCEM -- Text Cursor Enable Mode */ - xsetmode(!set, MODE_HIDE); - break; - case 9: /* X10 mouse compatibility mode */ - xsetpointermotion(0); - xsetmode(0, MODE_MOUSE); - xsetmode(set, MODE_MOUSEX10); - break; - case 1000: /* 1000: report button press */ - xsetpointermotion(0); - xsetmode(0, MODE_MOUSE); - xsetmode(set, MODE_MOUSEBTN); - break; - case 1002: /* 1002: report motion on button press */ - xsetpointermotion(0); - xsetmode(0, MODE_MOUSE); - xsetmode(set, MODE_MOUSEMOTION); - break; - case 1003: /* 1003: enable all mouse motions */ - xsetpointermotion(set); - xsetmode(0, MODE_MOUSE); - xsetmode(set, MODE_MOUSEMANY); - break; - case 1004: /* 1004: send focus events to tty */ - xsetmode(set, MODE_FOCUS); - break; - case 1006: /* 1006: extended reporting mode */ - xsetmode(set, MODE_MOUSESGR); - break; - case 1034: - xsetmode(set, MODE_8BIT); - break; - case 1049: /* swap screen & set/restore cursor as xterm */ - if (!allowaltscreen) - break; - tcursor((set) ? CURSOR_SAVE : CURSOR_LOAD); - /* FALLTHROUGH */ - case 47: /* swap screen */ - case 1047: - if (!allowaltscreen) - break; - alt = IS_SET(MODE_ALTSCREEN); - if (alt) { - tclearregion(0, 0, term.col-1, - term.row-1); - } - if (set ^ alt) /* set is always 1 or 0 */ - tswapscreen(); - if (*args != 1049) - break; - /* FALLTHROUGH */ - case 1048: - tcursor((set) ? CURSOR_SAVE : CURSOR_LOAD); - break; - case 2004: /* 2004: bracketed paste mode */ - xsetmode(set, MODE_BRCKTPASTE); - break; - /* Not implemented mouse modes. See comments there. */ - case 1001: /* mouse highlight mode; can hang the - terminal by design when implemented. */ - case 1005: /* UTF-8 mouse mode; will confuse - applications not supporting UTF-8 - and luit. */ - case 1015: /* urxvt mangled mouse mode; incompatible - and can be mistaken for other control - codes. */ - break; - default: - fprintf(stderr, - "erresc: unknown private set/reset mode %d\n", - *args); - break; - } - } else { - switch (*args) { - case 0: /* Error (IGNORED) */ - break; - case 2: - xsetmode(set, MODE_KBDLOCK); - break; - case 4: /* IRM -- Insertion-replacement */ - MODBIT(term.mode, set, MODE_INSERT); - break; - case 12: /* SRM -- Send/Receive */ - MODBIT(term.mode, !set, MODE_ECHO); - break; - case 20: /* LNM -- Linefeed/new line */ - MODBIT(term.mode, set, MODE_CRLF); - break; - default: - fprintf(stderr, - "erresc: unknown set/reset mode %d\n", - *args); - break; - } - } - } -} - -void -csihandle(void) -{ - char buf[40]; - int len; - - switch (csiescseq.mode[0]) { - default: - unknown: - fprintf(stderr, "erresc: unknown csi "); - csidump(); - /* die(""); */ - break; - case '@': /* ICH -- Insert <n> blank char */ - DEFAULT(csiescseq.arg[0], 1); - tinsertblank(csiescseq.arg[0]); - break; - case 'A': /* CUU -- Cursor <n> Up */ - DEFAULT(csiescseq.arg[0], 1); - tmoveto(term.c.x, term.c.y-csiescseq.arg[0]); - break; - case 'B': /* CUD -- Cursor <n> Down */ - case 'e': /* VPR --Cursor <n> Down */ - DEFAULT(csiescseq.arg[0], 1); - tmoveto(term.c.x, term.c.y+csiescseq.arg[0]); - break; - case 'i': /* MC -- Media Copy */ - switch (csiescseq.arg[0]) { - case 0: - tdump(); - break; - case 1: - tdumpline(term.c.y); - break; - case 2: - tdumpsel(); - break; - case 4: - term.mode &= ~MODE_PRINT; - break; - case 5: - term.mode |= MODE_PRINT; - break; - } - break; - case 'c': /* DA -- Device Attributes */ - if (csiescseq.arg[0] == 0) - ttywrite(vtiden, strlen(vtiden), 0); - break; - case 'b': /* REP -- if last char is printable print it <n> more times */ - DEFAULT(csiescseq.arg[0], 1); - if (term.lastc) - while (csiescseq.arg[0]-- > 0) - tputc(term.lastc); - break; - case 'C': /* CUF -- Cursor <n> Forward */ - case 'a': /* HPR -- Cursor <n> Forward */ - DEFAULT(csiescseq.arg[0], 1); - tmoveto(term.c.x+csiescseq.arg[0], term.c.y); - break; - case 'D': /* CUB -- Cursor <n> Backward */ - DEFAULT(csiescseq.arg[0], 1); - tmoveto(term.c.x-csiescseq.arg[0], term.c.y); - break; - case 'E': /* CNL -- Cursor <n> Down and first col */ - DEFAULT(csiescseq.arg[0], 1); - tmoveto(0, term.c.y+csiescseq.arg[0]); - break; - case 'F': /* CPL -- Cursor <n> Up and first col */ - DEFAULT(csiescseq.arg[0], 1); - tmoveto(0, term.c.y-csiescseq.arg[0]); - break; - case 'g': /* TBC -- Tabulation clear */ - switch (csiescseq.arg[0]) { - case 0: /* clear current tab stop */ - term.tabs[term.c.x] = 0; - break; - case 3: /* clear all the tabs */ - memset(term.tabs, 0, term.col * sizeof(*term.tabs)); - break; - default: - goto unknown; - } - break; - case 'G': /* CHA -- Move to <col> */ - case '`': /* HPA */ - DEFAULT(csiescseq.arg[0], 1); - tmoveto(csiescseq.arg[0]-1, term.c.y); - break; - case 'H': /* CUP -- Move to <row> <col> */ - case 'f': /* HVP */ - DEFAULT(csiescseq.arg[0], 1); - DEFAULT(csiescseq.arg[1], 1); - tmoveato(csiescseq.arg[1]-1, csiescseq.arg[0]-1); - break; - case 'I': /* CHT -- Cursor Forward Tabulation <n> tab stops */ - DEFAULT(csiescseq.arg[0], 1); - tputtab(csiescseq.arg[0]); - break; - case 'J': /* ED -- Clear screen */ - switch (csiescseq.arg[0]) { - case 0: /* below */ - tclearregion(term.c.x, term.c.y, term.col-1, term.c.y); - if (term.c.y < term.row-1) { - tclearregion(0, term.c.y+1, term.col-1, - term.row-1); - } - break; - case 1: /* above */ - if (term.c.y > 1) - tclearregion(0, 0, term.col-1, term.c.y-1); - tclearregion(0, term.c.y, term.c.x, term.c.y); - break; - case 2: /* all */ - tclearregion(0, 0, term.col-1, term.row-1); - break; - default: - goto unknown; - } - break; - case 'K': /* EL -- Clear line */ - switch (csiescseq.arg[0]) { - case 0: /* right */ - tclearregion(term.c.x, term.c.y, term.col-1, - term.c.y); - break; - case 1: /* left */ - tclearregion(0, term.c.y, term.c.x, term.c.y); - break; - case 2: /* all */ - tclearregion(0, term.c.y, term.col-1, term.c.y); - break; - } - break; - case 'S': /* SU -- Scroll <n> line up */ - DEFAULT(csiescseq.arg[0], 1); - tscrollup(term.top, csiescseq.arg[0], 0); - break; - case 'T': /* SD -- Scroll <n> line down */ - DEFAULT(csiescseq.arg[0], 1); - tscrolldown(term.top, csiescseq.arg[0], 0); - break; - case 'L': /* IL -- Insert <n> blank lines */ - DEFAULT(csiescseq.arg[0], 1); - tinsertblankline(csiescseq.arg[0]); - break; - case 'l': /* RM -- Reset Mode */ - tsetmode(csiescseq.priv, 0, csiescseq.arg, csiescseq.narg); - break; - case 'M': /* DL -- Delete <n> lines */ - DEFAULT(csiescseq.arg[0], 1); - tdeleteline(csiescseq.arg[0]); - break; - case 'X': /* ECH -- Erase <n> char */ - DEFAULT(csiescseq.arg[0], 1); - tclearregion(term.c.x, term.c.y, - term.c.x + csiescseq.arg[0] - 1, term.c.y); - break; - case 'P': /* DCH -- Delete <n> char */ - DEFAULT(csiescseq.arg[0], 1); - tdeletechar(csiescseq.arg[0]); - break; - case 'Z': /* CBT -- Cursor Backward Tabulation <n> tab stops */ - DEFAULT(csiescseq.arg[0], 1); - tputtab(-csiescseq.arg[0]); - break; - case 'd': /* VPA -- Move to <row> */ - DEFAULT(csiescseq.arg[0], 1); - tmoveato(term.c.x, csiescseq.arg[0]-1); - break; - case 'h': /* SM -- Set terminal mode */ - tsetmode(csiescseq.priv, 1, csiescseq.arg, csiescseq.narg); - break; - case 'm': /* SGR -- Terminal attribute (color) */ - tsetattr(csiescseq.arg, csiescseq.narg); - break; - case 'n': /* DSR – Device Status Report (cursor position) */ - if (csiescseq.arg[0] == 6) { - len = snprintf(buf, sizeof(buf), "\033[%i;%iR", - term.c.y+1, term.c.x+1); - ttywrite(buf, len, 0); - } - break; - case 'r': /* DECSTBM -- Set Scrolling Region */ - if (csiescseq.priv) { - goto unknown; - } else { - DEFAULT(csiescseq.arg[0], 1); - DEFAULT(csiescseq.arg[1], term.row); - tsetscroll(csiescseq.arg[0]-1, csiescseq.arg[1]-1); - tmoveato(0, 0); - } - break; - case 's': /* DECSC -- Save cursor position (ANSI.SYS) */ - tcursor(CURSOR_SAVE); - break; - case 'u': /* DECRC -- Restore cursor position (ANSI.SYS) */ - tcursor(CURSOR_LOAD); - break; - case ' ': - switch (csiescseq.mode[1]) { - case 'q': /* DECSCUSR -- Set Cursor Style */ - if (xsetcursor(csiescseq.arg[0])) - goto unknown; - break; - default: - goto unknown; - } - break; - } -} - -void -csidump(void) -{ - size_t i; - uint c; - - fprintf(stderr, "ESC["); - for (i = 0; i < csiescseq.len; i++) { - c = csiescseq.buf[i] & 0xff; - if (isprint(c)) { - putc(c, stderr); - } else if (c == '\n') { - fprintf(stderr, "(\\n)"); - } else if (c == '\r') { - fprintf(stderr, "(\\r)"); - } else if (c == 0x1b) { - fprintf(stderr, "(\\e)"); - } else { - fprintf(stderr, "(%02x)", c); - } - } - putc('\n', stderr); -} - -void -csireset(void) -{ - memset(&csiescseq, 0, sizeof(csiescseq)); -} - -void -osc_color_response(int num, int index, int is_osc4) -{ - int n; - char buf[32]; - unsigned char r, g, b; - - if (xgetcolor(is_osc4 ? num : index, &r, &g, &b)) { - fprintf(stderr, "erresc: failed to fetch %s color %d\n", - is_osc4 ? "osc4" : "osc", - is_osc4 ? num : index); - return; - } - - n = snprintf(buf, sizeof buf, "\033]%s%d;rgb:%02x%02x/%02x%02x/%02x%02x\007", - is_osc4 ? "4;" : "", num, r, r, g, g, b, b); - if (n < 0 || n >= sizeof(buf)) { - fprintf(stderr, "error: %s while printing %s response\n", - n < 0 ? "snprintf failed" : "truncation occurred", - is_osc4 ? "osc4" : "osc"); - } else { - ttywrite(buf, n, 1); - } -} - -void -strhandle(void) -{ - char *p = NULL, *dec; - int j, narg, par; - const struct { int idx; char *str; } osc_table[] = { - { defaultfg, "foreground" }, - { defaultbg, "background" }, - { defaultcs, "cursor" } - }; - - term.esc &= ~(ESC_STR_END|ESC_STR); - strparse(); - par = (narg = strescseq.narg) ? atoi(strescseq.args[0]) : 0; - - switch (strescseq.type) { - case ']': /* OSC -- Operating System Command */ - switch (par) { - case 0: - if (narg > 1) { - xsettitle(strescseq.args[1]); - xseticontitle(strescseq.args[1]); - } - return; - case 1: - if (narg > 1) - xseticontitle(strescseq.args[1]); - return; - case 2: - if (narg > 1) - xsettitle(strescseq.args[1]); - return; - case 52: - if (narg > 2 && allowwindowops) { - dec = base64dec(strescseq.args[2]); - if (dec) { - xsetsel(dec); - xclipcopy(); - } else { - fprintf(stderr, "erresc: invalid base64\n"); - } - } - return; - case 10: - case 11: - case 12: - if (narg < 2) - break; - p = strescseq.args[1]; - if ((j = par - 10) < 0 || j >= LEN(osc_table)) - break; /* shouldn't be possible */ - - if (!strcmp(p, "?")) { - osc_color_response(par, osc_table[j].idx, 0); - } else if (xsetcolorname(osc_table[j].idx, p)) { - fprintf(stderr, "erresc: invalid %s color: %s\n", - osc_table[j].str, p); - } else { - tfulldirt(); - } - return; - case 4: /* color set */ - if (narg < 3) - break; - p = strescseq.args[2]; - /* FALLTHROUGH */ - case 104: /* color reset */ - j = (narg > 1) ? atoi(strescseq.args[1]) : -1; - - if (p && !strcmp(p, "?")) { - osc_color_response(j, 0, 1); - } else if (xsetcolorname(j, p)) { - if (par == 104 && narg <= 1) - return; /* color reset without parameter */ - fprintf(stderr, "erresc: invalid color j=%d, p=%s\n", - j, p ? p : "(null)"); - } else { - /* - * TODO if defaultbg color is changed, borders - * are dirty - */ - tfulldirt(); - } - return; - } - break; - case 'k': /* old title set compatibility */ - xsettitle(strescseq.args[0]); - return; - case 'P': /* DCS -- Device Control String */ - case '_': /* APC -- Application Program Command */ - case '^': /* PM -- Privacy Message */ - return; - } - - fprintf(stderr, "erresc: unknown str "); - strdump(); -} - -void -strparse(void) -{ - int c; - char *p = strescseq.buf; - - strescseq.narg = 0; - strescseq.buf[strescseq.len] = '\0'; - - if (*p == '\0') - return; - - while (strescseq.narg < STR_ARG_SIZ) { - strescseq.args[strescseq.narg++] = p; - while ((c = *p) != ';' && c != '\0') - ++p; - if (c == '\0') - return; - *p++ = '\0'; - } -} - -void -strdump(void) -{ - size_t i; - uint c; - - fprintf(stderr, "ESC%c", strescseq.type); - for (i = 0; i < strescseq.len; i++) { - c = strescseq.buf[i] & 0xff; - if (c == '\0') { - putc('\n', stderr); - return; - } else if (isprint(c)) { - putc(c, stderr); - } else if (c == '\n') { - fprintf(stderr, "(\\n)"); - } else if (c == '\r') { - fprintf(stderr, "(\\r)"); - } else if (c == 0x1b) { - fprintf(stderr, "(\\e)"); - } else { - fprintf(stderr, "(%02x)", c); - } - } - fprintf(stderr, "ESC\\\n"); -} - -void -strreset(void) -{ - strescseq = (STREscape){ - .buf = xrealloc(strescseq.buf, STR_BUF_SIZ), - .siz = STR_BUF_SIZ, - }; -} - -void -sendbreak(const Arg *arg) -{ - if (tcsendbreak(cmdfd, 0)) - perror("Error sending break"); -} - -void -tprinter(char *s, size_t len) -{ - if (iofd != -1 && xwrite(iofd, s, len) < 0) { - perror("Error writing to output file"); - close(iofd); - iofd = -1; - } -} - -void -toggleprinter(const Arg *arg) -{ - term.mode ^= MODE_PRINT; -} - -void -printscreen(const Arg *arg) -{ - tdump(); -} - -void -printsel(const Arg *arg) -{ - tdumpsel(); -} - -void -tdumpsel(void) -{ - char *ptr; - - if ((ptr = getsel())) { - tprinter(ptr, strlen(ptr)); - free(ptr); - } -} - -void -tdumpline(int n) -{ - char buf[UTF_SIZ]; - const Glyph *bp, *end; - - bp = &term.line[n][0]; - end = &bp[MIN(tlinelen(n), term.col) - 1]; - if (bp != end || bp->u != ' ') { - for ( ; bp <= end; ++bp) - tprinter(buf, utf8encode(bp->u, buf)); - } - tprinter("\n", 1); -} - -void -tdump(void) -{ - int i; - - for (i = 0; i < term.row; ++i) - tdumpline(i); -} - -void -tputtab(int n) -{ - uint x = term.c.x; - - if (n > 0) { - while (x < term.col && n--) - for (++x; x < term.col && !term.tabs[x]; ++x) - /* nothing */ ; - } else if (n < 0) { - while (x > 0 && n++) - for (--x; x > 0 && !term.tabs[x]; --x) - /* nothing */ ; - } - term.c.x = LIMIT(x, 0, term.col-1); -} - -void -tdefutf8(char ascii) -{ - if (ascii == 'G') - term.mode |= MODE_UTF8; - else if (ascii == '@') - term.mode &= ~MODE_UTF8; -} - -void -tdeftran(char ascii) -{ - static char cs[] = "0B"; - static int vcs[] = {CS_GRAPHIC0, CS_USA}; - char *p; - - if ((p = strchr(cs, ascii)) == NULL) { - fprintf(stderr, "esc unhandled charset: ESC ( %c\n", ascii); - } else { - term.trantbl[term.icharset] = vcs[p - cs]; - } -} - -void -tdectest(char c) -{ - int x, y; - - if (c == '8') { /* DEC screen alignment test. */ - for (x = 0; x < term.col; ++x) { - for (y = 0; y < term.row; ++y) - tsetchar('E', &term.c.attr, x, y); - } - } -} - -void -tstrsequence(uchar c) -{ - switch (c) { - case 0x90: /* DCS -- Device Control String */ - c = 'P'; - break; - case 0x9f: /* APC -- Application Program Command */ - c = '_'; - break; - case 0x9e: /* PM -- Privacy Message */ - c = '^'; - break; - case 0x9d: /* OSC -- Operating System Command */ - c = ']'; - break; - } - strreset(); - strescseq.type = c; - term.esc |= ESC_STR; -} - -void -tcontrolcode(uchar ascii) -{ - switch (ascii) { - case '\t': /* HT */ - tputtab(1); - return; - case '\b': /* BS */ - tmoveto(term.c.x-1, term.c.y); - return; - case '\r': /* CR */ - tmoveto(0, term.c.y); - return; - case '\f': /* LF */ - case '\v': /* VT */ - case '\n': /* LF */ - /* go to first col if the mode is set */ - tnewline(IS_SET(MODE_CRLF)); - return; - case '\a': /* BEL */ - if (term.esc & ESC_STR_END) { - /* backwards compatibility to xterm */ - strhandle(); - } else { - xbell(); - } - break; - case '\033': /* ESC */ - csireset(); - term.esc &= ~(ESC_CSI|ESC_ALTCHARSET|ESC_TEST); - term.esc |= ESC_START; - return; - case '\016': /* SO (LS1 -- Locking shift 1) */ - case '\017': /* SI (LS0 -- Locking shift 0) */ - term.charset = 1 - (ascii - '\016'); - return; - case '\032': /* SUB */ - tsetchar('?', &term.c.attr, term.c.x, term.c.y); - /* FALLTHROUGH */ - case '\030': /* CAN */ - csireset(); - break; - case '\005': /* ENQ (IGNORED) */ - case '\000': /* NUL (IGNORED) */ - case '\021': /* XON (IGNORED) */ - case '\023': /* XOFF (IGNORED) */ - case 0177: /* DEL (IGNORED) */ - return; - case 0x80: /* TODO: PAD */ - case 0x81: /* TODO: HOP */ - case 0x82: /* TODO: BPH */ - case 0x83: /* TODO: NBH */ - case 0x84: /* TODO: IND */ - break; - case 0x85: /* NEL -- Next line */ - tnewline(1); /* always go to first col */ - break; - case 0x86: /* TODO: SSA */ - case 0x87: /* TODO: ESA */ - break; - case 0x88: /* HTS -- Horizontal tab stop */ - term.tabs[term.c.x] = 1; - break; - case 0x89: /* TODO: HTJ */ - case 0x8a: /* TODO: VTS */ - case 0x8b: /* TODO: PLD */ - case 0x8c: /* TODO: PLU */ - case 0x8d: /* TODO: RI */ - case 0x8e: /* TODO: SS2 */ - case 0x8f: /* TODO: SS3 */ - case 0x91: /* TODO: PU1 */ - case 0x92: /* TODO: PU2 */ - case 0x93: /* TODO: STS */ - case 0x94: /* TODO: CCH */ - case 0x95: /* TODO: MW */ - case 0x96: /* TODO: SPA */ - case 0x97: /* TODO: EPA */ - case 0x98: /* TODO: SOS */ - case 0x99: /* TODO: SGCI */ - break; - case 0x9a: /* DECID -- Identify Terminal */ - ttywrite(vtiden, strlen(vtiden), 0); - break; - case 0x9b: /* TODO: CSI */ - case 0x9c: /* TODO: ST */ - break; - case 0x90: /* DCS -- Device Control String */ - case 0x9d: /* OSC -- Operating System Command */ - case 0x9e: /* PM -- Privacy Message */ - case 0x9f: /* APC -- Application Program Command */ - tstrsequence(ascii); - return; - } - /* only CAN, SUB, \a and C1 chars interrupt a sequence */ - term.esc &= ~(ESC_STR_END|ESC_STR); -} - -/* - * returns 1 when the sequence is finished and it hasn't to read - * more characters for this sequence, otherwise 0 - */ -int -eschandle(uchar ascii) -{ - switch (ascii) { - case '[': - term.esc |= ESC_CSI; - return 0; - case '#': - term.esc |= ESC_TEST; - return 0; - case '%': - term.esc |= ESC_UTF8; - return 0; - case 'P': /* DCS -- Device Control String */ - case '_': /* APC -- Application Program Command */ - case '^': /* PM -- Privacy Message */ - case ']': /* OSC -- Operating System Command */ - case 'k': /* old title set compatibility */ - tstrsequence(ascii); - return 0; - case 'n': /* LS2 -- Locking shift 2 */ - case 'o': /* LS3 -- Locking shift 3 */ - term.charset = 2 + (ascii - 'n'); - break; - case '(': /* GZD4 -- set primary charset G0 */ - case ')': /* G1D4 -- set secondary charset G1 */ - case '*': /* G2D4 -- set tertiary charset G2 */ - case '+': /* G3D4 -- set quaternary charset G3 */ - term.icharset = ascii - '('; - term.esc |= ESC_ALTCHARSET; - return 0; - case 'D': /* IND -- Linefeed */ - if (term.c.y == term.bot) { - tscrollup(term.top, 1, 1); - } else { - tmoveto(term.c.x, term.c.y+1); - } - break; - case 'E': /* NEL -- Next line */ - tnewline(1); /* always go to first col */ - break; - case 'H': /* HTS -- Horizontal tab stop */ - term.tabs[term.c.x] = 1; - break; - case 'M': /* RI -- Reverse index */ - if (term.c.y == term.top) { - tscrolldown(term.top, 1, 1); - } else { - tmoveto(term.c.x, term.c.y-1); - } - break; - case 'Z': /* DECID -- Identify Terminal */ - ttywrite(vtiden, strlen(vtiden), 0); - break; - case 'c': /* RIS -- Reset to initial state */ - treset(); - resettitle(); - xloadcols(); - break; - case '=': /* DECPAM -- Application keypad */ - xsetmode(1, MODE_APPKEYPAD); - break; - case '>': /* DECPNM -- Normal keypad */ - xsetmode(0, MODE_APPKEYPAD); - break; - case '7': /* DECSC -- Save Cursor */ - tcursor(CURSOR_SAVE); - break; - case '8': /* DECRC -- Restore Cursor */ - tcursor(CURSOR_LOAD); - break; - case '\\': /* ST -- String Terminator */ - if (term.esc & ESC_STR_END) - strhandle(); - break; - default: - fprintf(stderr, "erresc: unknown sequence ESC 0x%02X '%c'\n", - (uchar) ascii, isprint(ascii)? ascii:'.'); - break; - } - return 1; -} - -void -tputc(Rune u) -{ - char c[UTF_SIZ]; - int control; - int width, len; - Glyph *gp; - - control = ISCONTROL(u); - if (u < 127 || !IS_SET(MODE_UTF8)) { - c[0] = u; - width = len = 1; - } else { - len = utf8encode(u, c); - if (!control && (width = wcwidth(u)) == -1) - width = 1; - } - - if (IS_SET(MODE_PRINT)) - tprinter(c, len); - - /* - * STR sequence must be checked before anything else - * because it uses all following characters until it - * receives a ESC, a SUB, a ST or any other C1 control - * character. - */ - if (term.esc & ESC_STR) { - if (u == '\a' || u == 030 || u == 032 || u == 033 || - ISCONTROLC1(u)) { - term.esc &= ~(ESC_START|ESC_STR); - term.esc |= ESC_STR_END; - goto check_control_code; - } - - if (strescseq.len+len >= strescseq.siz) { - /* - * Here is a bug in terminals. If the user never sends - * some code to stop the str or esc command, then st - * will stop responding. But this is better than - * silently failing with unknown characters. At least - * then users will report back. - * - * In the case users ever get fixed, here is the code: - */ - /* - * term.esc = 0; - * strhandle(); - */ - if (strescseq.siz > (SIZE_MAX - UTF_SIZ) / 2) - return; - strescseq.siz *= 2; - strescseq.buf = xrealloc(strescseq.buf, strescseq.siz); - } - - memmove(&strescseq.buf[strescseq.len], c, len); - strescseq.len += len; - return; - } - -check_control_code: - /* - * Actions of control codes must be performed as soon they arrive - * because they can be embedded inside a control sequence, and - * they must not cause conflicts with sequences. - */ - if (control) { - tcontrolcode(u); - /* - * control codes are not shown ever - */ - if (!term.esc) - term.lastc = 0; - return; - } else if (term.esc & ESC_START) { - if (term.esc & ESC_CSI) { - csiescseq.buf[csiescseq.len++] = u; - if (BETWEEN(u, 0x40, 0x7E) - || csiescseq.len >= \ - sizeof(csiescseq.buf)-1) { - term.esc = 0; - csiparse(); - csihandle(); - } - return; - } else if (term.esc & ESC_UTF8) { - tdefutf8(u); - } else if (term.esc & ESC_ALTCHARSET) { - tdeftran(u); - } else if (term.esc & ESC_TEST) { - tdectest(u); - } else { - if (!eschandle(u)) - return; - /* sequence already finished */ - } - term.esc = 0; - /* - * All characters which form part of a sequence are not - * printed - */ - return; - } - if (selected(term.c.x, term.c.y)) - selclear(); - - gp = &term.line[term.c.y][term.c.x]; - if (IS_SET(MODE_WRAP) && (term.c.state & CURSOR_WRAPNEXT)) { - gp->mode |= ATTR_WRAP; - tnewline(1); - gp = &term.line[term.c.y][term.c.x]; - } - - if (IS_SET(MODE_INSERT) && term.c.x+width < term.col) - memmove(gp+width, gp, (term.col - term.c.x - width) * sizeof(Glyph)); - - if (term.c.x+width > term.col) { - tnewline(1); - gp = &term.line[term.c.y][term.c.x]; - } - - tsetchar(u, &term.c.attr, term.c.x, term.c.y); - term.lastc = u; - - if (width == 2) { - gp->mode |= ATTR_WIDE; - if (term.c.x+1 < term.col) { - if (gp[1].mode == ATTR_WIDE && term.c.x+2 < term.col) { - gp[2].u = ' '; - gp[2].mode &= ~ATTR_WDUMMY; - } - gp[1].u = '\0'; - gp[1].mode = ATTR_WDUMMY; - } - } - if (term.c.x+width < term.col) { - tmoveto(term.c.x+width, term.c.y); - } else { - term.c.state |= CURSOR_WRAPNEXT; - } -} - -int -twrite(const char *buf, int buflen, int show_ctrl) -{ - int charsize; - Rune u; - int n; - - for (n = 0; n < buflen; n += charsize) { - if (IS_SET(MODE_UTF8)) { - /* process a complete utf8 char */ - charsize = utf8decode(buf + n, &u, buflen - n); - if (charsize == 0) - break; - } else { - u = buf[n] & 0xFF; - charsize = 1; - } - if (show_ctrl && ISCONTROL(u)) { - if (u & 0x80) { - u &= 0x7f; - tputc('^'); - tputc('['); - } else if (u != '\n' && u != '\r' && u != '\t') { - u ^= 0x40; - tputc('^'); - } - } - tputc(u); - } - return n; -} - -void -tresize(int col, int row) -{ - int i, j; - int minrow = MIN(row, term.row); - int mincol = MIN(col, term.col); - int *bp; - TCursor c; - - if (col < 1 || row < 1) { - fprintf(stderr, - "tresize: error resizing to %dx%d\n", col, row); - return; - } - - /* - * slide screen to keep cursor where we expect it - - * tscrollup would work here, but we can optimize to - * memmove because we're freeing the earlier lines - */ - for (i = 0; i <= term.c.y - row; i++) { - free(term.line[i]); - free(term.alt[i]); - } - /* ensure that both src and dst are not NULL */ - if (i > 0) { - memmove(term.line, term.line + i, row * sizeof(Line)); - memmove(term.alt, term.alt + i, row * sizeof(Line)); - } - for (i += row; i < term.row; i++) { - free(term.line[i]); - free(term.alt[i]); - } - - /* resize to new height */ - term.line = xrealloc(term.line, row * sizeof(Line)); - term.alt = xrealloc(term.alt, row * sizeof(Line)); - term.dirty = xrealloc(term.dirty, row * sizeof(*term.dirty)); - term.tabs = xrealloc(term.tabs, col * sizeof(*term.tabs)); - - for (i = 0; i < HISTSIZE; i++) { - term.hist[i] = xrealloc(term.hist[i], col * sizeof(Glyph)); - for (j = mincol; j < col; j++) { - term.hist[i][j] = term.c.attr; - term.hist[i][j].u = ' '; - } - } - - /* resize each row to new width, zero-pad if needed */ - for (i = 0; i < minrow; i++) { - term.line[i] = xrealloc(term.line[i], col * sizeof(Glyph)); - term.alt[i] = xrealloc(term.alt[i], col * sizeof(Glyph)); - } - - /* allocate any new rows */ - for (/* i = minrow */; i < row; i++) { - term.line[i] = xmalloc(col * sizeof(Glyph)); - term.alt[i] = xmalloc(col * sizeof(Glyph)); - } - if (col > term.col) { - bp = term.tabs + term.col; - - memset(bp, 0, sizeof(*term.tabs) * (col - term.col)); - while (--bp > term.tabs && !*bp) - /* nothing */ ; - for (bp += tabspaces; bp < term.tabs + col; bp += tabspaces) - *bp = 1; - } - /* update terminal size */ - term.col = col; - term.row = row; - /* reset scrolling region */ - tsetscroll(0, row-1); - /* make use of the LIMIT in tmoveto */ - tmoveto(term.c.x, term.c.y); - /* Clearing both screens (it makes dirty all lines) */ - c = term.c; - for (i = 0; i < 2; i++) { - if (mincol < col && 0 < minrow) { - tclearregion(mincol, 0, col - 1, minrow - 1); - } - if (0 < col && minrow < row) { - tclearregion(0, minrow, col - 1, row - 1); - } - tswapscreen(); - tcursor(CURSOR_LOAD); - } - term.c = c; -} - -void -resettitle(void) -{ - xsettitle(NULL); -} - -void -drawregion(int x1, int y1, int x2, int y2) -{ - int y; - - for (y = y1; y < y2; y++) { - if (!term.dirty[y]) - continue; - - term.dirty[y] = 0; - xdrawline(TLINE(y), x1, y, x2); - } -} - -void -draw(void) -{ - int cx = term.c.x, ocx = term.ocx, ocy = term.ocy; - - if (!xstartdraw()) - return; - - /* adjust cursor position */ - LIMIT(term.ocx, 0, term.col-1); - LIMIT(term.ocy, 0, term.row-1); - if (term.line[term.ocy][term.ocx].mode & ATTR_WDUMMY) - term.ocx--; - if (term.line[term.c.y][cx].mode & ATTR_WDUMMY) - cx--; - - drawregion(0, 0, term.col, term.row); - if (term.scr == 0) - xdrawcursor(cx, term.c.y, term.line[term.c.y][cx], - term.ocx, term.ocy, term.line[term.ocy][term.ocx]); - term.ocx = cx; - term.ocy = term.c.y; - xfinishdraw(); - if (ocx != term.ocx || ocy != term.ocy) - xximspot(term.ocx, term.ocy); -} - -void -redraw(void) -{ - tfulldirt(); - draw(); -} diff --git a/utils/st-0.9/st.c.orig b/utils/st-0.9/st.c.orig deleted file mode 100644 index 62def59..0000000 --- a/utils/st-0.9/st.c.orig +++ /dev/null @@ -1,2656 +0,0 @@ -/* See LICENSE for license details. */ -#include <ctype.h> -#include <errno.h> -#include <fcntl.h> -#include <limits.h> -#include <pwd.h> -#include <stdarg.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <signal.h> -#include <sys/ioctl.h> -#include <sys/select.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <termios.h> -#include <unistd.h> -#include <wchar.h> - -#include "st.h" -#include "win.h" - -#if defined(__linux) - #include <pty.h> -#elif defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__) - #include <util.h> -#elif defined(__FreeBSD__) || defined(__DragonFly__) - #include <libutil.h> -#endif - -/* Arbitrary sizes */ -#define UTF_INVALID 0xFFFD -#define UTF_SIZ 4 -#define ESC_BUF_SIZ (128*UTF_SIZ) -#define ESC_ARG_SIZ 16 -#define STR_BUF_SIZ ESC_BUF_SIZ -#define STR_ARG_SIZ ESC_ARG_SIZ - -/* macros */ -#define IS_SET(flag) ((term.mode & (flag)) != 0) -#define ISCONTROLC0(c) (BETWEEN(c, 0, 0x1f) || (c) == 0x7f) -#define ISCONTROLC1(c) (BETWEEN(c, 0x80, 0x9f)) -#define ISCONTROL(c) (ISCONTROLC0(c) || ISCONTROLC1(c)) -#define ISDELIM(u) (u && wcschr(worddelimiters, u)) - -enum term_mode { - MODE_WRAP = 1 << 0, - MODE_INSERT = 1 << 1, - MODE_ALTSCREEN = 1 << 2, - MODE_CRLF = 1 << 3, - MODE_ECHO = 1 << 4, - MODE_PRINT = 1 << 5, - MODE_UTF8 = 1 << 6, -}; - -enum cursor_movement { - CURSOR_SAVE, - CURSOR_LOAD -}; - -enum cursor_state { - CURSOR_DEFAULT = 0, - CURSOR_WRAPNEXT = 1, - CURSOR_ORIGIN = 2 -}; - -enum charset { - CS_GRAPHIC0, - CS_GRAPHIC1, - CS_UK, - CS_USA, - CS_MULTI, - CS_GER, - CS_FIN -}; - -enum escape_state { - ESC_START = 1, - ESC_CSI = 2, - ESC_STR = 4, /* DCS, OSC, PM, APC */ - ESC_ALTCHARSET = 8, - ESC_STR_END = 16, /* a final string was encountered */ - ESC_TEST = 32, /* Enter in test mode */ - ESC_UTF8 = 64, -}; - -typedef struct { - Glyph attr; /* current char attributes */ - int x; - int y; - char state; -} TCursor; - -typedef struct { - int mode; - int type; - int snap; - /* - * Selection variables: - * nb – normalized coordinates of the beginning of the selection - * ne – normalized coordinates of the end of the selection - * ob – original coordinates of the beginning of the selection - * oe – original coordinates of the end of the selection - */ - struct { - int x, y; - } nb, ne, ob, oe; - - int alt; -} Selection; - -/* Internal representation of the screen */ -typedef struct { - int row; /* nb row */ - int col; /* nb col */ - Line *line; /* screen */ - Line *alt; /* alternate screen */ - int *dirty; /* dirtyness of lines */ - TCursor c; /* cursor */ - int ocx; /* old cursor col */ - int ocy; /* old cursor row */ - int top; /* top scroll limit */ - int bot; /* bottom scroll limit */ - int mode; /* terminal mode flags */ - int esc; /* escape state flags */ - char trantbl[4]; /* charset table translation */ - int charset; /* current charset */ - int icharset; /* selected charset for sequence */ - int *tabs; - Rune lastc; /* last printed char outside of sequence, 0 if control */ -} Term; - -/* CSI Escape sequence structs */ -/* ESC '[' [[ [<priv>] <arg> [;]] <mode> [<mode>]] */ -typedef struct { - char buf[ESC_BUF_SIZ]; /* raw string */ - size_t len; /* raw string length */ - char priv; - int arg[ESC_ARG_SIZ]; - int narg; /* nb of args */ - char mode[2]; -} CSIEscape; - -/* STR Escape sequence structs */ -/* ESC type [[ [<priv>] <arg> [;]] <mode>] ESC '\' */ -typedef struct { - char type; /* ESC type ... */ - char *buf; /* allocated raw string */ - size_t siz; /* allocation size */ - size_t len; /* raw string length */ - char *args[STR_ARG_SIZ]; - int narg; /* nb of args */ -} STREscape; - -static void execsh(char *, char **); -static void stty(char **); -static void sigchld(int); -static void ttywriteraw(const char *, size_t); - -static void csidump(void); -static void csihandle(void); -static void csiparse(void); -static void csireset(void); -static void osc_color_response(int, int, int); -static int eschandle(uchar); -static void strdump(void); -static void strhandle(void); -static void strparse(void); -static void strreset(void); - -static void tprinter(char *, size_t); -static void tdumpsel(void); -static void tdumpline(int); -static void tdump(void); -static void tclearregion(int, int, int, int); -static void tcursor(int); -static void tdeletechar(int); -static void tdeleteline(int); -static void tinsertblank(int); -static void tinsertblankline(int); -static int tlinelen(int); -static void tmoveto(int, int); -static void tmoveato(int, int); -static void tnewline(int); -static void tputtab(int); -static void tputc(Rune); -static void treset(void); -static void tscrollup(int, int); -static void tscrolldown(int, int); -static void tsetattr(const int *, int); -static void tsetchar(Rune, const Glyph *, int, int); -static void tsetdirt(int, int); -static void tsetscroll(int, int); -static void tswapscreen(void); -static void tsetmode(int, int, const int *, int); -static int twrite(const char *, int, int); -static void tfulldirt(void); -static void tcontrolcode(uchar ); -static void tdectest(char ); -static void tdefutf8(char); -static int32_t tdefcolor(const int *, int *, int); -static void tdeftran(char); -static void tstrsequence(uchar); - -static void drawregion(int, int, int, int); - -static void selnormalize(void); -static void selscroll(int, int); -static void selsnap(int *, int *, int); - -static size_t utf8decode(const char *, Rune *, size_t); -static Rune utf8decodebyte(char, size_t *); -static char utf8encodebyte(Rune, size_t); -static size_t utf8validate(Rune *, size_t); - -static char *base64dec(const char *); -static char base64dec_getc(const char **); - -static ssize_t xwrite(int, const char *, size_t); - -/* Globals */ -static Term term; -static Selection sel; -static CSIEscape csiescseq; -static STREscape strescseq; -static int iofd = 1; -static int cmdfd; -static pid_t pid; - -static const uchar utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0}; -static const uchar utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; -static const Rune utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000}; -static const Rune utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; - -ssize_t -xwrite(int fd, const char *s, size_t len) -{ - size_t aux = len; - ssize_t r; - - while (len > 0) { - r = write(fd, s, len); - if (r < 0) - return r; - len -= r; - s += r; - } - - return aux; -} - -void * -xmalloc(size_t len) -{ - void *p; - - if (!(p = malloc(len))) - die("malloc: %s\n", strerror(errno)); - - return p; -} - -void * -xrealloc(void *p, size_t len) -{ - if ((p = realloc(p, len)) == NULL) - die("realloc: %s\n", strerror(errno)); - - return p; -} - -char * -xstrdup(const char *s) -{ - char *p; - - if ((p = strdup(s)) == NULL) - die("strdup: %s\n", strerror(errno)); - - return p; -} - -size_t -utf8decode(const char *c, Rune *u, size_t clen) -{ - size_t i, j, len, type; - Rune udecoded; - - *u = UTF_INVALID; - if (!clen) - return 0; - udecoded = utf8decodebyte(c[0], &len); - if (!BETWEEN(len, 1, UTF_SIZ)) - return 1; - for (i = 1, j = 1; i < clen && j < len; ++i, ++j) { - udecoded = (udecoded << 6) | utf8decodebyte(c[i], &type); - if (type != 0) - return j; - } - if (j < len) - return 0; - *u = udecoded; - utf8validate(u, len); - - return len; -} - -Rune -utf8decodebyte(char c, size_t *i) -{ - for (*i = 0; *i < LEN(utfmask); ++(*i)) - if (((uchar)c & utfmask[*i]) == utfbyte[*i]) - return (uchar)c & ~utfmask[*i]; - - return 0; -} - -size_t -utf8encode(Rune u, char *c) -{ - size_t len, i; - - len = utf8validate(&u, 0); - if (len > UTF_SIZ) - return 0; - - for (i = len - 1; i != 0; --i) { - c[i] = utf8encodebyte(u, 0); - u >>= 6; - } - c[0] = utf8encodebyte(u, len); - - return len; -} - -char -utf8encodebyte(Rune u, size_t i) -{ - return utfbyte[i] | (u & ~utfmask[i]); -} - -size_t -utf8validate(Rune *u, size_t i) -{ - if (!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF)) - *u = UTF_INVALID; - for (i = 1; *u > utfmax[i]; ++i) - ; - - return i; -} - -char -base64dec_getc(const char **src) -{ - while (**src && !isprint((unsigned char)**src)) - (*src)++; - return **src ? *((*src)++) : '='; /* emulate padding if string ends */ -} - -char * -base64dec(const char *src) -{ - size_t in_len = strlen(src); - char *result, *dst; - static const char base64_digits[256] = { - [43] = 62, 0, 0, 0, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, - 0, 0, 0, -1, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, - 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, - 0, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, - 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 - }; - - if (in_len % 4) - in_len += 4 - (in_len % 4); - result = dst = xmalloc(in_len / 4 * 3 + 1); - while (*src) { - int a = base64_digits[(unsigned char) base64dec_getc(&src)]; - int b = base64_digits[(unsigned char) base64dec_getc(&src)]; - int c = base64_digits[(unsigned char) base64dec_getc(&src)]; - int d = base64_digits[(unsigned char) base64dec_getc(&src)]; - - /* invalid input. 'a' can be -1, e.g. if src is "\n" (c-str) */ - if (a == -1 || b == -1) - break; - - *dst++ = (a << 2) | ((b & 0x30) >> 4); - if (c == -1) - break; - *dst++ = ((b & 0x0f) << 4) | ((c & 0x3c) >> 2); - if (d == -1) - break; - *dst++ = ((c & 0x03) << 6) | d; - } - *dst = '\0'; - return result; -} - -void -selinit(void) -{ - sel.mode = SEL_IDLE; - sel.snap = 0; - sel.ob.x = -1; -} - -int -tlinelen(int y) -{ - int i = term.col; - - if (term.line[y][i - 1].mode & ATTR_WRAP) - return i; - - while (i > 0 && term.line[y][i - 1].u == ' ') - --i; - - return i; -} - -void -selstart(int col, int row, int snap) -{ - selclear(); - sel.mode = SEL_EMPTY; - sel.type = SEL_REGULAR; - sel.alt = IS_SET(MODE_ALTSCREEN); - sel.snap = snap; - sel.oe.x = sel.ob.x = col; - sel.oe.y = sel.ob.y = row; - selnormalize(); - - if (sel.snap != 0) - sel.mode = SEL_READY; - tsetdirt(sel.nb.y, sel.ne.y); -} - -void -selextend(int col, int row, int type, int done) -{ - int oldey, oldex, oldsby, oldsey, oldtype; - - if (sel.mode == SEL_IDLE) - return; - if (done && sel.mode == SEL_EMPTY) { - selclear(); - return; - } - - oldey = sel.oe.y; - oldex = sel.oe.x; - oldsby = sel.nb.y; - oldsey = sel.ne.y; - oldtype = sel.type; - - sel.oe.x = col; - sel.oe.y = row; - selnormalize(); - sel.type = type; - - if (oldey != sel.oe.y || oldex != sel.oe.x || oldtype != sel.type || sel.mode == SEL_EMPTY) - tsetdirt(MIN(sel.nb.y, oldsby), MAX(sel.ne.y, oldsey)); - - sel.mode = done ? SEL_IDLE : SEL_READY; -} - -void -selnormalize(void) -{ - int i; - - if (sel.type == SEL_REGULAR && sel.ob.y != sel.oe.y) { - sel.nb.x = sel.ob.y < sel.oe.y ? sel.ob.x : sel.oe.x; - sel.ne.x = sel.ob.y < sel.oe.y ? sel.oe.x : sel.ob.x; - } else { - sel.nb.x = MIN(sel.ob.x, sel.oe.x); - sel.ne.x = MAX(sel.ob.x, sel.oe.x); - } - sel.nb.y = MIN(sel.ob.y, sel.oe.y); - sel.ne.y = MAX(sel.ob.y, sel.oe.y); - - selsnap(&sel.nb.x, &sel.nb.y, -1); - selsnap(&sel.ne.x, &sel.ne.y, +1); - - /* expand selection over line breaks */ - if (sel.type == SEL_RECTANGULAR) - return; - i = tlinelen(sel.nb.y); - if (i < sel.nb.x) - sel.nb.x = i; - if (tlinelen(sel.ne.y) <= sel.ne.x) - sel.ne.x = term.col - 1; -} - -int -selected(int x, int y) -{ - if (sel.mode == SEL_EMPTY || sel.ob.x == -1 || - sel.alt != IS_SET(MODE_ALTSCREEN)) - return 0; - - if (sel.type == SEL_RECTANGULAR) - return BETWEEN(y, sel.nb.y, sel.ne.y) - && BETWEEN(x, sel.nb.x, sel.ne.x); - - return BETWEEN(y, sel.nb.y, sel.ne.y) - && (y != sel.nb.y || x >= sel.nb.x) - && (y != sel.ne.y || x <= sel.ne.x); -} - -void -selsnap(int *x, int *y, int direction) -{ - int newx, newy, xt, yt; - int delim, prevdelim; - const Glyph *gp, *prevgp; - - switch (sel.snap) { - case SNAP_WORD: - /* - * Snap around if the word wraps around at the end or - * beginning of a line. - */ - prevgp = &term.line[*y][*x]; - prevdelim = ISDELIM(prevgp->u); - for (;;) { - newx = *x + direction; - newy = *y; - if (!BETWEEN(newx, 0, term.col - 1)) { - newy += direction; - newx = (newx + term.col) % term.col; - if (!BETWEEN(newy, 0, term.row - 1)) - break; - - if (direction > 0) - yt = *y, xt = *x; - else - yt = newy, xt = newx; - if (!(term.line[yt][xt].mode & ATTR_WRAP)) - break; - } - - if (newx >= tlinelen(newy)) - break; - - gp = &term.line[newy][newx]; - delim = ISDELIM(gp->u); - if (!(gp->mode & ATTR_WDUMMY) && (delim != prevdelim - || (delim && gp->u != prevgp->u))) - break; - - *x = newx; - *y = newy; - prevgp = gp; - prevdelim = delim; - } - break; - case SNAP_LINE: - /* - * Snap around if the the previous line or the current one - * has set ATTR_WRAP at its end. Then the whole next or - * previous line will be selected. - */ - *x = (direction < 0) ? 0 : term.col - 1; - if (direction < 0) { - for (; *y > 0; *y += direction) { - if (!(term.line[*y-1][term.col-1].mode - & ATTR_WRAP)) { - break; - } - } - } else if (direction > 0) { - for (; *y < term.row-1; *y += direction) { - if (!(term.line[*y][term.col-1].mode - & ATTR_WRAP)) { - break; - } - } - } - break; - } -} - -char * -getsel(void) -{ - char *str, *ptr; - int y, bufsize, lastx, linelen; - const Glyph *gp, *last; - - if (sel.ob.x == -1) - return NULL; - - bufsize = (term.col+1) * (sel.ne.y-sel.nb.y+1) * UTF_SIZ; - ptr = str = xmalloc(bufsize); - - /* append every set & selected glyph to the selection */ - for (y = sel.nb.y; y <= sel.ne.y; y++) { - if ((linelen = tlinelen(y)) == 0) { - *ptr++ = '\n'; - continue; - } - - if (sel.type == SEL_RECTANGULAR) { - gp = &term.line[y][sel.nb.x]; - lastx = sel.ne.x; - } else { - gp = &term.line[y][sel.nb.y == y ? sel.nb.x : 0]; - lastx = (sel.ne.y == y) ? sel.ne.x : term.col-1; - } - last = &term.line[y][MIN(lastx, linelen-1)]; - while (last >= gp && last->u == ' ') - --last; - - for ( ; gp <= last; ++gp) { - if (gp->mode & ATTR_WDUMMY) - continue; - - ptr += utf8encode(gp->u, ptr); - } - - /* - * Copy and pasting of line endings is inconsistent - * in the inconsistent terminal and GUI world. - * The best solution seems like to produce '\n' when - * something is copied from st and convert '\n' to - * '\r', when something to be pasted is received by - * st. - * FIXME: Fix the computer world. - */ - if ((y < sel.ne.y || lastx >= linelen) && - (!(last->mode & ATTR_WRAP) || sel.type == SEL_RECTANGULAR)) - *ptr++ = '\n'; - } - *ptr = 0; - return str; -} - -void -selclear(void) -{ - if (sel.ob.x == -1) - return; - sel.mode = SEL_IDLE; - sel.ob.x = -1; - tsetdirt(sel.nb.y, sel.ne.y); -} - -void -die(const char *errstr, ...) -{ - va_list ap; - - va_start(ap, errstr); - vfprintf(stderr, errstr, ap); - va_end(ap); - exit(1); -} - -void -execsh(char *cmd, char **args) -{ - char *sh, *prog, *arg; - const struct passwd *pw; - - errno = 0; - if ((pw = getpwuid(getuid())) == NULL) { - if (errno) - die("getpwuid: %s\n", strerror(errno)); - else - die("who are you?\n"); - } - - if ((sh = getenv("SHELL")) == NULL) - sh = (pw->pw_shell[0]) ? pw->pw_shell : cmd; - - if (args) { - prog = args[0]; - arg = NULL; - } else if (scroll) { - prog = scroll; - arg = utmp ? utmp : sh; - } else if (utmp) { - prog = utmp; - arg = NULL; - } else { - prog = sh; - arg = NULL; - } - DEFAULT(args, ((char *[]) {prog, arg, NULL})); - - unsetenv("COLUMNS"); - unsetenv("LINES"); - unsetenv("TERMCAP"); - setenv("LOGNAME", pw->pw_name, 1); - setenv("USER", pw->pw_name, 1); - setenv("SHELL", sh, 1); - setenv("HOME", pw->pw_dir, 1); - setenv("TERM", termname, 1); - - signal(SIGCHLD, SIG_DFL); - signal(SIGHUP, SIG_DFL); - signal(SIGINT, SIG_DFL); - signal(SIGQUIT, SIG_DFL); - signal(SIGTERM, SIG_DFL); - signal(SIGALRM, SIG_DFL); - - execvp(prog, args); - _exit(1); -} - -void -sigchld(int a) -{ - int stat; - pid_t p; - - if ((p = waitpid(pid, &stat, WNOHANG)) < 0) - die("waiting for pid %hd failed: %s\n", pid, strerror(errno)); - - if (pid != p) - return; - - if (WIFEXITED(stat) && WEXITSTATUS(stat)) - die("child exited with status %d\n", WEXITSTATUS(stat)); - else if (WIFSIGNALED(stat)) - die("child terminated due to signal %d\n", WTERMSIG(stat)); - _exit(0); -} - -void -stty(char **args) -{ - char cmd[_POSIX_ARG_MAX], **p, *q, *s; - size_t n, siz; - - if ((n = strlen(stty_args)) > sizeof(cmd)-1) - die("incorrect stty parameters\n"); - memcpy(cmd, stty_args, n); - q = cmd + n; - siz = sizeof(cmd) - n; - for (p = args; p && (s = *p); ++p) { - if ((n = strlen(s)) > siz-1) - die("stty parameter length too long\n"); - *q++ = ' '; - memcpy(q, s, n); - q += n; - siz -= n + 1; - } - *q = '\0'; - if (system(cmd) != 0) - perror("Couldn't call stty"); -} - -int -ttynew(const char *line, char *cmd, const char *out, char **args) -{ - int m, s; - - if (out) { - term.mode |= MODE_PRINT; - iofd = (!strcmp(out, "-")) ? - 1 : open(out, O_WRONLY | O_CREAT, 0666); - if (iofd < 0) { - fprintf(stderr, "Error opening %s:%s\n", - out, strerror(errno)); - } - } - - if (line) { - if ((cmdfd = open(line, O_RDWR)) < 0) - die("open line '%s' failed: %s\n", - line, strerror(errno)); - dup2(cmdfd, 0); - stty(args); - return cmdfd; - } - - /* seems to work fine on linux, openbsd and freebsd */ - if (openpty(&m, &s, NULL, NULL, NULL) < 0) - die("openpty failed: %s\n", strerror(errno)); - - switch (pid = fork()) { - case -1: - die("fork failed: %s\n", strerror(errno)); - break; - case 0: - close(iofd); - close(m); - setsid(); /* create a new process group */ - dup2(s, 0); - dup2(s, 1); - dup2(s, 2); - if (ioctl(s, TIOCSCTTY, NULL) < 0) - die("ioctl TIOCSCTTY failed: %s\n", strerror(errno)); - if (s > 2) - close(s); -#ifdef __OpenBSD__ - if (pledge("stdio getpw proc exec", NULL) == -1) - die("pledge\n"); -#endif - execsh(cmd, args); - break; - default: -#ifdef __OpenBSD__ - if (pledge("stdio rpath tty proc", NULL) == -1) - die("pledge\n"); -#endif - close(s); - cmdfd = m; - signal(SIGCHLD, sigchld); - break; - } - return cmdfd; -} - -size_t -ttyread(void) -{ - static char buf[BUFSIZ]; - static int buflen = 0; - int ret, written; - - /* append read bytes to unprocessed bytes */ - ret = read(cmdfd, buf+buflen, LEN(buf)-buflen); - - switch (ret) { - case 0: - exit(0); - case -1: - die("couldn't read from shell: %s\n", strerror(errno)); - default: - buflen += ret; - written = twrite(buf, buflen, 0); - buflen -= written; - /* keep any incomplete UTF-8 byte sequence for the next call */ - if (buflen > 0) - memmove(buf, buf + written, buflen); - return ret; - } -} - -void -ttywrite(const char *s, size_t n, int may_echo) -{ - const char *next; - - if (may_echo && IS_SET(MODE_ECHO)) - twrite(s, n, 1); - - if (!IS_SET(MODE_CRLF)) { - ttywriteraw(s, n); - return; - } - - /* This is similar to how the kernel handles ONLCR for ttys */ - while (n > 0) { - if (*s == '\r') { - next = s + 1; - ttywriteraw("\r\n", 2); - } else { - next = memchr(s, '\r', n); - DEFAULT(next, s + n); - ttywriteraw(s, next - s); - } - n -= next - s; - s = next; - } -} - -void -ttywriteraw(const char *s, size_t n) -{ - fd_set wfd, rfd; - ssize_t r; - size_t lim = 256; - - /* - * Remember that we are using a pty, which might be a modem line. - * Writing too much will clog the line. That's why we are doing this - * dance. - * FIXME: Migrate the world to Plan 9. - */ - while (n > 0) { - FD_ZERO(&wfd); - FD_ZERO(&rfd); - FD_SET(cmdfd, &wfd); - FD_SET(cmdfd, &rfd); - - /* Check if we can write. */ - if (pselect(cmdfd+1, &rfd, &wfd, NULL, NULL, NULL) < 0) { - if (errno == EINTR) - continue; - die("select failed: %s\n", strerror(errno)); - } - if (FD_ISSET(cmdfd, &wfd)) { - /* - * Only write the bytes written by ttywrite() or the - * default of 256. This seems to be a reasonable value - * for a serial line. Bigger values might clog the I/O. - */ - if ((r = write(cmdfd, s, (n < lim)? n : lim)) < 0) - goto write_error; - if (r < n) { - /* - * We weren't able to write out everything. - * This means the buffer is getting full - * again. Empty it. - */ - if (n < lim) - lim = ttyread(); - n -= r; - s += r; - } else { - /* All bytes have been written. */ - break; - } - } - if (FD_ISSET(cmdfd, &rfd)) - lim = ttyread(); - } - return; - -write_error: - die("write error on tty: %s\n", strerror(errno)); -} - -void -ttyresize(int tw, int th) -{ - struct winsize w; - - w.ws_row = term.row; - w.ws_col = term.col; - w.ws_xpixel = tw; - w.ws_ypixel = th; - if (ioctl(cmdfd, TIOCSWINSZ, &w) < 0) - fprintf(stderr, "Couldn't set window size: %s\n", strerror(errno)); -} - -void -ttyhangup(void) -{ - /* Send SIGHUP to shell */ - kill(pid, SIGHUP); -} - -int -tattrset(int attr) -{ - int i, j; - - for (i = 0; i < term.row-1; i++) { - for (j = 0; j < term.col-1; j++) { - if (term.line[i][j].mode & attr) - return 1; - } - } - - return 0; -} - -void -tsetdirt(int top, int bot) -{ - int i; - - LIMIT(top, 0, term.row-1); - LIMIT(bot, 0, term.row-1); - - for (i = top; i <= bot; i++) - term.dirty[i] = 1; -} - -void -tsetdirtattr(int attr) -{ - int i, j; - - for (i = 0; i < term.row-1; i++) { - for (j = 0; j < term.col-1; j++) { - if (term.line[i][j].mode & attr) { - tsetdirt(i, i); - break; - } - } - } -} - -void -tfulldirt(void) -{ - tsetdirt(0, term.row-1); -} - -void -tcursor(int mode) -{ - static TCursor c[2]; - int alt = IS_SET(MODE_ALTSCREEN); - - if (mode == CURSOR_SAVE) { - c[alt] = term.c; - } else if (mode == CURSOR_LOAD) { - term.c = c[alt]; - tmoveto(c[alt].x, c[alt].y); - } -} - -void -treset(void) -{ - uint i; - - term.c = (TCursor){{ - .mode = ATTR_NULL, - .fg = defaultfg, - .bg = defaultbg - }, .x = 0, .y = 0, .state = CURSOR_DEFAULT}; - - memset(term.tabs, 0, term.col * sizeof(*term.tabs)); - for (i = tabspaces; i < term.col; i += tabspaces) - term.tabs[i] = 1; - term.top = 0; - term.bot = term.row - 1; - term.mode = MODE_WRAP|MODE_UTF8; - memset(term.trantbl, CS_USA, sizeof(term.trantbl)); - term.charset = 0; - - for (i = 0; i < 2; i++) { - tmoveto(0, 0); - tcursor(CURSOR_SAVE); - tclearregion(0, 0, term.col-1, term.row-1); - tswapscreen(); - } -} - -void -tnew(int col, int row) -{ - term = (Term){ .c = { .attr = { .fg = defaultfg, .bg = defaultbg } } }; - tresize(col, row); - treset(); -} - -void -tswapscreen(void) -{ - Line *tmp = term.line; - - term.line = term.alt; - term.alt = tmp; - term.mode ^= MODE_ALTSCREEN; - tfulldirt(); -} - -void -tscrolldown(int orig, int n) -{ - int i; - Line temp; - - LIMIT(n, 0, term.bot-orig+1); - - tsetdirt(orig, term.bot-n); - tclearregion(0, term.bot-n+1, term.col-1, term.bot); - - for (i = term.bot; i >= orig+n; i--) { - temp = term.line[i]; - term.line[i] = term.line[i-n]; - term.line[i-n] = temp; - } - - selscroll(orig, n); -} - -void -tscrollup(int orig, int n) -{ - int i; - Line temp; - - LIMIT(n, 0, term.bot-orig+1); - - tclearregion(0, orig, term.col-1, orig+n-1); - tsetdirt(orig+n, term.bot); - - for (i = orig; i <= term.bot-n; i++) { - temp = term.line[i]; - term.line[i] = term.line[i+n]; - term.line[i+n] = temp; - } - - selscroll(orig, -n); -} - -void -selscroll(int orig, int n) -{ - if (sel.ob.x == -1) - return; - - if (BETWEEN(sel.nb.y, orig, term.bot) != BETWEEN(sel.ne.y, orig, term.bot)) { - selclear(); - } else if (BETWEEN(sel.nb.y, orig, term.bot)) { - sel.ob.y += n; - sel.oe.y += n; - if (sel.ob.y < term.top || sel.ob.y > term.bot || - sel.oe.y < term.top || sel.oe.y > term.bot) { - selclear(); - } else { - selnormalize(); - } - } -} - -void -tnewline(int first_col) -{ - int y = term.c.y; - - if (y == term.bot) { - tscrollup(term.top, 1); - } else { - y++; - } - tmoveto(first_col ? 0 : term.c.x, y); -} - -void -csiparse(void) -{ - char *p = csiescseq.buf, *np; - long int v; - - csiescseq.narg = 0; - if (*p == '?') { - csiescseq.priv = 1; - p++; - } - - csiescseq.buf[csiescseq.len] = '\0'; - while (p < csiescseq.buf+csiescseq.len) { - np = NULL; - v = strtol(p, &np, 10); - if (np == p) - v = 0; - if (v == LONG_MAX || v == LONG_MIN) - v = -1; - csiescseq.arg[csiescseq.narg++] = v; - p = np; - if (*p != ';' || csiescseq.narg == ESC_ARG_SIZ) - break; - p++; - } - csiescseq.mode[0] = *p++; - csiescseq.mode[1] = (p < csiescseq.buf+csiescseq.len) ? *p : '\0'; -} - -/* for absolute user moves, when decom is set */ -void -tmoveato(int x, int y) -{ - tmoveto(x, y + ((term.c.state & CURSOR_ORIGIN) ? term.top: 0)); -} - -void -tmoveto(int x, int y) -{ - int miny, maxy; - - if (term.c.state & CURSOR_ORIGIN) { - miny = term.top; - maxy = term.bot; - } else { - miny = 0; - maxy = term.row - 1; - } - term.c.state &= ~CURSOR_WRAPNEXT; - term.c.x = LIMIT(x, 0, term.col-1); - term.c.y = LIMIT(y, miny, maxy); -} - -void -tsetchar(Rune u, const Glyph *attr, int x, int y) -{ - static const char *vt100_0[62] = { /* 0x41 - 0x7e */ - "↑", "↓", "→", "←", "█", "▚", "☃", /* A - G */ - 0, 0, 0, 0, 0, 0, 0, 0, /* H - O */ - 0, 0, 0, 0, 0, 0, 0, 0, /* P - W */ - 0, 0, 0, 0, 0, 0, 0, " ", /* X - _ */ - "◆", "▒", "␉", "␌", "␍", "␊", "°", "±", /* ` - g */ - "", "␋", "┘", "┐", "┌", "└", "┼", "⎺", /* h - o */ - "⎻", "─", "⎼", "⎽", "├", "┤", "┴", "┬", /* p - w */ - "│", "≤", "≥", "π", "≠", "£", "·", /* x - ~ */ - }; - - /* - * The table is proudly stolen from rxvt. - */ - if (term.trantbl[term.charset] == CS_GRAPHIC0 && - BETWEEN(u, 0x41, 0x7e) && vt100_0[u - 0x41]) - utf8decode(vt100_0[u - 0x41], &u, UTF_SIZ); - - if (term.line[y][x].mode & ATTR_WIDE) { - if (x+1 < term.col) { - term.line[y][x+1].u = ' '; - term.line[y][x+1].mode &= ~ATTR_WDUMMY; - } - } else if (term.line[y][x].mode & ATTR_WDUMMY) { - term.line[y][x-1].u = ' '; - term.line[y][x-1].mode &= ~ATTR_WIDE; - } - - term.dirty[y] = 1; - term.line[y][x] = *attr; - term.line[y][x].u = u; -} - -void -tclearregion(int x1, int y1, int x2, int y2) -{ - int x, y, temp; - Glyph *gp; - - if (x1 > x2) - temp = x1, x1 = x2, x2 = temp; - if (y1 > y2) - temp = y1, y1 = y2, y2 = temp; - - LIMIT(x1, 0, term.col-1); - LIMIT(x2, 0, term.col-1); - LIMIT(y1, 0, term.row-1); - LIMIT(y2, 0, term.row-1); - - for (y = y1; y <= y2; y++) { - term.dirty[y] = 1; - for (x = x1; x <= x2; x++) { - gp = &term.line[y][x]; - if (selected(x, y)) - selclear(); - gp->fg = term.c.attr.fg; - gp->bg = term.c.attr.bg; - gp->mode = 0; - gp->u = ' '; - } - } -} - -void -tdeletechar(int n) -{ - int dst, src, size; - Glyph *line; - - LIMIT(n, 0, term.col - term.c.x); - - dst = term.c.x; - src = term.c.x + n; - size = term.col - src; - line = term.line[term.c.y]; - - memmove(&line[dst], &line[src], size * sizeof(Glyph)); - tclearregion(term.col-n, term.c.y, term.col-1, term.c.y); -} - -void -tinsertblank(int n) -{ - int dst, src, size; - Glyph *line; - - LIMIT(n, 0, term.col - term.c.x); - - dst = term.c.x + n; - src = term.c.x; - size = term.col - dst; - line = term.line[term.c.y]; - - memmove(&line[dst], &line[src], size * sizeof(Glyph)); - tclearregion(src, term.c.y, dst - 1, term.c.y); -} - -void -tinsertblankline(int n) -{ - if (BETWEEN(term.c.y, term.top, term.bot)) - tscrolldown(term.c.y, n); -} - -void -tdeleteline(int n) -{ - if (BETWEEN(term.c.y, term.top, term.bot)) - tscrollup(term.c.y, n); -} - -int32_t -tdefcolor(const int *attr, int *npar, int l) -{ - int32_t idx = -1; - uint r, g, b; - - switch (attr[*npar + 1]) { - case 2: /* direct color in RGB space */ - if (*npar + 4 >= l) { - fprintf(stderr, - "erresc(38): Incorrect number of parameters (%d)\n", - *npar); - break; - } - r = attr[*npar + 2]; - g = attr[*npar + 3]; - b = attr[*npar + 4]; - *npar += 4; - if (!BETWEEN(r, 0, 255) || !BETWEEN(g, 0, 255) || !BETWEEN(b, 0, 255)) - fprintf(stderr, "erresc: bad rgb color (%u,%u,%u)\n", - r, g, b); - else - idx = TRUECOLOR(r, g, b); - break; - case 5: /* indexed color */ - if (*npar + 2 >= l) { - fprintf(stderr, - "erresc(38): Incorrect number of parameters (%d)\n", - *npar); - break; - } - *npar += 2; - if (!BETWEEN(attr[*npar], 0, 255)) - fprintf(stderr, "erresc: bad fgcolor %d\n", attr[*npar]); - else - idx = attr[*npar]; - break; - case 0: /* implemented defined (only foreground) */ - case 1: /* transparent */ - case 3: /* direct color in CMY space */ - case 4: /* direct color in CMYK space */ - default: - fprintf(stderr, - "erresc(38): gfx attr %d unknown\n", attr[*npar]); - break; - } - - return idx; -} - -void -tsetattr(const int *attr, int l) -{ - int i; - int32_t idx; - - for (i = 0; i < l; i++) { - switch (attr[i]) { - case 0: - term.c.attr.mode &= ~( - ATTR_BOLD | - ATTR_FAINT | - ATTR_ITALIC | - ATTR_UNDERLINE | - ATTR_BLINK | - ATTR_REVERSE | - ATTR_INVISIBLE | - ATTR_STRUCK ); - term.c.attr.fg = defaultfg; - term.c.attr.bg = defaultbg; - break; - case 1: - term.c.attr.mode |= ATTR_BOLD; - break; - case 2: - term.c.attr.mode |= ATTR_FAINT; - break; - case 3: - term.c.attr.mode |= ATTR_ITALIC; - break; - case 4: - term.c.attr.mode |= ATTR_UNDERLINE; - break; - case 5: /* slow blink */ - /* FALLTHROUGH */ - case 6: /* rapid blink */ - term.c.attr.mode |= ATTR_BLINK; - break; - case 7: - term.c.attr.mode |= ATTR_REVERSE; - break; - case 8: - term.c.attr.mode |= ATTR_INVISIBLE; - break; - case 9: - term.c.attr.mode |= ATTR_STRUCK; - break; - case 22: - term.c.attr.mode &= ~(ATTR_BOLD | ATTR_FAINT); - break; - case 23: - term.c.attr.mode &= ~ATTR_ITALIC; - break; - case 24: - term.c.attr.mode &= ~ATTR_UNDERLINE; - break; - case 25: - term.c.attr.mode &= ~ATTR_BLINK; - break; - case 27: - term.c.attr.mode &= ~ATTR_REVERSE; - break; - case 28: - term.c.attr.mode &= ~ATTR_INVISIBLE; - break; - case 29: - term.c.attr.mode &= ~ATTR_STRUCK; - break; - case 38: - if ((idx = tdefcolor(attr, &i, l)) >= 0) - term.c.attr.fg = idx; - break; - case 39: - term.c.attr.fg = defaultfg; - break; - case 48: - if ((idx = tdefcolor(attr, &i, l)) >= 0) - term.c.attr.bg = idx; - break; - case 49: - term.c.attr.bg = defaultbg; - break; - default: - if (BETWEEN(attr[i], 30, 37)) { - term.c.attr.fg = attr[i] - 30; - } else if (BETWEEN(attr[i], 40, 47)) { - term.c.attr.bg = attr[i] - 40; - } else if (BETWEEN(attr[i], 90, 97)) { - term.c.attr.fg = attr[i] - 90 + 8; - } else if (BETWEEN(attr[i], 100, 107)) { - term.c.attr.bg = attr[i] - 100 + 8; - } else { - fprintf(stderr, - "erresc(default): gfx attr %d unknown\n", - attr[i]); - csidump(); - } - break; - } - } -} - -void -tsetscroll(int t, int b) -{ - int temp; - - LIMIT(t, 0, term.row-1); - LIMIT(b, 0, term.row-1); - if (t > b) { - temp = t; - t = b; - b = temp; - } - term.top = t; - term.bot = b; -} - -void -tsetmode(int priv, int set, const int *args, int narg) -{ - int alt; const int *lim; - - for (lim = args + narg; args < lim; ++args) { - if (priv) { - switch (*args) { - case 1: /* DECCKM -- Cursor key */ - xsetmode(set, MODE_APPCURSOR); - break; - case 5: /* DECSCNM -- Reverse video */ - xsetmode(set, MODE_REVERSE); - break; - case 6: /* DECOM -- Origin */ - MODBIT(term.c.state, set, CURSOR_ORIGIN); - tmoveato(0, 0); - break; - case 7: /* DECAWM -- Auto wrap */ - MODBIT(term.mode, set, MODE_WRAP); - break; - case 0: /* Error (IGNORED) */ - case 2: /* DECANM -- ANSI/VT52 (IGNORED) */ - case 3: /* DECCOLM -- Column (IGNORED) */ - case 4: /* DECSCLM -- Scroll (IGNORED) */ - case 8: /* DECARM -- Auto repeat (IGNORED) */ - case 18: /* DECPFF -- Printer feed (IGNORED) */ - case 19: /* DECPEX -- Printer extent (IGNORED) */ - case 42: /* DECNRCM -- National characters (IGNORED) */ - case 12: /* att610 -- Start blinking cursor (IGNORED) */ - break; - case 25: /* DECTCEM -- Text Cursor Enable Mode */ - xsetmode(!set, MODE_HIDE); - break; - case 9: /* X10 mouse compatibility mode */ - xsetpointermotion(0); - xsetmode(0, MODE_MOUSE); - xsetmode(set, MODE_MOUSEX10); - break; - case 1000: /* 1000: report button press */ - xsetpointermotion(0); - xsetmode(0, MODE_MOUSE); - xsetmode(set, MODE_MOUSEBTN); - break; - case 1002: /* 1002: report motion on button press */ - xsetpointermotion(0); - xsetmode(0, MODE_MOUSE); - xsetmode(set, MODE_MOUSEMOTION); - break; - case 1003: /* 1003: enable all mouse motions */ - xsetpointermotion(set); - xsetmode(0, MODE_MOUSE); - xsetmode(set, MODE_MOUSEMANY); - break; - case 1004: /* 1004: send focus events to tty */ - xsetmode(set, MODE_FOCUS); - break; - case 1006: /* 1006: extended reporting mode */ - xsetmode(set, MODE_MOUSESGR); - break; - case 1034: - xsetmode(set, MODE_8BIT); - break; - case 1049: /* swap screen & set/restore cursor as xterm */ - if (!allowaltscreen) - break; - tcursor((set) ? CURSOR_SAVE : CURSOR_LOAD); - /* FALLTHROUGH */ - case 47: /* swap screen */ - case 1047: - if (!allowaltscreen) - break; - alt = IS_SET(MODE_ALTSCREEN); - if (alt) { - tclearregion(0, 0, term.col-1, - term.row-1); - } - if (set ^ alt) /* set is always 1 or 0 */ - tswapscreen(); - if (*args != 1049) - break; - /* FALLTHROUGH */ - case 1048: - tcursor((set) ? CURSOR_SAVE : CURSOR_LOAD); - break; - case 2004: /* 2004: bracketed paste mode */ - xsetmode(set, MODE_BRCKTPASTE); - break; - /* Not implemented mouse modes. See comments there. */ - case 1001: /* mouse highlight mode; can hang the - terminal by design when implemented. */ - case 1005: /* UTF-8 mouse mode; will confuse - applications not supporting UTF-8 - and luit. */ - case 1015: /* urxvt mangled mouse mode; incompatible - and can be mistaken for other control - codes. */ - break; - default: - fprintf(stderr, - "erresc: unknown private set/reset mode %d\n", - *args); - break; - } - } else { - switch (*args) { - case 0: /* Error (IGNORED) */ - break; - case 2: - xsetmode(set, MODE_KBDLOCK); - break; - case 4: /* IRM -- Insertion-replacement */ - MODBIT(term.mode, set, MODE_INSERT); - break; - case 12: /* SRM -- Send/Receive */ - MODBIT(term.mode, !set, MODE_ECHO); - break; - case 20: /* LNM -- Linefeed/new line */ - MODBIT(term.mode, set, MODE_CRLF); - break; - default: - fprintf(stderr, - "erresc: unknown set/reset mode %d\n", - *args); - break; - } - } - } -} - -void -csihandle(void) -{ - char buf[40]; - int len; - - switch (csiescseq.mode[0]) { - default: - unknown: - fprintf(stderr, "erresc: unknown csi "); - csidump(); - /* die(""); */ - break; - case '@': /* ICH -- Insert <n> blank char */ - DEFAULT(csiescseq.arg[0], 1); - tinsertblank(csiescseq.arg[0]); - break; - case 'A': /* CUU -- Cursor <n> Up */ - DEFAULT(csiescseq.arg[0], 1); - tmoveto(term.c.x, term.c.y-csiescseq.arg[0]); - break; - case 'B': /* CUD -- Cursor <n> Down */ - case 'e': /* VPR --Cursor <n> Down */ - DEFAULT(csiescseq.arg[0], 1); - tmoveto(term.c.x, term.c.y+csiescseq.arg[0]); - break; - case 'i': /* MC -- Media Copy */ - switch (csiescseq.arg[0]) { - case 0: - tdump(); - break; - case 1: - tdumpline(term.c.y); - break; - case 2: - tdumpsel(); - break; - case 4: - term.mode &= ~MODE_PRINT; - break; - case 5: - term.mode |= MODE_PRINT; - break; - } - break; - case 'c': /* DA -- Device Attributes */ - if (csiescseq.arg[0] == 0) - ttywrite(vtiden, strlen(vtiden), 0); - break; - case 'b': /* REP -- if last char is printable print it <n> more times */ - DEFAULT(csiescseq.arg[0], 1); - if (term.lastc) - while (csiescseq.arg[0]-- > 0) - tputc(term.lastc); - break; - case 'C': /* CUF -- Cursor <n> Forward */ - case 'a': /* HPR -- Cursor <n> Forward */ - DEFAULT(csiescseq.arg[0], 1); - tmoveto(term.c.x+csiescseq.arg[0], term.c.y); - break; - case 'D': /* CUB -- Cursor <n> Backward */ - DEFAULT(csiescseq.arg[0], 1); - tmoveto(term.c.x-csiescseq.arg[0], term.c.y); - break; - case 'E': /* CNL -- Cursor <n> Down and first col */ - DEFAULT(csiescseq.arg[0], 1); - tmoveto(0, term.c.y+csiescseq.arg[0]); - break; - case 'F': /* CPL -- Cursor <n> Up and first col */ - DEFAULT(csiescseq.arg[0], 1); - tmoveto(0, term.c.y-csiescseq.arg[0]); - break; - case 'g': /* TBC -- Tabulation clear */ - switch (csiescseq.arg[0]) { - case 0: /* clear current tab stop */ - term.tabs[term.c.x] = 0; - break; - case 3: /* clear all the tabs */ - memset(term.tabs, 0, term.col * sizeof(*term.tabs)); - break; - default: - goto unknown; - } - break; - case 'G': /* CHA -- Move to <col> */ - case '`': /* HPA */ - DEFAULT(csiescseq.arg[0], 1); - tmoveto(csiescseq.arg[0]-1, term.c.y); - break; - case 'H': /* CUP -- Move to <row> <col> */ - case 'f': /* HVP */ - DEFAULT(csiescseq.arg[0], 1); - DEFAULT(csiescseq.arg[1], 1); - tmoveato(csiescseq.arg[1]-1, csiescseq.arg[0]-1); - break; - case 'I': /* CHT -- Cursor Forward Tabulation <n> tab stops */ - DEFAULT(csiescseq.arg[0], 1); - tputtab(csiescseq.arg[0]); - break; - case 'J': /* ED -- Clear screen */ - switch (csiescseq.arg[0]) { - case 0: /* below */ - tclearregion(term.c.x, term.c.y, term.col-1, term.c.y); - if (term.c.y < term.row-1) { - tclearregion(0, term.c.y+1, term.col-1, - term.row-1); - } - break; - case 1: /* above */ - if (term.c.y > 1) - tclearregion(0, 0, term.col-1, term.c.y-1); - tclearregion(0, term.c.y, term.c.x, term.c.y); - break; - case 2: /* all */ - tclearregion(0, 0, term.col-1, term.row-1); - break; - default: - goto unknown; - } - break; - case 'K': /* EL -- Clear line */ - switch (csiescseq.arg[0]) { - case 0: /* right */ - tclearregion(term.c.x, term.c.y, term.col-1, - term.c.y); - break; - case 1: /* left */ - tclearregion(0, term.c.y, term.c.x, term.c.y); - break; - case 2: /* all */ - tclearregion(0, term.c.y, term.col-1, term.c.y); - break; - } - break; - case 'S': /* SU -- Scroll <n> line up */ - DEFAULT(csiescseq.arg[0], 1); - tscrollup(term.top, csiescseq.arg[0]); - break; - case 'T': /* SD -- Scroll <n> line down */ - DEFAULT(csiescseq.arg[0], 1); - tscrolldown(term.top, csiescseq.arg[0]); - break; - case 'L': /* IL -- Insert <n> blank lines */ - DEFAULT(csiescseq.arg[0], 1); - tinsertblankline(csiescseq.arg[0]); - break; - case 'l': /* RM -- Reset Mode */ - tsetmode(csiescseq.priv, 0, csiescseq.arg, csiescseq.narg); - break; - case 'M': /* DL -- Delete <n> lines */ - DEFAULT(csiescseq.arg[0], 1); - tdeleteline(csiescseq.arg[0]); - break; - case 'X': /* ECH -- Erase <n> char */ - DEFAULT(csiescseq.arg[0], 1); - tclearregion(term.c.x, term.c.y, - term.c.x + csiescseq.arg[0] - 1, term.c.y); - break; - case 'P': /* DCH -- Delete <n> char */ - DEFAULT(csiescseq.arg[0], 1); - tdeletechar(csiescseq.arg[0]); - break; - case 'Z': /* CBT -- Cursor Backward Tabulation <n> tab stops */ - DEFAULT(csiescseq.arg[0], 1); - tputtab(-csiescseq.arg[0]); - break; - case 'd': /* VPA -- Move to <row> */ - DEFAULT(csiescseq.arg[0], 1); - tmoveato(term.c.x, csiescseq.arg[0]-1); - break; - case 'h': /* SM -- Set terminal mode */ - tsetmode(csiescseq.priv, 1, csiescseq.arg, csiescseq.narg); - break; - case 'm': /* SGR -- Terminal attribute (color) */ - tsetattr(csiescseq.arg, csiescseq.narg); - break; - case 'n': /* DSR – Device Status Report (cursor position) */ - if (csiescseq.arg[0] == 6) { - len = snprintf(buf, sizeof(buf), "\033[%i;%iR", - term.c.y+1, term.c.x+1); - ttywrite(buf, len, 0); - } - break; - case 'r': /* DECSTBM -- Set Scrolling Region */ - if (csiescseq.priv) { - goto unknown; - } else { - DEFAULT(csiescseq.arg[0], 1); - DEFAULT(csiescseq.arg[1], term.row); - tsetscroll(csiescseq.arg[0]-1, csiescseq.arg[1]-1); - tmoveato(0, 0); - } - break; - case 's': /* DECSC -- Save cursor position (ANSI.SYS) */ - tcursor(CURSOR_SAVE); - break; - case 'u': /* DECRC -- Restore cursor position (ANSI.SYS) */ - tcursor(CURSOR_LOAD); - break; - case ' ': - switch (csiescseq.mode[1]) { - case 'q': /* DECSCUSR -- Set Cursor Style */ - if (xsetcursor(csiescseq.arg[0])) - goto unknown; - break; - default: - goto unknown; - } - break; - } -} - -void -csidump(void) -{ - size_t i; - uint c; - - fprintf(stderr, "ESC["); - for (i = 0; i < csiescseq.len; i++) { - c = csiescseq.buf[i] & 0xff; - if (isprint(c)) { - putc(c, stderr); - } else if (c == '\n') { - fprintf(stderr, "(\\n)"); - } else if (c == '\r') { - fprintf(stderr, "(\\r)"); - } else if (c == 0x1b) { - fprintf(stderr, "(\\e)"); - } else { - fprintf(stderr, "(%02x)", c); - } - } - putc('\n', stderr); -} - -void -csireset(void) -{ - memset(&csiescseq, 0, sizeof(csiescseq)); -} - -void -osc_color_response(int num, int index, int is_osc4) -{ - int n; - char buf[32]; - unsigned char r, g, b; - - if (xgetcolor(is_osc4 ? num : index, &r, &g, &b)) { - fprintf(stderr, "erresc: failed to fetch %s color %d\n", - is_osc4 ? "osc4" : "osc", - is_osc4 ? num : index); - return; - } - - n = snprintf(buf, sizeof buf, "\033]%s%d;rgb:%02x%02x/%02x%02x/%02x%02x\007", - is_osc4 ? "4;" : "", num, r, r, g, g, b, b); - if (n < 0 || n >= sizeof(buf)) { - fprintf(stderr, "error: %s while printing %s response\n", - n < 0 ? "snprintf failed" : "truncation occurred", - is_osc4 ? "osc4" : "osc"); - } else { - ttywrite(buf, n, 1); - } -} - -void -strhandle(void) -{ - char *p = NULL, *dec; - int j, narg, par; - const struct { int idx; char *str; } osc_table[] = { - { defaultfg, "foreground" }, - { defaultbg, "background" }, - { defaultcs, "cursor" } - }; - - term.esc &= ~(ESC_STR_END|ESC_STR); - strparse(); - par = (narg = strescseq.narg) ? atoi(strescseq.args[0]) : 0; - - switch (strescseq.type) { - case ']': /* OSC -- Operating System Command */ - switch (par) { - case 0: - if (narg > 1) { - xsettitle(strescseq.args[1]); - xseticontitle(strescseq.args[1]); - } - return; - case 1: - if (narg > 1) - xseticontitle(strescseq.args[1]); - return; - case 2: - if (narg > 1) - xsettitle(strescseq.args[1]); - return; - case 52: - if (narg > 2 && allowwindowops) { - dec = base64dec(strescseq.args[2]); - if (dec) { - xsetsel(dec); - xclipcopy(); - } else { - fprintf(stderr, "erresc: invalid base64\n"); - } - } - return; - case 10: - case 11: - case 12: - if (narg < 2) - break; - p = strescseq.args[1]; - if ((j = par - 10) < 0 || j >= LEN(osc_table)) - break; /* shouldn't be possible */ - - if (!strcmp(p, "?")) { - osc_color_response(par, osc_table[j].idx, 0); - } else if (xsetcolorname(osc_table[j].idx, p)) { - fprintf(stderr, "erresc: invalid %s color: %s\n", - osc_table[j].str, p); - } else { - tfulldirt(); - } - return; - case 4: /* color set */ - if (narg < 3) - break; - p = strescseq.args[2]; - /* FALLTHROUGH */ - case 104: /* color reset */ - j = (narg > 1) ? atoi(strescseq.args[1]) : -1; - - if (p && !strcmp(p, "?")) { - osc_color_response(j, 0, 1); - } else if (xsetcolorname(j, p)) { - if (par == 104 && narg <= 1) - return; /* color reset without parameter */ - fprintf(stderr, "erresc: invalid color j=%d, p=%s\n", - j, p ? p : "(null)"); - } else { - /* - * TODO if defaultbg color is changed, borders - * are dirty - */ - tfulldirt(); - } - return; - } - break; - case 'k': /* old title set compatibility */ - xsettitle(strescseq.args[0]); - return; - case 'P': /* DCS -- Device Control String */ - case '_': /* APC -- Application Program Command */ - case '^': /* PM -- Privacy Message */ - return; - } - - fprintf(stderr, "erresc: unknown str "); - strdump(); -} - -void -strparse(void) -{ - int c; - char *p = strescseq.buf; - - strescseq.narg = 0; - strescseq.buf[strescseq.len] = '\0'; - - if (*p == '\0') - return; - - while (strescseq.narg < STR_ARG_SIZ) { - strescseq.args[strescseq.narg++] = p; - while ((c = *p) != ';' && c != '\0') - ++p; - if (c == '\0') - return; - *p++ = '\0'; - } -} - -void -strdump(void) -{ - size_t i; - uint c; - - fprintf(stderr, "ESC%c", strescseq.type); - for (i = 0; i < strescseq.len; i++) { - c = strescseq.buf[i] & 0xff; - if (c == '\0') { - putc('\n', stderr); - return; - } else if (isprint(c)) { - putc(c, stderr); - } else if (c == '\n') { - fprintf(stderr, "(\\n)"); - } else if (c == '\r') { - fprintf(stderr, "(\\r)"); - } else if (c == 0x1b) { - fprintf(stderr, "(\\e)"); - } else { - fprintf(stderr, "(%02x)", c); - } - } - fprintf(stderr, "ESC\\\n"); -} - -void -strreset(void) -{ - strescseq = (STREscape){ - .buf = xrealloc(strescseq.buf, STR_BUF_SIZ), - .siz = STR_BUF_SIZ, - }; -} - -void -sendbreak(const Arg *arg) -{ - if (tcsendbreak(cmdfd, 0)) - perror("Error sending break"); -} - -void -tprinter(char *s, size_t len) -{ - if (iofd != -1 && xwrite(iofd, s, len) < 0) { - perror("Error writing to output file"); - close(iofd); - iofd = -1; - } -} - -void -toggleprinter(const Arg *arg) -{ - term.mode ^= MODE_PRINT; -} - -void -printscreen(const Arg *arg) -{ - tdump(); -} - -void -printsel(const Arg *arg) -{ - tdumpsel(); -} - -void -tdumpsel(void) -{ - char *ptr; - - if ((ptr = getsel())) { - tprinter(ptr, strlen(ptr)); - free(ptr); - } -} - -void -tdumpline(int n) -{ - char buf[UTF_SIZ]; - const Glyph *bp, *end; - - bp = &term.line[n][0]; - end = &bp[MIN(tlinelen(n), term.col) - 1]; - if (bp != end || bp->u != ' ') { - for ( ; bp <= end; ++bp) - tprinter(buf, utf8encode(bp->u, buf)); - } - tprinter("\n", 1); -} - -void -tdump(void) -{ - int i; - - for (i = 0; i < term.row; ++i) - tdumpline(i); -} - -void -tputtab(int n) -{ - uint x = term.c.x; - - if (n > 0) { - while (x < term.col && n--) - for (++x; x < term.col && !term.tabs[x]; ++x) - /* nothing */ ; - } else if (n < 0) { - while (x > 0 && n++) - for (--x; x > 0 && !term.tabs[x]; --x) - /* nothing */ ; - } - term.c.x = LIMIT(x, 0, term.col-1); -} - -void -tdefutf8(char ascii) -{ - if (ascii == 'G') - term.mode |= MODE_UTF8; - else if (ascii == '@') - term.mode &= ~MODE_UTF8; -} - -void -tdeftran(char ascii) -{ - static char cs[] = "0B"; - static int vcs[] = {CS_GRAPHIC0, CS_USA}; - char *p; - - if ((p = strchr(cs, ascii)) == NULL) { - fprintf(stderr, "esc unhandled charset: ESC ( %c\n", ascii); - } else { - term.trantbl[term.icharset] = vcs[p - cs]; - } -} - -void -tdectest(char c) -{ - int x, y; - - if (c == '8') { /* DEC screen alignment test. */ - for (x = 0; x < term.col; ++x) { - for (y = 0; y < term.row; ++y) - tsetchar('E', &term.c.attr, x, y); - } - } -} - -void -tstrsequence(uchar c) -{ - switch (c) { - case 0x90: /* DCS -- Device Control String */ - c = 'P'; - break; - case 0x9f: /* APC -- Application Program Command */ - c = '_'; - break; - case 0x9e: /* PM -- Privacy Message */ - c = '^'; - break; - case 0x9d: /* OSC -- Operating System Command */ - c = ']'; - break; - } - strreset(); - strescseq.type = c; - term.esc |= ESC_STR; -} - -void -tcontrolcode(uchar ascii) -{ - switch (ascii) { - case '\t': /* HT */ - tputtab(1); - return; - case '\b': /* BS */ - tmoveto(term.c.x-1, term.c.y); - return; - case '\r': /* CR */ - tmoveto(0, term.c.y); - return; - case '\f': /* LF */ - case '\v': /* VT */ - case '\n': /* LF */ - /* go to first col if the mode is set */ - tnewline(IS_SET(MODE_CRLF)); - return; - case '\a': /* BEL */ - if (term.esc & ESC_STR_END) { - /* backwards compatibility to xterm */ - strhandle(); - } else { - xbell(); - } - break; - case '\033': /* ESC */ - csireset(); - term.esc &= ~(ESC_CSI|ESC_ALTCHARSET|ESC_TEST); - term.esc |= ESC_START; - return; - case '\016': /* SO (LS1 -- Locking shift 1) */ - case '\017': /* SI (LS0 -- Locking shift 0) */ - term.charset = 1 - (ascii - '\016'); - return; - case '\032': /* SUB */ - tsetchar('?', &term.c.attr, term.c.x, term.c.y); - /* FALLTHROUGH */ - case '\030': /* CAN */ - csireset(); - break; - case '\005': /* ENQ (IGNORED) */ - case '\000': /* NUL (IGNORED) */ - case '\021': /* XON (IGNORED) */ - case '\023': /* XOFF (IGNORED) */ - case 0177: /* DEL (IGNORED) */ - return; - case 0x80: /* TODO: PAD */ - case 0x81: /* TODO: HOP */ - case 0x82: /* TODO: BPH */ - case 0x83: /* TODO: NBH */ - case 0x84: /* TODO: IND */ - break; - case 0x85: /* NEL -- Next line */ - tnewline(1); /* always go to first col */ - break; - case 0x86: /* TODO: SSA */ - case 0x87: /* TODO: ESA */ - break; - case 0x88: /* HTS -- Horizontal tab stop */ - term.tabs[term.c.x] = 1; - break; - case 0x89: /* TODO: HTJ */ - case 0x8a: /* TODO: VTS */ - case 0x8b: /* TODO: PLD */ - case 0x8c: /* TODO: PLU */ - case 0x8d: /* TODO: RI */ - case 0x8e: /* TODO: SS2 */ - case 0x8f: /* TODO: SS3 */ - case 0x91: /* TODO: PU1 */ - case 0x92: /* TODO: PU2 */ - case 0x93: /* TODO: STS */ - case 0x94: /* TODO: CCH */ - case 0x95: /* TODO: MW */ - case 0x96: /* TODO: SPA */ - case 0x97: /* TODO: EPA */ - case 0x98: /* TODO: SOS */ - case 0x99: /* TODO: SGCI */ - break; - case 0x9a: /* DECID -- Identify Terminal */ - ttywrite(vtiden, strlen(vtiden), 0); - break; - case 0x9b: /* TODO: CSI */ - case 0x9c: /* TODO: ST */ - break; - case 0x90: /* DCS -- Device Control String */ - case 0x9d: /* OSC -- Operating System Command */ - case 0x9e: /* PM -- Privacy Message */ - case 0x9f: /* APC -- Application Program Command */ - tstrsequence(ascii); - return; - } - /* only CAN, SUB, \a and C1 chars interrupt a sequence */ - term.esc &= ~(ESC_STR_END|ESC_STR); -} - -/* - * returns 1 when the sequence is finished and it hasn't to read - * more characters for this sequence, otherwise 0 - */ -int -eschandle(uchar ascii) -{ - switch (ascii) { - case '[': - term.esc |= ESC_CSI; - return 0; - case '#': - term.esc |= ESC_TEST; - return 0; - case '%': - term.esc |= ESC_UTF8; - return 0; - case 'P': /* DCS -- Device Control String */ - case '_': /* APC -- Application Program Command */ - case '^': /* PM -- Privacy Message */ - case ']': /* OSC -- Operating System Command */ - case 'k': /* old title set compatibility */ - tstrsequence(ascii); - return 0; - case 'n': /* LS2 -- Locking shift 2 */ - case 'o': /* LS3 -- Locking shift 3 */ - term.charset = 2 + (ascii - 'n'); - break; - case '(': /* GZD4 -- set primary charset G0 */ - case ')': /* G1D4 -- set secondary charset G1 */ - case '*': /* G2D4 -- set tertiary charset G2 */ - case '+': /* G3D4 -- set quaternary charset G3 */ - term.icharset = ascii - '('; - term.esc |= ESC_ALTCHARSET; - return 0; - case 'D': /* IND -- Linefeed */ - if (term.c.y == term.bot) { - tscrollup(term.top, 1); - } else { - tmoveto(term.c.x, term.c.y+1); - } - break; - case 'E': /* NEL -- Next line */ - tnewline(1); /* always go to first col */ - break; - case 'H': /* HTS -- Horizontal tab stop */ - term.tabs[term.c.x] = 1; - break; - case 'M': /* RI -- Reverse index */ - if (term.c.y == term.top) { - tscrolldown(term.top, 1); - } else { - tmoveto(term.c.x, term.c.y-1); - } - break; - case 'Z': /* DECID -- Identify Terminal */ - ttywrite(vtiden, strlen(vtiden), 0); - break; - case 'c': /* RIS -- Reset to initial state */ - treset(); - resettitle(); - xloadcols(); - break; - case '=': /* DECPAM -- Application keypad */ - xsetmode(1, MODE_APPKEYPAD); - break; - case '>': /* DECPNM -- Normal keypad */ - xsetmode(0, MODE_APPKEYPAD); - break; - case '7': /* DECSC -- Save Cursor */ - tcursor(CURSOR_SAVE); - break; - case '8': /* DECRC -- Restore Cursor */ - tcursor(CURSOR_LOAD); - break; - case '\\': /* ST -- String Terminator */ - if (term.esc & ESC_STR_END) - strhandle(); - break; - default: - fprintf(stderr, "erresc: unknown sequence ESC 0x%02X '%c'\n", - (uchar) ascii, isprint(ascii)? ascii:'.'); - break; - } - return 1; -} - -void -tputc(Rune u) -{ - char c[UTF_SIZ]; - int control; - int width, len; - Glyph *gp; - - control = ISCONTROL(u); - if (u < 127 || !IS_SET(MODE_UTF8)) { - c[0] = u; - width = len = 1; - } else { - len = utf8encode(u, c); - if (!control && (width = wcwidth(u)) == -1) - width = 1; - } - - if (IS_SET(MODE_PRINT)) - tprinter(c, len); - - /* - * STR sequence must be checked before anything else - * because it uses all following characters until it - * receives a ESC, a SUB, a ST or any other C1 control - * character. - */ - if (term.esc & ESC_STR) { - if (u == '\a' || u == 030 || u == 032 || u == 033 || - ISCONTROLC1(u)) { - term.esc &= ~(ESC_START|ESC_STR); - term.esc |= ESC_STR_END; - goto check_control_code; - } - - if (strescseq.len+len >= strescseq.siz) { - /* - * Here is a bug in terminals. If the user never sends - * some code to stop the str or esc command, then st - * will stop responding. But this is better than - * silently failing with unknown characters. At least - * then users will report back. - * - * In the case users ever get fixed, here is the code: - */ - /* - * term.esc = 0; - * strhandle(); - */ - if (strescseq.siz > (SIZE_MAX - UTF_SIZ) / 2) - return; - strescseq.siz *= 2; - strescseq.buf = xrealloc(strescseq.buf, strescseq.siz); - } - - memmove(&strescseq.buf[strescseq.len], c, len); - strescseq.len += len; - return; - } - -check_control_code: - /* - * Actions of control codes must be performed as soon they arrive - * because they can be embedded inside a control sequence, and - * they must not cause conflicts with sequences. - */ - if (control) { - tcontrolcode(u); - /* - * control codes are not shown ever - */ - if (!term.esc) - term.lastc = 0; - return; - } else if (term.esc & ESC_START) { - if (term.esc & ESC_CSI) { - csiescseq.buf[csiescseq.len++] = u; - if (BETWEEN(u, 0x40, 0x7E) - || csiescseq.len >= \ - sizeof(csiescseq.buf)-1) { - term.esc = 0; - csiparse(); - csihandle(); - } - return; - } else if (term.esc & ESC_UTF8) { - tdefutf8(u); - } else if (term.esc & ESC_ALTCHARSET) { - tdeftran(u); - } else if (term.esc & ESC_TEST) { - tdectest(u); - } else { - if (!eschandle(u)) - return; - /* sequence already finished */ - } - term.esc = 0; - /* - * All characters which form part of a sequence are not - * printed - */ - return; - } - if (selected(term.c.x, term.c.y)) - selclear(); - - gp = &term.line[term.c.y][term.c.x]; - if (IS_SET(MODE_WRAP) && (term.c.state & CURSOR_WRAPNEXT)) { - gp->mode |= ATTR_WRAP; - tnewline(1); - gp = &term.line[term.c.y][term.c.x]; - } - - if (IS_SET(MODE_INSERT) && term.c.x+width < term.col) - memmove(gp+width, gp, (term.col - term.c.x - width) * sizeof(Glyph)); - - if (term.c.x+width > term.col) { - tnewline(1); - gp = &term.line[term.c.y][term.c.x]; - } - - tsetchar(u, &term.c.attr, term.c.x, term.c.y); - term.lastc = u; - - if (width == 2) { - gp->mode |= ATTR_WIDE; - if (term.c.x+1 < term.col) { - if (gp[1].mode == ATTR_WIDE && term.c.x+2 < term.col) { - gp[2].u = ' '; - gp[2].mode &= ~ATTR_WDUMMY; - } - gp[1].u = '\0'; - gp[1].mode = ATTR_WDUMMY; - } - } - if (term.c.x+width < term.col) { - tmoveto(term.c.x+width, term.c.y); - } else { - term.c.state |= CURSOR_WRAPNEXT; - } -} - -int -twrite(const char *buf, int buflen, int show_ctrl) -{ - int charsize; - Rune u; - int n; - - for (n = 0; n < buflen; n += charsize) { - if (IS_SET(MODE_UTF8)) { - /* process a complete utf8 char */ - charsize = utf8decode(buf + n, &u, buflen - n); - if (charsize == 0) - break; - } else { - u = buf[n] & 0xFF; - charsize = 1; - } - if (show_ctrl && ISCONTROL(u)) { - if (u & 0x80) { - u &= 0x7f; - tputc('^'); - tputc('['); - } else if (u != '\n' && u != '\r' && u != '\t') { - u ^= 0x40; - tputc('^'); - } - } - tputc(u); - } - return n; -} - -void -tresize(int col, int row) -{ - int i; - int minrow = MIN(row, term.row); - int mincol = MIN(col, term.col); - int *bp; - TCursor c; - - if (col < 1 || row < 1) { - fprintf(stderr, - "tresize: error resizing to %dx%d\n", col, row); - return; - } - - /* - * slide screen to keep cursor where we expect it - - * tscrollup would work here, but we can optimize to - * memmove because we're freeing the earlier lines - */ - for (i = 0; i <= term.c.y - row; i++) { - free(term.line[i]); - free(term.alt[i]); - } - /* ensure that both src and dst are not NULL */ - if (i > 0) { - memmove(term.line, term.line + i, row * sizeof(Line)); - memmove(term.alt, term.alt + i, row * sizeof(Line)); - } - for (i += row; i < term.row; i++) { - free(term.line[i]); - free(term.alt[i]); - } - - /* resize to new height */ - term.line = xrealloc(term.line, row * sizeof(Line)); - term.alt = xrealloc(term.alt, row * sizeof(Line)); - term.dirty = xrealloc(term.dirty, row * sizeof(*term.dirty)); - term.tabs = xrealloc(term.tabs, col * sizeof(*term.tabs)); - - /* resize each row to new width, zero-pad if needed */ - for (i = 0; i < minrow; i++) { - term.line[i] = xrealloc(term.line[i], col * sizeof(Glyph)); - term.alt[i] = xrealloc(term.alt[i], col * sizeof(Glyph)); - } - - /* allocate any new rows */ - for (/* i = minrow */; i < row; i++) { - term.line[i] = xmalloc(col * sizeof(Glyph)); - term.alt[i] = xmalloc(col * sizeof(Glyph)); - } - if (col > term.col) { - bp = term.tabs + term.col; - - memset(bp, 0, sizeof(*term.tabs) * (col - term.col)); - while (--bp > term.tabs && !*bp) - /* nothing */ ; - for (bp += tabspaces; bp < term.tabs + col; bp += tabspaces) - *bp = 1; - } - /* update terminal size */ - term.col = col; - term.row = row; - /* reset scrolling region */ - tsetscroll(0, row-1); - /* make use of the LIMIT in tmoveto */ - tmoveto(term.c.x, term.c.y); - /* Clearing both screens (it makes dirty all lines) */ - c = term.c; - for (i = 0; i < 2; i++) { - if (mincol < col && 0 < minrow) { - tclearregion(mincol, 0, col - 1, minrow - 1); - } - if (0 < col && minrow < row) { - tclearregion(0, minrow, col - 1, row - 1); - } - tswapscreen(); - tcursor(CURSOR_LOAD); - } - term.c = c; -} - -void -resettitle(void) -{ - xsettitle(NULL); -} - -void -drawregion(int x1, int y1, int x2, int y2) -{ - int y; - - for (y = y1; y < y2; y++) { - if (!term.dirty[y]) - continue; - - term.dirty[y] = 0; - xdrawline(term.line[y], x1, y, x2); - } -} - -void -draw(void) -{ - int cx = term.c.x, ocx = term.ocx, ocy = term.ocy; - - if (!xstartdraw()) - return; - - /* adjust cursor position */ - LIMIT(term.ocx, 0, term.col-1); - LIMIT(term.ocy, 0, term.row-1); - if (term.line[term.ocy][term.ocx].mode & ATTR_WDUMMY) - term.ocx--; - if (term.line[term.c.y][cx].mode & ATTR_WDUMMY) - cx--; - - drawregion(0, 0, term.col, term.row); - xdrawcursor(cx, term.c.y, term.line[term.c.y][cx], - term.ocx, term.ocy, term.line[term.ocy][term.ocx]); - term.ocx = cx; - term.ocy = term.c.y; - xfinishdraw(); - if (ocx != term.ocx || ocy != term.ocy) - xximspot(term.ocx, term.ocy); -} - -void -redraw(void) -{ - tfulldirt(); - draw(); -} diff --git a/utils/st-0.9/st.h b/utils/st-0.9/st.h deleted file mode 100644 index 78762a2..0000000 --- a/utils/st-0.9/st.h +++ /dev/null @@ -1,129 +0,0 @@ -/* See LICENSE for license details. */ - -#include <stdint.h> -#include <sys/types.h> - -/* macros */ -#define MIN(a, b) ((a) < (b) ? (a) : (b)) -#define MAX(a, b) ((a) < (b) ? (b) : (a)) -#define LEN(a) (sizeof(a) / sizeof(a)[0]) -#define BETWEEN(x, a, b) ((a) <= (x) && (x) <= (b)) -#define DIVCEIL(n, d) (((n) + ((d) - 1)) / (d)) -#define DEFAULT(a, b) (a) = (a) ? (a) : (b) -#define LIMIT(x, a, b) (x) = (x) < (a) ? (a) : (x) > (b) ? (b) : (x) -#define ATTRCMP(a, b) ((a).mode != (b).mode || (a).fg != (b).fg || \ - (a).bg != (b).bg) -#define TIMEDIFF(t1, t2) ((t1.tv_sec-t2.tv_sec)*1000 + \ - (t1.tv_nsec-t2.tv_nsec)/1E6) -#define MODBIT(x, set, bit) ((set) ? ((x) |= (bit)) : ((x) &= ~(bit))) - -#define TRUECOLOR(r,g,b) (1 << 24 | (r) << 16 | (g) << 8 | (b)) -#define IS_TRUECOL(x) (1 << 24 & (x)) - -enum glyph_attribute { - ATTR_NULL = 0, - ATTR_BOLD = 1 << 0, - ATTR_FAINT = 1 << 1, - ATTR_ITALIC = 1 << 2, - ATTR_UNDERLINE = 1 << 3, - ATTR_BLINK = 1 << 4, - ATTR_REVERSE = 1 << 5, - ATTR_INVISIBLE = 1 << 6, - ATTR_STRUCK = 1 << 7, - ATTR_WRAP = 1 << 8, - ATTR_WIDE = 1 << 9, - ATTR_WDUMMY = 1 << 10, - ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT, -}; - -enum selection_mode { - SEL_IDLE = 0, - SEL_EMPTY = 1, - SEL_READY = 2 -}; - -enum selection_type { - SEL_REGULAR = 1, - SEL_RECTANGULAR = 2 -}; - -enum selection_snap { - SNAP_WORD = 1, - SNAP_LINE = 2 -}; - -typedef unsigned char uchar; -typedef unsigned int uint; -typedef unsigned long ulong; -typedef unsigned short ushort; - -typedef uint_least32_t Rune; - -#define Glyph Glyph_ -typedef struct { - Rune u; /* character code */ - ushort mode; /* attribute flags */ - uint32_t fg; /* foreground */ - uint32_t bg; /* background */ -} Glyph; - -typedef Glyph *Line; - -typedef union { - int i; - uint ui; - float f; - const void *v; - const char *s; -} Arg; - -void die(const char *, ...); -void redraw(void); -void draw(void); - -void kscrolldown(const Arg *); -void kscrollup(const Arg *); -void printscreen(const Arg *); -void printsel(const Arg *); -void sendbreak(const Arg *); -void toggleprinter(const Arg *); - -int tattrset(int); -void tnew(int, int); -void tresize(int, int); -void tsetdirtattr(int); -void ttyhangup(void); -int ttynew(const char *, char *, const char *, char **); -size_t ttyread(void); -void ttyresize(int, int); -void ttywrite(const char *, size_t, int); - -void resettitle(void); - -void selclear(void); -void selinit(void); -void selstart(int, int, int); -void selextend(int, int, int, int); -int selected(int, int); -char *getsel(void); - -size_t utf8encode(Rune, char *); - -void *xmalloc(size_t); -void *xrealloc(void *, size_t); -char *xstrdup(const char *); - -/* config.h globals */ -extern char *utmp; -extern char *scroll; -extern char *stty_args; -extern char *vtiden; -extern wchar_t *worddelimiters; -extern int allowaltscreen; -extern int allowwindowops; -extern char *termname; -extern unsigned int tabspaces; -extern unsigned int defaultfg; -extern unsigned int defaultbg; -extern unsigned int defaultcs; -extern float alpha; diff --git a/utils/st-0.9/st.info b/utils/st-0.9/st.info deleted file mode 100644 index 8201ad6..0000000 --- a/utils/st-0.9/st.info +++ /dev/null @@ -1,239 +0,0 @@ -st-mono| simpleterm monocolor, - acsc=+C\,D-A.B0E``aaffgghFiGjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~, - am, - bce, - bel=^G, - blink=\E[5m, - bold=\E[1m, - cbt=\E[Z, - cvvis=\E[?25h, - civis=\E[?25l, - clear=\E[H\E[2J, - cnorm=\E[?12l\E[?25h, - colors#2, - cols#80, - cr=^M, - csr=\E[%i%p1%d;%p2%dr, - cub=\E[%p1%dD, - cub1=^H, - cud1=^J, - cud=\E[%p1%dB, - cuf1=\E[C, - cuf=\E[%p1%dC, - cup=\E[%i%p1%d;%p2%dH, - cuu1=\E[A, - cuu=\E[%p1%dA, - dch=\E[%p1%dP, - dch1=\E[P, - dim=\E[2m, - dl=\E[%p1%dM, - dl1=\E[M, - ech=\E[%p1%dX, - ed=\E[J, - el=\E[K, - el1=\E[1K, - enacs=\E)0, - flash=\E[?5h$<80/>\E[?5l, - fsl=^G, - home=\E[H, - hpa=\E[%i%p1%dG, - hs, - ht=^I, - hts=\EH, - ich=\E[%p1%d@, - il1=\E[L, - il=\E[%p1%dL, - ind=^J, - indn=\E[%p1%dS, - invis=\E[8m, - is2=\E[4l\E>\E[?1034l, - it#8, - kel=\E[1;2F, - ked=\E[1;5F, - ka1=\E[1~, - ka3=\E[5~, - kc1=\E[4~, - kc3=\E[6~, - kbs=\177, - kcbt=\E[Z, - kb2=\EOu, - kcub1=\EOD, - kcud1=\EOB, - kcuf1=\EOC, - kcuu1=\EOA, - kDC=\E[3;2~, - kent=\EOM, - kEND=\E[1;2F, - kIC=\E[2;2~, - kNXT=\E[6;2~, - kPRV=\E[5;2~, - kHOM=\E[1;2H, - kLFT=\E[1;2D, - kRIT=\E[1;2C, - kind=\E[1;2B, - kri=\E[1;2A, - kclr=\E[3;5~, - kdl1=\E[3;2~, - kdch1=\E[3~, - kich1=\E[2~, - kend=\E[4~, - kf1=\EOP, - kf2=\EOQ, - kf3=\EOR, - kf4=\EOS, - kf5=\E[15~, - kf6=\E[17~, - kf7=\E[18~, - kf8=\E[19~, - kf9=\E[20~, - kf10=\E[21~, - kf11=\E[23~, - kf12=\E[24~, - kf13=\E[1;2P, - kf14=\E[1;2Q, - kf15=\E[1;2R, - kf16=\E[1;2S, - kf17=\E[15;2~, - kf18=\E[17;2~, - kf19=\E[18;2~, - kf20=\E[19;2~, - kf21=\E[20;2~, - kf22=\E[21;2~, - kf23=\E[23;2~, - kf24=\E[24;2~, - kf25=\E[1;5P, - kf26=\E[1;5Q, - kf27=\E[1;5R, - kf28=\E[1;5S, - kf29=\E[15;5~, - kf30=\E[17;5~, - kf31=\E[18;5~, - kf32=\E[19;5~, - kf33=\E[20;5~, - kf34=\E[21;5~, - kf35=\E[23;5~, - kf36=\E[24;5~, - kf37=\E[1;6P, - kf38=\E[1;6Q, - kf39=\E[1;6R, - kf40=\E[1;6S, - kf41=\E[15;6~, - kf42=\E[17;6~, - kf43=\E[18;6~, - kf44=\E[19;6~, - kf45=\E[20;6~, - kf46=\E[21;6~, - kf47=\E[23;6~, - kf48=\E[24;6~, - kf49=\E[1;3P, - kf50=\E[1;3Q, - kf51=\E[1;3R, - kf52=\E[1;3S, - kf53=\E[15;3~, - kf54=\E[17;3~, - kf55=\E[18;3~, - kf56=\E[19;3~, - kf57=\E[20;3~, - kf58=\E[21;3~, - kf59=\E[23;3~, - kf60=\E[24;3~, - kf61=\E[1;4P, - kf62=\E[1;4Q, - kf63=\E[1;4R, - khome=\E[1~, - kil1=\E[2;5~, - krmir=\E[2;2~, - knp=\E[6~, - kmous=\E[M, - kpp=\E[5~, - lines#24, - mir, - msgr, - npc, - op=\E[39;49m, - pairs#64, - mc0=\E[i, - mc4=\E[4i, - mc5=\E[5i, - rc=\E8, - rev=\E[7m, - ri=\EM, - rin=\E[%p1%dT, - ritm=\E[23m, - rmacs=\E(B, - rmcup=\E[?1049l, - rmir=\E[4l, - rmkx=\E[?1l\E>, - rmso=\E[27m, - rmul=\E[24m, - rs1=\Ec, - rs2=\E[4l\E>\E[?1034l, - sc=\E7, - sitm=\E[3m, - sgr0=\E[0m, - smacs=\E(0, - smcup=\E[?1049h, - smir=\E[4h, - smkx=\E[?1h\E=, - smso=\E[7m, - smul=\E[4m, - tbc=\E[3g, - tsl=\E]0;, - xenl, - vpa=\E[%i%p1%dd, -# XTerm extensions - rmxx=\E[29m, - smxx=\E[9m, -# disabled rep for now: causes some issues with older ncurses versions. -# rep=%p1%c\E[%p2%{1}%-%db, -# tmux extensions, see TERMINFO EXTENSIONS in tmux(1) - Tc, - Ms=\E]52;%p1%s;%p2%s\007, - Se=\E[2 q, - Ss=\E[%p1%d q, - -st| simpleterm, - use=st-mono, - colors#8, - setab=\E[4%p1%dm, - setaf=\E[3%p1%dm, - setb=\E[4%?%p1%{1}%=%t4%e%p1%{3}%=%t6%e%p1%{4}%=%t1%e%p1%{6}%=%t3%e%p1%d%;m, - setf=\E[3%?%p1%{1}%=%t4%e%p1%{3}%=%t6%e%p1%{4}%=%t1%e%p1%{6}%=%t3%e%p1%d%;m, - sgr=%?%p9%t\E(0%e\E(B%;\E[0%?%p6%t;1%;%?%p2%t;4%;%?%p1%p3%|%t;7%;%?%p4%t;5%;%?%p7%t;8%;m, - -st-256color| simpleterm with 256 colors, - use=st, - ccc, - colors#256, - oc=\E]104\007, - pairs#32767, -# Nicked from xterm-256color - initc=\E]4;%p1%d;rgb\:%p2%{255}%*%{1000}%/%2.2X/%p3%{255}%*%{1000}%/%2.2X/%p4%{255}%*%{1000}%/%2.2X\E\\, - setab=\E[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m, - setaf=\E[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m, - -st-meta| simpleterm with meta key, - use=st, - km, - rmm=\E[?1034l, - smm=\E[?1034h, - rs2=\E[4l\E>\E[?1034h, - is2=\E[4l\E>\E[?1034h, - -st-meta-256color| simpleterm with meta key and 256 colors, - use=st-256color, - km, - rmm=\E[?1034l, - smm=\E[?1034h, - rs2=\E[4l\E>\E[?1034h, - is2=\E[4l\E>\E[?1034h, - -st-bs| simpleterm with backspace as backspace, - use=st, - kbs=\010, - kdch1=\177, - -st-bs-256color| simpleterm with backspace as backspace and 256colors, - use=st-256color, - kbs=\010, - kdch1=\177, diff --git a/utils/st-0.9/win.h b/utils/st-0.9/win.h deleted file mode 100644 index 6de960d..0000000 --- a/utils/st-0.9/win.h +++ /dev/null @@ -1,41 +0,0 @@ -/* See LICENSE for license details. */ - -enum win_mode { - MODE_VISIBLE = 1 << 0, - MODE_FOCUSED = 1 << 1, - MODE_APPKEYPAD = 1 << 2, - MODE_MOUSEBTN = 1 << 3, - MODE_MOUSEMOTION = 1 << 4, - MODE_REVERSE = 1 << 5, - MODE_KBDLOCK = 1 << 6, - MODE_HIDE = 1 << 7, - MODE_APPCURSOR = 1 << 8, - MODE_MOUSESGR = 1 << 9, - MODE_8BIT = 1 << 10, - MODE_BLINK = 1 << 11, - MODE_FBLINK = 1 << 12, - MODE_FOCUS = 1 << 13, - MODE_MOUSEX10 = 1 << 14, - MODE_MOUSEMANY = 1 << 15, - MODE_BRCKTPASTE = 1 << 16, - MODE_NUMLOCK = 1 << 17, - MODE_MOUSE = MODE_MOUSEBTN|MODE_MOUSEMOTION|MODE_MOUSEX10\ - |MODE_MOUSEMANY, -}; - -void xbell(void); -void xclipcopy(void); -void xdrawcursor(int, int, Glyph, int, int, Glyph); -void xdrawline(Line, int, int, int); -void xfinishdraw(void); -void xloadcols(void); -int xsetcolorname(int, const char *); -int xgetcolor(int, unsigned char *, unsigned char *, unsigned char *); -void xseticontitle(char *); -void xsettitle(char *); -int xsetcursor(int); -void xsetmode(int, unsigned int); -void xsetpointermotion(int); -void xsetsel(char *); -int xstartdraw(void); -void xximspot(int, int); diff --git a/utils/st-0.9/x.c b/utils/st-0.9/x.c deleted file mode 100644 index 27e81d1..0000000 --- a/utils/st-0.9/x.c +++ /dev/null @@ -1,2116 +0,0 @@ -/* See LICENSE for license details. */ -#include <errno.h> -#include <math.h> -#include <limits.h> -#include <locale.h> -#include <signal.h> -#include <sys/select.h> -#include <time.h> -#include <unistd.h> -#include <libgen.h> -#include <X11/Xatom.h> -#include <X11/Xlib.h> -#include <X11/cursorfont.h> -#include <X11/keysym.h> -#include <X11/Xft/Xft.h> -#include <X11/XKBlib.h> - -char *argv0; -#include "arg.h" -#include "st.h" -#include "win.h" - -/* types used in config.h */ -typedef struct { - uint mod; - KeySym keysym; - void (*func)(const Arg *); - const Arg arg; -} Shortcut; - -typedef struct { - uint mod; - uint button; - void (*func)(const Arg *); - const Arg arg; - uint release; -} MouseShortcut; - -typedef struct { - KeySym k; - uint mask; - char *s; - /* three-valued logic variables: 0 indifferent, 1 on, -1 off */ - signed char appkey; /* application keypad */ - signed char appcursor; /* application cursor */ -} Key; - -/* X modifiers */ -#define XK_ANY_MOD UINT_MAX -#define XK_NO_MOD 0 -#define XK_SWITCH_MOD (1<<13|1<<14) - -/* function definitions used in config.h */ -static void clipcopy(const Arg *); -static void clippaste(const Arg *); -static void numlock(const Arg *); -static void selpaste(const Arg *); -static void zoom(const Arg *); -static void zoomabs(const Arg *); -static void zoomreset(const Arg *); -static void ttysend(const Arg *); - -/* config.h for applying patches and the configuration. */ -#include "config.h" - -/* XEMBED messages */ -#define XEMBED_FOCUS_IN 4 -#define XEMBED_FOCUS_OUT 5 - -/* macros */ -#define IS_SET(flag) ((win.mode & (flag)) != 0) -#define TRUERED(x) (((x) & 0xff0000) >> 8) -#define TRUEGREEN(x) (((x) & 0xff00)) -#define TRUEBLUE(x) (((x) & 0xff) << 8) - -typedef XftDraw *Draw; -typedef XftColor Color; -typedef XftGlyphFontSpec GlyphFontSpec; - -/* Purely graphic info */ -typedef struct { - int tw, th; /* tty width and height */ - int w, h; /* window width and height */ - int ch; /* char height */ - int cw; /* char width */ - int mode; /* window state/mode flags */ - int cursor; /* cursor style */ -} TermWindow; - -typedef struct { - Display *dpy; - Colormap cmap; - Window win; - Drawable buf; - GlyphFontSpec *specbuf; /* font spec buffer used for rendering */ - Atom xembed, wmdeletewin, netwmname, netwmiconname, netwmpid; - struct { - XIM xim; - XIC xic; - XPoint spot; - XVaNestedList spotlist; - } ime; - Draw draw; - Visual *vis; - XSetWindowAttributes attrs; - int scr; - int isfixed; /* is fixed geometry? */ - int depth; /* bit depth */ - int l, t; /* left and top offset */ - int gm; /* geometry mask */ -} XWindow; - -typedef struct { - Atom xtarget; - char *primary, *clipboard; - struct timespec tclick1; - struct timespec tclick2; -} XSelection; - -/* Font structure */ -#define Font Font_ -typedef struct { - int height; - int width; - int ascent; - int descent; - int badslant; - int badweight; - short lbearing; - short rbearing; - XftFont *match; - FcFontSet *set; - FcPattern *pattern; -} Font; - -/* Drawing Context */ -typedef struct { - Color *col; - size_t collen; - Font font, bfont, ifont, ibfont; - GC gc; -} DC; - -static inline ushort sixd_to_16bit(int); -static int xmakeglyphfontspecs(XftGlyphFontSpec *, const Glyph *, int, int, int); -static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, int); -static void xdrawglyph(Glyph, int, int); -static void xclear(int, int, int, int); -static int xgeommasktogravity(int); -static int ximopen(Display *); -static void ximinstantiate(Display *, XPointer, XPointer); -static void ximdestroy(XIM, XPointer, XPointer); -static int xicdestroy(XIC, XPointer, XPointer); -static void xinit(int, int); -static void cresize(int, int); -static void xresize(int, int); -static void xhints(void); -static int xloadcolor(int, const char *, Color *); -static int xloadfont(Font *, FcPattern *); -static void xloadfonts(const char *, double); -static void xunloadfont(Font *); -static void xunloadfonts(void); -static void xsetenv(void); -static void xseturgency(int); -static int evcol(XEvent *); -static int evrow(XEvent *); - -static void expose(XEvent *); -static void visibility(XEvent *); -static void unmap(XEvent *); -static void kpress(XEvent *); -static void cmessage(XEvent *); -static void resize(XEvent *); -static void focus(XEvent *); -static uint buttonmask(uint); -static int mouseaction(XEvent *, uint); -static void brelease(XEvent *); -static void bpress(XEvent *); -static void bmotion(XEvent *); -static void propnotify(XEvent *); -static void selnotify(XEvent *); -static void selclear_(XEvent *); -static void selrequest(XEvent *); -static void setsel(char *, Time); -static void mousesel(XEvent *, int); -static void mousereport(XEvent *); -static char *kmap(KeySym, uint); -static int match(uint, uint); - -static void run(void); -static void usage(void); - -static void (*handler[LASTEvent])(XEvent *) = { - [KeyPress] = kpress, - [ClientMessage] = cmessage, - [ConfigureNotify] = resize, - [VisibilityNotify] = visibility, - [UnmapNotify] = unmap, - [Expose] = expose, - [FocusIn] = focus, - [FocusOut] = focus, - [MotionNotify] = bmotion, - [ButtonPress] = bpress, - [ButtonRelease] = brelease, -/* - * Uncomment if you want the selection to disappear when you select something - * different in another window. - */ -/* [SelectionClear] = selclear_, */ - [SelectionNotify] = selnotify, -/* - * PropertyNotify is only turned on when there is some INCR transfer happening - * for the selection retrieval. - */ - [PropertyNotify] = propnotify, - [SelectionRequest] = selrequest, -}; - -/* Globals */ -static DC dc; -static XWindow xw; -static XSelection xsel; -static TermWindow win; - -/* Font Ring Cache */ -enum { - FRC_NORMAL, - FRC_ITALIC, - FRC_BOLD, - FRC_ITALICBOLD -}; - -typedef struct { - XftFont *font; - int flags; - Rune unicodep; -} Fontcache; - -/* Fontcache is an array now. A new font will be appended to the array. */ -static Fontcache *frc = NULL; -static int frclen = 0; -static int frccap = 0; -static char *usedfont = NULL; -static double usedfontsize = 0; -static double defaultfontsize = 0; - -static char *opt_alpha = NULL; -static char *opt_class = NULL; -static char **opt_cmd = NULL; -static char *opt_embed = NULL; -static char *opt_font = NULL; -static char *opt_io = NULL; -static char *opt_line = NULL; -static char *opt_name = NULL; -static char *opt_title = NULL; - -static uint buttons; /* bit field of pressed buttons */ - -void -clipcopy(const Arg *dummy) -{ - Atom clipboard; - - free(xsel.clipboard); - xsel.clipboard = NULL; - - if (xsel.primary != NULL) { - xsel.clipboard = xstrdup(xsel.primary); - clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); - XSetSelectionOwner(xw.dpy, clipboard, xw.win, CurrentTime); - } -} - -void -clippaste(const Arg *dummy) -{ - Atom clipboard; - - clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); - XConvertSelection(xw.dpy, clipboard, xsel.xtarget, clipboard, - xw.win, CurrentTime); -} - -void -selpaste(const Arg *dummy) -{ - XConvertSelection(xw.dpy, XA_PRIMARY, xsel.xtarget, XA_PRIMARY, - xw.win, CurrentTime); -} - -void -numlock(const Arg *dummy) -{ - win.mode ^= MODE_NUMLOCK; -} - -void -zoom(const Arg *arg) -{ - Arg larg; - - larg.f = usedfontsize + arg->f; - zoomabs(&larg); -} - -void -zoomabs(const Arg *arg) -{ - xunloadfonts(); - xloadfonts(usedfont, arg->f); - cresize(0, 0); - redraw(); - xhints(); -} - -void -zoomreset(const Arg *arg) -{ - Arg larg; - - if (defaultfontsize > 0) { - larg.f = defaultfontsize; - zoomabs(&larg); - } -} - -void -ttysend(const Arg *arg) -{ - ttywrite(arg->s, strlen(arg->s), 1); -} - -int -evcol(XEvent *e) -{ - int x = e->xbutton.x - borderpx; - LIMIT(x, 0, win.tw - 1); - return x / win.cw; -} - -int -evrow(XEvent *e) -{ - int y = e->xbutton.y - borderpx; - LIMIT(y, 0, win.th - 1); - return y / win.ch; -} - -void -mousesel(XEvent *e, int done) -{ - int type, seltype = SEL_REGULAR; - uint state = e->xbutton.state & ~(Button1Mask | forcemousemod); - - for (type = 1; type < LEN(selmasks); ++type) { - if (match(selmasks[type], state)) { - seltype = type; - break; - } - } - selextend(evcol(e), evrow(e), seltype, done); - if (done) - setsel(getsel(), e->xbutton.time); -} - -void -mousereport(XEvent *e) -{ - int len, btn, code; - int x = evcol(e), y = evrow(e); - int state = e->xbutton.state; - char buf[40]; - static int ox, oy; - - if (e->type == MotionNotify) { - if (x == ox && y == oy) - return; - if (!IS_SET(MODE_MOUSEMOTION) && !IS_SET(MODE_MOUSEMANY)) - return; - /* MODE_MOUSEMOTION: no reporting if no button is pressed */ - if (IS_SET(MODE_MOUSEMOTION) && buttons == 0) - return; - /* Set btn to lowest-numbered pressed button, or 12 if no - * buttons are pressed. */ - for (btn = 1; btn <= 11 && !(buttons & (1<<(btn-1))); btn++) - ; - code = 32; - } else { - btn = e->xbutton.button; - /* Only buttons 1 through 11 can be encoded */ - if (btn < 1 || btn > 11) - return; - if (e->type == ButtonRelease) { - /* MODE_MOUSEX10: no button release reporting */ - if (IS_SET(MODE_MOUSEX10)) - return; - /* Don't send release events for the scroll wheel */ - if (btn == 4 || btn == 5) - return; - } - code = 0; - } - - ox = x; - oy = y; - - /* Encode btn into code. If no button is pressed for a motion event in - * MODE_MOUSEMANY, then encode it as a release. */ - if ((!IS_SET(MODE_MOUSESGR) && e->type == ButtonRelease) || btn == 12) - code += 3; - else if (btn >= 8) - code += 128 + btn - 8; - else if (btn >= 4) - code += 64 + btn - 4; - else - code += btn - 1; - - if (!IS_SET(MODE_MOUSEX10)) { - code += ((state & ShiftMask ) ? 4 : 0) - + ((state & Mod1Mask ) ? 8 : 0) /* meta key: alt */ - + ((state & ControlMask) ? 16 : 0); - } - - if (IS_SET(MODE_MOUSESGR)) { - len = snprintf(buf, sizeof(buf), "\033[<%d;%d;%d%c", - code, x+1, y+1, - e->type == ButtonRelease ? 'm' : 'M'); - } else if (x < 223 && y < 223) { - len = snprintf(buf, sizeof(buf), "\033[M%c%c%c", - 32+code, 32+x+1, 32+y+1); - } else { - return; - } - - ttywrite(buf, len, 0); -} - -uint -buttonmask(uint button) -{ - return button == Button1 ? Button1Mask - : button == Button2 ? Button2Mask - : button == Button3 ? Button3Mask - : button == Button4 ? Button4Mask - : button == Button5 ? Button5Mask - : 0; -} - -int -mouseaction(XEvent *e, uint release) -{ - MouseShortcut *ms; - - /* ignore Button<N>mask for Button<N> - it's set on release */ - uint state = e->xbutton.state & ~buttonmask(e->xbutton.button); - - for (ms = mshortcuts; ms < mshortcuts + LEN(mshortcuts); ms++) { - if (ms->release == release && - ms->button == e->xbutton.button && - (match(ms->mod, state) || /* exact or forced */ - match(ms->mod, state & ~forcemousemod))) { - ms->func(&(ms->arg)); - return 1; - } - } - - return 0; -} - -void -bpress(XEvent *e) -{ - int btn = e->xbutton.button; - struct timespec now; - int snap; - - if (1 <= btn && btn <= 11) - buttons |= 1 << (btn-1); - - if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { - mousereport(e); - return; - } - - if (mouseaction(e, 0)) - return; - - if (btn == Button1) { - /* - * If the user clicks below predefined timeouts specific - * snapping behaviour is exposed. - */ - clock_gettime(CLOCK_MONOTONIC, &now); - if (TIMEDIFF(now, xsel.tclick2) <= tripleclicktimeout) { - snap = SNAP_LINE; - } else if (TIMEDIFF(now, xsel.tclick1) <= doubleclicktimeout) { - snap = SNAP_WORD; - } else { - snap = 0; - } - xsel.tclick2 = xsel.tclick1; - xsel.tclick1 = now; - - selstart(evcol(e), evrow(e), snap); - } -} - -void -propnotify(XEvent *e) -{ - XPropertyEvent *xpev; - Atom clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); - - xpev = &e->xproperty; - if (xpev->state == PropertyNewValue && - (xpev->atom == XA_PRIMARY || - xpev->atom == clipboard)) { - selnotify(e); - } -} - -void -selnotify(XEvent *e) -{ - ulong nitems, ofs, rem; - int format; - uchar *data, *last, *repl; - Atom type, incratom, property = None; - - incratom = XInternAtom(xw.dpy, "INCR", 0); - - ofs = 0; - if (e->type == SelectionNotify) - property = e->xselection.property; - else if (e->type == PropertyNotify) - property = e->xproperty.atom; - - if (property == None) - return; - - do { - if (XGetWindowProperty(xw.dpy, xw.win, property, ofs, - BUFSIZ/4, False, AnyPropertyType, - &type, &format, &nitems, &rem, - &data)) { - fprintf(stderr, "Clipboard allocation failed\n"); - return; - } - - if (e->type == PropertyNotify && nitems == 0 && rem == 0) { - /* - * If there is some PropertyNotify with no data, then - * this is the signal of the selection owner that all - * data has been transferred. We won't need to receive - * PropertyNotify events anymore. - */ - MODBIT(xw.attrs.event_mask, 0, PropertyChangeMask); - XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, - &xw.attrs); - } - - if (type == incratom) { - /* - * Activate the PropertyNotify events so we receive - * when the selection owner does send us the next - * chunk of data. - */ - MODBIT(xw.attrs.event_mask, 1, PropertyChangeMask); - XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, - &xw.attrs); - - /* - * Deleting the property is the transfer start signal. - */ - XDeleteProperty(xw.dpy, xw.win, (int)property); - continue; - } - - /* - * As seen in getsel: - * Line endings are inconsistent in the terminal and GUI world - * copy and pasting. When receiving some selection data, - * replace all '\n' with '\r'. - * FIXME: Fix the computer world. - */ - repl = data; - last = data + nitems * format / 8; - while ((repl = memchr(repl, '\n', last - repl))) { - *repl++ = '\r'; - } - - if (IS_SET(MODE_BRCKTPASTE) && ofs == 0) - ttywrite("\033[200~", 6, 0); - ttywrite((char *)data, nitems * format / 8, 1); - if (IS_SET(MODE_BRCKTPASTE) && rem == 0) - ttywrite("\033[201~", 6, 0); - XFree(data); - /* number of 32-bit chunks returned */ - ofs += nitems * format / 32; - } while (rem > 0); - - /* - * Deleting the property again tells the selection owner to send the - * next data chunk in the property. - */ - XDeleteProperty(xw.dpy, xw.win, (int)property); -} - -void -xclipcopy(void) -{ - clipcopy(NULL); -} - -void -selclear_(XEvent *e) -{ - selclear(); -} - -void -selrequest(XEvent *e) -{ - XSelectionRequestEvent *xsre; - XSelectionEvent xev; - Atom xa_targets, string, clipboard; - char *seltext; - - xsre = (XSelectionRequestEvent *) e; - xev.type = SelectionNotify; - xev.requestor = xsre->requestor; - xev.selection = xsre->selection; - xev.target = xsre->target; - xev.time = xsre->time; - if (xsre->property == None) - xsre->property = xsre->target; - - /* reject */ - xev.property = None; - - xa_targets = XInternAtom(xw.dpy, "TARGETS", 0); - if (xsre->target == xa_targets) { - /* respond with the supported type */ - string = xsel.xtarget; - XChangeProperty(xsre->display, xsre->requestor, xsre->property, - XA_ATOM, 32, PropModeReplace, - (uchar *) &string, 1); - xev.property = xsre->property; - } else if (xsre->target == xsel.xtarget || xsre->target == XA_STRING) { - /* - * xith XA_STRING non ascii characters may be incorrect in the - * requestor. It is not our problem, use utf8. - */ - clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); - if (xsre->selection == XA_PRIMARY) { - seltext = xsel.primary; - } else if (xsre->selection == clipboard) { - seltext = xsel.clipboard; - } else { - fprintf(stderr, - "Unhandled clipboard selection 0x%lx\n", - xsre->selection); - return; - } - if (seltext != NULL) { - XChangeProperty(xsre->display, xsre->requestor, - xsre->property, xsre->target, - 8, PropModeReplace, - (uchar *)seltext, strlen(seltext)); - xev.property = xsre->property; - } - } - - /* all done, send a notification to the listener */ - if (!XSendEvent(xsre->display, xsre->requestor, 1, 0, (XEvent *) &xev)) - fprintf(stderr, "Error sending SelectionNotify event\n"); -} - -void -setsel(char *str, Time t) -{ - if (!str) - return; - - free(xsel.primary); - xsel.primary = str; - - XSetSelectionOwner(xw.dpy, XA_PRIMARY, xw.win, t); - if (XGetSelectionOwner(xw.dpy, XA_PRIMARY) != xw.win) - selclear(); -} - -void -xsetsel(char *str) -{ - setsel(str, CurrentTime); -} - -void -brelease(XEvent *e) -{ - int btn = e->xbutton.button; - - if (1 <= btn && btn <= 11) - buttons &= ~(1 << (btn-1)); - - if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { - mousereport(e); - return; - } - - if (mouseaction(e, 1)) - return; - if (btn == Button1) - mousesel(e, 1); -} - -void -bmotion(XEvent *e) -{ - if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { - mousereport(e); - return; - } - - mousesel(e, 0); -} - -void -cresize(int width, int height) -{ - int col, row; - - if (width != 0) - win.w = width; - if (height != 0) - win.h = height; - - col = (win.w - 2 * borderpx) / win.cw; - row = (win.h - 2 * borderpx) / win.ch; - col = MAX(1, col); - row = MAX(1, row); - - tresize(col, row); - xresize(col, row); - ttyresize(win.tw, win.th); -} - -void -xresize(int col, int row) -{ - win.tw = col * win.cw; - win.th = row * win.ch; - - XFreePixmap(xw.dpy, xw.buf); - xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, - xw.depth); - XftDrawChange(xw.draw, xw.buf); - xclear(0, 0, win.w, win.h); - - /* resize to new width */ - xw.specbuf = xrealloc(xw.specbuf, col * sizeof(GlyphFontSpec)); -} - -ushort -sixd_to_16bit(int x) -{ - return x == 0 ? 0 : 0x3737 + 0x2828 * x; -} - -int -xloadcolor(int i, const char *name, Color *ncolor) -{ - XRenderColor color = { .alpha = 0xffff }; - - if (!name) { - if (BETWEEN(i, 16, 255)) { /* 256 color */ - if (i < 6*6*6+16) { /* same colors as xterm */ - color.red = sixd_to_16bit( ((i-16)/36)%6 ); - color.green = sixd_to_16bit( ((i-16)/6) %6 ); - color.blue = sixd_to_16bit( ((i-16)/1) %6 ); - } else { /* greyscale */ - color.red = 0x0808 + 0x0a0a * (i - (6*6*6+16)); - color.green = color.blue = color.red; - } - return XftColorAllocValue(xw.dpy, xw.vis, - xw.cmap, &color, ncolor); - } else - name = colorname[i]; - } - - return XftColorAllocName(xw.dpy, xw.vis, xw.cmap, name, ncolor); -} - -void -xloadcols(void) -{ - int i; - static int loaded; - Color *cp; - - if (loaded) { - for (cp = dc.col; cp < &dc.col[dc.collen]; ++cp) - XftColorFree(xw.dpy, xw.vis, xw.cmap, cp); - } else { - dc.collen = MAX(LEN(colorname), 256); - dc.col = xmalloc(dc.collen * sizeof(Color)); - } - - for (i = 0; i < dc.collen; i++) - if (!xloadcolor(i, NULL, &dc.col[i])) { - if (colorname[i]) - die("could not allocate color '%s'\n", colorname[i]); - else - die("could not allocate color %d\n", i); - } - - /* set alpha value of bg color */ - if (opt_alpha) - alpha = strtof(opt_alpha, NULL); - dc.col[defaultbg].color.alpha = (unsigned short)(0xffff * alpha); - dc.col[defaultbg].pixel &= 0x00FFFFFF; - dc.col[defaultbg].pixel |= (unsigned char)(0xff * alpha) << 24; - loaded = 1; -} - -int -xgetcolor(int x, unsigned char *r, unsigned char *g, unsigned char *b) -{ - if (!BETWEEN(x, 0, dc.collen)) - return 1; - - *r = dc.col[x].color.red >> 8; - *g = dc.col[x].color.green >> 8; - *b = dc.col[x].color.blue >> 8; - - return 0; -} - -int -xsetcolorname(int x, const char *name) -{ - Color ncolor; - - if (!BETWEEN(x, 0, dc.collen)) - return 1; - - if (!xloadcolor(x, name, &ncolor)) - return 1; - - XftColorFree(xw.dpy, xw.vis, xw.cmap, &dc.col[x]); - dc.col[x] = ncolor; - - return 0; -} - -/* - * Absolute coordinates. - */ -void -xclear(int x1, int y1, int x2, int y2) -{ - XftDrawRect(xw.draw, - &dc.col[IS_SET(MODE_REVERSE)? defaultfg : defaultbg], - x1, y1, x2-x1, y2-y1); -} - -void -xhints(void) -{ - XClassHint class = {opt_name ? opt_name : termname, - opt_class ? opt_class : termname}; - XWMHints wm = {.flags = InputHint, .input = 1}; - XSizeHints *sizeh; - - sizeh = XAllocSizeHints(); - - sizeh->flags = PSize | PResizeInc | PBaseSize | PMinSize; - sizeh->height = win.h; - sizeh->width = win.w; - sizeh->height_inc = win.ch; - sizeh->width_inc = win.cw; - sizeh->base_height = 2 * borderpx; - sizeh->base_width = 2 * borderpx; - sizeh->min_height = win.ch + 2 * borderpx; - sizeh->min_width = win.cw + 2 * borderpx; - if (xw.isfixed) { - sizeh->flags |= PMaxSize; - sizeh->min_width = sizeh->max_width = win.w; - sizeh->min_height = sizeh->max_height = win.h; - } - if (xw.gm & (XValue|YValue)) { - sizeh->flags |= USPosition | PWinGravity; - sizeh->x = xw.l; - sizeh->y = xw.t; - sizeh->win_gravity = xgeommasktogravity(xw.gm); - } - - XSetWMProperties(xw.dpy, xw.win, NULL, NULL, NULL, 0, sizeh, &wm, - &class); - XFree(sizeh); -} - -int -xgeommasktogravity(int mask) -{ - switch (mask & (XNegative|YNegative)) { - case 0: - return NorthWestGravity; - case XNegative: - return NorthEastGravity; - case YNegative: - return SouthWestGravity; - } - - return SouthEastGravity; -} - -int -xloadfont(Font *f, FcPattern *pattern) -{ - FcPattern *configured; - FcPattern *match; - FcResult result; - XGlyphInfo extents; - int wantattr, haveattr; - - /* - * Manually configure instead of calling XftMatchFont - * so that we can use the configured pattern for - * "missing glyph" lookups. - */ - configured = FcPatternDuplicate(pattern); - if (!configured) - return 1; - - FcConfigSubstitute(NULL, configured, FcMatchPattern); - XftDefaultSubstitute(xw.dpy, xw.scr, configured); - - match = FcFontMatch(NULL, configured, &result); - if (!match) { - FcPatternDestroy(configured); - return 1; - } - - if (!(f->match = XftFontOpenPattern(xw.dpy, match))) { - FcPatternDestroy(configured); - FcPatternDestroy(match); - return 1; - } - - if ((XftPatternGetInteger(pattern, "slant", 0, &wantattr) == - XftResultMatch)) { - /* - * Check if xft was unable to find a font with the appropriate - * slant but gave us one anyway. Try to mitigate. - */ - if ((XftPatternGetInteger(f->match->pattern, "slant", 0, - &haveattr) != XftResultMatch) || haveattr < wantattr) { - f->badslant = 1; - fputs("font slant does not match\n", stderr); - } - } - - if ((XftPatternGetInteger(pattern, "weight", 0, &wantattr) == - XftResultMatch)) { - if ((XftPatternGetInteger(f->match->pattern, "weight", 0, - &haveattr) != XftResultMatch) || haveattr != wantattr) { - f->badweight = 1; - fputs("font weight does not match\n", stderr); - } - } - - XftTextExtentsUtf8(xw.dpy, f->match, - (const FcChar8 *) ascii_printable, - strlen(ascii_printable), &extents); - - f->set = NULL; - f->pattern = configured; - - f->ascent = f->match->ascent; - f->descent = f->match->descent; - f->lbearing = 0; - f->rbearing = f->match->max_advance_width; - - f->height = f->ascent + f->descent; - f->width = DIVCEIL(extents.xOff, strlen(ascii_printable)); - - return 0; -} - -void -xloadfonts(const char *fontstr, double fontsize) -{ - FcPattern *pattern; - double fontval; - - if (fontstr[0] == '-') - pattern = XftXlfdParse(fontstr, False, False); - else - pattern = FcNameParse((const FcChar8 *)fontstr); - - if (!pattern) - die("can't open font %s\n", fontstr); - - if (fontsize > 1) { - FcPatternDel(pattern, FC_PIXEL_SIZE); - FcPatternDel(pattern, FC_SIZE); - FcPatternAddDouble(pattern, FC_PIXEL_SIZE, (double)fontsize); - usedfontsize = fontsize; - } else { - if (FcPatternGetDouble(pattern, FC_PIXEL_SIZE, 0, &fontval) == - FcResultMatch) { - usedfontsize = fontval; - } else if (FcPatternGetDouble(pattern, FC_SIZE, 0, &fontval) == - FcResultMatch) { - usedfontsize = -1; - } else { - /* - * Default font size is 12, if none given. This is to - * have a known usedfontsize value. - */ - FcPatternAddDouble(pattern, FC_PIXEL_SIZE, 12); - usedfontsize = 12; - } - defaultfontsize = usedfontsize; - } - - if (xloadfont(&dc.font, pattern)) - die("can't open font %s\n", fontstr); - - if (usedfontsize < 0) { - FcPatternGetDouble(dc.font.match->pattern, - FC_PIXEL_SIZE, 0, &fontval); - usedfontsize = fontval; - if (fontsize == 0) - defaultfontsize = fontval; - } - - /* Setting character width and height. */ - win.cw = ceilf(dc.font.width * cwscale); - win.ch = ceilf(dc.font.height * chscale); - - FcPatternDel(pattern, FC_SLANT); - FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC); - if (xloadfont(&dc.ifont, pattern)) - die("can't open font %s\n", fontstr); - - FcPatternDel(pattern, FC_WEIGHT); - FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_BOLD); - if (xloadfont(&dc.ibfont, pattern)) - die("can't open font %s\n", fontstr); - - FcPatternDel(pattern, FC_SLANT); - FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ROMAN); - if (xloadfont(&dc.bfont, pattern)) - die("can't open font %s\n", fontstr); - - FcPatternDestroy(pattern); -} - -void -xunloadfont(Font *f) -{ - XftFontClose(xw.dpy, f->match); - FcPatternDestroy(f->pattern); - if (f->set) - FcFontSetDestroy(f->set); -} - -void -xunloadfonts(void) -{ - /* Free the loaded fonts in the font cache. */ - while (frclen > 0) - XftFontClose(xw.dpy, frc[--frclen].font); - - xunloadfont(&dc.font); - xunloadfont(&dc.bfont); - xunloadfont(&dc.ifont); - xunloadfont(&dc.ibfont); -} - -int -ximopen(Display *dpy) -{ - XIMCallback imdestroy = { .client_data = NULL, .callback = ximdestroy }; - XICCallback icdestroy = { .client_data = NULL, .callback = xicdestroy }; - - xw.ime.xim = XOpenIM(xw.dpy, NULL, NULL, NULL); - if (xw.ime.xim == NULL) - return 0; - - if (XSetIMValues(xw.ime.xim, XNDestroyCallback, &imdestroy, NULL)) - fprintf(stderr, "XSetIMValues: " - "Could not set XNDestroyCallback.\n"); - - xw.ime.spotlist = XVaCreateNestedList(0, XNSpotLocation, &xw.ime.spot, - NULL); - - if (xw.ime.xic == NULL) { - xw.ime.xic = XCreateIC(xw.ime.xim, XNInputStyle, - XIMPreeditNothing | XIMStatusNothing, - XNClientWindow, xw.win, - XNDestroyCallback, &icdestroy, - NULL); - } - if (xw.ime.xic == NULL) - fprintf(stderr, "XCreateIC: Could not create input context.\n"); - - return 1; -} - -void -ximinstantiate(Display *dpy, XPointer client, XPointer call) -{ - if (ximopen(dpy)) - XUnregisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, - ximinstantiate, NULL); -} - -void -ximdestroy(XIM xim, XPointer client, XPointer call) -{ - xw.ime.xim = NULL; - XRegisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, - ximinstantiate, NULL); - XFree(xw.ime.spotlist); -} - -int -xicdestroy(XIC xim, XPointer client, XPointer call) -{ - xw.ime.xic = NULL; - return 1; -} - -void -xinit(int cols, int rows) -{ - XGCValues gcvalues; - Cursor cursor; - Window parent; - pid_t thispid = getpid(); - XColor xmousefg, xmousebg; - XWindowAttributes attr; - XVisualInfo vis; - - if (!(xw.dpy = XOpenDisplay(NULL))) - die("can't open display\n"); - xw.scr = XDefaultScreen(xw.dpy); - - if (!(opt_embed && (parent = strtol(opt_embed, NULL, 0)))) { - parent = XRootWindow(xw.dpy, xw.scr); - xw.depth = 32; - } else { - XGetWindowAttributes(xw.dpy, parent, &attr); - xw.depth = attr.depth; - } - - XMatchVisualInfo(xw.dpy, xw.scr, xw.depth, TrueColor, &vis); - xw.vis = vis.visual; - - /* font */ - if (!FcInit()) - die("could not init fontconfig.\n"); - - usedfont = (opt_font == NULL)? font : opt_font; - xloadfonts(usedfont, 0); - - /* colors */ - xw.cmap = XCreateColormap(xw.dpy, parent, xw.vis, None); - xloadcols(); - - /* adjust fixed window geometry */ - win.w = 2 * borderpx + cols * win.cw; - win.h = 2 * borderpx + rows * win.ch; - if (xw.gm & XNegative) - xw.l += DisplayWidth(xw.dpy, xw.scr) - win.w - 2; - if (xw.gm & YNegative) - xw.t += DisplayHeight(xw.dpy, xw.scr) - win.h - 2; - - /* Events */ - xw.attrs.background_pixel = dc.col[defaultbg].pixel; - xw.attrs.border_pixel = dc.col[defaultbg].pixel; - xw.attrs.bit_gravity = NorthWestGravity; - xw.attrs.event_mask = FocusChangeMask | KeyPressMask | KeyReleaseMask - | ExposureMask | VisibilityChangeMask | StructureNotifyMask - | ButtonMotionMask | ButtonPressMask | ButtonReleaseMask; - xw.attrs.colormap = xw.cmap; - - xw.win = XCreateWindow(xw.dpy, parent, xw.l, xw.t, - win.w, win.h, 0, xw.depth, InputOutput, - xw.vis, CWBackPixel | CWBorderPixel | CWBitGravity - | CWEventMask | CWColormap, &xw.attrs); - - memset(&gcvalues, 0, sizeof(gcvalues)); - gcvalues.graphics_exposures = False; - xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, xw.depth); - dc.gc = XCreateGC(xw.dpy, xw.buf, GCGraphicsExposures, &gcvalues); - XSetForeground(xw.dpy, dc.gc, dc.col[defaultbg].pixel); - XFillRectangle(xw.dpy, xw.buf, dc.gc, 0, 0, win.w, win.h); - - /* font spec buffer */ - xw.specbuf = xmalloc(cols * sizeof(GlyphFontSpec)); - - /* Xft rendering context */ - xw.draw = XftDrawCreate(xw.dpy, xw.buf, xw.vis, xw.cmap); - - /* input methods */ - if (!ximopen(xw.dpy)) { - XRegisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, - ximinstantiate, NULL); - } - - /* white cursor, black outline */ - cursor = XCreateFontCursor(xw.dpy, mouseshape); - XDefineCursor(xw.dpy, xw.win, cursor); - - if (XParseColor(xw.dpy, xw.cmap, colorname[mousefg], &xmousefg) == 0) { - xmousefg.red = 0xffff; - xmousefg.green = 0xffff; - xmousefg.blue = 0xffff; - } - - if (XParseColor(xw.dpy, xw.cmap, colorname[mousebg], &xmousebg) == 0) { - xmousebg.red = 0x0000; - xmousebg.green = 0x0000; - xmousebg.blue = 0x0000; - } - - XRecolorCursor(xw.dpy, cursor, &xmousefg, &xmousebg); - - xw.xembed = XInternAtom(xw.dpy, "_XEMBED", False); - xw.wmdeletewin = XInternAtom(xw.dpy, "WM_DELETE_WINDOW", False); - xw.netwmname = XInternAtom(xw.dpy, "_NET_WM_NAME", False); - xw.netwmiconname = XInternAtom(xw.dpy, "_NET_WM_ICON_NAME", False); - XSetWMProtocols(xw.dpy, xw.win, &xw.wmdeletewin, 1); - - xw.netwmpid = XInternAtom(xw.dpy, "_NET_WM_PID", False); - XChangeProperty(xw.dpy, xw.win, xw.netwmpid, XA_CARDINAL, 32, - PropModeReplace, (uchar *)&thispid, 1); - - win.mode = MODE_NUMLOCK; - resettitle(); - xhints(); - XMapWindow(xw.dpy, xw.win); - XSync(xw.dpy, False); - - clock_gettime(CLOCK_MONOTONIC, &xsel.tclick1); - clock_gettime(CLOCK_MONOTONIC, &xsel.tclick2); - xsel.primary = NULL; - xsel.clipboard = NULL; - xsel.xtarget = XInternAtom(xw.dpy, "UTF8_STRING", 0); - if (xsel.xtarget == None) - xsel.xtarget = XA_STRING; -} - -int -xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x, int y) -{ - float winx = borderpx + x * win.cw, winy = borderpx + y * win.ch, xp, yp; - ushort mode, prevmode = USHRT_MAX; - Font *font = &dc.font; - int frcflags = FRC_NORMAL; - float runewidth = win.cw; - Rune rune; - FT_UInt glyphidx; - FcResult fcres; - FcPattern *fcpattern, *fontpattern; - FcFontSet *fcsets[] = { NULL }; - FcCharSet *fccharset; - int i, f, numspecs = 0; - - for (i = 0, xp = winx, yp = winy + font->ascent; i < len; ++i) { - /* Fetch rune and mode for current glyph. */ - rune = glyphs[i].u; - mode = glyphs[i].mode; - - /* Skip dummy wide-character spacing. */ - if (mode == ATTR_WDUMMY) - continue; - - /* Determine font for glyph if different from previous glyph. */ - if (prevmode != mode) { - prevmode = mode; - font = &dc.font; - frcflags = FRC_NORMAL; - runewidth = win.cw * ((mode & ATTR_WIDE) ? 2.0f : 1.0f); - if ((mode & ATTR_ITALIC) && (mode & ATTR_BOLD)) { - font = &dc.ibfont; - frcflags = FRC_ITALICBOLD; - } else if (mode & ATTR_ITALIC) { - font = &dc.ifont; - frcflags = FRC_ITALIC; - } else if (mode & ATTR_BOLD) { - font = &dc.bfont; - frcflags = FRC_BOLD; - } - yp = winy + font->ascent; - } - - /* Lookup character index with default font. */ - glyphidx = XftCharIndex(xw.dpy, font->match, rune); - if (glyphidx) { - specs[numspecs].font = font->match; - specs[numspecs].glyph = glyphidx; - specs[numspecs].x = (short)xp; - specs[numspecs].y = (short)yp; - xp += runewidth; - numspecs++; - continue; - } - - /* Fallback on font cache, search the font cache for match. */ - for (f = 0; f < frclen; f++) { - glyphidx = XftCharIndex(xw.dpy, frc[f].font, rune); - /* Everything correct. */ - if (glyphidx && frc[f].flags == frcflags) - break; - /* We got a default font for a not found glyph. */ - if (!glyphidx && frc[f].flags == frcflags - && frc[f].unicodep == rune) { - break; - } - } - - /* Nothing was found. Use fontconfig to find matching font. */ - if (f >= frclen) { - if (!font->set) - font->set = FcFontSort(0, font->pattern, - 1, 0, &fcres); - fcsets[0] = font->set; - - /* - * Nothing was found in the cache. Now use - * some dozen of Fontconfig calls to get the - * font for one single character. - * - * Xft and fontconfig are design failures. - */ - fcpattern = FcPatternDuplicate(font->pattern); - fccharset = FcCharSetCreate(); - - FcCharSetAddChar(fccharset, rune); - FcPatternAddCharSet(fcpattern, FC_CHARSET, - fccharset); - FcPatternAddBool(fcpattern, FC_SCALABLE, 1); - - FcConfigSubstitute(0, fcpattern, - FcMatchPattern); - FcDefaultSubstitute(fcpattern); - - fontpattern = FcFontSetMatch(0, fcsets, 1, - fcpattern, &fcres); - - /* Allocate memory for the new cache entry. */ - if (frclen >= frccap) { - frccap += 16; - frc = xrealloc(frc, frccap * sizeof(Fontcache)); - } - - frc[frclen].font = XftFontOpenPattern(xw.dpy, - fontpattern); - if (!frc[frclen].font) - die("XftFontOpenPattern failed seeking fallback font: %s\n", - strerror(errno)); - frc[frclen].flags = frcflags; - frc[frclen].unicodep = rune; - - glyphidx = XftCharIndex(xw.dpy, frc[frclen].font, rune); - - f = frclen; - frclen++; - - FcPatternDestroy(fcpattern); - FcCharSetDestroy(fccharset); - } - - specs[numspecs].font = frc[f].font; - specs[numspecs].glyph = glyphidx; - specs[numspecs].x = (short)xp; - specs[numspecs].y = (short)yp; - xp += runewidth; - numspecs++; - } - - return numspecs; -} - -void -xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y) -{ - int charlen = len * ((base.mode & ATTR_WIDE) ? 2 : 1); - int winx = borderpx + x * win.cw, winy = borderpx + y * win.ch, - width = charlen * win.cw; - Color *fg, *bg, *temp, revfg, revbg, truefg, truebg; - XRenderColor colfg, colbg; - XRectangle r; - - /* Fallback on color display for attributes not supported by the font */ - if (base.mode & ATTR_ITALIC && base.mode & ATTR_BOLD) { - if (dc.ibfont.badslant || dc.ibfont.badweight) - base.fg = defaultattr; - } else if ((base.mode & ATTR_ITALIC && dc.ifont.badslant) || - (base.mode & ATTR_BOLD && dc.bfont.badweight)) { - base.fg = defaultattr; - } - - if (IS_TRUECOL(base.fg)) { - colfg.alpha = 0xffff; - colfg.red = TRUERED(base.fg); - colfg.green = TRUEGREEN(base.fg); - colfg.blue = TRUEBLUE(base.fg); - XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colfg, &truefg); - fg = &truefg; - } else { - fg = &dc.col[base.fg]; - } - - if (IS_TRUECOL(base.bg)) { - colbg.alpha = 0xffff; - colbg.green = TRUEGREEN(base.bg); - colbg.red = TRUERED(base.bg); - colbg.blue = TRUEBLUE(base.bg); - XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colbg, &truebg); - bg = &truebg; - } else { - bg = &dc.col[base.bg]; - } - - /* Change basic system colors [0-7] to bright system colors [8-15] */ - if ((base.mode & ATTR_BOLD_FAINT) == ATTR_BOLD && BETWEEN(base.fg, 0, 7)) - fg = &dc.col[base.fg + 8]; - - if (IS_SET(MODE_REVERSE)) { - if (fg == &dc.col[defaultfg]) { - fg = &dc.col[defaultbg]; - } else { - colfg.red = ~fg->color.red; - colfg.green = ~fg->color.green; - colfg.blue = ~fg->color.blue; - colfg.alpha = fg->color.alpha; - XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colfg, - &revfg); - fg = &revfg; - } - - if (bg == &dc.col[defaultbg]) { - bg = &dc.col[defaultfg]; - } else { - colbg.red = ~bg->color.red; - colbg.green = ~bg->color.green; - colbg.blue = ~bg->color.blue; - colbg.alpha = bg->color.alpha; - XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colbg, - &revbg); - bg = &revbg; - } - } - - if ((base.mode & ATTR_BOLD_FAINT) == ATTR_FAINT) { - colfg.red = fg->color.red / 2; - colfg.green = fg->color.green / 2; - colfg.blue = fg->color.blue / 2; - colfg.alpha = fg->color.alpha; - XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colfg, &revfg); - fg = &revfg; - } - - if (base.mode & ATTR_REVERSE) { - temp = fg; - fg = bg; - bg = temp; - } - - if (base.mode & ATTR_BLINK && win.mode & MODE_BLINK) - fg = bg; - - if (base.mode & ATTR_INVISIBLE) - fg = bg; - - /* Intelligent cleaning up of the borders. */ - if (x == 0) { - xclear(0, (y == 0)? 0 : winy, borderpx, - winy + win.ch + - ((winy + win.ch >= borderpx + win.th)? win.h : 0)); - } - if (winx + width >= borderpx + win.tw) { - xclear(winx + width, (y == 0)? 0 : winy, win.w, - ((winy + win.ch >= borderpx + win.th)? win.h : (winy + win.ch))); - } - if (y == 0) - xclear(winx, 0, winx + width, borderpx); - if (winy + win.ch >= borderpx + win.th) - xclear(winx, winy + win.ch, winx + width, win.h); - - /* Clean up the region we want to draw to. */ - XftDrawRect(xw.draw, bg, winx, winy, width, win.ch); - - /* Set the clip region because Xft is sometimes dirty. */ - r.x = 0; - r.y = 0; - r.height = win.ch; - r.width = width; - XftDrawSetClipRectangles(xw.draw, winx, winy, &r, 1); - - /* Render the glyphs. */ - XftDrawGlyphFontSpec(xw.draw, fg, specs, len); - - /* Render underline and strikethrough. */ - if (base.mode & ATTR_UNDERLINE) { - XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent * chscale + 1, - width, 1); - } - - if (base.mode & ATTR_STRUCK) { - XftDrawRect(xw.draw, fg, winx, winy + 2 * dc.font.ascent * chscale / 3, - width, 1); - } - - /* Reset clip to none. */ - XftDrawSetClip(xw.draw, 0); -} - -void -xdrawglyph(Glyph g, int x, int y) -{ - int numspecs; - XftGlyphFontSpec spec; - - numspecs = xmakeglyphfontspecs(&spec, &g, 1, x, y); - xdrawglyphfontspecs(&spec, g, numspecs, x, y); -} - -void -xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og) -{ - Color drawcol; - - /* remove the old cursor */ - if (selected(ox, oy)) - og.mode ^= ATTR_REVERSE; - xdrawglyph(og, ox, oy); - - if (IS_SET(MODE_HIDE)) - return; - - /* - * Select the right color for the right mode. - */ - g.mode &= ATTR_BOLD|ATTR_ITALIC|ATTR_UNDERLINE|ATTR_STRUCK|ATTR_WIDE; - - if (IS_SET(MODE_REVERSE)) { - g.mode |= ATTR_REVERSE; - g.bg = defaultfg; - if (selected(cx, cy)) { - drawcol = dc.col[defaultcs]; - g.fg = defaultrcs; - } else { - drawcol = dc.col[defaultrcs]; - g.fg = defaultcs; - } - } else { - if (selected(cx, cy)) { - g.fg = defaultfg; - g.bg = defaultrcs; - } else { - g.fg = defaultbg; - g.bg = defaultcs; - } - drawcol = dc.col[g.bg]; - } - - /* draw the new one */ - if (IS_SET(MODE_FOCUSED)) { - switch (win.cursor) { - case 7: /* st extension */ - g.u = 0x2603; /* snowman (U+2603) */ - /* FALLTHROUGH */ - case 0: /* Blinking Block */ - case 1: /* Blinking Block (Default) */ - case 2: /* Steady Block */ - xdrawglyph(g, cx, cy); - break; - case 3: /* Blinking Underline */ - case 4: /* Steady Underline */ - XftDrawRect(xw.draw, &drawcol, - borderpx + cx * win.cw, - borderpx + (cy + 1) * win.ch - \ - cursorthickness, - win.cw, cursorthickness); - break; - case 5: /* Blinking bar */ - case 6: /* Steady bar */ - XftDrawRect(xw.draw, &drawcol, - borderpx + cx * win.cw, - borderpx + cy * win.ch, - cursorthickness, win.ch); - break; - } - } else { - XftDrawRect(xw.draw, &drawcol, - borderpx + cx * win.cw, - borderpx + cy * win.ch, - win.cw - 1, 1); - XftDrawRect(xw.draw, &drawcol, - borderpx + cx * win.cw, - borderpx + cy * win.ch, - 1, win.ch - 1); - XftDrawRect(xw.draw, &drawcol, - borderpx + (cx + 1) * win.cw - 1, - borderpx + cy * win.ch, - 1, win.ch - 1); - XftDrawRect(xw.draw, &drawcol, - borderpx + cx * win.cw, - borderpx + (cy + 1) * win.ch - 1, - win.cw, 1); - } -} - -void -xsetenv(void) -{ - char buf[sizeof(long) * 8 + 1]; - - snprintf(buf, sizeof(buf), "%lu", xw.win); - setenv("WINDOWID", buf, 1); -} - -void -xseticontitle(char *p) -{ - XTextProperty prop; - DEFAULT(p, opt_title); - - if (Xutf8TextListToTextProperty(xw.dpy, &p, 1, XUTF8StringStyle, - &prop) != Success) - return; - XSetWMIconName(xw.dpy, xw.win, &prop); - XSetTextProperty(xw.dpy, xw.win, &prop, xw.netwmiconname); - XFree(prop.value); -} - -void -xsettitle(char *p) -{ - XTextProperty prop; - DEFAULT(p, opt_title); - - if (Xutf8TextListToTextProperty(xw.dpy, &p, 1, XUTF8StringStyle, - &prop) != Success) - return; - XSetWMName(xw.dpy, xw.win, &prop); - XSetTextProperty(xw.dpy, xw.win, &prop, xw.netwmname); - XFree(prop.value); -} - -int -xstartdraw(void) -{ - return IS_SET(MODE_VISIBLE); -} - -void -xdrawline(Line line, int x1, int y1, int x2) -{ - int i, x, ox, numspecs; - Glyph base, new; - XftGlyphFontSpec *specs = xw.specbuf; - - numspecs = xmakeglyphfontspecs(specs, &line[x1], x2 - x1, x1, y1); - i = ox = 0; - for (x = x1; x < x2 && i < numspecs; x++) { - new = line[x]; - if (new.mode == ATTR_WDUMMY) - continue; - if (selected(x, y1)) - new.mode ^= ATTR_REVERSE; - if (i > 0 && ATTRCMP(base, new)) { - xdrawglyphfontspecs(specs, base, i, ox, y1); - specs += i; - numspecs -= i; - i = 0; - } - if (i == 0) { - ox = x; - base = new; - } - i++; - } - if (i > 0) - xdrawglyphfontspecs(specs, base, i, ox, y1); -} - -void -xfinishdraw(void) -{ - XCopyArea(xw.dpy, xw.buf, xw.win, dc.gc, 0, 0, win.w, - win.h, 0, 0); - XSetForeground(xw.dpy, dc.gc, - dc.col[IS_SET(MODE_REVERSE)? - defaultfg : defaultbg].pixel); -} - -void -xximspot(int x, int y) -{ - if (xw.ime.xic == NULL) - return; - - xw.ime.spot.x = borderpx + x * win.cw; - xw.ime.spot.y = borderpx + (y + 1) * win.ch; - - XSetICValues(xw.ime.xic, XNPreeditAttributes, xw.ime.spotlist, NULL); -} - -void -expose(XEvent *ev) -{ - redraw(); -} - -void -visibility(XEvent *ev) -{ - XVisibilityEvent *e = &ev->xvisibility; - - MODBIT(win.mode, e->state != VisibilityFullyObscured, MODE_VISIBLE); -} - -void -unmap(XEvent *ev) -{ - win.mode &= ~MODE_VISIBLE; -} - -void -xsetpointermotion(int set) -{ - MODBIT(xw.attrs.event_mask, set, PointerMotionMask); - XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, &xw.attrs); -} - -void -xsetmode(int set, unsigned int flags) -{ - int mode = win.mode; - MODBIT(win.mode, set, flags); - if ((win.mode & MODE_REVERSE) != (mode & MODE_REVERSE)) - redraw(); -} - -int -xsetcursor(int cursor) -{ - if (!BETWEEN(cursor, 0, 7)) /* 7: st extension */ - return 1; - win.cursor = cursor; - return 0; -} - -void -xseturgency(int add) -{ - XWMHints *h = XGetWMHints(xw.dpy, xw.win); - - MODBIT(h->flags, add, XUrgencyHint); - XSetWMHints(xw.dpy, xw.win, h); - XFree(h); -} - -void -xbell(void) -{ - if (!(IS_SET(MODE_FOCUSED))) - xseturgency(1); - if (bellvolume) - XkbBell(xw.dpy, xw.win, bellvolume, (Atom)NULL); -} - -void -focus(XEvent *ev) -{ - XFocusChangeEvent *e = &ev->xfocus; - - if (e->mode == NotifyGrab) - return; - - if (ev->type == FocusIn) { - if (xw.ime.xic) - XSetICFocus(xw.ime.xic); - win.mode |= MODE_FOCUSED; - xseturgency(0); - if (IS_SET(MODE_FOCUS)) - ttywrite("\033[I", 3, 0); - } else { - if (xw.ime.xic) - XUnsetICFocus(xw.ime.xic); - win.mode &= ~MODE_FOCUSED; - if (IS_SET(MODE_FOCUS)) - ttywrite("\033[O", 3, 0); - } -} - -int -match(uint mask, uint state) -{ - return mask == XK_ANY_MOD || mask == (state & ~ignoremod); -} - -char* -kmap(KeySym k, uint state) -{ - Key *kp; - int i; - - /* Check for mapped keys out of X11 function keys. */ - for (i = 0; i < LEN(mappedkeys); i++) { - if (mappedkeys[i] == k) - break; - } - if (i == LEN(mappedkeys)) { - if ((k & 0xFFFF) < 0xFD00) - return NULL; - } - - for (kp = key; kp < key + LEN(key); kp++) { - if (kp->k != k) - continue; - - if (!match(kp->mask, state)) - continue; - - if (IS_SET(MODE_APPKEYPAD) ? kp->appkey < 0 : kp->appkey > 0) - continue; - if (IS_SET(MODE_NUMLOCK) && kp->appkey == 2) - continue; - - if (IS_SET(MODE_APPCURSOR) ? kp->appcursor < 0 : kp->appcursor > 0) - continue; - - return kp->s; - } - - return NULL; -} - -void -kpress(XEvent *ev) -{ - XKeyEvent *e = &ev->xkey; - KeySym ksym; - char buf[64], *customkey; - int len; - Rune c; - Status status; - Shortcut *bp; - - if (IS_SET(MODE_KBDLOCK)) - return; - - if (xw.ime.xic) - len = XmbLookupString(xw.ime.xic, e, buf, sizeof buf, &ksym, &status); - else - len = XLookupString(e, buf, sizeof buf, &ksym, NULL); - /* 1. shortcuts */ - for (bp = shortcuts; bp < shortcuts + LEN(shortcuts); bp++) { - if (ksym == bp->keysym && match(bp->mod, e->state)) { - bp->func(&(bp->arg)); - return; - } - } - - /* 2. custom keys from config.h */ - if ((customkey = kmap(ksym, e->state))) { - ttywrite(customkey, strlen(customkey), 1); - return; - } - - /* 3. composed string from input method */ - if (len == 0) - return; - if (len == 1 && e->state & Mod1Mask) { - if (IS_SET(MODE_8BIT)) { - if (*buf < 0177) { - c = *buf | 0x80; - len = utf8encode(c, buf); - } - } else { - buf[1] = buf[0]; - buf[0] = '\033'; - len = 2; - } - } - ttywrite(buf, len, 1); -} - -void -cmessage(XEvent *e) -{ - /* - * See xembed specs - * http://standards.freedesktop.org/xembed-spec/xembed-spec-latest.html - */ - if (e->xclient.message_type == xw.xembed && e->xclient.format == 32) { - if (e->xclient.data.l[1] == XEMBED_FOCUS_IN) { - win.mode |= MODE_FOCUSED; - xseturgency(0); - } else if (e->xclient.data.l[1] == XEMBED_FOCUS_OUT) { - win.mode &= ~MODE_FOCUSED; - } - } else if (e->xclient.data.l[0] == xw.wmdeletewin) { - ttyhangup(); - exit(0); - } -} - -void -resize(XEvent *e) -{ - if (e->xconfigure.width == win.w && e->xconfigure.height == win.h) - return; - - cresize(e->xconfigure.width, e->xconfigure.height); -} - -void -run(void) -{ - XEvent ev; - int w = win.w, h = win.h; - fd_set rfd; - int xfd = XConnectionNumber(xw.dpy), ttyfd, xev, drawing; - struct timespec seltv, *tv, now, lastblink, trigger; - double timeout; - - /* Waiting for window mapping */ - do { - XNextEvent(xw.dpy, &ev); - /* - * This XFilterEvent call is required because of XOpenIM. It - * does filter out the key event and some client message for - * the input method too. - */ - if (XFilterEvent(&ev, None)) - continue; - if (ev.type == ConfigureNotify) { - w = ev.xconfigure.width; - h = ev.xconfigure.height; - } - } while (ev.type != MapNotify); - - ttyfd = ttynew(opt_line, shell, opt_io, opt_cmd); - cresize(w, h); - - for (timeout = -1, drawing = 0, lastblink = (struct timespec){0};;) { - FD_ZERO(&rfd); - FD_SET(ttyfd, &rfd); - FD_SET(xfd, &rfd); - - if (XPending(xw.dpy)) - timeout = 0; /* existing events might not set xfd */ - - seltv.tv_sec = timeout / 1E3; - seltv.tv_nsec = 1E6 * (timeout - 1E3 * seltv.tv_sec); - tv = timeout >= 0 ? &seltv : NULL; - - if (pselect(MAX(xfd, ttyfd)+1, &rfd, NULL, NULL, tv, NULL) < 0) { - if (errno == EINTR) - continue; - die("select failed: %s\n", strerror(errno)); - } - clock_gettime(CLOCK_MONOTONIC, &now); - - if (FD_ISSET(ttyfd, &rfd)) - ttyread(); - - xev = 0; - while (XPending(xw.dpy)) { - xev = 1; - XNextEvent(xw.dpy, &ev); - if (XFilterEvent(&ev, None)) - continue; - if (handler[ev.type]) - (handler[ev.type])(&ev); - } - - /* - * To reduce flicker and tearing, when new content or event - * triggers drawing, we first wait a bit to ensure we got - * everything, and if nothing new arrives - we draw. - * We start with trying to wait minlatency ms. If more content - * arrives sooner, we retry with shorter and shorter periods, - * and eventually draw even without idle after maxlatency ms. - * Typically this results in low latency while interacting, - * maximum latency intervals during `cat huge.txt`, and perfect - * sync with periodic updates from animations/key-repeats/etc. - */ - if (FD_ISSET(ttyfd, &rfd) || xev) { - if (!drawing) { - trigger = now; - drawing = 1; - } - timeout = (maxlatency - TIMEDIFF(now, trigger)) \ - / maxlatency * minlatency; - if (timeout > 0) - continue; /* we have time, try to find idle */ - } - - /* idle detected or maxlatency exhausted -> draw */ - timeout = -1; - if (blinktimeout && tattrset(ATTR_BLINK)) { - timeout = blinktimeout - TIMEDIFF(now, lastblink); - if (timeout <= 0) { - if (-timeout > blinktimeout) /* start visible */ - win.mode |= MODE_BLINK; - win.mode ^= MODE_BLINK; - tsetdirtattr(ATTR_BLINK); - lastblink = now; - timeout = blinktimeout; - } - } - - draw(); - XFlush(xw.dpy); - drawing = 0; - } -} - -void -usage(void) -{ - die("usage: %s [-aiv] [-c class] [-f font] [-g geometry]" - " [-n name] [-o file]\n" - " [-T title] [-t title] [-w windowid]" - " [[-e] command [args ...]]\n" - " %s [-aiv] [-c class] [-f font] [-g geometry]" - " [-n name] [-o file]\n" - " [-T title] [-t title] [-w windowid] -l line" - " [stty_args ...]\n", argv0, argv0); -} - -int -main(int argc, char *argv[]) -{ - xw.l = xw.t = 0; - xw.isfixed = False; - xsetcursor(cursorshape); - - ARGBEGIN { - case 'a': - allowaltscreen = 0; - break; - case 'A': - opt_alpha = EARGF(usage()); - break; - case 'c': - opt_class = EARGF(usage()); - break; - case 'e': - if (argc > 0) - --argc, ++argv; - goto run; - case 'f': - opt_font = EARGF(usage()); - break; - case 'g': - xw.gm = XParseGeometry(EARGF(usage()), - &xw.l, &xw.t, &cols, &rows); - break; - case 'i': - xw.isfixed = 1; - break; - case 'o': - opt_io = EARGF(usage()); - break; - case 'l': - opt_line = EARGF(usage()); - break; - case 'n': - opt_name = EARGF(usage()); - break; - case 't': - case 'T': - opt_title = EARGF(usage()); - break; - case 'w': - opt_embed = EARGF(usage()); - break; - case 'v': - die("%s " VERSION "\n", argv0); - break; - default: - usage(); - } ARGEND; - -run: - if (argc > 0) /* eat all remaining arguments */ - opt_cmd = argv; - - if (!opt_title) - opt_title = (opt_line || !opt_cmd) ? "st" : opt_cmd[0]; - - setlocale(LC_CTYPE, ""); - XSetLocaleModifiers(""); - cols = MAX(cols, 1); - rows = MAX(rows, 1); - tnew(cols, rows); - xinit(cols, rows); - xsetenv(); - selinit(); - run(); - - return 0; -} diff --git a/utils/st-0.9/x.c.orig b/utils/st-0.9/x.c.orig deleted file mode 100644 index 27e81d1..0000000 --- a/utils/st-0.9/x.c.orig +++ /dev/null @@ -1,2116 +0,0 @@ -/* See LICENSE for license details. */ -#include <errno.h> -#include <math.h> -#include <limits.h> -#include <locale.h> -#include <signal.h> -#include <sys/select.h> -#include <time.h> -#include <unistd.h> -#include <libgen.h> -#include <X11/Xatom.h> -#include <X11/Xlib.h> -#include <X11/cursorfont.h> -#include <X11/keysym.h> -#include <X11/Xft/Xft.h> -#include <X11/XKBlib.h> - -char *argv0; -#include "arg.h" -#include "st.h" -#include "win.h" - -/* types used in config.h */ -typedef struct { - uint mod; - KeySym keysym; - void (*func)(const Arg *); - const Arg arg; -} Shortcut; - -typedef struct { - uint mod; - uint button; - void (*func)(const Arg *); - const Arg arg; - uint release; -} MouseShortcut; - -typedef struct { - KeySym k; - uint mask; - char *s; - /* three-valued logic variables: 0 indifferent, 1 on, -1 off */ - signed char appkey; /* application keypad */ - signed char appcursor; /* application cursor */ -} Key; - -/* X modifiers */ -#define XK_ANY_MOD UINT_MAX -#define XK_NO_MOD 0 -#define XK_SWITCH_MOD (1<<13|1<<14) - -/* function definitions used in config.h */ -static void clipcopy(const Arg *); -static void clippaste(const Arg *); -static void numlock(const Arg *); -static void selpaste(const Arg *); -static void zoom(const Arg *); -static void zoomabs(const Arg *); -static void zoomreset(const Arg *); -static void ttysend(const Arg *); - -/* config.h for applying patches and the configuration. */ -#include "config.h" - -/* XEMBED messages */ -#define XEMBED_FOCUS_IN 4 -#define XEMBED_FOCUS_OUT 5 - -/* macros */ -#define IS_SET(flag) ((win.mode & (flag)) != 0) -#define TRUERED(x) (((x) & 0xff0000) >> 8) -#define TRUEGREEN(x) (((x) & 0xff00)) -#define TRUEBLUE(x) (((x) & 0xff) << 8) - -typedef XftDraw *Draw; -typedef XftColor Color; -typedef XftGlyphFontSpec GlyphFontSpec; - -/* Purely graphic info */ -typedef struct { - int tw, th; /* tty width and height */ - int w, h; /* window width and height */ - int ch; /* char height */ - int cw; /* char width */ - int mode; /* window state/mode flags */ - int cursor; /* cursor style */ -} TermWindow; - -typedef struct { - Display *dpy; - Colormap cmap; - Window win; - Drawable buf; - GlyphFontSpec *specbuf; /* font spec buffer used for rendering */ - Atom xembed, wmdeletewin, netwmname, netwmiconname, netwmpid; - struct { - XIM xim; - XIC xic; - XPoint spot; - XVaNestedList spotlist; - } ime; - Draw draw; - Visual *vis; - XSetWindowAttributes attrs; - int scr; - int isfixed; /* is fixed geometry? */ - int depth; /* bit depth */ - int l, t; /* left and top offset */ - int gm; /* geometry mask */ -} XWindow; - -typedef struct { - Atom xtarget; - char *primary, *clipboard; - struct timespec tclick1; - struct timespec tclick2; -} XSelection; - -/* Font structure */ -#define Font Font_ -typedef struct { - int height; - int width; - int ascent; - int descent; - int badslant; - int badweight; - short lbearing; - short rbearing; - XftFont *match; - FcFontSet *set; - FcPattern *pattern; -} Font; - -/* Drawing Context */ -typedef struct { - Color *col; - size_t collen; - Font font, bfont, ifont, ibfont; - GC gc; -} DC; - -static inline ushort sixd_to_16bit(int); -static int xmakeglyphfontspecs(XftGlyphFontSpec *, const Glyph *, int, int, int); -static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, int); -static void xdrawglyph(Glyph, int, int); -static void xclear(int, int, int, int); -static int xgeommasktogravity(int); -static int ximopen(Display *); -static void ximinstantiate(Display *, XPointer, XPointer); -static void ximdestroy(XIM, XPointer, XPointer); -static int xicdestroy(XIC, XPointer, XPointer); -static void xinit(int, int); -static void cresize(int, int); -static void xresize(int, int); -static void xhints(void); -static int xloadcolor(int, const char *, Color *); -static int xloadfont(Font *, FcPattern *); -static void xloadfonts(const char *, double); -static void xunloadfont(Font *); -static void xunloadfonts(void); -static void xsetenv(void); -static void xseturgency(int); -static int evcol(XEvent *); -static int evrow(XEvent *); - -static void expose(XEvent *); -static void visibility(XEvent *); -static void unmap(XEvent *); -static void kpress(XEvent *); -static void cmessage(XEvent *); -static void resize(XEvent *); -static void focus(XEvent *); -static uint buttonmask(uint); -static int mouseaction(XEvent *, uint); -static void brelease(XEvent *); -static void bpress(XEvent *); -static void bmotion(XEvent *); -static void propnotify(XEvent *); -static void selnotify(XEvent *); -static void selclear_(XEvent *); -static void selrequest(XEvent *); -static void setsel(char *, Time); -static void mousesel(XEvent *, int); -static void mousereport(XEvent *); -static char *kmap(KeySym, uint); -static int match(uint, uint); - -static void run(void); -static void usage(void); - -static void (*handler[LASTEvent])(XEvent *) = { - [KeyPress] = kpress, - [ClientMessage] = cmessage, - [ConfigureNotify] = resize, - [VisibilityNotify] = visibility, - [UnmapNotify] = unmap, - [Expose] = expose, - [FocusIn] = focus, - [FocusOut] = focus, - [MotionNotify] = bmotion, - [ButtonPress] = bpress, - [ButtonRelease] = brelease, -/* - * Uncomment if you want the selection to disappear when you select something - * different in another window. - */ -/* [SelectionClear] = selclear_, */ - [SelectionNotify] = selnotify, -/* - * PropertyNotify is only turned on when there is some INCR transfer happening - * for the selection retrieval. - */ - [PropertyNotify] = propnotify, - [SelectionRequest] = selrequest, -}; - -/* Globals */ -static DC dc; -static XWindow xw; -static XSelection xsel; -static TermWindow win; - -/* Font Ring Cache */ -enum { - FRC_NORMAL, - FRC_ITALIC, - FRC_BOLD, - FRC_ITALICBOLD -}; - -typedef struct { - XftFont *font; - int flags; - Rune unicodep; -} Fontcache; - -/* Fontcache is an array now. A new font will be appended to the array. */ -static Fontcache *frc = NULL; -static int frclen = 0; -static int frccap = 0; -static char *usedfont = NULL; -static double usedfontsize = 0; -static double defaultfontsize = 0; - -static char *opt_alpha = NULL; -static char *opt_class = NULL; -static char **opt_cmd = NULL; -static char *opt_embed = NULL; -static char *opt_font = NULL; -static char *opt_io = NULL; -static char *opt_line = NULL; -static char *opt_name = NULL; -static char *opt_title = NULL; - -static uint buttons; /* bit field of pressed buttons */ - -void -clipcopy(const Arg *dummy) -{ - Atom clipboard; - - free(xsel.clipboard); - xsel.clipboard = NULL; - - if (xsel.primary != NULL) { - xsel.clipboard = xstrdup(xsel.primary); - clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); - XSetSelectionOwner(xw.dpy, clipboard, xw.win, CurrentTime); - } -} - -void -clippaste(const Arg *dummy) -{ - Atom clipboard; - - clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); - XConvertSelection(xw.dpy, clipboard, xsel.xtarget, clipboard, - xw.win, CurrentTime); -} - -void -selpaste(const Arg *dummy) -{ - XConvertSelection(xw.dpy, XA_PRIMARY, xsel.xtarget, XA_PRIMARY, - xw.win, CurrentTime); -} - -void -numlock(const Arg *dummy) -{ - win.mode ^= MODE_NUMLOCK; -} - -void -zoom(const Arg *arg) -{ - Arg larg; - - larg.f = usedfontsize + arg->f; - zoomabs(&larg); -} - -void -zoomabs(const Arg *arg) -{ - xunloadfonts(); - xloadfonts(usedfont, arg->f); - cresize(0, 0); - redraw(); - xhints(); -} - -void -zoomreset(const Arg *arg) -{ - Arg larg; - - if (defaultfontsize > 0) { - larg.f = defaultfontsize; - zoomabs(&larg); - } -} - -void -ttysend(const Arg *arg) -{ - ttywrite(arg->s, strlen(arg->s), 1); -} - -int -evcol(XEvent *e) -{ - int x = e->xbutton.x - borderpx; - LIMIT(x, 0, win.tw - 1); - return x / win.cw; -} - -int -evrow(XEvent *e) -{ - int y = e->xbutton.y - borderpx; - LIMIT(y, 0, win.th - 1); - return y / win.ch; -} - -void -mousesel(XEvent *e, int done) -{ - int type, seltype = SEL_REGULAR; - uint state = e->xbutton.state & ~(Button1Mask | forcemousemod); - - for (type = 1; type < LEN(selmasks); ++type) { - if (match(selmasks[type], state)) { - seltype = type; - break; - } - } - selextend(evcol(e), evrow(e), seltype, done); - if (done) - setsel(getsel(), e->xbutton.time); -} - -void -mousereport(XEvent *e) -{ - int len, btn, code; - int x = evcol(e), y = evrow(e); - int state = e->xbutton.state; - char buf[40]; - static int ox, oy; - - if (e->type == MotionNotify) { - if (x == ox && y == oy) - return; - if (!IS_SET(MODE_MOUSEMOTION) && !IS_SET(MODE_MOUSEMANY)) - return; - /* MODE_MOUSEMOTION: no reporting if no button is pressed */ - if (IS_SET(MODE_MOUSEMOTION) && buttons == 0) - return; - /* Set btn to lowest-numbered pressed button, or 12 if no - * buttons are pressed. */ - for (btn = 1; btn <= 11 && !(buttons & (1<<(btn-1))); btn++) - ; - code = 32; - } else { - btn = e->xbutton.button; - /* Only buttons 1 through 11 can be encoded */ - if (btn < 1 || btn > 11) - return; - if (e->type == ButtonRelease) { - /* MODE_MOUSEX10: no button release reporting */ - if (IS_SET(MODE_MOUSEX10)) - return; - /* Don't send release events for the scroll wheel */ - if (btn == 4 || btn == 5) - return; - } - code = 0; - } - - ox = x; - oy = y; - - /* Encode btn into code. If no button is pressed for a motion event in - * MODE_MOUSEMANY, then encode it as a release. */ - if ((!IS_SET(MODE_MOUSESGR) && e->type == ButtonRelease) || btn == 12) - code += 3; - else if (btn >= 8) - code += 128 + btn - 8; - else if (btn >= 4) - code += 64 + btn - 4; - else - code += btn - 1; - - if (!IS_SET(MODE_MOUSEX10)) { - code += ((state & ShiftMask ) ? 4 : 0) - + ((state & Mod1Mask ) ? 8 : 0) /* meta key: alt */ - + ((state & ControlMask) ? 16 : 0); - } - - if (IS_SET(MODE_MOUSESGR)) { - len = snprintf(buf, sizeof(buf), "\033[<%d;%d;%d%c", - code, x+1, y+1, - e->type == ButtonRelease ? 'm' : 'M'); - } else if (x < 223 && y < 223) { - len = snprintf(buf, sizeof(buf), "\033[M%c%c%c", - 32+code, 32+x+1, 32+y+1); - } else { - return; - } - - ttywrite(buf, len, 0); -} - -uint -buttonmask(uint button) -{ - return button == Button1 ? Button1Mask - : button == Button2 ? Button2Mask - : button == Button3 ? Button3Mask - : button == Button4 ? Button4Mask - : button == Button5 ? Button5Mask - : 0; -} - -int -mouseaction(XEvent *e, uint release) -{ - MouseShortcut *ms; - - /* ignore Button<N>mask for Button<N> - it's set on release */ - uint state = e->xbutton.state & ~buttonmask(e->xbutton.button); - - for (ms = mshortcuts; ms < mshortcuts + LEN(mshortcuts); ms++) { - if (ms->release == release && - ms->button == e->xbutton.button && - (match(ms->mod, state) || /* exact or forced */ - match(ms->mod, state & ~forcemousemod))) { - ms->func(&(ms->arg)); - return 1; - } - } - - return 0; -} - -void -bpress(XEvent *e) -{ - int btn = e->xbutton.button; - struct timespec now; - int snap; - - if (1 <= btn && btn <= 11) - buttons |= 1 << (btn-1); - - if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { - mousereport(e); - return; - } - - if (mouseaction(e, 0)) - return; - - if (btn == Button1) { - /* - * If the user clicks below predefined timeouts specific - * snapping behaviour is exposed. - */ - clock_gettime(CLOCK_MONOTONIC, &now); - if (TIMEDIFF(now, xsel.tclick2) <= tripleclicktimeout) { - snap = SNAP_LINE; - } else if (TIMEDIFF(now, xsel.tclick1) <= doubleclicktimeout) { - snap = SNAP_WORD; - } else { - snap = 0; - } - xsel.tclick2 = xsel.tclick1; - xsel.tclick1 = now; - - selstart(evcol(e), evrow(e), snap); - } -} - -void -propnotify(XEvent *e) -{ - XPropertyEvent *xpev; - Atom clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); - - xpev = &e->xproperty; - if (xpev->state == PropertyNewValue && - (xpev->atom == XA_PRIMARY || - xpev->atom == clipboard)) { - selnotify(e); - } -} - -void -selnotify(XEvent *e) -{ - ulong nitems, ofs, rem; - int format; - uchar *data, *last, *repl; - Atom type, incratom, property = None; - - incratom = XInternAtom(xw.dpy, "INCR", 0); - - ofs = 0; - if (e->type == SelectionNotify) - property = e->xselection.property; - else if (e->type == PropertyNotify) - property = e->xproperty.atom; - - if (property == None) - return; - - do { - if (XGetWindowProperty(xw.dpy, xw.win, property, ofs, - BUFSIZ/4, False, AnyPropertyType, - &type, &format, &nitems, &rem, - &data)) { - fprintf(stderr, "Clipboard allocation failed\n"); - return; - } - - if (e->type == PropertyNotify && nitems == 0 && rem == 0) { - /* - * If there is some PropertyNotify with no data, then - * this is the signal of the selection owner that all - * data has been transferred. We won't need to receive - * PropertyNotify events anymore. - */ - MODBIT(xw.attrs.event_mask, 0, PropertyChangeMask); - XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, - &xw.attrs); - } - - if (type == incratom) { - /* - * Activate the PropertyNotify events so we receive - * when the selection owner does send us the next - * chunk of data. - */ - MODBIT(xw.attrs.event_mask, 1, PropertyChangeMask); - XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, - &xw.attrs); - - /* - * Deleting the property is the transfer start signal. - */ - XDeleteProperty(xw.dpy, xw.win, (int)property); - continue; - } - - /* - * As seen in getsel: - * Line endings are inconsistent in the terminal and GUI world - * copy and pasting. When receiving some selection data, - * replace all '\n' with '\r'. - * FIXME: Fix the computer world. - */ - repl = data; - last = data + nitems * format / 8; - while ((repl = memchr(repl, '\n', last - repl))) { - *repl++ = '\r'; - } - - if (IS_SET(MODE_BRCKTPASTE) && ofs == 0) - ttywrite("\033[200~", 6, 0); - ttywrite((char *)data, nitems * format / 8, 1); - if (IS_SET(MODE_BRCKTPASTE) && rem == 0) - ttywrite("\033[201~", 6, 0); - XFree(data); - /* number of 32-bit chunks returned */ - ofs += nitems * format / 32; - } while (rem > 0); - - /* - * Deleting the property again tells the selection owner to send the - * next data chunk in the property. - */ - XDeleteProperty(xw.dpy, xw.win, (int)property); -} - -void -xclipcopy(void) -{ - clipcopy(NULL); -} - -void -selclear_(XEvent *e) -{ - selclear(); -} - -void -selrequest(XEvent *e) -{ - XSelectionRequestEvent *xsre; - XSelectionEvent xev; - Atom xa_targets, string, clipboard; - char *seltext; - - xsre = (XSelectionRequestEvent *) e; - xev.type = SelectionNotify; - xev.requestor = xsre->requestor; - xev.selection = xsre->selection; - xev.target = xsre->target; - xev.time = xsre->time; - if (xsre->property == None) - xsre->property = xsre->target; - - /* reject */ - xev.property = None; - - xa_targets = XInternAtom(xw.dpy, "TARGETS", 0); - if (xsre->target == xa_targets) { - /* respond with the supported type */ - string = xsel.xtarget; - XChangeProperty(xsre->display, xsre->requestor, xsre->property, - XA_ATOM, 32, PropModeReplace, - (uchar *) &string, 1); - xev.property = xsre->property; - } else if (xsre->target == xsel.xtarget || xsre->target == XA_STRING) { - /* - * xith XA_STRING non ascii characters may be incorrect in the - * requestor. It is not our problem, use utf8. - */ - clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); - if (xsre->selection == XA_PRIMARY) { - seltext = xsel.primary; - } else if (xsre->selection == clipboard) { - seltext = xsel.clipboard; - } else { - fprintf(stderr, - "Unhandled clipboard selection 0x%lx\n", - xsre->selection); - return; - } - if (seltext != NULL) { - XChangeProperty(xsre->display, xsre->requestor, - xsre->property, xsre->target, - 8, PropModeReplace, - (uchar *)seltext, strlen(seltext)); - xev.property = xsre->property; - } - } - - /* all done, send a notification to the listener */ - if (!XSendEvent(xsre->display, xsre->requestor, 1, 0, (XEvent *) &xev)) - fprintf(stderr, "Error sending SelectionNotify event\n"); -} - -void -setsel(char *str, Time t) -{ - if (!str) - return; - - free(xsel.primary); - xsel.primary = str; - - XSetSelectionOwner(xw.dpy, XA_PRIMARY, xw.win, t); - if (XGetSelectionOwner(xw.dpy, XA_PRIMARY) != xw.win) - selclear(); -} - -void -xsetsel(char *str) -{ - setsel(str, CurrentTime); -} - -void -brelease(XEvent *e) -{ - int btn = e->xbutton.button; - - if (1 <= btn && btn <= 11) - buttons &= ~(1 << (btn-1)); - - if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { - mousereport(e); - return; - } - - if (mouseaction(e, 1)) - return; - if (btn == Button1) - mousesel(e, 1); -} - -void -bmotion(XEvent *e) -{ - if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { - mousereport(e); - return; - } - - mousesel(e, 0); -} - -void -cresize(int width, int height) -{ - int col, row; - - if (width != 0) - win.w = width; - if (height != 0) - win.h = height; - - col = (win.w - 2 * borderpx) / win.cw; - row = (win.h - 2 * borderpx) / win.ch; - col = MAX(1, col); - row = MAX(1, row); - - tresize(col, row); - xresize(col, row); - ttyresize(win.tw, win.th); -} - -void -xresize(int col, int row) -{ - win.tw = col * win.cw; - win.th = row * win.ch; - - XFreePixmap(xw.dpy, xw.buf); - xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, - xw.depth); - XftDrawChange(xw.draw, xw.buf); - xclear(0, 0, win.w, win.h); - - /* resize to new width */ - xw.specbuf = xrealloc(xw.specbuf, col * sizeof(GlyphFontSpec)); -} - -ushort -sixd_to_16bit(int x) -{ - return x == 0 ? 0 : 0x3737 + 0x2828 * x; -} - -int -xloadcolor(int i, const char *name, Color *ncolor) -{ - XRenderColor color = { .alpha = 0xffff }; - - if (!name) { - if (BETWEEN(i, 16, 255)) { /* 256 color */ - if (i < 6*6*6+16) { /* same colors as xterm */ - color.red = sixd_to_16bit( ((i-16)/36)%6 ); - color.green = sixd_to_16bit( ((i-16)/6) %6 ); - color.blue = sixd_to_16bit( ((i-16)/1) %6 ); - } else { /* greyscale */ - color.red = 0x0808 + 0x0a0a * (i - (6*6*6+16)); - color.green = color.blue = color.red; - } - return XftColorAllocValue(xw.dpy, xw.vis, - xw.cmap, &color, ncolor); - } else - name = colorname[i]; - } - - return XftColorAllocName(xw.dpy, xw.vis, xw.cmap, name, ncolor); -} - -void -xloadcols(void) -{ - int i; - static int loaded; - Color *cp; - - if (loaded) { - for (cp = dc.col; cp < &dc.col[dc.collen]; ++cp) - XftColorFree(xw.dpy, xw.vis, xw.cmap, cp); - } else { - dc.collen = MAX(LEN(colorname), 256); - dc.col = xmalloc(dc.collen * sizeof(Color)); - } - - for (i = 0; i < dc.collen; i++) - if (!xloadcolor(i, NULL, &dc.col[i])) { - if (colorname[i]) - die("could not allocate color '%s'\n", colorname[i]); - else - die("could not allocate color %d\n", i); - } - - /* set alpha value of bg color */ - if (opt_alpha) - alpha = strtof(opt_alpha, NULL); - dc.col[defaultbg].color.alpha = (unsigned short)(0xffff * alpha); - dc.col[defaultbg].pixel &= 0x00FFFFFF; - dc.col[defaultbg].pixel |= (unsigned char)(0xff * alpha) << 24; - loaded = 1; -} - -int -xgetcolor(int x, unsigned char *r, unsigned char *g, unsigned char *b) -{ - if (!BETWEEN(x, 0, dc.collen)) - return 1; - - *r = dc.col[x].color.red >> 8; - *g = dc.col[x].color.green >> 8; - *b = dc.col[x].color.blue >> 8; - - return 0; -} - -int -xsetcolorname(int x, const char *name) -{ - Color ncolor; - - if (!BETWEEN(x, 0, dc.collen)) - return 1; - - if (!xloadcolor(x, name, &ncolor)) - return 1; - - XftColorFree(xw.dpy, xw.vis, xw.cmap, &dc.col[x]); - dc.col[x] = ncolor; - - return 0; -} - -/* - * Absolute coordinates. - */ -void -xclear(int x1, int y1, int x2, int y2) -{ - XftDrawRect(xw.draw, - &dc.col[IS_SET(MODE_REVERSE)? defaultfg : defaultbg], - x1, y1, x2-x1, y2-y1); -} - -void -xhints(void) -{ - XClassHint class = {opt_name ? opt_name : termname, - opt_class ? opt_class : termname}; - XWMHints wm = {.flags = InputHint, .input = 1}; - XSizeHints *sizeh; - - sizeh = XAllocSizeHints(); - - sizeh->flags = PSize | PResizeInc | PBaseSize | PMinSize; - sizeh->height = win.h; - sizeh->width = win.w; - sizeh->height_inc = win.ch; - sizeh->width_inc = win.cw; - sizeh->base_height = 2 * borderpx; - sizeh->base_width = 2 * borderpx; - sizeh->min_height = win.ch + 2 * borderpx; - sizeh->min_width = win.cw + 2 * borderpx; - if (xw.isfixed) { - sizeh->flags |= PMaxSize; - sizeh->min_width = sizeh->max_width = win.w; - sizeh->min_height = sizeh->max_height = win.h; - } - if (xw.gm & (XValue|YValue)) { - sizeh->flags |= USPosition | PWinGravity; - sizeh->x = xw.l; - sizeh->y = xw.t; - sizeh->win_gravity = xgeommasktogravity(xw.gm); - } - - XSetWMProperties(xw.dpy, xw.win, NULL, NULL, NULL, 0, sizeh, &wm, - &class); - XFree(sizeh); -} - -int -xgeommasktogravity(int mask) -{ - switch (mask & (XNegative|YNegative)) { - case 0: - return NorthWestGravity; - case XNegative: - return NorthEastGravity; - case YNegative: - return SouthWestGravity; - } - - return SouthEastGravity; -} - -int -xloadfont(Font *f, FcPattern *pattern) -{ - FcPattern *configured; - FcPattern *match; - FcResult result; - XGlyphInfo extents; - int wantattr, haveattr; - - /* - * Manually configure instead of calling XftMatchFont - * so that we can use the configured pattern for - * "missing glyph" lookups. - */ - configured = FcPatternDuplicate(pattern); - if (!configured) - return 1; - - FcConfigSubstitute(NULL, configured, FcMatchPattern); - XftDefaultSubstitute(xw.dpy, xw.scr, configured); - - match = FcFontMatch(NULL, configured, &result); - if (!match) { - FcPatternDestroy(configured); - return 1; - } - - if (!(f->match = XftFontOpenPattern(xw.dpy, match))) { - FcPatternDestroy(configured); - FcPatternDestroy(match); - return 1; - } - - if ((XftPatternGetInteger(pattern, "slant", 0, &wantattr) == - XftResultMatch)) { - /* - * Check if xft was unable to find a font with the appropriate - * slant but gave us one anyway. Try to mitigate. - */ - if ((XftPatternGetInteger(f->match->pattern, "slant", 0, - &haveattr) != XftResultMatch) || haveattr < wantattr) { - f->badslant = 1; - fputs("font slant does not match\n", stderr); - } - } - - if ((XftPatternGetInteger(pattern, "weight", 0, &wantattr) == - XftResultMatch)) { - if ((XftPatternGetInteger(f->match->pattern, "weight", 0, - &haveattr) != XftResultMatch) || haveattr != wantattr) { - f->badweight = 1; - fputs("font weight does not match\n", stderr); - } - } - - XftTextExtentsUtf8(xw.dpy, f->match, - (const FcChar8 *) ascii_printable, - strlen(ascii_printable), &extents); - - f->set = NULL; - f->pattern = configured; - - f->ascent = f->match->ascent; - f->descent = f->match->descent; - f->lbearing = 0; - f->rbearing = f->match->max_advance_width; - - f->height = f->ascent + f->descent; - f->width = DIVCEIL(extents.xOff, strlen(ascii_printable)); - - return 0; -} - -void -xloadfonts(const char *fontstr, double fontsize) -{ - FcPattern *pattern; - double fontval; - - if (fontstr[0] == '-') - pattern = XftXlfdParse(fontstr, False, False); - else - pattern = FcNameParse((const FcChar8 *)fontstr); - - if (!pattern) - die("can't open font %s\n", fontstr); - - if (fontsize > 1) { - FcPatternDel(pattern, FC_PIXEL_SIZE); - FcPatternDel(pattern, FC_SIZE); - FcPatternAddDouble(pattern, FC_PIXEL_SIZE, (double)fontsize); - usedfontsize = fontsize; - } else { - if (FcPatternGetDouble(pattern, FC_PIXEL_SIZE, 0, &fontval) == - FcResultMatch) { - usedfontsize = fontval; - } else if (FcPatternGetDouble(pattern, FC_SIZE, 0, &fontval) == - FcResultMatch) { - usedfontsize = -1; - } else { - /* - * Default font size is 12, if none given. This is to - * have a known usedfontsize value. - */ - FcPatternAddDouble(pattern, FC_PIXEL_SIZE, 12); - usedfontsize = 12; - } - defaultfontsize = usedfontsize; - } - - if (xloadfont(&dc.font, pattern)) - die("can't open font %s\n", fontstr); - - if (usedfontsize < 0) { - FcPatternGetDouble(dc.font.match->pattern, - FC_PIXEL_SIZE, 0, &fontval); - usedfontsize = fontval; - if (fontsize == 0) - defaultfontsize = fontval; - } - - /* Setting character width and height. */ - win.cw = ceilf(dc.font.width * cwscale); - win.ch = ceilf(dc.font.height * chscale); - - FcPatternDel(pattern, FC_SLANT); - FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC); - if (xloadfont(&dc.ifont, pattern)) - die("can't open font %s\n", fontstr); - - FcPatternDel(pattern, FC_WEIGHT); - FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_BOLD); - if (xloadfont(&dc.ibfont, pattern)) - die("can't open font %s\n", fontstr); - - FcPatternDel(pattern, FC_SLANT); - FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ROMAN); - if (xloadfont(&dc.bfont, pattern)) - die("can't open font %s\n", fontstr); - - FcPatternDestroy(pattern); -} - -void -xunloadfont(Font *f) -{ - XftFontClose(xw.dpy, f->match); - FcPatternDestroy(f->pattern); - if (f->set) - FcFontSetDestroy(f->set); -} - -void -xunloadfonts(void) -{ - /* Free the loaded fonts in the font cache. */ - while (frclen > 0) - XftFontClose(xw.dpy, frc[--frclen].font); - - xunloadfont(&dc.font); - xunloadfont(&dc.bfont); - xunloadfont(&dc.ifont); - xunloadfont(&dc.ibfont); -} - -int -ximopen(Display *dpy) -{ - XIMCallback imdestroy = { .client_data = NULL, .callback = ximdestroy }; - XICCallback icdestroy = { .client_data = NULL, .callback = xicdestroy }; - - xw.ime.xim = XOpenIM(xw.dpy, NULL, NULL, NULL); - if (xw.ime.xim == NULL) - return 0; - - if (XSetIMValues(xw.ime.xim, XNDestroyCallback, &imdestroy, NULL)) - fprintf(stderr, "XSetIMValues: " - "Could not set XNDestroyCallback.\n"); - - xw.ime.spotlist = XVaCreateNestedList(0, XNSpotLocation, &xw.ime.spot, - NULL); - - if (xw.ime.xic == NULL) { - xw.ime.xic = XCreateIC(xw.ime.xim, XNInputStyle, - XIMPreeditNothing | XIMStatusNothing, - XNClientWindow, xw.win, - XNDestroyCallback, &icdestroy, - NULL); - } - if (xw.ime.xic == NULL) - fprintf(stderr, "XCreateIC: Could not create input context.\n"); - - return 1; -} - -void -ximinstantiate(Display *dpy, XPointer client, XPointer call) -{ - if (ximopen(dpy)) - XUnregisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, - ximinstantiate, NULL); -} - -void -ximdestroy(XIM xim, XPointer client, XPointer call) -{ - xw.ime.xim = NULL; - XRegisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, - ximinstantiate, NULL); - XFree(xw.ime.spotlist); -} - -int -xicdestroy(XIC xim, XPointer client, XPointer call) -{ - xw.ime.xic = NULL; - return 1; -} - -void -xinit(int cols, int rows) -{ - XGCValues gcvalues; - Cursor cursor; - Window parent; - pid_t thispid = getpid(); - XColor xmousefg, xmousebg; - XWindowAttributes attr; - XVisualInfo vis; - - if (!(xw.dpy = XOpenDisplay(NULL))) - die("can't open display\n"); - xw.scr = XDefaultScreen(xw.dpy); - - if (!(opt_embed && (parent = strtol(opt_embed, NULL, 0)))) { - parent = XRootWindow(xw.dpy, xw.scr); - xw.depth = 32; - } else { - XGetWindowAttributes(xw.dpy, parent, &attr); - xw.depth = attr.depth; - } - - XMatchVisualInfo(xw.dpy, xw.scr, xw.depth, TrueColor, &vis); - xw.vis = vis.visual; - - /* font */ - if (!FcInit()) - die("could not init fontconfig.\n"); - - usedfont = (opt_font == NULL)? font : opt_font; - xloadfonts(usedfont, 0); - - /* colors */ - xw.cmap = XCreateColormap(xw.dpy, parent, xw.vis, None); - xloadcols(); - - /* adjust fixed window geometry */ - win.w = 2 * borderpx + cols * win.cw; - win.h = 2 * borderpx + rows * win.ch; - if (xw.gm & XNegative) - xw.l += DisplayWidth(xw.dpy, xw.scr) - win.w - 2; - if (xw.gm & YNegative) - xw.t += DisplayHeight(xw.dpy, xw.scr) - win.h - 2; - - /* Events */ - xw.attrs.background_pixel = dc.col[defaultbg].pixel; - xw.attrs.border_pixel = dc.col[defaultbg].pixel; - xw.attrs.bit_gravity = NorthWestGravity; - xw.attrs.event_mask = FocusChangeMask | KeyPressMask | KeyReleaseMask - | ExposureMask | VisibilityChangeMask | StructureNotifyMask - | ButtonMotionMask | ButtonPressMask | ButtonReleaseMask; - xw.attrs.colormap = xw.cmap; - - xw.win = XCreateWindow(xw.dpy, parent, xw.l, xw.t, - win.w, win.h, 0, xw.depth, InputOutput, - xw.vis, CWBackPixel | CWBorderPixel | CWBitGravity - | CWEventMask | CWColormap, &xw.attrs); - - memset(&gcvalues, 0, sizeof(gcvalues)); - gcvalues.graphics_exposures = False; - xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, xw.depth); - dc.gc = XCreateGC(xw.dpy, xw.buf, GCGraphicsExposures, &gcvalues); - XSetForeground(xw.dpy, dc.gc, dc.col[defaultbg].pixel); - XFillRectangle(xw.dpy, xw.buf, dc.gc, 0, 0, win.w, win.h); - - /* font spec buffer */ - xw.specbuf = xmalloc(cols * sizeof(GlyphFontSpec)); - - /* Xft rendering context */ - xw.draw = XftDrawCreate(xw.dpy, xw.buf, xw.vis, xw.cmap); - - /* input methods */ - if (!ximopen(xw.dpy)) { - XRegisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, - ximinstantiate, NULL); - } - - /* white cursor, black outline */ - cursor = XCreateFontCursor(xw.dpy, mouseshape); - XDefineCursor(xw.dpy, xw.win, cursor); - - if (XParseColor(xw.dpy, xw.cmap, colorname[mousefg], &xmousefg) == 0) { - xmousefg.red = 0xffff; - xmousefg.green = 0xffff; - xmousefg.blue = 0xffff; - } - - if (XParseColor(xw.dpy, xw.cmap, colorname[mousebg], &xmousebg) == 0) { - xmousebg.red = 0x0000; - xmousebg.green = 0x0000; - xmousebg.blue = 0x0000; - } - - XRecolorCursor(xw.dpy, cursor, &xmousefg, &xmousebg); - - xw.xembed = XInternAtom(xw.dpy, "_XEMBED", False); - xw.wmdeletewin = XInternAtom(xw.dpy, "WM_DELETE_WINDOW", False); - xw.netwmname = XInternAtom(xw.dpy, "_NET_WM_NAME", False); - xw.netwmiconname = XInternAtom(xw.dpy, "_NET_WM_ICON_NAME", False); - XSetWMProtocols(xw.dpy, xw.win, &xw.wmdeletewin, 1); - - xw.netwmpid = XInternAtom(xw.dpy, "_NET_WM_PID", False); - XChangeProperty(xw.dpy, xw.win, xw.netwmpid, XA_CARDINAL, 32, - PropModeReplace, (uchar *)&thispid, 1); - - win.mode = MODE_NUMLOCK; - resettitle(); - xhints(); - XMapWindow(xw.dpy, xw.win); - XSync(xw.dpy, False); - - clock_gettime(CLOCK_MONOTONIC, &xsel.tclick1); - clock_gettime(CLOCK_MONOTONIC, &xsel.tclick2); - xsel.primary = NULL; - xsel.clipboard = NULL; - xsel.xtarget = XInternAtom(xw.dpy, "UTF8_STRING", 0); - if (xsel.xtarget == None) - xsel.xtarget = XA_STRING; -} - -int -xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x, int y) -{ - float winx = borderpx + x * win.cw, winy = borderpx + y * win.ch, xp, yp; - ushort mode, prevmode = USHRT_MAX; - Font *font = &dc.font; - int frcflags = FRC_NORMAL; - float runewidth = win.cw; - Rune rune; - FT_UInt glyphidx; - FcResult fcres; - FcPattern *fcpattern, *fontpattern; - FcFontSet *fcsets[] = { NULL }; - FcCharSet *fccharset; - int i, f, numspecs = 0; - - for (i = 0, xp = winx, yp = winy + font->ascent; i < len; ++i) { - /* Fetch rune and mode for current glyph. */ - rune = glyphs[i].u; - mode = glyphs[i].mode; - - /* Skip dummy wide-character spacing. */ - if (mode == ATTR_WDUMMY) - continue; - - /* Determine font for glyph if different from previous glyph. */ - if (prevmode != mode) { - prevmode = mode; - font = &dc.font; - frcflags = FRC_NORMAL; - runewidth = win.cw * ((mode & ATTR_WIDE) ? 2.0f : 1.0f); - if ((mode & ATTR_ITALIC) && (mode & ATTR_BOLD)) { - font = &dc.ibfont; - frcflags = FRC_ITALICBOLD; - } else if (mode & ATTR_ITALIC) { - font = &dc.ifont; - frcflags = FRC_ITALIC; - } else if (mode & ATTR_BOLD) { - font = &dc.bfont; - frcflags = FRC_BOLD; - } - yp = winy + font->ascent; - } - - /* Lookup character index with default font. */ - glyphidx = XftCharIndex(xw.dpy, font->match, rune); - if (glyphidx) { - specs[numspecs].font = font->match; - specs[numspecs].glyph = glyphidx; - specs[numspecs].x = (short)xp; - specs[numspecs].y = (short)yp; - xp += runewidth; - numspecs++; - continue; - } - - /* Fallback on font cache, search the font cache for match. */ - for (f = 0; f < frclen; f++) { - glyphidx = XftCharIndex(xw.dpy, frc[f].font, rune); - /* Everything correct. */ - if (glyphidx && frc[f].flags == frcflags) - break; - /* We got a default font for a not found glyph. */ - if (!glyphidx && frc[f].flags == frcflags - && frc[f].unicodep == rune) { - break; - } - } - - /* Nothing was found. Use fontconfig to find matching font. */ - if (f >= frclen) { - if (!font->set) - font->set = FcFontSort(0, font->pattern, - 1, 0, &fcres); - fcsets[0] = font->set; - - /* - * Nothing was found in the cache. Now use - * some dozen of Fontconfig calls to get the - * font for one single character. - * - * Xft and fontconfig are design failures. - */ - fcpattern = FcPatternDuplicate(font->pattern); - fccharset = FcCharSetCreate(); - - FcCharSetAddChar(fccharset, rune); - FcPatternAddCharSet(fcpattern, FC_CHARSET, - fccharset); - FcPatternAddBool(fcpattern, FC_SCALABLE, 1); - - FcConfigSubstitute(0, fcpattern, - FcMatchPattern); - FcDefaultSubstitute(fcpattern); - - fontpattern = FcFontSetMatch(0, fcsets, 1, - fcpattern, &fcres); - - /* Allocate memory for the new cache entry. */ - if (frclen >= frccap) { - frccap += 16; - frc = xrealloc(frc, frccap * sizeof(Fontcache)); - } - - frc[frclen].font = XftFontOpenPattern(xw.dpy, - fontpattern); - if (!frc[frclen].font) - die("XftFontOpenPattern failed seeking fallback font: %s\n", - strerror(errno)); - frc[frclen].flags = frcflags; - frc[frclen].unicodep = rune; - - glyphidx = XftCharIndex(xw.dpy, frc[frclen].font, rune); - - f = frclen; - frclen++; - - FcPatternDestroy(fcpattern); - FcCharSetDestroy(fccharset); - } - - specs[numspecs].font = frc[f].font; - specs[numspecs].glyph = glyphidx; - specs[numspecs].x = (short)xp; - specs[numspecs].y = (short)yp; - xp += runewidth; - numspecs++; - } - - return numspecs; -} - -void -xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y) -{ - int charlen = len * ((base.mode & ATTR_WIDE) ? 2 : 1); - int winx = borderpx + x * win.cw, winy = borderpx + y * win.ch, - width = charlen * win.cw; - Color *fg, *bg, *temp, revfg, revbg, truefg, truebg; - XRenderColor colfg, colbg; - XRectangle r; - - /* Fallback on color display for attributes not supported by the font */ - if (base.mode & ATTR_ITALIC && base.mode & ATTR_BOLD) { - if (dc.ibfont.badslant || dc.ibfont.badweight) - base.fg = defaultattr; - } else if ((base.mode & ATTR_ITALIC && dc.ifont.badslant) || - (base.mode & ATTR_BOLD && dc.bfont.badweight)) { - base.fg = defaultattr; - } - - if (IS_TRUECOL(base.fg)) { - colfg.alpha = 0xffff; - colfg.red = TRUERED(base.fg); - colfg.green = TRUEGREEN(base.fg); - colfg.blue = TRUEBLUE(base.fg); - XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colfg, &truefg); - fg = &truefg; - } else { - fg = &dc.col[base.fg]; - } - - if (IS_TRUECOL(base.bg)) { - colbg.alpha = 0xffff; - colbg.green = TRUEGREEN(base.bg); - colbg.red = TRUERED(base.bg); - colbg.blue = TRUEBLUE(base.bg); - XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colbg, &truebg); - bg = &truebg; - } else { - bg = &dc.col[base.bg]; - } - - /* Change basic system colors [0-7] to bright system colors [8-15] */ - if ((base.mode & ATTR_BOLD_FAINT) == ATTR_BOLD && BETWEEN(base.fg, 0, 7)) - fg = &dc.col[base.fg + 8]; - - if (IS_SET(MODE_REVERSE)) { - if (fg == &dc.col[defaultfg]) { - fg = &dc.col[defaultbg]; - } else { - colfg.red = ~fg->color.red; - colfg.green = ~fg->color.green; - colfg.blue = ~fg->color.blue; - colfg.alpha = fg->color.alpha; - XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colfg, - &revfg); - fg = &revfg; - } - - if (bg == &dc.col[defaultbg]) { - bg = &dc.col[defaultfg]; - } else { - colbg.red = ~bg->color.red; - colbg.green = ~bg->color.green; - colbg.blue = ~bg->color.blue; - colbg.alpha = bg->color.alpha; - XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colbg, - &revbg); - bg = &revbg; - } - } - - if ((base.mode & ATTR_BOLD_FAINT) == ATTR_FAINT) { - colfg.red = fg->color.red / 2; - colfg.green = fg->color.green / 2; - colfg.blue = fg->color.blue / 2; - colfg.alpha = fg->color.alpha; - XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colfg, &revfg); - fg = &revfg; - } - - if (base.mode & ATTR_REVERSE) { - temp = fg; - fg = bg; - bg = temp; - } - - if (base.mode & ATTR_BLINK && win.mode & MODE_BLINK) - fg = bg; - - if (base.mode & ATTR_INVISIBLE) - fg = bg; - - /* Intelligent cleaning up of the borders. */ - if (x == 0) { - xclear(0, (y == 0)? 0 : winy, borderpx, - winy + win.ch + - ((winy + win.ch >= borderpx + win.th)? win.h : 0)); - } - if (winx + width >= borderpx + win.tw) { - xclear(winx + width, (y == 0)? 0 : winy, win.w, - ((winy + win.ch >= borderpx + win.th)? win.h : (winy + win.ch))); - } - if (y == 0) - xclear(winx, 0, winx + width, borderpx); - if (winy + win.ch >= borderpx + win.th) - xclear(winx, winy + win.ch, winx + width, win.h); - - /* Clean up the region we want to draw to. */ - XftDrawRect(xw.draw, bg, winx, winy, width, win.ch); - - /* Set the clip region because Xft is sometimes dirty. */ - r.x = 0; - r.y = 0; - r.height = win.ch; - r.width = width; - XftDrawSetClipRectangles(xw.draw, winx, winy, &r, 1); - - /* Render the glyphs. */ - XftDrawGlyphFontSpec(xw.draw, fg, specs, len); - - /* Render underline and strikethrough. */ - if (base.mode & ATTR_UNDERLINE) { - XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent * chscale + 1, - width, 1); - } - - if (base.mode & ATTR_STRUCK) { - XftDrawRect(xw.draw, fg, winx, winy + 2 * dc.font.ascent * chscale / 3, - width, 1); - } - - /* Reset clip to none. */ - XftDrawSetClip(xw.draw, 0); -} - -void -xdrawglyph(Glyph g, int x, int y) -{ - int numspecs; - XftGlyphFontSpec spec; - - numspecs = xmakeglyphfontspecs(&spec, &g, 1, x, y); - xdrawglyphfontspecs(&spec, g, numspecs, x, y); -} - -void -xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og) -{ - Color drawcol; - - /* remove the old cursor */ - if (selected(ox, oy)) - og.mode ^= ATTR_REVERSE; - xdrawglyph(og, ox, oy); - - if (IS_SET(MODE_HIDE)) - return; - - /* - * Select the right color for the right mode. - */ - g.mode &= ATTR_BOLD|ATTR_ITALIC|ATTR_UNDERLINE|ATTR_STRUCK|ATTR_WIDE; - - if (IS_SET(MODE_REVERSE)) { - g.mode |= ATTR_REVERSE; - g.bg = defaultfg; - if (selected(cx, cy)) { - drawcol = dc.col[defaultcs]; - g.fg = defaultrcs; - } else { - drawcol = dc.col[defaultrcs]; - g.fg = defaultcs; - } - } else { - if (selected(cx, cy)) { - g.fg = defaultfg; - g.bg = defaultrcs; - } else { - g.fg = defaultbg; - g.bg = defaultcs; - } - drawcol = dc.col[g.bg]; - } - - /* draw the new one */ - if (IS_SET(MODE_FOCUSED)) { - switch (win.cursor) { - case 7: /* st extension */ - g.u = 0x2603; /* snowman (U+2603) */ - /* FALLTHROUGH */ - case 0: /* Blinking Block */ - case 1: /* Blinking Block (Default) */ - case 2: /* Steady Block */ - xdrawglyph(g, cx, cy); - break; - case 3: /* Blinking Underline */ - case 4: /* Steady Underline */ - XftDrawRect(xw.draw, &drawcol, - borderpx + cx * win.cw, - borderpx + (cy + 1) * win.ch - \ - cursorthickness, - win.cw, cursorthickness); - break; - case 5: /* Blinking bar */ - case 6: /* Steady bar */ - XftDrawRect(xw.draw, &drawcol, - borderpx + cx * win.cw, - borderpx + cy * win.ch, - cursorthickness, win.ch); - break; - } - } else { - XftDrawRect(xw.draw, &drawcol, - borderpx + cx * win.cw, - borderpx + cy * win.ch, - win.cw - 1, 1); - XftDrawRect(xw.draw, &drawcol, - borderpx + cx * win.cw, - borderpx + cy * win.ch, - 1, win.ch - 1); - XftDrawRect(xw.draw, &drawcol, - borderpx + (cx + 1) * win.cw - 1, - borderpx + cy * win.ch, - 1, win.ch - 1); - XftDrawRect(xw.draw, &drawcol, - borderpx + cx * win.cw, - borderpx + (cy + 1) * win.ch - 1, - win.cw, 1); - } -} - -void -xsetenv(void) -{ - char buf[sizeof(long) * 8 + 1]; - - snprintf(buf, sizeof(buf), "%lu", xw.win); - setenv("WINDOWID", buf, 1); -} - -void -xseticontitle(char *p) -{ - XTextProperty prop; - DEFAULT(p, opt_title); - - if (Xutf8TextListToTextProperty(xw.dpy, &p, 1, XUTF8StringStyle, - &prop) != Success) - return; - XSetWMIconName(xw.dpy, xw.win, &prop); - XSetTextProperty(xw.dpy, xw.win, &prop, xw.netwmiconname); - XFree(prop.value); -} - -void -xsettitle(char *p) -{ - XTextProperty prop; - DEFAULT(p, opt_title); - - if (Xutf8TextListToTextProperty(xw.dpy, &p, 1, XUTF8StringStyle, - &prop) != Success) - return; - XSetWMName(xw.dpy, xw.win, &prop); - XSetTextProperty(xw.dpy, xw.win, &prop, xw.netwmname); - XFree(prop.value); -} - -int -xstartdraw(void) -{ - return IS_SET(MODE_VISIBLE); -} - -void -xdrawline(Line line, int x1, int y1, int x2) -{ - int i, x, ox, numspecs; - Glyph base, new; - XftGlyphFontSpec *specs = xw.specbuf; - - numspecs = xmakeglyphfontspecs(specs, &line[x1], x2 - x1, x1, y1); - i = ox = 0; - for (x = x1; x < x2 && i < numspecs; x++) { - new = line[x]; - if (new.mode == ATTR_WDUMMY) - continue; - if (selected(x, y1)) - new.mode ^= ATTR_REVERSE; - if (i > 0 && ATTRCMP(base, new)) { - xdrawglyphfontspecs(specs, base, i, ox, y1); - specs += i; - numspecs -= i; - i = 0; - } - if (i == 0) { - ox = x; - base = new; - } - i++; - } - if (i > 0) - xdrawglyphfontspecs(specs, base, i, ox, y1); -} - -void -xfinishdraw(void) -{ - XCopyArea(xw.dpy, xw.buf, xw.win, dc.gc, 0, 0, win.w, - win.h, 0, 0); - XSetForeground(xw.dpy, dc.gc, - dc.col[IS_SET(MODE_REVERSE)? - defaultfg : defaultbg].pixel); -} - -void -xximspot(int x, int y) -{ - if (xw.ime.xic == NULL) - return; - - xw.ime.spot.x = borderpx + x * win.cw; - xw.ime.spot.y = borderpx + (y + 1) * win.ch; - - XSetICValues(xw.ime.xic, XNPreeditAttributes, xw.ime.spotlist, NULL); -} - -void -expose(XEvent *ev) -{ - redraw(); -} - -void -visibility(XEvent *ev) -{ - XVisibilityEvent *e = &ev->xvisibility; - - MODBIT(win.mode, e->state != VisibilityFullyObscured, MODE_VISIBLE); -} - -void -unmap(XEvent *ev) -{ - win.mode &= ~MODE_VISIBLE; -} - -void -xsetpointermotion(int set) -{ - MODBIT(xw.attrs.event_mask, set, PointerMotionMask); - XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, &xw.attrs); -} - -void -xsetmode(int set, unsigned int flags) -{ - int mode = win.mode; - MODBIT(win.mode, set, flags); - if ((win.mode & MODE_REVERSE) != (mode & MODE_REVERSE)) - redraw(); -} - -int -xsetcursor(int cursor) -{ - if (!BETWEEN(cursor, 0, 7)) /* 7: st extension */ - return 1; - win.cursor = cursor; - return 0; -} - -void -xseturgency(int add) -{ - XWMHints *h = XGetWMHints(xw.dpy, xw.win); - - MODBIT(h->flags, add, XUrgencyHint); - XSetWMHints(xw.dpy, xw.win, h); - XFree(h); -} - -void -xbell(void) -{ - if (!(IS_SET(MODE_FOCUSED))) - xseturgency(1); - if (bellvolume) - XkbBell(xw.dpy, xw.win, bellvolume, (Atom)NULL); -} - -void -focus(XEvent *ev) -{ - XFocusChangeEvent *e = &ev->xfocus; - - if (e->mode == NotifyGrab) - return; - - if (ev->type == FocusIn) { - if (xw.ime.xic) - XSetICFocus(xw.ime.xic); - win.mode |= MODE_FOCUSED; - xseturgency(0); - if (IS_SET(MODE_FOCUS)) - ttywrite("\033[I", 3, 0); - } else { - if (xw.ime.xic) - XUnsetICFocus(xw.ime.xic); - win.mode &= ~MODE_FOCUSED; - if (IS_SET(MODE_FOCUS)) - ttywrite("\033[O", 3, 0); - } -} - -int -match(uint mask, uint state) -{ - return mask == XK_ANY_MOD || mask == (state & ~ignoremod); -} - -char* -kmap(KeySym k, uint state) -{ - Key *kp; - int i; - - /* Check for mapped keys out of X11 function keys. */ - for (i = 0; i < LEN(mappedkeys); i++) { - if (mappedkeys[i] == k) - break; - } - if (i == LEN(mappedkeys)) { - if ((k & 0xFFFF) < 0xFD00) - return NULL; - } - - for (kp = key; kp < key + LEN(key); kp++) { - if (kp->k != k) - continue; - - if (!match(kp->mask, state)) - continue; - - if (IS_SET(MODE_APPKEYPAD) ? kp->appkey < 0 : kp->appkey > 0) - continue; - if (IS_SET(MODE_NUMLOCK) && kp->appkey == 2) - continue; - - if (IS_SET(MODE_APPCURSOR) ? kp->appcursor < 0 : kp->appcursor > 0) - continue; - - return kp->s; - } - - return NULL; -} - -void -kpress(XEvent *ev) -{ - XKeyEvent *e = &ev->xkey; - KeySym ksym; - char buf[64], *customkey; - int len; - Rune c; - Status status; - Shortcut *bp; - - if (IS_SET(MODE_KBDLOCK)) - return; - - if (xw.ime.xic) - len = XmbLookupString(xw.ime.xic, e, buf, sizeof buf, &ksym, &status); - else - len = XLookupString(e, buf, sizeof buf, &ksym, NULL); - /* 1. shortcuts */ - for (bp = shortcuts; bp < shortcuts + LEN(shortcuts); bp++) { - if (ksym == bp->keysym && match(bp->mod, e->state)) { - bp->func(&(bp->arg)); - return; - } - } - - /* 2. custom keys from config.h */ - if ((customkey = kmap(ksym, e->state))) { - ttywrite(customkey, strlen(customkey), 1); - return; - } - - /* 3. composed string from input method */ - if (len == 0) - return; - if (len == 1 && e->state & Mod1Mask) { - if (IS_SET(MODE_8BIT)) { - if (*buf < 0177) { - c = *buf | 0x80; - len = utf8encode(c, buf); - } - } else { - buf[1] = buf[0]; - buf[0] = '\033'; - len = 2; - } - } - ttywrite(buf, len, 1); -} - -void -cmessage(XEvent *e) -{ - /* - * See xembed specs - * http://standards.freedesktop.org/xembed-spec/xembed-spec-latest.html - */ - if (e->xclient.message_type == xw.xembed && e->xclient.format == 32) { - if (e->xclient.data.l[1] == XEMBED_FOCUS_IN) { - win.mode |= MODE_FOCUSED; - xseturgency(0); - } else if (e->xclient.data.l[1] == XEMBED_FOCUS_OUT) { - win.mode &= ~MODE_FOCUSED; - } - } else if (e->xclient.data.l[0] == xw.wmdeletewin) { - ttyhangup(); - exit(0); - } -} - -void -resize(XEvent *e) -{ - if (e->xconfigure.width == win.w && e->xconfigure.height == win.h) - return; - - cresize(e->xconfigure.width, e->xconfigure.height); -} - -void -run(void) -{ - XEvent ev; - int w = win.w, h = win.h; - fd_set rfd; - int xfd = XConnectionNumber(xw.dpy), ttyfd, xev, drawing; - struct timespec seltv, *tv, now, lastblink, trigger; - double timeout; - - /* Waiting for window mapping */ - do { - XNextEvent(xw.dpy, &ev); - /* - * This XFilterEvent call is required because of XOpenIM. It - * does filter out the key event and some client message for - * the input method too. - */ - if (XFilterEvent(&ev, None)) - continue; - if (ev.type == ConfigureNotify) { - w = ev.xconfigure.width; - h = ev.xconfigure.height; - } - } while (ev.type != MapNotify); - - ttyfd = ttynew(opt_line, shell, opt_io, opt_cmd); - cresize(w, h); - - for (timeout = -1, drawing = 0, lastblink = (struct timespec){0};;) { - FD_ZERO(&rfd); - FD_SET(ttyfd, &rfd); - FD_SET(xfd, &rfd); - - if (XPending(xw.dpy)) - timeout = 0; /* existing events might not set xfd */ - - seltv.tv_sec = timeout / 1E3; - seltv.tv_nsec = 1E6 * (timeout - 1E3 * seltv.tv_sec); - tv = timeout >= 0 ? &seltv : NULL; - - if (pselect(MAX(xfd, ttyfd)+1, &rfd, NULL, NULL, tv, NULL) < 0) { - if (errno == EINTR) - continue; - die("select failed: %s\n", strerror(errno)); - } - clock_gettime(CLOCK_MONOTONIC, &now); - - if (FD_ISSET(ttyfd, &rfd)) - ttyread(); - - xev = 0; - while (XPending(xw.dpy)) { - xev = 1; - XNextEvent(xw.dpy, &ev); - if (XFilterEvent(&ev, None)) - continue; - if (handler[ev.type]) - (handler[ev.type])(&ev); - } - - /* - * To reduce flicker and tearing, when new content or event - * triggers drawing, we first wait a bit to ensure we got - * everything, and if nothing new arrives - we draw. - * We start with trying to wait minlatency ms. If more content - * arrives sooner, we retry with shorter and shorter periods, - * and eventually draw even without idle after maxlatency ms. - * Typically this results in low latency while interacting, - * maximum latency intervals during `cat huge.txt`, and perfect - * sync with periodic updates from animations/key-repeats/etc. - */ - if (FD_ISSET(ttyfd, &rfd) || xev) { - if (!drawing) { - trigger = now; - drawing = 1; - } - timeout = (maxlatency - TIMEDIFF(now, trigger)) \ - / maxlatency * minlatency; - if (timeout > 0) - continue; /* we have time, try to find idle */ - } - - /* idle detected or maxlatency exhausted -> draw */ - timeout = -1; - if (blinktimeout && tattrset(ATTR_BLINK)) { - timeout = blinktimeout - TIMEDIFF(now, lastblink); - if (timeout <= 0) { - if (-timeout > blinktimeout) /* start visible */ - win.mode |= MODE_BLINK; - win.mode ^= MODE_BLINK; - tsetdirtattr(ATTR_BLINK); - lastblink = now; - timeout = blinktimeout; - } - } - - draw(); - XFlush(xw.dpy); - drawing = 0; - } -} - -void -usage(void) -{ - die("usage: %s [-aiv] [-c class] [-f font] [-g geometry]" - " [-n name] [-o file]\n" - " [-T title] [-t title] [-w windowid]" - " [[-e] command [args ...]]\n" - " %s [-aiv] [-c class] [-f font] [-g geometry]" - " [-n name] [-o file]\n" - " [-T title] [-t title] [-w windowid] -l line" - " [stty_args ...]\n", argv0, argv0); -} - -int -main(int argc, char *argv[]) -{ - xw.l = xw.t = 0; - xw.isfixed = False; - xsetcursor(cursorshape); - - ARGBEGIN { - case 'a': - allowaltscreen = 0; - break; - case 'A': - opt_alpha = EARGF(usage()); - break; - case 'c': - opt_class = EARGF(usage()); - break; - case 'e': - if (argc > 0) - --argc, ++argv; - goto run; - case 'f': - opt_font = EARGF(usage()); - break; - case 'g': - xw.gm = XParseGeometry(EARGF(usage()), - &xw.l, &xw.t, &cols, &rows); - break; - case 'i': - xw.isfixed = 1; - break; - case 'o': - opt_io = EARGF(usage()); - break; - case 'l': - opt_line = EARGF(usage()); - break; - case 'n': - opt_name = EARGF(usage()); - break; - case 't': - case 'T': - opt_title = EARGF(usage()); - break; - case 'w': - opt_embed = EARGF(usage()); - break; - case 'v': - die("%s " VERSION "\n", argv0); - break; - default: - usage(); - } ARGEND; - -run: - if (argc > 0) /* eat all remaining arguments */ - opt_cmd = argv; - - if (!opt_title) - opt_title = (opt_line || !opt_cmd) ? "st" : opt_cmd[0]; - - setlocale(LC_CTYPE, ""); - XSetLocaleModifiers(""); - cols = MAX(cols, 1); - rows = MAX(rows, 1); - tnew(cols, rows); - xinit(cols, rows); - xsetenv(); - selinit(); - run(); - - return 0; -} diff --git a/utils/st-0.9/x.c.rej b/utils/st-0.9/x.c.rej deleted file mode 100644 index d90329c..0000000 --- a/utils/st-0.9/x.c.rej +++ /dev/null @@ -1,11 +0,0 @@ ---- x.c -+++ x.c -@@ -643,7 +643,7 @@ brelease(XEvent *e) - return; - } - -- if (e->xbutton.button == Button2) -+ if (e->xbutton.button == Button3) - selpaste(NULL); - else if (e->xbutton.button == Button1) - mousesel(e, 1); diff --git a/utils/wterm b/utils/wterm new file mode 160000 +Subproject dfb410329ae8baf425e99000c2032ce7fd3b219 |