From 5de5ece675aa79134a8d3b82252a440d345791e4 Mon Sep 17 00:00:00 2001 From: Alexis Jhon Gaspar Date: Mon, 8 Jul 2024 14:13:30 +0800 Subject: [PATCH] Huge codebase update --- README.md | 3 +- dmenu-flexipatch/README.md | 4 +- dmenu-flexipatch/config.mk | 2 +- dmenu-flexipatch/dmenu.c | 10 +- dmenu-flexipatch/drw.c | 22 +- dmenu-flexipatch/drw.h | 2 +- dwm-flexipatch/README.md | 24 +- dwm-flexipatch/config.def.h | 55 +- dwm-flexipatch/config.mk | 2 +- dwm-flexipatch/drw.c | 28 +- dwm-flexipatch/dwm.c | 174 ++- dwm-flexipatch/patch/alttab.c | 6 +- dwm-flexipatch/patch/alttab.h | 2 +- dwm-flexipatch/patch/bar_dockbutton.c | 3 +- dwm-flexipatch/patch/bar_powerline_tags.c | 5 + dwm-flexipatch/patch/bar_statusbutton.h | 1 + dwm-flexipatch/patch/bar_systray.c | 21 +- dwm-flexipatch/patch/bar_taglabels.c | 5 + dwm-flexipatch/patch/bar_tags.c | 5 + dwm-flexipatch/patch/bar_wintitleactions.c | 2 +- dwm-flexipatch/patch/focusmaster.c | 40 +- dwm-flexipatch/patch/include.c | 6 +- dwm-flexipatch/patch/include.h | 5 +- dwm-flexipatch/patch/layout_deck.c | 3 +- dwm-flexipatch/patch/layout_flextile-deluxe.c | 2 +- dwm-flexipatch/patch/placedir.c | 96 ++ dwm-flexipatch/patch/placedir.h | 1 + dwm-flexipatch/patch/renamed_scratchpads.c | 1 + dwm-flexipatch/patch/seamless_restart.c | 12 +- dwm-flexipatch/patch/shift.c | 6 +- dwm-flexipatch/patch/tapresize.c | 7 + dwm-flexipatch/patch/vanitygaps.c | 27 +- dwm-flexipatch/patch/xrdb.c | 5 + dwm-flexipatch/patches.def.h | 42 +- dwmblocks-async/.clang-format | 6 +- dwmblocks-async/.clang-tidy | 30 + dwmblocks-async/.clangd | 11 +- dwmblocks-async/.gitignore | 2 +- dwmblocks-async/Makefile | 36 +- dwmblocks-async/README.md | 29 +- dwmblocks-async/config.c | 17 - dwmblocks-async/config.h | 33 +- dwmblocks-async/inc/bar.h | 15 - dwmblocks-async/inc/block.h | 17 - dwmblocks-async/inc/util.h | 8 - dwmblocks-async/inc/x11.h | 5 - dwmblocks-async/include/block.h | 29 + dwmblocks-async/include/cli.h | 12 + dwmblocks-async/include/main.h | 16 + dwmblocks-async/include/signal-handler.h | 33 + dwmblocks-async/include/status.h | 31 + dwmblocks-async/include/timer.h | 21 + dwmblocks-async/include/util.h | 28 + dwmblocks-async/include/watcher.h | 28 + dwmblocks-async/include/x11.h | 13 + dwmblocks-async/src/bar.c | 62 - dwmblocks-async/src/block.c | 161 ++- dwmblocks-async/src/cli.c | 33 + dwmblocks-async/src/main.c | 305 ++-- dwmblocks-async/src/signal-handler.c | 124 ++ dwmblocks-async/src/status.c | 78 ++ dwmblocks-async/src/timer.c | 72 + dwmblocks-async/src/util.c | 60 +- dwmblocks-async/src/watcher.c | 69 + dwmblocks-async/src/x11.c | 51 +- nsxiv/.github/workflows/build.yml | 8 +- nsxiv/README.md | 4 +- nsxiv/autoreload.c | 4 +- nsxiv/config.def.h | 2 +- nsxiv/config.mk | 3 +- nsxiv/etc/nsxiv.1 | 4 +- nsxiv/etc/nsxiv.desktop | 15 +- nsxiv/etc/woodpecker/analysis.yml | 5 +- nsxiv/etc/woodpecker/build.yml | 5 +- nsxiv/etc/woodpecker/clang-tidy-checks | 4 +- nsxiv/etc/woodpecker/spell.yml | 9 +- nsxiv/image.c | 7 +- nsxiv/main.c | 53 +- nsxiv/nsxiv.h | 8 +- nsxiv/thumbs.c | 6 +- nsxiv/util.c | 17 +- nsxiv/window.c | 14 +- slstatus/components/battery.o | Bin 4568 -> 0 bytes slstatus/components/cpu.o | Bin 3096 -> 0 bytes slstatus/components/datetime.o | Bin 1896 -> 0 bytes slstatus/components/disk.o | Bin 2832 -> 0 bytes slstatus/components/entropy.o | Bin 1720 -> 0 bytes slstatus/components/hostname.o | Bin 1712 -> 0 bytes slstatus/components/ip.o | Bin 2416 -> 0 bytes slstatus/components/kernel_release.o | Bin 1744 -> 0 bytes slstatus/components/keyboard_indicators.o | Bin 2392 -> 0 bytes slstatus/components/keymap.o | Bin 3680 -> 0 bytes slstatus/components/load_avg.o | Bin 1792 -> 0 bytes slstatus/components/netspeeds.o | Bin 2544 -> 0 bytes slstatus/components/num_files.o | Bin 2080 -> 0 bytes slstatus/components/ram.o | Bin 2712 -> 0 bytes slstatus/components/run_command.o | Bin 2096 -> 0 bytes slstatus/components/separator.o | Bin 1272 -> 0 bytes slstatus/components/swap.o | Bin 3344 -> 0 bytes slstatus/components/temperature.o | Bin 1672 -> 0 bytes slstatus/components/uptime.o | Bin 1872 -> 0 bytes slstatus/components/user.o | Bin 2176 -> 0 bytes slstatus/components/volume.o | Bin 3440 -> 0 bytes slstatus/components/wifi.o | Bin 3904 -> 0 bytes st-flexipatch/.gitignore | 4 - st-flexipatch/Makefile | 10 +- st-flexipatch/README.md | 35 +- st-flexipatch/] | 763 ---------- st-flexipatch/config.def.h | 69 +- st-flexipatch/config.mk | 17 +- st-flexipatch/hb.c | 101 +- st-flexipatch/hb.h | 5 +- st-flexipatch/patch/externalpipe.c | 4 + st-flexipatch/patch/keyboardselect_reflow.txt | 29 + .../patch/keyboardselect_reflow_st.c | 769 +++++++++++ .../patch/keyboardselect_reflow_st.h | 6 + st-flexipatch/patch/keyboardselect_reflow_x.c | 16 + st-flexipatch/patch/keyboardselect_reflow_x.h | 3 + st-flexipatch/patch/keyboardselect_x.c | 4 +- st-flexipatch/patch/netwmicon.c | 40 + st-flexipatch/patch/netwmicon.h | 687 +-------- st-flexipatch/patch/netwmicon_ff.c | 46 + st-flexipatch/patch/netwmicon_icon.h | 686 +++++++++ st-flexipatch/patch/netwmicon_legacy.c | 7 + st-flexipatch/patch/normalMode.c | 284 ---- st-flexipatch/patch/normalMode.h | 8 - st-flexipatch/patch/openurlonclick.c | 119 +- st-flexipatch/patch/reflow.c | 924 +++++++++++++ st-flexipatch/patch/reflow.h | 44 + st-flexipatch/patch/sixel_st.c | 42 - st-flexipatch/patch/sixel_st.h | 2 - st-flexipatch/patch/sixel_x.c | 14 - st-flexipatch/patch/st_include.c | 14 +- st-flexipatch/patch/st_include.h | 14 +- st-flexipatch/patch/x_include.c | 14 +- st-flexipatch/patch/x_include.h | 13 +- st-flexipatch/patches.def.h | 77 +- st-flexipatch/sixel.c | 356 +++-- st-flexipatch/sixel.h | 11 +- st-flexipatch/sixel_hls.c | 2 +- st-flexipatch/st.c | 1229 +++++++++-------- st-flexipatch/st.h | 96 +- st-flexipatch/st.info | 4 + st-flexipatch/win.h | 9 +- st-flexipatch/x.c | 931 +++++++++---- tabbed-flexipatch/Makefile | 97 +- tabbed-flexipatch/README.md | 22 +- tabbed-flexipatch/config.def.h | 36 +- tabbed-flexipatch/config.mk | 36 - tabbed-flexipatch/patch/basename.c | 10 + tabbed-flexipatch/patch/basename.h | 1 + tabbed-flexipatch/patch/drag.c | 2 +- tabbed-flexipatch/patch/include.c | 5 +- tabbed-flexipatch/patch/include.h | 5 +- tabbed-flexipatch/patch/xresources.c | 31 +- tabbed-flexipatch/patch/xresources.h | 7 +- tabbed-flexipatch/patches.def.h | 25 +- tabbed-flexipatch/tabbed.c | 100 +- 158 files changed, 6407 insertions(+), 3710 deletions(-) create mode 100644 dwm-flexipatch/patch/placedir.c create mode 100644 dwm-flexipatch/patch/placedir.h create mode 100644 dwmblocks-async/.clang-tidy delete mode 100644 dwmblocks-async/config.c delete mode 100644 dwmblocks-async/inc/bar.h delete mode 100644 dwmblocks-async/inc/block.h delete mode 100644 dwmblocks-async/inc/util.h delete mode 100644 dwmblocks-async/inc/x11.h create mode 100644 dwmblocks-async/include/block.h create mode 100644 dwmblocks-async/include/cli.h create mode 100644 dwmblocks-async/include/main.h create mode 100644 dwmblocks-async/include/signal-handler.h create mode 100644 dwmblocks-async/include/status.h create mode 100644 dwmblocks-async/include/timer.h create mode 100644 dwmblocks-async/include/util.h create mode 100644 dwmblocks-async/include/watcher.h create mode 100644 dwmblocks-async/include/x11.h delete mode 100644 dwmblocks-async/src/bar.c create mode 100644 dwmblocks-async/src/cli.c create mode 100644 dwmblocks-async/src/signal-handler.c create mode 100644 dwmblocks-async/src/status.c create mode 100644 dwmblocks-async/src/timer.c create mode 100644 dwmblocks-async/src/watcher.c delete mode 100644 slstatus/components/battery.o delete mode 100644 slstatus/components/cpu.o delete mode 100644 slstatus/components/datetime.o delete mode 100644 slstatus/components/disk.o delete mode 100644 slstatus/components/entropy.o delete mode 100644 slstatus/components/hostname.o delete mode 100644 slstatus/components/ip.o delete mode 100644 slstatus/components/kernel_release.o delete mode 100644 slstatus/components/keyboard_indicators.o delete mode 100644 slstatus/components/keymap.o delete mode 100644 slstatus/components/load_avg.o delete mode 100644 slstatus/components/netspeeds.o delete mode 100644 slstatus/components/num_files.o delete mode 100644 slstatus/components/ram.o delete mode 100644 slstatus/components/run_command.o delete mode 100644 slstatus/components/separator.o delete mode 100644 slstatus/components/swap.o delete mode 100644 slstatus/components/temperature.o delete mode 100644 slstatus/components/uptime.o delete mode 100644 slstatus/components/user.o delete mode 100644 slstatus/components/volume.o delete mode 100644 slstatus/components/wifi.o delete mode 100644 st-flexipatch/.gitignore delete mode 100644 st-flexipatch/] create mode 100644 st-flexipatch/patch/keyboardselect_reflow.txt create mode 100644 st-flexipatch/patch/keyboardselect_reflow_st.c create mode 100644 st-flexipatch/patch/keyboardselect_reflow_st.h create mode 100644 st-flexipatch/patch/keyboardselect_reflow_x.c create mode 100644 st-flexipatch/patch/keyboardselect_reflow_x.h create mode 100644 st-flexipatch/patch/netwmicon.c create mode 100644 st-flexipatch/patch/netwmicon_ff.c create mode 100644 st-flexipatch/patch/netwmicon_icon.h create mode 100644 st-flexipatch/patch/netwmicon_legacy.c delete mode 100644 st-flexipatch/patch/normalMode.c delete mode 100644 st-flexipatch/patch/normalMode.h create mode 100644 st-flexipatch/patch/reflow.c create mode 100644 st-flexipatch/patch/reflow.h delete mode 100644 st-flexipatch/patch/sixel_st.c delete mode 100644 st-flexipatch/patch/sixel_st.h delete mode 100644 st-flexipatch/patch/sixel_x.c delete mode 100644 tabbed-flexipatch/config.mk create mode 100644 tabbed-flexipatch/patch/basename.c create mode 100644 tabbed-flexipatch/patch/basename.h diff --git a/README.md b/README.md index 82ffd37..b34573d 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Suckless Utilities version 6.4 +# Suckless Utilities version 6.5 ## About These are my builds of suckless software such as dwm and st, based on the work for flexipatch by bakkeby. This aims for much more streamlined configuration and patching than 6.3 (which becomes more complicated over time and whenever more patches are integrated). @@ -119,6 +119,7 @@ Linux/Unix users: - libexif(-devel or -dev) (for nsxiv) - jq (for handling eww notifications) - pamixer +- xcb-util(-devel or -dev) Termux users: - xorg diff --git a/dmenu-flexipatch/README.md b/dmenu-flexipatch/README.md index 9e1bff7..f3479d5 100644 --- a/dmenu-flexipatch/README.md +++ b/dmenu-flexipatch/README.md @@ -1,5 +1,5 @@ -Similar to [dwm-flexipatch](https://github.com/bakkeby/dwm-flexipatch) this dmenu 5.2 (8df553e, -2023-09-22) project has a different take on patching. It uses preprocessor directives to decide +Similar to [dwm-flexipatch](https://github.com/bakkeby/dwm-flexipatch) this dmenu 5.3 (7be720c, +2024-03-19) project has a different take on patching. It uses preprocessor directives to decide whether or not to include a patch during build time. Essentially this means that this build, for better or worse, contains both the patched _and_ the original code. The aim being that you can select which patches to include and the build will contain that code and nothing more. diff --git a/dmenu-flexipatch/config.mk b/dmenu-flexipatch/config.mk index 29b96ca..9d94f27 100644 --- a/dmenu-flexipatch/config.mk +++ b/dmenu-flexipatch/config.mk @@ -1,5 +1,5 @@ # dmenu version -VERSION = 5.2 +VERSION = 5.3 # paths PREFIX = /usr/local diff --git a/dmenu-flexipatch/dmenu.c b/dmenu-flexipatch/dmenu.c index 0bcafd1..490be3f 100644 --- a/dmenu-flexipatch/dmenu.c +++ b/dmenu-flexipatch/dmenu.c @@ -1645,7 +1645,11 @@ setup(void) #if CENTER_PATCH if (center) { + #if XYW_PATCH + mw = (dmw>0 ? dmw : MIN(MAX(max_textw() + promptw, min_width), info[i].width)); + #else mw = MIN(MAX(max_textw() + promptw, min_width), info[i].width); + #endif // XYW_PATCH x = info[i].x_org + ((info[i].width - mw) / 2); y = info[i].y_org + ((info[i].height - mh) / 2); } else { @@ -1677,7 +1681,11 @@ setup(void) parentwin); #if CENTER_PATCH if (center) { + #if XYW_PATCH + mw = (dmw>0 ? dmw : MIN(MAX(max_textw() + promptw, min_width), wa.width)); + #else mw = MIN(MAX(max_textw() + promptw, min_width), wa.width); + #endif // XYW_PATCH x = (wa.width - mw) / 2; y = (wa.height - mh) / 2; } else { @@ -2054,7 +2062,7 @@ main(int argc, char *argv[]) prompt = argv[++i]; else if (!strcmp(argv[i], "-fn")) /* font or font set */ #if PANGO_PATCH - strcpy(font, argv[++i]); + font = argv[++i]; #else fonts[0] = argv[++i]; #endif // PANGO_PATCH diff --git a/dmenu-flexipatch/drw.c b/dmenu-flexipatch/drw.c index 41857e5..b8eeb96 100644 --- a/dmenu-flexipatch/drw.c +++ b/dmenu-flexipatch/drw.c @@ -234,7 +234,7 @@ xfont_free(Fnt *font) #if PANGO_PATCH Fnt* -drw_font_create(Drw* drw, const char font[]) +drw_font_create(Drw* drw, const char *font) { Fnt *fnt = NULL; @@ -365,10 +365,10 @@ int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert, Bool markup) { char buf[1024]; - int ty; - unsigned int ew; + int i, ty, th; + unsigned int ew, eh; XftDraw *d = NULL; - size_t i, len; + size_t len; int render = x || y || w || h; if (!drw || (render && !drw->scheme) || !text || !drw->font) @@ -393,10 +393,14 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp len = strlen(text); if (len) { - drw_font_getexts(drw->font, text, len, &ew, NULL, markup); + drw_font_getexts(drw->font, text, len, &ew, &eh, markup); + th = eh; /* shorten text if necessary */ - for (len = MIN(len, sizeof(buf) - 1); len && ew > w; len--) - drw_font_getexts(drw->font, text, len, &ew, NULL, markup); + for (len = MIN(len, sizeof(buf) - 1); len && ew > w; len--) { + drw_font_getexts(drw->font, text, len, &ew, &eh, markup); + if (eh > th) + th = eh; + } if (len) { memcpy(buf, text, len); @@ -406,7 +410,7 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp ; /* NOP */ if (render) { - ty = y + (h - drw->font->h) / 2; + ty = y + (h - th) / 2; if (markup) pango_layout_set_markup(drw->font->layout, buf, len); else @@ -650,7 +654,7 @@ drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, if (w) *w = r.width / PANGO_SCALE; if (h) - *h = font->h; + *h = r.height / PANGO_SCALE; } #else void diff --git a/dmenu-flexipatch/drw.h b/dmenu-flexipatch/drw.h index af4af4d..be4f3aa 100644 --- a/dmenu-flexipatch/drw.h +++ b/dmenu-flexipatch/drw.h @@ -55,7 +55,7 @@ void drw_free(Drw *drw); /* Fnt abstraction */ #if PANGO_PATCH -Fnt *drw_font_create(Drw* drw, const char font[]); +Fnt *drw_font_create(Drw* drw, const char *font); void drw_font_free(Fnt* set); unsigned int drw_font_getwidth(Drw *drw, const char *text, Bool markup); unsigned int drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n); diff --git a/dwm-flexipatch/README.md b/dwm-flexipatch/README.md index 14e76bd..e7c6e61 100644 --- a/dwm-flexipatch/README.md +++ b/dwm-flexipatch/README.md @@ -1,4 +1,4 @@ -This dwm 6.4 (9f88553, 2023-09-22) side project has a different take on dwm patching. It uses preprocessor directives to decide whether or not to include a patch during build time. Essentially this means that this build, for better or worse, contains both the patched _and_ the original code. The aim being that you can select which patches to include and the build will contain that code and nothing more. Due to the complexity of some of the patches dwm-flexipatch has diverged from mainstream dwm by making some core patches non-optional for maintenance reasons. For the classic dwm-flexipatch build refer to branch [dwm-flexipatch-1.0](https://github.com/bakkeby/dwm-flexipatch/tree/dwm-flexipatch-1.0). +This dwm 6.5 (5687f46, 2024-06-08) side project has a different take on dwm patching. It uses preprocessor directives to decide whether or not to include a patch during build time. Essentially this means that this build, for better or worse, contains both the patched _and_ the original code. The aim being that you can select which patches to include and the build will contain that code and nothing more. Due to the complexity of some of the patches dwm-flexipatch has diverged from mainstream dwm by making some core patches non-optional for maintenance reasons. For the classic dwm-flexipatch build refer to branch [dwm-flexipatch-1.0](https://github.com/bakkeby/dwm-flexipatch/tree/dwm-flexipatch-1.0). For example to include the `alpha` patch then you would only need to flip this setting from 0 to 1 in [patches.h](https://github.com/bakkeby/dwm-flexipatch/blob/master/patches.def.h): ```c @@ -19,6 +19,14 @@ Browsing patches? There is a [map of patches](https://coggle.it/diagram/X9IiSSM6 ### Changelog: +2024-01-31 - Added the placedir patch + +2023-12-22 - Added the do-not-die-on-color-allocation-failure patch + +2023-12-01 - Added the sendmoncenter patch + +2023-11-12 - Added the focusmaster-return patch variant + 2023-06-27 - Added the focusfollowmouse and unmanaged patches 2023-06-25 - Added the toggletopbar patch @@ -355,6 +363,10 @@ Browsing patches? There is a [map of patches](https://coggle.it/diagram/X9IiSSM6 - i.e. if topbar is 0 then dmenu will appear at the bottom and if 1 then dmenu will appear at the top + - do-not-die-on-color-allocation-failure + - avoids dwm terminating (dying) on color allocation failures + - useful for the xrdb (xresources) and status2d patches + - [dragcfact](https://github.com/bakkeby/patches/wiki/dragcfact/) - lets you resize clients' size (i.e. modify cfact) by holding modkey + shift + right-click and dragging the mouse @@ -442,6 +454,10 @@ Browsing patches? There is a [map of patches](https://coggle.it/diagram/X9IiSSM6 - [focusmaster](https://dwm.suckless.org/patches/focusmaster/) - a simple patch that just puts focus back to the master client + - [focusmaster-return](https://dwm.suckless.org/patches/focusmaster/) + - a simple patch that just puts focus back to the master client + - additionally allows focus to be switched back to the previous client + - [focusonclick](https://dwm.suckless.org/patches/focusonclick/) - this patch makes you switch focus only by mouse click and not sloppy (focus follows mouse pointer) @@ -587,6 +603,9 @@ Browsing patches? There is a [map of patches](https://coggle.it/diagram/X9IiSSM6 - [pertag](https://dwm.suckless.org/patches/pertag/) - adds nmaster, mfact, layouts and more per tag rather than per monitor + - [placedir](https://github.com/bakkeby/patches/wiki/placedir) + - allows tiled windows to be moved in any direction (up, down, left, right) + - [placemouse](https://github.com/bakkeby/patches/wiki/placemouse) - lets the user change the position of a client in the stack using the mouse. @@ -644,6 +663,9 @@ Browsing patches? There is a [map of patches](https://coggle.it/diagram/X9IiSSM6 - [selfrestart](https://dwm.suckless.org/patches/selfrestart/) - restart dwm without the unnecessary dependency of an external script + - [sendmoncenter](https://dwm.suckless.org/patches/sendmoncenter/) + - floating windows being sent to another monitor will be centered + - [sendmon\_keepfocus](https://github.com/bakkeby/patches/wiki/sendmon_keepfocus/) - minor patch that allow clients to keep focus when being sent to another monitor diff --git a/dwm-flexipatch/config.def.h b/dwm-flexipatch/config.def.h index af6bb9a..8940a33 100644 --- a/dwm-flexipatch/config.def.h +++ b/dwm-flexipatch/config.def.h @@ -11,7 +11,7 @@ static const unsigned int borderpx = 1; /* border pixel of windows */ /* This allows the bar border size to be explicitly set separately from borderpx. * If left as 0 then it will default to the borderpx value of the monitor and will * automatically update with setborderpx. */ -static const unsigned int barborderpx = 0; /* border pixel of bar */ +static const unsigned int barborderpx = 1; /* border pixel of bar */ #endif // BAR_BORDER_PATCH static const unsigned int snap = 32; /* snap pixel */ #if SWALLOW_PATCH @@ -95,14 +95,20 @@ static const int vertpadbar = 0; /* vertical padding for statusba #endif // BAR_STATUSPADDING_PATCH #if BAR_STATUSBUTTON_PATCH static const char buttonbar[] = "󰕰 Start"; +#endif // BAR_STATUSBUTTON_PATCH +#if BAR_DOCKBUTTONS_PATCH static const char buttonbar2[] = " st"; static const char buttonbar3[] = "󰈹 Firefox"; static const char buttonbar4[] = "󰝚 mpd"; +#endif // BAR_DOCKBUTTONS_PATCH +#if BAR_POWERBUTTON_PATCH static const char buttonbar5[] = "󰗼 󰐥"; +#endif // BAR_POWERBUTTON_PATCH +#if BAR_WINCONTROLBUTTONS_PATCH static const char buttonbar6[] = "󰅖"; static const char buttonbar7[] = "󰖯"; static const char buttonbar8[] = "󰖰"; -#endif // BAR_STATUSBUTTON_PATCH +#endif // BAR_WINCONTROLBUTTONS_PATCH #if BAR_SYSTRAY_PATCH static const unsigned int systrayspacing = 2; /* systray spacing */ static const int showsystray = 1; /* 0 means no systray */ @@ -507,6 +513,17 @@ static const Rule rules[] = { RULE(.wintype = WTYPE "DOCK", .unmanaged = 1) RULE(.wintype = WTYPE "DIALOG", .isfloating = 1, .noswallow = 1) RULE(.class = "Xmessage", .isfloating = 1, .noswallow = 1) + RULE(.class = "pce-atarist", .isfloating = 1, .noswallow = 1) + RULE(.class = "pce-cpm80", .isfloating = 1, .noswallow = 1) + RULE(.class = "pce-dos", .isfloating = 1, .noswallow = 1) + RULE(.class = "pce-ibmpc", .isfloating = 1, .noswallow = 1) + RULE(.class = "pce-img", .isfloating = 1, .noswallow = 1) + RULE(.class = "pce-macplus", .isfloating = 1, .noswallow = 1) + RULE(.class = "pce-rc759", .isfloating = 1, .noswallow = 1) + RULE(.class = "pce-sim405", .isfloating = 1, .noswallow = 1) + RULE(.class = "pce-simarm", .isfloating = 1, .noswallow = 1) + RULE(.class = "pce-sims32", .isfloating = 1, .noswallow = 1) + RULE(.class = "pce-vic20", .isfloating = 1, .noswallow = 1) RULE(.wintype = WTYPE "UTILITY", .isfloating = 1, .noswallow = 1) RULE(.wintype = WTYPE "TOOLBAR", .isfloating = 1, .noswallow = 1) RULE(.wintype = WTYPE "SPLASH", .isfloating = 1, .noswallow = 1) @@ -570,6 +587,14 @@ static const BarRule barrules[] = { { -1, 1, BAR_ALIGN_LEFT, width_dcbutton2, draw_dcbutton2, click_dcbutton2, NULL, "dockbutton2" }, { -1, 1, BAR_ALIGN_LEFT, width_dcbutton3, draw_dcbutton3, click_dcbutton3, NULL, "dockbutton3" }, #endif // BAR_DOCKBUTTONS_PATCH + #if BAR_POWERBUTTON_PATCH + { -1, 0, BAR_ALIGN_RIGHT, width_powbutton, draw_powbutton, click_powbutton, NULL, "powerbutton" }, + #endif // BAR_POWERBUTTON_PATCH + #if BAR_WINCONTROLBUTTONS_PATCH + { -1, 1, BAR_ALIGN_RIGHT, width_winbutton, draw_winbutton, click_winbutton, NULL, "statusbutton6" }, + { -1, 1, BAR_ALIGN_RIGHT, width_winbutton2, draw_winbutton2, click_winbutton2, NULL, "statusbutton7" }, + { -1, 1, BAR_ALIGN_RIGHT, width_winbutton3, draw_winbutton3, click_winbutton3, NULL, "statusbutton8" }, + #endif // BAR_WINCONTROLBUTTONS_PATCH #if BAR_TAGGRID_PATCH { -1, 0, BAR_ALIGN_LEFT, width_taggrid, draw_taggrid, click_taggrid, NULL, "taggrid" }, #endif // BAR_TAGGRID_PATCH @@ -582,14 +607,6 @@ static const BarRule barrules[] = { #if BAR_TAGLABELS_PATCH { -1, 0, BAR_ALIGN_LEFT, width_taglabels, draw_taglabels, click_taglabels, hover_taglabels, "taglabels" }, #endif // BAR_TAGLABELS_PATCH - #if BAR_POWERBUTTON_PATCH - { -1, 0, BAR_ALIGN_RIGHT, width_powbutton, draw_powbutton, click_powbutton, NULL, "powerbutton" }, - #endif // BAR_POWERBUTTON_PATCH - #if BAR_WINCONTROLBUTTONS_PATCH - { -1, 1, BAR_ALIGN_RIGHT, width_winbutton, draw_winbutton, click_winbutton, NULL, "statusbutton6" }, - { -1, 1, BAR_ALIGN_RIGHT, width_winbutton2, draw_winbutton2, click_winbutton2, NULL, "statusbutton7" }, - { -1, 1, BAR_ALIGN_RIGHT, width_winbutton3, draw_winbutton3, click_winbutton3, NULL, "statusbutton8" }, - #endif // BAR_WINCONTROLBUTTONS_PATCH #if BAR_SYSTRAY_PATCH { 0, 0, BAR_ALIGN_RIGHT, width_systray, draw_systray, click_systray, NULL, "systray" }, #endif // BAR_SYSTRAY_PATCH @@ -997,9 +1014,9 @@ static const Key keys[] = { #if TAB_PATCH { MODKEY|ControlMask, XK_b, tabmode, {-1} }, #endif // TAB_PATCH - #if FOCUSMASTER_PATCH + #if FOCUSMASTER_PATCH || FOCUSMASTER_RETURN_PATCH { MODKEY|ControlMask, XK_space, focusmaster, {0} }, - #endif // FOCUSMASTER_PATCH + #endif // FOCUSMASTER_PATCH / FOCUSMASTER_RETURN_PATCH #if STACKER_PATCH STACKKEYS(MODKEY, focus) STACKKEYS(MODKEY|ShiftMask, push) @@ -1013,6 +1030,12 @@ static const Key keys[] = { { MODKEY, XK_Up, focusdir, {.i = 2 } }, // up { MODKEY, XK_Down, focusdir, {.i = 3 } }, // down #endif // FOCUSDIR_PATCH + #if PLACEDIR_PATCH + { MODKEY|ControlMask, XK_Left, placedir, {.i = 0 } }, // left + { MODKEY|ControlMask, XK_Right, placedir, {.i = 1 } }, // right + { MODKEY|ControlMask, XK_Up, placedir, {.i = 2 } }, // up + { MODKEY|ControlMask, XK_Down, placedir, {.i = 3 } }, // down + #endif // PLACEDIR_PATCH #if SWAPFOCUS_PATCH && PERTAG_PATCH { MODKEY, XK_s, swapfocus, {.i = -1 } }, #endif // SWAPFOCUS_PATCH @@ -1227,8 +1250,8 @@ static const Key keys[] = { { MODKEY, XK_Right, viewtoright, {0} }, // note keybinding conflict with focusdir { MODKEY|ShiftMask, XK_Left, tagtoleft, {0} }, // note keybinding conflict with shifttag { MODKEY|ShiftMask, XK_Right, tagtoright, {0} }, // note keybinding conflict with shifttag - { MODKEY|ControlMask, XK_Left, tagandviewtoleft, {0} }, - { MODKEY|ControlMask, XK_Right, tagandviewtoright, {0} }, + { MODKEY|ControlMask, XK_Left, tagandviewtoleft, {0} }, // note keybinding conflict with placedir + { MODKEY|ControlMask, XK_Right, tagandviewtoright, {0} }, // note keybinding conflict with placedir #endif // FOCUSADJACENTTAG_PATCH #if TAGALL_PATCH { MODKEY|ShiftMask, XK_F1, tagall, {.v = "F1"} }, @@ -1267,8 +1290,8 @@ static const Key keys[] = { #if BAR_TAGGRID_PATCH { MODKEY|ControlMask, XK_Up, switchtag, { .ui = SWITCHTAG_UP | SWITCHTAG_VIEW } }, { MODKEY|ControlMask, XK_Down, switchtag, { .ui = SWITCHTAG_DOWN | SWITCHTAG_VIEW } }, - { MODKEY|ControlMask, XK_Right, switchtag, { .ui = SWITCHTAG_RIGHT | SWITCHTAG_VIEW } }, - { MODKEY|ControlMask, XK_Left, switchtag, { .ui = SWITCHTAG_LEFT | SWITCHTAG_VIEW } }, + { MODKEY|ControlMask, XK_Right, switchtag, { .ui = SWITCHTAG_RIGHT | SWITCHTAG_VIEW } }, // note keybinding conflict with placedir + { MODKEY|ControlMask, XK_Left, switchtag, { .ui = SWITCHTAG_LEFT | SWITCHTAG_VIEW } }, // note keybinding conflict with placedir { MODKEY|Mod4Mask, XK_Up, switchtag, { .ui = SWITCHTAG_UP | SWITCHTAG_TAG | SWITCHTAG_VIEW } }, { MODKEY|Mod4Mask, XK_Down, switchtag, { .ui = SWITCHTAG_DOWN | SWITCHTAG_TAG | SWITCHTAG_VIEW } }, { MODKEY|Mod4Mask, XK_Right, switchtag, { .ui = SWITCHTAG_RIGHT | SWITCHTAG_TAG | SWITCHTAG_VIEW } }, diff --git a/dwm-flexipatch/config.mk b/dwm-flexipatch/config.mk index e712f43..1e6abd3 100644 --- a/dwm-flexipatch/config.mk +++ b/dwm-flexipatch/config.mk @@ -1,5 +1,5 @@ # dwm version -VERSION = 6.4 +VERSION = 6.5 # Customize below to fit your system diff --git a/dwm-flexipatch/drw.c b/dwm-flexipatch/drw.c index 2e74b20..cbd41ae 100644 --- a/dwm-flexipatch/drw.c +++ b/dwm-flexipatch/drw.c @@ -337,14 +337,22 @@ drw_clr_create( #if BAR_ALPHA_PATCH if (!XftColorAllocName(drw->dpy, drw->visual, drw->cmap, clrname, dest)) + #if DO_NOT_DIE_ON_COLOR_ALLOCATION_FAILURE_PATCH + fprintf(stderr, "warning, cannot allocate color '%s'", clrname); + #else die("error, cannot allocate color '%s'", clrname); + #endif // DO_NOT_DIE_ON_COLOR_ALLOCATION_FAILURE_PATCH dest->pixel = (dest->pixel & 0x00ffffffU) | (alpha << 24); #else if (!XftColorAllocName(drw->dpy, DefaultVisual(drw->dpy, drw->screen), DefaultColormap(drw->dpy, drw->screen), clrname, dest)) + #if DO_NOT_DIE_ON_COLOR_ALLOCATION_FAILURE_PATCH + fprintf(stderr, "warning, cannot allocate color '%s'", clrname); + #else die("error, cannot allocate color '%s'", clrname); + #endif // DO_NOT_DIE_ON_COLOR_ALLOCATION_FAILURE_PATCH #if NO_TRANSPARENT_BORDERS_PATCH dest->pixel |= 0xff << 24; @@ -428,10 +436,10 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp { #if BAR_PANGO_PATCH char buf[1024]; - int ty; - unsigned int ew; + int i, ty, th; + unsigned int ew, eh; XftDraw *d = NULL; - size_t i, len; + size_t len; int render = x || y || w || h; if (!drw || (render && !drw->scheme) || !text || !drw->fonts) @@ -456,10 +464,14 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp len = strlen(text); if (len) { - drw_font_getexts(drw->fonts, text, len, &ew, NULL, markup); + drw_font_getexts(drw->fonts, text, len, &ew, &eh, markup); + th = eh; /* shorten text if necessary */ - for (len = MIN(len, sizeof(buf) - 1); len && ew > w; len--) - drw_font_getexts(drw->fonts, text, len, &ew, NULL, markup); + for (len = MIN(len, sizeof(buf) - 1); len && ew > w; len--) { + drw_font_getexts(drw->fonts, text, len, &ew, &eh, markup); + if (eh > th) + th = eh; + } if (len) { memcpy(buf, text, len); @@ -469,7 +481,7 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp ; /* NOP */ if (render) { - ty = y + (h - drw->fonts->h) / 2; + ty = y + (h - th) / 2; if (markup) pango_layout_set_markup(drw->fonts->layout, buf, len); else @@ -701,7 +713,7 @@ drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, if (w) *w = r.width / PANGO_SCALE; if (h) - *h = font->h; + *h = r.height / PANGO_SCALE; } #else void diff --git a/dwm-flexipatch/dwm.c b/dwm-flexipatch/dwm.c index 0064924..5bb0b1c 100644 --- a/dwm-flexipatch/dwm.c +++ b/dwm-flexipatch/dwm.c @@ -495,6 +495,9 @@ struct Monitor { int gappiv; /* vertical gap between windows */ int gappoh; /* horizontal outer gaps */ int gappov; /* vertical outer gaps */ + #if PERMON_VANITYGAPS_PATCH + int enablegaps; /* whether gaps are enabled */ + #endif // PERMON_VANITYGAPS_PATCH #endif // VANITYGAPS_PATCH #if SETBORDERPX_PATCH int borderpx; @@ -517,6 +520,9 @@ struct Monitor { Client *clients; Client *sel; Client *stack; + #if FOCUSMASTER_RETURN_PATCH + Client *tagmarked[32]; + #endif // FOCUSMASTER_RETURN_PATCH Monitor *next; Bar *bar; const Layout *lt[2]; @@ -695,6 +701,9 @@ static void maprequest(XEvent *e); static void motionnotify(XEvent *e); static void movemouse(const Arg *arg); static Client *nexttiled(Client *c); +#if NOBORDER_PATCH +static int noborder(Client *c); +#endif // NOBORDER_PATCH #if !ZOOMSWAP_PATCH || TAGINTOSTACK_ALLMASTER_PATCH || TAGINTOSTACK_ONEMASTER_PATCH static void pop(Client *c); #endif // !ZOOMSWAP_PATCH / TAGINTOSTACK_ALLMASTER_PATCH / TAGINTOSTACK_ONEMASTER_PATCH @@ -972,6 +981,7 @@ applyrules(Client *c) if (r->switchtag) #endif // SWALLOW_PATCH { + unfocus(selmon->sel, 1, NULL); selmon = c->mon; if (r->switchtag == 2 || r->switchtag == 4) newtagset = c->mon->tagset[c->mon->seltags] ^ c->tags; @@ -1115,6 +1125,11 @@ arrange(Monitor *m) void arrangemon(Monitor *m) { + #if BAR_PADDING_SMART_PATCH + updatebarpos(selmon); + for (Bar *bar = selmon->bar; bar; bar = bar->next) + XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw, bar->bh); + #endif // BAR_PADDING_SMART_PATCH #if TAB_PATCH updatebarpos(m); XMoveResizeWindow(dpy, m->tabwin, m->wx, m->ty, m->ww, th); @@ -1468,6 +1483,15 @@ configure(Client *c) ce.width = c->w; ce.height = c->h; ce.border_width = c->bw; + + #if NOBORDER_PATCH + if (noborder(c)) { + ce.width += c->bw * 2; + ce.height += c->bw * 2; + ce.border_width = 0; + } + #endif // NOBORDER_PATCH + ce.above = None; ce.override_redirect = False; XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&ce); @@ -1779,6 +1803,10 @@ createmon(void) } #endif // PERTAG_PATCH + #if PERMON_VANITYGAPS_PATCH + m->enablegaps = 1; + #endif // PERMON_VANITYGAPS_PATCH + #if SEAMLESS_RESTART_PATCH restoremonitorstate(m); #endif // SEAMLESS_RESTART_PATCH @@ -1831,6 +1859,11 @@ detach(Client *c) #if SEAMLESS_RESTART_PATCH c->idx = 0; #endif // SEAMLESS_RESTART_PATCH + #if FOCUSMASTER_RETURN_PATCH + for (int i = 1; i < NUMTAGS; i++) + if (c == c->mon->tagmarked[i]) + c->mon->tagmarked[i] = NULL; + #endif // FOCUSMASTER_RETURN_PATCH for (tc = &c->mon->clients; *tc && *tc != c; tc = &(*tc)->next); *tc = c->next; @@ -1871,7 +1904,7 @@ void drawbar(Monitor *m) { Bar *bar; - + #if !BAR_FLEXWINTITLE_PATCH if (m->showbar) #endif // BAR_FLEXWINTITLE_PATCH @@ -2059,6 +2092,10 @@ focus(Client *c) if (!c || !ISVISIBLE(c)) c = getpointerclient(); #endif // FOCUSFOLLOWMOUSE_PATCH + #if STICKY_PATCH + if (!c || !ISVISIBLE(c)) + for (c = selmon->stack; c && (!ISVISIBLE(c) || c->issticky); c = c->snext); + #endif // STICKY_PATCH if (!c || !ISVISIBLE(c)) for (c = selmon->stack; c && !ISVISIBLE(c); c = c->snext); if (selmon->sel && selmon->sel != c) @@ -2493,8 +2530,10 @@ manage(Window w, XWindowAttributes *wa) #endif // CENTER_TRANSIENT_WINDOWS_PATCH | CENTER_TRANSIENT_WINDOWS_BY_PARENT_PATCH | CENTER_PATCH } else { #if SEAMLESS_RESTART_PATCH - if (!settings_restored) + if (!settings_restored || c->mon == NULL) { c->mon = selmon; + settings_restored = 0; + } #else c->mon = selmon; #endif // SEAMLESS_RESTART_PATCH @@ -2851,10 +2890,63 @@ nexttiled(Client *c) return c; } +#if NOBORDER_PATCH +int +noborder(Client *c) +{ + int monocle_layout = 0; + + #if MONOCLE_LAYOUT + if (&monocle == c->mon->lt[c->mon->sellt]->arrange) + monocle_layout = 1; + #endif // MONOCLE_LAYOUT + + #if DECK_LAYOUT + if (&deck == c->mon->lt[c->mon->sellt]->arrange && c->mon->nmaster == 0) + monocle_layout = 1; + #endif // DECK_LAYOUT + + #if FLEXTILE_DELUXE_LAYOUT + if (&flextile == c->mon->lt[c->mon->sellt]->arrange && ( + (c->mon->ltaxis[LAYOUT] == NO_SPLIT && c->mon->ltaxis[MASTER] == MONOCLE) || + (c->mon->ltaxis[STACK] == MONOCLE && c->mon->nmaster == 0) + )) { + monocle_layout = 1; + } + #endif //FLEXTILE_DELUXE_LAYOUT + + if (!monocle_layout && (nexttiled(c->mon->clients) != c || nexttiled(c->next))) + return 0; + + if (c->isfloating) + return 0; + + if (!c->mon->lt[c->mon->sellt]->arrange) + return 0; + + #if FAKEFULLSCREEN_CLIENT_PATCH && !FAKEFULLSCREEN_PATCH + if (c->fakefullscreen != 1 && c->isfullscreen) + return 0; + #elif !FAKEFULLSCREEN_PATCH + if (c->isfullscreen) + return 0; + #endif // FAKEFULLSCREEN_CLIENT_PATCH + + return 1; +} +#endif // NOBORDER_PATCH + #if !ZOOMSWAP_PATCH || TAGINTOSTACK_ALLMASTER_PATCH || TAGINTOSTACK_ONEMASTER_PATCH void pop(Client *c) { + #if FOCUSMASTER_RETURN_PATCH + int i; + for (i = 0; !(selmon->tagset[selmon->seltags] & 1 << i); i++); + i++; + + c->mon->tagmarked[i] = nexttiled(c->mon->clients); + #endif // FOCUSMASTER_RETURN_PATCH detach(c); attach(c); focus(c); @@ -2998,31 +3090,9 @@ resizeclient(Client *c, int x, int y, int w, int h) drawroundedcorners(c); #endif // ROUNDED_CORNERS_PATCH #if NOBORDER_PATCH - if (((nexttiled(c->mon->clients) == c && !nexttiled(c->next)) - #if MONOCLE_LAYOUT - || &monocle == c->mon->lt[c->mon->sellt]->arrange - #endif // MONOCLE_LAYOUT - #if DECK_LAYOUT - || (&deck == c->mon->lt[c->mon->sellt]->arrange && - c->mon->nmaster == 0) - #endif // DECK_LAYOUT - #if FLEXTILE_DELUXE_LAYOUT - || (&flextile == c->mon->lt[c->mon->sellt]->arrange && ( - (c->mon->ltaxis[LAYOUT] == NO_SPLIT && - c->mon->ltaxis[MASTER] == MONOCLE) || - (c->mon->ltaxis[STACK] == MONOCLE && - c->mon->nmaster == 0))) - #endif //FLEXTILE_DELUXE_LAYOUT - ) - #if FAKEFULLSCREEN_CLIENT_PATCH && !FAKEFULLSCREEN_PATCH - && (c->fakefullscreen == 1 || !c->isfullscreen) - #else - && !c->isfullscreen - #endif // FAKEFULLSCREEN_CLIENT_PATCH - && !c->isfloating - && c->mon->lt[c->mon->sellt]->arrange) { - c->w = wc.width += c->bw * 2; - c->h = wc.height += c->bw * 2; + if (noborder(c)) { + wc.width += c->bw * 2; + wc.height += c->bw * 2; wc.border_width = 0; } #endif // NOBORDER_PATCH @@ -3377,6 +3447,14 @@ sendmon(Client *c, Monitor *m) #else c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */ #endif // EMPTYVIEW_PATCH + #if SENDMON_CENTER_PATCH + c->x = m->mx + (m->mw - WIDTH(c)) / 2; + c->y = m->my + (m->mh - HEIGHT(c)) / 2; + #if SAVEFLOATS_PATCH + c->sfx = m->mx + (m->mw - c->sfw - 2 * c->bw) / 2; + c->sfy = m->my + (m->mh - c->sfh - 2 * c->bw) / 2; + #endif // SAVEFLOATS_PATCH + #endif // SENDMON_CENTER_PATCH #if ATTACHABOVE_PATCH || ATTACHASIDE_PATCH || ATTACHBELOW_PATCH || ATTACHBOTTOM_PATCH attachx(c); #else @@ -4219,10 +4297,21 @@ togglefloating(const Arg *arg) #endif // !FAKEFULLSCREEN_PATCH c->isfloating = !c->isfloating || c->isfixed; #if !BAR_FLEXWINTITLE_PATCH + #if RENAMED_SCRATCHPADS_PATCH + if (c->scratchkey != 0 && c->isfloating) + XSetWindowBorder(dpy, c->win, scheme[SchemeScratchSel][ColFloat].pixel); + else if (c->scratchkey != 0) + XSetWindowBorder(dpy, c->win, scheme[SchemeScratchSel][ColBorder].pixel); + else if (c->isfloating) + XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColFloat].pixel); + else + XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColBorder].pixel); + #else if (c->isfloating) XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColFloat].pixel); else XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColBorder].pixel); + #endif // RENAMED_SCRATCHPADS_PATCH #endif // BAR_FLEXWINTITLE_PATCH if (c->isfloating) { #if SAVEFLOATS_PATCH || EXRESIZE_PATCH @@ -4637,16 +4726,36 @@ updatebarpos(Monitor *m) #if BAR_PADDING_VANITYGAPS_PATCH && VANITYGAPS_PATCH #if PERTAG_VANITYGAPS_PATCH && PERTAG_PATCH if (!selmon || selmon->pertag->enablegaps[selmon->pertag->curtag]) + #elif PERMON_VANITYGAPS_PATCH + if (!selmon || selmon->enablegaps) #else if (enablegaps) #endif // PERTAG_VANITYGAPS_PATCH { + #if BAR_PADDING_SMART_PATCH + unsigned int n; Client *c; + for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); + if (n > 1) { + y_pad = gappoh; + x_pad = gappov; + } + #else y_pad = gappoh; x_pad = gappov; + #endif // BAR_PADDING_SMART_PATCH } #elif BAR_PADDING_PATCH + #if BAR_PADDING_SMART_PATCH + unsigned int n; Client *c; + for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); + if (n > 1) { + y_pad = vertpad; + x_pad = sidepad; + } + #else y_pad = vertpad; x_pad = sidepad; + #endif // BAR_PADDING_SMART_PATCH #endif // BAR_PADDING_PATCH | BAR_PADDING_VANITYGAPS_PATCH #if INSETS_PATCH @@ -4701,7 +4810,7 @@ updatebarpos(Monitor *m) } void -updateclientlist() +updateclientlist(void) { Client *c; Monitor *m; @@ -5095,6 +5204,9 @@ void zoom(const Arg *arg) { Client *c = selmon->sel; + #if FOCUSMASTER_RETURN_PATCH && ZOOMSWAP_PATCH + int i; + #endif // FOCUSMASTER_RETURN_PATCH if (arg && arg->v) c = (Client*)arg->v; if (!c) @@ -5148,6 +5260,12 @@ zoom(const Arg *arg) cold = nexttiled(c->mon->clients); if (c != cold && !at) at = findbefore(c); + #if FOCUSMASTER_RETURN_PATCH + for (i = 0; !(selmon->tagset[selmon->seltags] & 1 << i); i++); + i++; + + c->mon->tagmarked[i] = cold; + #endif // FOCUSMASTER_RETURN_PATCH detach(c); attach(c); /* swap windows instead of pushing the previous one down */ diff --git a/dwm-flexipatch/patch/alttab.c b/dwm-flexipatch/patch/alttab.c index f6775d8..59e6dd9 100644 --- a/dwm-flexipatch/patch/alttab.c +++ b/dwm-flexipatch/patch/alttab.c @@ -21,7 +21,7 @@ alttab() /* redraw tab */ XRaiseWindow(dpy, alttabwin); - drawtab(ntabs, 0, m); + drawalttab(ntabs, 0, m); } void @@ -66,7 +66,7 @@ alttabend() } void -drawtab(int nwins, int first, Monitor *m) +drawalttab(int nwins, int first, Monitor *m) { Client *c; int i, h; @@ -178,7 +178,7 @@ alttabstart(const Arg *arg) i++; } - drawtab(ntabs, 1, m); + drawalttab(ntabs, 1, m); struct timespec ts = { .tv_sec = 0, .tv_nsec = 1000000 }; diff --git a/dwm-flexipatch/patch/alttab.h b/dwm-flexipatch/patch/alttab.h index 2951d04..07fed28 100644 --- a/dwm-flexipatch/patch/alttab.h +++ b/dwm-flexipatch/patch/alttab.h @@ -1,5 +1,5 @@ #include -static void drawtab(int nwins, int first, Monitor *m); +static void drawalttab(int nwins, int first, Monitor *m); static void alttabstart(const Arg *arg); static void alttabend(); diff --git a/dwm-flexipatch/patch/bar_dockbutton.c b/dwm-flexipatch/patch/bar_dockbutton.c index b083013..eee9443 100644 --- a/dwm-flexipatch/patch/bar_dockbutton.c +++ b/dwm-flexipatch/patch/bar_dockbutton.c @@ -15,8 +15,7 @@ click_dcbutton(Bar *bar, Arg *arg, BarArg *a) { return ClkButton2; } -int -width_dcbutton2(Bar *bar, BarArg *a) +int width_dcbutton2(Bar *bar, BarArg *a) { return TEXTW(buttonbar3); } diff --git a/dwm-flexipatch/patch/bar_powerline_tags.c b/dwm-flexipatch/patch/bar_powerline_tags.c index 0987c9b..86fe0a1 100644 --- a/dwm-flexipatch/patch/bar_powerline_tags.c +++ b/dwm-flexipatch/patch/bar_powerline_tags.c @@ -102,6 +102,11 @@ click_pwrl_tags(Bar *bar, Arg *arg, BarArg *a) if (i < NUMTAGS) { arg->ui = 1 << i; } + #if BAR_TAGPREVIEW_PATCH + if (selmon->previewshow != 0) { + hidetagpreview(selmon); + } + #endif // BAR_TAGPREVIEW_PATCH return ClkTagBar; } diff --git a/dwm-flexipatch/patch/bar_statusbutton.h b/dwm-flexipatch/patch/bar_statusbutton.h index 5d61ba4..ed5beb5 100644 --- a/dwm-flexipatch/patch/bar_statusbutton.h +++ b/dwm-flexipatch/patch/bar_statusbutton.h @@ -1,3 +1,4 @@ static int width_stbutton(Bar *bar, BarArg *a); static int draw_stbutton(Bar *bar, BarArg *a); static int click_stbutton(Bar *bar, Arg *arg, BarArg *a); + diff --git a/dwm-flexipatch/patch/bar_systray.c b/dwm-flexipatch/patch/bar_systray.c index f80aff5..5d18e7c 100644 --- a/dwm-flexipatch/patch/bar_systray.c +++ b/dwm-flexipatch/patch/bar_systray.c @@ -13,14 +13,7 @@ width_systray(Bar *bar, BarArg *a) if (!w) XMoveWindow(dpy, systray->win, -systray->h, bar->by); } - - if (w) { - w += lrpad / 2 - systrayspacing; - #if !BAR_STATUS_PATCH - w += lrpad / 2; - #endif // BAR_STATUS_PATCH - } - return w; + return w ? w + lrpad - systrayspacing : 0; } int @@ -101,11 +94,13 @@ draw_systray(Bar *bar, BarArg *a) i->mon = bar->mon; } - unsigned int xpos = bar->bx + a->x + lrpad / 2; - #if BAR_STATUS_PATCH - xpos -= lrpad / 2; - #endif // BAR_STATUS_PATCH - XMoveResizeWindow(dpy, systray->win, xpos, (w ? bar->by + a->y + (a->h - systray->h) / 2: -bar->by - a->y), MAX(w, 1), systray->h); + #if !BAR_ALPHA_PATCH + wa.background_pixel = scheme[SchemeNorm][ColBg].pixel; + XChangeWindowAttributes(dpy, systray->win, CWBackPixel, &wa); + XClearWindow(dpy, systray->win); + #endif // BAR_ALPHA_PATCH + + XMoveResizeWindow(dpy, systray->win, bar->bx + a->x + lrpad / 2, (w ? bar->by + a->y + (a->h - systray->h) / 2: -systray->h), MAX(w, 1), systray->h); return w; } diff --git a/dwm-flexipatch/patch/bar_taglabels.c b/dwm-flexipatch/patch/bar_taglabels.c index cf1b762..48dce77 100644 --- a/dwm-flexipatch/patch/bar_taglabels.c +++ b/dwm-flexipatch/patch/bar_taglabels.c @@ -87,6 +87,11 @@ click_taglabels(Bar *bar, Arg *arg, BarArg *a) if (i < NUMTAGS) { arg->ui = 1 << i; } + #if BAR_TAGPREVIEW_PATCH + if (selmon->previewshow != 0) { + hidetagpreview(selmon); + } + #endif // BAR_TAGPREVIEW_PATCH return ClkTagBar; } diff --git a/dwm-flexipatch/patch/bar_tags.c b/dwm-flexipatch/patch/bar_tags.c index 6a420d0..4715e95 100644 --- a/dwm-flexipatch/patch/bar_tags.c +++ b/dwm-flexipatch/patch/bar_tags.c @@ -88,6 +88,11 @@ click_tags(Bar *bar, Arg *arg, BarArg *a) if (i < NUMTAGS) { arg->ui = 1 << i; } + #if BAR_TAGPREVIEW_PATCH + if (selmon->previewshow != 0) { + hidetagpreview(selmon); + } + #endif // BAR_TAGPREVIEW_PATCH return ClkTagBar; } diff --git a/dwm-flexipatch/patch/bar_wintitleactions.c b/dwm-flexipatch/patch/bar_wintitleactions.c index 61a5d21..36a06fb 100644 --- a/dwm-flexipatch/patch/bar_wintitleactions.c +++ b/dwm-flexipatch/patch/bar_wintitleactions.c @@ -51,7 +51,7 @@ togglewin(const Arg *arg) Client *c = (Client*)arg->v; if (!c) return; - if (c == selmon->sel) + if (!HIDDEN(c) && c == selmon->sel) hide(c); else { if (HIDDEN(c)) diff --git a/dwm-flexipatch/patch/focusmaster.c b/dwm-flexipatch/patch/focusmaster.c index 13a47e5..ae0771c 100644 --- a/dwm-flexipatch/patch/focusmaster.c +++ b/dwm-flexipatch/patch/focusmaster.c @@ -1,14 +1,42 @@ void focusmaster(const Arg *arg) { - Client *c; + Client *master; + Monitor *m = selmon; + #if FOCUSMASTER_RETURN_PATCH + int i; + #endif // FOCUSMASTER_RETURN_PATCH - if (selmon->nmaster < 1) + if (m->nmaster < 1) + return; + #if !FAKEFULLSCREEN_PATCH + #if FAKEFULLSCREEN_CLIENT_PATCH + if (!m->sel || (m->sel->isfullscreen && m->sel->fakefullscreen != 1 && lockfullscreen)) + return; + #else + if (!m->sel || (m->sel->isfullscreen && lockfullscreen)) + return; + #endif // FAKEFULLSCREEN_CLIENT_PATCH + #endif // FAKEFULLSCREEN_PATCH + + master = nexttiled(m->clients); + + if (!master) return; - c = nexttiled(selmon->clients); + #if FOCUSMASTER_RETURN_PATCH + for (i = 0; !(m->tagset[m->seltags] & 1 << i); i++); + i++; - if (c) - focus(c); + if (m->sel == master) { + if (m->tagmarked[i] && ISVISIBLE(m->tagmarked[i])) + focus(m->tagmarked[i]); + } else { + m->tagmarked[i] = m->sel; + focus(master); + } + #else + focus(master); + #endif // FOCUSMASTER_RETURN_PATCH + restack(m); } - diff --git a/dwm-flexipatch/patch/include.c b/dwm-flexipatch/patch/include.c index 0d19a04..5b54f36 100644 --- a/dwm-flexipatch/patch/include.c +++ b/dwm-flexipatch/patch/include.c @@ -154,7 +154,7 @@ #if FOCUSFOLLOWMOUSE_PATCH #include "focusfollowmouse.c" #endif -#if FOCUSMASTER_PATCH +#if FOCUSMASTER_PATCH || FOCUSMASTER_RETURN_PATCH #include "focusmaster.c" #endif #if FOCUSURGENT_PATCH @@ -208,6 +208,9 @@ #if PERTAG_PATCH #include "pertag.c" #endif +#if PLACEDIR_PATCH +#include "placedir.c" +#endif #if PLACEMOUSE_PATCH #include "placemouse.c" #endif @@ -404,3 +407,4 @@ #if BAR_WINCONTROLBUTTONS_PATCH #include "bar_wincontrolbutton.c" #endif + diff --git a/dwm-flexipatch/patch/include.h b/dwm-flexipatch/patch/include.h index 4135c26..34d7e0d 100644 --- a/dwm-flexipatch/patch/include.h +++ b/dwm-flexipatch/patch/include.h @@ -157,7 +157,7 @@ #if FOCUSFOLLOWMOUSE_PATCH #include "focusfollowmouse.h" #endif -#if FOCUSMASTER_PATCH +#if FOCUSMASTER_PATCH || FOCUSMASTER_RETURN_PATCH #include "focusmaster.h" #endif #if FOCUSURGENT_PATCH @@ -207,6 +207,9 @@ #if PERTAG_PATCH #include "pertag.h" #endif +#if PLACEDIR_PATCH +#include "placedir.h" +#endif #if PLACEMOUSE_PATCH #include "placemouse.h" #endif diff --git a/dwm-flexipatch/patch/layout_deck.c b/dwm-flexipatch/patch/layout_deck.c index 51307bf..1cabf0e 100644 --- a/dwm-flexipatch/patch/layout_deck.c +++ b/dwm-flexipatch/patch/layout_deck.c @@ -44,10 +44,9 @@ deck(Monitor *m) #endif // VANITYGAPS_PATCH getfacts(m, mh, sh, &mfacts, &sfacts, &mrest, &srest); - #if !MONOCLESYMBOL_PATCH + if (n - m->nmaster > 0) /* override layout symbol */ snprintf(m->ltsymbol, sizeof m->ltsymbol, "D %d", n - m->nmaster); - #endif // MONOCLESMYBOL_PATCH for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) if (i < m->nmaster) { diff --git a/dwm-flexipatch/patch/layout_flextile-deluxe.c b/dwm-flexipatch/patch/layout_flextile-deluxe.c index c7429f4..ec7cd7d 100644 --- a/dwm-flexipatch/patch/layout_flextile-deluxe.c +++ b/dwm-flexipatch/patch/layout_flextile-deluxe.c @@ -643,7 +643,7 @@ arrange_tatami(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, in if (j < ai + cats) { /* Arrange cats (all excess clients that can't be tiled as mats). Cats sleep on mats. */ - switch (cats) { + switch (cats) { case 1: // fill break; case 2: // up and down diff --git a/dwm-flexipatch/patch/placedir.c b/dwm-flexipatch/patch/placedir.c new file mode 100644 index 0000000..6fdfd63 --- /dev/null +++ b/dwm-flexipatch/patch/placedir.c @@ -0,0 +1,96 @@ +void +placedir(const Arg *arg) +{ + Client *s = selmon->sel, *f = NULL, *c, *next, *fprior, *sprior; + + if (!s || s->isfloating) + return; + + unsigned int score = -1; + unsigned int client_score; + int dist; + int dirweight = 20; + + next = s->next; + if (!next) + next = s->mon->clients; + for (c = next; c != s; c = next) { + + next = c->next; + if (!next) + next = s->mon->clients; + + if (!ISVISIBLE(c)) // || HIDDEN(c) + continue; + + switch (arg->i) { + case 0: // left + dist = s->x - c->x - c->w; + client_score = + dirweight * MIN(abs(dist), abs(dist + s->mon->ww)) + + abs(s->y - c->y); + break; + case 1: // right + dist = c->x - s->x - s->w; + client_score = + dirweight * MIN(abs(dist), abs(dist + s->mon->ww)) + + abs(c->y - s->y); + break; + case 2: // up + dist = s->y - c->y - c->h; + client_score = + dirweight * MIN(abs(dist), abs(dist + s->mon->wh)) + + abs(s->x - c->x); + break; + default: + case 3: // down + dist = c->y - s->y - s->h; + client_score = + dirweight * MIN(abs(dist), abs(dist + s->mon->wh)) + + abs(c->x - s->x); + break; + } + + if (((arg->i == 0 || arg->i == 2) && client_score <= score) || client_score < score) { + score = client_score; + f = c; + } + } + + if (f && f != s) { + for (fprior = f->mon->clients; fprior && fprior->next != f; fprior = fprior->next); + for (sprior = s->mon->clients; sprior && sprior->next != s; sprior = sprior->next); + + if (s == fprior) { + next = f->next; + if (sprior) + sprior->next = f; + else + f->mon->clients = f; + f->next = s; + s->next = next; + } else if (f == sprior) { + next = s->next; + if (fprior) + fprior->next = s; + else + s->mon->clients = s; + s->next = f; + f->next = next; + } else { // clients are not adjacent to each other + next = f->next; + f->next = s->next; + s->next = next; + if (fprior) + fprior->next = s; + else + s->mon->clients = s; + if (sprior) + sprior->next = f; + else + f->mon->clients = f; + } + + arrange(f->mon); + } +} diff --git a/dwm-flexipatch/patch/placedir.h b/dwm-flexipatch/patch/placedir.h new file mode 100644 index 0000000..a2c864a --- /dev/null +++ b/dwm-flexipatch/patch/placedir.h @@ -0,0 +1 @@ +static void placedir(const Arg *arg); diff --git a/dwm-flexipatch/patch/renamed_scratchpads.c b/dwm-flexipatch/patch/renamed_scratchpads.c index 9bf3f22..3bc9bb0 100644 --- a/dwm-flexipatch/patch/renamed_scratchpads.c +++ b/dwm-flexipatch/patch/renamed_scratchpads.c @@ -149,3 +149,4 @@ togglescratch(const Arg *arg) spawnscratch(arg); } } + diff --git a/dwm-flexipatch/patch/seamless_restart.c b/dwm-flexipatch/patch/seamless_restart.c index 2be269e..9c1d8f0 100644 --- a/dwm-flexipatch/patch/seamless_restart.c +++ b/dwm-flexipatch/patch/seamless_restart.c @@ -39,12 +39,12 @@ persistclientstate(Client *c) int restoreclientstate(Client *c) { - return getclienttags(c) - | getclientfields(c) - #if SAVEFLOATS_PATCH - | restorewindowfloatposition(c, c->mon ? c->mon : selmon) - #endif // SAVEFLOATS_PATCH - ; + int restored = getclientfields(c); + getclienttags(c); + #if SAVEFLOATS_PATCH + restorewindowfloatposition(c, c->mon ? c->mon : selmon); + #endif // SAVEFLOATS_PATCH + return restored; } void setmonitorfields(Monitor *m) diff --git a/dwm-flexipatch/patch/shift.c b/dwm-flexipatch/patch/shift.c index 355e645..66b4dce 100644 --- a/dwm-flexipatch/patch/shift.c +++ b/dwm-flexipatch/patch/shift.c @@ -6,7 +6,7 @@ shift(const Arg *arg, int clients) unsigned int tagmask = 0; #if SCRATCHPADS_PATCH && !RENAMED_SCRATCHPADS_PATCH - shifted.ui = selmon->tagset[selmon->seltags]; + shifted.ui = selmon->tagset[selmon->seltags] & ~SPTAGMASK; #else shifted.ui = selmon->tagset[selmon->seltags]; #endif // SCRATCHPADS_PATCH @@ -18,6 +18,10 @@ shift(const Arg *arg, int clients) for (c = selmon->clients; c && clients; c = c->next) { if (c == selmon->sel) continue; + #if STICKY_PATCH + if (c->issticky) + continue; + #endif // STICKY_PATCH #if SCRATCHPADS_PATCH && !RENAMED_SCRATCHPADS_PATCH if (!(c->tags & SPTAGMASK)) tagmask |= c->tags; diff --git a/dwm-flexipatch/patch/tapresize.c b/dwm-flexipatch/patch/tapresize.c index c236b5d..7b918cb 100644 --- a/dwm-flexipatch/patch/tapresize.c +++ b/dwm-flexipatch/patch/tapresize.c @@ -10,8 +10,15 @@ resizemousescroll(const Arg *arg) if (!(c = selmon->sel)) return; + #if !FAKEFULLSCREEN_PATCH + #if FAKEFULLSCREEN_CLIENT_PATCH + if (c->isfullscreen && c->fakefullscreen != 1) /* no support resizing fullscreen windows by mouse */ + return; + #else if (c->isfullscreen) /* no support resizing fullscreen windows by mouse */ return; + #endif // FAKEFULLSCREEN_CLIENT_PATCH + #endif // !FAKEFULLSCREEN_PATCH restack(selmon); if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, None, cursor[CurResize]->cursor, CurrentTime) != GrabSuccess) diff --git a/dwm-flexipatch/patch/vanitygaps.c b/dwm-flexipatch/patch/vanitygaps.c index 303d4df..bf51660 100644 --- a/dwm-flexipatch/patch/vanitygaps.c +++ b/dwm-flexipatch/patch/vanitygaps.c @@ -1,5 +1,5 @@ /* Settings */ -#if !PERTAG_VANITYGAPS_PATCH +#if !(PERTAG_VANITYGAPS_PATCH || PERMON_VANITYGAPS_PATCH) static int enablegaps = 1; #endif // PERTAG_VANITYGAPS_PATCH @@ -69,10 +69,12 @@ setgapsex(const Arg *arg) #if PERTAG_VANITYGAPS_PATCH && PERTAG_PATCH if (!selmon->pertag->enablegaps[selmon->pertag->curtag]) selmon->pertag->enablegaps[selmon->pertag->curtag] = 1; + #elif PERMON_VANITYGAPS_PATCH + selmon->enablegaps = 1; #else if (!enablegaps) enablegaps = 1; - #endif // PERTAG_VANITYGAPS_PATCH + #endif // PERTAG_VANITYGAPS_PATCH | PERMON_VANITYGAPS_PATCH setgaps(oh, ov, ih, iv); } @@ -83,24 +85,35 @@ togglegaps(const Arg *arg) { #if PERTAG_VANITYGAPS_PATCH && PERTAG_PATCH selmon->pertag->enablegaps[selmon->pertag->curtag] = !selmon->pertag->enablegaps[selmon->pertag->curtag]; + #elif PERMON_VANITYGAPS_PATCH + selmon->enablegaps = !selmon->enablegaps; #else enablegaps = !enablegaps; - #endif // PERTAG_VANITYGAPS_PATCH + #endif // PERTAG_VANITYGAPS_PATCH | PERMON_VANITYGAPS_PATCH #if BAR_PADDING_VANITYGAPS_PATCH + #if PERMON_VANITYGAPS_PATCH updatebarpos(selmon); for (Bar *bar = selmon->bar; bar; bar = bar->next) XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw, bar->bh); + #else + for (Monitor *m = mons; m; m = m->next) { + updatebarpos(m); + for (Bar *bar = m->bar; bar; bar = bar->next) + XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw, bar->bh); + } + #endif // PERMON_VANITYGAPS_PATCH #if BAR_SYSTRAY_PATCH drawbarwin(systray->bar); #endif // BAR_SYSTRAY_PATCH #endif // BAR_PADDING_VANITYGAPS_PATCH - #if PERTAG_VANITYGAPS_PATCH && PERTAG_PATCH + + #if (PERTAG_VANITYGAPS_PATCH && PERTAG_PATCH) || PERMON_VANITYGAPS_PATCH arrange(selmon); #else arrange(NULL); - #endif // PERTAG_VANITYGAPS_PATCH + #endif // PERTAG_VANITYGAPS_PATCH | PERMON_VANITYGAPS_PATCH } static void @@ -193,9 +206,11 @@ getgaps(Monitor *m, int *oh, int *ov, int *ih, int *iv, unsigned int *nc) unsigned int n, oe, ie; #if PERTAG_VANITYGAPS_PATCH && PERTAG_PATCH oe = ie = m->pertag->enablegaps[m->pertag->curtag]; + #elif PERMON_VANITYGAPS_PATCH + oe = ie = m->enablegaps; #else oe = ie = enablegaps; - #endif // PERTAG_VANITYGAPS_PATCH + #endif // PERTAG_VANITYGAPS_PATCH | PERMON_VANITYGAPS_PATCH Client *c; for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); diff --git a/dwm-flexipatch/patch/xrdb.c b/dwm-flexipatch/patch/xrdb.c index 0db3a6d..dd03735 100644 --- a/dwm-flexipatch/patch/xrdb.c +++ b/dwm-flexipatch/patch/xrdb.c @@ -132,6 +132,11 @@ xrdb(const Arg *arg) #endif // BAR_ALPHA_PATCH ColCount ); + #if BAR_SYSTRAY_PATCH && !BAR_ALPHA_PATCH + if (systray) { + XMoveWindow(dpy, systray->win, -32000, -32000); + } + #endif // BAR_SYSTRAY_PATCH arrange(NULL); focus(NULL); } diff --git a/dwm-flexipatch/patches.def.h b/dwm-flexipatch/patches.def.h index b5931b8..d727443 100644 --- a/dwm-flexipatch/patches.def.h +++ b/dwm-flexipatch/patches.def.h @@ -367,7 +367,13 @@ * toggled in unison when vanitygaps are toggled. Increasing or decreasing gaps during runtime * will not affect the bar padding. */ -#define BAR_PADDING_VANITYGAPS_PATCH 1 +#define BAR_PADDING_VANITYGAPS_PATCH 1 + +/* Smart bar padding patch that automatically adjusts the padding when there is + * only one client on the monitor. Works well with vanitygaps and barpadding + * patches. + */ +#define BAR_PADDING_SMART_PATCH 0 /* This patch adds simple markup for status messages using pango markup. * This depends on the pango library v1.44 or greater. @@ -572,6 +578,18 @@ */ #define DISTRIBUTETAGS_PATCH 0 +/* By default dwm will terminate on color allocation failure and the behaviour is intended to + * catch and inform the user of color configuration issues. + * + * Some patches like status2d and xresources / xrdb can change colours during runtime, which + * means that if a color can't be allocated at this time then the window manager will abruptly + * terminate. + * + * This patch will ignore color allocation failures and continue on as normal. The effect of + * this is that the existing color, that was supposed to be replaced, will remain as-is. + */ +#define DO_NOT_DIE_ON_COLOR_ALLOCATION_FAILURE_PATCH 1 + /* Similarly to the dragmfact patch this allows you to click and drag clients to change the * cfact to adjust the client's size in the stack. This patch depends on the cfacts patch. */ @@ -657,6 +675,12 @@ */ #define FOCUSMASTER_PATCH 0 +/* A variant of the focusmaster patch that additionally allows the focus to be returned to the + * previously focused client + * https://dwm.suckless.org/patches/focusmaster/ + */ +#define FOCUSMASTER_RETURN_PATCH 0 + /* Switch focus only by mouse click and not sloppy (focus follows mouse pointer). * https://dwm.suckless.org/patches/focusonclick/ */ @@ -885,11 +909,22 @@ */ #define PERTAG_VANITYGAPS_PATCH 0 +/* This patch allows configuring vanity gaps on a per-monitor basis rather than + * all monitors (default). + */ +#define PERMON_VANITYGAPS_PATCH 0 + /* This controls whether or not to also store bar position on a per * tag basis, or leave it as one bar per monitor. */ #define PERTAGBAR_PATCH 0 +/* Similar to the focusdir patch this patch allow users to move a window in any direction + * in the tiled stack (up, down, left, right). + * https://github.com/bakkeby/patches/wiki/placedir + */ +#define PLACEDIR_PATCH 0 + /* This patch lets you change the position of a client in the stack using the mouse. * https://github.com/bakkeby/patches/wiki/placemouse */ @@ -1022,6 +1057,11 @@ */ #define SELFRESTART_PATCH 1 +/* Floating windows being sent to another monitor will be centered. + * https://dwm.suckless.org/patches/sendmoncenter/ + */ +#define SENDMON_CENTER_PATCH 0 + /* This patch allow clients to keep focus when being sent to another monitor. * https://github.com/bakkeby/patches/blob/master/dwm/dwm-sendmon_keepfocus-6.2.diff */ diff --git a/dwmblocks-async/.clang-format b/dwmblocks-async/.clang-format index d9be3e2..299675f 100644 --- a/dwmblocks-async/.clang-format +++ b/dwmblocks-async/.clang-format @@ -1,6 +1,8 @@ BasedOnStyle: Google IndentWidth: 4 +InsertBraces: true ColumnLimit: 79 -AlignArrayOfStructures: Left -AlignConsecutiveMacros: true +AlignConsecutiveMacros: Consecutive AllowShortFunctionsOnASingleLine: None +AllowShortLoopsOnASingleLine: false +AllowShortIfStatementsOnASingleLine: Never diff --git a/dwmblocks-async/.clang-tidy b/dwmblocks-async/.clang-tidy new file mode 100644 index 0000000..17ce268 --- /dev/null +++ b/dwmblocks-async/.clang-tidy @@ -0,0 +1,30 @@ +Checks: | + -*, + abseil-*, + bugprone-*, + clang-analyzer-*, + misc-*, + modernize-*, + performance-*, + portability-*, + readability-*, + llvm-*, + -bugprone-easily-swappable-parameters, + -readability-avoid-const-params-in-decls, + -readability-identifier-length + +CheckOptions: + - key: readability-inconsistent-declaration-parameter-name.Strict + value: true + - key: readability-identifier-naming.StructCase + value: lower_case + - key: readability-identifier-naming.FunctionCase + value: lower_case + - key: readability-identifier-naming.VariableCase + value: lower_case + - key: readability-identifier-naming.EnumConstantCase + value: UPPER_CASE + - key: readability-identifier-naming.MacroDefinitionCase + value: UPPER_CASE + - key: readability-function-cognitive-complexity.Threshold + value: 15 diff --git a/dwmblocks-async/.clangd b/dwmblocks-async/.clangd index 6c32dd2..d5ba524 100644 --- a/dwmblocks-async/.clangd +++ b/dwmblocks-async/.clangd @@ -1,6 +1,5 @@ -CompileFlags: - Add: - - "-I." - - "-I./inc" - - "-I.." - - "-I../inc" +Diagnostics: + UnusedIncludes: Strict + MissingIncludes: Strict + Includes: + IgnoreHeader: bits/getopt_core.h diff --git a/dwmblocks-async/.gitignore b/dwmblocks-async/.gitignore index 9056e50..902f3c7 100644 --- a/dwmblocks-async/.gitignore +++ b/dwmblocks-async/.gitignore @@ -1,3 +1,3 @@ build/ .cache/ -dwmblocks +compile_commands.json diff --git a/dwmblocks-async/Makefile b/dwmblocks-async/Makefile index 0d8d60e..413e9da 100644 --- a/dwmblocks-async/Makefile +++ b/dwmblocks-async/Makefile @@ -3,19 +3,22 @@ BIN := dwmblocks BUILD_DIR := build SRC_DIR := src -INC_DIR := inc +INC_DIR := include +CC=cc +DEBUG := 0 VERBOSE := 0 +LIBS := xcb-atom PREFIX := /usr/local -CC = cc -CFLAGS := -Wall -Wextra -Ofast -I. -I$(INC_DIR) -CFLAGS += -Wall -Wextra -Wno-missing-field-initializers -LDLIBS := -lX11 +CFLAGS := -Ofast -I. -I$(INC_DIR) -std=c99 +CFLAGS += -DBINARY=\"$(BIN)\" -D_POSIX_C_SOURCE=200809L +CFLAGS += -Wall -Wpedantic -Wextra -Wswitch-enum +CFLAGS += $(shell pkg-config --cflags $(LIBS)) +LDLIBS := $(shell pkg-config --libs $(LIBS)) -VPATH := $(SRC_DIR) -OBJS := $(patsubst $(SRC_DIR)/%.c,$(BUILD_DIR)/%.o,$(wildcard $(SRC_DIR)/*.c)) -OBJS += $(patsubst %.c,$(BUILD_DIR)/%.o,$(wildcard *.c)) +SRCS := $(wildcard $(SRC_DIR)/*.c) +OBJS := $(subst $(SRC_DIR)/,$(BUILD_DIR)/,$(SRCS:.c=.o)) INSTALL_DIR := $(DESTDIR)$(PREFIX)/bin @@ -25,20 +28,21 @@ ifeq ($(VERBOSE), 0) Q := @ endif +ifeq ($(DEBUG), 1) + CFLAGS += -g +endif + all: $(BUILD_DIR)/$(BIN) +$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c config.h + $Qmkdir -p $(@D) + $(PRINTF) "CC" $@ + $Q$(COMPILE.c) -o $@ $< + $(BUILD_DIR)/$(BIN): $(OBJS) $(PRINTF) "LD" $@ $Q$(LINK.o) $^ $(LDLIBS) -o $@ -$(BUILD_DIR)/%.o: %.c config.h | $(BUILD_DIR) - $(PRINTF) "CC" $@ - $Q$(COMPILE.c) -o $@ $< - -$(BUILD_DIR): - $(PRINTF) "MKDIR" $@ - $Qmkdir -p $@ - clean: $(PRINTF) "CLEAN" $(BUILD_DIR) $Q$(RM) $(BUILD_DIR)/* diff --git a/dwmblocks-async/README.md b/dwmblocks-async/README.md index 2006457..1b389f6 100644 --- a/dwmblocks-async/README.md +++ b/dwmblocks-async/README.md @@ -85,21 +85,21 @@ dwmblocks & ### Modifying the blocks -You can define your status bar blocks in `config.c`: +You can define your status bar blocks in `config.h`: ```c -Block blocks[] = { +#define BLOCKS(X) \ ... - {"volume", 0, 5}, - {"date", 1800, 1}, + X(" ", "wpctl get-volume @DEFAULT_AUDIO_SINK@ | cut -d' ' -f2", 0, 5) \ + X("󰥔 ", "date '+%H:%M:%S'", 1, 1) \ ... -} ``` Each block has the following properties: | Property | Description | | --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | +| Icon | An icon you wish to prepend to your block output. | | Command | The command you wish to execute in your block. | | Update interval | Time in seconds, after which you want the block to update. If `0`, the block will never be updated. | | Update signal | Signal to be used for triggering the block. Must be a positive integer. If `0`, a signal won't be set up for the block and it will be unclickable. | @@ -107,17 +107,20 @@ Each block has the following properties: Apart from defining the blocks, features can be toggled through `config.h`: ```c -// Maximum possible length of output from block, expressed in number of characters. -#define CMDLENGTH 50 +// String used to delimit block outputs in the status. +#define DELIMITER " " -// The status bar's delimiter that appears in between each block. -#define DELIMITER " " +// Maximum number of Unicode characters that a block can output. +#define MAX_BLOCK_OUTPUT_LENGTH 45 -// Adds a leading delimiter to the status bar, useful for powerline. -#define LEADING_DELIMITER 1 - -// Enable clickability for blocks. See the "Clickable blocks" section below. +// Control whether blocks are clickable. #define CLICKABLE_BLOCKS 1 + +// Control whether a leading delimiter should be prepended to the status. +#define LEADING_DELIMITER 0 + +// Control whether a trailing delimiter should be appended to the status. +#define TRAILING_DELIMITER 0 ``` ### Signalling changes diff --git a/dwmblocks-async/config.c b/dwmblocks-async/config.c deleted file mode 100644 index a6b85c1..0000000 --- a/dwmblocks-async/config.c +++ /dev/null @@ -1,17 +0,0 @@ -#include "config.h" - -#include "block.h" -#include "util.h" - -Block blocks[] = { - {"sb-forecast", 900, 1 }, - {"sb-disk", 1800, 2 }, - {"sb-memory", 10, 3 }, - {"sb-loadavg", 5, 4 }, - {"sb-music", 1, 5 }, - {"sb-volume", 1, 6 }, - {"sb-date", 1, 7 }, - {"sb-user", 0, 8 }, -}; - -const unsigned short blockCount = LEN(blocks); diff --git a/dwmblocks-async/config.h b/dwmblocks-async/config.h index 235ee71..61fb7c8 100644 --- a/dwmblocks-async/config.h +++ b/dwmblocks-async/config.h @@ -1,6 +1,29 @@ -#pragma once +#ifndef CONFIG_H +#define CONFIG_H -#define CLICKABLE_BLOCKS 1 // Enable clickability for blocks -#define CMDLENGTH 45 // Trim block output to this length -#define DELIMITER " " // Delimiter string used to separate blocks -#define LEADING_DELIMITER 0 // Whether a leading separator should be used +// String used to delimit block outputs in the status. +#define DELIMITER " " + +// Maximum number of Unicode characters that a block can output. +#define MAX_BLOCK_OUTPUT_LENGTH 45 + +// Control whether blocks are clickable. +#define CLICKABLE_BLOCKS 1 + +// Control whether a leading delimiter should be prepended to the status. +#define LEADING_DELIMITER 0 + +// Control whether a trailing delimiter should be appended to the status. +#define TRAILING_DELIMITER 0 + +// Define blocks for the status feed as X(icon, cmd, interval, signal). +#define BLOCKS(X) \ + X("", "sb-forecast", 900, 1) \ + X("", "sb-disk", 1800, 2) \ + X("", "sb-memory", 10, 3) \ + X("", "sb-loadavg", 5, 4) \ + X("", "sb-music", 1, 5) \ + X("", "sb-volume", 1, 6) \ + X("", "sb-date", 1, 7) \ + X("", "sb-user", 0, 8) +#endif // CONFIG_H diff --git a/dwmblocks-async/inc/bar.h b/dwmblocks-async/inc/bar.h deleted file mode 100644 index 377886e..0000000 --- a/dwmblocks-async/inc/bar.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once -#include "block.h" -#include "config.h" -#include "util.h" - -typedef struct { - char *current; - char *previous; -} BarStatus; - -extern unsigned short debugMode; - -void initStatus(BarStatus *); -void freeStatus(BarStatus *); -void writeStatus(BarStatus *); diff --git a/dwmblocks-async/inc/block.h b/dwmblocks-async/inc/block.h deleted file mode 100644 index f0d264c..0000000 --- a/dwmblocks-async/inc/block.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once -#include "config.h" - -typedef struct { - const char *command; - const unsigned int interval; - const unsigned int signal; - int pipe[2]; - char output[CMDLENGTH * 4 + 1]; -} Block; - -extern Block blocks[]; -extern const unsigned short blockCount; - -void execBlock(const Block *, const char *); -void execBlocks(unsigned int); -void updateBlock(Block *); diff --git a/dwmblocks-async/inc/util.h b/dwmblocks-async/inc/util.h deleted file mode 100644 index bfc030d..0000000 --- a/dwmblocks-async/inc/util.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -#define LEN(arr) (sizeof(arr) / sizeof(arr[0])) -#define MAX(a, b) (a > b ? a : b) - -int gcd(int, int); -void closePipe(int[2]); -void trimUTF8(char*, unsigned int); diff --git a/dwmblocks-async/inc/x11.h b/dwmblocks-async/inc/x11.h deleted file mode 100644 index abb4f0f..0000000 --- a/dwmblocks-async/inc/x11.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -int setupX(); -int closeX(); -void setXRootName(char *); diff --git a/dwmblocks-async/include/block.h b/dwmblocks-async/include/block.h new file mode 100644 index 0000000..c4f8d54 --- /dev/null +++ b/dwmblocks-async/include/block.h @@ -0,0 +1,29 @@ +#ifndef BLOCK_H +#define BLOCK_H + +#include +#include +#include + +#include "config.h" +#include "util.h" + +typedef struct { + const char *const icon; + const char *const command; + const unsigned int interval; + const int signal; + + int pipe[PIPE_FD_COUNT]; + char output[MAX_BLOCK_OUTPUT_LENGTH * UTF8_MAX_BYTE_COUNT + 1]; + pid_t fork_pid; +} block; + +block block_new(const char *const icon, const char *const command, + const unsigned int interval, const int signal); +int block_init(block *const block); +int block_deinit(block *const block); +int block_execute(block *const block, const uint8_t button); +int block_update(block *const block); + +#endif // BLOCK_H diff --git a/dwmblocks-async/include/cli.h b/dwmblocks-async/include/cli.h new file mode 100644 index 0000000..2f93f62 --- /dev/null +++ b/dwmblocks-async/include/cli.h @@ -0,0 +1,12 @@ +#ifndef CLI_H +#define CLI_H + +#include + +typedef struct { + bool is_debug_mode; +} cli_arguments; + +cli_arguments cli_parse_arguments(const char* const argv[], const int argc); + +#endif // CLI_H diff --git a/dwmblocks-async/include/main.h b/dwmblocks-async/include/main.h new file mode 100644 index 0000000..b37a6b1 --- /dev/null +++ b/dwmblocks-async/include/main.h @@ -0,0 +1,16 @@ +#ifndef MAIN_H +#define MAIN_H + +#include + +#include "config.h" +#include "util.h" + +#define REFRESH_SIGNAL SIGUSR1 + +// Utilise C's adjacent string concatenation to count the number of blocks. +#define X(...) "." +enum { BLOCK_COUNT = LEN(BLOCKS(X)) - 1 }; +#undef X + +#endif // MAIN_H diff --git a/dwmblocks-async/include/signal-handler.h b/dwmblocks-async/include/signal-handler.h new file mode 100644 index 0000000..da2d471 --- /dev/null +++ b/dwmblocks-async/include/signal-handler.h @@ -0,0 +1,33 @@ +#ifndef SIGNAL_HANDLER_H +#define SIGNAL_HANDLER_H + +#include + +#include "block.h" +#include "timer.h" + +typedef sigset_t signal_set; +typedef int (*signal_refresh_callback)(block* const blocks, + const unsigned short block_count); +typedef int (*signal_timer_callback)(block* const blocks, + const unsigned short block_code, + timer* const timer); + +typedef struct { + int fd; + const signal_refresh_callback refresh_callback; + const signal_timer_callback timer_callback; + + block* const blocks; + const unsigned short block_count; +} signal_handler; + +signal_handler signal_handler_new( + block* const blocks, const unsigned short block_count, + const signal_refresh_callback refresh_callback, + const signal_timer_callback timer_callback); +int signal_handler_init(signal_handler* const handler); +int signal_handler_deinit(signal_handler* const handler); +int signal_handler_process(signal_handler* const handler, timer* const timer); + +#endif // SIGNAL_HANDLER_H diff --git a/dwmblocks-async/include/status.h b/dwmblocks-async/include/status.h new file mode 100644 index 0000000..48fb3d8 --- /dev/null +++ b/dwmblocks-async/include/status.h @@ -0,0 +1,31 @@ +#ifndef STATUS_H +#define STATUS_H + +#include + +#include "block.h" +#include "config.h" +#include "main.h" +#include "util.h" +#include "x11.h" + +typedef struct { +#define STATUS_LENGTH \ + ((BLOCK_COUNT * (MEMBER_LENGTH(block, output) - 1) + CLICKABLE_BLOCKS) + \ + (BLOCK_COUNT - 1 + LEADING_DELIMITER + TRAILING_DELIMITER) * \ + (LEN(DELIMITER) - 1) + \ + 1) + char current[STATUS_LENGTH]; + char previous[STATUS_LENGTH]; +#undef STATUS_LENGTH + + const block* const blocks; + const unsigned short block_count; +} status; + +status status_new(const block* const blocks, const unsigned short block_count); +bool status_update(status* const status); +int status_write(const status* const status, const bool is_debug_mode, + x11_connection* const connection); + +#endif // STATUS_H diff --git a/dwmblocks-async/include/timer.h b/dwmblocks-async/include/timer.h new file mode 100644 index 0000000..1ec7f75 --- /dev/null +++ b/dwmblocks-async/include/timer.h @@ -0,0 +1,21 @@ +#ifndef TIMER_H +#define TIMER_H + +#include +#include + +#include "block.h" + +#define TIMER_SIGNAL SIGALRM + +typedef struct { + unsigned int time; + const unsigned int tick; + const unsigned int reset_value; +} timer; + +timer timer_new(const block *const blocks, const unsigned short block_count); +int timer_arm(timer *const timer); +bool timer_must_run_block(const timer *const timer, const block *const block); + +#endif // TIMER_H diff --git a/dwmblocks-async/include/util.h b/dwmblocks-async/include/util.h new file mode 100644 index 0000000..a3bdcce --- /dev/null +++ b/dwmblocks-async/include/util.h @@ -0,0 +1,28 @@ +#ifndef UTIL_H +#define UTIL_H + +#include + +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#define LEN(arr) (sizeof(arr) / sizeof((arr)[0])) +#define BIT(n) (1 << (n)) + +// NOLINTBEGIN(bugprone-macro-parentheses) +#define MEMBER_SIZE(type, member) sizeof(((type*)NULL)->member) +#define MEMBER_LENGTH(type, member) \ + (MEMBER_SIZE(type, member) / MEMBER_SIZE(type, member[0])) +// NOLINTEND(bugprone-macro-parentheses) + +#define UTF8_MAX_BYTE_COUNT 4 + +enum pipe_fd_index { + READ_END, + WRITE_END, + PIPE_FD_COUNT, +}; + +unsigned int gcd(unsigned int a, unsigned int b); +size_t truncate_utf8_string(char* const buffer, const size_t size, + const size_t char_limit); + +#endif // UTIL_H diff --git a/dwmblocks-async/include/watcher.h b/dwmblocks-async/include/watcher.h new file mode 100644 index 0000000..ff31809 --- /dev/null +++ b/dwmblocks-async/include/watcher.h @@ -0,0 +1,28 @@ +#ifndef WATCHER_H +#define WATCHER_H + +#include +#include + +#include "block.h" +#include "main.h" + +enum watcher_fd_index { + SIGNAL_FD = BLOCK_COUNT, + WATCHER_FD_COUNT, +}; + +typedef struct pollfd watcher_fd; + +typedef struct { + watcher_fd fds[WATCHER_FD_COUNT]; + unsigned short active_blocks[BLOCK_COUNT]; + unsigned short active_block_count; + bool got_signal; +} watcher; + +int watcher_init(watcher *const watcher, const block *const blocks, + const unsigned short block_count, const int signal_fd); +int watcher_poll(watcher *const watcher, const int timeout_ms); + +#endif // WATCHER_H diff --git a/dwmblocks-async/include/x11.h b/dwmblocks-async/include/x11.h new file mode 100644 index 0000000..6faaced --- /dev/null +++ b/dwmblocks-async/include/x11.h @@ -0,0 +1,13 @@ +#ifndef X11_H +#define X11_H + +#include + +typedef xcb_connection_t x11_connection; + +x11_connection* x11_connection_open(void); +void x11_connection_close(x11_connection* const connection); +int x11_set_root_name(x11_connection* const connection, + const char* const name); + +#endif // X11_H diff --git a/dwmblocks-async/src/bar.c b/dwmblocks-async/src/bar.c deleted file mode 100644 index 9f8261c..0000000 --- a/dwmblocks-async/src/bar.c +++ /dev/null @@ -1,62 +0,0 @@ -#include "bar.h" - -#include -#include -#include - -#include "block.h" -#include "x11.h" - -void initStatus(BarStatus *status) { - const unsigned int statusLength = - (blockCount * (LEN(blocks[0].output) - 1)) + - (blockCount - 1 + LEADING_DELIMITER) * (LEN(DELIMITER) - 1); - - status->current = (char *)malloc(statusLength); - status->previous = (char *)malloc(statusLength); - status->current[0] = '\0'; - status->previous[0] = '\0'; -} - -void freeStatus(BarStatus *status) { - free(status->current); - free(status->previous); -} - -int updateStatus(BarStatus *status) { - strcpy(status->previous, status->current); - status->current[0] = '\0'; - - for (int i = 0; i < blockCount; i++) { - Block *block = blocks + i; - - if (strlen(block->output)) { -#if LEADING_DELIMITER - strcat(status->current, DELIMITER); -#else - if (status->current[0]) strcat(status->current, DELIMITER); -#endif - -#if CLICKABLE_BLOCKS - if (!debugMode && block->signal) { - char signal[] = {block->signal, '\0'}; - strcat(status->current, signal); - } -#endif - - strcat(status->current, block->output); - } - } - return strcmp(status->current, status->previous); -} - -void writeStatus(BarStatus *status) { - // Only write out if status has changed - if (!updateStatus(status)) return; - - if (debugMode) { - printf("%s\n", status->current); - return; - } - setXRootName(status->current); -} diff --git a/dwmblocks-async/src/block.c b/dwmblocks-async/src/block.c index ae50ea5..a6c919d 100644 --- a/dwmblocks-async/src/block.c +++ b/dwmblocks-async/src/block.c @@ -1,72 +1,147 @@ #include "block.h" -#define _GNU_SOURCE +#include +#include +#include #include #include #include +#include +#include #include +#include "config.h" #include "util.h" -static int execLock = 0; +block block_new(const char *const icon, const char *const command, + const unsigned int interval, const int signal) { + block block = { + .icon = icon, + .command = command, + .interval = interval, + .signal = signal, -void execBlock(const Block *block, const char *button) { - unsigned short i = block - blocks; + .output = {[0] = '\0'}, + .fork_pid = -1, + }; - // Ensure only one child process exists per block at an instance - if (execLock & 1 << i) return; - // Lock execution of block until current instance finishes execution - execLock |= 1 << i; + return block; +} - if (fork() == 0) { - close(block->pipe[0]); - dup2(block->pipe[1], STDOUT_FILENO); - close(block->pipe[1]); +int block_init(block *const block) { + if (pipe(block->pipe) != 0) { + (void)fprintf(stderr, + "error: could not create a pipe for \"%s\" block\n", + block->command); + return 1; + } - if (button) setenv("BLOCK_BUTTON", button, 1); + return 0; +} - FILE *file = popen(block->command, "r"); - if (!file) { - printf("\n"); +int block_deinit(block *const block) { + int status = close(block->pipe[READ_END]); + status |= close(block->pipe[WRITE_END]); + if (status != 0) { + (void)fprintf(stderr, "error: could not close \"%s\" block's pipe\n", + block->command); + return 1; + } + + return 0; +} + +int block_execute(block *const block, const uint8_t button) { + // Ensure only one child process exists per block at an instance. + if (block->fork_pid != -1) { + return 0; + } + + block->fork_pid = fork(); + if (block->fork_pid == -1) { + (void)fprintf( + stderr, "error: could not create a subprocess for \"%s\" block\n", + block->command); + return 1; + } + + if (block->fork_pid == 0) { + const int write_fd = block->pipe[WRITE_END]; + int status = close(block->pipe[READ_END]); + + if (button != 0) { + char button_str[4]; + (void)snprintf(button_str, LEN(button_str), "%hhu", button); + status |= setenv("BLOCK_BUTTON", button_str, 1); + } + + const char null = '\0'; + if (status != 0) { + (void)write(write_fd, &null, sizeof(null)); exit(EXIT_FAILURE); } - // Buffer will hold both '\n' and '\0' - char buffer[LEN(block->output) + 1]; - if (fgets(buffer, LEN(buffer), file) == NULL) { - // Send an empty line in case of no output - printf("\n"); - exit(EXIT_SUCCESS); + FILE *const file = popen(block->command, "r"); + if (file == NULL) { + (void)write(write_fd, &null, sizeof(null)); + exit(EXIT_FAILURE); } - pclose(file); - // Trim to the max possible UTF-8 capacity - trimUTF8(buffer, LEN(buffer)); + // Ensure null-termination since fgets() will leave buffer untouched on + // no output. + char buffer[LEN(block->output)] = {[0] = null}; + (void)fgets(buffer, LEN(buffer), file); + + // Remove trailing newlines. + const size_t length = strcspn(buffer, "\n"); + buffer[length] = null; + + // Exit if command execution failed or if file could not be closed. + if (pclose(file) != 0) { + (void)write(write_fd, &null, sizeof(null)); + exit(EXIT_FAILURE); + } + + const size_t output_size = + truncate_utf8_string(buffer, LEN(buffer), MAX_BLOCK_OUTPUT_LENGTH); + (void)write(write_fd, buffer, output_size); - printf("%s\n", buffer); exit(EXIT_SUCCESS); } + + return 0; } -void execBlocks(unsigned int time) { - for (int i = 0; i < blockCount; i++) { - const Block *block = blocks + i; - if (time == 0 || - (block->interval != 0 && time % block->interval == 0)) { - execBlock(block, NULL); - } - } -} - -void updateBlock(Block *block) { +int block_update(block *const block) { char buffer[LEN(block->output)]; - int bytesRead = read(block->pipe[0], buffer, LEN(buffer)); - // String from pipe will always end with '\n' - buffer[bytesRead - 1] = '\0'; + const ssize_t bytes_read = + read(block->pipe[READ_END], buffer, LEN(buffer)); + if (bytes_read == -1) { + (void)fprintf(stderr, + "error: could not fetch output of \"%s\" block\n", + block->command); + return 2; + } - strcpy(block->output, buffer); + // Collect exit-status of the subprocess to avoid zombification. + int fork_status = 0; + if (waitpid(block->fork_pid, &fork_status, 0) == -1) { + (void)fprintf(stderr, + "error: could not obtain exit status for \"%s\" block\n", + block->command); + return 2; + } + block->fork_pid = -1; - // Remove execution lock for the current block - execLock &= ~(1 << (block - blocks)); + if (fork_status != 0) { + (void)fprintf(stderr, + "error: \"%s\" block exited with non-zero status\n", + block->command); + return 1; + } + + (void)strncpy(block->output, buffer, LEN(buffer)); + + return 0; } diff --git a/dwmblocks-async/src/cli.c b/dwmblocks-async/src/cli.c new file mode 100644 index 0000000..b1849ec --- /dev/null +++ b/dwmblocks-async/src/cli.c @@ -0,0 +1,33 @@ +#include "cli.h" + +#include +#include +#include +#include + +cli_arguments cli_parse_arguments(const char *const argv[], const int argc) { + errno = 0; + cli_arguments args = { + .is_debug_mode = false, + }; + + int opt = -1; + opterr = 0; // Suppress getopt's built-in invalid opt message + while ((opt = getopt(argc, (char *const *)argv, "dh")) != -1) { + switch (opt) { + case 'd': + args.is_debug_mode = true; + break; + case '?': + (void)fprintf(stderr, "error: unknown option `-%c'\n", optopt); + // fall through + case 'h': + // fall through + default: + (void)fprintf(stderr, "usage: %s [-d]\n", BINARY); + errno = 1; + } + } + + return args; +} diff --git a/dwmblocks-async/src/main.c b/dwmblocks-async/src/main.c index 8b87b63..747b075 100644 --- a/dwmblocks-async/src/main.c +++ b/dwmblocks-async/src/main.c @@ -1,157 +1,168 @@ -#define _GNU_SOURCE -#include -#include -#include -#include -#include +#include "main.h" + +#include +#include +#include -#include "bar.h" #include "block.h" +#include "cli.h" +#include "config.h" +#include "signal-handler.h" +#include "status.h" +#include "timer.h" #include "util.h" +#include "watcher.h" #include "x11.h" -static unsigned short statusContinue = 1; -unsigned short debugMode = 0; -static int epollFD, signalFD; -static unsigned int timerTick = 0, maxInterval = 1; - -void signalHandler() { - struct signalfd_siginfo info; - read(signalFD, &info, sizeof(info)); - unsigned int signal = info.ssi_signo; - - static unsigned int timer = 0; - switch (signal) { - case SIGALRM: - // Schedule the next timer event and execute blocks - alarm(timerTick); - execBlocks(timer); - - // Wrap `timer` to the interval [1, `maxInterval`] - timer = (timer + timerTick - 1) % maxInterval + 1; - return; - case SIGUSR1: - // Update all blocks on receiving SIGUSR1 - execBlocks(0); - return; - } - - for (int j = 0; j < blockCount; j++) { - const Block *block = blocks + j; - if (block->signal == signal - SIGRTMIN) { - char button[4]; // value can't be more than 255; - sprintf(button, "%d", info.ssi_int & 0xff); - execBlock(block, button); - break; +static int init_blocks(block *const blocks, const unsigned short block_count) { + for (unsigned short i = 0; i < block_count; ++i) { + block *const block = &blocks[i]; + if (block_init(block) != 0) { + return 1; } } -} - -void termHandler() { - statusContinue = 0; -} - -void setupSignals() { - sigset_t handledSignals; - sigemptyset(&handledSignals); - sigaddset(&handledSignals, SIGUSR1); - sigaddset(&handledSignals, SIGALRM); - - // Append all block signals to `handledSignals` - for (int i = 0; i < blockCount; i++) - if (blocks[i].signal > 0) - sigaddset(&handledSignals, SIGRTMIN + blocks[i].signal); - - // Create a signal file descriptor for epoll to watch - signalFD = signalfd(-1, &handledSignals, 0); - - // Block all realtime and handled signals - for (int i = SIGRTMIN; i <= SIGRTMAX; i++) sigaddset(&handledSignals, i); - sigprocmask(SIG_BLOCK, &handledSignals, NULL); - - // Handle termination signals - signal(SIGINT, termHandler); - signal(SIGTERM, termHandler); - - // Avoid zombie subprocesses - struct sigaction signalAction; - signalAction.sa_handler = SIG_DFL; - sigemptyset(&signalAction.sa_mask); - signalAction.sa_flags = SA_NOCLDWAIT; - sigaction(SIGCHLD, &signalAction, 0); -} - -void statusLoop() { - // Update all blocks initially - raise(SIGALRM); - - BarStatus status; - initStatus(&status); - struct epoll_event events[blockCount + 1]; - while (statusContinue) { - int eventCount = epoll_wait(epollFD, events, LEN(events), 100); - for (int i = 0; i < eventCount; i++) { - unsigned short id = events[i].data.u32; - if (id < blockCount) { - updateBlock(blocks + id); - } else { - signalHandler(); - } - } - - if (eventCount != -1) writeStatus(&status); - } - freeStatus(&status); -} - -void init() { - epollFD = epoll_create(blockCount); - struct epoll_event event = { - .events = EPOLLIN, - }; - - for (int i = 0; i < blockCount; i++) { - // Append each block's pipe's read end to `epollFD` - pipe(blocks[i].pipe); - event.data.u32 = i; - epoll_ctl(epollFD, EPOLL_CTL_ADD, blocks[i].pipe[0], &event); - - // Calculate the max interval and tick size for the timer - if (blocks[i].interval) { - maxInterval = MAX(blocks[i].interval, maxInterval); - timerTick = gcd(blocks[i].interval, timerTick); - } - } - - setupSignals(); - - // Watch signal file descriptor as well - event.data.u32 = blockCount; - epoll_ctl(epollFD, EPOLL_CTL_ADD, signalFD, &event); -} - -int main(const int argc, const char *argv[]) { - if (setupX()) { - fprintf(stderr, "%s\n", "dwmblocks: Failed to open display"); - return 1; - } - - for (int i = 0; i < argc; i++) { - if (!strcmp("-d", argv[i])) { - debugMode = 1; - break; - } - } - - init(); - statusLoop(); - - if (closeX()) - fprintf(stderr, "%s\n", "dwmblocks: Failed to close display"); - - close(epollFD); - close(signalFD); - for (int i = 0; i < blockCount; i++) closePipe(blocks[i].pipe); return 0; } + +static int deinit_blocks(block *const blocks, + const unsigned short block_count) { + for (unsigned short i = 0; i < block_count; ++i) { + block *const block = &blocks[i]; + if (block_deinit(block) != 0) { + return 1; + } + } + + return 0; +} + +static int execute_blocks(block *const blocks, + const unsigned short block_count, + const timer *const timer) { + for (unsigned short i = 0; i < block_count; ++i) { + block *const block = &blocks[i]; + if (!timer_must_run_block(timer, block)) { + continue; + } + + if (block_execute(&blocks[i], 0) != 0) { + return 1; + } + } + + return 0; +} + +static int trigger_event(block *const blocks, const unsigned short block_count, + timer *const timer) { + if (execute_blocks(blocks, block_count, timer) != 0) { + return 1; + } + + if (timer_arm(timer) != 0) { + return 1; + } + + return 0; +} + +static int refresh_callback(block *const blocks, + const unsigned short block_count) { + if (execute_blocks(blocks, block_count, NULL) != 0) { + return 1; + } + + return 0; +} + +static int event_loop(block *const blocks, const unsigned short block_count, + const bool is_debug_mode, + x11_connection *const connection, + signal_handler *const signal_handler) { + timer timer = timer_new(blocks, block_count); + + // Kickstart the event loop with an initial execution. + if (trigger_event(blocks, block_count, &timer) != 0) { + return 1; + } + + watcher watcher; + if (watcher_init(&watcher, blocks, block_count, signal_handler->fd) != 0) { + return 1; + } + + status status = status_new(blocks, block_count); + bool is_alive = true; + while (is_alive) { + if (watcher_poll(&watcher, -1) != 0) { + return 1; + } + + if (watcher.got_signal) { + is_alive = signal_handler_process(signal_handler, &timer) == 0; + } + + for (unsigned short i = 0; i < watcher.active_block_count; ++i) { + (void)block_update(&blocks[watcher.active_blocks[i]]); + } + + const bool has_status_changed = status_update(&status); + if (has_status_changed && + status_write(&status, is_debug_mode, connection) != 0) { + return 1; + } + } + + return 0; +} + +int main(const int argc, const char *const argv[]) { + const cli_arguments cli_args = cli_parse_arguments(argv, argc); + if (errno != 0) { + return 1; + } + + x11_connection *const connection = x11_connection_open(); + if (connection == NULL) { + return 1; + } + +#define BLOCK(icon, command, interval, signal) \ + block_new(icon, command, interval, signal), + block blocks[BLOCK_COUNT] = {BLOCKS(BLOCK)}; +#undef BLOCK + const unsigned short block_count = LEN(blocks); + + int status = 0; + if (init_blocks(blocks, block_count) != 0) { + status = 1; + goto x11_close; + } + + signal_handler signal_handler = signal_handler_new( + blocks, block_count, refresh_callback, trigger_event); + if (signal_handler_init(&signal_handler) != 0) { + status = 1; + goto deinit_blocks; + } + + if (event_loop(blocks, block_count, cli_args.is_debug_mode, connection, + &signal_handler) != 0) { + status = 1; + } + + if (signal_handler_deinit(&signal_handler) != 0) { + status = 1; + } + +deinit_blocks: + if (deinit_blocks(blocks, block_count) != 0) { + status = 1; + } + +x11_close: + x11_connection_close(connection); + + return status; +} diff --git a/dwmblocks-async/src/signal-handler.c b/dwmblocks-async/src/signal-handler.c new file mode 100644 index 0000000..d816dcd --- /dev/null +++ b/dwmblocks-async/src/signal-handler.c @@ -0,0 +1,124 @@ +#include "signal-handler.h" + +#include +#include +#include +#include +#include +#include + +#include "block.h" +#include "main.h" +#include "timer.h" + +typedef struct signalfd_siginfo signal_info; + +signal_handler signal_handler_new( + block *const blocks, const unsigned short block_count, + const signal_refresh_callback refresh_callback, + const signal_timer_callback timer_callback) { + signal_handler handler = { + .refresh_callback = refresh_callback, + .timer_callback = timer_callback, + + .blocks = blocks, + .block_count = block_count, + }; + + return handler; +} + +int signal_handler_init(signal_handler *const handler) { + signal_set set; + (void)sigemptyset(&set); + + // Handle user-generated signal for refreshing the status. + (void)sigaddset(&set, REFRESH_SIGNAL); + + // Handle SIGALRM generated by the timer. + (void)sigaddset(&set, TIMER_SIGNAL); + + // Handle termination signals. + (void)sigaddset(&set, SIGINT); + (void)sigaddset(&set, SIGTERM); + + for (unsigned short i = 0; i < handler->block_count; ++i) { + const block *const block = &handler->blocks[i]; + if (block->signal > 0) { + if (sigaddset(&set, SIGRTMIN + block->signal) != 0) { + (void)fprintf( + stderr, + "error: invalid or unsupported signal specified for " + "\"%s\" block\n", + block->command); + return 1; + } + } + } + + // Create a signal file descriptor for epoll to watch. + handler->fd = signalfd(-1, &set, 0); + if (handler->fd == -1) { + (void)fprintf(stderr, + "error: could not create file descriptor for signals\n"); + return 1; + } + + // Block all realtime and handled signals. + for (int i = SIGRTMIN; i <= SIGRTMAX; ++i) { + (void)sigaddset(&set, i); + } + (void)sigprocmask(SIG_BLOCK, &set, NULL); + + return 0; +} + +int signal_handler_deinit(signal_handler *const handler) { + if (close(handler->fd) != 0) { + (void)fprintf(stderr, + "error: could not close signal file descriptor\n"); + return 1; + } + + return 0; +} + +int signal_handler_process(signal_handler *const handler, timer *const timer) { + signal_info info; + const ssize_t bytes_read = read(handler->fd, &info, sizeof(info)); + if (bytes_read == -1) { + (void)fprintf(stderr, "error: could not read info of incoming signal"); + return 1; + } + + const int signal = (int)info.ssi_signo; + switch (signal) { + case TIMER_SIGNAL: + if (handler->timer_callback(handler->blocks, handler->block_count, + timer) != 0) { + return 1; + } + return 0; + case REFRESH_SIGNAL: + if (handler->refresh_callback(handler->blocks, + handler->block_count) != 0) { + return 1; + } + return 0; + case SIGTERM: + // fall through + case SIGINT: + return 1; + } + + for (unsigned short i = 0; i < handler->block_count; ++i) { + block *const block = &handler->blocks[i]; + if (block->signal == signal - SIGRTMIN) { + const uint8_t button = (uint8_t)info.ssi_int; + block_execute(block, button); + break; + } + } + + return 0; +} diff --git a/dwmblocks-async/src/status.c b/dwmblocks-async/src/status.c new file mode 100644 index 0000000..cf0911a --- /dev/null +++ b/dwmblocks-async/src/status.c @@ -0,0 +1,78 @@ +#include "status.h" + +#include +#include +#include + +#include "block.h" +#include "config.h" +#include "util.h" +#include "x11.h" + +static bool has_status_changed(const status *const status) { + return strcmp(status->current, status->previous) != 0; +} + +status status_new(const block *const blocks, + const unsigned short block_count) { + status status = { + .current = {[0] = '\0'}, + .previous = {[0] = '\0'}, + + .blocks = blocks, + .block_count = block_count, + }; + + return status; +} + +bool status_update(status *const status) { + (void)strncpy(status->previous, status->current, LEN(status->current)); + status->current[0] = '\0'; + + for (unsigned short i = 0; i < status->block_count; ++i) { + const block *const block = &status->blocks[i]; + + if (strlen(block->output) > 0) { +#if LEADING_DELIMITER + (void)strncat(status->current, DELIMITER, LEN(DELIMITER)); +#else + if (status->current[0] != '\0') { + (void)strncat(status->current, DELIMITER, LEN(DELIMITER)); + } +#endif + +#if CLICKABLE_BLOCKS + if (block->signal > 0) { + const char signal[] = {(char)block->signal, '\0'}; + (void)strncat(status->current, signal, LEN(signal)); + } +#endif + + (void)strncat(status->current, block->icon, LEN(block->output)); + (void)strncat(status->current, block->output, LEN(block->output)); + } + } + +#if TRAILING_DELIMITER + if (status->current[0] != '\0') { + (void)strncat(status->current, DELIMITER, LEN(DELIMITER)); + } +#endif + + return has_status_changed(status); +} + +int status_write(const status *const status, const bool is_debug_mode, + x11_connection *const connection) { + if (is_debug_mode) { + (void)printf("%s\n", status->current); + return 0; + } + + if (x11_set_root_name(connection, status->current) != 0) { + return 1; + } + + return 0; +} diff --git a/dwmblocks-async/src/timer.c b/dwmblocks-async/src/timer.c new file mode 100644 index 0000000..2ee555b --- /dev/null +++ b/dwmblocks-async/src/timer.c @@ -0,0 +1,72 @@ +#include "timer.h" + +#include +#include +#include +#include + +#include "block.h" +#include "util.h" + +static unsigned int compute_tick(const block *const blocks, + const unsigned short block_count) { + unsigned int tick = 0; + + for (unsigned short i = 0; i < block_count; ++i) { + const block *const block = &blocks[i]; + tick = gcd(block->interval, tick); + } + + return tick; +} + +static unsigned int compute_reset_value(const block *const blocks, + const unsigned short block_count) { + unsigned int reset_value = 1; + + for (unsigned short i = 0; i < block_count; ++i) { + const block *const block = &blocks[i]; + reset_value = MAX(block->interval, reset_value); + } + + return reset_value; +} + +timer timer_new(const block *const blocks, const unsigned short block_count) { + const unsigned int reset_value = compute_reset_value(blocks, block_count); + + timer timer = { + .time = reset_value, // Initial value to execute all blocks. + .tick = compute_tick(blocks, block_count), + .reset_value = reset_value, + }; + + return timer; +} + +int timer_arm(timer *const timer) { + errno = 0; + (void)alarm(timer->tick); + + if (errno != 0) { + (void)fprintf(stderr, "error: could not arm timer\n"); + return 1; + } + + // Wrap `time` to the interval [1, reset_value]. + timer->time = (timer->time + timer->tick) % timer->reset_value; + + return 0; +} + +bool timer_must_run_block(const timer *const timer, const block *const block) { + if (timer == NULL || timer->time == timer->reset_value) { + return true; + } + + if (block->interval == 0) { + return false; + } + + return timer->time % block->interval == 0; +} diff --git a/dwmblocks-async/src/util.c b/dwmblocks-async/src/util.c index 157e626..10485db 100644 --- a/dwmblocks-async/src/util.c +++ b/dwmblocks-async/src/util.c @@ -1,41 +1,49 @@ #include "util.h" -#include +#define UTF8_MULTIBYTE_BIT BIT(7) -int gcd(int a, int b) { - int temp; +unsigned int gcd(unsigned int a, unsigned int b) { while (b > 0) { - temp = a % b; + const unsigned int temp = a % b; a = b; b = temp; } + return a; } -void closePipe(int pipe[2]) { - close(pipe[0]); - close(pipe[1]); -} - -void trimUTF8(char* buffer, unsigned int size) { - int length = (size - 1) / 4; - int count = 0, j = 0; - char ch = buffer[j]; - while (ch != '\0' && ch != '\n' && count < length) { - // Skip continuation bytes, if any - int skip = 1; - while ((ch & 0xc0) > 0x80) { - ch <<= 1; - skip++; +size_t truncate_utf8_string(char* const buffer, const size_t size, + const size_t char_limit) { + size_t char_count = 0; + size_t i = 0; + while (char_count < char_limit) { + char ch = buffer[i]; + if (ch == '\0') { + break; } - j += skip; - ch = buffer[j]; - count++; + unsigned short skip = 1; + + // Multibyte unicode character. + if ((ch & UTF8_MULTIBYTE_BIT) != 0) { + // Skip continuation bytes. + ch <<= 1; + while ((ch & UTF8_MULTIBYTE_BIT) != 0) { + ch <<= 1; + ++skip; + } + } + + // Avoid buffer overflow. + if (i + skip >= size) { + break; + } + + ++char_count; + i += skip; } - // Trim trailing newline and spaces - buffer[j] = ' '; - while (j >= 0 && buffer[j] == ' ') j--; - buffer[j + 1] = '\0'; + buffer[i] = '\0'; + + return i + 1; } diff --git a/dwmblocks-async/src/watcher.c b/dwmblocks-async/src/watcher.c new file mode 100644 index 0000000..71b6c52 --- /dev/null +++ b/dwmblocks-async/src/watcher.c @@ -0,0 +1,69 @@ +#include "watcher.h" + +#include +#include +#include +#include + +#include "block.h" +#include "util.h" + +static bool watcher_fd_is_readable(const watcher_fd* const watcher_fd) { + return (watcher_fd->revents & POLLIN) != 0; +} + +int watcher_init(watcher* const watcher, const block* const blocks, + const unsigned short block_count, const int signal_fd) { + if (signal_fd == -1) { + (void)fprintf( + stderr, + "error: invalid signal file descriptor passed to watcher\n"); + return 1; + } + + watcher_fd* const fd = &watcher->fds[SIGNAL_FD]; + fd->fd = signal_fd; + fd->events = POLLIN; + + for (unsigned short i = 0; i < block_count; ++i) { + const int block_fd = blocks[i].pipe[READ_END]; + if (block_fd == -1) { + (void)fprintf( + stderr, + "error: invalid block file descriptors passed to watcher\n"); + return 1; + } + + watcher_fd* const fd = &watcher->fds[i]; + fd->fd = block_fd; + fd->events = POLLIN; + } + + return 0; +} + +int watcher_poll(watcher* watcher, const int timeout_ms) { + int event_count = poll(watcher->fds, LEN(watcher->fds), timeout_ms); + + // Don't return non-zero status for signal interruptions. + if (event_count == -1 && errno != EINTR) { + (void)fprintf(stderr, "error: watcher could not poll blocks\n"); + return 1; + } + + watcher->got_signal = watcher_fd_is_readable(&watcher->fds[SIGNAL_FD]); + + watcher->active_block_count = event_count - (int)watcher->got_signal; + unsigned short i = 0; + unsigned short j = 0; + while (i < event_count && j < LEN(watcher->active_blocks)) { + if (watcher_fd_is_readable(&watcher->fds[j])) { + watcher->active_blocks[i] = j; + ++i; + } + + ++j; + } + + return 0; +} diff --git a/dwmblocks-async/src/x11.c b/dwmblocks-async/src/x11.c index 63c5d14..7a310e9 100644 --- a/dwmblocks-async/src/x11.c +++ b/dwmblocks-async/src/x11.c @@ -1,25 +1,44 @@ #include "x11.h" -#include +#include +#include +#include +#include -static Display *display; -static Window rootWindow; +x11_connection *x11_connection_open(void) { + xcb_connection_t *const connection = xcb_connect(NULL, NULL); + if (xcb_connection_has_error(connection)) { + (void)fprintf(stderr, "error: could not connect to X server\n"); + return NULL; + } -int setupX() { - display = XOpenDisplay(NULL); - if (!display) { + return connection; +} + +void x11_connection_close(xcb_connection_t *const connection) { + xcb_disconnect(connection); +} + +int x11_set_root_name(x11_connection *const connection, const char *name) { + xcb_screen_t *const screen = + xcb_setup_roots_iterator(xcb_get_setup(connection)).data; + const xcb_window_t root_window = screen->root; + + const unsigned short name_format = 8; + const xcb_void_cookie_t cookie = xcb_change_property( + connection, XCB_PROP_MODE_REPLACE, root_window, XCB_ATOM_WM_NAME, + XCB_ATOM_STRING, name_format, strlen(name), name); + + xcb_generic_error_t *error = xcb_request_check(connection, cookie); + if (error != NULL) { + (void)fprintf(stderr, "error: could not set X root name\n"); + return 1; + } + + if (xcb_flush(connection) <= 0) { + (void)fprintf(stderr, "error: could not flush X output buffer\n"); return 1; } - rootWindow = DefaultRootWindow(display); return 0; } - -int closeX() { - return XCloseDisplay(display); -} - -void setXRootName(char *str) { - XStoreName(display, rootWindow, str); - XFlush(display); -} diff --git a/nsxiv/.github/workflows/build.yml b/nsxiv/.github/workflows/build.yml index 6b6af3f..054dd94 100644 --- a/nsxiv/.github/workflows/build.yml +++ b/nsxiv/.github/workflows/build.yml @@ -47,7 +47,11 @@ jobs: - name: build run: | # libinotify-kqueue isn't available on homebrew - make clean && make -s OPT_DEP_DEFAULT=1 HAVE_INOTIFY=0 + make clean && make -s OPT_DEP_DEFAULT=1 HAVE_INOTIFY=0 \ + CPPFLAGS="-I/opt/homebrew/include -I/opt/homebrew/include/freetype2" \ + LDLIBS="-L/opt/homebrew/lib" # force uninstallation with --ignore-dependencies brew uninstall --ignore-dependencies libxft libexif - make clean && make -s OPT_DEP_DEFAULT=0 + make clean && make -s OPT_DEP_DEFAULT=0 \ + CPPFLAGS="-I/opt/homebrew/include" \ + LDLIBS="-L/opt/homebrew/lib" diff --git a/nsxiv/README.md b/nsxiv/README.md index 9a9c1d4..e8ce9e9 100644 --- a/nsxiv/README.md +++ b/nsxiv/README.md @@ -81,8 +81,8 @@ you want to build nsxiv on a distribution with separate runtime and development packages (e.g. \*-dev on Debian). \* [inotify][] is a Linux-specific API for monitoring filesystem changes. - It's not natively available on `*BSD` systems but can be enabed via installing - and linking against [libinotify-kqueue][]. + It's not natively available on `*BSD` systems but can be enabled via + installing and linking against [libinotify-kqueue][]. [inotify]: https://www.man7.org/linux/man-pages/man7/inotify.7.html [libinotify-kqueue]: https://github.com/libinotify-kqueue/libinotify-kqueue diff --git a/nsxiv/autoreload.c b/nsxiv/autoreload.c index 8b3f6da..1a889dc 100644 --- a/nsxiv/autoreload.c +++ b/nsxiv/autoreload.c @@ -85,8 +85,8 @@ void arl_add(arl_t *arl, const char *filepath) add_watch(arl->fd, &arl->wd_file, filepath, IN_CLOSE_WRITE | IN_DELETE_SELF); base = strrchr(filepath, '/'); - assert(base != NULL); /* filepath must be result of `realpath(3)` */ - dir = arl_scratch_push(filepath, base - filepath); + assert(base != NULL && "filepath must be result of realpath(3)"); + dir = arl_scratch_push(filepath, MAX(base - filepath, 1)); add_watch(arl->fd, &arl->wd_dir, dir, IN_CREATE | IN_MOVED_TO); arl->filename = arl_scratch_push(base + 1, strlen(base + 1)); } diff --git a/nsxiv/config.def.h b/nsxiv/config.def.h index 9d424ee..7fbfb17 100644 --- a/nsxiv/config.def.h +++ b/nsxiv/config.def.h @@ -13,7 +13,7 @@ static const char *MARK_FG[] = { "Nsxiv.mark.foreground", NULL }; #if HAVE_LIBFONTS static const char *BAR_BG[] = { "Nsxiv.bar.background", NULL }; static const char *BAR_FG[] = { "Nsxiv.bar.foreground", NULL }; -static const char *BAR_FONT[] = { "Nsxiv.bar.font", "Hack Nerd Font-11" }; +static const char *BAR_FONT[] = { "Nsxiv.bar.font", "monospace-8" }; /* if true, statusbar appears on top of the window */ static const bool TOP_STATUSBAR = false; diff --git a/nsxiv/config.mk b/nsxiv/config.mk index 480785f..67d801b 100644 --- a/nsxiv/config.mk +++ b/nsxiv/config.mk @@ -25,7 +25,6 @@ CFLAGS = -Wall -pedantic -O2 -DNDEBUG # icons that will be installed via `make icon` ICONS = 16x16.png 32x32.png 48x48.png 64x64.png 128x128.png -CC = gcc # Uncomment on OpenBSD # HAVE_INOTIFY = 0 # lib_fonts_bsd_0 = @@ -34,3 +33,5 @@ CC = gcc # inc_fonts_bsd_1 = -I/usr/X11R6/include/freetype2 # CPPFLAGS = -I/usr/X11R6/include -I/usr/local/include $(inc_fonts_bsd_$(HAVE_LIBFONTS)) # LDLIBS = -L/usr/X11R6/lib -L/usr/local/lib $(lib_fonts_bsd_$(HAVE_LIBFONTS)) + +CC = gcc diff --git a/nsxiv/etc/nsxiv.1 b/nsxiv/etc/nsxiv.1 index 9b5c243..5edfece 100644 --- a/nsxiv/etc/nsxiv.1 +++ b/nsxiv/etc/nsxiv.1 @@ -440,7 +440,9 @@ Zoom in. .B Button5 Zoom out. .SH CONFIGURATION -The following X resources are supported: +The following X resources are supported under "Nsxiv" (e.g. +.B Nsxiv.bar.font +): .TP .B window.background Color of the window background diff --git a/nsxiv/etc/nsxiv.desktop b/nsxiv/etc/nsxiv.desktop index 4d3549c..de90437 100644 --- a/nsxiv/etc/nsxiv.desktop +++ b/nsxiv/etc/nsxiv.desktop @@ -1,15 +1,8 @@ [Desktop Entry] -Comment= -Exec=nsxiv ~/Pictures -GenericName=Image Viewer -Icon=nsxiv +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 -Path= -StartupNotify=true -Terminal=false -TerminalOptions= -Type=Application -X-KDE-SubstituteUID=false -X-KDE-Username= +Icon=nsxiv diff --git a/nsxiv/etc/woodpecker/analysis.yml b/nsxiv/etc/woodpecker/analysis.yml index b08dc36..4edcd6b 100644 --- a/nsxiv/etc/woodpecker/analysis.yml +++ b/nsxiv/etc/woodpecker/analysis.yml @@ -1,6 +1,7 @@ -branches: master +when: + branch: master -pipeline: +steps: analysis: image: alpine commands: | diff --git a/nsxiv/etc/woodpecker/build.yml b/nsxiv/etc/woodpecker/build.yml index 1f447a3..431f27f 100644 --- a/nsxiv/etc/woodpecker/build.yml +++ b/nsxiv/etc/woodpecker/build.yml @@ -1,7 +1,8 @@ -branches: master +when: + branch: master # NOTE: "stable" tcc is too old and fails at linking. instead fetching a recent known working commit. -pipeline: +steps: build: image: alpine environment: diff --git a/nsxiv/etc/woodpecker/clang-tidy-checks b/nsxiv/etc/woodpecker/clang-tidy-checks index edf0ba6..c326eef 100644 --- a/nsxiv/etc/woodpecker/clang-tidy-checks +++ b/nsxiv/etc/woodpecker/clang-tidy-checks @@ -4,13 +4,13 @@ misc-*,android-cloexec-*,llvm-include-order -readability-*,readability-duplicate-include,readability-misleading-indentation # silence --misc-unused-parameters +-misc-unused-parameters,-misc-include-cleaner,-misc-no-recursion -bugprone-easily-swappable-parameters,-bugprone-narrowing-conversions,-bugprone-incorrect-roundings -bugprone-implicit-widening-of-multiplication-result,-bugprone-integer-division -android-cloexec-fopen,-android-cloexec-pipe,-cert-err33-c -bugprone-assignment-in-if-condition -bugprone-suspicious-realloc-usage +-bugprone-switch-missing-default-case # false positive warnings -clang-analyzer-valist.Uninitialized --misc-no-recursion diff --git a/nsxiv/etc/woodpecker/spell.yml b/nsxiv/etc/woodpecker/spell.yml index a6b71d8..78ce57f 100644 --- a/nsxiv/etc/woodpecker/spell.yml +++ b/nsxiv/etc/woodpecker/spell.yml @@ -1,10 +1,13 @@ -branches: master +when: + branch: master -# NOTE: codespell not available on stable alpine, use edge -pipeline: +# NOTE: codespell not available on stable alpine, grab it from pip +steps: spell-check: image: alpine:edge commands: | apk add --no-cache python3 py3-pip git + python3 -m venv ~/py3-venv + . ~/py3-venv/bin/activate pip install codespell git ls-files | sed '/\.png$/d' | xargs codespell diff --git a/nsxiv/image.c b/nsxiv/image.c index a138f95..50d792f 100644 --- a/nsxiv/image.c +++ b/nsxiv/image.c @@ -234,7 +234,8 @@ static bool img_load_multiframe(img_t *img, const fileinfo_t *file) imlib_context_set_blend(!!(finfo.frame_flags & IMLIB_FRAME_BLEND)); imlib_blend_image_onto_image(frame, has_alpha, 0, 0, sw, sh, sx, sy, sw, sh); m->frames[m->cnt].im = canvas; - m->frames[m->cnt].delay = finfo.frame_delay ? finfo.frame_delay : DEF_ANIM_DELAY; + m->frames[m->cnt].delay = m->framedelay ? m->framedelay : + (finfo.frame_delay ? finfo.frame_delay : DEF_ANIM_DELAY); m->length += m->frames[m->cnt].delay; m->cnt++; img_free(frame, false); @@ -676,8 +677,8 @@ void img_rotate(img_t *img, degree_t d) 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; + img->x = oy + (int)(img->win->w - img->win->h) / 2; + img->y = ox + (int)(img->win->h - img->win->w) / 2; tmp = img->w; img->w = img->h; diff --git a/nsxiv/main.c b/nsxiv/main.c index e0ff5b3..74776fe 100644 --- a/nsxiv/main.c +++ b/nsxiv/main.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -249,10 +250,10 @@ void reset_timeout(timeout_f handler) static bool check_timeouts(int *t) { - int i = 0, tdiff, tmin = -1; + int i = 0, tdiff, tmin; struct timeval now; - while (i < (int)ARRLEN(timeouts)) { + for (i = 0; i < (int)ARRLEN(timeouts); ++i) { if (timeouts[i].active) { gettimeofday(&now, 0); tdiff = TV_DIFF(&timeouts[i].when, &now); @@ -260,16 +261,22 @@ static bool check_timeouts(int *t) 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) - *t = tmin; - return tmin > 0; + + tmin = INT_MAX; + gettimeofday(&now, 0); + for (i = 0; i < (int)ARRLEN(timeouts); ++i) { + if (timeouts[i].active) { + tdiff = TV_DIFF(&timeouts[i].when, &now); + tmin = MIN(tmin, tdiff); + } + } + + if (tmin != INT_MAX && t != NULL) + *t = MAX(tmin, 0); + return tmin != INT_MAX; } static void autoreload(void) @@ -328,8 +335,7 @@ static void open_title(void) snprintf(fcnt, ARRLEN(fcnt), "%d", filecnt); construct_argv(argv, ARRLEN(argv), wintitle.f.cmd, files[fileidx].path, fidx, fcnt, w, h, z, NULL); - if ((wintitle.pid = spawn(&wintitle.fd, NULL, argv)) > 0) - fcntl(wintitle.fd, F_SETFL, O_NONBLOCK); + wintitle.pid = spawn(&wintitle.fd, NULL, O_NONBLOCK, argv); } void close_info(void) @@ -352,8 +358,7 @@ void open_info(void) } construct_argv(argv, ARRLEN(argv), cmd, files[fileidx].name, w, h, files[fileidx].path, NULL); - if ((info.pid = spawn(&info.fd, NULL, argv)) > 0) - fcntl(info.fd, F_SETFL, O_NONBLOCK); + info.pid = spawn(&info.fd, NULL, O_NONBLOCK, argv); } static void read_info(void) @@ -455,7 +460,6 @@ static void update_info(void) open_title(); } - /* update bar contents */ if (win.bar.h == 0 || extprefix) return; @@ -601,12 +605,10 @@ void handle_key_handler(bool init) if (win.bar.h == 0) return; if (init) { - close_info(); - snprintf(win.bar.l.buf, win.bar.l.size, + snprintf(win.bar.r.buf, win.bar.r.size, "Getting key handler input (%s to abort)...", XKeysymToString(KEYHANDLER_ABORT)); } else { /* abort */ - open_info(); update_info(); } win_draw(&win); @@ -635,8 +637,7 @@ static bool run_key_handler(const char *key, unsigned int mask) if (key == NULL) return false; - close_info(); - strncpy(win.bar.l.buf, "Running key handler...", win.bar.l.size); + strncpy(win.bar.r.buf, "Running key handler...", win.bar.r.size); win_draw(&win); win_set_cursor(&win, CURSOR_WATCH); setenv("NSXIV_USING_NULL", options->using_null ? "1" : "0", 1); @@ -646,7 +647,7 @@ static bool run_key_handler(const char *key, unsigned int mask) mask & Mod1Mask ? "M-" : "", mask & ShiftMask ? "S-" : "", key); construct_argv(argv, ARRLEN(argv), keyhandler.f.cmd, kstr, NULL); - if ((pid = spawn(NULL, &writefd, argv)) < 0) + if ((pid = spawn(NULL, &writefd, 0x0, argv)) < 0) return false; if ((pfs = fdopen(writefd, "w")) == NULL) { error(0, errno, "open pipe"); @@ -687,6 +688,8 @@ static bool run_key_handler(const char *key, unsigned int mask) if (mode == MODE_IMAGE && changed) { img_close(&img, true); load_image(fileidx); + } else { + update_info(); } free(oldst); reset_cursor(); @@ -801,13 +804,15 @@ static void run(void) pfd[FD_INFO].fd = info.fd; pfd[FD_TITLE].fd = wintitle.fd; pfd[FD_ARL].fd = arl.fd; - pfd[FD_X].events = pfd[FD_INFO].events = pfd[FD_TITLE].events = pfd[FD_ARL].events = POLLIN; + + pfd[FD_X].events = pfd[FD_ARL].events = POLLIN; + pfd[FD_INFO].events = pfd[FD_TITLE].events = 0; if (poll(pfd, ARRLEN(pfd), to_set ? timeout : -1) < 0) continue; - if (pfd[FD_INFO].revents & POLLIN) + if (pfd[FD_INFO].revents & POLLHUP) read_info(); - if (pfd[FD_TITLE].revents & POLLIN) + if (pfd[FD_TITLE].revents & POLLHUP) read_title(); if ((pfd[FD_ARL].revents & POLLIN) && arl_handle(&arl)) { img.autoreload_pending = true; @@ -835,7 +840,7 @@ static void run(void) } } while (discard); - switch (ev.type) { /* handle events */ + switch (ev.type) { case ButtonPress: on_buttonpress(&ev.xbutton); break; diff --git a/nsxiv/nsxiv.h b/nsxiv/nsxiv.h index 3ffc113..ccd1796 100644 --- a/nsxiv/nsxiv.h +++ b/nsxiv/nsxiv.h @@ -101,7 +101,7 @@ typedef enum { typedef struct { const char *name; /* as given by user */ - const char *path; /* always absolute */ + const char *path; /* always absolute, result of realpath(3) */ fileflags_t flags; } fileinfo_t; @@ -180,7 +180,7 @@ typedef struct { unsigned int cnt; unsigned int sel; bool animate; - unsigned int framedelay; + int framedelay; int length; } multi_img_t; @@ -265,7 +265,7 @@ struct opt { /* window: */ bool fullscreen; bool hide_bar; - Window embed; /* unsigned long */ + Window embed; char *geometry; char *res_name; @@ -356,7 +356,7 @@ int r_closedir(r_dir_t*); char* r_readdir(r_dir_t*, bool); int r_mkdir(char*); void construct_argv(char**, unsigned int, ...); -pid_t spawn(int*, int*, char *const []); +pid_t spawn(int*, int*, int, char *const []); /* window.c */ diff --git a/nsxiv/thumbs.c b/nsxiv/thumbs.c index bd1e314..9909333 100644 --- a/nsxiv/thumbs.c +++ b/nsxiv/thumbs.c @@ -43,7 +43,7 @@ static char *tns_cache_filepath(const char *filepath) size_t len; char *cfile = NULL; - assert(*filepath == '/' && "filepath should be result of realpath(3)"); + assert(*filepath == '/' && "filepath must be result of realpath(3)"); if (strncmp(filepath, cache_dir, strlen(cache_dir)) != 0) { /* don't cache images inside the cache directory! */ @@ -181,7 +181,7 @@ void tns_init(tns_t *tns, fileinfo_t *tns_files, const int *cnt, int *sel, win_t memcpy(cache_tmpfile, cache_dir, len - 1); cache_tmpfile_base = cache_tmpfile + len - 1; } else { - error(0, 0, "Cache directory not found"); + error(EXIT_FAILURE, 0, "Cache directory not found"); } } @@ -198,6 +198,8 @@ CLEANUP void tns_free(tns_t *tns) free(cache_dir); cache_dir = NULL; + free(cache_tmpfile); + cache_tmpfile = cache_tmpfile_base = NULL; } static Imlib_Image tns_scale_down(Imlib_Image im, int dim) diff --git a/nsxiv/util.c b/nsxiv/util.c index c7fb210..e2fe8af 100644 --- a/nsxiv/util.c +++ b/nsxiv/util.c @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -230,25 +231,27 @@ void construct_argv(char **argv, unsigned int len, ...) assert(argv[len - 1] == NULL && "argv should be NULL terminated"); } -static int mkspawn_pipe(posix_spawn_file_actions_t *fa, const char *cmd, int *pfd, int dupidx) +static int mkspawn_pipe(posix_spawn_file_actions_t *fa, const char *cmd, int *pfd, int dupidx, int pipeflags) { - int err; + int err = 0; if (pipe(pfd) < 0) { error(0, errno, "pipe: %s", cmd); return -1; } - err = posix_spawn_file_actions_adddup2(fa, pfd[dupidx], dupidx); + if (pipeflags && (fcntl(pfd[0], F_SETFL, pipeflags) < 0 || fcntl(pfd[1], F_SETFL, pipeflags) < 0)) + err = errno; + err = err ? err : posix_spawn_file_actions_adddup2(fa, pfd[dupidx], dupidx); err = err ? err : posix_spawn_file_actions_addclose(fa, pfd[0]); err = err ? err : posix_spawn_file_actions_addclose(fa, pfd[1]); if (err) { - error(0, err, "posix_spawn_file_actions: %s", cmd); + error(0, err, "mkspawn_pipe: %s", cmd); close(pfd[0]); close(pfd[1]); } return err ? -1 : 0; } -pid_t spawn(int *readfd, int *writefd, char *const argv[]) +pid_t spawn(int *readfd, int *writefd, int pipeflags, char *const argv[]) { pid_t pid = -1; const char *cmd; @@ -263,9 +266,9 @@ pid_t spawn(int *readfd, int *writefd, char *const argv[]) return pid; } - if (readfd != NULL && mkspawn_pipe(&fa, cmd, pfd_read, 1) < 0) + if (readfd != NULL && mkspawn_pipe(&fa, cmd, pfd_read, 1, pipeflags) < 0) goto err_destroy_fa; - if (writefd != NULL && mkspawn_pipe(&fa, cmd, pfd_write, 0) < 0) + if (writefd != NULL && mkspawn_pipe(&fa, cmd, pfd_write, 0, pipeflags) < 0) goto err_close_readfd; if ((err = posix_spawnp(&pid, cmd, &fa, NULL, argv, environ)) != 0) { diff --git a/nsxiv/window.c b/nsxiv/window.c index 387d789..3c8b3f0 100644 --- a/nsxiv/window.c +++ b/nsxiv/window.c @@ -470,17 +470,15 @@ static void win_draw_bar(win_t *win) XSetBackground(e->dpy, gc, win->bar_bg.pixel); if ((len = strlen(r->buf)) > 0) { - if ((tw = TEXTWIDTH(win, r->buf, len)) > w) { - XftDrawDestroy(d); - return; + if ((tw = TEXTWIDTH(win, r->buf, len)) <= w) { + x = win->w - tw - H_TEXT_PAD; + win_draw_text(win, d, &win->bar_fg, x, y, r->buf, len, tw); } - x = win->w - tw - H_TEXT_PAD; - w -= tw; - win_draw_text(win, d, &win->bar_fg, x, y, r->buf, len, tw); + /* remaining width, also keeping gap between left and right parts */ + w -= tw + (2 * H_TEXT_PAD); } - if ((len = strlen(l->buf)) > 0) { + if ((len = strlen(l->buf)) > 0 && w > 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); diff --git a/slstatus/components/battery.o b/slstatus/components/battery.o deleted file mode 100644 index 1a06144d9baa348a6a8b5e01a8a5e2331fe342e1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4568 zcmb_eU2GIp6u!G{X^XhKAZU{sGU~1rgze6jLh*riDbOJg)vWvuclbL(& zcfRx8Gw0s9GyB%W*Lpo3#+!$&WYZ&#GIsp&X}irf+t_RtV6m=s)?GOt+qBNQqF9q% ziuH|R-RV@U-xTZjvp`_6jW>`#oZnY3=i}DRxOLsefx;d03JcCw0%sb^T`4@tp}6%k z5lyfB<5tDGx@|{ndu+#fm`Ki_L2*ZL|F3m0pE9yH7@&ZmN;zLxBaPUCtg=O!wZBkzL6c#=@$JBsy}Py&fcAn_7Z%lVu8K*Gs&ZZTJf09ClAjKqTy z)e-frYd1porlyqPym=m?tm{}b$qppZ!H)RdD; zO;Lm=>woWM@G3`E2Wwz<|Dl*Ynj2JxFAr8vD*i=dg?Wl~>ELyba_Od0dkLX)lm5+l zU^|2hNEkaf0fb+a+A$Se9$Awm04V_(`YovHGof}*z$xY#CSeBxZXj7ym(j;xuwYQQ+GLx26 zHM)F7?=p4S(&lB+zDRRKUZKgoaurQY-QtIRVP@YK($t~mzerGP(8zP;G5@&!h`9lpAw6&*h5aAk+D z;b7HzU&On?*Ra|r#e8)@Smmp!1L`J<+lu{bzLS!--B$x9`m%^Y`v`Bg?|s`BgyB)d zpq;{GW4^#a?-t*vRB^)N3&d=a?Ja%7kV$H0Wz6ao7gX;fiXujsN3 ztc8coD1woq#aM+4=kT+(flqyZYp{nkO!R~Shu83d)=~y<1$+)<#Pham4OqMkzq1U! zjdXs19-F-`&?n(4l@G2T&if9P&R#3PSWm(S`)m4A8YyBALcx z#%UqyanIu({~JzfY%9y)uek7;Eo9XEb}_=us8x8r1p^L|1&=Lc#0nTtOQY@X-& zGW?4!KK}A>{!apbA&n*cQhOv3s4?y^~MmJ9gjgg+zT6NIl6aGs|^xVTS7 z3CFG)F1{b`xo}()j?b@fCgOQk({qLhM}7A`ci7H%41Ihb@^!{=#AlNZKf5^2>xSPT zY#hhGLTr+KpT_wGo}`XpM)iF zvZ}jjyfd8(=yHvCsqYb)J^$Xyk2957Wte^WF<@H++IOZ}3E_WNJ`T2Xt zeZ2m>$Nv-i diff --git a/slstatus/components/cpu.o b/slstatus/components/cpu.o deleted file mode 100644 index 078c9585c6cb91237f20dddf73d4cd07af6f725f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3096 zcmb7GO>7%g5Ps_vV%p$@2vAUa*uw^uDqVZ+I3xujm&C-C0xB(mh#w`+dL0{V$Mvou z2~kKDBDJazIUx|2N?bT_pchnVRq}Tz6$j|ak%=X4japSIryMGUncW%3d87v>dT(aF znR)NcyxHe`79V=erznC+5wD0{jZq;+{JV0@6=R}R1Vm!tUWc)K1Cd{GN__E_=D&l| z#nqi#VuEQ0p59ZXptXHCmS*|G9L zvslIv!YN&{&IN5VnadU?M$K|*6amqB%vL*x(vKPqB8|M-F#IH_V=Gq zkDeVq8&`+2h4R!3su9t{x}k^Ui3doKF^9 zOVKKsV!T+&7M!%VGvmS1ToLuK^3FkU+ zYqLMs!B73kIOi3RaL&t+@Gjb~Pr|uwBZTukTI4^|;E!J;pZ_buF<-0^<0{BVcupKl zy(BQs`wHEj&O6C*;7-Zo8J0>`E~z`#lq2+1(n$(^+_r^YnnVTN4c(}#rtNeK-JHzl ztpfNLCLK$Mcl9{D=jKPGPZY{JJo4~yI@1t{t6LfPij#THmQVZtxe6gz68Xi70fuy) z>g8#>?>y^=LBLwZ7$ANXL7+QSOzaa}iXZF_Gy**j199x(MtUgi%QhLt{=hZmc)r9U z2NG8$-2ffe3`;o2XC$2WXC4DP%I%V0hVrH|)UB*Df1Tp_y<*24#q+zyIPc5+ZHi|* z^EHZRojJ#`j?X;4@v{3(0_1b?{c-#p2)L#kzfHgxI}(@Urvb-W#K_LNnc> zSPBK$8#>U7p<09t9ETOF{oB~Lc79~{2({k4m`GdgTNCN7+5Y|kh5v&3FHf8KN+DM;O8I;~_YmmPz>p6iFWgy$6lfj76lu~{y*ecw+V(PNt*kaaI+A{i z&U1(p6WycFY$m&tTFkJNmC4R#(gYWFB<>OSx9Wji0*=4e zl^aU)M9t=bXa&HrJ2vo=?*sQ5WKg)l4d70rUKcKgxQ#$?e3IAvz;+%>d);mFO|P*j zykHAcsi4?+RPk)=>3<=HRp?DpkE2wShI&`Zr}jeGmqO$Dmdu~-hV{Pj{2F?a=6_cXM9rDz zPy3|u6`pi99rj9||C0=)QDn8-WUG9t8J|7*H{}n}e4`}G_Mj7}CFO5O@Odw?tHksF E0KO8n83m1M2}n$5)wjy1eK3~%FNq&$;(S3wHfL8&HUcX?0d7b z&mT@sznU@(kYd1T*svr8m>JyAOF}Jy2^pC6R{!x<{%m`zzy3z}R(J7fr|Yf$^fg%m zIo&^=^=>ca(w_OnQqKAc_V9wY@?HDVw-1*g_HLicS>CN~XRz;?FHp+WwUwU@@80j; zzBNK?ee=yOd1cqVdRx7|N3Xkm^WAUyX7)+iqS&X??VFc-ee*4W`sVTbV&{*tLFI_q z-5v1|6)EezxRg665{Po8m5oHPA78IU){)`p$VnKk()IzC&j9qsVQOOHq;+)m;_Rd~ zU2iUQj#*B@c5TOU^KKzOnlD(F!r*#6s<)a}rQ*IkRvoE~oG6aCwR|z}j0H~BajW_2 zs9UU!6~>%$u~;m;1N5%I!tof6sS6h&1xA;c>=A?QeaJ|jNhUCEyaq-mYYgolOn-vT z&mpHlGEP5dGuf5YRA$-eWU^;7X$#RS#8Ez@pY`?Br@{dd#b3oivQv&_v5I@8c|FHX znSxihPIR6D({5fJ5LMaC(!$)k8KNZ`3-*e7s*4BEIH2Sg=R!tj&8m*9 z=XT)7cHjl%lwal*wMBMn2meX-{{?3f88?GE*yZ@V*~5q1K46%q=whX5!Ee!U~kzVZ9mG5)!v!e?CzcqJWzl_R}*^sORVk`u9O1 zhX|rPj$=S*$=4TU9{GRkW3@Kc#gQIXY{~6|b{&R}IT8Fa2)%+H3 zjLu6#N{JQ8$JwrGT=wHf8khYDcC^@t{W8vRn9Orh3xj#zj)P7NcGZu4u**>dcGx0= z+#MTRm(5BPp8&hkYBYi-`Zrr~VB@{_683WC8r$zR7wmS}!WNDfF_5wcbJ+5JBjDZb zezGu>N~qr;C1fP?T;IgnxQC@ZgbKa$k_0^8A&AoBc>1nLP3|jzgS3e9JPzXOH%0t& z?YYEAbbK5c<=kz&!#Q1?RguqsN`{O8H&id zy`eBt<#Xlyy24b~!)ntj3o=fk8Y=Yt>FyQ-eP8-{KEPPYsmISSxPxn|=<$oVxLyCu zaYJ6^VCo;b6J)&XpY5JaA%FApXZXPMe@H3yc)Bz6-a!NW}T>d%XXT Kl~_{s`2PW~|CcEM diff --git a/slstatus/components/entropy.o b/slstatus/components/entropy.o deleted file mode 100644 index 6c360fc5fea6e2f4c86811f7b195281e4531168f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1720 zcmbtU&2G~`5FV$61}LHY2t|~Gg$fFYZfu8ygae9HN`q8!pi~7RR5^}ALlZl-ohX3= zhn^5Z;t_h}5ja5voOlurTsXl2Da<6ZspAGA!AR?w@0-8%?$|GuS8vA@1*9l&6ZVm0 z0rFG(c5z@9ApysswEHco_udopfgYvT_ZQ+{$$I%w@Abd5PLy5+3-N((K$mtuCqG?$ z+Jbb`bFH-B_0!w7=h*eMXF3(Pk+z+{bDP~wvu)Pu04qyNH`LVH`r5L(T60>R%c`Cc zhR{_*GcsCU%cze$yIu2ZuA^F(alKHpm&StZj z#{ko~LlxH{Tq}3iAqGm1I4KHac@}5bp**_>N@q@)pPh-nK_~I&*_R`IE1~Wr;>;XW zRBsx-_YZmirY4>|@wCfvIfn35D1Oizxzo7j#zP0_+#h)0;}({*py^wtQ-yNVt2sfH zYt67eiaIn3FdO0J8J=aHFzxV5S~kb!gZm8u-rxi-yMYG2DZQvSo8za+GhO3X$hRqrtJk? zOr?VM)@Ic+8}?`i|7EC{O|wAn8kQmhd7siJ=TPE#H0Z2~l3<@WFA xy)g_PaR0XiQ0V)nIg92~&FI}DHF}{71F-+#vLoUoT9fkM@&2EWB8Nsa|2HAIm9YQ- diff --git a/slstatus/components/hostname.o b/slstatus/components/hostname.o deleted file mode 100644 index 916948995dd923f67d513514ac73f2fb89c4ec92..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1712 zcmb_bO=}Zj5T0$Tjap;;I0zM45kyg6b~kQJdXPw|MJR%nB3eW?n@tni?AG0lCiURS zgEx=<43C~P=r7QdKf$Xv4?>+uW|Ga@fFKS`X6BjCyfgc1W$n(4VStbUw_t1u3SiBS z_3A*aLLQF8{f{sQ@QIKg^z-KP2NJKp_40Oq4BP$3U$%m@86|107kcer31D@3dC9!I zzOlYyuC>BW_ljv3m7{Fav7Dk+wu?-m;BNVx8yV|*Rm^tUALXO zRWCbkqf)HcHP>~EPpCN&4h1IiA>`G28!!V#pD-bVZTYWf*kSBF0Ha$l78mAoZ_!Ek zIrd#8c{^Wd<#UW26jW~xe(oRi0L)H(S;A?`Nji<@sZ9K!H)0FOg~`x?Mc6c)W}k)w zt%4Sze5iFAz{?>7UU+dRE#_G{iZVMT%|S$OdKmfl{*Y*HB0c{65FX%}Q-X_(QyuCh zbxg)*P!f+wCB1g))j%a_Jd{n*;$X*9Y0ynU)xFdMRZ9|3aYP1%+sX#zN9}eHVn`UJ zfx^?co}`|?&GuHkFkeAuM55ZH4LDd|C(=OF4c69vn2gbWI@!WzsM?M zmKL|i_CpPqJdt-fUkih;I>5H%iTe>Mbf*(HiS~C6(C3o(XE!`Ug=*^gId1f~{2k1l zw*PlrQ1(pwKY}d%1)tU%!=TLl`(z-|_f38De5$GM9wGR}`4`B@5W^$nBx=+0-}C%0 KN0CEC&;J8RyoJ{Q diff --git a/slstatus/components/ip.o b/slstatus/components/ip.o deleted file mode 100644 index 2b5aca567d7d54347a428ca514b41e107e2369ee..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2416 zcmbtUO>7fa5T11cxImYHkZMQ-doaj|cICBk8b=lK5=<5;AVi2Nk_On=>ttKJHtP*d zNYxf9SF%hb)MM2{±}1qlU9EeLKogVYn^M`@LE=ncu8S-%%QR`!LC{NBubZ@xF< z_vY<)*|8HLNdhhs9EG;WQGkCowe5^=WQm#-+o zs1HP|jm4c0$k7@;wpKFg{YLef_pMQ1iWt?Vw|?fHgruzYB&#*PlvW0axqL3VpY5>} z9;>~mJ@mcF^VP=uicuel6pp83^LLHtE>8zpsQa|LcRzW^-jLSp#UzTAp1n^Le*23}`!M(XyRFX;?W> z0sO(}$jGn~8=n}@Dr2@Yzi>#=l4?TLltes{j1R?=%9LwewJUbXQF6J&r|JA)ZtzHI zFj0u7;#%6$@>(Jv&krS1g>*8l&7@MP=;lC08nOzv9_W#!1tp5wCeW3Mj9e%LfBH^OE4arl(H8oq#9 zM?W+v$8=fImv8Q7P0`&N&@GfIB zx_BlVp#R^{`v3>k85F9s6TYVlexM8faTk233!d$QpF(^W*3awa=XsXlPf?R_9PF~1 z!-*P^H6?s)x{lbGQ1RScu?z**vUtp_X(GiBFyyaH}>^$1Oa03Wr|`29w` z_7?k|B+78g-@|NDhnY>iNO!>Frv!Y9fZGC2J;dX02sqst$Cm}1a&!DAhVy#1GyfMM zUaaT0KslRJmdK%SP1Qinm5N2n!4Rk9St@=KKB;(S?knccI`eATEtM_T zTSO{tXw6+LxcJH975_i2Ae~+tov|nx<~$ccwA(MUwa|}>dM49yH|8*bC<-Icosdbr zLK0~yIEb2Xu@`A68cakWN)V=ZOMAXAUt@bFP>aIz?-xO|d48@l42uWiMp(e-0i5%= zKFRojF!-4V1Qvqud0eM=DfTc?er18dy7>8149OK76dL5OGX5k IayEef0JnQG=l}o! diff --git a/slstatus/components/kernel_release.o b/slstatus/components/kernel_release.o deleted file mode 100644 index 7ebe3e090fc2265260efc87a841c9b6c20af4ade..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1744 zcmbtUPiqrV5T8w|jkOK6^iZh63iTi8V|UYyO%D<&H4%!4rHDu=o6U<2O*V0NqlpTV zgC{L`^yr81;LQd70DcBff?m7}b!PKk`m#+Cbl~mG?>GNm-VAxUzHuw1X&^;|8*qpu z3vf4mXcuF%2w9kca{uQ$j4$uMSep7y{Hv%pYet{QjIkO0m@n^tSbBp*%$iZmm-}BR z@pH#>ntT;51OTPAwN?G{=GNxAzESr&-7C78V-_=Y%dm3BijmVF`us^fsJA@bb*<}# zYTnH++j*;I*oIl)X4SN+Ms>xqYlU3Ftk|}l+op@4OyJS+oWN7Mvjr*8BI2ZI0?Xe% zFC5yld!Th^wZ-Yl%v*F4e^&Tzk}hT6r+e9qppGc2Hvzv6jyRA=k9}$4>6W81hj31b zk9#9`9?$G(XpAl$!(Tmyhdu6lys_i+26qC^+ynvfoZzYBdr)cnbuX;NeP-hC;C<=V zzYhkoAowZN%Id&5CH|xm&l2&I0^3SFak9QH_!Me7Lt#O$89EhULFfTx7yqfdzeZE`R-25 z#~mKt;J*wVvuS7OZB!`=Am=W96syW20@~}MN)i^2)D`?`)RZe1SI+CA;MJK?N}oPs zB-x+#i)#LBzKOY1)54>Q>`(ioitI0S5uIckY7pA51-_r)WuDZx(JyT^^qUG4I~n@` zeYB?|JBc{{&qJNOmwbP8#qt=xR5O{sAR7HGzk#{q=KoO?lyj!}pTZ;iOMYB$41==h q9}z&A#zTFQ`BXDGd!!&E`Y#huM3fyeXV4m#|5fBaA4U$0Wd0v4W}9pP diff --git a/slstatus/components/keyboard_indicators.o b/slstatus/components/keyboard_indicators.o deleted file mode 100644 index 1a9c512bd82384d9bc864240c0695d9a054cb141..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2392 zcmbuA-EZ4e6u__3t{q!(I)uce^598;iWruikdll7agw&K*731YR#Zyl*zOw5wS#@b z8hD^m)v2MtK*0aNGkZZoDv=7C#0yV|2_E1HHVp*4^l4K#$GLZNt@s6wbbZhHosWCs zd$05E)ZBDR5C|86JV)+XoDy>V&^^5vszoA_`-yf=dsSP|UYTv*R=W%H`sN?{4Rq`6 zJ$(bRtRLNKP&^N!)_4f6p zW$krsS$jjP?k&F9u-!^MXgEgelr(MB9ov$qCwYJ+tH%kMDVI-4m$4xbd|MI>+?JUa7D$Q+9b{YtX7jy#kU506&k|vMR2Ul>KKv0l=YT)VeET?; z#L>&Cl6d^Xfs!bFFjx}D-#;`hDwl>dF~2!n5jTX?4`RL|Dw;SB5fBL(CGjw;ku+f+ zgXEuXKmS1A6GzBE`0Ea4JOt(gk@&D@U{AmpJs28V`2_xK0)IJyR}=X81pZC}zns9y z1-n)A4Bx8OU8`;y)bj(`>_id>)0-- zR!!P!*j4H|-bLH5I-VI}%|?Txrg&laAw+ufd=Kqtr%7z3f!dyF$3(Qt=TSw zxE{4-xZ+O+)G#kF`@Gwf8$Nt)eA4gX$mV#y1H9k<7x5zk!uJ{XAMZEM=e*zAnD-KED9`%9yNK(=^RZ@p?*Wl* c2E%`P1WZ^tZjxi5^~+ym{p0sND)Ib(0pmwTj{pDw diff --git a/slstatus/components/keymap.o b/slstatus/components/keymap.o deleted file mode 100644 index 704f26e63be517249a7d03a4be27486b347762ab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3680 zcmbtWU1%It6uz6ECTcoKo1&45%tI>ir{m71sY!*BNjJ$v*IG=|2HJEpyE|#O+1*)Z zXSdlRMhR7iwN`}Ui=Z!pzW5>(@gYXriaz)t6cmf(!3Qg`6cMa~xSlg}PjWNvJg5im zo^!wZopbL!bMLvkIGPx1ibNPmgzaY=Jwh3qy>r7J_RL|{#X6aGRIO`Av?=ZI)TF-j zvwj1|boZ)$Zl%2K6YQuf9`;ib!g`j6PPkWq;@qpdpDnj|F1Nfvz`D7cdfj)t=@0AY z5BDm|xVVidntK)Ixi(RY_eOR1mR>7%Z46GhpW_slIxof15hUT>9#!jZytl(+>F#Cy z+;yiCAIkN1JZGt2>a{&zAy0P`y*;{nTX&saKcHR%OLtdcxt=S;RrDIN>YwUMf3%dZ zz@Q(r{zcjHtI zm#X=cl`C=XqyquMxZaF%2`OwE0&9+y$KWFWr0K{8;Bo;5*u(qSE(m=fXO+wbTT3Ip zzBjXyF)J)vFdbG*vy@RX@dN)089#7fpWHV&H90CLvW4=(gR2&O|q0HX&-aP|*V{_4gs5)e-88w!PW(H#eb3^?@YHDC$pnrxjJo7TN zR%qh~r&tq zbHj?kShKgg%^p}rB5cb#D6d<{-@pmReQy`ydwT?IC$ugi3A!%?-yMSQ55b=Z!HxscUJb!t4#6*k;1@&icSCRn_d9PCl{DOyijm7^lqiRoSVPzu!!G=zV2CwA zyz`qbG%Go_W6h(=nFUmZbiT-v$+S}~n#oiW3JpsY?QFrBW7A`{3H4w;g_`Qp<~t7? z0omp&?>@DG{b${m`#Fy1t(n`Xc5xf;8XkG#KPupN2>2e3QylWgdxwH?aE#(iAqYbJ zNx#cZa2=etEZ}#6O>xe0oZ>9<{u=_nL*Ty|;D5mT?+5T}y#Eo`xSp-hXx^_mj%&f% zMDhbSkS{?a{;vYwDd1aq;R^Ea5pcY}6z3t1(|&24s=yc5`FMc;4PVEoz{j&e@ec|3 zb^%Wbc(;I`7I3UV6la0sw9fBf3}sQ^i|5K8#hT}zL;9;l<(BX^?oTz1@D7gm@IZuj za$M$k6KHJfqQD#M7%8UUwe$2TvTQSFD2}<{FePI+22)a{5>spoJ4ja*6}m|BF{Y%g zeBLYozhF700`Jvsc(Bv+ynnJ#R*E+KrLdhUcQj8W=WKke|F6gp0Jj=^8HNEvq4&V= z`CPJ5<2!+8a2T2>D?H#kJZX5ga312I32n(H2A&Y&3_VHOk*C7Dr18BaTcn-|CN$tr+&M7tT?p=ff%^y7Me8U3=fS}FgZ}Sv|5HTdI_Qt@ zd87QT@chv^!}EtVm;4EDG&fGwg+W1n=gGmE+$jGzO`}w`BN^mFU#);O;xZ^ zd=Ugcil0CO^}`hOMW2N_bJ@LKt}TcT%+1VielxS|Ecb3Ll_e82i@IP-XX1ivfenK1J?jlsOC zSl<1X-K)x=?g>Y1RcG0vsMV#z0*`s6K-64D878)*FRBtIxLsk<2ViM#ZkAwhKx?|Uk<}+dMk7{aVe@m z?_1}H8<#N*Xcxseh<;ODQd{BY&{C~_up- zL)2vb!@sPrW9@PK-&YOwo@xK|kJIxte%x%N!H$~Wp#X*cLo_E@Pd$^nM+k~){v-u4 UQEemS0(!^QYw%6P>^jN%KLnVlu>b%7 diff --git a/slstatus/components/netspeeds.o b/slstatus/components/netspeeds.o deleted file mode 100644 index 31bd049e86345280d7e9478e20167be594626b8f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2544 zcmc(h&x;#n7{{O4-P)>ch$2|5!dPgr#ZEGb+3xmGQupEP;Kq$ z2K22#f5spDa%L21`D(X*)IV=N>Hbt(-+|cmJ$U-xKcE>daOj6xbFeYZ)*sJmYmd`v zwd;@2|@3{@fNEiLzTr0BpW-G7hN5=jdu zPabpMTD-V;+CA5dyS+oMU-n9#@0Nb*-N9XIa;p{t=*;1oe zDf;t~U-wJ(VtuYuY0Q`B{pCufQocgiOLBQ&ix7dMqsjxaUChwC^@;v7^lWphhiH1@ z%>=hsGR~Y%S391=!sT)}9`6Ye{VLnwBEsKf@Uqo6T@SM(JopZ7k)zx2*e{Rja3}^my#YuD()oBSU0Gn!XR!C+fi~gSfxfwFRgT2 zK|GGvJ#I-m@nCs@$9Ol0UP~$Qy}^EuefteZEcWd0&7t^)qYmO_KW8nDoP%bL{egfz z&qL~*2V}|ieSe5kjvf-%QS&_PV|`Jlpp>i`(n^&8lOs%eCTBOXQR>z%WMl$5Z{54wlJNIvMH}v65&t@O0GE z5K3lT+tL&U~{)6;? zkMX|X{PBC0d^!I~z0t2{`p=nl>}G~_X7f=qd-jazj)7M&vBZ=ck(bz-l>fVV|1U<7 ILnE9253cY_H~;_u diff --git a/slstatus/components/num_files.o b/slstatus/components/num_files.o deleted file mode 100644 index 5879df8d4710bf1e9890ba034162f0e0237cae7c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2080 zcmbu8PiqrV5WpvCwXuJeXhj1R+)J%R`^avZw&_8WHnAxbsm7wxmYQrfHkfSU?nYZZ zSSShw1wVox!J{V)h~OviB=sVqco1)bLY>)tFWoN5MF(DH<~M)d=FNMLG7Fc2fdB{z zzy;X%1O<4}y>BNSGYJw5Kb{p3)D zy9dDbuRv=1$~U)oS7|!P>9MRdS5qr*YjxcymQ8tN*czDz z28_XQ5nyh1c3M80TgqkRg|gAu7?qV6Q<);GQ8gBwipJz+Q@>ZX$~8mQG<7mjoX{r5 z;}dEr8jmUoT`4MRFH4qByV>EsvcX4$Yya6fMv*cqVD`E}fHR_%NN7#^jo*M(*3l{~Zc4I5Z7Z|8v(EDM-fBZtxz zrU27w)v9h_iczz5hEHb9vh&&(+N4!iMtr zbT6r=ipwia?ws&Kw8j2HCpnAy@;-3?x{r%Gq33zMFAc^-f-m65H!)7{>A;;tKgtvR z-zCmpw7rW4rTXh{@%lxP$hE(|g1p`QLj+O8oN4~_oZzhTqtgfXyC|SzzrneP%f1!q%gBPV{aeMr5)+*%=~8N_rAu@ zAI?`6#u5n-Nx(@MdV&IE_6_ZFXqF)jkAu1KSLQnTKhVeMSFX)vQ-=-f=s(O_v*zXr9Jt14|4Ce^dGNM*cs-kmAI8+Jv#z()3arL)?ZD-( zwt9LTfd$`n zbiS4==8PHFaE!c@b4vMQZKg0|REx!8;VtSL>=V#%?8R~B+yxkeM4vE`1pCsfPjevg z{%ep}n@sGV*q8bggM>fNu~Vey(%O1D6=FvjZ%24(F>{+zJ#c4dR5&^E7YC3GcYl8c{S2Rs<%fGhY?8+`@ko7m z28bQnB|p#k-=Zc7&xAGc{2ihI7HjY=Pq*oNsfG;)TLm z`}Jl}3xR-|KeW0X*C8spf0A(=$6zV0fx@IRY~ z0xJJ}43G0`%rl0XhKQWA;L=~qoFKULk@TJ5(np|ou6lu0MIHE&UJ=W88$awo9tRrcR$c6EF-u>pgtSW1NM3U;dH zxw4ao(;Al3(b1X3rOeJbK39n;F6_qu-9=dvSbs$z$`%(qhBle<@MI{6@*)nxcwBBG&dN<-C^M4Zu(U$o|ml?|`c_*n+P+pJJ;45{aU%`mjgCsOQ z7Y-~inFf%(dE>ADn)s>5~mQZv>lXX>3sKaVPo^z}xOYTzH zmQ7P1O63R5!K=wZy`UylEoEtWP0y?OVLe$$B~n^0nM@|;fv!Ww?+|{Iw`U;=k%n+Z zc!z<{@A4G#NFvYfLS&^U(%aSE@fH^c5If_q0IZQ7m3rPpC#3jVEF;OU+oCloo{@S+ zr4B}Fp{Pz9{M>D}9BbN9fSAAggAvEjJt6S@Jt5YMU(Z3R@11Rd_qD(;x4`ul_)rTR zoT|NGmP;kW&MT(q1y2ET)dCb2Ezf1o0iGI;4X)=nX3?Ru2SQJb+k|unu-{+m?VsI1 zPBWbIqs%`i;D?z_N@F&?iFW*Wo@)Y5E#-KY;XJ>@{5t~wh``SYe6jALz^7b1f0g01 zZ{qK;bG=|Vam73`!->z&>O+cKD|to^6uinn7rEtF%ZB1vD;_9$!!tn1xh^P9nH-{P ziUtbx%(9VUmpx0t(YfM!hWUv3i*{A1I5^9WSHnV)VEp4&&unO0w{|n0bukrLQ zDJRXFD7-$MPZVCC>ohKst%@YHzcT-R2?{o8$<>((NI~(P|d2vi(2bV+KYz{x7k_+I|24 diff --git a/slstatus/components/separator.o b/slstatus/components/separator.o deleted file mode 100644 index eceb3266e3e3f535db8ef000ad11a05813a60f3d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1272 zcmbVLO-md>5Up8_ABlpBpkNN;DG9`8J~FH8AuO1UIfw^E5(uKRGrj9#c4nDr!}vSR^+OQ|-wnJV^me?^{anbey|R~QZjuDsjkKQB z-$eDG<3*m|kbde1sh92qQKu0${B{&Y;pw>dGzJ&_3Htuw3Dm&(O&pt}F&}SLFF4QTx;T*N9bL;_Vlz7y4| zX{UT-qP*^_xDBFI#W-GYrsPn8NMjX)XqP33B=7fShFq2_De!r=N);!U8h5iRF(~qZ zEYvlKLVk&byg2I=abI$?$Hxtn(i_cKC7K#n_t%)`!`nA8A#REZ9p71)p{;*`3v=j? z)xSn9)%4I!x~JFoOMjKFquWC`J47j1N&TbSJUYCpqjS+PH%ch z{|WcejGB5shoL^`x+dl^(mA<5^OJgyBwBwy0sv1j(u{09)wO3wl5?$JBVd@OD`pw9 PNqYL%$-3iEeQo_euTodJ diff --git a/slstatus/components/swap.o b/slstatus/components/swap.o deleted file mode 100644 index 86051d6b7e957e929660341728883652dde4acff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3344 zcmbVOU2Gdg5Z-gz#-!zHC?HD#bfPXbDqMZe4{=eeIC0yJaA-vm3M$1o=W}hvK8N#} zrVvC`*PtU9`hrvh4;7C*ARdqqLKH(()LeEab&R15c^((ELFh#wUqSjdWAh}cs1(NklD7bcE60-XzmIgyf>q^qP zX6LUpDjz>uU)(Jut>2xkHovt8ewk}Fn@ZzTEUgW!!Rnng(dzk}_5I-^@u%ZQ;?KlW zP`b-O<&x607qI%y^=8xhQfbsKRkq-U{O8CzD8d&%_t|+MI*1WrTAvQV24Fk5X8)?% zj@wC>lCYK9H|92KU8FmpYWNB|Rhw&M=-c#kaJD{M>7QhO+_Yq#6I+mWFE}7{9L2I9(X|^$*R&!d07-Z+XQBrpnwPIe+mPocV zuj$hE8^GVsM*R>9W3?ci+$9GBLshO$0QZlbs79Nn40XZrwQZy1B zh>S!Aq{D{xe7>A7>5{5OAC6^))#1UR;b=B86j5TDl2M|WNMKJ%9t30kTKCu2+omXxuU2O zqEv(d#803PGL5f<81Wqt{fJ{9p}6_juOHedEC)64U&0CgLvZQq$ZyR~l%9?^4Iw>t z^=^#7S)i6J(5?x1cfk{Ap=|^A(+S6#cEY!I!FP1Q2fEma7x`1YKYGPJuR_c4t(e-Ato^CL`i{9fkoW_lxNW{doadQj{!cDGe)Bv}A3HzHkH3^0?`JsA zvzNthb@6eG^9Nlx?wR9zT=*szzUab57ycQ;`Mg;eL;23d$3ElveLj2Gz8~Fr5?ye~ zp+nDO-?ydU!Fk`D^5DEb-u2+T4?gnXybp+6K3+7_v!G4G(K&7zS|Kf)+JZ^sOxjEn zdA3|8vQa_@>58lnSuGWdnhq4bWNI?}1UytW)9M`akLnc}e#GGGH;+RoCe(7!An79i z5ZStJR!IZ-*e#F!spL(fN4HI*Q0==&F>dRBUjn_4{?BL9>?_r z;M{goC%qf;#B(m*`*=@y%XN^&d)LM5&*Ps11Lya~pJ4G9Igx2^JoZFYKk=)f>D-^@4j_RUM4%q?6>83rgZ-~wz% z3I#|HZTp3;TYxb*2*vduqO(e=M@45v)w~8B| zWV>7QJtf=4^^fBpPTXw*%+Ji6H>Vbt7U#@`YS3(*GG$iSLYlT^XRT=~Yu*g~2i2%r z4@}Rq&*jTGFL&0-*%iyNWZsu$X_u|?wCz;#*}N<{j+0%cnZu|i>K@ejD@%|9qfM9+ zgJbp0M>%0Uyb4AuV@!;Wq+el@@ME02NOpG2d_0zBWVfMy!?4xaodFmcc*BI#DR;^t z43B8_-PwrIc``doyV1lSaESd{!w=oK8T!KOM$m{nH>g0V5mtk^(rY%tJ@=#4Rt|?5 zr@Nz5{_6B(it%KP^N|Xi57bqP1G=mOw;t*t09j3;k7B#C|IVQFdb&L@A0u zgmnt2TnY)otJi9NfF(ga_64r`OccA`J&x}LP0`y{VY?Mt56K0NV^-(ru0ppe3$)dE<i$*XeRQa2lAqy0f8(zrchLSD+)(YA_P-BR%~$xK*;obzp8uKxlu=ZgljKv+ fm|{;y>r}Kk8TZoFxA@vh|Lt diff --git a/slstatus/components/uptime.o b/slstatus/components/uptime.o deleted file mode 100644 index 1220785e8a7f2da9d746a5c48928dd5418afccb4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1872 zcmbtT&ubG=5S~q|ty)7A4~2^Ep_Te0&)tn%6BP-R+7+sZrHF{s&1TcYCY!js(NqQL z!9x(CN4|sCX`T@h=cTFP=mY>dfZ7bhB(d=)k<0`QA74-oBZAG&6T0AxR)a zg7dHy2^3&sV9U=3ZXS}b7mU^KqsV_dgqYF(@|Ct8cUF$C6Y!d%H&jpU7*8LLr-JQ% z|6AI4GC01TN@5YB8_$iOzt+!@*Zyd(=t(lI{DInk`Qh zVd8ePEaOrGn4O+JBTvpR%+JVk6{p!cDytc$F;&(SEu&| zSyQL4R@cnvoXB2G%uqGdMuB9Uk$hspnoP~AcJu^C4hi0vG}KycgsjNKUS z5AlOLAhr)R)lUtg!`tAK+u-SKaA-EDW6a_X^feMZr{Pu{zXbP8*MR~LLbd3v>Fs}S zcI6QIB=kL@5rvZh+U?g)^acNH2&WMh_$7{uI`j@C)vgKpPQ4L)nd1qxq&;EYO3gP5 zz&zjW+OqImyJ|AuZu!89rf&i(cpfmfP65$XrUJ9-wVLf9#i{!?!x2k+zG*G-6At=NDH* zkI>rS*fbgQ8J(30?bQRJ?WVP{;r@XSlmvfK=FS1{q|*0N0}(eR`GVx14yFcXhgK;Y z*FBVZwN6sU0Q=|@zYmTji0JJ+N#d1Z%EBSSQAHoEO&s==mKqgCy71?TM<1?_-jO)H zi+-{TZ*}1>6OaCjgfL!5w3=RElyOrwtF9C^SE_s|EpCKrIFXnkZj}v;HpD>zxwa_UMhCz&5 z>;>MoV}#yrC=AyL9buH3O<@Fe1dv;XC5&>tR`Yz4`1Q~;=##zC44v|G8E^V6qY=~_ zUJ&k4DH?iP8oXQ90pDbS#Lp5RC3vo5yi0lZ zRq044vV(SwIDG5s9Y&wDtWWNX&mS7t3wj_;))!^{7DS3A>$fS_Y5sYTWD79}%pd diff --git a/slstatus/components/volume.o b/slstatus/components/volume.o deleted file mode 100644 index 3e31f5341b001a7b2d530c63679f0676985c8723..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3440 zcmds(O>7%Q6vv+vLsLGS6p#oih?Pi4Qqh&yjzdxjWVbOfkd!ECN>C}mUT>0B>|JZU zP8~pys(@hG&M82geeV&tk-)n-fu+{k`3}Y#(-ZXCad=7Qy$dOwNMhlH<=q!OTOk zV5Ju<4|29+LEbjO%wkifz6f}h3HDstcEGLODafdWMr!vcWbHYFZV|dgp)ilJg?YE+ z!=jzFT=3Fa+l9RA*uLx0EBHUz$i97hwBE_7$)q-FJEd};W<>RfZfKEkBpMzJN3}zq zwP+V@*U?Nf^7v48z#Qn04Mb+cv9K{@8CfHe4QB@5U3Ip7GN#DnftgS@X7=P${m57cWrAsjh+3-ALPDk)b0&+oNO5jb-vv?9MX;j zM?${`TD}iyiBM-E)Uh|z#<9&B8ZQWctT*a!ZTJNPwAP+tYep;Fz6IWa5vF~Yr6CdM1vF8MzU{3pvOz;=#5;SfFpJCmraFaFdFESCoP?s>st>6XL zafSP=Qwl%AdR*bJvYuA>GV7NW{wC{rg}=jE%uCGkH1o0&{~qgQg}=}GxWYeRE$WH- zA2C0p#DBv2tir`U`&i*CtUp!w1=i;k{uS%0!mqH_xNX6ft_{z+%3!VTR(NkMf6y6NWgmV@z*>svbhF6=J)X>)<~oKw;Z z9v(xUzr=~w{LHME&RZMPxm8EQM0yA6i5*8qcCFrQ+$mPJohaz6ipvoFzX+l&bHd%| zliNlRt+U?1qu3Ic&p_(hr4B?8O~sEPqnfvxPv;ZWr2m_;iSbuuh`tzKv`J?F*&CF@ zKVk5o z$P=-%=+JqtKEKBK>b%7KMgHsPP)#*|ob$&;Ah&A%67ojtx5|NHpV9i!?}f-0ywTV+ t)L9;1;|C5QqyKDbKK*7jTB<7V|3U1ROAr&r^s78&rQ`PIQ`e;tV&=rs|hcl{*3JAaY03&EFJzu|Xh!N=w?cY8;Z`;wy zTlhe;zk;4-KX-X+Te#K96D0dl^=j1*>>a&`swiFNjM=46WK6TGU|3!4W>;~_D4ABq zGDwN!U{H`d+Rcv5q&&5PbWN3tIwc;?my8L+G&$wJ7I2ZzWimfAVE8v^Ewx-}tpq*Kog45juArqijdfD&@DpO7p4 zWN2Vuvm8l}qzC2Ue4#x3xU6<7F-4VQ(O7r1H`*=lEg7%n&3v&S>w0WcU$#f@*%ojUw5B69*@VnN1bdnK_|l>Pr}g75#lGl8e;q|`q;PyFqAb; zM|`ipKz!37-}+U{mcI?;Ucet_wsCasmqMrf!&3NUV4Eb*H6^7;rFpwllLK3PQY0zK zNhu7JehJQ31n4g@-;c0QN})Obvr@PcNJ$C*87T}v5}DqDQ#O%5>WvtI#ogR(4S+`@ z3D9iZZNbTX0>71+@1^}ccaveXn&Ivl)=?X-))AU3P%$380u1Nf6CSwgf%kaeTRiXq z4}7}^zS9FA@xb?a;1eFW1^8;nG|vk?4}cx<;LmyBSR)$clN`?H@`_IKStUx8;ek!q z^ip&T3WQD!voKZ47p$C90m$J@sX%fE3=2wvK2bCcVp=7Aa*B+XbEv`(y9uK}#>Vn+ zwfp+UOjFMka%7wZ!YRj~rsT8i>O1!xR!9gx)GI(2&q_PBIvC!)f1t*rC=BO(e&_K1 zpT^a{j9VzDmH$0*+^%^YOW$@c5n1kl3up_!9g%|1`rn zpRfNN7tZ(j9>d-H`q0HsvhgPZU)`493B8 z$M?I2U3J9o6YvKa&hx;^G3gZeSVMT6xQl-VY$(q#9N)HBg*bmmz?TX5E+PK?0zT)8 z|1Q{2P78eT9KJ8$Yk|k-{n!=fER90Qd4VrJm#Yj%3_gYy<(j~M08k$Px+^}f4?hTe zG5)Utj+PSiOGO5ODnZuvmX9< zClc@%WjP*JkQz%e-bwW3bux@bkjLPUxcDp(-{qPYF%w43D98rpzem7O<@56X zMFA736?a0Ik^6CO4itP;?sT7E{_b_T_wy$BVobOHIp%*9Y@)dRXTaF#{9M5c3c}~d z^Merg=jW%<-00WK5}aTQ!`hF&Zhx$WjZ!tuF2qT&i{j27z6%=p-(u@OAv%NZ_Wu`Z CC1E81 diff --git a/st-flexipatch/.gitignore b/st-flexipatch/.gitignore deleted file mode 100644 index 2bfe577..0000000 --- a/st-flexipatch/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -*.o -config.h -patches.h -st diff --git a/st-flexipatch/Makefile b/st-flexipatch/Makefile index dc0a906..2b3859a 100644 --- a/st-flexipatch/Makefile +++ b/st-flexipatch/Makefile @@ -7,13 +7,7 @@ include config.mk SRC = st.c x.c $(LIGATURES_C) $(SIXEL_C) OBJ = $(SRC:.c=.o) -all: options st - -options: - @echo st build options: - @echo "CFLAGS = $(STCFLAGS)" - @echo "LDFLAGS = $(STLDFLAGS)" - @echo "CC = $(CC)" +all: st config.h: cp config.def.h config.h @@ -60,4 +54,4 @@ uninstall: rm -f $(DESTDIR)$(MANPREFIX)/man1/st.1 rm -f $(DESTDIR)$(PREFIX)/share/applications/st.desktop # desktop-entry patch -.PHONY: all options clean dist install uninstall +.PHONY: all clean dist install uninstall diff --git a/st-flexipatch/README.md b/st-flexipatch/README.md index 62912e5..67cce1e 100644 --- a/st-flexipatch/README.md +++ b/st-flexipatch/README.md @@ -1,4 +1,4 @@ -Similar to [dwm-flexipatch](https://github.com/bakkeby/dwm-flexipatch) this st 0.9 (3a6d6d7, 2023-06-25) project has a different take on st patching. It uses preprocessor directives to decide whether or not to include a patch during build time. Essentially this means that this build, for better or worse, contains both the patched _and_ the original code. The aim being that you can select which patches to include and the build will contain that code and nothing more. +Similar to [dwm-flexipatch](https://github.com/bakkeby/dwm-flexipatch) this st 0.9.2 (5dbcca4, 2024-05-01) project has a different take on st patching. It uses preprocessor directives to decide whether or not to include a patch during build time. Essentially this means that this build, for better or worse, contains both the patched _and_ the original code. The aim being that you can select which patches to include and the build will contain that code and nothing more. For example to include the `alpha` patch then you would only need to flip this setting from 0 to 1 in [patches.h](https://github.com/bakkeby/st-flexipatch/blob/master/patches.def.h): ```c @@ -15,6 +15,12 @@ Refer to [https://st.suckless.org/](https://st.suckless.org/) for details on the ### Changelog: +2024-05-31 - Added the anygeometry patch + +2024-03-13 - Added the reflow patch and upgraded the netwmicon patch + +2024-03-07 - Improved sixel support, removed VIM browse patch + 2022-10-24 - Added the fullscreen patch 2022-08-28 - Added the use XftFontMatch patch @@ -98,6 +104,10 @@ Refer to [https://st.suckless.org/](https://st.suckless.org/) for details on the - allows the user to specify two distinct opacity values or background colors in order to easily differentiate between focused and unfocused terminal windows + - [anygeometry](https://st.suckless.org/patches/anygeometry/) + - allows st to start at any pixel size using the \-G command line option (if floating) + - can be combined with the anysize patch to resize to any pixel size + - [anysize](https://st.suckless.org/patches/anysize/) - allows st to reize to any pixel size rather than snapping to character width / height @@ -206,7 +216,9 @@ Refer to [https://st.suckless.org/](https://st.suckless.org/) for details on the - makes st ignore terminal color attributes to make for a monochrome look - [netwmicon](https://st.suckless.org/patches/netwmicon/) - - this patch sets the \_NET\_WM\_ICON X property with a hardcoded icon for st + - sets the \_NET\_WM\_ICON X property with a .png file + - or alternatively sets the \_NET\_WM\_ICON X property with a farbfeld (.ff) file + - or alternatively sets the \_NET\_WM\_ICON X property with a hardcoded icon - [newterm](https://st.suckless.org/patches/newterm/) - allows you to spawn a new st terminal using Ctrl-Shift-Return @@ -229,6 +241,10 @@ Refer to [https://st.suckless.org/](https://st.suckless.org/) for details on the ~and 07 in order to facilitate the use of theme setting scripts like~ [~theme.sh~](https://github.com/lemnos/theme.sh) ~which expect these colours to be distinct~ + - reflow + - allows st to be resized without cutting off text when the terminal window is made larger again + - text wraps when the terminal window is made smaller + - [relativeborder](https://st.suckless.org/patches/relativeborder/) - allows you to specify a border that is relative in size to the width of a cell in the terminal @@ -278,11 +294,16 @@ Refer to [https://st.suckless.org/](https://st.suckless.org/) for details on the - [vertcenter](https://st.suckless.org/patches/vertcenter/) - vertically center lines in the space available if you have set a larger chscale in config.h - - [vim-browse](https://st.suckless.org/patches/vim_browse/) - - the vim-browse patch offers the possibility to move through the terminal history-buffer, - search for strings using VIM-like motions, operations and quantifiers - - it overlays the screen with highlighted search results and displays the current operation - / motions / search string in the bottom right corner + - [~vim-browse~](https://st.suckless.org/patches/vim_browse/) + - ~the vim-browse patch offers the possibility to move through the terminal history-buffer,~ + ~search for strings using VIM-like motions, operations and quantifiers~ + - ~it overlays the screen with highlighted search results and displays the current operation~ + ~/ motions / search string in the bottom right corner~ + - the VIM browse patch was removed due to sheer complexity and it being incompatible with a + significant number of other patches + - if you want to try this patch out then the recommendation is to play around with the + author's own build of st where this is properly implemented with history buffer (scrollback) + - https://github.com/juliusHuelsmann/st - [visualbell](https://st.suckless.org/patches/visualbell/) - adds visual indicators for the terminal bell event diff --git a/st-flexipatch/] b/st-flexipatch/] deleted file mode 100644 index 366628d..0000000 --- a/st-flexipatch/] +++ /dev/null @@ -1,763 +0,0 @@ -/* See LICENSE file for copyright and license details. */ - -/* - * appearance - * - * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html - */ -static char *font = "Hack Nerd Font:pixelsize=14:antialias=true:autohint=true"; -#if FONT2_PATCH -/* Spare fonts */ -static char *font2[] = { -/* "Inconsolata for Powerline:pixelsize=12:antialias=true:autohint=true", */ -/* "Hack Nerd Font Mono:pixelsize=11:antialias=true:autohint=true", */ -}; -#endif // FONT2_PATCH - -#if BACKGROUND_IMAGE_PATCH -/* - * background image - * expects farbfeld format - * pseudo transparency fixes coordinates to the screen origin - */ -static const char *bgfile = "/path/to/image.ff"; -static const int pseudotransparency = 0; -#endif // BACKGROUND_IMAGE_PATCH - -#if RELATIVEBORDER_PATCH -/* borderperc: percentage of cell width to use as a border - * 0 = no border, 100 = border width is same as cell width */ -int borderperc = 20; -#else -static int borderpx = 2; -#endif // RELATIVEBORDER_PATCH - -#if OPENURLONCLICK_PATCH -/* modkey options: ControlMask, ShiftMask or XK_ANY_MOD */ -static uint url_opener_modkey = XK_ANY_MOD; -static char *url_opener = "xdg-open"; -#endif // OPENURLONCLICK_PATCH - -/* - * 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 */ -#if SIXEL_PATCH -char *vtiden = "\033[?12;4c"; -#else -char *vtiden = "\033[?6c"; -#endif - -/* 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; - -#if SYNC_PATCH -/* - * Synchronized-Update timeout in ms - * https://gitlab.com/gnachman/iterm2/-/wikis/synchronized-updates-spec - */ -static uint su_timeout = 200; -#endif // SYNC_PATCH - -/* - * 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; - -#if BOXDRAW_PATCH -/* - * 1: render most of the lines/blocks characters without using the font for - * perfect alignment between cells (U2500 - U259F except dashes/diagonals). - * Bold affects lines thickness if boxdraw_bold is not 0. Italic is ignored. - * 0: disable (render all U25XX glyphs normally from the font). - */ -const int boxdraw = 0; -const int boxdraw_bold = 0; - -/* braille (U28XX): 1: render as adjacent "pixels", 0: use font */ -const int boxdraw_braille = 0; -#endif // BOXDRAW_PATCH - -/* - * 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; - -#if ALPHA_PATCH -/* bg opacity */ -float alpha = 0.8; -#if ALPHA_GRADIENT_PATCH -float grad_alpha = 0.54; //alpha value that'll change -float stat_alpha = 0.46; //constant alpha value that'll get added to grad_alpha -#endif // ALPHA_GRADIENT_PATCH -#if ALPHA_FOCUS_HIGHLIGHT_PATCH -float alphaUnfocused = 0.6; -#endif // ALPHA_FOCUS_HIGHLIGHT_PATCH -#endif // ALPHA_PATCH - -/* 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 */ - "#add8e6", /* 256 -> cursor */ - "#555555", /* 257 -> rev cursor*/ - "#000000", /* 258 -> bg */ - "#e5e5e5", /* 259 -> fg */ -}; - - -/* - * Default colors (colorname index) - * foreground, background, cursor, reverse cursor - */ -#if ALPHA_PATCH && ALPHA_FOCUS_HIGHLIGHT_PATCH -unsigned int defaultbg = 0; -unsigned int bg = 17, bgUnfocused = 16; -#else -unsigned int defaultbg = 258; -#endif // ALPHA_FOCUS_HIGHLIGHT_PATCH -unsigned int defaultfg = 259; -unsigned int defaultcs = 256; -unsigned int defaultrcs = 257; - -#if VIM_BROWSE_PATCH -unsigned int const currentBg = 6, buffSize = 2048; -/// Enable double / triple click yanking / selection of word / line. -int const mouseYank = 1, mouseSelect = 0; -/// [Vim Browse] Colors for search results currently on screen. -unsigned int const highlightBg = 160, highlightFg = 15; -char const wDelS[] = "!\"#$%&'()*+,-./:;<=>?@[\\]^`{|}~", wDelL[] = " \t"; -char *nmKeys [] = { ///< Shortcusts executed in normal mode - "R/Building\nN", "r/Building\n", "X/juli@machine\nN", "x/juli@machine\n", - "Q?[Leaving vim, starting execution]\n","F/: error:\nN", "f/: error:\n", "DQf" -}; -unsigned int const amountNmKeys = sizeof(nmKeys) / sizeof(*nmKeys); -/// Style of the {command, search} string shown in the right corner (y,v,V,/) -Glyph styleSearch = {' ', ATTR_ITALIC | ATTR_BOLD_FAINT, 7, 16}; -Glyph style[] = {{' ',ATTR_ITALIC|ATTR_FAINT,15,16}, {' ',ATTR_ITALIC,232,11}, - {' ', ATTR_ITALIC, 232, 4}, {' ', ATTR_ITALIC, 232, 12}}; -#endif // VIM_BROWSE_PATCH - -#if BLINKING_CURSOR_PATCH -/* - * https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h4-Functions-using-CSI-_-ordered-by-the-final-character-lparen-s-rparen:CSI-Ps-SP-q.1D81 - * Default style of cursor - * 0: Blinking block - * 1: Blinking block (default) - * 2: Steady block ("â–ˆ") - * 3: Blinking underline - * 4: Steady underline ("_") - * 5: Blinking bar - * 6: Steady bar ("|") - * 7: Blinking st cursor - * 8: Steady st cursor - */ -static unsigned int cursorstyle = 1; -static Rune stcursor = 0x2603; /* snowman (U+2603) */ -#else -/* - * Default shape of cursor - * 2: Block ("█") - * 4: Underline ("_") - * 6: Bar ("|") - * 7: Snowman ("☃") - */ -static unsigned int cursorshape = 2; -#endif // BLINKING_CURSOR_PATCH - -/* - * Default columns and rows numbers - */ - -static unsigned int cols = 80; -static unsigned int rows = 24; - -#if THEMED_CURSOR_PATCH -/* - * Default shape of the mouse cursor - */ -static char* mouseshape = "xterm"; -#else -/* - * Default colour and shape of the mouse cursor - */ -static unsigned int mouseshape = XC_xterm; -static unsigned int mousefg = 7; -static unsigned int mousebg = 0; -#endif // THEMED_CURSOR_PATCH - -/* - * Color used to display font attributes when fontconfig selected a font which - * doesn't match the ones requested. - */ -static unsigned int defaultattr = 11; - -#if XRESOURCES_PATCH -/* - * Xresources preferences to load at startup - */ -ResourcePref resources[] = { - { "font", STRING, &font }, - { "color0", STRING, &colorname[0] }, - { "color1", STRING, &colorname[1] }, - { "color2", STRING, &colorname[2] }, - { "color3", STRING, &colorname[3] }, - { "color4", STRING, &colorname[4] }, - { "color5", STRING, &colorname[5] }, - { "color6", STRING, &colorname[6] }, - { "color7", STRING, &colorname[7] }, - { "color8", STRING, &colorname[8] }, - { "color9", STRING, &colorname[9] }, - { "color10", STRING, &colorname[10] }, - { "color11", STRING, &colorname[11] }, - { "color12", STRING, &colorname[12] }, - { "color13", STRING, &colorname[13] }, - { "color14", STRING, &colorname[14] }, - { "color15", STRING, &colorname[15] }, - { "background", STRING, &colorname[258] }, - { "foreground", STRING, &colorname[259] }, - { "cursorColor", STRING, &colorname[256] }, - { "termname", STRING, &termname }, - { "shell", STRING, &shell }, - { "minlatency", INTEGER, &minlatency }, - { "maxlatency", INTEGER, &maxlatency }, - { "blinktimeout", INTEGER, &blinktimeout }, - { "bellvolume", INTEGER, &bellvolume }, - { "tabspaces", INTEGER, &tabspaces }, - #if RELATIVEBORDER_PATCH - { "borderperc", INTEGER, &borderperc }, - #else - { "borderpx", INTEGER, &borderpx }, - #endif // RELATIVEBORDER_PATCH - { "cwscale", FLOAT, &cwscale }, - { "chscale", FLOAT, &chscale }, - #if ALPHA_PATCH - { "alpha", FLOAT, &alpha }, - #endif // ALPHA_PATCH - #if ALPHA_FOCUS_HIGHLIGHT_PATCH - { "alphaUnfocused",FLOAT, &alphaUnfocused }, - #endif // ALPHA_FOCUS_HIGHLIGHT_PATCH -}; -#endif // XRESOURCES_PATCH - -/* - * 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 screen */ - #if CLIPBOARD_PATCH - { XK_ANY_MOD, Button2, clippaste, {.i = 0}, 1 }, - #else - { XK_ANY_MOD, Button2, selpaste, {.i = 0}, 1 }, - #endif // CLIPBOARD_PATCH - #if SCROLLBACK_MOUSE_PATCH - { ShiftMask, Button4, kscrollup, {.i = 1}, 0, S_PRI}, - { ShiftMask, Button5, kscrolldown, {.i = 1}, 0, S_PRI}, - #elif UNIVERSCROLL_PATCH - { XK_ANY_MOD, Button4, ttysend, {.s = "\033[5;2~"}, 0, S_PRI }, - { XK_ANY_MOD, Button5, ttysend, {.s = "\033[6;2~"}, 0, S_PRI }, - #else - { ShiftMask, Button4, ttysend, {.s = "\033[5;2~"} }, - { ShiftMask, Button5, ttysend, {.s = "\033[6;2~"} }, - #endif // SCROLLBACK_MOUSE_PATCH - #if SCROLLBACK_MOUSE_ALTSCREEN_PATCH - { XK_NO_MOD, Button4, kscrollup, {.i = 1}, 0, S_PRI }, - { XK_NO_MOD, Button5, kscrolldown, {.i = 1}, 0, S_PRI }, - { XK_ANY_MOD, Button4, ttysend, {.s = "\031"}, 0, S_ALT }, - { XK_ANY_MOD, Button5, ttysend, {.s = "\005"}, 0, S_ALT }, - #else - { XK_ANY_MOD, Button4, ttysend, {.s = "\031"} }, - { XK_ANY_MOD, Button5, ttysend, {.s = "\005"} }, - #endif // SCROLLBACK_MOUSE_ALTSCREEN_PATCH -}; - -/* Internal keyboard shortcuts. */ -#define MODKEY Mod1Mask -#define TERMMOD (ControlMask|ShiftMask) - -#if EXTERNALPIPE_PATCH // example command -static char *openurlcmd[] = { "/bin/sh", "-c", - "xurls | dmenu -l 10 -w $WINDOWID | xargs -r open", - "externalpipe", NULL }; - -#if EXTERNALPIPEIN_PATCH // example command -static char *setbgcolorcmd[] = { "/bin/sh", "-c", - "printf '\033]11;#008000\007'", - "externalpipein", NULL }; -#endif // EXTERNALPIPEIN_PATCH -#endif // EXTERNALPIPE_PATCH - -static Shortcut shortcuts[] = { - /* mask keysym function argument screen */ - { 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} }, - #if ALPHA_PATCH - { TERMMOD, XK_O, changealpha, {.f = +0.05} }, - { TERMMOD, XK_P, changealpha, {.f = -0.05} }, - #if ALPHA_FOCUS_HIGHLIGHT_PATCH - //{ TERMMOD, XK_, changealphaunfocused, {.f = +0.05} }, - //{ TERMMOD, XK_, changealphaunfocused, {.f = -0.05} }, - #endif // ALPHA_FOCUS_HIGHLIGHT_PATCH - #endif // ALPHA_PATCH - #if FULLSCREEN_PATCH - { XK_NO_MOD, XK_F11, fullscreen, {.i = 0} }, - { MODKEY, XK_Return, fullscreen, {.i = 0} }, - #endif // FULLSCREEN_PATCH - #if SCROLLBACK_PATCH - { ShiftMask, XK_Page_Up, kscrollup, {.i = -1}, S_PRI }, - { ShiftMask, XK_Page_Down, kscrolldown, {.i = -1}, S_PRI }, - #endif // SCROLLBACK_PATCH - #if CLIPBOARD_PATCH - { TERMMOD, XK_Y, clippaste, {.i = 0} }, - { ShiftMask, XK_Insert, clippaste, {.i = 0} }, - #else - { TERMMOD, XK_Y, selpaste, {.i = 0} }, - { ShiftMask, XK_Insert, selpaste, {.i = 0} }, - #endif // CLIPBOARD_PATCH - { TERMMOD, XK_Num_Lock, numlock, {.i = 0} }, - #if COPYURL_PATCH || COPYURL_HIGHLIGHT_SELECTED_URLS_PATCH - { MODKEY|ShiftMask, XK_L, copyurl, {.i = 0} }, - #endif // COPYURL_PATCH - #if OPENCOPIED_PATCH - { MODKEY, XK_o, opencopied, {.v = "xdg-open"} }, - #endif // OPENCOPIED_PATCH - #if NEWTERM_PATCH - { TERMMOD, XK_Return, newterm, {.i = 0} }, - #endif // NEWTERM_PATCH - #if EXTERNALPIPE_PATCH - { TERMMOD, XK_U, externalpipe, { .v = openurlcmd } }, - #if EXTERNALPIPEIN_PATCH - { TERMMOD, XK_M, externalpipein, { .v = setbgcolorcmd } }, - #endif // EXTERNALPIPEIN_PATCH - #endif // EXTERNALPIPE_PATCH - #if KEYBOARDSELECT_PATCH - { TERMMOD, XK_Escape, keyboard_select, { 0 } }, - #endif // KEYBOARDSELECT_PATCH - #if ISO14755_PATCH - { TERMMOD, XK_I, iso14755, {.i = 0} }, - #endif // ISO14755_PATCH - #if INVERT_PATCH - { TERMMOD, XK_X, invert, { 0 } }, - #endif // INVERT_PATCH - #if VIM_BROWSE_PATCH - { MODKEY, XK_c, normalMode, {.i = 0} }, - #endif // VIM_BROWSE_PATCH -}; - -/* - * 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 !FIXKEYBOARDINPUT_PATCH -/* - * 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 }; -#endif // FIXKEYBOARDINPUT_PATCH - -/* - * 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; - -#if !FIXKEYBOARDINPUT_PATCH -/* - * 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}, - #if DELKEY_PATCH - { XK_KP_Delete, XK_ANY_MOD, "\033[3~", -1, 0}, - #else - { XK_KP_Delete, XK_ANY_MOD, "\033[P", -1, 0}, - #endif // DELKEY_PATCH - { 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}, - #if DELKEY_PATCH - { XK_Delete, XK_ANY_MOD, "\033[3~", -1, 0}, - #else - { XK_Delete, XK_ANY_MOD, "\033[P", -1, 0}, - #endif // DELKEY_PATCH - { 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}, -}; -#endif // FIXKEYBOARDINPUT_PATCH - -/* - * 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{|}~"; - -#if RIGHTCLICKTOPLUMB_PATCH -/* - * plumb_cmd is run on mouse button 3 click, with argument set to - * current selection and with cwd set to the cwd of the active shell - */ -static char *plumb_cmd = "plumb"; -#endif // RIGHTCLICKTOPLUMB_PATCH - -#if UNDERCURL_PATCH -/** - * Undercurl style. Set UNDERCURL_STYLE to one of the available styles. - * - * Curly: Dunno how to draw it *shrug* - * _ _ _ _ - * ( ) ( ) ( ) ( ) - * (_) (_) (_) (_) - * - * Spiky: - * /\ /\ /\ /\ - * \/ \/ \/ - * - * Capped: - * _ _ _ - * / \ / \ / \ - * \_/ \_/ - */ -// Available styles -#define UNDERCURL_CURLY 0 -#define UNDERCURL_SPIKY 1 -#define UNDERCURL_CAPPED 2 -// Active style -#define UNDERCURL_STYLE UNDERCURL_SPIKY -#endif // UNDERCURL_PATCH diff --git a/st-flexipatch/config.def.h b/st-flexipatch/config.def.h index 340cc3b..8cf0c54 100644 --- a/st-flexipatch/config.def.h +++ b/st-flexipatch/config.def.h @@ -54,7 +54,10 @@ char *stty_args = "stty raw pass8 nl -echo -iexten -cstopb 38400"; /* identification sequence returned in DA and DECID */ #if SIXEL_PATCH -char *vtiden = "\033[?12;4c"; +char *vtiden = "\033[?62;4c"; /* VT200 family (62) with sixel (4) */ + +/* sixel rgb byte order: LSBFirst or MSBFirst */ +int const sixelbyteorder = LSBFirst; #else char *vtiden = "\033[?6c"; #endif @@ -70,6 +73,12 @@ static float chscale = 1.0; */ wchar_t *worddelimiters = L" "; +#if KEYBOARDSELECT_PATCH && REFLOW_PATCH +/* Word delimiters for short and long jumps in the keyboard select patch */ +wchar_t *kbds_sdelim = L"!\"#$%&'()*+,-./:;<=>?@[\\]^`{|}~ "; +wchar_t *kbds_ldelim = L" "; +#endif // KEYBOARDSELECT_PATCH + /* selection timeouts (in milliseconds) */ static unsigned int doubleclicktimeout = 300; static unsigned int tripleclicktimeout = 600; @@ -109,6 +118,11 @@ static unsigned int blinktimeout = 800; */ static unsigned int cursorthickness = 2; +#if HIDECURSOR_PATCH +/* Hide the X cursor whenever a key is pressed. 0: off, 1: on */ +int hidecursor = 1; +#endif // HIDECURSOR_PATCH + #if BOXDRAW_PATCH /* * 1: render most of the lines/blocks characters without using the font for @@ -206,24 +220,18 @@ unsigned int defaultbg = 258; unsigned int defaultfg = 259; unsigned int defaultcs = 256; unsigned int defaultrcs = 257; - -#if VIM_BROWSE_PATCH -unsigned int const currentBg = 6, buffSize = 2048; -/// Enable double / triple click yanking / selection of word / line. -int const mouseYank = 1, mouseSelect = 0; -/// [Vim Browse] Colors for search results currently on screen. -unsigned int const highlightBg = 160, highlightFg = 15; -char const wDelS[] = "!\"#$%&'()*+,-./:;<=>?@[\\]^`{|}~", wDelL[] = " \t"; -char *nmKeys [] = { ///< Shortcusts executed in normal mode - "R/Building\nN", "r/Building\n", "X/juli@machine\nN", "x/juli@machine\n", - "Q?[Leaving vim, starting execution]\n","F/: error:\nN", "f/: error:\n", "DQf" -}; -unsigned int const amountNmKeys = sizeof(nmKeys) / sizeof(*nmKeys); -/// Style of the {command, search} string shown in the right corner (y,v,V,/) -Glyph styleSearch = {' ', ATTR_ITALIC | ATTR_BOLD_FAINT, 7, 16}; -Glyph style[] = {{' ',ATTR_ITALIC|ATTR_FAINT,15,16}, {' ',ATTR_ITALIC,232,11}, - {' ', ATTR_ITALIC, 232, 4}, {' ', ATTR_ITALIC, 232, 12}}; -#endif // VIM_BROWSE_PATCH +#if SELECTION_COLORS_PATCH +unsigned int selectionfg = 258; +unsigned int selectionbg = 259; +/* If 0 use selectionfg as foreground in order to have a uniform foreground-color */ +/* Else if 1 keep original foreground-color of each cell => more colors :) */ +static int ignoreselfg = 1; +#endif // SELECTION_COLORS_PATCH +#if KEYBOARDSELECT_PATCH && REFLOW_PATCH +/* Foreground and background color of search results */ +unsigned int highlightfg = 15; +unsigned int highlightbg = 160; +#endif // KEYBOARDSELECT_PATCH #if BLINKING_CURSOR_PATCH /* @@ -259,6 +267,16 @@ static unsigned int cursorshape = 2; static unsigned int cols = 80; static unsigned int rows = 24; +#if ANYGEOMETRY_PATCH +/* + * Whether to use pixel geometry or cell geometry + */ + +static Geometry geometry = CellGeometry; // or PixelGeometry to use the below size +static unsigned int width = 564; +static unsigned int height = 364; +#endif // ANYGEOMETRY_PATCH + #if THEMED_CURSOR_PATCH /* * Default shape of the mouse cursor @@ -324,6 +342,10 @@ ResourcePref resources[] = { #if ALPHA_FOCUS_HIGHLIGHT_PATCH { "alphaUnfocused",FLOAT, &alphaUnfocused }, #endif // ALPHA_FOCUS_HIGHLIGHT_PATCH + #if KEYBOARDSELECT_PATCH && REFLOW_PATCH + { "highlightfg", INTEGER, &highlightfg }, + { "highlightbg", INTEGER, &highlightbg }, + #endif // KEYBOARDSELECT_PATCH }; #endif // XRESOURCES_PATCH @@ -355,7 +377,7 @@ static MouseShortcut mshortcuts[] = { { ShiftMask, Button4, ttysend, {.s = "\033[5;2~"} }, { ShiftMask, Button5, ttysend, {.s = "\033[6;2~"} }, #endif // SCROLLBACK_MOUSE_PATCH - #if SCROLLBACK_MOUSE_ALTSCREEN_PATCH + #if SCROLLBACK_MOUSE_ALTSCREEN_PATCH || REFLOW_PATCH { XK_NO_MOD, Button4, kscrollup, {.i = 1}, 0, S_PRI }, { XK_NO_MOD, Button5, kscrolldown, {.i = 1}, 0, S_PRI }, { XK_ANY_MOD, Button4, ttysend, {.s = "\031"}, 0, S_ALT }, @@ -435,15 +457,16 @@ static Shortcut shortcuts[] = { #if KEYBOARDSELECT_PATCH { TERMMOD, XK_Escape, keyboard_select, { 0 } }, #endif // KEYBOARDSELECT_PATCH + #if KEYBOARDSELECT_PATCH && REFLOW_PATCH + { TERMMOD, XK_F, searchforward, { 0 } }, + { TERMMOD, XK_B, searchbackward, { 0 } }, + #endif // KEYBOARDSELECT_PATCH #if ISO14755_PATCH { TERMMOD, XK_I, iso14755, {.i = 0} }, #endif // ISO14755_PATCH #if INVERT_PATCH { TERMMOD, XK_X, invert, { 0 } }, #endif // INVERT_PATCH - #if VIM_BROWSE_PATCH - { MODKEY, XK_c, normalMode, {.i = 0} }, - #endif // VIM_BROWSE_PATCH }; /* diff --git a/st-flexipatch/config.mk b/st-flexipatch/config.mk index 9f56bb5..ecc3013 100644 --- a/st-flexipatch/config.mk +++ b/st-flexipatch/config.mk @@ -1,11 +1,13 @@ # st version -VERSION = 0.9 +VERSION = 0.9.2 # Customize below to fit your system # paths PREFIX = /usr/local MANPREFIX = $(PREFIX)/share/man +ICONPREFIX = $(PREFIX)/share/pixmaps +ICONNAME = st.png X11INC = /usr/X11R6/include X11LIB = /usr/X11R6/lib @@ -16,7 +18,7 @@ PKG_CONFIG = pkg-config XRENDER = -lXrender # Uncomment this for the themed cursor patch / THEMED_CURSOR_PATCH -#XCURSOR = -lXcursor +XCURSOR = -lXcursor # Uncomment the lines below for the ligatures patch / LIGATURES_PATCH LIGATURES_C = hb.c @@ -26,19 +28,24 @@ LIGATURES_LIBS = `$(PKG_CONFIG) --libs harfbuzz` # Uncomment this for the SIXEL patch / SIXEL_PATCH #SIXEL_C = sixel.c sixel_hls.c +#SIXEL_LIBS = `$(PKG_CONFIG) --libs imlib2` + +# Uncomment for the netwmicon patch / NETWMICON_PATCH +#NETWMICON_LIBS = `$(PKG_CONFIG) --libs gdlib` # includes and libs, uncomment harfbuzz for the ligatures patch INCS = -I$(X11INC) \ `$(PKG_CONFIG) --cflags fontconfig` \ `$(PKG_CONFIG) --cflags freetype2` \ $(LIGATURES_INC) -LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft ${XRENDER} ${XCURSOR}\ +LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft ${SIXEL_LIBS} ${XRENDER} ${XCURSOR}\ `$(PKG_CONFIG) --libs fontconfig` \ `$(PKG_CONFIG) --libs freetype2` \ - $(LIGATURES_LIBS) + $(LIGATURES_LIBS) \ + $(NETWMICON_LIBS) # flags -STCPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600 +STCPPFLAGS = -DVERSION=\"$(VERSION)\" -DICON=\"$(ICONPREFIX)/$(ICONNAME)\" -D_XOPEN_SOURCE=600 STCFLAGS = $(INCS) $(STCPPFLAGS) $(CPPFLAGS) $(CFLAGS) STLDFLAGS = $(LIBS) $(LDFLAGS) diff --git a/st-flexipatch/hb.c b/st-flexipatch/hb.c index db845e7..ae3dcc3 100644 --- a/st-flexipatch/hb.c +++ b/st-flexipatch/hb.c @@ -11,6 +11,7 @@ #include "hb.h" #define FEATURE(c1,c2,c3,c4) { .tag = HB_TAG(c1,c2,c3,c4), .value = 1, .start = HB_FEATURE_GLOBAL_START, .end = HB_FEATURE_GLOBAL_END } +#define BUFFER_STEP 256 hb_font_t *hbfindfont(XftFont *match); @@ -19,74 +20,109 @@ typedef struct { hb_font_t *font; } HbFontMatch; -static int hbfontslen = 0; -static HbFontMatch *hbfontcache = NULL; +typedef struct { + size_t capacity; + HbFontMatch *fonts; +} HbFontCache; + +static HbFontCache hbfontcache = { 0, NULL }; + +typedef struct { + size_t capacity; + Rune *runes; +} RuneBuffer; + +static RuneBuffer hbrunebuffer = { 0, NULL }; +static hb_buffer_t *hbbuffer; /* * Poplulate the array with a list of font features, wrapped in FEATURE macro, * e. g. * FEATURE('c', 'a', 'l', 't'), FEATURE('d', 'l', 'i', 'g') */ -hb_feature_t features[] = { 0 }; +hb_feature_t features[] = { }; void -hbunloadfonts() +hbcreatebuffer(void) { - for (int i = 0; i < hbfontslen; i++) { - hb_font_destroy(hbfontcache[i].font); - XftUnlockFace(hbfontcache[i].match); + hbbuffer = hb_buffer_create(); +} + +void +hbdestroybuffer(void) +{ + hb_buffer_destroy(hbbuffer); +} + +void +hbunloadfonts(void) +{ + for (int i = 0; i < hbfontcache.capacity; i++) { + hb_font_destroy(hbfontcache.fonts[i].font); + XftUnlockFace(hbfontcache.fonts[i].match); } - if (hbfontcache != NULL) { - free(hbfontcache); - hbfontcache = NULL; + if (hbfontcache.fonts != NULL) { + free(hbfontcache.fonts); + hbfontcache.fonts = NULL; } - hbfontslen = 0; + hbfontcache.capacity = 0; } hb_font_t * hbfindfont(XftFont *match) { - for (int i = 0; i < hbfontslen; i++) { - if (hbfontcache[i].match == match) - return hbfontcache[i].font; + for (int i = 0; i < hbfontcache.capacity; i++) { + if (hbfontcache.fonts[i].match == match) + return hbfontcache.fonts[i].font; } /* Font not found in cache, caching it now. */ - hbfontcache = realloc(hbfontcache, sizeof(HbFontMatch) * (hbfontslen + 1)); + hbfontcache.fonts = realloc(hbfontcache.fonts, sizeof(HbFontMatch) * (hbfontcache.capacity + 1)); FT_Face face = XftLockFace(match); hb_font_t *font = hb_ft_font_create(face, NULL); if (font == NULL) die("Failed to load Harfbuzz font."); - hbfontcache[hbfontslen].match = match; - hbfontcache[hbfontslen].font = font; - hbfontslen += 1; + hbfontcache.fonts[hbfontcache.capacity].match = match; + hbfontcache.fonts[hbfontcache.capacity].font = font; + hbfontcache.capacity += 1; return font; } -void hbtransform(HbTransformData *data, XftFont *xfont, const Glyph *glyphs, int start, int length) { - Rune rune; - ushort mode = USHRT_MAX; +void +hbtransform(HbTransformData *data, XftFont *xfont, const Glyph *glyphs, int start, int length) +{ + uint32_t mode; unsigned int glyph_count; - int i, end = start + length; + int rune_idx, glyph_idx, end = start + length; + hb_buffer_t *buffer = hbbuffer; hb_font_t *font = hbfindfont(xfont); - if (font == NULL) + if (font == NULL) { + data->count = 0; return; + } - hb_buffer_t *buffer = hb_buffer_create(); + hb_buffer_reset(buffer); hb_buffer_set_direction(buffer, HB_DIRECTION_LTR); + hb_buffer_set_cluster_level(buffer, HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS); + + /* Resize the buffer if required length is larger. */ + if (hbrunebuffer.capacity < length) { + hbrunebuffer.capacity = (length / BUFFER_STEP + 1) * BUFFER_STEP; + hbrunebuffer.runes = realloc(hbrunebuffer.runes, hbrunebuffer.capacity * sizeof(Rune)); + } /* Fill buffer with codepoints. */ - for (i = start; i < end; i++) { - rune = glyphs[i].u; - mode = glyphs[i].mode; + for (rune_idx = 0, glyph_idx = start; glyph_idx < end; glyph_idx++, rune_idx++) { + hbrunebuffer.runes[rune_idx] = glyphs[glyph_idx].u; + mode = glyphs[glyph_idx].mode; if (mode & ATTR_WDUMMY) - rune = 0x0020; - hb_buffer_add_codepoints(buffer, &rune, 1, 0, 1); + hbrunebuffer.runes[rune_idx] = 0x0020; } + hb_buffer_add_codepoints(buffer, hbrunebuffer.runes, length, 0, length); /* Shape the segment. */ hb_shape(font, buffer, features, sizeof(features)/sizeof(hb_feature_t)); @@ -95,14 +131,9 @@ void hbtransform(HbTransformData *data, XftFont *xfont, const Glyph *glyphs, int hb_glyph_info_t *info = hb_buffer_get_glyph_infos(buffer, &glyph_count); hb_glyph_position_t *pos = hb_buffer_get_glyph_positions(buffer, &glyph_count); - /** Fill the output. */ + /* Fill the output. */ data->buffer = buffer; data->glyphs = info; data->positions = pos; data->count = glyph_count; } - -void hbcleanup(HbTransformData *data) { - hb_buffer_destroy(data->buffer); - memset(data, 0, sizeof(HbTransformData)); -} diff --git a/st-flexipatch/hb.h b/st-flexipatch/hb.h index 3b0ef44..cb7ea48 100644 --- a/st-flexipatch/hb.h +++ b/st-flexipatch/hb.h @@ -9,6 +9,7 @@ typedef struct { unsigned int count; } HbTransformData; -void hbunloadfonts(); +void hbcreatebuffer(void); +void hbdestroybuffer(void); +void hbunloadfonts(void); void hbtransform(HbTransformData *, XftFont *, const Glyph *, int, int); -void hbcleanup(HbTransformData *); diff --git a/st-flexipatch/patch/externalpipe.c b/st-flexipatch/patch/externalpipe.c index 37d8848..7df5474 100644 --- a/st-flexipatch/patch/externalpipe.c +++ b/st-flexipatch/patch/externalpipe.c @@ -42,7 +42,11 @@ externalpipe(const Arg *arg) newline = 0; for (n = 0; n < term.row; n++) { bp = term.line[n]; + #if REFLOW_PATCH + lastpos = MIN(tlinelen(TLINE(n)) + 1, term.col) - 1; + #else lastpos = MIN(tlinelen(n) + 1, term.col) - 1; + #endif // REFLOW_PATCH if (lastpos < 0) break; end = &bp[lastpos + 1]; diff --git a/st-flexipatch/patch/keyboardselect_reflow.txt b/st-flexipatch/patch/keyboardselect_reflow.txt new file mode 100644 index 0000000..8dd6c49 --- /dev/null +++ b/st-flexipatch/patch/keyboardselect_reflow.txt @@ -0,0 +1,29 @@ +Shortcuts in keyboard selection mode: + +h, j, k, l: move cursor left/down/up/right (also with arrow keys) +H, M, L: move cursor to the top/middle/bottom of the screen +Home, End: move cursor to the top/bottom of the screen +Backspace or 0, $ or A: move cursor to the beginning/end of the line +^ or I: move cursor to the beginning of the indented line +!: move cursor to the middle of the row +_: move cursor to the right edge of the screen +*: move cursor to the center of the screen +w, W jump forward to the start of a word +e, E jump forward to the end of a word +b, B jump backward to the start of a word +g, G: go to the first/last line +z: center the screen on the cursor +PgUp or K, PgDown or J: scroll the page up/down +/, ?: activate input mode and search up/down +n, N: repeat last search and search forward/backward +f, F: jump forward/backward to the given character +t, T: jump forward/backward to before the given character +; or r repeat previous f, t, F or T movement and move forward +, or R repeat previous f, t, F or T movement and move backward +v: toggle selection mode +V: toggle line selection mode +s: toggle regular/rectangular selection type +y: yank (copy) selected text +0 - 9: set the quantifier +Return: quit keyboard_select, yank and keep the highlight of the selection +Escape, q: quit keyboard_select/exit input mode/exit selection mode/reset quantifier diff --git a/st-flexipatch/patch/keyboardselect_reflow_st.c b/st-flexipatch/patch/keyboardselect_reflow_st.c new file mode 100644 index 0000000..b532557 --- /dev/null +++ b/st-flexipatch/patch/keyboardselect_reflow_st.c @@ -0,0 +1,769 @@ +#include + +enum keyboardselect_mode { + KBDS_MODE_MOVE = 0, + KBDS_MODE_SELECT = 1<<1, + KBDS_MODE_LSELECT = 1<<2, + KBDS_MODE_FIND = 1<<3, + KBDS_MODE_SEARCH = 1<<4, +}; + +enum cursor_wrap { + KBDS_WRAP_NONE = 0, + KBDS_WRAP_LINE = 1<<0, + KBDS_WRAP_EDGE = 1<<1, +}; + +typedef struct { + int x; + int y; + Line line; + int len; +} KCursor; + +static int kbds_in_use, kbds_quant; +static int kbds_seltype = SEL_REGULAR; +static int kbds_mode, kbds_directsearch; +static int kbds_searchlen, kbds_searchdir, kbds_searchcase; +static int kbds_finddir, kbds_findtill; +static Glyph *kbds_searchstr; +static Rune kbds_findchar; +static KCursor kbds_c, kbds_oc; + +void +kbds_drawstatusbar(int y) +{ + static char *modes[] = { " MOVE ", "", " SELECT ", " RSELECT ", " LSELECT ", + " SEARCH FW ", " SEARCH BW ", " FIND FW ", " FIND BW " }; + static char quant[20] = { ' ' }; + static Glyph g; + int i, n, m; + int mlen, qlen; + + if (!kbds_in_use) + return; + + g.mode = ATTR_REVERSE; + g.fg = defaultfg; + g.bg = defaultbg; + + if (y == 0) { + if (kbds_issearchmode()) + m = 5 + (kbds_searchdir < 0 ? 1 : 0); + else if (kbds_mode & KBDS_MODE_FIND) + m = 7 + (kbds_finddir < 0 ? 1 : 0); + else if (kbds_mode & KBDS_MODE_SELECT) + m = 2 + (kbds_seltype == SEL_RECTANGULAR ? 1 : 0); + else + m = kbds_mode; + mlen = strlen(modes[m]); + qlen = kbds_quant ? snprintf(quant+1, sizeof quant-1, "%i", kbds_quant) + 1 : 0; + if (kbds_c.y != y || kbds_c.x < term.col - qlen - mlen) { + for (n = mlen, i = term.col-1; i >= 0 && n > 0; i--) { + g.u = modes[m][--n]; + xdrawglyph(g, i, y); + } + for (n = qlen; i >= 0 && n > 0; i--) { + g.u = quant[--n]; + xdrawglyph(g, i, y); + } + } + } + + if (y == term.row-1 && kbds_issearchmode()) { + for (g.u = ' ', i = 0; i < term.col; i++) + xdrawglyph(g, i, y); + g.u = (kbds_searchdir > 0) ? '/' : '?'; + xdrawglyph(g, 0, y); + for (i = 0; i < kbds_searchlen; i++) { + g.u = kbds_searchstr[i].u; + g.mode = kbds_searchstr[i].mode | ATTR_WIDE | ATTR_REVERSE; + if (g.u == ' ' || g.mode & ATTR_WDUMMY) + continue; + xdrawglyph(g, i + 1, y); + } + g.u = ' '; + g.mode = ATTR_NULL; + xdrawglyph(g, i + 1, y); + } +} + +void +kbds_pasteintosearch(const char *data, int len, int append) +{ + static char buf[BUFSIZ]; + static int buflen; + Rune u; + int l, n, charsize; + + if (!append) + buflen = 0; + + for (; len > 0; len -= l, data += l) { + l = MIN(sizeof(buf) - buflen, len); + memmove(buf + buflen, data, l); + buflen += l; + 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 (u > 0x1f && kbds_searchlen < term.col-2) { + kbds_searchstr[kbds_searchlen].u = u; + kbds_searchstr[kbds_searchlen++].mode = ATTR_NULL; + if (wcwidth(u) > 1) { + kbds_searchstr[kbds_searchlen-1].mode = ATTR_WIDE; + if (kbds_searchlen < term.col-2) { + kbds_searchstr[kbds_searchlen].u = 0; + kbds_searchstr[kbds_searchlen++].mode = ATTR_WDUMMY; + } + } + } + } + buflen -= n; + /* keep any incomplete UTF-8 byte sequence for the next call */ + if (buflen > 0) + memmove(buf, buf + n, buflen); + } + term.dirty[term.row-1] = 1; +} + +int +kbds_top(void) +{ + return IS_SET(MODE_ALTSCREEN) ? 0 : -term.histf + term.scr; +} + +int +kbds_bot(void) +{ + return IS_SET(MODE_ALTSCREEN) ? term.row-1 : term.row-1 + term.scr; +} + +int +kbds_iswrapped(KCursor *c) +{ + return c->len > 0 && (c->line[c->len-1].mode & ATTR_WRAP); +} + +int +kbds_isselectmode(void) +{ + return kbds_in_use && (kbds_mode & (KBDS_MODE_SELECT | KBDS_MODE_LSELECT)); +} + +int +kbds_issearchmode(void) +{ + return kbds_in_use && (kbds_mode & KBDS_MODE_SEARCH); +} + +void +kbds_setmode(int mode) +{ + kbds_mode = mode; + term.dirty[0] = 1; +} + +void +kbds_selecttext(void) +{ + if (kbds_isselectmode()) { + if (kbds_mode & KBDS_MODE_LSELECT) + selextend(term.col-1, kbds_c.y, SEL_RECTANGULAR, 0); + else + selextend(kbds_c.x, kbds_c.y, kbds_seltype, 0); + if (sel.mode == SEL_IDLE) + kbds_setmode(kbds_mode & ~(KBDS_MODE_SELECT | KBDS_MODE_LSELECT)); + } +} + +void +kbds_copytoclipboard(void) +{ + if (kbds_mode & KBDS_MODE_LSELECT) { + selextend(term.col-1, kbds_c.y, SEL_RECTANGULAR, 1); + sel.type = SEL_REGULAR; + } else { + selextend(kbds_c.x, kbds_c.y, kbds_seltype, 1); + } + xsetsel(getsel()); + + #if !CLIPBOARD_PATCH + xclipcopy(); + #endif // CLIPBOARD_PATCH +} + +void +kbds_clearhighlights(void) +{ + int x, y; + Line line; + + for (y = (IS_SET(MODE_ALTSCREEN) ? 0 : -term.histf); y < term.row; y++) { + line = TLINEABS(y); + for (x = 0; x < term.col; x++) + line[x].mode &= ~ATTR_HIGHLIGHT; + } + tfulldirt(); +} + +int +kbds_moveto(int x, int y) +{ + if (y < 0) + kscrollup(&((Arg){ .i = -y })); + else if (y >= term.row) + kscrolldown(&((Arg){ .i = y - term.row + 1 })); + kbds_c.x = (x < 0) ? 0 : (x > term.col-1) ? term.col-1 : x; + kbds_c.y = (y < 0) ? 0 : (y > term.row-1) ? term.row-1 : y; + kbds_c.line = TLINE(kbds_c.y); + kbds_c.len = tlinelen(kbds_c.line); + if (kbds_c.x > 0 && (kbds_c.line[kbds_c.x].mode & ATTR_WDUMMY)) + kbds_c.x--; +} + +int +kbds_moveforward(KCursor *c, int dx, int wrap) +{ + KCursor n = *c; + + n.x += dx; + if (n.x >= 0 && n.x < term.col && (n.line[n.x].mode & ATTR_WDUMMY)) + n.x += dx; + + if (n.x < 0) { + if (!wrap || --n.y < kbds_top()) + return 0; + n.line = TLINE(n.y); + n.len = tlinelen(n.line); + if ((wrap & KBDS_WRAP_LINE) && kbds_iswrapped(&n)) + n.x = n.len-1; + else if (wrap & KBDS_WRAP_EDGE) + n.x = term.col-1; + else + return 0; + n.x -= (n.x > 0 && (n.line[n.x].mode & ATTR_WDUMMY)) ? 1 : 0; + } else if (n.x >= term.col) { + if (((wrap & KBDS_WRAP_EDGE) || + ((wrap & KBDS_WRAP_LINE) && kbds_iswrapped(&n))) && ++n.y <= kbds_bot()) { + n.line = TLINE(n.y); + n.len = tlinelen(n.line); + n.x = 0; + } else { + return 0; + } + } else if (n.x >= n.len && dx > 0 && (wrap & KBDS_WRAP_LINE)) { + if (n.x == n.len && kbds_iswrapped(&n) && n.y < kbds_bot()) { + ++n.y; + n.line = TLINE(n.y); + n.len = tlinelen(n.line); + n.x = 0; + } else if (!(wrap & KBDS_WRAP_EDGE)) { + return 0; + } + } + *c = n; + return 1; +} + +int +kbds_ismatch(KCursor c) +{ + KCursor m = c; + int i, next; + + if (c.x + kbds_searchlen > c.len && (!kbds_iswrapped(&c) || c.y >= kbds_bot())) + return 0; + + for (next = 0, i = 0; i < kbds_searchlen; i++) { + if (kbds_searchstr[i].mode & ATTR_WDUMMY) + continue; + if ((next++ && !kbds_moveforward(&c, 1, KBDS_WRAP_LINE)) || + (kbds_searchcase && kbds_searchstr[i].u != c.line[c.x].u) || + (!kbds_searchcase && kbds_searchstr[i].u != towlower(c.line[c.x].u))) + return 0; + } + + for (i = 0; i < kbds_searchlen; i++) { + if (!(kbds_searchstr[i].mode & ATTR_WDUMMY)) { + m.line[m.x].mode |= ATTR_HIGHLIGHT; + kbds_moveforward(&m, 1, KBDS_WRAP_LINE); + } + } + return 1; +} + +int +kbds_searchall(void) +{ + KCursor c; + int count = 0; + + if (!kbds_searchlen) + return 0; + + for (c.y = kbds_top(); c.y <= kbds_bot(); c.y++) { + c.line = TLINE(c.y); + c.len = tlinelen(c.line); + for (c.x = 0; c.x < c.len; c.x++) + count += kbds_ismatch(c); + } + tfulldirt(); + + return count; +} + +void +kbds_searchnext(int dir) +{ + KCursor c = kbds_c, n = kbds_c; + int wrapped = 0; + + if (!kbds_searchlen) { + kbds_quant = 0; + return; + } + + if (dir < 0 && c.x > c.len) + c.x = c.len; + + for (kbds_quant = MAX(kbds_quant, 1); kbds_quant > 0;) { + if (!kbds_moveforward(&c, dir, KBDS_WRAP_LINE)) { + c.y += dir; + if (c.y < kbds_top()) + c.y = kbds_bot(), wrapped++; + else if (c.y > kbds_bot()) + c.y = kbds_top(), wrapped++; + if (wrapped > 1) + break;; + c.line = TLINE(c.y); + c.len = tlinelen(c.line); + c.x = (dir < 0 && c.len > 0) ? c.len-1 : 0; + c.x -= (c.x > 0 && (c.line[c.x].mode & ATTR_WDUMMY)) ? 1 : 0; + } + if (kbds_ismatch(c)) { + n = c; + kbds_quant--; + } + } + + kbds_moveto(n.x, n.y); + kbds_quant = 0; +} + +void +kbds_findnext(int dir, int repeat) +{ + KCursor prev, c = kbds_c, n = kbds_c; + int skipfirst, yoff = 0; + + if (c.len <= 0 || kbds_findchar == 0) { + kbds_quant = 0; + return; + } + + if (dir < 0 && c.x > c.len) + c.x = c.len; + + kbds_quant = MAX(kbds_quant, 1); + skipfirst = (kbds_quant == 1 && repeat && kbds_findtill); + + while (kbds_quant > 0) { + prev = c; + if (!kbds_moveforward(&c, dir, KBDS_WRAP_LINE)) + break; + if (c.line[c.x].u == kbds_findchar) { + if (skipfirst && prev.x == kbds_c.x && prev.y == kbds_c.y) { + skipfirst = 0; + continue; + } + n.x = kbds_findtill ? prev.x : c.x; + n.y = c.y; + yoff = kbds_findtill ? prev.y - c.y : 0; + kbds_quant--; + } + } + + kbds_moveto(n.x, n.y); + kbds_moveto(kbds_c.x, kbds_c.y + yoff); + kbds_quant = 0; +} + +int +kbds_isdelim(KCursor c, int xoff, wchar_t *delims) +{ + if (xoff && !kbds_moveforward(&c, xoff, KBDS_WRAP_LINE)) + return 1; + return wcschr(delims, c.line[c.x].u) != NULL; +} + +void +kbds_nextword(int start, int dir, wchar_t *delims) +{ + KCursor c = kbds_c, n = kbds_c; + int xoff = start ? -1 : 1; + + if (dir < 0 && c.x > c.len) + c.x = c.len; + else if (dir > 0 && c.x >= c.len && c.len > 0) + c.x = c.len-1; + + for (kbds_quant = MAX(kbds_quant, 1); kbds_quant > 0;) { + if (!kbds_moveforward(&c, dir, KBDS_WRAP_LINE)) { + c.y += dir; + if (c.y < kbds_top() || c.y > kbds_bot()) + break; + c.line = TLINE(c.y); + c.len = tlinelen(c.line); + c.x = (dir < 0 && c.len > 0) ? c.len-1 : 0; + c.x -= (c.x > 0 && (c.line[c.x].mode & ATTR_WDUMMY)) ? 1 : 0; + } + if (c.len > 0 && + !kbds_isdelim(c, 0, delims) && kbds_isdelim(c, xoff, delims)) { + n = c; + kbds_quant--; + } + } + + kbds_moveto(n.x, n.y); + kbds_quant = 0; +} + +int +kbds_drawcursor(void) +{ + if (kbds_in_use && (!kbds_issearchmode() || kbds_c.y != term.row-1)) { + #if LIGATURES_PATCH + xdrawcursor(kbds_c.x, kbds_c.y, TLINE(kbds_c.y)[kbds_c.x], + kbds_oc.x, kbds_oc.y, TLINE(kbds_oc.y)[kbds_oc.x], + TLINE(kbds_oc.y), term.col); + #else + xdrawcursor(kbds_c.x, kbds_c.y, TLINE(kbds_c.y)[kbds_c.x], + kbds_oc.x, kbds_oc.y, TLINE(kbds_oc.y)[kbds_oc.x]); + #endif // LIGATURES_PATCH + kbds_moveto(kbds_c.x, kbds_c.y); + kbds_oc = kbds_c; + } + return term.scr != 0 || kbds_in_use; +} + +int +kbds_keyboardhandler(KeySym ksym, char *buf, int len, int forcequit) +{ + int i, q, dy, eol, islast, prevscr, count, wrap; + int alt = IS_SET(MODE_ALTSCREEN); + Line line; + Rune u; + + if (kbds_issearchmode() && !forcequit) { + switch (ksym) { + case XK_Escape: + kbds_searchlen = 0; + /* FALLTHROUGH */ + case XK_Return: + for (kbds_searchcase = 0, i = 0; i < kbds_searchlen; i++) { + if (kbds_searchstr[i].u != towlower(kbds_searchstr[i].u)) { + kbds_searchcase = 1; + break; + } + } + count = kbds_searchall(); + kbds_searchnext(kbds_searchdir); + kbds_selecttext(); + kbds_setmode(kbds_mode & ~KBDS_MODE_SEARCH); + if (count == 0 && kbds_directsearch) + ksym = XK_Escape; + break; + case XK_BackSpace: + if (kbds_searchlen) { + kbds_searchlen--; + if (kbds_searchlen && (kbds_searchstr[kbds_searchlen].mode & ATTR_WDUMMY)) + kbds_searchlen--; + } + break; + default: + if (len < 1 || kbds_searchlen >= term.col-2) + return 0; + utf8decode(buf, &u, len); + kbds_searchstr[kbds_searchlen].u = u; + kbds_searchstr[kbds_searchlen++].mode = ATTR_NULL; + if (wcwidth(u) > 1) { + kbds_searchstr[kbds_searchlen-1].mode = ATTR_WIDE; + if (kbds_searchlen < term.col-2) { + kbds_searchstr[kbds_searchlen].u = 0; + kbds_searchstr[kbds_searchlen++].mode = ATTR_WDUMMY; + } + } + break; + } + /* If the direct search is aborted, we just go to the next switch + * statement and exit the keyboard selection mode immediately */ + if (!(ksym == XK_Escape && kbds_directsearch)) { + term.dirty[term.row-1] = 1; + return 0; + } + } else if ((kbds_mode & KBDS_MODE_FIND) && !forcequit) { + kbds_findchar = 0; + switch (ksym) { + case XK_Escape: + case XK_Return: + kbds_quant = 0; + break; + default: + if (len < 1) + return 0; + utf8decode(buf, &kbds_findchar, len); + kbds_findnext(kbds_finddir, 0); + kbds_selecttext(); + break; + } + kbds_setmode(kbds_mode & ~KBDS_MODE_FIND); + return 0; + } + + switch (ksym) { + case -1: + kbds_searchstr = xmalloc(term.col * sizeof(Glyph)); + kbds_in_use = 1; + kbds_moveto(term.c.x, term.c.y); + kbds_oc = kbds_c; + kbds_setmode(KBDS_MODE_MOVE); + return MODE_KBDSELECT; + case XK_V: + if (kbds_mode & KBDS_MODE_LSELECT) { + selclear(); + kbds_setmode(kbds_mode & ~(KBDS_MODE_SELECT | KBDS_MODE_LSELECT)); + } else if (kbds_mode & KBDS_MODE_SELECT) { + selextend(term.col-1, kbds_c.y, SEL_RECTANGULAR, 0); + sel.ob.x = 0; + tfulldirt(); + kbds_setmode((kbds_mode ^ KBDS_MODE_SELECT) | KBDS_MODE_LSELECT); + } else { + selstart(0, kbds_c.y, 0); + selextend(term.col-1, kbds_c.y, SEL_RECTANGULAR, 0); + kbds_setmode(kbds_mode | KBDS_MODE_LSELECT); + } + break; + case XK_v: + if (kbds_mode & KBDS_MODE_SELECT) { + selclear(); + kbds_setmode(kbds_mode & ~(KBDS_MODE_SELECT | KBDS_MODE_LSELECT)); + } else if (kbds_mode & KBDS_MODE_LSELECT) { + selextend(kbds_c.x, kbds_c.y, kbds_seltype, 0); + kbds_setmode((kbds_mode ^ KBDS_MODE_LSELECT) | KBDS_MODE_SELECT); + } else { + selstart(kbds_c.x, kbds_c.y, 0); + kbds_setmode(kbds_mode | KBDS_MODE_SELECT); + } + break; + case XK_s: + if (!(kbds_mode & KBDS_MODE_LSELECT)) { + kbds_seltype ^= (SEL_REGULAR | SEL_RECTANGULAR); + selextend(kbds_c.x, kbds_c.y, kbds_seltype, 0); + } + break; + case XK_y: + case XK_Y: + if (kbds_isselectmode()) { + kbds_copytoclipboard(); + selclear(); + kbds_setmode(kbds_mode & ~(KBDS_MODE_SELECT | KBDS_MODE_LSELECT)); + } + break; + case -2: + case -3: + case XK_slash: + case XK_KP_Divide: + case XK_question: + kbds_directsearch = (ksym == -2 || ksym == -3); + kbds_searchdir = (ksym == XK_question || ksym == -3) ? -1 : 1; + kbds_searchlen = 0; + kbds_setmode(kbds_mode | KBDS_MODE_SEARCH); + kbds_clearhighlights(); + return 0; + case XK_q: + case XK_Escape: + if (!kbds_in_use) + return 0; + if (kbds_quant && !forcequit) { + kbds_quant = 0; + break; + } + selclear(); + if (kbds_isselectmode() && !forcequit) { + kbds_setmode(KBDS_MODE_MOVE); + break; + } + kbds_setmode(KBDS_MODE_MOVE); + /* FALLTHROUGH */ + case XK_Return: + if (kbds_isselectmode()) + kbds_copytoclipboard(); + kbds_in_use = kbds_quant = 0; + free(kbds_searchstr); + kscrolldown(&((Arg){ .i = term.histf })); + kbds_clearhighlights(); + return MODE_KBDSELECT; + case XK_n: + case XK_N: + kbds_searchnext(ksym == XK_n ? kbds_searchdir : -kbds_searchdir); + break; + case XK_BackSpace: + kbds_moveto(0, kbds_c.y); + break; + case XK_exclam: + kbds_moveto(term.col/2, kbds_c.y); + break; + case XK_underscore: + kbds_moveto(term.col-1, kbds_c.y); + break; + case XK_dollar: + case XK_A: + eol = kbds_c.len-1; + line = kbds_c.line; + islast = (kbds_c.x == eol || (kbds_c.x == eol-1 && (line[eol-1].mode & ATTR_WIDE))); + if (islast && kbds_iswrapped(&kbds_c) && kbds_c.y < kbds_bot()) + kbds_moveto(tlinelen(TLINE(kbds_c.y+1))-1, kbds_c.y+1); + else + kbds_moveto(islast ? term.col-1 : eol, kbds_c.y); + break; + case XK_asciicircum: + case XK_I: + for (i = 0; i < kbds_c.len && kbds_c.line[i].u == ' '; i++) + ; + kbds_moveto((i < kbds_c.len) ? i : 0, kbds_c.y); + break; + case XK_End: + case XK_KP_End: + kbds_moveto(kbds_c.x, term.row-1); + break; + case XK_Home: + case XK_KP_Home: + case XK_H: + kbds_moveto(kbds_c.x, 0); + break; + case XK_M: + kbds_moveto(kbds_c.x, alt ? (term.row-1) / 2 + : MIN(term.c.y + term.scr, term.row-1) / 2); + break; + case XK_L: + kbds_moveto(kbds_c.x, alt ? term.row-1 + : MIN(term.c.y + term.scr, term.row-1)); + break; + case XK_Page_Up: + case XK_KP_Page_Up: + case XK_K: + prevscr = term.scr; + kscrollup(&((Arg){ .i = term.row })); + kbds_moveto(kbds_c.x, alt ? 0 + : MAX(0, kbds_c.y - term.row + term.scr - prevscr)); + break; + case XK_Page_Down: + case XK_KP_Page_Down: + case XK_J: + prevscr = term.scr; + kscrolldown(&((Arg){ .i = term.row })); + kbds_moveto(kbds_c.x, alt ? term.row-1 + : MIN(MIN(term.c.y + term.scr, term.row-1), + kbds_c.y + term.row + term.scr - prevscr)); + break; + case XK_asterisk: + case XK_KP_Multiply: + kbds_moveto(term.col/2, (term.row-1) / 2); + break; + case XK_g: + kscrollup(&((Arg){ .i = term.histf })); + kbds_moveto(kbds_c.x, 0); + break; + case XK_G: + kscrolldown(&((Arg){ .i = term.histf })); + kbds_moveto(kbds_c.x, alt ? term.row-1 : term.c.y); + break; + case XK_b: + case XK_B: + kbds_nextword(1, -1, (ksym == XK_b) ? kbds_sdelim : kbds_ldelim); + break; + case XK_w: + case XK_W: + kbds_nextword(1, +1, (ksym == XK_w) ? kbds_sdelim : kbds_ldelim); + break; + case XK_e: + case XK_E: + kbds_nextword(0, +1, (ksym == XK_e) ? kbds_sdelim : kbds_ldelim); + break; + case XK_z: + prevscr = term.scr; + dy = kbds_c.y - (term.row-1) / 2; + if (dy <= 0) + kscrollup(&((Arg){ .i = -dy })); + else + kscrolldown(&((Arg){ .i = dy })); + kbds_moveto(kbds_c.x, kbds_c.y + term.scr - prevscr); + break; + case XK_f: + case XK_F: + case XK_t: + case XK_T: + kbds_finddir = (ksym == XK_f || ksym == XK_t) ? 1 : -1; + kbds_findtill = (ksym == XK_t || ksym == XK_T) ? 1 : 0; + kbds_setmode(kbds_mode | KBDS_MODE_FIND); + return 0; + case XK_semicolon: + case XK_r: + kbds_findnext(kbds_finddir, 1); + break; + case XK_comma: + case XK_R: + kbds_findnext(-kbds_finddir, 1); + break; + case XK_0: + case XK_KP_0: + if (!kbds_quant) { + kbds_moveto(0, kbds_c.y); + break; + } + /* FALLTHROUGH */ + default: + if (ksym >= XK_0 && ksym <= XK_9) { /* 0-9 keyboard */ + q = (kbds_quant * 10) + (ksym ^ XK_0); + kbds_quant = q <= 99999999 ? q : kbds_quant; + term.dirty[0] = 1; + return 0; + } else if (ksym >= XK_KP_0 && ksym <= XK_KP_9) { /* 0-9 numpad */ + q = (kbds_quant * 10) + (ksym ^ XK_KP_0); + kbds_quant = q <= 99999999 ? q : kbds_quant; + term.dirty[0] = 1; + return 0; + } else if (ksym == XK_k || ksym == XK_h) + i = ksym & 1; + else if (ksym == XK_l || ksym == XK_j) + i = ((ksym & 6) | 4) >> 1; + else if (ksym >= XK_KP_Left && ksym <= XK_KP_Down) + i = ksym - XK_KP_Left; + else if ((XK_Home & ksym) != XK_Home || (i = (ksym ^ XK_Home) - 1) > 3) + return 0; + + kbds_quant = (kbds_quant ? kbds_quant : 1); + + if (i & 1) { + kbds_c.y += kbds_quant * (i & 2 ? 1 : -1); + } else { + for (;kbds_quant > 0; kbds_quant--) { + if (!kbds_moveforward(&kbds_c, (i & 2) ? 1 : -1, + KBDS_WRAP_LINE | KBDS_WRAP_EDGE)) + break; + } + } + kbds_moveto(kbds_c.x, kbds_c.y); + } + kbds_selecttext(); + kbds_quant = 0; + term.dirty[0] = 1; + return 0; +} diff --git a/st-flexipatch/patch/keyboardselect_reflow_st.h b/st-flexipatch/patch/keyboardselect_reflow_st.h new file mode 100644 index 0000000..c840af8 --- /dev/null +++ b/st-flexipatch/patch/keyboardselect_reflow_st.h @@ -0,0 +1,6 @@ +void kbds_drawstatusbar(int y); +void kbds_pasteintosearch(const char *, int, int); +int kbds_isselectmode(void); +int kbds_issearchmode(void); +int kbds_drawcursor(void); +int kbds_keyboardhandler(KeySym, char *, int, int); diff --git a/st-flexipatch/patch/keyboardselect_reflow_x.c b/st-flexipatch/patch/keyboardselect_reflow_x.c new file mode 100644 index 0000000..c8a39a2 --- /dev/null +++ b/st-flexipatch/patch/keyboardselect_reflow_x.c @@ -0,0 +1,16 @@ +void keyboard_select(const Arg *dummy) +{ + win.mode ^= kbds_keyboardhandler(-1, NULL, 0, 0); +} + +void searchforward(const Arg *) +{ + win.mode ^= kbds_keyboardhandler(-1, NULL, 0, 0); + kbds_keyboardhandler(-2, NULL, 0, 0); +} + +void searchbackward(const Arg *) +{ + win.mode ^= kbds_keyboardhandler(-1, NULL, 0, 0); + kbds_keyboardhandler(-3, NULL, 0, 0); +} diff --git a/st-flexipatch/patch/keyboardselect_reflow_x.h b/st-flexipatch/patch/keyboardselect_reflow_x.h new file mode 100644 index 0000000..6893013 --- /dev/null +++ b/st-flexipatch/patch/keyboardselect_reflow_x.h @@ -0,0 +1,3 @@ +void keyboard_select(const Arg *); +void searchforward(const Arg *); +void searchbackward(const Arg *); diff --git a/st-flexipatch/patch/keyboardselect_x.c b/st-flexipatch/patch/keyboardselect_x.c index 16af3e1..44cbe64 100644 --- a/st-flexipatch/patch/keyboardselect_x.c +++ b/st-flexipatch/patch/keyboardselect_x.c @@ -1,7 +1,7 @@ void toggle_winmode(int flag) { - win.mode ^= flag; + win.mode ^= flag; } void keyboard_select(const Arg *dummy) { win.mode ^= trt_kbdselect(-1, NULL, 0); -} \ No newline at end of file +} diff --git a/st-flexipatch/patch/netwmicon.c b/st-flexipatch/patch/netwmicon.c new file mode 100644 index 0000000..6ae0533 --- /dev/null +++ b/st-flexipatch/patch/netwmicon.c @@ -0,0 +1,40 @@ +#include + +void +setnetwmicon(void) +{ + /* use a png-image to set _NET_WM_ICON */ + FILE* file = fopen(ICON, "r"); + if (file) { + /* load image in rgba-format */ + const gdImagePtr icon_rgba = gdImageCreateFromPng(file); + fclose(file); + /* declare icon-variable which will store the image in bgra-format */ + const int width = gdImageSX(icon_rgba); + const int height = gdImageSY(icon_rgba); + const int icon_n = width * height + 2; + long icon_bgra[icon_n]; + /* set width and height of the icon */ + int i = 0; + icon_bgra[i++] = width; + icon_bgra[i++] = height; + /* rgba -> bgra */ + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + const int pixel_rgba = gdImageGetPixel(icon_rgba, x, y); + unsigned char *pixel_bgra = (unsigned char *) &icon_bgra[i++]; + pixel_bgra[0] = gdImageBlue(icon_rgba, pixel_rgba); + pixel_bgra[1] = gdImageGreen(icon_rgba, pixel_rgba); + pixel_bgra[2] = gdImageRed(icon_rgba, pixel_rgba); + /* scale alpha from 0-127 to 0-255 */ + const unsigned char alpha = 127 - gdImageAlpha(icon_rgba, pixel_rgba); + pixel_bgra[3] = alpha == 127 ? 255 : alpha * 2; + } + } + gdImageDestroy(icon_rgba); + /* set _NET_WM_ICON */ + xw.netwmicon = XInternAtom(xw.dpy, "_NET_WM_ICON", False); + XChangeProperty(xw.dpy, xw.win, xw.netwmicon, XA_CARDINAL, 32, + PropModeReplace, (uchar *) icon_bgra, icon_n); + } +} diff --git a/st-flexipatch/patch/netwmicon.h b/st-flexipatch/patch/netwmicon.h index 5e9c654..99afb44 100644 --- a/st-flexipatch/patch/netwmicon.h +++ b/st-flexipatch/patch/netwmicon.h @@ -1,686 +1 @@ -unsigned long icon[] = { - 64, 64, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x02000000, 0x03000000, - 0x03000000, 0x03000000, 0x03000000, 0x03000000, 0x03000000, 0x03000000, - 0x03000000, 0x03000000, 0x03000000, 0x03000000, 0x03000000, 0x03000000, - 0x03000000, 0x03000000, 0x03000000, 0x03000000, 0x03000000, 0x03000000, - 0x03000000, 0x03000000, 0x03000000, 0x03000000, 0x03000000, 0x03000000, - 0x03000000, 0x03000000, 0x03000000, 0x03000000, 0x03000000, 0x03000000, - 0x03000000, 0x03000000, 0x03000000, 0x03000000, 0x03000000, 0x03000000, - 0x03000000, 0x03000000, 0x03000000, 0x03000000, 0x03000000, 0x03000000, - 0x03000000, 0x03000000, 0x03000000, 0x03000000, 0x03000000, 0x03000000, - 0x03000000, 0x02000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x03000000, - 0x20181818, 0x4e868686, 0x74b2b2b2, 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, - 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, - 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, - 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, - 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, - 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, - 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, - 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, - 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, 0x74b2b2b2, - 0x4e868686, 0x20181818, 0x03000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x03000000, 0x46717171, 0xcef3f3f3, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xcdf3f3f3, - 0x456f6f6f, 0x03000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x211f1f1f, 0xd1f4f4f4, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xd0f3f3f3, 0x20181818, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x59959595, 0xffffffff, - 0xffffffff, 0xff8b8b8b, 0xff363636, 0xff363636, 0xff363636, 0xff363636, - 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, - 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, - 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, - 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, - 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, - 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, - 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, - 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, - 0xff8c8c8c, 0xffffffff, 0xffffffff, 0x58919191, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x83b3b3b3, 0xffffffff, 0xffffffff, 0xff262626, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff262626, 0xffffffff, - 0xffffffff, 0x83b3b3b3, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x8eacacac, 0xffffffff, 0xffffffff, 0xff222222, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff222222, 0xffffffff, 0xffffffff, 0x8eacacac, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8eacacac, 0xffffffff, - 0xffffffff, 0xff222222, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff222222, 0xffffffff, 0xffffffff, 0x8eacacac, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x8eacacac, 0xffffffff, 0xffffffff, 0xff222222, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff222222, 0xffffffff, - 0xffffffff, 0x8eacacac, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x8eacacac, 0xffffffff, 0xffffffff, 0xff222222, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff222222, 0xffffffff, 0xffffffff, 0x8eacacac, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8eacacac, 0xffffffff, - 0xffffffff, 0xff222222, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff2c2c2c, 0xffe0e0e0, 0xff1c1c1c, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff222222, 0xffffffff, 0xffffffff, 0x8eacacac, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x8eacacac, 0xffffffff, 0xffffffff, 0xff222222, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff202020, - 0xff6c6c6c, 0xffffffff, 0xff6d6d6d, 0xff3c3c3c, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff222222, 0xffffffff, - 0xffffffff, 0x8eacacac, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x8eacacac, 0xffffffff, 0xffffffff, 0xff222222, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff2d2d2d, 0xffe1e1e1, 0xffc3c3c3, 0xffffffff, - 0xffa1a1a1, 0xffdddddd, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff222222, 0xffffffff, 0xffffffff, 0x8eacacac, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8eacacac, 0xffffffff, - 0xffffffff, 0xff222222, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff7f7f7f, 0xffbfbfbf, 0xff303030, 0xffffffff, 0xff1c1c1c, 0xff181818, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff222222, 0xffffffff, 0xffffffff, 0x8eacacac, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x8eacacac, 0xffffffff, 0xffffffff, 0xff222222, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff717171, 0xffe1e1e1, - 0xff545454, 0xffffffff, 0xff1c1c1c, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff222222, 0xffffffff, - 0xffffffff, 0x8eacacac, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x8eacacac, 0xffffffff, 0xffffffff, 0xff222222, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff1c1c1c, 0xffa1a1a1, 0xfff6f6f6, 0xffffffff, - 0xffaeaeae, 0xff515151, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff222222, 0xffffffff, 0xffffffff, 0x8eacacac, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8eacacac, 0xffffffff, - 0xffffffff, 0xff222222, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff343434, 0xffffffff, 0xff979797, 0xfff9f9f9, - 0xff515151, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff222222, 0xffffffff, 0xffffffff, 0x8eacacac, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x8eacacac, 0xffffffff, 0xffffffff, 0xff222222, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff303030, 0xffffffff, 0xff1c1c1c, 0xffb3b3b3, 0xff8d8d8d, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff222222, 0xffffffff, - 0xffffffff, 0x8eacacac, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x8eacacac, 0xffffffff, 0xffffffff, 0xff222222, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff686868, 0xff616161, 0xff3c3c3c, 0xffffffff, - 0xff545454, 0xffe8e8e8, 0xff5b5b5b, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff222222, 0xffffffff, 0xffffffff, 0x8eacacac, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8eacacac, 0xffffffff, - 0xffffffff, 0xff222222, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff4b4b4b, 0xffb3b3b3, 0xffe1e1e1, 0xffffffff, 0xffcccccc, 0xff717171, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff222222, 0xffffffff, 0xffffffff, 0x8eacacac, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x8eacacac, 0xffffffff, 0xffffffff, 0xff222222, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff303030, 0xffffffff, 0xff1c1c1c, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff222222, 0xffffffff, - 0xffffffff, 0x8eacacac, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x8eacacac, 0xffffffff, 0xffffffff, 0xff222222, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff2b2b2b, 0xffd1d1d1, - 0xff1c1c1c, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff222222, 0xffffffff, 0xffffffff, 0x8eacacac, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8eacacac, 0xffffffff, - 0xffffffff, 0xff222222, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff7f7f7f, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, - 0xffe9e9e9, 0xffe9e9e9, 0xff444444, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff222222, 0xffffffff, 0xffffffff, 0x8eacacac, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x8eacacac, 0xffffffff, 0xffffffff, 0xff222222, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff222222, 0xffffffff, - 0xffffffff, 0x8eacacac, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x8eacacac, 0xffffffff, 0xffffffff, 0xff222222, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff222222, 0xffffffff, 0xffffffff, 0x8eacacac, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8eacacac, 0xffffffff, - 0xffffffff, 0xff222222, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff222222, 0xffffffff, 0xffffffff, 0x8eacacac, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x8eacacac, 0xffffffff, 0xffffffff, 0xff222222, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff222222, 0xffffffff, - 0xffffffff, 0x8eacacac, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x8eacacac, 0xffffffff, 0xffffffff, 0xff222222, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff222222, 0xffffffff, 0xffffffff, 0x8eacacac, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8eacacac, 0xffffffff, - 0xffffffff, 0xff222222, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff222222, 0xffffffff, 0xffffffff, 0x8eacacac, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x8eacacac, 0xffffffff, 0xffffffff, 0xff222222, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff222222, 0xffffffff, - 0xffffffff, 0x8eacacac, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x8eacacac, 0xffffffff, 0xffffffff, 0xff222222, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff222222, 0xffffffff, 0xffffffff, 0x8eacacac, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8eacacac, 0xffffffff, - 0xffffffff, 0xff222222, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff222222, 0xffffffff, 0xffffffff, 0x8eacacac, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x8eacacac, 0xffffffff, 0xffffffff, 0xff222222, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff222222, 0xffffffff, - 0xffffffff, 0x8eacacac, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x8eacacac, 0xffffffff, 0xffffffff, 0xff222222, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff222222, 0xffffffff, 0xffffffff, 0x8eacacac, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8eacacac, 0xffffffff, - 0xffffffff, 0xff222222, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff222222, 0xffffffff, 0xffffffff, 0x8eacacac, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x8eacacac, 0xffffffff, 0xffffffff, 0xff222222, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff222222, 0xffffffff, - 0xffffffff, 0x8eacacac, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x8eacacac, 0xffffffff, 0xffffffff, 0xff222222, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff222222, 0xffffffff, 0xffffffff, 0x8eacacac, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8eacacac, 0xffffffff, - 0xffffffff, 0xff222222, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff222222, 0xffffffff, 0xffffffff, 0x8eacacac, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x8eacacac, 0xffffffff, 0xffffffff, 0xff222222, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff222222, 0xffffffff, - 0xffffffff, 0x8eacacac, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x8eacacac, 0xffffffff, 0xffffffff, 0xff222222, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff222222, 0xffffffff, 0xffffffff, 0x8eacacac, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8eacacac, 0xffffffff, - 0xffffffff, 0xff222222, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff222222, 0xffffffff, 0xffffffff, 0x8eacacac, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x8eacacac, 0xffffffff, 0xffffffff, 0xff222222, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff222222, 0xffffffff, - 0xffffffff, 0x8eacacac, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x8eacacac, 0xffffffff, 0xffffffff, 0xff222222, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff222222, 0xffffffff, 0xffffffff, 0x8eacacac, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8eacacac, 0xffffffff, - 0xffffffff, 0xff222222, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff222222, 0xffffffff, 0xffffffff, 0x8eacacac, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x8aacacac, 0xffffffff, 0xffffffff, 0xff262626, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, - 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff262626, 0xffffffff, - 0xffffffff, 0x8aacacac, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x62858585, 0xffffffff, 0xffffffff, 0xff8c8c8c, 0xff373737, 0xff363636, - 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, - 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, - 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, - 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, - 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, - 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, - 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, - 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, - 0xff363636, 0xff373737, 0xff8d8d8d, 0xffffffff, 0xffffffff, 0x62828282, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x21171717, 0xdee2e2e2, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xdee1e1e1, 0x1f101010, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x03000000, 0x5f4e4e4e, 0xdbe1e1e1, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xdae1e1e1, - 0x5f4b4b4b, 0x03000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x12000000, 0x48040404, 0x6d595959, 0x8d929292, 0x90979797, - 0x90979797, 0x90979797, 0x90979797, 0x90979797, 0x90979797, 0x90979797, - 0x90979797, 0x90979797, 0x90979797, 0x90979797, 0x90979797, 0x90979797, - 0x90979797, 0x90979797, 0x90979797, 0x90979797, 0x90979797, 0x90979797, - 0x90979797, 0x90979797, 0x90979797, 0x90979797, 0x90979797, 0x90979797, - 0x90979797, 0x90979797, 0x90979797, 0x90979797, 0x90979797, 0x90979797, - 0x90979797, 0x90979797, 0x90979797, 0x90979797, 0x90979797, 0x90979797, - 0x90979797, 0x90979797, 0x90979797, 0x90979797, 0x90979797, 0x90979797, - 0x90979797, 0x90979797, 0x90979797, 0x90979797, 0x90979797, 0x90979797, - 0x90979797, 0x8d929292, 0x6d595959, 0x48040404, 0x12000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x06000000, 0x22000000, 0x29000000, 0x29000000, 0x29000000, 0x29000000, - 0x29000000, 0x29000000, 0x29000000, 0x29000000, 0x29000000, 0x29000000, - 0x29000000, 0x29000000, 0x29000000, 0x29000000, 0x29000000, 0x29000000, - 0x29000000, 0x29000000, 0x29000000, 0x29000000, 0x29000000, 0x29000000, - 0x29000000, 0x29000000, 0x29000000, 0x29000000, 0x29000000, 0x29000000, - 0x29000000, 0x29000000, 0x29000000, 0x29000000, 0x29000000, 0x29000000, - 0x29000000, 0x29000000, 0x29000000, 0x29000000, 0x29000000, 0x29000000, - 0x29000000, 0x29000000, 0x29000000, 0x29000000, 0x29000000, 0x29000000, - 0x29000000, 0x29000000, 0x29000000, 0x29000000, 0x29000000, 0x29000000, - 0x22000000, 0x06000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, -}; \ No newline at end of file +static void setnetwmicon(void); diff --git a/st-flexipatch/patch/netwmicon_ff.c b/st-flexipatch/patch/netwmicon_ff.c new file mode 100644 index 0000000..3bb9ed9 --- /dev/null +++ b/st-flexipatch/patch/netwmicon_ff.c @@ -0,0 +1,46 @@ +void +setnetwmicon(void) +{ + /* use a farbfeld image to set _NET_WM_ICON */ + FILE* file = fopen(ICON, "r"); + if (file) { + unsigned char buf[16] = {0}; + + int hasdata = fread(buf,1,16,file); + if (memcmp(buf,"farbfeld",8)) { + fprintf(stderr,"netwmicon: file %s is not a farbfeld image\n", ICON); + fclose(file); + return; + } + + /* declare icon-variable which will store the image in bgra-format */ + const int width=(buf[8]<<24)|(buf[9]<<16)|(buf[10]<<8)|buf[11]; + const int height=(buf[12]<<24)|(buf[13]<<16)|(buf[14]<<8)|buf[15]; + const int icon_n = width * height + 2; + long icon_bgra[icon_n]; + + /* set width and height of the icon */ + int i = 0; + icon_bgra[i++] = width; + icon_bgra[i++] = height; + + /* rgba -> bgra */ + for (int y = 0; y < height && hasdata; y++) { + for (int x = 0; x < width && hasdata; x++) { + unsigned char *pixel_bgra = (unsigned char *) &icon_bgra[i++]; + hasdata = fread(buf,1,8,file); + pixel_bgra[0] = buf[4]; + pixel_bgra[1] = buf[2]; + pixel_bgra[2] = buf[0]; + pixel_bgra[3] = buf[6]; + } + } + + /* set _NET_WM_ICON */ + xw.netwmicon = XInternAtom(xw.dpy, "_NET_WM_ICON", False); + XChangeProperty(xw.dpy, xw.win, xw.netwmicon, XA_CARDINAL, 32, + PropModeReplace, (uchar *) icon_bgra, icon_n); + + fclose(file); + } +} diff --git a/st-flexipatch/patch/netwmicon_icon.h b/st-flexipatch/patch/netwmicon_icon.h new file mode 100644 index 0000000..5e9c654 --- /dev/null +++ b/st-flexipatch/patch/netwmicon_icon.h @@ -0,0 +1,686 @@ +unsigned long icon[] = { + 64, 64, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x02000000, 0x03000000, + 0x03000000, 0x03000000, 0x03000000, 0x03000000, 0x03000000, 0x03000000, + 0x03000000, 0x03000000, 0x03000000, 0x03000000, 0x03000000, 0x03000000, + 0x03000000, 0x03000000, 0x03000000, 0x03000000, 0x03000000, 0x03000000, + 0x03000000, 0x03000000, 0x03000000, 0x03000000, 0x03000000, 0x03000000, + 0x03000000, 0x03000000, 0x03000000, 0x03000000, 0x03000000, 0x03000000, + 0x03000000, 0x03000000, 0x03000000, 0x03000000, 0x03000000, 0x03000000, + 0x03000000, 0x03000000, 0x03000000, 0x03000000, 0x03000000, 0x03000000, + 0x03000000, 0x03000000, 0x03000000, 0x03000000, 0x03000000, 0x03000000, + 0x03000000, 0x02000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x03000000, + 0x20181818, 0x4e868686, 0x74b2b2b2, 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, + 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, + 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, + 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, + 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, + 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, + 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, + 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, + 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, 0x77b6b6b6, 0x74b2b2b2, + 0x4e868686, 0x20181818, 0x03000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x03000000, 0x46717171, 0xcef3f3f3, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xcdf3f3f3, + 0x456f6f6f, 0x03000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x211f1f1f, 0xd1f4f4f4, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xd0f3f3f3, 0x20181818, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x59959595, 0xffffffff, + 0xffffffff, 0xff8b8b8b, 0xff363636, 0xff363636, 0xff363636, 0xff363636, + 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, + 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, + 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, + 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, + 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, + 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, + 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, + 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, + 0xff8c8c8c, 0xffffffff, 0xffffffff, 0x58919191, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x83b3b3b3, 0xffffffff, 0xffffffff, 0xff262626, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff262626, 0xffffffff, + 0xffffffff, 0x83b3b3b3, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x8eacacac, 0xffffffff, 0xffffffff, 0xff222222, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff222222, 0xffffffff, 0xffffffff, 0x8eacacac, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8eacacac, 0xffffffff, + 0xffffffff, 0xff222222, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff222222, 0xffffffff, 0xffffffff, 0x8eacacac, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x8eacacac, 0xffffffff, 0xffffffff, 0xff222222, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff222222, 0xffffffff, + 0xffffffff, 0x8eacacac, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x8eacacac, 0xffffffff, 0xffffffff, 0xff222222, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff222222, 0xffffffff, 0xffffffff, 0x8eacacac, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8eacacac, 0xffffffff, + 0xffffffff, 0xff222222, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff2c2c2c, 0xffe0e0e0, 0xff1c1c1c, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff222222, 0xffffffff, 0xffffffff, 0x8eacacac, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x8eacacac, 0xffffffff, 0xffffffff, 0xff222222, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff202020, + 0xff6c6c6c, 0xffffffff, 0xff6d6d6d, 0xff3c3c3c, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff222222, 0xffffffff, + 0xffffffff, 0x8eacacac, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x8eacacac, 0xffffffff, 0xffffffff, 0xff222222, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff2d2d2d, 0xffe1e1e1, 0xffc3c3c3, 0xffffffff, + 0xffa1a1a1, 0xffdddddd, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff222222, 0xffffffff, 0xffffffff, 0x8eacacac, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8eacacac, 0xffffffff, + 0xffffffff, 0xff222222, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff7f7f7f, 0xffbfbfbf, 0xff303030, 0xffffffff, 0xff1c1c1c, 0xff181818, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff222222, 0xffffffff, 0xffffffff, 0x8eacacac, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x8eacacac, 0xffffffff, 0xffffffff, 0xff222222, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff717171, 0xffe1e1e1, + 0xff545454, 0xffffffff, 0xff1c1c1c, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff222222, 0xffffffff, + 0xffffffff, 0x8eacacac, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x8eacacac, 0xffffffff, 0xffffffff, 0xff222222, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff1c1c1c, 0xffa1a1a1, 0xfff6f6f6, 0xffffffff, + 0xffaeaeae, 0xff515151, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff222222, 0xffffffff, 0xffffffff, 0x8eacacac, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8eacacac, 0xffffffff, + 0xffffffff, 0xff222222, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff343434, 0xffffffff, 0xff979797, 0xfff9f9f9, + 0xff515151, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff222222, 0xffffffff, 0xffffffff, 0x8eacacac, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x8eacacac, 0xffffffff, 0xffffffff, 0xff222222, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff303030, 0xffffffff, 0xff1c1c1c, 0xffb3b3b3, 0xff8d8d8d, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff222222, 0xffffffff, + 0xffffffff, 0x8eacacac, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x8eacacac, 0xffffffff, 0xffffffff, 0xff222222, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff686868, 0xff616161, 0xff3c3c3c, 0xffffffff, + 0xff545454, 0xffe8e8e8, 0xff5b5b5b, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff222222, 0xffffffff, 0xffffffff, 0x8eacacac, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8eacacac, 0xffffffff, + 0xffffffff, 0xff222222, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff4b4b4b, 0xffb3b3b3, 0xffe1e1e1, 0xffffffff, 0xffcccccc, 0xff717171, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff222222, 0xffffffff, 0xffffffff, 0x8eacacac, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x8eacacac, 0xffffffff, 0xffffffff, 0xff222222, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff303030, 0xffffffff, 0xff1c1c1c, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff222222, 0xffffffff, + 0xffffffff, 0x8eacacac, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x8eacacac, 0xffffffff, 0xffffffff, 0xff222222, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff2b2b2b, 0xffd1d1d1, + 0xff1c1c1c, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff222222, 0xffffffff, 0xffffffff, 0x8eacacac, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8eacacac, 0xffffffff, + 0xffffffff, 0xff222222, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff7f7f7f, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, 0xffe9e9e9, + 0xffe9e9e9, 0xffe9e9e9, 0xff444444, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff222222, 0xffffffff, 0xffffffff, 0x8eacacac, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x8eacacac, 0xffffffff, 0xffffffff, 0xff222222, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff222222, 0xffffffff, + 0xffffffff, 0x8eacacac, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x8eacacac, 0xffffffff, 0xffffffff, 0xff222222, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff222222, 0xffffffff, 0xffffffff, 0x8eacacac, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8eacacac, 0xffffffff, + 0xffffffff, 0xff222222, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff222222, 0xffffffff, 0xffffffff, 0x8eacacac, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x8eacacac, 0xffffffff, 0xffffffff, 0xff222222, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff222222, 0xffffffff, + 0xffffffff, 0x8eacacac, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x8eacacac, 0xffffffff, 0xffffffff, 0xff222222, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff222222, 0xffffffff, 0xffffffff, 0x8eacacac, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8eacacac, 0xffffffff, + 0xffffffff, 0xff222222, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff222222, 0xffffffff, 0xffffffff, 0x8eacacac, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x8eacacac, 0xffffffff, 0xffffffff, 0xff222222, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff222222, 0xffffffff, + 0xffffffff, 0x8eacacac, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x8eacacac, 0xffffffff, 0xffffffff, 0xff222222, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff222222, 0xffffffff, 0xffffffff, 0x8eacacac, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8eacacac, 0xffffffff, + 0xffffffff, 0xff222222, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff222222, 0xffffffff, 0xffffffff, 0x8eacacac, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x8eacacac, 0xffffffff, 0xffffffff, 0xff222222, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff222222, 0xffffffff, + 0xffffffff, 0x8eacacac, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x8eacacac, 0xffffffff, 0xffffffff, 0xff222222, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff222222, 0xffffffff, 0xffffffff, 0x8eacacac, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8eacacac, 0xffffffff, + 0xffffffff, 0xff222222, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff222222, 0xffffffff, 0xffffffff, 0x8eacacac, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x8eacacac, 0xffffffff, 0xffffffff, 0xff222222, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff222222, 0xffffffff, + 0xffffffff, 0x8eacacac, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x8eacacac, 0xffffffff, 0xffffffff, 0xff222222, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff222222, 0xffffffff, 0xffffffff, 0x8eacacac, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8eacacac, 0xffffffff, + 0xffffffff, 0xff222222, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff222222, 0xffffffff, 0xffffffff, 0x8eacacac, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x8eacacac, 0xffffffff, 0xffffffff, 0xff222222, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff222222, 0xffffffff, + 0xffffffff, 0x8eacacac, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x8eacacac, 0xffffffff, 0xffffffff, 0xff222222, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff222222, 0xffffffff, 0xffffffff, 0x8eacacac, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8eacacac, 0xffffffff, + 0xffffffff, 0xff222222, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff222222, 0xffffffff, 0xffffffff, 0x8eacacac, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x8eacacac, 0xffffffff, 0xffffffff, 0xff222222, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff222222, 0xffffffff, + 0xffffffff, 0x8eacacac, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x8eacacac, 0xffffffff, 0xffffffff, 0xff222222, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff222222, 0xffffffff, 0xffffffff, 0x8eacacac, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8eacacac, 0xffffffff, + 0xffffffff, 0xff222222, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff222222, 0xffffffff, 0xffffffff, 0x8eacacac, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x8aacacac, 0xffffffff, 0xffffffff, 0xff262626, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff171717, + 0xff171717, 0xff171717, 0xff171717, 0xff171717, 0xff262626, 0xffffffff, + 0xffffffff, 0x8aacacac, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x62858585, 0xffffffff, 0xffffffff, 0xff8c8c8c, 0xff373737, 0xff363636, + 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, + 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, + 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, + 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, + 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, + 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, + 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, + 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, 0xff363636, + 0xff363636, 0xff373737, 0xff8d8d8d, 0xffffffff, 0xffffffff, 0x62828282, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x21171717, 0xdee2e2e2, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xdee1e1e1, 0x1f101010, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x03000000, 0x5f4e4e4e, 0xdbe1e1e1, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xdae1e1e1, + 0x5f4b4b4b, 0x03000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x12000000, 0x48040404, 0x6d595959, 0x8d929292, 0x90979797, + 0x90979797, 0x90979797, 0x90979797, 0x90979797, 0x90979797, 0x90979797, + 0x90979797, 0x90979797, 0x90979797, 0x90979797, 0x90979797, 0x90979797, + 0x90979797, 0x90979797, 0x90979797, 0x90979797, 0x90979797, 0x90979797, + 0x90979797, 0x90979797, 0x90979797, 0x90979797, 0x90979797, 0x90979797, + 0x90979797, 0x90979797, 0x90979797, 0x90979797, 0x90979797, 0x90979797, + 0x90979797, 0x90979797, 0x90979797, 0x90979797, 0x90979797, 0x90979797, + 0x90979797, 0x90979797, 0x90979797, 0x90979797, 0x90979797, 0x90979797, + 0x90979797, 0x90979797, 0x90979797, 0x90979797, 0x90979797, 0x90979797, + 0x90979797, 0x8d929292, 0x6d595959, 0x48040404, 0x12000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x06000000, 0x22000000, 0x29000000, 0x29000000, 0x29000000, 0x29000000, + 0x29000000, 0x29000000, 0x29000000, 0x29000000, 0x29000000, 0x29000000, + 0x29000000, 0x29000000, 0x29000000, 0x29000000, 0x29000000, 0x29000000, + 0x29000000, 0x29000000, 0x29000000, 0x29000000, 0x29000000, 0x29000000, + 0x29000000, 0x29000000, 0x29000000, 0x29000000, 0x29000000, 0x29000000, + 0x29000000, 0x29000000, 0x29000000, 0x29000000, 0x29000000, 0x29000000, + 0x29000000, 0x29000000, 0x29000000, 0x29000000, 0x29000000, 0x29000000, + 0x29000000, 0x29000000, 0x29000000, 0x29000000, 0x29000000, 0x29000000, + 0x29000000, 0x29000000, 0x29000000, 0x29000000, 0x29000000, 0x29000000, + 0x22000000, 0x06000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, +}; \ No newline at end of file diff --git a/st-flexipatch/patch/netwmicon_legacy.c b/st-flexipatch/patch/netwmicon_legacy.c new file mode 100644 index 0000000..9a3bd36 --- /dev/null +++ b/st-flexipatch/patch/netwmicon_legacy.c @@ -0,0 +1,7 @@ +void +setnetwmicon(void) +{ + xw.netwmicon = XInternAtom(xw.dpy, "_NET_WM_ICON", False); + XChangeProperty(xw.dpy, xw.win, xw.netwmicon, XA_CARDINAL, 32, + PropModeReplace, (uchar *)&icon, LEN(icon)); +} diff --git a/st-flexipatch/patch/normalMode.c b/st-flexipatch/patch/normalMode.c deleted file mode 100644 index bbc9cfb..0000000 --- a/st-flexipatch/patch/normalMode.c +++ /dev/null @@ -1,284 +0,0 @@ -#include -#include - -#include "normalMode.h" -#include "utils.h" - -extern Glyph const styleSearch, style[]; -extern char const wDelS[], wDelL[], *nmKeys[]; -extern unsigned int bg[], fg, currentBg, highlightBg, highlightFg, amountNmKeys; - -typedef struct { int p[3]; } Pos; - -typedef enum {visual='v', visualLine='V', yank = 'y'} Op; -typedef enum {infix_none=0, infix_i='i', infix_a='a'} Infix; -typedef enum {fw='/', bw='?'} Search; -struct NormalModeState { - struct OperationState { Op op; Infix infix; } cmd; - struct MotionState { uint32_t c; int active; Pos searchPos; Search search; } m; -} defaultNormalMode, state; - -DynamicArray searchStr=UTF8_ARRAY, cCmd=UTF8_ARRAY, lCmd=UTF8_ARRAY; -Glyph styleCmd; -char posBuffer[10], braces[6][3] = { {"()"}, {"<>"}, {"{}"}, {"[]"}, {"\"\""}, {"''"}}; -int exited=1, overlay=1; -static inline Rune cChar() { return term.line[term.c.y][term.c.x].u; } -static inline int pos(int p, int h) {return IS_SET(MODE_ALTSCREEN)?p:rangeY(p+h*histOff-insertOff);} -static inline int contains(Rune l, char const * values, size_t const memSize) { - for (uint32_t i = 0; i < memSize; ++i) if (l == values[i]) return 1; - return 0; -} -static inline void decodeTo(char const *cs, size_t len, DynamicArray *arr) { - char *var = expand(arr); - if (!var) empty(arr); else utf8decode(cs, (Rune*)(var), len); -} -static inline void applyPos(Pos p) { - term.c.x = p.p[0], term.c.y = p.p[1]; - if (!IS_SET(MODE_ALTSCREEN) && histOp) term.line = &buf[histOff = p.p[2]]; -} -/// Find string in history buffer, and provide string-match-lookup for highlighting matches -static int highlighted(int x, int y) { - int const s=term.row*term.col, i=y*term.col+x, sz=size(&searchStr); - return sz && i0)==cChar())?wIdx+1:0; - if (wi && !wIdx) historyMove(-(int)(s*wi), 0, 0); - } - if (wIdx == strSz && wIdx) historyMove(-(int)(s*strSz), 0, 0); - else applyPos(p); - markSearchMatches(all); - return wIdx == strSz; -} -/// Execute series of normal-mode commands from char array / decoded from dynamic array -ExitState pressKeys(char const* s, size_t e) { - ExitState x=success; - for (size_t i=0; iu = *((Rune*)(st->content + (size(st)+x-xEnd)*st->elSize)); -} -/// Expand "infix" expression: for instance (w =>) l b | | v e | | y -static ExitState expandExpression(char l) { // ({ =>) l ? { \n | l | v / } \n | h | y - int a=state.cmd.infix==infix_a, yank=state.cmd.op=='y', lc=tolower(l), found=1; - state.cmd.infix = infix_none; - if(!yank && state.cmd.op!=visual && state.cmd.op!=visualLine) return failed; - char mot[11] = {'l', 0, 'b', 0, 0, 'v', 0, 'e', 0, 0, (char)(yank ? 'y' : 0)}; - if (lc == 'w') mot[2] = (char) ('b' - lc + l), mot[7] = (char) ((a ? 'w' : 'e') - lc + l), mot[9]=(char)(a?'h':0); - else { - mot[1]='?', mot[3]=mot[8]='\n', mot[6]='/', mot[4]=(char)(a?0:'l'), mot[9]=(char)(a?0:'h'); - for (int i=found=0; !found && i < 6; ++i) - if ((found=contains(l,braces[i],2))) mot[2]=braces[i][0], mot[7]=braces[i][1]; - } - if (!found) return failed; - assign(&lCmd, &cCmd); - empty(&cCmd); - state.cmd = defaultNormalMode.cmd; - return pressKeys(mot, 11); -} - -ExitState executeMotion(char const cs, KeySym const *const ks) { - state.m.c = state.m.c < 1u ? 1u : state.m.c; - if (ks && *ks == XK_d) historyMove(0, 0, term.row / 2); - else if (ks && *ks == XK_u) historyMove(0, 0, -term.row / 2); - else if (ks && *ks == XK_f) historyMove(0, 0, term.row-1+(term.c.y=0)); - else if (ks && *ks == XK_b) historyMove(0, 0, -(term.c.y=term.row-1)); - else if (ks && *ks == XK_h) overlay = !overlay; - else if (cs == 'K') historyMove(0, 0, -(int)state.m.c); - else if (cs == 'J') historyMove(0, 0, (int)state.m.c); - else if (cs == 'k') historyMove(0, -(int)state.m.c, 0); - else if (cs == 'j') historyMove(0, (int)state.m.c, 0); - else if (cs == 'h') historyMove(-(int)state.m.c, 0, 0); - else if (cs == 'l') historyMove( (int)state.m.c, 0, 0); - else if (cs == 'H') term.c.y = 0; - else if (cs == 'M') term.c.y = term.bot / 2; - else if (cs == 'L') term.c.y = term.bot; - else if (cs == 's' || cs == 'S') altToggle = cs == 's' ? !altToggle : 1; - else if (cs == 'G' || cs == 'g') { - if (cs == 'G') term.c = c[0] = c[IS_SET(MODE_ALTSCREEN)+1]; - if (!IS_SET(MODE_ALTSCREEN)) term.line = &buf[histOff=insertOff]; - } else if (cs == '0') term.c.x = 0; - else if (cs == '$') term.c.x = term.col-1; - else if (cs == 't') sel.type = sel.type==SEL_REGULAR ? SEL_RECTANGULAR : SEL_REGULAR; - else if (cs == 'n' || cs == 'N') { - int const d = ((cs=='N')!=(state.m.search==bw))?-1:1; - for (uint32_t i = state.m.c; i && findString(d, 0); --i); - } else if (contains(cs, "wWeEbB", 6)) { - int const low=cs<=90, off=tolower(cs)!='w', sgn=(tolower(cs)=='b')?-1:1; - size_t const l=strlen(wDelL), s=strlen(wDelS), maxIt=rows()*term.col; - for (int it=0, on=0; state.m.c > 0 && it < maxIt; ++it) { - // If an offset is to be performed in beginning or not in beginning, move in history. - if ((off || it) && historyMove(sgn, 0, 0)) break; - // Determine if the category of the current letter changed since last iteration. - int n = 1<<(contains(cChar(),wDelS,s) ?(2-low) :!contains(cChar(),wDelL,l)), - found = (on|=n)^n && ((off ?on^n :n)!=1); - // If a reverse offset is to be performed and this is the last letter: - if (found && off) historyMove(-sgn, 0, 0); - // Terminate iteration: reset #it and old n value #on and decrease operation count: - if (found) it=-1, on=0, --state.m.c; - } - } else return failed; - state.m.c = 0; - return state.cmd.op == yank ? exitMotion : success; -} - -ExitState kPressHist(char const *cs, size_t len, int ctrl, KeySym const *kSym) { - historyOpToggle(1, 1); - int const prevYOff=IS_SET(MODE_ALTSCREEN)?0:histOff, search=state.m.search&&state.m.active, - prevAltToggle=altToggle, prevOverlay=overlay; - int const noOp=!state.cmd.op&&!state.cmd.infix, num=len==1&&BETWEEN(cs[0],48,57), - esc=kSym&&*kSym==XK_Escape, ret=(kSym&&*kSym==XK_Return)||(len==1&&cs[0]=='\n'), - quantifier=num&&(cs[0]!='0'||state.m.c), ins=!search &&noOp &&len &&cs[0]=='i'; - exited = 0; - ExitState result = success; - if (esc || ret || ins) { result = exitMotion, len = 0; - } else if (kSym && *kSym == XK_BackSpace) { - if ((search || state.m.c) && size(&cCmd)) pop(&cCmd); - if (search) { - if (size(&searchStr)) pop(&searchStr); - else result = exitMotion; - if (!size(&searchStr)) tfulldirt(); - applyPos(state.m.searchPos); - findString(state.m.search==fw ? 1 : -1, 1); - } else if (state.m.c) state.m.c /= 10; - len = 0; - } else if (search) { - if (len >= 1) decodeTo(cs, len, &searchStr); - applyPos(state.m.searchPos); - findString(state.m.search==fw ? 1 : -1, 1); - } else if (len == 0) { result = failed; - } else if (quantifier) { state.m.c = min(SHRT_MAX, (int)state.m.c*10+cs[0]-48); - } else if (state.cmd.infix && state.cmd.op && (result = expandExpression(cs[0]), len=0)) { - } else if (cs[0] == 'd') { state = defaultNormalMode; result = exitMotion; state.m.active = 1; - } else if (cs[0] == '.') { - if (size(&cCmd)) assign(&lCmd, &cCmd); - empty(&cCmd); - executeCommand((uint32_t*) lCmd.content, size(&lCmd)); - empty(&cCmd); - len = 0; - } else if (cs[0] == 'r') { tfulldirt(); - } else if (cs[0] == 'c') { - empty(&lCmd); - empty(&cCmd); - empty(&searchStr); - tfulldirt(); - len = 0; - } else if (cs[0] == fw || cs[0] == bw) { - empty(&searchStr); - state.m.search = (Search) cs[0]; - state.m.searchPos = (Pos){.p={term.c.x, term.c.y, prevYOff}}; - state.m.active = 1; - } else if (cs[0]==infix_i || cs[0]==infix_a) { state.cmd.infix=(Infix) cs[0]; - } else if (cs[0] == 'y') { - if (state.cmd.op) { - result = (state.cmd.op == yank || state.cmd.op == visualLine) ? exitOp : exitMotion; - if (state.cmd.op == yank) selstart(0, term.c.y, 0); - } else selstart(term.c.x, term.c.y, 0); - state.cmd.op = yank; - } else if (cs[0] == visual || cs[0] == visualLine) { - if (state.cmd.op != (Op) cs[0]) { - state.cmd = defaultNormalMode.cmd; - state.cmd.op = (Op) cs[0]; - selstart(cs[0] == visualLine ?0 :term.c.x, term.c.y, 0); - } else result = exitOp; - } else if (!(result =executeMotion((char) (len?cs[0]:0), ctrl?kSym:NULL))) { - result=failed; - for (size_t i = 0; !ctrl && i < amountNmKeys; ++i) - if (cs[0]==nmKeys[i][0] && - failed!=(result=pressKeys(&nmKeys[i][1], strlen(nmKeys[i])-1))) goto end; - } // Operation/Motion finished if valid: update cmd string, extend selection, update search - if (result != failed) { - if (len == 1 && !ctrl) decodeTo(cs, len, &cCmd); - if ((state.cmd.op == visualLine) || ((state.cmd.op == yank) && (result == exitOp))) { - int const off = term.c.y + (IS_SET(MODE_ALTSCREEN) ? 0 : histOff) < sel.ob.y; //< Selection start below end. - sel.ob.x = off ? term.col - 1 : 0; - selextend(off ? 0 : term.col-1, term.c.y, sel.type, 0); - } else if (sel.oe.x != -1) { - selextend(term.c.x, term.c.y, sel.type, 0); - } - } // Set repaint for motion or status bar - if (!IS_SET(MODE_ALTSCREEN) && prevYOff != histOff) tfulldirt(); - // Terminate Motion / operation if thus indicated - if (result == exitMotion) { - if (!state.m.active) result = (exited=noOp) ? finish : exitOp; - state.m.active = (int) (state.m.c = 0u); - } - if (result == exitOp || result == finish) { - if (state.cmd.op == yank) { - xsetsel(getsel()); - xclipcopy(); - } - state = defaultNormalMode; - selclear(); - if (!esc) assign(&lCmd, &cCmd); - empty(&cCmd); - } // Update the content displayed in the history overlay - styleCmd = style[state.cmd.op==yank ? 1 : (state.cmd.op==visual ? 2 : - (state.cmd.op==visualLine ? 3 :0))]; - int const posLin = !IS_SET(MODE_ALTSCREEN) ? rangeY(insertOff-histOff):0, h=rows()-term.row; - if (!posLin || posLin==h || !h) strcpy(posBuffer, posLin ? " [BOT] " : " [TOP] "); - else sprintf(posBuffer, " % 3d%c ", min(100, max(0, (int)(.5 + posLin * 100. / h))),'%'); - if ((overlay || overlay!=prevOverlay) && term.col>9 && term.row>4) { - if (!term.dirty[term.row-1]) xdrawline(term.line[term.row-1], term.col*2/3, term.row-1, term.col-1); - if (!term.dirty[term.row-2]) xdrawline(term.line[term.row-2], term.col*2/3, term.row-2, term.col-1); - } - if (result==finish) altToggle = 0; - if (altToggle != prevAltToggle) tswapscreen(); -end: - historyOpToggle(-1, 1); - return result; -} - -void historyOverlay(int x, int y, Glyph* g) { - if (!histMode) return; - TCursor const *cHist = histOp ? &term.c : &c[0]; - if(overlay && term.col > 9 && term.row > 4 && (x > (2*term.col/3)) && (y >= (term.row-2))) { - *g = (y == term.row - 2) ? styleSearch : styleCmd; - if (y == term.row-2) getChar(&searchStr, g, term.row-2, term.col-2, term.col/3, x); - else if (x > term.col - 7) g->u = (Rune)(posBuffer[x - term.col + 7]); - else getChar(size(&cCmd) ?&cCmd :&lCmd, g, term.row-1, term.col-7, term.col/3-6, x); - } else if (highlighted(x, y)) g->bg = highlightBg, g->fg = highlightFg; - else if ((x==cHist->x) ^ (y==cHist->y)) g->bg = currentBg; - else if (x==cHist->x) g->mode^=ATTR_REVERSE; -} -void historyPreDraw() { - static Pos op = {.p={0, 0, 0}}; - historyOpToggle(1, 0); - // Draw the cursor cross if changed - if (term.c.y >= term.row || op.p[1] >= term.row) tfulldirt(); - else if (exited || (op.p[1] != term.c.y)) term.dirty[term.c.y] = term.dirty[op.p[1]] = 1; - for (int i=0; (exited || term.c.x != op.p[0]) && i= 0); + + return -1; +} +#else static int findeowl(int row) { - #if VIM_BROWSE_PATCH - int col = buffCols - 1; - #elif COLUMNS_PATCH + #if COLUMNS_PATCH int col = term.maxcol - 1; #else int col = term.col - 1; - #endif // VIM_BROWSE_PATCH + #endif // COLUMNS_PATCH do { if (TLINEURL(row)[col].mode & ATTR_WRAP) @@ -41,6 +51,7 @@ findeowl(int row) } while (TLINEURL(row)[col].u == ' ' && --col >= 0); return -1; } +#endif // REFLOW_PATCH void clearurl(void) @@ -50,6 +61,84 @@ clearurl(void) url_y2 = -1; } +#if REFLOW_PATCH +char * +detecturl(int col, int row, int draw) +{ + static char url[2048]; + Line line; + int x1, y1, x2, y2; + int i = sizeof(url)/2+1, j = sizeof(url)/2; + int row_start = row, col_start = col; + int minrow = tisaltscr() ? 0 : term.scr - term.histf; + int maxrow = tisaltscr() ? term.row - 1 : term.scr + term.row - 1; + + /* clear previously underlined url */ + if (draw) + clearurl(); + + url_maxcol = 0; + line = TLINE(row); + + if (!isvalidurlchar(line[col].u)) + return NULL; + + /* find the first character of url */ + do { + x1 = col_start, y1 = row_start; + url_maxcol = MAX(url_maxcol, x1); + url[--i] = line[col_start].u; + if (--col_start < 0) { + if (--row_start < minrow || (col_start = findeowl(TLINE(row_start))) < 0) + break; + line = TLINE(row_start); + } + } while (isvalidurlchar(line[col_start].u) && i > 0); + + /* early detection */ + if (url[i] != 'h') + return NULL; + + /* find the last character of url */ + line = TLINE(row); + do { + x2 = col, y2 = row; + url_maxcol = MAX(url_maxcol, x2); + url[j++] = line[col].u; + if (line[col++].mode & ATTR_WRAP) { + if (++row > maxrow) + break; + col = 0; + line = TLINE(row); + } + } while (col < term.col && isvalidurlchar(line[col].u) && j < sizeof(url)-1); + + url[j] = 0; + + if (strncmp("https://", &url[i], 8) && strncmp("http://", &url[i], 7)) + return NULL; + + /* Ignore some trailing characters to improve detection. */ + /* Alacritty and many other terminals also ignore these. */ + if (strchr(",.;:?!", (int)(url[j-1])) != NULL) { + x2 = MAX(x2-1, 0); + url[j-1] = 0; + } + + /* underline url (see xdrawglyphfontspecs() in x.c) */ + if (draw) { + url_x1 = (y1 >= 0) ? x1 : 0; + url_x2 = (y2 < term.row) ? x2 : url_maxcol; + url_y1 = MAX(y1, 0); + url_y2 = MIN(y2, term.row-1); + url_draw = 1; + for (y1 = url_y1; y1 <= url_y2; y1++) + term.dirty[y1] = 1; + } + + return &url[i]; +} +#else char * detecturl(int col, int row, int draw) { @@ -58,14 +147,15 @@ detecturl(int col, int row, int draw) int row_start = row; int col_start = col; int i = sizeof(url)/2+1, j = sizeof(url)/2; - #if SCROLLBACK_PATCH && !VIM_BROWSE_PATCH + + #if SCROLLBACK_PATCH int minrow = term.scr - term.histn, maxrow = term.scr + term.row - 1; /* Fixme: MODE_ALTSCREEN is not defined here, I had to use the magic number 1<<2 */ if ((term.mode & (1 << 2)) != 0) minrow = 0, maxrow = term.row - 1; #else int minrow = 0, maxrow = term.row - 1; - #endif // scrollback_patch + #endif // SCROLLBACK_PATCH url_maxcol = 0; /* clear previously underlined url */ @@ -96,13 +186,11 @@ detecturl(int col, int row, int draw) url_maxcol = MAX(url_maxcol, x2); url[j++] = TLINEURL(row)[col].u; wrapped = TLINEURL(row)[col].mode & ATTR_WRAP; - #if VIM_BROWSE_PATCH - if (++col >= buffCols || wrapped) { - #elif COLUMNS_PATCH + #if COLUMNS_PATCH if (++col >= term.maxcol || wrapped) { #else if (++col >= term.col || wrapped) { - #endif // VIM_BROWSE_PATCH + #endif // COLUMNS_PATCH col = 0; if (++row > maxrow || !wrapped) break; @@ -127,6 +215,7 @@ detecturl(int col, int row, int draw) return &url[i]; } +#endif // REFLOW_PATCH void openUrlOnClick(int col, int row, char* url_opener) diff --git a/st-flexipatch/patch/reflow.c b/st-flexipatch/patch/reflow.c new file mode 100644 index 0000000..2fd80f0 --- /dev/null +++ b/st-flexipatch/patch/reflow.c @@ -0,0 +1,924 @@ +void +tloaddefscreen(int clear, int loadcursor) +{ + int col, row, alt = IS_SET(MODE_ALTSCREEN); + + if (alt) { + if (clear) { + tclearregion(0, 0, term.col-1, term.row-1, 1); + #if SIXEL_PATCH + tdeleteimages(); + #endif // SIXEL_PATCH + } + col = term.col, row = term.row; + tswapscreen(); + } + if (loadcursor) + tcursor(CURSOR_LOAD); + if (alt) + tresizedef(col, row); +} + +void +tloadaltscreen(int clear, int savecursor) +{ + int col, row, def = !IS_SET(MODE_ALTSCREEN); + + if (savecursor) + tcursor(CURSOR_SAVE); + if (def) { + col = term.col, row = term.row; + kscrolldown(&((Arg){ .i = term.scr })); + tswapscreen(); + tresizealt(col, row); + } + if (clear) { + tclearregion(0, 0, term.col-1, term.row-1, 1); + #if SIXEL_PATCH + tdeleteimages(); + #endif // SIXEL_PATCH + } +} + +void +selmove(int n) +{ + sel.ob.y += n, sel.nb.y += n; + sel.oe.y += n, sel.ne.y += n; +} + +void +tclearglyph(Glyph *gp, int usecurattr) +{ + if (usecurattr) { + gp->fg = term.c.attr.fg; + gp->bg = term.c.attr.bg; + } else { + gp->fg = defaultfg; + gp->bg = defaultbg; + } + gp->mode = ATTR_NULL; + gp->u = ' '; +} + +#if SIXEL_PATCH +void +treflow_moveimages(int oldy, int newy) +{ + ImageList *im; + + for (im = term.images; im; im = im->next) { + if (im->y == oldy) + im->reflow_y = newy; + } +} +#endif // SIXEL_PATCH + +void +treflow(int col, int row) +{ + int i, j, x, x2; + int oce, nce, bot, scr; + int ox = 0, oy = -term.histf, nx = 0, ny = -1, len; + int cy = -1; /* proxy for new y coordinate of cursor */ + int buflen, nlines; + Line *buf, bufline, line; + #if SIXEL_PATCH + ImageList *im, *next; + + for (im = term.images; im; im = im->next) + im->reflow_y = INT_MIN; /* unset reflow_y */ + #endif // SIXEL_PATCH + + /* y coordinate of cursor line end */ + for (oce = term.c.y; oce < term.row - 1 && + tiswrapped(term.line[oce]); oce++); + + nlines = HISTSIZE + row; + buf = xmalloc(nlines * sizeof(Line)); + do { + if (!nx && ++ny < nlines) + buf[ny] = xmalloc(col * sizeof(Glyph)); + if (!ox) { + line = TLINEABS(oy); + len = tlinelen(line); + } + if (oy == term.c.y) { + if (!ox) + len = MAX(len, term.c.x + 1); + /* update cursor */ + if (cy < 0 && term.c.x - ox < col - nx) { + term.c.x = nx + term.c.x - ox, cy = ny; + UPDATEWRAPNEXT(0, col); + } + } + /* get reflowed lines in buf */ + bufline = buf[ny % nlines]; + if (col - nx > len - ox) { + memcpy(&bufline[nx], &line[ox], (len-ox) * sizeof(Glyph)); + nx += len - ox; + if (len == 0 || !(line[len - 1].mode & ATTR_WRAP)) { + for (j = nx; j < col; j++) + tclearglyph(&bufline[j], 0); + #if SIXEL_PATCH + treflow_moveimages(oy+term.scr, ny); + #endif // SIXEL_PATCH + nx = 0; + } else if (nx > 0) { + bufline[nx - 1].mode &= ~ATTR_WRAP; + } + ox = 0, oy++; + } else if (col - nx == len - ox) { + memcpy(&bufline[nx], &line[ox], (col-nx) * sizeof(Glyph)); + #if SIXEL_PATCH + treflow_moveimages(oy+term.scr, ny); + #endif // SIXEL_PATCH + ox = 0, oy++, nx = 0; + } else/* if (col - nx < len - ox) */ { + memcpy(&bufline[nx], &line[ox], (col-nx) * sizeof(Glyph)); + if (bufline[col - 1].mode & ATTR_WIDE) { + bufline[col - 2].mode |= ATTR_WRAP; + tclearglyph(&bufline[col - 1], 0); + ox--; + } else { + bufline[col - 1].mode |= ATTR_WRAP; + } + #if SIXEL_PATCH + treflow_moveimages(oy+term.scr, ny); + #endif // SIXEL_PATCH + ox += col - nx; + nx = 0; + } + } while (oy <= oce); + if (nx) + for (j = nx; j < col; j++) + tclearglyph(&bufline[j], 0); + + /* free extra lines */ + for (i = row; i < term.row; i++) + free(term.line[i]); + /* resize to new height */ + term.line = xrealloc(term.line, row * sizeof(Line)); + + buflen = MIN(ny + 1, nlines); + bot = MIN(ny, row - 1); + scr = MAX(row - term.row, 0); + /* update y coordinate of cursor line end */ + nce = MIN(oce + scr, bot); + /* update cursor y coordinate */ + term.c.y = nce - (ny - cy); + if (term.c.y < 0) { + j = nce, nce = MIN(nce + -term.c.y, bot); + term.c.y += nce - j; + while (term.c.y < 0) { + free(buf[ny-- % nlines]); + buflen--; + term.c.y++; + } + } + /* allocate new rows */ + for (i = row - 1; i > nce; i--) { + if (i >= term.row) + term.line[i] = xmalloc(col * sizeof(Glyph)); + else + term.line[i] = xrealloc(term.line[i], col * sizeof(Glyph)); + for (j = 0; j < col; j++) + tclearglyph(&term.line[i][j], 0); + } + /* fill visible area */ + for (/*i = nce */; i >= term.row; i--, ny--, buflen--) + term.line[i] = buf[ny % nlines]; + for (/*i = term.row - 1 */; i >= 0; i--, ny--, buflen--) { + free(term.line[i]); + term.line[i] = buf[ny % nlines]; + } + /* fill lines in history buffer and update term.histf */ + for (/*i = -1 */; buflen > 0 && i >= -HISTSIZE; i--, ny--, buflen--) { + j = (term.histi + i + 1 + HISTSIZE) % HISTSIZE; + free(term.hist[j]); + term.hist[j] = buf[ny % nlines]; + } + term.histf = -i - 1; + term.scr = MIN(term.scr, term.histf); + /* resize rest of the history lines */ + for (/*i = -term.histf - 1 */; i >= -HISTSIZE; i--) { + j = (term.histi + i + 1 + HISTSIZE) % HISTSIZE; + term.hist[j] = xrealloc(term.hist[j], col * sizeof(Glyph)); + } + + #if SIXEL_PATCH + /* move images to the final position */ + for (im = term.images; im; im = next) { + next = im->next; + if (im->reflow_y == INT_MIN) { + delete_image(im); + } else { + im->y = im->reflow_y - term.histf + term.scr - (ny + 1); + if (im->y - term.scr < -HISTSIZE || im->y - term.scr >= row) + delete_image(im); + } + } + + /* expand images into new text cells */ + for (im = term.images; im; im = next) { + next = im->next; + if (im->x < col) { + line = TLINE(im->y); + x2 = MIN(im->x + im->cols, col); + for (x = im->x; x < x2; x++) + line[x].mode |= ATTR_SIXEL; + } + } + #endif // SIXEL_PATCH + + for (; buflen > 0; ny--, buflen--) + free(buf[ny % nlines]); + free(buf); +} + +void +rscrolldown(int n) +{ + int i; + Line temp; + + /* can never be true as of now + if (IS_SET(MODE_ALTSCREEN)) + return; */ + + if ((n = MIN(n, term.histf)) <= 0) + return; + + for (i = term.c.y + n; i >= n; i--) { + temp = term.line[i]; + term.line[i] = term.line[i-n]; + term.line[i-n] = temp; + } + for (/*i = n - 1 */; i >= 0; i--) { + temp = term.line[i]; + term.line[i] = term.hist[term.histi]; + term.hist[term.histi] = temp; + term.histi = (term.histi - 1 + HISTSIZE) % HISTSIZE; + } + term.c.y += n; + term.histf -= n; + if ((i = term.scr - n) >= 0) { + term.scr = i; + } else { + #if SIXEL_PATCH + scroll_images(n - term.scr); + #endif // SIXEL_PATCH + term.scr = 0; + if (sel.ob.x != -1 && !sel.alt) + selmove(-i); + } +} + +void +tresizedef(int col, int row) +{ + int i, j; + + /* return if dimensions haven't changed */ + if (term.col == col && term.row == row) { + tfulldirt(); + return; + } + if (col != term.col) { + if (!sel.alt) + selremove(); + treflow(col, row); + } else { + /* slide screen up if otherwise cursor would get out of the screen */ + if (term.c.y >= row) { + tscrollup(0, term.row - 1, term.c.y - row + 1, SCROLL_RESIZE); + term.c.y = row - 1; + } + for (i = row; i < term.row; i++) + free(term.line[i]); + + /* resize to new height */ + term.line = xrealloc(term.line, row * sizeof(Line)); + /* allocate any new rows */ + for (i = term.row; i < row; i++) { + term.line[i] = xmalloc(col * sizeof(Glyph)); + for (j = 0; j < col; j++) + tclearglyph(&term.line[i][j], 0); + } + /* scroll down as much as height has increased */ + rscrolldown(row - term.row); + } + /* update terminal size */ + term.col = col, term.row = row; + /* reset scrolling region */ + term.top = 0, term.bot = row - 1; + /* dirty all lines */ + tfulldirt(); +} + +void +tresizealt(int col, int row) +{ + int i, j; + #if SIXEL_PATCH + ImageList *im, *next; + #endif // SIXEL_PATCH + + /* return if dimensions haven't changed */ + if (term.col == col && term.row == row) { + tfulldirt(); + return; + } + if (sel.alt) + selremove(); + /* slide screen up if otherwise cursor would get out of the screen */ + for (i = 0; i <= term.c.y - row; i++) + free(term.line[i]); + if (i > 0) { + /* ensure that both src and dst are not NULL */ + memmove(term.line, term.line + i, row * sizeof(Line)); + #if SIXEL_PATCH + scroll_images(-i); + #endif // SIXEL_PATCH + term.c.y = row - 1; + } + for (i += row; i < term.row; i++) + free(term.line[i]); + /* resize to new height */ + term.line = xrealloc(term.line, row * sizeof(Line)); + /* resize to new width */ + for (i = 0; i < MIN(row, term.row); i++) { + term.line[i] = xrealloc(term.line[i], col * sizeof(Glyph)); + for (j = term.col; j < col; j++) + tclearglyph(&term.line[i][j], 0); + } + /* allocate any new rows */ + for (/*i = MIN(row, term.row) */; i < row; i++) { + term.line[i] = xmalloc(col * sizeof(Glyph)); + for (j = 0; j < col; j++) + tclearglyph(&term.line[i][j], 0); + } + /* update cursor */ + if (term.c.x >= col) { + term.c.state &= ~CURSOR_WRAPNEXT; + term.c.x = col - 1; + } else { + UPDATEWRAPNEXT(1, col); + } + /* update terminal size */ + term.col = col, term.row = row; + /* reset scrolling region */ + term.top = 0, term.bot = row - 1; + + #if SIXEL_PATCH + /* delete or clip images if they are not inside the screen */ + for (im = term.images; im; im = next) { + next = im->next; + if (im->x >= term.col || im->y >= term.row || im->y < 0) { + delete_image(im); + } else { + if ((im->cols = MIN(im->x + im->cols, term.col) - im->x) <= 0) + delete_image(im); + } + } + #endif // SIXEL_PATCH + + /* dirty all lines */ + tfulldirt(); +} + +void +kscrolldown(const Arg* a) +{ + int n = a->i; + + if (!term.scr || IS_SET(MODE_ALTSCREEN)) + return; + + if (n < 0) + n = MAX(term.row / -n, 1); + + if (n <= term.scr) { + term.scr -= n; + } else { + n = term.scr; + term.scr = 0; + } + + if (sel.ob.x != -1 && !sel.alt) + selmove(-n); /* negate change in term.scr */ + tfulldirt(); + + #if SIXEL_PATCH + scroll_images(-1*n); + #endif // SIXEL_PATCH + + #if OPENURLONCLICK_PATCH + if (n > 0) + restoremousecursor(); + #endif // OPENURLONCLICK_PATCH +} + +void +kscrollup(const Arg* a) +{ + int n = a->i; + + if (!term.histf || IS_SET(MODE_ALTSCREEN)) + return; + + if (n < 0) + n = MAX(term.row / -n, 1); + + if (term.scr + n <= term.histf) { + term.scr += n; + } else { + n = term.histf - term.scr; + term.scr = term.histf; + } + + if (sel.ob.x != -1 && !sel.alt) + selmove(n); /* negate change in term.scr */ + tfulldirt(); + + #if SIXEL_PATCH + scroll_images(n); + #endif // SIXEL_PATCH + + #if OPENURLONCLICK_PATCH + if (n > 0) + restoremousecursor(); + #endif // OPENURLONCLICK_PATCH +} + +void +tscrollup(int top, int bot, int n, int mode) +{ + #if OPENURLONCLICK_PATCH + restoremousecursor(); + #endif //OPENURLONCLICK_PATCH + + int i, j, s; + Line temp; + int alt = IS_SET(MODE_ALTSCREEN); + int savehist = !alt && top == 0 && mode != SCROLL_NOSAVEHIST; + int scr = alt ? 0 : term.scr; + #if SIXEL_PATCH + int itop = top + scr, ibot = bot + scr; + ImageList *im, *next; + #endif // SIXEL_PATCH + + if (n <= 0) + return; + n = MIN(n, bot-top+1); + + if (savehist) { + for (i = 0; i < n; i++) { + term.histi = (term.histi + 1) % HISTSIZE; + temp = term.hist[term.histi]; + for (j = 0; j < term.col; j++) + tclearglyph(&temp[j], 1); + term.hist[term.histi] = term.line[i]; + term.line[i] = temp; + } + term.histf = MIN(term.histf + n, HISTSIZE); + s = n; + if (term.scr) { + j = term.scr; + term.scr = MIN(j + n, HISTSIZE); + s = j + n - term.scr; + } + if (mode != SCROLL_RESIZE) + tfulldirt(); + } else { + tclearregion(0, top, term.col-1, top+n-1, 1); + tsetdirt(top + scr, bot + scr); + } + + for (i = top; i <= bot-n; i++) { + temp = term.line[i]; + term.line[i] = term.line[i+n]; + term.line[i+n] = temp; + } + + #if SIXEL_PATCH + if (alt || !savehist) { + /* move images, if they are inside the scrolling region */ + for (im = term.images; im; im = next) { + next = im->next; + if (im->y >= itop && im->y <= ibot) { + im->y -= n; + if (im->y < itop) + delete_image(im); + } + } + } else { + /* move images, if they are inside the scrolling region or scrollback */ + for (im = term.images; im; im = next) { + next = im->next; + im->y -= scr; + if (im->y < 0) { + im->y -= n; + } else if (im->y >= top && im->y <= bot) { + im->y -= n; + if (im->y < top) + im->y -= top; // move to scrollback + } + if (im->y < -HISTSIZE) + delete_image(im); + else + im->y += term.scr; + } + } + #endif // SIXEL_PATCH + + if (sel.ob.x != -1 && sel.alt == alt) { + if (!savehist) { + selscroll(top, bot, -n); + } else if (s > 0) { + selmove(-s); + if (-term.scr + sel.nb.y < -term.histf) + selremove(); + } + } +} + +void +tscrolldown(int top, int n) +{ + #if OPENURLONCLICK_PATCH + restoremousecursor(); + #endif //OPENURLONCLICK_PATCH + + int i, bot = term.bot; + int scr = IS_SET(MODE_ALTSCREEN) ? 0 : term.scr; + int itop = top + scr, ibot = bot + scr; + Line temp; + #if SIXEL_PATCH + ImageList *im, *next; + #endif // SIXEL_PATCH + + if (n <= 0) + return; + n = MIN(n, bot-top+1); + + tsetdirt(top + scr, bot + scr); + tclearregion(0, bot-n+1, term.col-1, bot, 1); + + for (i = bot; i >= top+n; i--) { + temp = term.line[i]; + term.line[i] = term.line[i-n]; + term.line[i-n] = temp; + } + + #if SIXEL_PATCH + /* move images, if they are inside the scrolling region */ + for (im = term.images; im; im = next) { + next = im->next; + if (im->y >= itop && im->y <= ibot) { + im->y += n; + if (im->y > ibot) + delete_image(im); + } + } + #endif // SIXEL_PATCH + + if (sel.ob.x != -1 && sel.alt == IS_SET(MODE_ALTSCREEN)) + selscroll(top, bot, n); +} + +void +tresize(int col, int row) +{ + int *bp; + + #if KEYBOARDSELECT_PATCH + if (row != term.row || col != term.col) + win.mode ^= kbds_keyboardhandler(XK_Escape, NULL, 0, 1); + #endif // KEYBOARDSELECT_PATCH + + term.dirty = xrealloc(term.dirty, row * sizeof(*term.dirty)); + term.tabs = xrealloc(term.tabs, col * sizeof(*term.tabs)); + 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; + } + + if (IS_SET(MODE_ALTSCREEN)) + tresizealt(col, row); + else + tresizedef(col, row); +} + +void +tclearregion(int x1, int y1, int x2, int y2, int usecurattr) +{ + int x, y; + + /* regionselected() takes relative coordinates */ + if (regionselected(x1+term.scr, y1+term.scr, x2+term.scr, y2+term.scr)) + selremove(); + + for (y = y1; y <= y2; y++) { + term.dirty[y] = 1; + for (x = x1; x <= x2; x++) + tclearglyph(&term.line[y][x], usecurattr); + } +} + +void +tnew(int col, int row) +{ + int i, j; + for (i = 0; i < 2; i++) { + term.line = xmalloc(row * sizeof(Line)); + for (j = 0; j < row; j++) + term.line[j] = xmalloc(col * sizeof(Glyph)); + term.col = col, term.row = row; + tswapscreen(); + } + term.dirty = xmalloc(row * sizeof(*term.dirty)); + term.tabs = xmalloc(col * sizeof(*term.tabs)); + for (i = 0; i < HISTSIZE; i++) + term.hist[i] = xmalloc(col * sizeof(Glyph)); + treset(); +} + +void +tdeletechar(int n) +{ + int src, dst, size; + Line line; + + if (n <= 0) + return; + dst = term.c.x; + src = MIN(term.c.x + n, term.col); + size = term.col - src; + if (size > 0) { /* otherwise src would point beyond the array + https://stackoverflow.com/questions/29844298 */ + line = term.line[term.c.y]; + memmove(&line[dst], &line[src], size * sizeof(Glyph)); + } + tclearregion(dst + size, term.c.y, term.col - 1, term.c.y, 1); +} + +void +tinsertblank(int n) +{ + int src, dst, size; + Line line; + + if (n <= 0) + return; + dst = MIN(term.c.x + n, term.col); + src = term.c.x; + size = term.col - dst; + + if (size > 0) { /* otherwise dst would point beyond the array */ + line = term.line[term.c.y]; + memmove(&line[dst], &line[src], size * sizeof(Glyph)); + } + tclearregion(src, term.c.y, dst - 1, term.c.y, 1); +} + +int +tlinelen(Line line) +{ + int i = term.col - 1; + + /* We are using a different algorithm on the alt screen because an + * application might use spaces to clear the screen and in that case it is + * impossible to find the end of the line when every cell has the ATTR_SET + * attribute. The second algorithm is more accurate on the main screen and + * and we can use it there. */ + if (IS_SET(MODE_ALTSCREEN)) + for (; i >= 0 && !(line[i].mode & ATTR_WRAP) && line[i].u == ' '; i--); + else + for (; i >= 0 && !(line[i].mode & (ATTR_SET | ATTR_WRAP)); i--); + + return i + 1; +} + +int +tiswrapped(Line line) +{ + int len = tlinelen(line); + + return len > 0 && (line[len - 1].mode & ATTR_WRAP); +} + +char * +tgetglyphs(char *buf, const Glyph *gp, const Glyph *lgp) +{ + while (gp <= lgp) + if (gp->mode & ATTR_WDUMMY) { + gp++; + } else { + buf += utf8encode((gp++)->u, buf); + } + return buf; +} + +size_t +tgetline(char *buf, const Glyph *fgp) +{ + char *ptr; + const Glyph *lgp = &fgp[term.col - 1]; + + while (lgp > fgp && !(lgp->mode & (ATTR_SET | ATTR_WRAP))) + lgp--; + ptr = tgetglyphs(buf, fgp, lgp); + if (!(lgp->mode & ATTR_WRAP)) + *(ptr++) = '\n'; + return ptr - buf; +} + +int +regionselected(int x1, int y1, int x2, int y2) +{ + if (sel.ob.x == -1 || sel.mode == SEL_EMPTY || + sel.alt != IS_SET(MODE_ALTSCREEN) || sel.nb.y > y2 || sel.ne.y < y1) + return 0; + + return (sel.type == SEL_RECTANGULAR) ? sel.nb.x <= x2 && sel.ne.x >= x1 + : (sel.nb.y != y2 || sel.nb.x <= x2) && + (sel.ne.y != y1 || sel.ne.x >= x1); +} + +int +selected(int x, int y) +{ + return regionselected(x, y, x, y); +} + +void +selsnap(int *x, int *y, int direction) +{ + int newx, newy; + int rtop = 0, rbot = term.row - 1; + int delim, prevdelim, maxlen; + const Glyph *gp, *prevgp; + + if (!IS_SET(MODE_ALTSCREEN)) + rtop += -term.histf + term.scr, rbot += term.scr; + + switch (sel.snap) { + case SNAP_WORD: + /* + * Snap around if the word wraps around at the end or + * beginning of a line. + */ + maxlen = (TLINE(*y)[term.col-2].mode & ATTR_WRAP) ? term.col-1 : term.col; + LIMIT(*x, 0, maxlen - 1); + prevgp = &TLINE(*y)[*x]; + prevdelim = ISDELIM(prevgp->u); + for (;;) { + newx = *x + direction; + newy = *y; + if (!BETWEEN(newx, 0, maxlen - 1)) { + newy += direction; + if (!BETWEEN(newy, rtop, rbot)) + break; + + if (!tiswrapped(TLINE(direction > 0 ? *y : newy))) + break; + + maxlen = (TLINE(newy)[term.col-2].mode & ATTR_WRAP) ? term.col-1 : term.col; + newx = direction > 0 ? 0 : maxlen - 1; + } + + 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; + if (!(gp->mode & ATTR_WDUMMY)) { + 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 > rtop; *y -= 1) { + if (!tiswrapped(TLINE(*y-1))) + break; + } + } else if (direction > 0) { + for (; *y < rbot; *y += 1) { + if (!tiswrapped(TLINE(*y))) + break; + } + } + break; + } +} + +void +selscroll(int top, int bot, int n) +{ + /* turn absolute coordinates into relative */ + top += term.scr, bot += term.scr; + + if (BETWEEN(sel.nb.y, top, bot) != BETWEEN(sel.ne.y, top, bot)) { + selclear(); + } else if (BETWEEN(sel.nb.y, top, bot)) { + selmove(n); + if (sel.nb.y < top || sel.ne.y > bot) + selclear(); + } +} + +void +tswapscreen(void) +{ + static Line *altline; + static int altcol, altrow; + Line *tmpline = term.line; + int tmpcol = term.col, tmprow = term.row; + #if SIXEL_PATCH + ImageList *im = term.images; + #endif // SIXEL_PATCH + + term.line = altline; + term.col = altcol, term.row = altrow; + altline = tmpline; + altcol = tmpcol, altrow = tmprow; + term.mode ^= MODE_ALTSCREEN; + + #if SIXEL_PATCH + term.images = term.images_alt; + term.images_alt = im; + #endif // SIXEL_PATCH +} + +char * +getsel(void) +{ + char *str, *ptr; + int y, lastx, linelen; + const Glyph *gp, *lgp; + + if (sel.ob.x == -1 || sel.alt != IS_SET(MODE_ALTSCREEN)) + return NULL; + + str = xmalloc((term.col + 1) * (sel.ne.y - sel.nb.y + 1) * UTF_SIZ); + ptr = str; + + /* append every set & selected glyph to the selection */ + for (y = sel.nb.y; y <= sel.ne.y; y++) { + Line line = TLINE(y); + + if ((linelen = tlinelen(line)) == 0) { + *ptr++ = '\n'; + continue; + } + + if (sel.type == SEL_RECTANGULAR) { + gp = &line[sel.nb.x]; + lastx = sel.ne.x; + } else { + gp = &line[sel.nb.y == y ? sel.nb.x : 0]; + lastx = (sel.ne.y == y) ? sel.ne.x : term.col-1; + } + lgp = &line[MIN(lastx, linelen-1)]; + + ptr = tgetglyphs(ptr, gp, lgp); + /* + * 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) && + (!(lgp->mode & ATTR_WRAP) || sel.type == SEL_RECTANGULAR)) + *ptr++ = '\n'; + } + *ptr = '\0'; + return str; +} + +void +tdumpline(int n) +{ + char str[(term.col + 1) * UTF_SIZ]; + + tprinter(str, tgetline(str, &term.line[n][0])); +} diff --git a/st-flexipatch/patch/reflow.h b/st-flexipatch/patch/reflow.h new file mode 100644 index 0000000..ec28375 --- /dev/null +++ b/st-flexipatch/patch/reflow.h @@ -0,0 +1,44 @@ +#define TLINE(y) ( \ + (y) < term.scr ? term.hist[(term.histi + (y) - term.scr + 1 + HISTSIZE) % HISTSIZE] \ + : term.line[(y) - term.scr] \ +) + +#define TLINEABS(y) ( \ + (y) < 0 ? term.hist[(term.histi + (y) + 1 + HISTSIZE) % HISTSIZE] : term.line[(y)] \ +) + +#define UPDATEWRAPNEXT(alt, col) do { \ + if ((term.c.state & CURSOR_WRAPNEXT) && term.c.x + term.wrapcwidth[alt] < col) { \ + term.c.x += term.wrapcwidth[alt]; \ + term.c.state &= ~CURSOR_WRAPNEXT; \ + } \ +} while (0); + +static int tiswrapped(Line line); +static size_t tgetline(char *, const Glyph *); +static inline int regionselected(int, int, int, int); +static void tloaddefscreen(int, int); +static void tloadaltscreen(int, int); +static void selmove(int); +static inline void tclearglyph(Glyph *, int); +static void treflow(int, int); +static void rscrolldown(int); +static void tresizedef(int, int); +static void tresizealt(int, int); +void kscrolldown(const Arg *); +void kscrollup(const Arg *); +static void tscrollup(int, int, int, int); +static void tclearregion(int, int, int, int, int); +static void tdeletechar(int); +static int tlinelen(Line len); +static char * tgetglyphs(char *buf, const Glyph *gp, const Glyph *lgp); +static void selscroll(int, int, int); + +typedef struct { + uint b; + uint mask; + void (*func)(const Arg *); + const Arg arg; +} MouseKey; + +extern MouseKey mkeys[]; diff --git a/st-flexipatch/patch/sixel_st.c b/st-flexipatch/patch/sixel_st.c deleted file mode 100644 index ed64fee..0000000 --- a/st-flexipatch/patch/sixel_st.c +++ /dev/null @@ -1,42 +0,0 @@ -sixel_state_t sixel_st; - -void -dcshandle(void) -{ - switch (csiescseq.mode[0]) { - default: - fprintf(stderr, "erresc: unknown csi "); - csidump(); - /* die(""); */ - break; - case 'q': /* DECSIXEL */ - if (sixel_parser_init(&sixel_st, 0, 0 << 16 | 0 << 8 | 0, 1, win.cw, win.ch) != 0) - perror("sixel_parser_init() failed"); - term.mode |= MODE_SIXEL; - break; - } -} - -void -scroll_images(int n) { - ImageList *im; - int tmp; - - /* maximum sixel distance in lines from current view before - * deallocation - * TODO: should be in config.h */ - int max_sixel_distance = 10000; - - for (im = term.images; im; im = im->next) { - im->y += n; - - /* check if the current sixel has exceeded the maximum - * draw distance, and should therefore be deleted */ - tmp = im->y; - if (tmp < 0) { tmp = tmp * -1; } - if (tmp > max_sixel_distance) { - fprintf(stderr, "im@0x%08x exceeded maximum distance\n"); - im->should_delete = 1; - } - } -} \ No newline at end of file diff --git a/st-flexipatch/patch/sixel_st.h b/st-flexipatch/patch/sixel_st.h deleted file mode 100644 index cf2f0e1..0000000 --- a/st-flexipatch/patch/sixel_st.h +++ /dev/null @@ -1,2 +0,0 @@ -static void dcshandle(void); -static void scroll_images(int n); \ No newline at end of file diff --git a/st-flexipatch/patch/sixel_x.c b/st-flexipatch/patch/sixel_x.c deleted file mode 100644 index 0f74f53..0000000 --- a/st-flexipatch/patch/sixel_x.c +++ /dev/null @@ -1,14 +0,0 @@ -void -delete_image(ImageList *im) -{ - if (im->prev) - im->prev->next = im->next; - else - term.images = im->next; - if (im->next) - im->next->prev = im->prev; - if (im->pixmap) - XFreePixmap(xw.dpy, (Drawable)im->pixmap); - free(im->pixels); - free(im); -} \ No newline at end of file diff --git a/st-flexipatch/patch/st_include.c b/st-flexipatch/patch/st_include.c index 6772a6e..20c2386 100644 --- a/st-flexipatch/patch/st_include.c +++ b/st-flexipatch/patch/st_include.c @@ -8,7 +8,9 @@ #if ISO14755_PATCH #include "iso14755.c" #endif -#if KEYBOARDSELECT_PATCH +#if REFLOW_PATCH && KEYBOARDSELECT_PATCH +#include "keyboardselect_reflow_st.c" +#elif KEYBOARDSELECT_PATCH #include "keyboardselect_st.c" #endif #if RIGHTCLICKTOPLUMB_PATCH @@ -17,15 +19,11 @@ #if NEWTERM_PATCH #include "newterm.c" #endif -#if SCROLLBACK_PATCH || SCROLLBACK_MOUSE_PATCH || SCROLLBACK_MOUSE_ALTSCREEN_PATCH +#if REFLOW_PATCH +#include "reflow.c" +#elif SCROLLBACK_PATCH || SCROLLBACK_MOUSE_PATCH || SCROLLBACK_MOUSE_ALTSCREEN_PATCH #include "scrollback.c" #endif -#if SIXEL_PATCH -#include "sixel_st.c" -#endif #if SYNC_PATCH #include "sync.c" #endif -#if VIM_BROWSE_PATCH -#include "normalMode.c" -#endif \ No newline at end of file diff --git a/st-flexipatch/patch/st_include.h b/st-flexipatch/patch/st_include.h index c30a752..acc2975 100644 --- a/st-flexipatch/patch/st_include.h +++ b/st-flexipatch/patch/st_include.h @@ -8,7 +8,9 @@ #if ISO14755_PATCH #include "iso14755.h" #endif -#if KEYBOARDSELECT_PATCH +#if REFLOW_PATCH && KEYBOARDSELECT_PATCH +#include "keyboardselect_reflow_st.h" +#elif KEYBOARDSELECT_PATCH #include "keyboardselect_st.h" #endif #if OPENURLONCLICK_PATCH @@ -20,15 +22,11 @@ #if NEWTERM_PATCH #include "newterm.h" #endif -#if SCROLLBACK_PATCH || SCROLLBACK_MOUSE_PATCH || SCROLLBACK_MOUSE_ALTSCREEN_PATCH +#if REFLOW_PATCH +#include "reflow.h" +#elif SCROLLBACK_PATCH || SCROLLBACK_MOUSE_PATCH || SCROLLBACK_MOUSE_ALTSCREEN_PATCH #include "scrollback.h" #endif -#if SIXEL_PATCH -#include "sixel_st.h" -#endif #if SYNC_PATCH #include "sync.h" #endif -// #if VIM_BROWSE_PATCH -// #include "normalMode.h" -// #endif diff --git a/st-flexipatch/patch/x_include.c b/st-flexipatch/patch/x_include.c index cbea418..73a709a 100644 --- a/st-flexipatch/patch/x_include.c +++ b/st-flexipatch/patch/x_include.c @@ -23,18 +23,24 @@ #if INVERT_PATCH #include "invert.c" #endif -#if KEYBOARDSELECT_PATCH +#if REFLOW_PATCH && KEYBOARDSELECT_PATCH +#include "keyboardselect_reflow_x.c" +#elif KEYBOARDSELECT_PATCH #include "keyboardselect_x.c" #endif +#if NETWMICON_PATCH +#include "netwmicon.c" +#elif NETWMICON_FF_PATCH +#include "netwmicon_ff.c" +#elif NETWMICON_LEGACY_PATCH +#include "netwmicon_legacy.c" +#endif #if OPENURLONCLICK_PATCH #include "openurlonclick.c" #endif #if RIGHTCLICKTOPLUMB_PATCH #include "rightclicktoplumb_x.c" #endif -#if SIXEL_PATCH -#include "sixel_x.c" -#endif #if ST_EMBEDDER_PATCH #include "st_embedder_x.c" #endif diff --git a/st-flexipatch/patch/x_include.h b/st-flexipatch/patch/x_include.h index 6505909..b94317c 100644 --- a/st-flexipatch/patch/x_include.h +++ b/st-flexipatch/patch/x_include.h @@ -20,10 +20,16 @@ #if INVERT_PATCH #include "invert.h" #endif -#if KEYBOARDSELECT_PATCH +#if REFLOW_PATCH && KEYBOARDSELECT_PATCH +#include "keyboardselect_reflow_st.h" +#include "keyboardselect_reflow_x.h" +#elif KEYBOARDSELECT_PATCH #include "keyboardselect_x.h" #endif -#if NETWMICON_PATCH +#if NETWMICON_LEGACY_PATCH +#include "netwmicon_icon.h" +#endif +#if NETWMICON_PATCH || NETWMICON_FF_PATCH || NETWMICON_LEGACY_PATCH #include "netwmicon.h" #endif #if RIGHTCLICKTOPLUMB_PATCH @@ -35,6 +41,3 @@ #if XRESOURCES_PATCH #include "xresources.h" #endif -#if VIM_BROWSE_PATCH -#include "normalMode.h" -#endif diff --git a/st-flexipatch/patches.def.h b/st-flexipatch/patches.def.h index d367b05..25b9519 100644 --- a/st-flexipatch/patches.def.h +++ b/st-flexipatch/patches.def.h @@ -29,6 +29,13 @@ */ #define ALPHA_GRADIENT_PATCH 0 +/* Allows for the initial size of the terminal to be specified as pixel width and height + * using the -G command line option. Can be combined with the anysize patch to also allow + * the window to be resized to any pixel size. + * https://st.suckless.org/patches/anygeometry/ + */ +#define ANYGEOMETRY_PATCH 0 + /* This patch allows st to resize to any pixel size rather than snapping to character width/height. * https://st.suckless.org/patches/anysize/ */ @@ -77,9 +84,8 @@ #define CLIPBOARD_PATCH 1 /* This patch allows st to be resized without cutting off text when the terminal window is - * made larger again. Text does not wrap when the terminal window is made smaller. - * - * The vim browse patch takes precedence over this patch. + * made larger again. Text does not wrap when the terminal window is made smaller, you may + * also want to have a look at the reflow patch. * * https://github.com/bakkeby/st-flexipatch/issues/34 */ @@ -213,6 +219,8 @@ #define ISO14755_PATCH 1 /* This patch allows you to select text on the terminal using keyboard shortcuts. + * NB: An improved variant of this patch is enabled if combined with the reflow patch. + * * https://st.suckless.org/patches/keyboard_select/ */ #define KEYBOARDSELECT_PATCH 0 @@ -233,10 +241,39 @@ */ #define MONOCHROME_PATCH 0 -/* This patch sets the _NET_WM_ICON X property with a hardcoded icon for st. +/* This patch sets the _NET_WM_ICON X property with an icon that is read from a .png file. + * This patch depends on the GD Graphics Library and headers to compile. + * You need to uncomment the corresponding lines in config.mk to use the gd library. + * + * The default location for the .png file is: + * - /usr/local/share/pixmaps/st.png + * * https://st.suckless.org/patches/netwmicon/ */ -#define NETWMICON_PATCH 1 +#define NETWMICON_PATCH 0 + +/* This patch sets the _NET_WM_ICON X property with an icon that is read from a farbfeld image. + * The benefit of this patch is that you do not need an additional dependency on an external + * library to read and convert the farbfeld image. + * + * The default location for the farbfeld image is: + * - /usr/local/share/pixmaps/st.ff + * + * Remember to change the ICONNAME in config.mk from st.png to st.ff when using this patch. + * + * Example command to convert a .png to farbfeld: + * $ png2ff < st.png > st.ff + * + * https://tools.suckless.org/farbfeld/ + * https://github.com/bakkeby/patches/wiki/netwmicon/ + */ +#define NETWMICON_FF_PATCH 0 + +/* This patch sets the _NET_WM_ICON X property with a hardcoded icon for st. This is the + * original version that predates the version that reads the image from a .png file. + * https://st.suckless.org/patches/netwmicon/ + */ +#define NETWMICON_LEGACY_PATCH 0 /* This patch allows you to spawn a new st terminal using Ctrl-Shift-Return. It will have the * same CWD (current working directory) as the original st instance. @@ -262,7 +299,14 @@ * * https://www.reddit.com/r/suckless/comments/cc83om/st_open_url/ */ -#define OPENURLONCLICK_PATCH 1 +#define OPENURLONCLICK_PATCH 0 + +/* Reflow. + * Allows st to be resized without cutting off text when the terminal window is made larger again. + * Text wraps when the terminal window is made smaller. + * Comes with scrollback. + */ +#define REFLOW_PATCH 0 /* This patch allows you to specify a border that is relative in size to the width of a cell * in the terminal. @@ -293,6 +337,13 @@ */ #define SCROLLBACK_MOUSE_ALTSCREEN_PATCH 1 +/* This patch adds the two color-settings selectionfg and selectionbg to config.def.h. + * Those define the fore- and background colors which are used when text on the screen is selected + * with the mouse. This removes the default behaviour which would simply reverse the colors. + * https://st.suckless.org/patches/selectioncolors/ + */ +#define SELECTION_COLORS_PATCH 0 + /* This is the single drawable buffer patch as outlined in the FAQ to get images * in w3m to display. While this patch does not break the alpha patch it images * are not shown in w3m if the alpha patch is applied. @@ -354,7 +405,7 @@ * when including this patch. * https://st.suckless.org/patches/themed_cursor/ */ -#define THEMED_CURSOR_PATCH 0 +#define THEMED_CURSOR_PATCH 1 /* Adds support for special underlines. * @@ -372,7 +423,7 @@ * * https://st.suckless.org/patches/undercurl/ */ -#define UNDERCURL_PATCH 0 +#define UNDERCURL_PATCH 1 /* Allows mouse scroll without modifier keys for regardless of alt screen using the external * scroll program. @@ -399,16 +450,6 @@ */ #define VERTCENTER_PATCH 0 -/* The vim-browse patch offers the possibility to move through the terminal history-buffer, - * search for strings using VIM-like motions, operations and quantifiers. It overlays the - * screen with highlighted search results and displays the current operation / motions / search - * string in the bottom right corner. - * - * https://github.com/juliusHuelsmann/st-history-vim - * https://st.suckless.org/patches/vim_browse/ - */ -#define VIM_BROWSE_PATCH 0 - /* Briefly inverts window content on terminal bell event. * https://st.suckless.org/patches/visualbell/ */ diff --git a/st-flexipatch/sixel.c b/st-flexipatch/sixel.c index 2c382f4..ad6f6bc 100644 --- a/st-flexipatch/sixel.c +++ b/st-flexipatch/sixel.c @@ -5,10 +5,12 @@ #include #include /* memcpy */ +#include "st.h" +#include "win.h" #include "sixel.h" #include "sixel_hls.h" -#define SIXEL_RGB(r, g, b) ((r) + ((g) << 8) + ((b) << 16)) +#define SIXEL_RGB(r, g, b) ((255 << 24) + ((r) << 16) + ((g) << 8) + (b)) #define SIXEL_PALVAL(n,a,m) (((n) * (a) + ((m) / 2)) / (m)) #define SIXEL_XRGB(r,g,b) SIXEL_RGB(SIXEL_PALVAL(r, 255, 100), SIXEL_PALVAL(g, 255, 100), SIXEL_PALVAL(b, 255, 100)) @@ -31,6 +33,45 @@ static sixel_color_t const sixel_default_color_table[] = { SIXEL_XRGB(80, 80, 80), /* 15 Gray 75% */ }; +void +scroll_images(int n) { + ImageList *im, *next; + #if SCROLLBACK_PATCH || REFLOW_PATCH + int top = tisaltscr() ? 0 : term.scr - HISTSIZE; + #else + int top = 0; + #endif // SCROLLBACK_PATCH + + for (im = term.images; im; im = next) { + next = im->next; + im->y += n; + + /* check if the current sixel has exceeded the maximum + * draw distance, and should therefore be deleted */ + if (im->y < top) { + //fprintf(stderr, "im@0x%08x exceeded maximum distance\n"); + delete_image(im); + } + } +} + +void +delete_image(ImageList *im) +{ + if (im->prev) + im->prev->next = im->next; + else + term.images = im->next; + if (im->next) + im->next->prev = im->prev; + if (im->pixmap) + XFreePixmap(xw.dpy, (Drawable)im->pixmap); + if (im->clipmask) + XFreePixmap(xw.dpy, (Drawable)im->clipmask); + free(im->pixels); + free(im); +} + static int set_default_color(sixel_image_t *image) { @@ -171,12 +212,14 @@ end: static void sixel_image_deinit(sixel_image_t *image) { - free(image->data); + if (image->data) + free(image->data); image->data = NULL; } int sixel_parser_init(sixel_state_t *st, + int transparent, sixel_color_t fgcolor, sixel_color_t bgcolor, unsigned char use_private_register, int cell_width, int cell_height) @@ -192,6 +235,7 @@ sixel_parser_init(sixel_state_t *st, st->attributed_pad = 1; st->attributed_ph = 0; st->attributed_pv = 0; + st->transparent = transparent; st->repeat_count = 1; st->color_index = 16; st->grid_width = cell_width; @@ -200,7 +244,7 @@ sixel_parser_init(sixel_state_t *st, st->param = 0; /* buffer initialization */ - status = sixel_image_init(&st->image, 1, 1, fgcolor, bgcolor, use_private_register); + status = sixel_image_init(&st->image, 1, 1, fgcolor, transparent ? 0 : bgcolor, use_private_register); return status; } @@ -212,16 +256,19 @@ sixel_parser_set_default_color(sixel_state_t *st) } int -sixel_parser_finalize(sixel_state_t *st, unsigned char *pixels) +sixel_parser_finalize(sixel_state_t *st, ImageList **newimages, int cx, int cy, int cw, int ch) { - int status = (-1); - int sx; - int sy; sixel_image_t *image = &st->image; int x, y; sixel_color_no_t *src; - unsigned char *dst; + sixel_color_t *dst; int color; + int w, h; + int i, j, cols, numimages; + ImageList *im, *next, *tail; + + if (!image->data) + return -1; if (++st->max_x < st->attributed_ph) st->max_x = st->attributed_ph; @@ -229,79 +276,86 @@ sixel_parser_finalize(sixel_state_t *st, unsigned char *pixels) if (++st->max_y < st->attributed_pv) st->max_y = st->attributed_pv; - sx = (st->max_x + st->grid_width - 1) / st->grid_width * st->grid_width; - sy = (st->max_y + st->grid_height - 1) / st->grid_height * st->grid_height; - - if (image->width > sx || image->height > sy) { - status = image_buffer_resize(image, sx, sy); - if (status < 0) - goto end; - } - if (image->use_private_register && image->ncolors > 2 && !image->palette_modified) { - status = set_default_color(image); - if (status < 0) - goto end; + if (set_default_color(image) < 0) + return -1; } - src = st->image.data; - dst = pixels; - for (y = 0; y < st->image.height; ++y) { - for (x = 0; x < st->image.width; ++x) { - color = st->image.palette[*src++]; - *dst++ = color >> 16 & 0xff; /* b */ - *dst++ = color >> 8 & 0xff; /* g */ - *dst++ = color >> 0 & 0xff; /* r */ - *dst++ = 255; /* a */ + w = MIN(st->max_x, image->width); + h = MIN(st->max_y, image->height); + + if ((numimages = (h + ch-1) / ch) <= 0) + return -1; + + cols = (w + cw-1) / cw; + + *newimages = NULL, tail = NULL; + for (y = 0, i = 0; i < numimages; i++) { + if ((im = malloc(sizeof(ImageList)))) { + if (!tail) { + *newimages = tail = im; + im->prev = im->next = NULL; + } else { + tail->next = im; + im->prev = tail; + im->next = NULL; + tail = im; + } + im->x = cx; + im->y = cy + i; + im->cols = cols; + im->width = w; + im->height = MIN(h - ch * i, ch); + im->pixels = malloc(im->width * im->height * 4); + im->pixmap = NULL; + im->clipmask = NULL; + im->cw = cw; + im->ch = ch; + im->transparent = st->transparent; } - /* fill right padding with bgcolor */ - for (; x < st->image.width; ++x) { - color = st->image.palette[0]; /* bgcolor */ - *dst++ = color >> 16 & 0xff; /* b */ - *dst++ = color >> 8 & 0xff; /* g */ - *dst++ = color >> 0 & 0xff; /* r */ - dst++; /* a */ + if (!im || !im->pixels) { + for (im = *newimages; im; im = next) { + next = im->next; + if (im->pixels) + free(im->pixels); + free(im); + } + *newimages = NULL; + return -1; } - } - /* fill bottom padding with bgcolor */ - for (; y < st->image.height; ++y) { - for (x = 0; x < st->image.width; ++x) { - color = st->image.palette[0]; /* bgcolor */ - *dst++ = color >> 16 & 0xff; /* b */ - *dst++ = color >> 8 & 0xff; /* g */ - *dst++ = color >> 0 & 0xff; /* r */ - dst++; /* a */ + dst = (sixel_color_t *)im->pixels; + for (j = 0; j < im->height && y < h; j++, y++) { + src = st->image.data + image->width * y; + for (x = 0; x < w; x++) + *dst++ = st->image.palette[*src++]; } } - status = (0); - -end: - return status; + return numimages; } /* convert sixel data into indexed pixel bytes and palette data */ int -sixel_parser_parse(sixel_state_t *st, unsigned char *p, size_t len) +sixel_parser_parse(sixel_state_t *st, const unsigned char *p, size_t len) { - int status = (-1); - int n; + int n = 0; int i; int x; int y; int bits; - int sixel_vertical_mask; int sx; int sy; int c; int pos; - unsigned char *p0 = p; + int width; + const unsigned char *p0 = p, *p2 = p + len; sixel_image_t *image = &st->image; + sixel_color_no_t *data, color_index; - if (! image->data) - goto end; + if (!image->data) + st->state = PS_ERROR; - while (p < p0 + len) { + while (p < p2) { switch (st->state) { case PS_ESC: goto end; @@ -310,7 +364,6 @@ sixel_parser_parse(sixel_state_t *st, unsigned char *p, size_t len) switch (*p) { case '\x1b': st->state = PS_ESC; - p++; break; case '"': st->param = 0; @@ -355,14 +408,15 @@ sixel_parser_parse(sixel_state_t *st, unsigned char *p, size_t len) sy *= 2; } - if (sx > DECSIXEL_WIDTH_MAX) - sx = DECSIXEL_WIDTH_MAX; - if (sy > DECSIXEL_HEIGHT_MAX) - sy = DECSIXEL_HEIGHT_MAX; + sx = MIN(sx, DECSIXEL_WIDTH_MAX); + sy = MIN(sy, DECSIXEL_HEIGHT_MAX); - status = image_buffer_resize(image, sx, sy); - if (status < 0) - goto end; + if (image_buffer_resize(image, sx, sy) < 0) { + perror("sixel_parser_parse() failed"); + st->state = PS_ERROR; + p++; + break; + } } if (st->color_index > image->ncolors) @@ -371,46 +425,47 @@ sixel_parser_parse(sixel_state_t *st, unsigned char *p, size_t len) if (st->pos_x + st->repeat_count > image->width) st->repeat_count = image->width - st->pos_x; - if (st->repeat_count > 0 && st->pos_y - 5 < image->height) { + if (st->repeat_count > 0 && st->pos_y + 5 < image->height) { bits = *p - '?'; if (bits != 0) { - sixel_vertical_mask = 0x01; + data = image->data + image->width * st->pos_y + st->pos_x; + width = image->width; + color_index = st->color_index; if (st->repeat_count <= 1) { - for (i = 0; i < 6; i++) { - if ((bits & sixel_vertical_mask) != 0) { - pos = image->width * (st->pos_y + i) + st->pos_x; - image->data[pos] = st->color_index; - if (st->max_x < st->pos_x) - st->max_x = st->pos_x; - if (st->max_y < (st->pos_y + i)) - st->max_y = st->pos_y + i; - } - sixel_vertical_mask <<= 1; - } + if (bits & 0x01) + *data = color_index, n = 0; + data += width; + if (bits & 0x02) + *data = color_index, n = 1; + data += width; + if (bits & 0x04) + *data = color_index, n = 2; + data += width; + if (bits & 0x08) + *data = color_index, n = 3; + data += width; + if (bits & 0x10) + *data = color_index, n = 4; + if (bits & 0x20) + data[width] = color_index, n = 5; + if (st->max_x < st->pos_x) + st->max_x = st->pos_x; } else { /* st->repeat_count > 1 */ - for (i = 0; i < 6; i++) { - if ((bits & sixel_vertical_mask) != 0) { - c = sixel_vertical_mask << 1; - for (n = 1; (i + n) < 6; n++) { - if ((bits & c) == 0) - break; - c <<= 1; - } - for (y = st->pos_y + i; y < st->pos_y + i + n; ++y) { - for (x = st->pos_x; x < st->pos_x + st->repeat_count; ++x) - image->data[image->width * y + x] = st->color_index; - } - if (st->max_x < (st->pos_x + st->repeat_count - 1)) - st->max_x = st->pos_x + st->repeat_count - 1; - if (st->max_y < (st->pos_y + i + n - 1)) - st->max_y = st->pos_y + i + n - 1; - i += (n - 1); - sixel_vertical_mask <<= (n - 1); + for (i = 0; bits; bits >>= 1, i++, data += width) { + if (bits & 1) { + data[0] = color_index; + data[1] = color_index; + for (x = 2; x < st->repeat_count; x++) + data[x] = color_index; + n = i; } - sixel_vertical_mask <<= 1; } + if (st->max_x < (st->pos_x + st->repeat_count - 1)) + st->max_x = st->pos_x + st->repeat_count - 1; } + if (st->max_y < (st->pos_y + n)) + st->max_y = st->pos_y + n; } } if (st->repeat_count > 0) @@ -427,7 +482,6 @@ sixel_parser_parse(sixel_state_t *st, unsigned char *p, size_t len) switch (*p) { case '\x1b': st->state = PS_ESC; - p++; break; case '0': case '1': @@ -440,8 +494,7 @@ sixel_parser_parse(sixel_state_t *st, unsigned char *p, size_t len) case '8': case '9': st->param = st->param * 10 + *p - '0'; - if (st->param > DECSIXEL_PARAMVALUE_MAX) - st->param = DECSIXEL_PARAMVALUE_MAX; + st->param = MIN(st->param, DECSIXEL_PARAMVALUE_MAX); p++; break; case ';': @@ -469,25 +522,22 @@ sixel_parser_parse(sixel_state_t *st, unsigned char *p, size_t len) if (image->width < st->attributed_ph || image->height < st->attributed_pv) { - sx = st->attributed_ph; - if (image->width > st->attributed_ph) - sx = image->width; + sx = MAX(image->width, st->attributed_ph); + sy = MAX(image->height, st->attributed_pv); - sy = st->attributed_pv; - if (image->height > st->attributed_pv) - sy = image->height; + /* the height of the image buffer must be divisible by 6 + * to avoid unnecessary resizing of the image buffer when + * parsing the last sixel line */ + sy = (sy + 5) / 6 * 6; - sx = (sx + st->grid_width - 1) / st->grid_width * st->grid_width; - sy = (sy + st->grid_height - 1) / st->grid_height * st->grid_height; + sx = MIN(sx, DECSIXEL_WIDTH_MAX); + sy = MIN(sy, DECSIXEL_HEIGHT_MAX); - if (sx > DECSIXEL_WIDTH_MAX) - sx = DECSIXEL_WIDTH_MAX; - if (sy > DECSIXEL_HEIGHT_MAX) - sy = DECSIXEL_HEIGHT_MAX; - - status = image_buffer_resize(image, sx, sy); - if (status < 0) - goto end; + if (image_buffer_resize(image, sx, sy) < 0) { + perror("sixel_parser_parse() failed"); + st->state = PS_ERROR; + break; + } } st->state = PS_DECSIXEL; st->param = 0; @@ -500,7 +550,6 @@ sixel_parser_parse(sixel_state_t *st, unsigned char *p, size_t len) switch (*p) { case '\x1b': st->state = PS_ESC; - p++; break; case '0': case '1': @@ -513,14 +562,11 @@ sixel_parser_parse(sixel_state_t *st, unsigned char *p, size_t len) case '8': case '9': st->param = st->param * 10 + *p - '0'; - if (st->param > DECSIXEL_PARAMVALUE_MAX) - st->param = DECSIXEL_PARAMVALUE_MAX; + st->param = MIN(st->param, DECSIXEL_PARAMVALUE_MAX); p++; break; default: - st->repeat_count = st->param; - if (st->repeat_count == 0) - st->repeat_count = 1; + st->repeat_count = MAX(st->param, 1); st->state = PS_DECSIXEL; st->param = 0; st->nparams = 0; @@ -533,7 +579,6 @@ sixel_parser_parse(sixel_state_t *st, unsigned char *p, size_t len) switch (*p) { case '\x1b': st->state = PS_ESC; - p++; break; case '0': case '1': @@ -546,8 +591,7 @@ sixel_parser_parse(sixel_state_t *st, unsigned char *p, size_t len) case '8': case '9': st->param = st->param * 10 + *p - '0'; - if (st->param > DECSIXEL_PARAMVALUE_MAX) - st->param = DECSIXEL_PARAMVALUE_MAX; + st->param = MIN(st->param, DECSIXEL_PARAMVALUE_MAX); p++; break; case ';': @@ -574,22 +618,16 @@ sixel_parser_parse(sixel_state_t *st, unsigned char *p, size_t len) st->image.palette_modified = 1; if (st->params[1] == 1) { /* HLS */ - if (st->params[2] > 360) - st->params[2] = 360; - if (st->params[3] > 100) - st->params[3] = 100; - if (st->params[4] > 100) - st->params[4] = 100; + st->params[2] = MIN(st->params[2], 360); + st->params[3] = MIN(st->params[3], 100); + st->params[4] = MIN(st->params[4], 100); image->palette[st->color_index] = hls_to_rgb(st->params[2], st->params[3], st->params[4]); } else if (st->params[1] == 2) { /* RGB */ - if (st->params[2] > 100) - st->params[2] = 100; - if (st->params[3] > 100) - st->params[3] = 100; - if (st->params[4] > 100) - st->params[4] = 100; + st->params[2] = MIN(st->params[2], 100); + st->params[3] = MIN(st->params[3], 100); + st->params[4] = MIN(st->params[4], 100); image->palette[st->color_index] = SIXEL_XRGB(st->params[2], st->params[3], st->params[4]); } @@ -597,15 +635,21 @@ sixel_parser_parse(sixel_state_t *st, unsigned char *p, size_t len) break; } break; + + case PS_ERROR: + if (*p == '\x1b') { + st->state = PS_ESC; + goto end; + } + p++; + break; default: break; } } - status = (0); - end: - return status; + return p - p0; } void @@ -614,3 +658,35 @@ sixel_parser_deinit(sixel_state_t *st) if (st) sixel_image_deinit(&st->image); } + +Pixmap +sixel_create_clipmask(char *pixels, int width, int height) +{ + char c, *clipdata, *dst; + int b, i, n, y, w; + int msb = (XBitmapBitOrder(xw.dpy) == MSBFirst); + sixel_color_t *src = (sixel_color_t *)pixels; + Pixmap clipmask; + + clipdata = dst = malloc((width+7)/8 * height); + if (!clipdata) + return (Pixmap)None; + + for (y = 0; y < height; y++) { + for (w = width; w > 0; w -= n) { + n = MIN(w, 8); + if (msb) { + for (b = 0x80, c = 0, i = 0; i < n; i++, b >>= 1) + c |= (*src++) ? b : 0; + } else { + for (b = 0x01, c = 0, i = 0; i < n; i++, b <<= 1) + c |= (*src++) ? b : 0; + } + *dst++ = c; + } + } + + clipmask = XCreateBitmapFromData(xw.dpy, xw.win, clipdata, width, height); + free(clipdata); + return clipmask; +} diff --git a/st-flexipatch/sixel.h b/st-flexipatch/sixel.h index 8a05c44..7d14f8a 100644 --- a/st-flexipatch/sixel.h +++ b/st-flexipatch/sixel.h @@ -26,6 +26,7 @@ typedef enum parse_state { PS_DECGRA = 3, /* DECGRA Set Raster Attributes " Pan; Pad; Ph; Pv */ PS_DECGRI = 4, /* DECGRI Graphics Repeat Introducer ! Pn Ch */ PS_DECGCI = 5, /* DECGCI Graphics Color Introducer # Pc; Pu; Px; Py; Pz */ + PS_ERROR = 6, } parse_state_t; typedef struct parser_context { @@ -38,6 +39,7 @@ typedef struct parser_context { int attributed_pad; int attributed_ph; int attributed_pv; + int transparent; int repeat_count; int color_index; int bgindex; @@ -49,10 +51,13 @@ typedef struct parser_context { sixel_image_t image; } sixel_state_t; -int sixel_parser_init(sixel_state_t *st, sixel_color_t fgcolor, sixel_color_t bgcolor, unsigned char use_private_register, int cell_width, int cell_height); -int sixel_parser_parse(sixel_state_t *st, unsigned char *p, size_t len); +void scroll_images(int n); +void delete_image(ImageList *im); +int sixel_parser_init(sixel_state_t *st, int transparent, sixel_color_t fgcolor, sixel_color_t bgcolor, unsigned char use_private_register, int cell_width, int cell_height); +int sixel_parser_parse(sixel_state_t *st, const unsigned char *p, size_t len); int sixel_parser_set_default_color(sixel_state_t *st); -int sixel_parser_finalize(sixel_state_t *st, unsigned char *pixels); +int sixel_parser_finalize(sixel_state_t *st, ImageList **newimages, int cx, int cy, int cw, int ch); void sixel_parser_deinit(sixel_state_t *st); +Pixmap sixel_create_clipmask(char *pixels, int width, int height); #endif diff --git a/st-flexipatch/sixel_hls.c b/st-flexipatch/sixel_hls.c index 4f157b2..c88241c 100644 --- a/st-flexipatch/sixel_hls.c +++ b/st-flexipatch/sixel_hls.c @@ -30,7 +30,7 @@ // sale, use or other dealings in this Software without prior written // authorization. -#define SIXEL_RGB(r, g, b) (((r) << 16) + ((g) << 8) + (b)) +#define SIXEL_RGB(r, g, b) ((r) + ((g) << 8) + ((b) << 16) + (255 << 24)) int hls_to_rgb(int hue, int lum, int sat) diff --git a/st-flexipatch/st.c b/st-flexipatch/st.c index 862040b..f1fc668 100644 --- a/st-flexipatch/st.c +++ b/st-flexipatch/st.c @@ -14,16 +14,13 @@ #include #include #include +#include #include #include #include "st.h" #include "win.h" -#if VIM_BROWSE_PATCH -#include -#endif // VIM_BROWSE_PATCH - #if KEYBOARDSELECT_PATCH #include #include @@ -51,6 +48,8 @@ #endif // UNDERCURL_PATCH #define STR_BUF_SIZ ESC_BUF_SIZ #define STR_ARG_SIZ ESC_ARG_SIZ +#define STR_TERM_ST "\033\\" +#define STR_TERM_BEL "\007" /* macros */ #define IS_SET(flag) ((term.mode & (flag)) != 0) @@ -58,24 +57,30 @@ #define ISCONTROLC1(c) (BETWEEN(c, 0x80, 0x9f)) #define ISCONTROL(c) (ISCONTROLC0(c) || ISCONTROLC1(c)) #define ISDELIM(u) (u && wcschr(worddelimiters, u)) -#if VIM_BROWSE_PATCH -static inline int max(int a, int b) { return a > b ? a : b; } -static inline int min(int a, int b) { return a < b ? a : b; } -#endif // VIM_BROWSE_PATCH 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, + 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, #if SIXEL_PATCH - MODE_SIXEL = 1 << 7, + MODE_SIXEL = 1 << 7, + MODE_SIXEL_CUR_RT = 1 << 8, + MODE_SIXEL_SDM = 1 << 9 #endif // SIXEL_PATCH }; +#if REFLOW_PATCH +enum scroll_mode { + SCROLL_RESIZE = -1, + SCROLL_NOSAVEHIST = 0, + SCROLL_SAVEHIST = 1 +}; +#endif // REFLOW_PATCH + enum cursor_movement { CURSOR_SAVE, CURSOR_LOAD @@ -114,9 +119,6 @@ typedef struct { int mode; int type; int snap; - #if VIM_BROWSE_PATCH - int swap; - #endif // VIM_BROWSE_PATCH /* * Selection variables: * nb – normalized coordinates of the beginning of the selection @@ -154,6 +156,7 @@ typedef struct { size_t len; /* raw string length */ char *args[STR_ARG_SIZ]; int narg; /* nb of args */ + char *term; /* terminator: ST or BEL */ } STREscape; static void execsh(char *, char **); @@ -163,13 +166,15 @@ static void ttywriteraw(const char *, size_t); static void csidump(void); static void csihandle(void); +#if SIXEL_PATCH +static void dcshandle(void); +#endif // SIXEL_PATCH #if UNDERCURL_PATCH static void readcolonargs(char **, int, int[][CAR_PER_ARG]); #endif // UNDERCURL_PATCH static void csiparse(void); static void csireset(void); -static void osc4_color_response(int num); -static void osc_color_response(int index, int num); +static void osc_color_response(int, int, int); static int eschandle(uchar); static void strdump(void); static void strhandle(void); @@ -180,31 +185,44 @@ static void tprinter(char *, size_t); static void tdumpsel(void); static void tdumpline(int); static void tdump(void); +#if !REFLOW_PATCH static void tclearregion(int, int, int, int); +#endif // REFLOW_PATCH static void tcursor(int); +static void tresetcursor(void); +#if !REFLOW_PATCH static void tdeletechar(int); +#endif // REFLOW_PATCH +#if SIXEL_PATCH +static void tdeleteimages(void); +#endif // SIXEL_PATCH static void tdeleteline(int); static void tinsertblank(int); static void tinsertblankline(int); +#if !REFLOW_PATCH static int tlinelen(int); -#if !VIM_BROWSE_PATCH +#endif // REFLOW_PATCH static void tmoveto(int, int); -#endif // VIM_BROWSE_PATCH static void tmoveato(int, int); static void tnewline(int); static void tputtab(int); static void tputc(Rune); static void treset(void); +#if !REFLOW_PATCH #if SCROLLBACK_PATCH static void tscrollup(int, int, int); #else static void tscrollup(int, int); #endif // SCROLLBACK_PATCH +#endif // REFLOW_PATCH 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); +#if SIXEL_PATCH +static inline void tsetsixelattr(Line line, int x1, int x2); +#endif // SIXEL_PATCH static void tswapscreen(void); static void tsetmode(int, int, const int *, int); static int twrite(const char *, int, int); @@ -215,15 +233,15 @@ static int32_t tdefcolor(const int *, int *, int); static void tdeftran(char); static void tstrsequence(uchar); static void selnormalize(void); +#if !REFLOW_PATCH static void selscroll(int, int); -#if !VIM_BROWSE_PATCH +#endif // REFLOW_PATCH static void selsnap(int *, int *, int); -#endif // VIM_BROWSE_PATCH 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 inline Rune utf8decodebyte(char, size_t *); +static inline char utf8encodebyte(Rune, size_t); +static inline size_t utf8validate(Rune *, size_t); static char *base64dec(const char *); static char base64dec_getc(const char **); @@ -249,16 +267,6 @@ 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}; -#if VIM_BROWSE_PATCH -int buffCols; -extern int const buffSize; -int histOp, histMode, histOff, insertOff, altToggle, *mark; -Line *buf = NULL; -static TCursor c[3]; -static inline int rows() { return IS_SET(MODE_ALTSCREEN) ? term.row : buffSize;} -static inline int rangeY(int i) { while (i < 0) i += rows(); return i % rows();} -#endif // VIM_BROWSE_PATCH - #include "patch/st_include.h" ssize_t @@ -311,24 +319,27 @@ xstrdup(const char *s) size_t utf8decode(const char *c, Rune *u, size_t clen) { - size_t i, j, len, type; + size_t i, len; Rune udecoded; *u = UTF_INVALID; if (!clen) return 0; udecoded = utf8decodebyte(c[0], &len); - if (!BETWEEN(len, 1, UTF_SIZ)) + if (!BETWEEN(len, 2, UTF_SIZ)) { + *u = (len == 1) ? udecoded : UTF_INVALID; 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) + clen = MIN(clen, len); + for (i = 1; i < clen; ++i) { + if ((c[i] & 0xC0) != 0x80) + return i; + udecoded = (udecoded << 6) | (c[i] & 0x3F); + } + if (i < len) return 0; - *u = udecoded; - utf8validate(u, len); + *u = (!BETWEEN(udecoded, utfmin[len], utfmax[len]) || BETWEEN(udecoded, 0xD800, 0xDFFF)) + ? UTF_INVALID : udecoded; return len; } @@ -432,6 +443,7 @@ selinit(void) sel.ob.x = -1; } +#if !REFLOW_PATCH int tlinelen(int y) { @@ -453,118 +465,7 @@ tlinelen(int y) return i; } - -#if VIM_BROWSE_PATCH -void historyOpToggle(int start, int paint) { - if ((!histOp == !(histOp + start)) && ((histOp += start) || 1)) return; - if (histMode && paint && (!IS_SET(MODE_ALTSCREEN) || altToggle)) draw(); - tcursor(CURSOR_SAVE); - histOp += start; - if (histMode && altToggle) { - tswapscreen(); - memset(term.dirty,0,sizeof(*term.dirty)*term.row); - } - tcursor(CURSOR_LOAD); - *(!IS_SET(MODE_ALTSCREEN)?&term.line:&term.alt)=&buf[histOp?histOff:insertOff]; -} - -void historyModeToggle(int start) { - if (!(histMode = (histOp = !!start))) { - selnormalize(); - tfulldirt(); - } else { - tcursor(CURSOR_SAVE); - histOp = 0; - histOff = insertOff; - } -} - -int historyBufferScroll(int n) { - if (IS_SET(MODE_ALTSCREEN) || !n) return histOp; - int p=abs(n=(n<0) ? max(n,-term.row) : min(n,term.row)), r=term.row-p, - s=sizeof(*term.dirty), *ptr=histOp?&histOff:&insertOff; - if (!histMode || histOp) tfulldirt(); else { - memmove(&term.dirty[-min(n,0)], &term.dirty[max(n,0)], s*r); - memset(&term.dirty[n>0 ? r : 0], 0, s * p); - } - term.line = &buf[*ptr = (buffSize+*ptr+n) % buffSize]; - // Cut part of selection removed from buffer, and update sel.ne/b. - int const prevOffBuf = sel.alt ? 0 : insertOff + term.row; - if (sel.ob.x != -1 && !histOp && n) { - int const offBuf = sel.alt ? 0 : insertOff + term.row, - pb = rangeY(sel.ob.y - prevOffBuf), - pe = rangeY(sel.oe.y - prevOffBuf); - int const b = rangeY(sel.ob.y - offBuf), nln = n < 0, - e = rangeY(sel.oe.y - offBuf), last = offBuf - nln; - if (pb != b && ((pb < b) != nln)) sel.ob.y = last; - if (pe != e && ((pe < e) != nln)) sel.oe.y = last; - if (sel.oe.y == last && sel.ob.y == last) selclear(); - } - selnormalize(); - // Clear the new region exposed by the shift. - if (!histOp) tclearregion(0, n>0?r+1:0, buffCols-1, n>0?term.row:p-1); - return 1; -} - -int historyMove(int x, int y, int ly) { - historyOpToggle(1, 1); - y += ((term.c.x += x) < 0 ?term.c.x-term.col :term.c.x) / term.col;//< x - if ((term.c.x %= term.col) < 0) term.c.x += term.col; - if ((term.c.y += y) >= term.row) ly += term.c.y - term.row + 1; //< y - else if (term.c.y < 0) ly += term.c.y; - term.c.y = MIN(MAX(term.c.y, 0), term.row - 1); - // Check if scroll is necessary / arrived at top / bottom of terminal history - int t = 0, b = 0, finTop = ly < 0, finBot = ly > 0; - if (!IS_SET(MODE_ALTSCREEN)) { - b=rangeY(insertOff-histOff), t=-rangeY(-term.row-(insertOff-histOff)); - finBot = ly > b, finTop=histMode&&((-ly>-t)); - } - if ((finTop || finBot) && (x||y)) term.c.x = finBot ? term.col-1 : 0; - historyBufferScroll(finBot ? b : (finTop ? t : ly)); - historyOpToggle(-1, 1); - return finTop || finBot; -} - -void selnormalize(void) { - historyOpToggle(1, 1); - - int const oldb = sel.nb.y, olde = sel.ne.y; - if (sel.ob.x == -1) { - sel.ne.y = sel.nb.y = -1; - } else { - int const offsetBuffer = sel.alt ? 0 : insertOff + term.row; - int const off = sel.alt ? 0 : (histMode ? histOff : insertOff); - int const nby = rangeY(sel.ob.y - off), - ney = rangeY(sel.oe.y - off); - sel.swap = rangeY(sel.ob.y - offsetBuffer) - > rangeY(sel.oe.y - offsetBuffer); - sel.nb.y = sel.swap ? ney : nby; - sel.ne.y = !sel.swap ? ney : nby; - int const cnb = sel.nb.y < term.row, cne = sel.ne.y < term.row; - if (sel.type == SEL_REGULAR && sel.ob.y != sel.oe.y) { - if (cnb) sel.nb.x = (!sel.swap) ? sel.ob.x : sel.oe.x; - if (cne) sel.ne.x = (!sel.swap) ? sel.oe.x : sel.ob.x; - } else { - if (cnb) sel.nb.x = MIN(sel.ob.x, sel.oe.x); - if (cne) sel.ne.x = MAX(sel.ob.x, sel.oe.x); - } - } - int const nBet=sel.nb.y<=sel.ne.y, oBet=oldb<=olde; - for (int i = 0; i < term.row; ++i) { - int const n = nBet ? BETWEEN(i, sel.nb.y, sel.ne.y) - : OUT(i, sel.nb.y, sel.ne.y); - term.dirty[i] |= (sel.type == SEL_RECTANGULAR && n) || - (n != (oBet ? BETWEEN(i,oldb,olde) : OUT(i,oldb,olde))); - - } - if (BETWEEN(oldb, 0, term.row - 1)) term.dirty[oldb] = 1; - if (BETWEEN(olde, 0, term.row - 1)) term.dirty[olde] = 1; - if (BETWEEN(sel.nb.y, 0, term.row - 1)) term.dirty[sel.nb.y] = 1; - if (BETWEEN(sel.ne.y, 0, term.row - 1)) term.dirty[sel.ne.y] = 1; - - historyOpToggle(-1, 1); -} -#endif // VIM_BROWSE_PATCH +#endif // REFLOW_PATCH void selstart(int col, int row, int snap) @@ -575,27 +476,18 @@ selstart(int col, int row, int snap) sel.alt = IS_SET(MODE_ALTSCREEN); sel.snap = snap; sel.oe.x = sel.ob.x = col; - #if VIM_BROWSE_PATCH - sel.oe.y = sel.ob.y = row + !sel.alt * (histMode ? histOff : insertOff); - if (sel.snap != 0) sel.mode = SEL_READY; - #else sel.oe.y = sel.ob.y = row; - #endif // VIM_BROWSE_PATCH selnormalize(); - #if !VIM_BROWSE_PATCH if (sel.snap != 0) sel.mode = SEL_READY; tsetdirt(sel.nb.y, sel.ne.y); - #endif // VIM_BROWSE_PATCH } void selextend(int col, int row, int type, int done) { - #if !VIM_BROWSE_PATCH int oldey, oldex, oldsby, oldsey, oldtype; - #endif // VIM_BROWSE_PATCH if (sel.mode == SEL_IDLE) return; @@ -604,32 +496,23 @@ selextend(int col, int row, int type, int done) return; } - #if !VIM_BROWSE_PATCH oldey = sel.oe.y; oldex = sel.oe.x; oldsby = sel.nb.y; oldsey = sel.ne.y; oldtype = sel.type; - #endif // VIM_BROWSE_PATCH sel.oe.x = col; - #if VIM_BROWSE_PATCH - sel.oe.y = row + (sel.alt ? 0 : (histMode ? histOff : insertOff)); - #else sel.oe.y = row; - #endif // VIM_BROWSE_PATCH - selnormalize(); sel.type = type; + selnormalize(); - #if !VIM_BROWSE_PATCH 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)); - #endif // VIM_BROWSE_PATCH sel.mode = done ? SEL_IDLE : SEL_READY; } -#if !VIM_BROWSE_PATCH void selnormalize(void) { @@ -651,14 +534,23 @@ selnormalize(void) /* expand selection over line breaks */ if (sel.type == SEL_RECTANGULAR) return; + + #if REFLOW_PATCH + i = tlinelen(TLINE(sel.nb.y)); + if (sel.nb.x > i) + sel.nb.x = i; + if (sel.ne.x >= tlinelen(TLINE(sel.ne.y))) + sel.ne.x = term.col - 1; + #else 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; + #endif // REFLOW_PATCH } -#endif // VIM_BROWSE_PATCH +#if !REFLOW_PATCH int selected(int x, int y) { @@ -670,19 +562,13 @@ selected(int x, int y) return BETWEEN(y, sel.nb.y, sel.ne.y) && BETWEEN(x, sel.nb.x, sel.ne.x); - #if VIM_BROWSE_PATCH - return ((sel.nb.y > sel.ne.y) ? OUT(y, sel.nb.y, sel.ne.y) - : BETWEEN(y, sel.nb.y, sel.ne.y)) && - (y != sel.nb.y || x >= sel.nb.x) && - (y != sel.ne.y || x <= sel.ne.x); - #else 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); - #endif // VIM_BROWSE_PATCH } +#endif // REFLOW_PATCH -#if !VIM_BROWSE_PATCH +#if !REFLOW_PATCH void selsnap(int *x, int *y, int direction) { @@ -775,87 +661,53 @@ selsnap(int *x, int *y, int direction) break; } } -#endif // VIM_BROWSE_PATCH +#endif // REFLOW_PATCH +#if !REFLOW_PATCH char * getsel(void) { char *str, *ptr; - #if VIM_BROWSE_PATCH - int y, yy, bufsize, lastx; - #else int y, bufsize, lastx, linelen; - #endif // VIM_BROWSE_PATCH const Glyph *gp, *last; if (sel.ob.x == -1) return NULL; - #if VIM_BROWSE_PATCH - int const start = sel.swap ? sel.oe.y : sel.ob.y, h = rows(); - int endy = (sel.swap ? sel.ob.y : sel.oe.y); - for (; endy < start; endy += h); - Line * const cbuf = IS_SET(MODE_ALTSCREEN) ? term.line : buf; - bufsize = (term.col+1) * (endy-start+1 ) * UTF_SIZ; - assert(bufsize > 0); - #else bufsize = (term.col+1) * (sel.ne.y-sel.nb.y+1) * UTF_SIZ; - #endif // VIM_BROWSE_PATCH ptr = str = xmalloc(bufsize); /* append every set & selected glyph to the selection */ - #if VIM_BROWSE_PATCH - for (y = start; y <= endy; y++) - #else for (y = sel.nb.y; y <= sel.ne.y; y++) - #endif // VIM_BROWSE_PATCH { - #if VIM_BROWSE_PATCH - yy = y % h; - #else if ((linelen = tlinelen(y)) == 0) { *ptr++ = '\n'; continue; } - #endif // VIM_BROWSE_PATCH if (sel.type == SEL_RECTANGULAR) { - #if VIM_BROWSE_PATCH - gp = &cbuf[yy][sel.nb.x]; - #elif SCROLLBACK_PATCH + #if SCROLLBACK_PATCH gp = &TLINE(y)[sel.nb.x]; #else gp = &term.line[y][sel.nb.x]; #endif // SCROLLBACK_PATCH lastx = sel.ne.x; } else { - #if VIM_BROWSE_PATCH - gp = &cbuf[yy][start == y ? sel.nb.x : 0]; - #elif SCROLLBACK_PATCH + #if SCROLLBACK_PATCH gp = &TLINE(y)[sel.nb.y == y ? sel.nb.x : 0]; #else gp = &term.line[y][sel.nb.y == y ? sel.nb.x : 0]; #endif // SCROLLBACK_PATCH - #if VIM_BROWSE_PATCH - lastx = (endy == y) ? sel.ne.x : term.col-1; - #else lastx = (sel.ne.y == y) ? sel.ne.x : term.col-1; - #endif // VIM_BROWSE_PATCH } - #if VIM_BROWSE_PATCH - last = &cbuf[yy][lastx]; - #elif SCROLLBACK_PATCH + + #if SCROLLBACK_PATCH last = &TLINE(y)[MIN(lastx, linelen-1)]; #else last = &term.line[y][MIN(lastx, linelen-1)]; #endif // SCROLLBACK_PATCH - #if VIM_BROWSE_PATCH - if (!(cbuf[yy][term.col - 1].mode & ATTR_WRAP)) - while (last > gp && last->u == ' ') --last; - #else while (last >= gp && last->u == ' ') --last; - #endif // VIM_BROWSE_PATCH for ( ; gp <= last; ++gp) { if (gp->mode & ATTR_WDUMMY) @@ -873,31 +725,29 @@ getsel(void) * st. * FIXME: Fix the computer world. */ - if ( - #if VIM_BROWSE_PATCH - (y < endy || lastx == term.col - 1) - #else - (y < sel.ne.y || lastx >= linelen) - #endif // + if ((y < sel.ne.y || lastx >= linelen) && (!(last->mode & ATTR_WRAP) || sel.type == SEL_RECTANGULAR)) *ptr++ = '\n'; } *ptr = 0; return str; } +#endif // REFLOW_PATCH void selclear(void) { if (sel.ob.x == -1) return; + selremove(); + tsetdirt(sel.nb.y, sel.ne.y); +} + +void +selremove(void) +{ sel.mode = SEL_IDLE; sel.ob.x = -1; - #if VIM_BROWSE_PATCH - selnormalize(); - #else - tsetdirt(sel.nb.y, sel.ne.y); - #endif // VIM_BROWSE_PATCH } void @@ -1146,10 +996,8 @@ void ttywrite(const char *s, size_t n, int may_echo) { const char *next; - #if SCROLLBACK_PATCH - Arg arg = (Arg) { .i = term.scr }; - - kscrolldown(&arg); + #if REFLOW_PATCH || SCROLLBACK_PATCH + kscrolldown(&((Arg){ .i = term.scr })); #endif // SCROLLBACK_PATCH if (may_echo && IS_SET(MODE_ECHO)) @@ -1293,31 +1141,45 @@ tsetdirtattr(int attr) for (i = 0; i < term.row-1; i++) { for (j = 0; j < term.col-1; j++) { if (term.line[i][j].mode & attr) { + #if REFLOW_PATCH + term.dirty[i] = 1; + #else tsetdirt(i, i); + #endif // REFLOW_PATCH break; } } } } +#if SIXEL_PATCH +void +tsetsixelattr(Line line, int x1, int x2) +{ + for (; x1 <= x2; x1++) + line[x1].mode |= ATTR_SIXEL; +} +#endif // SIXEL_PATCH + void tfulldirt(void) { #if SYNC_PATCH tsync_end(); #endif // SYNC_PATCH + #if REFLOW_PATCH + for (int i = 0; i < term.row; i++) + term.dirty[i] = 1; + #else tsetdirt(0, term.row-1); + #endif // REFLOW_PATCH } void tcursor(int mode) { - #if VIM_BROWSE_PATCH - int alt = (histOp) ? 0 : (IS_SET(MODE_ALTSCREEN) + 1); - #else static TCursor c[2]; int alt = IS_SET(MODE_ALTSCREEN); - #endif // VIM_BROWSE_PATCH if (mode == CURSOR_SAVE) { c[alt] = term.c; @@ -1327,19 +1189,22 @@ tcursor(int mode) } } +void +tresetcursor(void) +{ + term.c = (TCursor){ { .mode = ATTR_NULL, .fg = defaultfg, .bg = defaultbg }, + .x = 0, .y = 0, .state = CURSOR_DEFAULT }; +} + void treset(void) { uint i; - #if SIXEL_PATCH - ImageList *im; - #endif // SIXEL_PATCH + #if REFLOW_PATCH + int x, y; + #endif // REFLOW_PATCH - term.c = (TCursor){{ - .mode = ATTR_NULL, - .fg = defaultfg, - .bg = defaultbg - }, .x = 0, .y = 0, .state = CURSOR_DEFAULT}; + tresetcursor(); memset(term.tabs, 0, term.col * sizeof(*term.tabs)); for (i = tabspaces; i < term.col; i += tabspaces) @@ -1349,23 +1214,39 @@ treset(void) term.mode = MODE_WRAP|MODE_UTF8; memset(term.trantbl, CS_USA, sizeof(term.trantbl)); term.charset = 0; + #if REFLOW_PATCH + term.histf = 0; + term.histi = 0; + term.scr = 0; + selremove(); + #endif // REFLOW_PATCH for (i = 0; i < 2; i++) { + #if REFLOW_PATCH + tcursor(CURSOR_SAVE); /* reset saved cursor */ + for (y = 0; y < term.row; y++) + for (x = 0; x < term.col; x++) + tclearglyph(&term.line[y][x], 0); + #else tmoveto(0, 0); tcursor(CURSOR_SAVE); - #if COLUMNS_PATCH && !VIM_BROWSE_PATCH + #if COLUMNS_PATCH tclearregion(0, 0, term.maxcol-1, term.row-1); #else tclearregion(0, 0, term.col-1, term.row-1); #endif // COLUMNS_PATCH + #endif // REFLOW_PATCH + #if SIXEL_PATCH + tdeleteimages(); + #endif // SIXEL_PATCH tswapscreen(); } - #if SIXEL_PATCH - for (im = term.images; im; im = im->next) - im->should_delete = 1; - #endif // SIXEL_PATCH + #if REFLOW_PATCH + tfulldirt(); + #endif // REFLOW_PATCH } +#if !REFLOW_PATCH void tnew(int col, int row) { @@ -1373,7 +1254,9 @@ tnew(int col, int row) tresize(col, row); treset(); } +#endif // REFLOW_PATCH +#if !REFLOW_PATCH void tswapscreen(void) { @@ -1391,7 +1274,9 @@ tswapscreen(void) term.mode ^= MODE_ALTSCREEN; tfulldirt(); } +#endif // REFLOW_PATCH +#if !REFLOW_PATCH void tscrolldown(int orig, int n) { @@ -1399,17 +1284,23 @@ tscrolldown(int orig, int n) restoremousecursor(); #endif //OPENURLONCLICK_PATCH - #if VIM_BROWSE_PATCH - if (!orig && historyBufferScroll(-n)) - return; - #endif // VIM_BROWSE_PATCH int i; Line temp; + #if SIXEL_PATCH + int bot = term.bot; + #if SCROLLBACK_PATCH + int scr = IS_SET(MODE_ALTSCREEN) ? 0 : term.scr; + #else + int scr = 0; + #endif // SCROLLBACK_PATCH + int itop = orig + scr, ibot = bot + scr; + ImageList *im, *next; + #endif // SIXEL_PATCH LIMIT(n, 0, term.bot-orig+1); tsetdirt(orig, term.bot-n); - #if COLUMNS_PATCH && !VIM_BROWSE_PATCH + #if COLUMNS_PATCH tclearregion(0, term.bot-n+1, term.maxcol-1, term.bot); #else tclearregion(0, term.bot-n+1, term.col-1, term.bot); @@ -1423,11 +1314,12 @@ tscrolldown(int orig, int n) #if SIXEL_PATCH /* move images, if they are inside the scrolling region */ - ImageList *im; - for (im = term.images; im; im = im->next) { - if (im->y * win.ch + im->height > orig * win.ch && im->y <= term.bot) { + for (im = term.images; im; im = next) { + next = im->next; + if (im->y >= itop && im->y <= ibot) { im->y += n; - im->should_delete |= (im->y >= term.row); + if (im->y > ibot) + delete_image(im); } } #endif // SIXEL_PATCH @@ -1439,7 +1331,9 @@ tscrolldown(int orig, int n) selscroll(orig, n); #endif // SCROLLBACK_PATCH } +#endif // REFLOW_PATCH +#if !REFLOW_PATCH void #if SCROLLBACK_PATCH tscrollup(int orig, int n, int copyhist) @@ -1451,12 +1345,18 @@ tscrollup(int orig, int n) restoremousecursor(); #endif //OPENURLONCLICK_PATCH - #if VIM_BROWSE_PATCH - if (!orig && historyBufferScroll(n)) - return; - #endif // VIM_BROWSE_PATCH int i; Line temp; + #if SIXEL_PATCH + int bot = term.bot; + #if SCROLLBACK_PATCH + int scr = IS_SET(MODE_ALTSCREEN) ? 0 : term.scr; + #else + int scr = 0; + #endif // SCROLLBACK_PATCH + int itop = orig + scr, ibot = bot + scr; + ImageList *im, *next; + #endif // SIXEL_PATCH LIMIT(n, 0, term.bot-orig+1); @@ -1475,7 +1375,7 @@ tscrollup(int orig, int n) } #endif // SCROLLBACK_PATCH - #if COLUMNS_PATCH && !VIM_BROWSE_PATCH + #if COLUMNS_PATCH tclearregion(0, orig, term.maxcol-1, orig+n-1); #else tclearregion(0, orig, term.col-1, orig+n-1); @@ -1490,11 +1390,45 @@ tscrollup(int orig, int n) #if SIXEL_PATCH #if SCROLLBACK_PATCH - if (term.scr == 0) - scroll_images(-1 * n); + if (IS_SET(MODE_ALTSCREEN) || !copyhist || orig != 0) { + /* move images, if they are inside the scrolling region */ + for (im = term.images; im; im = next) { + next = im->next; + if (im->y >= itop && im->y <= ibot) { + im->y -= n; + if (im->y < itop) + delete_image(im); + } + } + } else { + /* move images, if they are inside the scrolling region or scrollback */ + for (im = term.images; im; im = next) { + next = im->next; + im->y -= scr; + if (im->y < 0) { + im->y -= n; + } else if (im->y >= orig && im->y <= bot) { + im->y -= n; + if (im->y < orig) + im->y -= orig; // move to scrollback + } + if (im->y < -HISTSIZE) + delete_image(im); + else + im->y += term.scr; + } + } #else - scroll_images(-1 * n); - #endif + /* move images, if they are inside the scrolling region */ + for (im = term.images; im; im = next) { + next = im->next; + if (im->y >= itop && im->y <= ibot) { + im->y -= n; + if (im->y < itop) + delete_image(im); + } + } + #endif // SCROLLBACK_PATCH #endif // SIXEL_PATCH #if SCROLLBACK_PATCH @@ -1504,11 +1438,13 @@ tscrollup(int orig, int n) selscroll(orig, -n); #endif // SCROLLBACK_PATCH } +#endif // REFLOW_PATCH +#if !REFLOW_PATCH void selscroll(int orig, int n) { - if (sel.ob.x == -1) + if (sel.ob.x == -1 || sel.alt != IS_SET(MODE_ALTSCREEN)) return; if (BETWEEN(sel.nb.y, orig, term.bot) != BETWEEN(sel.ne.y, orig, term.bot)) { @@ -1524,6 +1460,7 @@ selscroll(int orig, int n) } } } +#endif // REFLOW_PATCH void tnewline(int first_col) @@ -1531,7 +1468,9 @@ tnewline(int first_col) int y = term.c.y; if (y == term.bot) { - #if SCROLLBACK_PATCH + #if REFLOW_PATCH + tscrollup(term.top, term.bot, 1, SCROLL_SAVEHIST); + #elif SCROLLBACK_PATCH tscrollup(term.top, 1, 1); #else tscrollup(term.top, 1); @@ -1571,6 +1510,7 @@ csiparse(void) { char *p = csiescseq.buf, *np; long int v; + int sep = ';'; /* colon or semi-colon, but not both */ csiescseq.narg = 0; if (*p == '?') { @@ -1591,7 +1531,9 @@ csiparse(void) #if UNDERCURL_PATCH readcolonargs(&p, csiescseq.narg-1, csiescseq.carg); #endif // UNDERCURL_PATCH - if (*p != ';' || csiescseq.narg == ESC_ARG_SIZ) + if (sep == ';' && *p == ':') + sep = ':'; /* allow override to colon once */ + if (*p != sep || csiescseq.narg == ESC_ARG_SIZ) break; p++; } @@ -1657,6 +1599,9 @@ tsetchar(Rune u, const Glyph *attr, int x, int y) term.dirty[y] = 1; term.line[y][x] = *attr; term.line[y][x].u = u; + #if REFLOW_PATCH + term.line[y][x].mode |= ATTR_SET; + #endif // REFLOW_PATCH #if BOXDRAW_PATCH if (isboxdraw(u)) @@ -1664,6 +1609,7 @@ tsetchar(Rune u, const Glyph *attr, int x, int y) #endif // BOXDRAW_PATCH } +#if !REFLOW_PATCH void tclearregion(int x1, int y1, int x2, int y2) { @@ -1675,16 +1621,13 @@ tclearregion(int x1, int y1, int x2, int y2) if (y1 > y2) temp = y1, y1 = y2, y2 = temp; - #if VIM_BROWSE_PATCH - LIMIT(x1, 0, buffCols-1); - LIMIT(x2, 0, buffCols-1); - #elif COLUMNS_PATCH + #if COLUMNS_PATCH LIMIT(x1, 0, term.maxcol-1); LIMIT(x2, 0, term.maxcol-1); #else LIMIT(x1, 0, term.col-1); LIMIT(x2, 0, term.col-1); - #endif // VIM_BROWSE_PATCH + #endif // COLUMNS_PATCH LIMIT(y1, 0, term.row-1); LIMIT(y2, 0, term.row-1); @@ -1701,7 +1644,9 @@ tclearregion(int x1, int y1, int x2, int y2) } } } +#endif // REFLOW_PATCH +#if !REFLOW_PATCH void tdeletechar(int n) { @@ -1718,7 +1663,9 @@ tdeletechar(int n) memmove(&line[dst], &line[src], size * sizeof(Glyph)); tclearregion(term.col-n, term.c.y, term.col-1, term.c.y); } +#endif // REFLOW_PATCH +#if !REFLOW_PATCH void tinsertblank(int n) { @@ -1735,6 +1682,7 @@ tinsertblank(int n) memmove(&line[dst], &line[src], size * sizeof(Glyph)); tclearregion(src, term.c.y, dst - 1, term.c.y); } +#endif // REFLOW_PATCH void tinsertblankline(int n) @@ -1743,15 +1691,31 @@ tinsertblankline(int n) tscrolldown(term.c.y, n); } +#if SIXEL_PATCH +void +tdeleteimages(void) +{ + ImageList *im, *next; + + for (im = term.images; im; im = next) { + next = im->next; + delete_image(im); + } +} +#endif // SIXEL_PATCH + void tdeleteline(int n) { - if (BETWEEN(term.c.y, term.top, term.bot)) - #if SCROLLBACK_PATCH + if (BETWEEN(term.c.y, term.top, term.bot)) { + #if REFLOW_PATCH + tscrollup(term.c.y, term.bot, n, SCROLL_NOSAVEHIST); + #elif SCROLLBACK_PATCH tscrollup(term.c.y, n, 0); #else tscrollup(term.c.y, n); #endif // SCROLLBACK_PATCH + } } int32_t @@ -2050,9 +2014,16 @@ tsetmode(int priv, int set, const int *args, int narg) case 1047: if (!allowaltscreen) break; + #if REFLOW_PATCH + if (set) + tloadaltscreen(*args != 47, *args == 1049); + else + tloaddefscreen(*args != 47, *args == 1049); + break; + #else alt = IS_SET(MODE_ALTSCREEN); if (alt) { - #if COLUMNS_PATCH && !VIM_BROWSE_PATCH + #if COLUMNS_PATCH tclearregion(0, 0, term.maxcol-1, term.row-1); #else tclearregion(0, 0, term.col-1, term.row-1); @@ -2063,7 +2034,12 @@ tsetmode(int priv, int set, const int *args, int narg) if (*args != 1049) break; /* FALLTHROUGH */ + #endif // REFLOW_PATCH case 1048: + #if REFLOW_PATCH + if (!allowaltscreen) + break; + #endif // REFLOW_PATCH tcursor((set) ? CURSOR_SAVE : CURSOR_LOAD); break; case 2004: /* 2004: bracketed paste mode */ @@ -2079,6 +2055,14 @@ tsetmode(int priv, int set, const int *args, int narg) and can be mistaken for other control codes. */ break; + #if SIXEL_PATCH + case 80: /* DECSDM -- Sixel Display Mode */ + MODBIT(term.mode, set, MODE_SIXEL_SDM); + break; + case 8452: /* sixel scrolling leaves cursor to right of graphic */ + MODBIT(term.mode, set, MODE_SIXEL_CUR_RT); + break; + #endif // SIXEL_PATCH default: fprintf(stderr, "erresc: unknown private set/reset mode %d\n", @@ -2115,11 +2099,15 @@ void csihandle(void) { char buffer[40]; - int len; + int n = 0, len; #if SIXEL_PATCH - ImageList *im; + ImageList *im, *next; + int pi, pa; #endif // SIXEL_PATCH - #if COLUMNS_PATCH && !VIM_BROWSE_PATCH + #if REFLOW_PATCH + int x; + #endif // REFLOW_PATCH + #if COLUMNS_PATCH int maxcol = term.maxcol; #else int maxcol = term.col; @@ -2169,7 +2157,7 @@ csihandle(void) ttywrite(vtiden, strlen(vtiden), 0); break; case 'b': /* REP -- if last char is printable print it more times */ - DEFAULT(csiescseq.arg[0], 1); + LIMIT(csiescseq.arg[0], 1, 65535); if (term.lastc) while (csiescseq.arg[0]-- > 0) tputc(term.lastc); @@ -2221,19 +2209,51 @@ csihandle(void) case 'J': /* ED -- Clear screen */ switch (csiescseq.arg[0]) { case 0: /* below */ + #if REFLOW_PATCH + tclearregion(term.c.x, term.c.y, term.col-1, term.c.y, 1); + if (term.c.y < term.row-1) + tclearregion(0, term.c.y+1, term.col-1, term.row-1, 1); + #else tclearregion(term.c.x, term.c.y, maxcol-1, term.c.y); - if (term.c.y < term.row-1) { - tclearregion(0, term.c.y+1, maxcol-1, - term.row-1); - } + if (term.c.y < term.row-1) + tclearregion(0, term.c.y+1, maxcol-1, term.row-1); + #endif // REFLOW_PATCH break; case 1: /* above */ + #if REFLOW_PATCH + if (term.c.y >= 1) + tclearregion(0, 0, term.col-1, term.c.y-1, 1); + tclearregion(0, term.c.y, term.c.x, term.c.y, 1); + #else if (term.c.y > 1) tclearregion(0, 0, maxcol-1, term.c.y-1); tclearregion(0, term.c.y, term.c.x, term.c.y); + #endif // REFLOW_PATCH break; case 2: /* screen */ - #if SCROLLBACK_PATCH || VIM_BROWSE_PATCH + #if REFLOW_PATCH + if (IS_SET(MODE_ALTSCREEN)) { + tclearregion(0, 0, term.col-1, term.row-1, 1); + #if SIXEL_PATCH + tdeleteimages(); + #endif // SIXEL_PATCH + break; + } + /* vte does this: + tscrollup(0, term.row-1, term.row, SCROLL_SAVEHIST); */ + /* alacritty does this: */ + for (n = term.row-1; n >= 0 && tlinelen(term.line[n]) == 0; n--) + ; + #if SIXEL_PATCH + for (im = term.images; im; im = im->next) + n = MAX(im->y - term.scr, n); + #endif // SIXEL_PATCH + if (n >= 0) + tscrollup(0, term.row-1, n+1, SCROLL_SAVEHIST); + tscrollup(0, term.row-1, term.row-n-1, SCROLL_NOSAVEHIST); + break; + #else // !REFLOW_PATCH + #if SCROLLBACK_PATCH if (!IS_SET(MODE_ALTSCREEN)) { #if SCROLLBACK_PATCH kscrolldown(&((Arg){ .i = term.scr })); @@ -2259,26 +2279,29 @@ csihandle(void) #endif // SCROLLBACK_PATCH tclearregion(0, 0, maxcol-1, term.row-1); - #if SIXEL_PATCH - for (im = term.images; im; im = im->next) - im->should_delete = 1; + tdeleteimages(); #endif // SIXEL_PATCH + #endif // REFLOW_PTCH break; case 3: /* scrollback */ - #if VIM_BROWSE_PATCH - if (!IS_SET(MODE_ALTSCREEN)) { - Glyph g=(Glyph){.bg=term.c.attr.bg, .fg=term.c.attr.fg, .u=' ', .mode=0}; - for (int i = 0; i < buffSize; ++i) { - if (!BETWEEN(i, insertOff, insertOff + term.row - 1) && - !(insertOff + term.row > buffSize && - BETWEEN(i, 0, (insertOff + term.row - 1) % buffSize))) { - for (int j = 0; j < term.col; ++j) - buf[i][j] = g; - } - } + #if REFLOW_PATCH + if (IS_SET(MODE_ALTSCREEN)) + break; + kscrolldown(&((Arg){ .i = term.scr })); + term.scr = 0; + term.histi = 0; + term.histf = 0; + #if SIXEL_PATCH + for (im = term.images; im; im = next) { + next = im->next; + if (im->y < 0) + delete_image(im); } - #elif SCROLLBACK_PATCH + #endif // SIXEL_PATCH + break; + #else // !REFLOW_PATCH + #if SCROLLBACK_PATCH if (!IS_SET(MODE_ALTSCREEN)) { term.scr = 0; term.histi = 0; @@ -2291,16 +2314,18 @@ csihandle(void) } #endif // SCROLLBACK_PATCH #if SIXEL_PATCH - if (!IS_SET(MODE_ALTSCREEN)) { - for (im = term.images; im; im = im->next) - im->should_delete |= (im->y * win.ch + im->height <= 0); + for (im = term.images; im; im = next) { + next = im->next; + if (im->y < 0) + delete_image(im); } #endif // SIXEL_PATCH break; + #endif // REFLOW_PATCH #if SIXEL_PATCH case 6: /* sixels */ - for (im = term.images; im; im = im->next) - im->should_delete = 1; + tdeleteimages(); + tfulldirt(); break; #endif // SIXEL_PATCH default: @@ -2309,9 +2334,20 @@ csihandle(void) break; case 'K': /* EL -- Clear line */ switch (csiescseq.arg[0]) { + #if REFLOW_PATCH case 0: /* right */ - tclearregion(term.c.x, term.c.y, maxcol-1, - term.c.y); + tclearregion(term.c.x, term.c.y, term.col-1, term.c.y, 1); + break; + case 1: /* left */ + tclearregion(0, term.c.y, term.c.x, term.c.y, 1); + break; + case 2: /* all */ + tclearregion(0, term.c.y, term.col-1, term.c.y, 1); + break; + } + #else + case 0: /* right */ + tclearregion(term.c.x, term.c.y, maxcol-1, term.c.y); break; case 1: /* left */ tclearregion(0, term.c.y, term.c.x, term.c.y); @@ -2320,10 +2356,42 @@ csihandle(void) tclearregion(0, term.c.y, maxcol-1, term.c.y); break; } + #endif // REFLOW_PATCH break; - case 'S': /* SU -- Scroll line up */ + case 'S': /* SU -- Scroll line up ; XTSMGRAPHICS */ + if (csiescseq.priv) { + #if SIXEL_PATCH + if (csiescseq.narg > 1) { + /* XTSMGRAPHICS */ + pi = csiescseq.arg[0]; + pa = csiescseq.arg[1]; + if (pi == 1 && (pa == 1 || pa == 2 || pa == 4)) { + /* number of sixel color registers */ + /* (read, reset and read the maximum value give the same response) */ + n = snprintf(buffer, sizeof buffer, "\033[?1;0;%dS", DECSIXEL_PALETTE_MAX); + ttywrite(buffer, n, 1); + break; + } else if (pi == 2 && (pa == 1 || pa == 2 || pa == 4)) { + /* sixel graphics geometry (in pixels) */ + /* (read, reset and read the maximum value give the same response) */ + n = snprintf(buffer, sizeof buffer, "\033[?2;0;%d;%dS", + MIN(term.col * win.cw, DECSIXEL_WIDTH_MAX), + MIN(term.row * win.ch, DECSIXEL_HEIGHT_MAX)); + ttywrite(buffer, n, 1); + break; + } + /* the number of color registers and sixel geometry can't be changed */ + n = snprintf(buffer, sizeof buffer, "\033[?%d;3;0S", pi); /* failure */ + ttywrite(buffer, n, 1); + } + #endif // SIXEL_PATCH + goto unknown; + } DEFAULT(csiescseq.arg[0], 1); - #if SIXEL_PATCH && SCROLLBACK_PATCH + #if REFLOW_PATCH + /* xterm, urxvt, alacritty save this in history */ + tscrollup(term.top, term.bot, csiescseq.arg[0], SCROLL_SAVEHIST); + #elif SIXEL_PATCH && SCROLLBACK_PATCH tscrollup(term.top, csiescseq.arg[0], 1); #elif SCROLLBACK_PATCH tscrollup(term.top, csiescseq.arg[0], 0); @@ -2341,21 +2409,23 @@ csihandle(void) break; case 'l': /* RM -- Reset Mode */ tsetmode(csiescseq.priv, 0, csiescseq.arg, csiescseq.narg); - #if SIXEL_PATCH - if (IS_SET(MODE_ALTSCREEN)) { - for (im = term.images; im; im = im->next) - im->should_delete = 1; - } - #endif // SIXEL_PATCH break; case 'M': /* DL -- Delete lines */ DEFAULT(csiescseq.arg[0], 1); tdeleteline(csiescseq.arg[0]); break; case 'X': /* ECH -- Erase char */ + #if REFLOW_PATCH + if (csiescseq.arg[0] < 0) + return; + DEFAULT(csiescseq.arg[0], 1); + x = MIN(term.c.x + csiescseq.arg[0], term.col) - 1; + tclearregion(term.c.x, term.c.y, x, term.c.y, 1); + #else DEFAULT(csiescseq.arg[0], 1); tclearregion(term.c.x, term.c.y, term.c.x + csiescseq.arg[0] - 1, term.c.y); + #endif // REFLOW_PATCH break; case 'P': /* DCH -- Delete char */ DEFAULT(csiescseq.arg[0], 1); @@ -2402,9 +2472,27 @@ csihandle(void) case 's': /* DECSC -- Save cursor position (ANSI.SYS) */ tcursor(CURSOR_SAVE); break; - #if CSI_22_23_PATCH - case 't': /* title stack operations */ + #if CSI_22_23_PATCH | SIXEL_PATCH + case 't': /* title stack operations ; XTWINOPS */ switch (csiescseq.arg[0]) { + #if SIXEL_PATCH + case 14: /* text area size in pixels */ + if (csiescseq.narg > 1) + goto unknown; + n = snprintf(buffer, sizeof buffer, "\033[4;%d;%dt", + term.row * win.ch, term.col * win.cw); + ttywrite(buffer, n, 1); + break; + case 16: /* character cell size in pixels */ + n = snprintf(buffer, sizeof buffer, "\033[6;%d;%dt", win.ch, win.cw); + ttywrite(buffer, n, 1); + break; + case 18: /* size of the text area in characters */ + n = snprintf(buffer, sizeof buffer, "\033[8;%d;%dt", term.row, term.col); + ttywrite(buffer, n, 1); + break; + #endif // SIXEL_PATCH + #if CSI_22_23_PATCH case 22: /* pust current title on stack */ switch (csiescseq.arg[1]) { case 0: @@ -2427,11 +2515,12 @@ csihandle(void) goto unknown; } break; + #endif // CSI_22_23_PATCH default: goto unknown; } break; - #endif // CSI_22_23_PATCH + #endif // CSI_22_23_PATCH | SIXEL_PATCH case 'u': /* DECRC -- Restore cursor position (ANSI.SYS) */ tcursor(CURSOR_LOAD); break; @@ -2479,39 +2568,28 @@ csireset(void) } void -osc4_color_response(int num) +osc_color_response(int num, int index, int is_osc4) { int n; char buf[32]; unsigned char r, g, b; - if (xgetcolor(num, &r, &g, &b)) { - fprintf(stderr, "erresc: failed to fetch osc4 color %d\n", num); + 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]4;%d;rgb:%02x%02x/%02x%02x/%02x%02x\007", - num, r, r, g, g, b, b); - - ttywrite(buf, n, 1); -} - -void -osc_color_response(int index, int num) -{ - int n; - char buf[32]; - unsigned char r, g, b; - - if (xgetcolor(index, &r, &g, &b)) { - fprintf(stderr, "erresc: failed to fetch osc color %d\n", index); - return; + n = snprintf(buf, sizeof buf, "\033]%s%d;rgb:%02x%02x/%02x%02x/%02x%02x%s", + is_osc4 ? "4;" : "", num, r, r, g, g, b, b, strescseq.term); + 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); } - - n = snprintf(buf, sizeof buf, "\033]%d;rgb:%02x%02x/%02x%02x/%02x%02x\007", - num, r, r, g, g, b, b); - - ttywrite(buf, n, 1); } void @@ -2519,9 +2597,21 @@ strhandle(void) { char *p = NULL, *dec; int j, narg, par; + const struct { int idx; char *str; } osc_table[] = { + { defaultfg, "foreground" }, + { defaultbg, "background" }, + { defaultcs, "cursor" } + }; #if SIXEL_PATCH - ImageList *new_image; - int i; + ImageList *im, *newimages, *next, *tail; + int i, x1, y1, x2, y2, numimages; + int cx, cy; + Line line; + #if SCROLLBACK_PATCH || REFLOW_PATCH + int scr = IS_SET(MODE_ALTSCREEN) ? 0 : term.scr; + #else + int scr = 0; + #endif // SCROLLBACK_PATCH #endif // SIXEL_PATCH term.esc &= ~(ESC_STR_END|ESC_STR); @@ -2567,62 +2657,34 @@ strhandle(void) case 8: /* Clear Hyperlinks */ return; case 10: - if (narg < 2) - break; - - p = strescseq.args[1]; - - if (!strcmp(p, "?")) - osc_color_response(defaultfg, 10); - else if (xsetcolorname(defaultfg, p)) - fprintf(stderr, "erresc: invalid foreground color: %s\n", p); - else - tfulldirt(); - return; case 11: - if (narg < 2) - break; - - p = strescseq.args[1]; - - if (!strcmp(p, "?")) - osc_color_response(defaultbg, 11); - else if (xsetcolorname(defaultbg, p)) - fprintf(stderr, "erresc: invalid background color: %s\n", p); - else - tfulldirt(); - return; 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(defaultcs, 12); - else if (xsetcolorname(defaultcs, p)) - fprintf(stderr, "erresc: invalid cursor color: %s\n", p); - else + 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 ((par == 4 && narg < 3) || narg < 2) + if (narg < 3) break; - p = strescseq.args[((par == 4) ? 2 : 1)]; + p = strescseq.args[2]; /* FALLTHROUGH */ case 104: /* color reset */ - if (par == 10) - j = defaultfg; - else if (par == 11) - j = defaultbg; - else if (par == 12) - j = defaultcs; - else - j = (narg > 1) ? atoi(strescseq.args[1]) : -1; + j = (narg > 1) ? atoi(strescseq.args[1]) : -1; - if (p && !strcmp(p, "?")) - osc4_color_response(j); - else if (xsetcolorname(j, p)) { + if (p && !strcmp(p, "?")) { + osc_color_response(j, 0, 1); + } else if (xsetcolorname(j, p)) { if (par == 104 && narg <= 1) { xloadcols(); return; /* color reset without parameter */ @@ -2630,8 +2692,10 @@ strhandle(void) fprintf(stderr, "erresc: invalid color j=%d, p=%s\n", j, p ? p : "(null)"); } else { - if (j == defaultbg) - xclearwin(); + /* + * TODO if defaultbg color is changed, borders + * are dirty + */ tfulldirt(); } return; @@ -2648,34 +2712,75 @@ strhandle(void) #if SIXEL_PATCH if (IS_SET(MODE_SIXEL)) { term.mode &= ~MODE_SIXEL; - new_image = malloc(sizeof(ImageList)); - memset(new_image, 0, sizeof(ImageList)); - new_image->x = term.c.x; - new_image->y = term.c.y; - new_image->width = sixel_st.image.width; - new_image->height = sixel_st.image.height; - new_image->pixels = malloc(new_image->width * new_image->height * 4); - if (sixel_parser_finalize(&sixel_st, new_image->pixels) != 0) { - perror("sixel_parser_finalize() failed"); + if (!sixel_st.image.data) { sixel_parser_deinit(&sixel_st); return; } - sixel_parser_deinit(&sixel_st); - if (term.images) { - ImageList *im; - for (im = term.images; im->next;) - im = im->next; - im->next = new_image; - new_image->prev = im; - } else { - term.images = new_image; + cx = IS_SET(MODE_SIXEL_SDM) ? 0 : term.c.x; + cy = IS_SET(MODE_SIXEL_SDM) ? 0 : term.c.y; + if ((numimages = sixel_parser_finalize(&sixel_st, &newimages, + cx, cy + scr, win.cw, win.ch)) <= 0) { + sixel_parser_deinit(&sixel_st); + perror("sixel_parser_finalize() failed"); + return; } - for (i = 0; i < (sixel_st.image.height + win.ch-1)/win.ch; ++i) { - int x; - tclearregion(term.c.x, term.c.y, term.c.x+(sixel_st.image.width+win.cw-1)/win.cw-1, term.c.y); - for (x = term.c.x; x < MIN(term.col, term.c.x+(sixel_st.image.width+win.cw-1)/win.cw); x++) - term.line[term.c.y][x].mode |= ATTR_SIXEL; - tnewline(0); + sixel_parser_deinit(&sixel_st); + x1 = newimages->x; + y1 = newimages->y; + x2 = x1 + newimages->cols; + y2 = y1 + numimages; + if (newimages->transparent) { + for (tail = term.images; tail && tail->next; tail = tail->next); + } else { + for (tail = NULL, im = term.images; im; im = next) { + next = im->next; + if (im->x >= x1 && im->x + im->cols <= x2 && + im->y >= y1 && im->y <= y2) { + delete_image(im); + continue; + } + tail = im; + } + } + if (tail) { + tail->next = newimages; + newimages->prev = tail; + } else { + term.images = newimages; + } + x2 = MIN(x2, term.col) - 1; + if (IS_SET(MODE_SIXEL_SDM)) { + /* Sixel display mode: put the sixel in the upper left corner of + * the screen, disable scrolling (the sixel will be truncated if + * it is too long) and do not change the cursor position. */ + for (i = 0, im = newimages; im; im = next, i++) { + next = im->next; + if (i >= term.row) { + delete_image(im); + continue; + } + im->y = i + scr; + tsetsixelattr(term.line[i], x1, x2); + term.dirty[MIN(im->y, term.row-1)] = 1; + } + } else { + for (i = 0, im = newimages; im; im = next, i++) { + next = im->next; + #if SCROLLBACK_PATCH || REFLOW_PATCH + scr = IS_SET(MODE_ALTSCREEN) ? 0 : term.scr; + #endif // SCROLLBACK_PATCH + im->y = term.c.y + scr; + tsetsixelattr(term.line[term.c.y], x1, x2); + term.dirty[MIN(im->y, term.row-1)] = 1; + if (i < numimages-1) { + im->next = NULL; + tnewline(0); + im->next = next; + } + } + /* if mode 8452 is set, sixel scrolling leaves cursor to right of graphic */ + if (IS_SET(MODE_SIXEL_CUR_RT)) + term.c.x = MIN(term.c.x + newimages->cols, term.col-1); } } #endif // SIXEL_PATCH @@ -2744,7 +2849,7 @@ strdump(void) fprintf(stderr, "(%02x)", c); } } - fprintf(stderr, "ESC\\\n"); + fprintf(stderr, (strescseq.term[0] == 0x1b) ? "ESC\\\n" : "BEL\n"); } void @@ -2802,6 +2907,7 @@ tdumpsel(void) } } +#if !REFLOW_PATCH void tdumpline(int n) { @@ -2816,6 +2922,7 @@ tdumpline(int n) } tprinter("\n", 1); } +#endif // REFLOW_PATCH void tdump(void) @@ -2932,6 +3039,7 @@ tcontrolcode(uchar ascii) case '\a': /* BEL */ if (term.esc & ESC_STR_END) { /* backwards compatibility to xterm */ + strescseq.term = STR_TERM_BEL; strhandle(); } else { xbell(); @@ -3007,6 +3115,51 @@ tcontrolcode(uchar ascii) term.esc &= ~(ESC_STR_END|ESC_STR); } +#if SIXEL_PATCH +void +dcshandle(void) +{ + int bgcolor, transparent; + unsigned char r, g, b, a = 255; + + switch (csiescseq.mode[0]) { + default: + unknown: + fprintf(stderr, "erresc: unknown csi "); + csidump(); + /* die(""); */ + break; + #if SYNC_PATCH + case '=': + /* https://gitlab.com/gnachman/iterm2/-/wikis/synchronized-updates-spec */ + if (csiescseq.buf[2] == 's' && csiescseq.buf[1] == '1') + tsync_begin(); /* BSU */ + else if (csiescseq.buf[2] == 's' && csiescseq.buf[1] == '2') + tsync_end(); /* ESU */ + else + goto unknown; + break; + #endif // SYNC_PATCH + case 'q': /* DECSIXEL */ + transparent = (csiescseq.narg >= 2 && csiescseq.arg[1] == 1); + if (IS_TRUECOL(term.c.attr.bg)) { + r = term.c.attr.bg >> 16 & 255; + g = term.c.attr.bg >> 8 & 255; + b = term.c.attr.bg >> 0 & 255; + } else { + xgetcolor(term.c.attr.bg, &r, &g, &b); + if (term.c.attr.bg == defaultbg) + a = dc.col[defaultbg].pixel >> 24 & 255; + } + bgcolor = a << 24 | r << 16 | g << 8 | b; + if (sixel_parser_init(&sixel_st, transparent, (255 << 24), bgcolor, 1, win.cw, win.ch) != 0) + perror("sixel_parser_init() failed"); + term.mode |= MODE_SIXEL; + break; + } +} +#endif // SIXEL_PATCH + /* * returns 1 when the sequence is finished and it hasn't to read * more characters for this sequence, otherwise 0 @@ -3047,7 +3200,9 @@ eschandle(uchar ascii) return 0; case 'D': /* IND -- Linefeed */ if (term.c.y == term.bot) { - #if SCROLLBACK_PATCH + #if REFLOW_PATCH + tscrollup(term.top, term.bot, 1, SCROLL_SAVEHIST); + #elif SCROLLBACK_PATCH tscrollup(term.top, 1, 1); #else tscrollup(term.top, 1); @@ -3079,7 +3234,8 @@ eschandle(uchar ascii) #endif // CSI_22_23_PATCH resettitle(); xloadcols(); - #if SCROLLBACK_PATCH + xsetmode(0, MODE_HIDE); + #if SCROLLBACK_PATCH && !REFLOW_PATCH if (!IS_SET(MODE_ALTSCREEN)) { term.scr = 0; term.histi = 0; @@ -3100,8 +3256,10 @@ eschandle(uchar ascii) tcursor(CURSOR_LOAD); break; case '\\': /* ST -- String Terminator */ - if (term.esc & ESC_STR_END) + if (term.esc & ESC_STR_END) { + strescseq.term = STR_TERM_ST; strhandle(); + } break; default: fprintf(stderr, "erresc: unknown sequence ESC 0x%02X '%c'\n", @@ -3120,11 +3278,7 @@ tputc(Rune u) Glyph *gp; control = ISCONTROL(u); - #if SIXEL_PATCH - if (u < 127 || !IS_SET(MODE_UTF8 | MODE_SIXEL)) - #else if (u < 127 || !IS_SET(MODE_UTF8)) - #endif // SIXEL_PATCH { c[0] = u; width = len = 1; @@ -3156,11 +3310,6 @@ tputc(Rune u) } #if SIXEL_PATCH - if (IS_SET(MODE_SIXEL)) { - if (sixel_parser_parse(&sixel_st, (unsigned char *)&u, 1) != 0) - perror("sixel_parser_parse() failed"); - return; - } if (term.esc & ESC_DCS) goto check_control_code; #endif // SIXEL_PATCH @@ -3247,10 +3396,15 @@ check_control_code: */ return; } - #if !VIM_BROWSE_PATCH + + #if REFLOW_PATCH + /* selected() takes relative coordinates */ + if (selected(term.c.x + term.scr, term.c.y + term.scr)) + selclear(); + #else if (selected(term.c.x, term.c.y)) selclear(); - #endif // VIM_BROWSE_PATCH + #endif // REFLOW_PATCH gp = &term.line[term.c.y][term.c.x]; if (IS_SET(MODE_WRAP) && (term.c.state & CURSOR_WRAPNEXT)) { @@ -3265,7 +3419,10 @@ check_control_code: } if (term.c.x+width > term.col) { - tnewline(1); + if (IS_SET(MODE_WRAP)) + tnewline(1); + else + tmoveto(term.col - width, term.c.y); gp = &term.line[term.c.y][term.c.x]; } @@ -3286,6 +3443,9 @@ check_control_code: if (term.c.x+width < term.col) { tmoveto(term.c.x+width, term.c.y); } else { + #if REFLOW_PATCH + term.wrapcwidth[IS_SET(MODE_ALTSCREEN)] = width; + #endif // REFLOW_PATCH term.c.state |= CURSOR_WRAPNEXT; } } @@ -3304,7 +3464,10 @@ twrite(const char *buf, int buflen, int show_ctrl) for (n = 0; n < buflen; n += charsize) { #if SIXEL_PATCH - if (IS_SET(MODE_UTF8) && !IS_SET(MODE_SIXEL)) + if (IS_SET(MODE_SIXEL) && sixel_st.state != PS_ESC) { + charsize = sixel_parser_parse(&sixel_st, (const unsigned char*)buf + n, buflen - n); + continue; + } else if (IS_SET(MODE_UTF8)) #else if (IS_SET(MODE_UTF8)) #endif // SIXEL_PATCH @@ -3338,19 +3501,12 @@ twrite(const char *buf, int buflen, int show_ctrl) return n; } +#if !REFLOW_PATCH void tresize(int col, int row) { - int i; - #if SCROLLBACK_PATCH - int j; - #endif // SCROLLBACK_PATCH - #if VIM_BROWSE_PATCH - int const colSet = col, alt = IS_SET(MODE_ALTSCREEN), ini = buf == NULL; - col = MAX(col, buffCols); - row = MIN(row, buffSize); - int const minrow = MIN(row, term.row), mincol = MIN(col, buffCols); - #elif COLUMNS_PATCH + int i, j; + #if COLUMNS_PATCH int tmp = col; int minrow, mincol; @@ -3362,9 +3518,13 @@ tresize(int col, int row) #else int minrow = MIN(row, term.row); int mincol = MIN(col, term.col); - #endif // VIM_BROWSE_PATCH + #endif // COLUMNS_PATCH int *bp; - TCursor c; + #if SIXEL_PATCH + int x, x2; + Line line; + ImageList *im, *next; + #endif // SIXEL_PATCH #if KEYBOARDSELECT_PATCH if ( row < term.row || col < term.col ) @@ -3377,43 +3537,27 @@ tresize(int col, int row) return; } - #if VIM_BROWSE_PATCH - if (alt) - tswapscreen(); - #endif // VIM_BROWSE_PATCH - - /* - * 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++) { - #if !VIM_BROWSE_PATCH - free(term.line[i]); - #endif // VIM_BROWSE_PATCH - free(term.alt[i]); - } - /* ensure that both src and dst are not NULL */ - if (i > 0) { - #if !VIM_BROWSE_PATCH - memmove(term.line, term.line + i, row * sizeof(Line)); - #endif // VIM_BROWSE_PATCH - memmove(term.alt, term.alt + i, row * sizeof(Line)); - } - for (i += row; i < term.row; i++) { - #if !VIM_BROWSE_PATCH - free(term.line[i]); - #endif // VIM_BROWSE_PATCH - free(term.alt[i]); + /* scroll both screens independently */ + if (row < term.row) { + tcursor(CURSOR_SAVE); + tsetscroll(0, term.row - 1); + for (i = 0; i < 2; i++) { + if (term.c.y >= row) { + #if SCROLLBACK_PATCH + tscrollup(0, term.c.y - row + 1, !IS_SET(MODE_ALTSCREEN)); + #else + tscrollup(0, term.c.y - row + 1); + #endif // SCROLLBACK_PATCH + } + for (j = row; j < term.row; j++) + free(term.line[j]); + tswapscreen(); + tcursor(CURSOR_LOAD); + } } /* resize to new height */ - #if VIM_BROWSE_PATCH - buf = xrealloc(buf, (buffSize + row) * sizeof(Line)); - mark = xrealloc(mark, col * row * sizeof(*mark)); - #else term.line = xrealloc(term.line, row * sizeof(Line)); - #endif // VIM_BROWSE_PATCH 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)); @@ -3429,75 +3573,50 @@ tresize(int col, int row) /* resize each row to new width, zero-pad if needed */ for (i = 0; i < minrow; i++) { - #if !VIM_BROWSE_PATCH term.line[i] = xrealloc(term.line[i], col * sizeof(Glyph)); - #endif // VIM_BROWSE_PATCH term.alt[i] = xrealloc(term.alt[i], col * sizeof(Glyph)); } /* allocate any new rows */ for (/* i = minrow */; i < row; i++) { - #if !VIM_BROWSE_PATCH term.line[i] = xmalloc(col * sizeof(Glyph)); - #endif // VIM_BROWSE_PATCH term.alt[i] = xmalloc(col * sizeof(Glyph)); } - #if VIM_BROWSE_PATCH - if (col > buffCols) - #elif COLUMNS_PATCH + #if COLUMNS_PATCH if (col > term.maxcol) #else if (col > term.col) - #endif // VIM_BROWSE_PATCH + #endif // COLUMNS_PATCH { - #if VIM_BROWSE_PATCH - bp = term.tabs + buffCols; - memset(bp, 0, sizeof(*term.tabs) * (col - buffCols)); - #elif COLUMNS_PATCH + #if COLUMNS_PATCH bp = term.tabs + term.maxcol; memset(bp, 0, sizeof(*term.tabs) * (col - term.maxcol)); #else bp = term.tabs + term.col; memset(bp, 0, sizeof(*term.tabs) * (col - term.col)); - #endif // VIM_BROWSE_PATCH + #endif // COLUMNS_PATCH while (--bp > term.tabs && !*bp) /* nothing */ ; for (bp += tabspaces; bp < term.tabs + col; bp += tabspaces) *bp = 1; } - #if VIM_BROWSE_PATCH - Glyph g=(Glyph){.bg=term.c.attr.bg, .fg=term.c.attr.fg, .u=' ', .mode=0}; - for (i = 0; i < buffSize; ++i) { - buf[i] = xrealloc(ini ? NULL : buf[i], col*sizeof(Glyph)); - for (int j = ini ? 0 : buffCols; j < col; ++j) buf[i][j] = g; - } - for (i = 0; i < row; ++i) buf[buffSize + i] = buf[i]; - term.line = &buf[*(histOp?&histOff:&insertOff) +=MAX(term.c.y-row+1,0)]; - memset(mark, 0, col * row * sizeof(*mark)); - #endif // VIM_BROWSE_PATCH + /* update terminal size */ - #if VIM_BROWSE_PATCH - term.col = colSet; - buffCols = col; - #elif COLUMNS_PATCH + #if COLUMNS_PATCH term.col = tmp; term.maxcol = col; #else term.col = col; - #endif // VIM_BROWSE_PATCH + #endif // COLUMNS_PATCH term.row = row; - #if VIM_BROWSE_PATCH - if (alt) - tswapscreen(); - #endif // VIM_BROWSE_PATCH + /* 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++) { + tmoveto(term.c.x, term.c.y); /* make use of the LIMIT in tmoveto */ + tcursor(CURSOR_SAVE); if (mincol < col && 0 < minrow) { tclearregion(mincol, 0, col - 1, minrow - 1); } @@ -3507,8 +3626,43 @@ tresize(int col, int row) tswapscreen(); tcursor(CURSOR_LOAD); } - term.c = c; + + #if SIXEL_PATCH + /* expand images into new text cells to prevent them from being deleted in + * xfinishdraw() that draws the images */ + for (i = 0; i < 2; i++) { + for (im = term.images; im; im = next) { + next = im->next; + #if SCROLLBACK_PATCH + if (IS_SET(MODE_ALTSCREEN)) { + if (im->y < 0 || im->y >= term.row) { + delete_image(im); + continue; + } + line = term.line[im->y]; + } else { + if (im->y - term.scr < -HISTSIZE || im->y - term.scr >= term.row) { + delete_image(im); + continue; + } + line = TLINE(im->y); + } + #else + if (im->y < 0 || im->y >= term.row) { + delete_image(im); + continue; + } + line = term.line[im->y]; + #endif // SCROLLBACK_PATCH + x2 = MIN(im->x + im->cols, term.col); + for (x = im->x; x < x2; x++) + line[x].mode |= ATTR_SIXEL; + } + tswapscreen(); + } + #endif // SIXEL_PATCH } +#endif // REFLOW_PATCH void resettitle(void) @@ -3523,33 +3677,19 @@ resettitle(void) void drawregion(int x1, int y1, int x2, int y2) { - #if VIM_BROWSE_PATCH - if (altToggle && histMode && !histOp) - memset(term.dirty, 0, sizeof(*term.dirty) * term.row); - int const o = !IS_SET(MODE_ALTSCREEN) && histMode && !histOp, h =rows(); - #endif // VIM_BROWSE_PATCH int y; for (y = y1; y < y2; y++) { - #if VIM_BROWSE_PATCH - int const oy = o ? (y + insertOff - histOff + h) % h : y; - if (!BETWEEN(oy, 0, term.row-1) || !term.dirty[y]) continue; - xdrawline(term.line[y], x1, oy, x2); - #else if (!term.dirty[y]) continue; term.dirty[y] = 0; - #if SCROLLBACK_PATCH + #if SCROLLBACK_PATCH || REFLOW_PATCH xdrawline(TLINE(y), x1, y, x2); #else xdrawline(term.line[y], x1, y, x2); #endif // SCROLLBACK_PATCH - #endif // VIM_BROWSE_PATCH } - #if VIM_BROWSE_PATCH - memset(&term.dirty[y1], 0, sizeof(*term.dirty) * (y2 - y1)); - #endif // VIM_BROWSE_PATCH } #include "patch/st_include.c" @@ -3570,18 +3710,13 @@ draw(void) if (term.line[term.c.y][cx].mode & ATTR_WDUMMY) cx--; - #if VIM_BROWSE_PATCH - if (histMode) - historyPreDraw(); - #endif // VIM_BROWSE_PATCH - drawregion(0, 0, term.col, term.row); - #if VIM_BROWSE_PATCH - if (!histMode) - #elif SCROLLBACK_PATCH + #if KEYBOARDSELECT_PATCH && REFLOW_PATCH + if (!kbds_drawcursor()) + #elif REFLOW_PATCH || SCROLLBACK_PATCH if (term.scr == 0) - #endif // SCROLLBACK_PATCH + #endif // SCROLLBACK_PATCH | REFLOW_PATCH | KEYBOARDSELECT_PATCH #if LIGATURES_PATCH xdrawcursor(cx, term.c.y, term.line[term.c.y][cx], term.ocx, term.ocy, term.line[term.ocy][term.ocx], diff --git a/st-flexipatch/st.h b/st-flexipatch/st.h index 41af307..95d1be1 100644 --- a/st-flexipatch/st.h +++ b/st-flexipatch/st.h @@ -1,6 +1,7 @@ /* See LICENSE for license details. */ #include +#include #include #include #include @@ -15,9 +16,6 @@ #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)) -#if VIM_BROWSE_PATCH -#define OUT(x, a, b) ((a) <= (x) || (x) <= (b)) -#endif // VIM_BROWSE_PATCH #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) @@ -35,36 +33,43 @@ #define TRUECOLOR(r,g,b) (1 << 24 | (r) << 16 | (g) << 8 | (b)) #define IS_TRUECOL(x) (1 << 24 & (x)) -#if SCROLLBACK_PATCH +#if SCROLLBACK_PATCH || REFLOW_PATCH #define HISTSIZE 2000 -#endif // SCROLLBACK_PATCH +#endif // SCROLLBACK_PATCH | REFLOW_PATCH 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_NULL = 0, + ATTR_SET = 1 << 0, + ATTR_BOLD = 1 << 1, + ATTR_FAINT = 1 << 2, + ATTR_ITALIC = 1 << 3, + ATTR_UNDERLINE = 1 << 4, + ATTR_BLINK = 1 << 5, + ATTR_REVERSE = 1 << 6, + ATTR_INVISIBLE = 1 << 7, + ATTR_STRUCK = 1 << 8, + ATTR_WRAP = 1 << 9, + ATTR_WIDE = 1 << 10, + ATTR_WDUMMY = 1 << 11, + #if SELECTION_COLORS_PATCH + ATTR_SELECTED = 1 << 12, + #endif // SELECTION_COLORS_PATCH | REFLOW_PATCH #if BOXDRAW_PATCH - ATTR_BOXDRAW = 1 << 11, + ATTR_BOXDRAW = 1 << 13, #endif // BOXDRAW_PATCH + #if UNDERCURL_PATCH + ATTR_DIRTYUNDERLINE = 1 << 14, + #endif // UNDERCURL_PATCH #if LIGATURES_PATCH - ATTR_LIGA = 1 << 12, + ATTR_LIGA = 1 << 15, #endif // LIGATURES_PATCH #if SIXEL_PATCH - ATTR_SIXEL = 1 << 13, + ATTR_SIXEL = 1 << 16, #endif // SIXEL_PATCH + #if KEYBOARDSELECT_PATCH && REFLOW_PATCH + ATTR_HIGHLIGHT = 1 << 17, + #endif // KEYBOARDSELECT_PATCH ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT, - #if UNDERCURL_PATCH - ATTR_DIRTYUNDERLINE = 1 << 15, - #endif // UNDERCURL_PATCH }; #if SIXEL_PATCH @@ -72,11 +77,18 @@ typedef struct _ImageList { struct _ImageList *next, *prev; unsigned char *pixels; void *pixmap; + void *clipmask; int width; int height; int x; int y; - int should_delete; + #if REFLOW_PATCH + int reflow_y; + #endif // REFLOW_PATCH + int cols; + int cw; + int ch; + int transparent; } ImageList; #endif // SIXEL_PATCH @@ -125,7 +137,7 @@ typedef XftGlyphFontSpec GlyphFontSpec; #define Glyph Glyph_ typedef struct { Rune u; /* character code */ - ushort mode; /* attribute flags */ + uint32_t mode; /* attribute flags */ uint32_t fg; /* foreground */ uint32_t bg; /* background */ #if UNDERCURL_PATCH @@ -136,6 +148,15 @@ typedef struct { typedef Glyph *Line; +#if LIGATURES_PATCH +typedef struct { + int ox; + int charlen; + int numspecs; + Glyph base; +} GlyphFontSeq; +#endif // LIGATURES_PATCH + typedef struct { Glyph attr; /* current char attributes */ int x; @@ -147,17 +168,23 @@ typedef struct { typedef struct { int row; /* nb row */ int col; /* nb col */ - #if COLUMNS_PATCH && !VIM_BROWSE_PATCH + #if COLUMNS_PATCH int maxcol; #endif // COLUMNS_PATCH Line *line; /* screen */ Line *alt; /* alternate screen */ - #if SCROLLBACK_PATCH + #if REFLOW_PATCH + Line hist[HISTSIZE]; /* history buffer */ + int histi; /* history index */ + int histf; /* nb history available */ + int scr; /* scroll back */ + int wrapcwidth[2]; /* used in updating WRAPNEXT when resizing */ + #elif SCROLLBACK_PATCH Line hist[HISTSIZE]; /* history buffer */ int histi; /* history index */ int histn; /* number of history entries */ int scr; /* scroll back */ - #endif // SCROLLBACK_PATCH + #endif // SCROLLBACK_PATCH | REFLOW_PATCH int *dirty; /* dirtyness of lines */ TCursor c; /* cursor */ int ocx; /* old cursor col */ @@ -210,11 +237,14 @@ typedef struct { Window win; Drawable buf; GlyphFontSpec *specbuf; /* font spec buffer used for rendering */ + #if LIGATURES_PATCH + GlyphFontSeq *specseq; + #endif // LIGATURES_PATCH Atom xembed, wmdeletewin, netwmname, netwmiconname, netwmpid; #if FULLSCREEN_PATCH Atom netwmstate, netwmfullscreen; #endif // FULLSCREEN_PATCH - #if NETWMICON_PATCH + #if NETWMICON_PATCH || NETWMICON_LEGACY_PATCH || NETWMICON_FF_PATCH Atom netwmicon; #endif // NETWMICON_PATCH struct { @@ -321,9 +351,6 @@ int tattrset(int); int tisaltscr(void); void tnew(int, int); void tresize(int, int); -#if VIM_BROWSE_PATCH -void tmoveto(int x, int y); -#endif // VIM_BROWSE_PATCH void tsetdirtattr(int); void ttyhangup(void); int ttynew(const char *, char *, const char *, char **); @@ -335,6 +362,7 @@ void resettitle(void); void selclear(void); void selinit(void); +void selremove(void); void selstart(int, int, int); void selextend(int, int, int, int); int selected(int, int); @@ -364,6 +392,10 @@ extern char *scroll; extern char *stty_args; extern char *vtiden; extern wchar_t *worddelimiters; +#if KEYBOARDSELECT_PATCH && REFLOW_PATCH +extern wchar_t *kbds_sdelim; +extern wchar_t *kbds_ldelim; +#endif // KEYBOARDSELECT_PATCH extern int allowaltscreen; extern int allowwindowops; extern char *termname; diff --git a/st-flexipatch/st.info b/st-flexipatch/st.info index 1ff5af9..b286fb5 100644 --- a/st-flexipatch/st.info +++ b/st-flexipatch/st.info @@ -191,6 +191,10 @@ st-mono| simpleterm monocolor, # XTerm extensions rmxx=\E[29m, smxx=\E[9m, + BE=\E[?2004h, + BD=\E[?2004l, + PS=\E[200~, + PE=\E[201~, # 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) diff --git a/st-flexipatch/win.h b/st-flexipatch/win.h index 55bd990..c7449ea 100644 --- a/st-flexipatch/win.h +++ b/st-flexipatch/win.h @@ -21,9 +21,7 @@ enum win_mode { MODE_NUMLOCK = 1 << 17, MODE_MOUSE = MODE_MOUSEBTN|MODE_MOUSEMOTION|MODE_MOUSEX10\ |MODE_MOUSEMANY, - #if VIM_BROWSE_PATCH - MODE_NORMAL = 1 << 18, - #endif // VIM_BROWSE_PATCH + MODE_PLACEHOLDER = 1 << 18, #if KEYBOARDSELECT_PATCH MODE_KBDSELECT = 1 << 19, #endif // KEYBOARDSELECT_PATCH @@ -54,4 +52,7 @@ void xsetpointermotion(int); void xsetsel(char *); int xstartdraw(void); void xximspot(int, int); -void xclearwin(void); \ No newline at end of file +void xclearwin(void); +#if REFLOW_PATCH && KEYBOARDSELECT_PATCH +void xdrawglyph(Glyph, int, int); +#endif // KEYBOARDSELECT_PATCH \ No newline at end of file diff --git a/st-flexipatch/x.c b/st-flexipatch/x.c index 9b45076..bf403ff 100644 --- a/st-flexipatch/x.c +++ b/st-flexipatch/x.c @@ -27,6 +27,11 @@ char *argv0; #include #endif // THEMED_CURSOR_PATCH +#if SIXEL_PATCH +#include +#include "sixel.h" +#endif // SIXEL_PATCH + #if UNDERCURL_PATCH /* Undercurl slope types */ enum undercurl_slope_type { @@ -37,6 +42,13 @@ enum undercurl_slope_type { }; #endif // UNDERCURL_PATCH +#if ANYGEOMETRY_PATCH +typedef enum { + PixelGeometry, + CellGeometry +} Geometry; +#endif // ANYGEOMETRY_PATCH + /* X modifiers */ #define XK_ANY_MOD UINT_MAX #define XK_NO_MOD 0 @@ -75,15 +87,17 @@ static void zoomreset(const Arg *); static inline ushort sixd_to_16bit(int); static int xmakeglyphfontspecs(XftGlyphFontSpec *, const Glyph *, int, int, int); -#if WIDE_GLYPHS_PATCH +#if LIGATURES_PATCH && WIDE_GLYPHS_PATCH +static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, int, int, int); +#elif LIGATURES_PATCH || WIDE_GLYPHS_PATCH static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, int, int); #else static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, int); -#endif // WIDE_GLYPHS_PATCH +#endif // WIDE_GLYPHS_PATCH | LIGATURES_PATCH #if LIGATURES_PATCH -static void xresetfontsettings(ushort mode, Font **font, int *frcflags); +static inline void xresetfontsettings(uint32_t mode, Font **font, int *frcflags); #endif // LIGATURES_PATCH -static void xdrawglyph(Glyph, int, int); +void xdrawglyph(Glyph, int, int); static void xclear(int, int, int, int); static int xgeommasktogravity(int); static int ximopen(Display *); @@ -252,6 +266,11 @@ clippaste(const Arg *dummy) { Atom clipboard; + #if KEYBOARDSELECT_PATCH && REFLOW_PATCH + if (IS_SET(MODE_KBDSELECT) && !kbds_issearchmode()) + return; + #endif // KEYBOARDSELECT_PATCH + clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); XConvertSelection(xw.dpy, clipboard, xsel.xtarget, clipboard, xw.win, CurrentTime); @@ -266,6 +285,11 @@ numlock(const Arg *dummy) void selpaste(const Arg *dummy) { + #if KEYBOARDSELECT_PATCH && REFLOW_PATCH + if (IS_SET(MODE_KBDSELECT) && !kbds_issearchmode()) + return; + #endif // KEYBOARDSELECT_PATCH + XConvertSelection(xw.dpy, XA_PRIMARY, xsel.xtarget, XA_PRIMARY, xw.win, CurrentTime); } @@ -282,17 +306,42 @@ zoom(const Arg *arg) Arg larg; larg.f = usedfontsize + arg->f; + #if SIXEL_PATCH + if (larg.f >= 1.0) + zoomabs(&larg); + #else zoomabs(&larg); + #endif // SIXEL_PATCH } void zoomabs(const Arg *arg) { + #if SIXEL_PATCH + int i; + ImageList *im; + #endif // SIXEL_PATCH + xunloadfonts(); xloadfonts(usedfont, arg->f); #if FONT2_PATCH xloadsparefonts(); #endif // FONT2_PATCH + + #if SIXEL_PATCH + /* delete old pixmaps so that xfinishdraw() can create new scaled ones */ + for (im = term.images, i = 0; i < 2; i++, im = term.images_alt) { + for (; im; im = im->next) { + if (im->pixmap) + XFreePixmap(xw.dpy, (Drawable)im->pixmap); + if (im->clipmask) + XFreePixmap(xw.dpy, (Drawable)im->clipmask); + im->pixmap = NULL; + im->clipmask = NULL; + } + } + #endif // SIXEL_PATCH + cresize(0, 0); redraw(); xhints(); @@ -373,6 +422,11 @@ mousesel(XEvent *e, int done) int type, seltype = SEL_REGULAR; uint state = e->xbutton.state & ~(Button1Mask | forcemousemod); + #if KEYBOARDSELECT_PATCH && REFLOW_PATCH + if (kbds_isselectmode()) + return; + #endif // KEYBOARDSELECT_PATCH + for (type = 1; type < LEN(selmasks); ++type) { if (match(selmasks[type], state)) { seltype = type; @@ -462,9 +516,7 @@ bpress(XEvent *e) { int btn = e->xbutton.button; struct timespec now; - #if !VIM_BROWSE_PATCH int snap; - #endif // VIM_BROWSE_PATCH if (1 <= btn && btn <= 11) buttons |= 1 << (btn-1); @@ -483,34 +535,6 @@ bpress(XEvent *e) * snapping behaviour is exposed. */ clock_gettime(CLOCK_MONOTONIC, &now); - #if VIM_BROWSE_PATCH - int const tripleClick = TIMEDIFF(now, xsel.tclick2) <= tripleclicktimeout, - doubleClick = TIMEDIFF(now, xsel.tclick1) <= doubleclicktimeout; - if ((mouseYank || mouseSelect) && (tripleClick || doubleClick)) { - if (!IS_SET(MODE_NORMAL)) normalMode(); - historyOpToggle(1, 1); - tmoveto(evcol(e), evrow(e)); - if (tripleClick) { - if (mouseYank) pressKeys("dVy", 3); - if (mouseSelect) pressKeys("dV", 2); - } else if (doubleClick) { - if (mouseYank) pressKeys("dyiW", 4); - if (mouseSelect) { - tmoveto(evcol(e), evrow(e)); - pressKeys("viW", 3); - } - } - historyOpToggle(-1, 1); - } else { - if (!IS_SET(MODE_NORMAL)) selstart(evcol(e), evrow(e), 0); - else { - historyOpToggle(1, 1); - tmoveto(evcol(e), evrow(e)); - pressKeys("v", 1); - historyOpToggle(-1, 1); - } - } - #else if (TIMEDIFF(now, xsel.tclick2) <= tripleclicktimeout) { snap = SNAP_LINE; } else if (TIMEDIFF(now, xsel.tclick1) <= doubleclicktimeout) { @@ -518,13 +542,15 @@ bpress(XEvent *e) } else { snap = 0; } - #endif // VIM_BROWSE_PATCH xsel.tclick2 = xsel.tclick1; xsel.tclick1 = now; - #if !VIM_BROWSE_PATCH + #if KEYBOARDSELECT_PATCH && REFLOW_PATCH + if (kbds_isselectmode()) + return; + #endif // KEYBOARDSELECT_PATCH + selstart(evcol(e), evrow(e), snap); - #endif // VIM_BROWSE_PATCH #if OPENURLONCLICK_PATCH clearurl(); @@ -562,6 +588,9 @@ selnotify(XEvent *e) int format; uchar *data, *last, *repl; Atom type, incratom, property = None; + #if KEYBOARDSELECT_PATCH && REFLOW_PATCH + int append = 0; + #endif // KEYBOARDSELECT_PATCH incratom = XInternAtom(xw.dpy, "INCR", 0); @@ -623,6 +652,30 @@ selnotify(XEvent *e) continue; } + #if KEYBOARDSELECT_PATCH && REFLOW_PATCH + if (IS_SET(MODE_KBDSELECT) && kbds_issearchmode()) { + kbds_pasteintosearch(data, nitems * format / 8, append++); + } else { + /* + * 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); + } + #else /* * As seen in getsel: * Line endings are inconsistent in the terminal and GUI world @@ -641,6 +694,7 @@ selnotify(XEvent *e) ttywrite((char *)data, nitems * format / 8, 1); if (IS_SET(MODE_BRCKTPASTE) && rem == 0) ttywrite("\033[201~", 6, 0); + #endif // KEYBOARDSELECT_PATCH XFree(data); /* number of 32-bit chunks returned */ ofs += nitems * format / 32; @@ -776,15 +830,7 @@ brelease(XEvent *e) if (mouseaction(e, 1)) return; - #if VIM_BROWSE_PATCH - if (btn == Button1 && !IS_SET(MODE_NORMAL)) { - mousesel(e, 1); - #if OPENURLONCLICK_PATCH - if (url_click && e->xkey.state & url_opener_modkey) - openUrlOnClick(evcol(e), evrow(e), url_opener); - #endif // OPENURLONCLICK_PATCH - } - #else + if (btn == Button1) { mousesel(e, 1); #if OPENURLONCLICK_PATCH @@ -792,7 +838,7 @@ brelease(XEvent *e) openUrlOnClick(evcol(e), evrow(e), url_opener); #endif // OPENURLONCLICK_PATCH } - #endif // VIM_BROWSE_PATCH + #if RIGHTCLICKTOPLUMB_PATCH else if (btn == Button3) plumb(xsel.primary); @@ -818,9 +864,6 @@ bmotion(XEvent *e) } #endif // HIDECURSOR_PATCH #if OPENURLONCLICK_PATCH - #if VIM_BROWSE_PATCH - if (!IS_SET(MODE_NORMAL)) - #endif // VIM_BROWSE_PATCH if (!IS_SET(MODE_MOUSE)) { if (!(e->xbutton.state & Button1Mask) && detecturl(evcol(e), evrow(e), 1)) XDefineCursor(xw.dpy, xw.win, xw.upointer); @@ -850,7 +893,7 @@ cresize(int width, int height) col = (win.w - 2 * borderpx) / win.cw; row = (win.h - 2 * borderpx) / win.ch; - col = MAX(1, col); + col = MAX(2, col); row = MAX(1, row); #if ANYSIZE_PATCH @@ -872,18 +915,23 @@ xresize(int col, int row) #if !SINGLE_DRAWABLE_BUFFER_PATCH XFreePixmap(xw.dpy, xw.buf); xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, - #if ALPHA_PATCH - xw.depth - #else - DefaultDepth(xw.dpy, xw.scr) - #endif // ALPHA_PATCH + #if ALPHA_PATCH + xw.depth + #else + DefaultDepth(xw.dpy, xw.scr) + #endif // ALPHA_PATCH ); XftDrawChange(xw.draw, xw.buf); #endif // SINGLE_DRAWABLE_BUFFER_PATCH xclear(0, 0, win.w, win.h); /* resize to new width */ + #if LIGATURES_PATCH + xw.specbuf = xrealloc(xw.specbuf, col * sizeof(GlyphFontSpec) * 4); + xw.specseq = xrealloc(xw.specseq, col * sizeof(GlyphFontSeq)); + #else xw.specbuf = xrealloc(xw.specbuf, col * sizeof(GlyphFontSpec)); + #endif // LIGATURES_PATCH } ushort @@ -916,17 +964,6 @@ xloadcolor(int i, const char *name, Color *ncolor) return XftColorAllocName(xw.dpy, xw.vis, xw.cmap, name, ncolor); } -#if VIM_BROWSE_PATCH -void normalMode() -{ - #if OPENURLONCLICK_PATCH - clearurl(); - restoremousecursor(); - #endif // OPENURLONCLICK_PATCH - historyModeToggle((win.mode ^=MODE_NORMAL) & MODE_NORMAL); -} -#endif // VIM_BROWSE_PATCH - #if ALPHA_PATCH && ALPHA_FOCUS_HIGHLIGHT_PATCH void xloadalpha(void) @@ -994,6 +1031,9 @@ xloadcols(void) dc.col[defaultbg].color.alpha = (unsigned short)(0xffff * alpha); dc.col[defaultbg].pixel &= 0x00FFFFFF; dc.col[defaultbg].pixel |= (unsigned char)(0xff * alpha) << 24; + dc.col[defaultbg].color.red *= alpha; + dc.col[defaultbg].color.green *= alpha; + dc.col[defaultbg].color.blue *= alpha; #endif // ALPHA_PATCH loaded = 1; } @@ -1002,7 +1042,7 @@ xloadcols(void) int xgetcolor(int x, unsigned char *r, unsigned char *g, unsigned char *b) { - if (!BETWEEN(x, 0, dc.collen)) + if (!BETWEEN(x, 0, dc.collen - 1)) return 1; *r = dc.col[x].color.red >> 8; @@ -1017,7 +1057,7 @@ xsetcolorname(int x, const char *name) { Color ncolor; - if (!BETWEEN(x, 0, dc.collen)) + if (!BETWEEN(x, 0, dc.collen - 1)) return 1; if (!xloadcolor(x, name, &ncolor)) @@ -1034,6 +1074,9 @@ xsetcolorname(int x, const char *name) dc.col[defaultbg].color.alpha = (unsigned short)(0xffff * alpha); dc.col[defaultbg].pixel &= 0x00FFFFFF; dc.col[defaultbg].pixel |= (unsigned char)(0xff * alpha) << 24; + dc.col[defaultbg].color.red *= alpha; + dc.col[defaultbg].color.green *= alpha; + dc.col[defaultbg].color.blue *= alpha; } #endif // ALPHA_PATCH return 0; @@ -1435,13 +1478,31 @@ xinit(int cols, int rows) xloadcols(); /* adjust fixed window geometry */ - #if ANYSIZE_PATCH + #if ANYGEOMETRY_PATCH + switch (geometry) { + case CellGeometry: + #if ANYSIZE_PATCH + win.w = 2 * win.hborderpx + cols * win.cw; + win.h = 2 * win.vborderpx + rows * win.ch; + #else + win.w = 2 * borderpx + cols * win.cw; + win.h = 2 * borderpx + rows * win.ch; + #endif // ANYGEOMETRY_PATCH | ANYSIZE_PATCH + break; + case PixelGeometry: + win.w = cols; + win.h = rows; + cols = (win.w - 2 * borderpx) / win.cw; + rows = (win.h - 2 * borderpx) / win.ch; + break; + } + #elif ANYSIZE_PATCH win.w = 2 * win.hborderpx + cols * win.cw; win.h = 2 * win.vborderpx + rows * win.ch; #else win.w = 2 * borderpx + cols * win.cw; win.h = 2 * borderpx + rows * win.ch; - #endif // ANYSIZE_PATCH + #endif // ANYGEOMETRY_PATCH | ANYSIZE_PATCH if (xw.gm & XNegative) xw.l += DisplayWidth(xw.dpy, xw.scr) - win.w - 2; if (xw.gm & YNegative) @@ -1500,7 +1561,12 @@ xinit(int cols, int rows) XFillRectangle(xw.dpy, xw.buf, dc.gc, 0, 0, win.w, win.h); /* font spec buffer */ + #if LIGATURES_PATCH + xw.specbuf = xmalloc(cols * sizeof(GlyphFontSpec) * 4); + xw.specseq = xmalloc(cols * sizeof(GlyphFontSeq)); + #else xw.specbuf = xmalloc(cols * sizeof(GlyphFontSpec)); + #endif // LIGATURES_PATCH /* Xft rendering context */ xw.draw = XftDrawCreate(xw.dpy, xw.buf, xw.vis, xw.cmap); @@ -1567,11 +1633,9 @@ xinit(int cols, int rows) xw.netwmiconname = XInternAtom(xw.dpy, "_NET_WM_ICON_NAME", False); XSetWMProtocols(xw.dpy, xw.win, &xw.wmdeletewin, 1); - #if NETWMICON_PATCH - xw.netwmicon = XInternAtom(xw.dpy, "_NET_WM_ICON", False); - XChangeProperty(xw.dpy, xw.win, xw.netwmicon, XA_CARDINAL, 32, - PropModeReplace, (uchar *)&icon, LEN(icon)); - #endif //NETWMICON_PATCH + #if NETWMICON_PATCH || NETWMICON_FF_PATCH || NETWMICON_LEGACY_PATCH + setnetwmicon(); + #endif // NETWMICON_PATCH #if NO_WINDOW_DECORATIONS_PATCH Atom motifwmhints = XInternAtom(xw.dpy, "_MOTIF_WM_HINTS", False); @@ -1610,7 +1674,7 @@ xinit(int cols, int rows) #if LIGATURES_PATCH void -xresetfontsettings(ushort mode, Font **font, int *frcflags) +xresetfontsettings(uint32_t mode, Font **font, int *frcflags) { *font = &dc.font; if ((mode & ATTR_ITALIC) && (mode & ATTR_BOLD)) { @@ -1637,7 +1701,7 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x ushort mode, prevmode = USHRT_MAX; Font *font = &dc.font; int frcflags = FRC_NORMAL; - float runewidth = win.cw; + float runewidth = win.cw * ((glyphs[0].mode & ATTR_WIDE) ? 2.0f : 1.0f); Rune rune; FT_UInt glyphidx; FcResult fcres; @@ -1646,160 +1710,136 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x FcCharSet *fccharset; int i, f, numspecs = 0; #if LIGATURES_PATCH - int length = 0, start = 0; - HbTransformData shaped = { 0 }; + float cluster_xp, cluster_yp; + HbTransformData shaped; /* Initial values. */ - mode = prevmode = glyphs[0].mode; - xresetfontsettings(mode, &font, &frcflags); + xresetfontsettings(glyphs[0].mode, &font, &frcflags); + #if VERTCENTER_PATCH + xp = winx, yp = winy + font->ascent + win.cyo; + #else + xp = winx, yp = winy + font->ascent; + #endif // VERTCENTER_PATCH + cluster_xp = xp; cluster_yp = yp; + /* Shape the segment. */ + hbtransform(&shaped, font->match, glyphs, 0, len); #endif // LIGATURES_PATCH - #if VERTCENTER_PATCH + #if LIGATURES_PATCH + for (int code_idx = 0; code_idx < shaped.count; code_idx++) + #elif VERTCENTER_PATCH for (i = 0, xp = winx, yp = winy + font->ascent + win.cyo; i < len; ++i) #else for (i = 0, xp = winx, yp = winy + font->ascent; i < len; ++i) - #endif // VERTCENTER_PATCH + #endif // LIGATURES_PATCH | VERTCENTER_PATCH { /* Fetch rune and mode for current glyph. */ - #if VIM_BROWSE_PATCH - Glyph g = glyphs[i]; - historyOverlay(x+i, y, &g); - rune = g.u; - mode = g.mode; - #elif LIGATURES_PATCH - mode = glyphs[i].mode; + #if LIGATURES_PATCH + int idx = shaped.glyphs[code_idx].cluster; #else rune = glyphs[i].u; mode = glyphs[i].mode; - #endif // VIM_BROWSE_PATCH | LIGATURES_PATCH + #endif // LIGATURES_PATCH /* Skip dummy wide-character spacing. */ #if LIGATURES_PATCH - if (mode & ATTR_WDUMMY) + if (glyphs[idx].mode & ATTR_WDUMMY) continue; - if ( - prevmode != mode - || ATTRCMP(glyphs[start], glyphs[i]) - || selected(x + i, y) != selected(x + start, y) - || i == (len - 1) - ) { - /* Handle 1-character wide segments and end of line */ - length = i - start; - if (i == start) { - length = 1; - } else if (i == (len - 1)) { - length = (i - start + 1); - } + /* Advance the drawing cursor if we've moved to a new cluster */ + if (code_idx > 0 && idx != shaped.glyphs[code_idx - 1].cluster) { + xp += runewidth; + cluster_xp = xp; + cluster_yp = yp; + } - /* Shape the segment. */ - hbtransform(&shaped, font->match, glyphs, start, length); - for (int code_idx = 0; code_idx < shaped.count; code_idx++) { - rune = glyphs[start + code_idx].u; - runewidth = win.cw * ((glyphs[start + code_idx].mode & ATTR_WIDE) ? 2.0f : 1.0f); - - if (glyphs[start + code_idx].mode & ATTR_WDUMMY) - continue; - - #if BOXDRAW_PATCH - if (glyphs[start + code_idx].mode & ATTR_BOXDRAW) { - /* minor shoehorning: boxdraw uses only this ushort */ - specs[numspecs].font = font->match; - specs[numspecs].glyph = boxdrawindex(&glyphs[start + code_idx]); - specs[numspecs].x = xp; - specs[numspecs].y = yp; - xp += runewidth; - numspecs++; - } else - #endif // BOXDRAW_PATCH - if (shaped.glyphs[code_idx].codepoint != 0) { - /* If symbol is found, put it into the specs. */ - specs[numspecs].font = font->match; - specs[numspecs].glyph = shaped.glyphs[code_idx].codepoint; - specs[numspecs].x = xp + (short)shaped.positions[code_idx].x_offset; - specs[numspecs].y = yp + (short)shaped.positions[code_idx].y_offset; - xp += runewidth; - numspecs++; - } else { - /* If it's not found, try to fetch it through the font cache. */ - 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++; + #if BOXDRAW_PATCH + if (glyphs[idx].mode & ATTR_BOXDRAW) { + /* minor shoehorning: boxdraw uses only this ushort */ + specs[numspecs].font = font->match; + specs[numspecs].glyph = boxdrawindex(&glyphs[idx]); + specs[numspecs].x = xp; + specs[numspecs].y = yp; + numspecs++; + } else if (shaped.glyphs[code_idx].codepoint != 0) { + #else + if (shaped.glyphs[code_idx].codepoint != 0) { + #endif // BOXDRAW_PATCH + /* If symbol is found, put it into the specs. */ + specs[numspecs].font = font->match; + specs[numspecs].glyph = shaped.glyphs[code_idx].codepoint; + specs[numspecs].x = cluster_xp + (short)(shaped.positions[code_idx].x_offset / 64.); + specs[numspecs].y = cluster_yp - (short)(shaped.positions[code_idx].y_offset / 64.); + cluster_xp += shaped.positions[code_idx].x_advance / 64.; + cluster_yp += shaped.positions[code_idx].y_advance / 64.; + numspecs++; + } else { + /* If it's not found, try to fetch it through the font cache. */ + rune = glyphs[idx].u; + 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; } } - /* Cleanup and get ready for next segment. */ - hbcleanup(&shaped); - start = i; + /* 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; - /* Determine font for glyph if different from previous glyph. */ - if (prevmode != mode) { - prevmode = mode; - xresetfontsettings(mode, &font, &frcflags); - yp = winy + font->ascent; + /* + * 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; + numspecs++; } #else // !LIGATURES_PATCH if (mode == ATTR_WDUMMY) @@ -1972,19 +2012,25 @@ static int getSlope (int x, int iPoint, int waveWidth) #endif // UNDERCURL_PATCH void -#if WIDE_GLYPHS_PATCH -xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y, int dmode) -#else -xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y) -#endif // WIDE_GLYPHS_PATCH -{ +xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y + #if WIDE_GLYPHS_PATCH + ,int dmode + #endif // WIDE_GLYPHS_PATCH + #if LIGATURES_PATCH + , int charlen + #endif // LIGATURES_PATCH +) { + #if LIGATURES_PATCH + int width = charlen * win.cw; + #else int charlen = len * ((base.mode & ATTR_WIDE) ? 2 : 1); + int width = charlen * win.cw; + #endif // WIDE_GLYPHS_PATCH #if ANYSIZE_PATCH int winx = win.hborderpx + x * win.cw, winy = win.vborderpx + y * win.ch; #else int winx = borderpx + x * win.cw, winy = borderpx + y * win.ch; #endif // ANYSIZE_PATCH - int width = charlen * win.cw; Color *fg, *bg, *temp, revfg, revbg, truefg, truebg; XRenderColor colfg, colbg; XRectangle r; @@ -2078,6 +2124,14 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i #endif // SPOILER_PATCH } + #if SELECTION_COLORS_PATCH + if (base.mode & ATTR_SELECTED) { + bg = &dc.col[selectionbg]; + if (!ignoreselfg) + fg = &dc.col[selectionfg]; + } + #endif // SELECTION_COLORS_PATCH + if (base.mode & ATTR_BLINK && win.mode & MODE_BLINK) fg = bg; @@ -2093,6 +2147,13 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i } #endif // INVERT_PATCH + #if KEYBOARDSELECT_PATCH && REFLOW_PATCH + if (base.mode & ATTR_HIGHLIGHT) { + fg = &dc.col[(base.mode & ATTR_REVERSE) ? highlightbg : highlightfg]; + bg = &dc.col[(base.mode & ATTR_REVERSE) ? highlightfg : highlightbg]; + } + #endif // KEYBOARDSELECT_PATCH + #if ALPHA_PATCH && ALPHA_GRADIENT_PATCH // gradient bg->color.alpha = grad_alpha * 0xffff * (win.h - y*win.ch) / win.h + stat_alpha * 0xffff; @@ -2153,8 +2214,8 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i XftDrawSetClipRectangles(xw.draw, winx, winy, &r, 1); #if WIDE_GLYPHS_PATCH - /* Fill the background */ - XftDrawRect(xw.draw, bg, winx, winy, width, win.ch); + /* Fill the background */ + XftDrawRect(xw.draw, bg, winx, winy, width, win.ch); } #endif // WIDE_GLYPHS_PATCH @@ -2552,6 +2613,7 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i #endif // WIDE_GLYPHS_PATCH #if OPENURLONCLICK_PATCH + /* underline url (openurlonclick patch) */ if (url_draw && y >= url_y1 && y <= url_y2) { int x1 = (y == url_y1) ? url_x1 : 0; int x2 = (y == url_y2) ? MIN(url_x2, term.col-1) : url_maxcol; @@ -2581,14 +2643,17 @@ void xdrawglyph(Glyph g, int x, int y) { int numspecs; - XftGlyphFontSpec spec; + XftGlyphFontSpec *specs = xw.specbuf; - numspecs = xmakeglyphfontspecs(&spec, &g, 1, x, y); - #if WIDE_GLYPHS_PATCH - xdrawglyphfontspecs(&spec, g, numspecs, x, y, DRAW_BG | DRAW_FG); - #else - xdrawglyphfontspecs(&spec, g, numspecs, x, y); - #endif // WIDE_GLYPHS_PATCH + numspecs = xmakeglyphfontspecs(specs, &g, 1, x, y); + xdrawglyphfontspecs(specs, g, numspecs, x, y + #if WIDE_GLYPHS_PATCH + ,DRAW_BG | DRAW_FG + #endif // WIDE_GLYPHS_PATCH + #if LIGATURES_PATCH + ,(g.mode & ATTR_WIDE) ? 2 : 1 + #endif // LIGATURES_PATCH + ); } void @@ -2603,9 +2668,16 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og) XRenderColor colbg; #endif // DYNAMIC_CURSOR_COLOR_PATCH + #if !DYNAMIC_CURSOR_COLOR_PATCH /* remove the old cursor */ if (selected(ox, oy)) + #if SELECTION_COLORS_PATCH + og.mode |= ATTR_SELECTED; + #else og.mode ^= ATTR_REVERSE; + #endif // SELECTION_COLORS_PATCH + #endif // DYNAMIC_CURSOR_COLOR_PATCH + #if LIGATURES_PATCH /* Redraw the line where cursor was previously. * It will restore the ligatures broken by the cursor. */ @@ -2625,15 +2697,25 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og) /* * Select the right color for the right mode. */ + g.mode &= ATTR_BOLD|ATTR_ITALIC|ATTR_UNDERLINE|ATTR_STRUCK|ATTR_WIDE #if BOXDRAW_PATCH - g.mode &= ATTR_BOLD|ATTR_ITALIC|ATTR_UNDERLINE|ATTR_STRUCK|ATTR_WIDE|ATTR_BOXDRAW; - #else - g.mode &= ATTR_BOLD|ATTR_ITALIC|ATTR_UNDERLINE|ATTR_STRUCK|ATTR_WIDE; + |ATTR_BOXDRAW #endif // BOXDRAW_PATCH + #if DYNAMIC_CURSOR_COLOR_PATCH + |ATTR_REVERSE + #endif // DYNAMIC_CURSOR_COLOR_PATCH + #if KEYBOARDSELECT_PATCH && REFLOW_PATCH + |ATTR_HIGHLIGHT + #endif // KEYBOARDSELECT_PATCH + ; if (IS_SET(MODE_REVERSE)) { g.mode |= ATTR_REVERSE; g.bg = defaultfg; + #if SELECTION_COLORS_PATCH + g.fg = defaultcs; + drawcol = dc.col[defaultrcs]; + #else if (selected(cx, cy)) { drawcol = dc.col[defaultcs]; g.fg = defaultrcs; @@ -2641,25 +2723,33 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og) drawcol = dc.col[defaultrcs]; g.fg = defaultcs; } + #endif // SELECTION_COLORS_PATCH } else { + #if SELECTION_COLORS_PATCH + g.fg = defaultbg; + g.bg = defaultcs; + drawcol = dc.col[defaultcs]; + #else if (selected(cx, cy)) { + #if KEYBOARDSELECT_PATCH && REFLOW_PATCH + g.mode &= ~(ATTR_REVERSE | ATTR_HIGHLIGHT); + #elif DYNAMIC_CURSOR_COLOR_PATCH + g.mode &= ~ATTR_REVERSE; + #endif // DYNAMIC_CURSOR_COLOR_PATCH g.fg = defaultfg; g.bg = defaultrcs; - } - #if !DYNAMIC_CURSOR_COLOR_PATCH - else { - g.fg = defaultbg; - g.bg = defaultcs; - } - - drawcol = dc.col[g.bg]; - #else - else if (!(og.mode & ATTR_REVERSE)) { + } else { + #if DYNAMIC_CURSOR_COLOR_PATCH unsigned int tmpcol = g.bg; g.bg = g.fg; g.fg = tmpcol; + #else + g.fg = defaultbg; + g.bg = defaultcs; + #endif // DYNAMIC_CURSOR_COLOR_PATCH } + #if DYNAMIC_CURSOR_COLOR_PATCH if (IS_TRUECOL(g.bg)) { colbg.alpha = 0xffff; colbg.red = TRUERED(g.bg); @@ -2668,9 +2758,17 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og) XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colbg, &drawcol); } else drawcol = dc.col[g.bg]; + #else + drawcol = dc.col[g.bg]; #endif // DYNAMIC_CURSOR_COLOR_PATCH + #endif // SELECTION_COLORS_PATCH } + #if KEYBOARDSELECT_PATCH && REFLOW_PATCH + if (g.mode & ATTR_HIGHLIGHT) + g.mode ^= ATTR_REVERSE; + #endif // KEYBOARDSELECT_PATCH + /* draw the new one */ if (IS_SET(MODE_FOCUSED)) { switch (win.cursor) { @@ -2793,6 +2891,9 @@ xseticontitle(char *p) XTextProperty prop; DEFAULT(p, opt_title); + if (p[0] == '\0') + p = opt_title; + if (Xutf8TextListToTextProperty(xw.dpy, &p, 1, XUTF8StringStyle, &prop) != Success) return; @@ -2812,7 +2913,7 @@ xsettitle(char *p, int pop) titlestack[tstki] = NULL; tstki = (tstki - 1 + TITLESTACKSIZE) % TITLESTACKSIZE; p = titlestack[tstki] ? titlestack[tstki] : opt_title; - } else if (p) { + } else if (p && p[0] != '\0') { titlestack[tstki] = xstrdup(p); } else { titlestack[tstki] = NULL; @@ -2852,6 +2953,9 @@ xsettitle(char *p) XTextProperty prop; DEFAULT(p, opt_title); + if (p[0] == '\0') + p = opt_title; + if (Xutf8TextListToTextProperty(xw.dpy, &p, 1, XUTF8StringStyle, &prop) != Success) return; @@ -2871,15 +2975,109 @@ xstartdraw(void) return IS_SET(MODE_VISIBLE); } +#if LIGATURES_PATCH && WIDE_GLYPHS_PATCH +void +xdrawline(Line line, int x1, int y1, int x2) +{ + int i, j, x, ox, numspecs; + Glyph new; + GlyphFontSeq *seq = xw.specseq; + XftGlyphFontSpec *specs = xw.specbuf; + + /* Draw line in 2 passes: background and foreground. This way wide glyphs + won't get truncated (#223) */ + + /* background */ + i = j = ox = 0; + for (x = x1; x < x2; x++) { + new = line[x]; + if (new.mode == ATTR_WDUMMY) + continue; + if (selected(x, y1)) + #if SELECTION_COLORS_PATCH + new.mode |= ATTR_SELECTED; + #else + new.mode ^= ATTR_REVERSE; + #endif // SELECTION_COLORS_PATCH + if ((i > 0) && ATTRCMP(seq[j].base, new)) { + numspecs = xmakeglyphfontspecs(specs, &line[ox], x - ox, ox, y1); + xdrawglyphfontspecs(specs, seq[j].base, numspecs, ox, y1, DRAW_BG, x - ox); + seq[j].charlen = x - ox; + seq[j++].numspecs = numspecs; + specs += numspecs; + i = 0; + } + if (i == 0) { + ox = x; + seq[j].ox= ox; + seq[j].base = new; + } + i++; + } + if (i > 0) { + numspecs = xmakeglyphfontspecs(specs, &line[ox], x2 - ox, ox, y1); + xdrawglyphfontspecs(specs, seq[j].base, numspecs, ox, y1, DRAW_BG, x2 - ox); + seq[j].charlen = x2 - ox; + seq[j++].numspecs = numspecs; + } + + /* foreground */ + specs = xw.specbuf; + for (i = 0; i < j; i++) { + xdrawglyphfontspecs(specs, seq[i].base, seq[i].numspecs, seq[i].ox, y1, DRAW_FG, seq[i].charlen); + specs += seq[i].numspecs; + } + + #if KEYBOARDSELECT_PATCH && REFLOW_PATCH + kbds_drawstatusbar(y1); + #endif // KEYBOARDSELECT_PATCH +} +#elif LIGATURES_PATCH void xdrawline(Line line, int x1, int y1, int x2) { int i, x, ox, numspecs; - #if WIDE_GLYPHS_PATCH - int numspecs_cached; - #endif // WIDE_GLYPHS_PATCH Glyph base, new; - #if WIDE_GLYPHS_PATCH + + XftGlyphFontSpec *specs = xw.specbuf; + + i = ox = 0; + for (x = x1; x < x2; x++) { + new = line[x]; + if (new.mode == ATTR_WDUMMY) + continue; + if (selected(x, y1)) + #if SELECTION_COLORS_PATCH + new.mode |= ATTR_SELECTED; + #else + new.mode ^= ATTR_REVERSE; + #endif // SELECTION_COLORS_PATCH + if ((i > 0) && ATTRCMP(base, new)) { + numspecs = xmakeglyphfontspecs(specs, &line[ox], x - ox, ox, y1); + xdrawglyphfontspecs(specs, base, numspecs, ox, y1, x - ox); + i = 0; + } + if (i == 0) { + ox = x; + base = new; + } + i++; + } + if (i > 0) { + numspecs = xmakeglyphfontspecs(specs, &line[ox], x2 - ox, ox, y1); + xdrawglyphfontspecs(specs, base, numspecs, ox, y1, x2 - ox); + } + + #if KEYBOARDSELECT_PATCH && REFLOW_PATCH + kbds_drawstatusbar(y1); + #endif // KEYBOARDSELECT_PATCH +} +#elif WIDE_GLYPHS_PATCH +void +xdrawline(Line line, int x1, int y1, int x2) +{ + int i, x, ox, numspecs, numspecs_cached; + Glyph base, new; XftGlyphFontSpec *specs; numspecs_cached = xmakeglyphfontspecs(xw.specbuf, &line[x1], x2 - x1, x1, y1); @@ -2892,13 +3090,14 @@ xdrawline(Line line, int x1, int y1, int x2) i = ox = 0; for (x = x1; x < x2 && i < numspecs; x++) { new = line[x]; - #if VIM_BROWSE_PATCH - historyOverlay(x, y1, &new); - #endif // VIM_BROWSE_PATCH if (new.mode == ATTR_WDUMMY) continue; if (selected(x, y1)) + #if SELECTION_COLORS_PATCH + new.mode |= ATTR_SELECTED; + #else new.mode ^= ATTR_REVERSE; + #endif // SELECTION_COLORS_PATCH if (i > 0 && ATTRCMP(base, new)) { xdrawglyphfontspecs(specs, base, i, ox, y1, dmode); specs += i; @@ -2914,20 +3113,32 @@ xdrawline(Line line, int x1, int y1, int x2) if (i > 0) xdrawglyphfontspecs(specs, base, i, ox, y1, dmode); } - #else + + #if KEYBOARDSELECT_PATCH && REFLOW_PATCH + kbds_drawstatusbar(y1); + #endif // KEYBOARDSELECT_PATCH +} +#else // !WIDE_GLYPHS_PATCH and !LIGATURES_PATCH +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 VIM_BROWSE_PATCH - historyOverlay(x, y1, &new); - #endif // VIM_BROWSE_PATCH if (new.mode == ATTR_WDUMMY) continue; if (selected(x, y1)) + #if SELECTION_COLORS_PATCH + new.mode |= ATTR_SELECTED; + #else new.mode ^= ATTR_REVERSE; + #endif // SELECTION_COLORS_PATCH if (i > 0 && ATTRCMP(base, new)) { xdrawglyphfontspecs(specs, base, i, ox, y1); specs += i; @@ -2942,79 +3153,156 @@ xdrawline(Line line, int x1, int y1, int x2) } if (i > 0) xdrawglyphfontspecs(specs, base, i, ox, y1); - #endif // WIDE_GLYPHS_PATCH + + #if KEYBOARDSELECT_PATCH && REFLOW_PATCH + kbds_drawstatusbar(y1); + #endif // KEYBOARDSELECT_PATCH } +#endif // WIDE_GLYPHS_PATCH | LIGATURES_PATCH void xfinishdraw(void) { #if SIXEL_PATCH ImageList *im, *next; + Imlib_Image origin, scaled; XGCValues gcvalues; GC gc; + int width, height; + int x, x2, del, destx, desty; + Line line; #endif // SIXEL_PATCH #if SIXEL_PATCH for (im = term.images; im; im = next) { - /* get the next image here, because delete_image() will delete the current image */ next = im->next; - if (im->should_delete) { - delete_image(im); + /* do not draw or process the image, if it is not visible */ + if (im->x >= term.col || im->y >= term.row || im->y < 0) continue; - } + #if KEYBOARDSELECT_PATCH && REFLOW_PATCH + /* do not draw the image on the search bar */ + if (im->y == term.row-1 && IS_SET(MODE_KBDSELECT) && kbds_issearchmode()) + continue; + #endif // KEYBOARDSELECT_PATCH + + /* scale the image */ + width = MAX(im->width * win.cw / im->cw, 1); + height = MAX(im->height * win.ch / im->ch, 1); if (!im->pixmap) { - im->pixmap = (void *)XCreatePixmap(xw.dpy, xw.win, im->width, im->height, + im->pixmap = (void *)XCreatePixmap(xw.dpy, xw.win, width, height, #if ALPHA_PATCH xw.depth #else DefaultDepth(xw.dpy, xw.scr) #endif // ALPHA_PATCH ); - XImage ximage = { - .format = ZPixmap, - .data = (char *)im->pixels, - .width = im->width, - .height = im->height, - .xoffset = 0, - .byte_order = LSBFirst, - .bitmap_bit_order = MSBFirst, - .bits_per_pixel = 32, - .bytes_per_line = im->width * 4, - .bitmap_unit = 32, - .bitmap_pad = 32, - #if ALPHA_PATCH - .depth = xw.depth - #else - .depth = 24 - #endif // ALPHA_PATCH - }; - XPutImage(xw.dpy, (Drawable)im->pixmap, dc.gc, &ximage, 0, 0, 0, 0, im->width, im->height); - free(im->pixels); - im->pixels = NULL; + if (!im->pixmap) + continue; + if (win.cw == im->cw && win.ch == im->ch) { + XImage ximage = { + .format = ZPixmap, + .data = (char *)im->pixels, + .width = im->width, + .height = im->height, + .xoffset = 0, + .byte_order = sixelbyteorder, + .bitmap_bit_order = MSBFirst, + .bits_per_pixel = 32, + .bytes_per_line = im->width * 4, + .bitmap_unit = 32, + .bitmap_pad = 32, + #if ALPHA_PATCH + .depth = xw.depth + #else + .depth = 24 + #endif // ALPHA_PATCH + }; + XPutImage(xw.dpy, (Drawable)im->pixmap, dc.gc, &ximage, 0, 0, 0, 0, width, height); + if (im->transparent) + im->clipmask = (void *)sixel_create_clipmask((char *)im->pixels, width, height); + } else { + origin = imlib_create_image_using_data(im->width, im->height, (DATA32 *)im->pixels); + if (!origin) + continue; + imlib_context_set_image(origin); + imlib_image_set_has_alpha(1); + imlib_context_set_anti_alias(im->transparent ? 0 : 1); /* anti-aliasing messes up the clip mask */ + scaled = imlib_create_cropped_scaled_image(0, 0, im->width, im->height, width, height); + imlib_free_image_and_decache(); + if (!scaled) + continue; + imlib_context_set_image(scaled); + imlib_image_set_has_alpha(1); + XImage ximage = { + .format = ZPixmap, + .data = (char *)imlib_image_get_data_for_reading_only(), + .width = width, + .height = height, + .xoffset = 0, + .byte_order = sixelbyteorder, + .bitmap_bit_order = MSBFirst, + .bits_per_pixel = 32, + .bytes_per_line = width * 4, + .bitmap_unit = 32, + .bitmap_pad = 32, + #if ALPHA_PATCH + .depth = xw.depth + #else + .depth = 24 + #endif // ALPHA_PATCH + }; + XPutImage(xw.dpy, (Drawable)im->pixmap, dc.gc, &ximage, 0, 0, 0, 0, width, height); + if (im->transparent) + im->clipmask = (void *)sixel_create_clipmask((char *)imlib_image_get_data_for_reading_only(), width, height); + imlib_free_image_and_decache(); + } } + /* clip the image so it does not go over to borders */ + x2 = MIN(im->x + im->cols, term.col); + width = MIN(width, (x2 - im->x) * win.cw); + + /* delete the image if the text cells behind it have been changed */ + #if SCROLLBACK_PATCH || REFLOW_PATCH + line = TLINE(im->y); + #else + line = term.line[im->y]; + #endif // SCROLLBACK_PATCH | REFLOW_PATCH + for (del = 0, x = im->x; x < x2; x++) { + if ((del = !(line[x].mode & ATTR_SIXEL))) + break; + } + if (del) { + delete_image(im); + continue; + } + + /* draw the image */ memset(&gcvalues, 0, sizeof(gcvalues)); gcvalues.graphics_exposures = False; gc = XCreateGC(xw.dpy, xw.win, GCGraphicsExposures, &gcvalues); - #if ANYSIZE_PATCH - XCopyArea(xw.dpy, (Drawable)im->pixmap, xw.buf, gc, 0, 0, im->width, im->height, win.hborderpx + im->x * win.cw, win.vborderpx + im->y * win.ch); + destx = win.hborderpx + im->x * win.cw; + desty = win.vborderpx + im->y * win.ch; #else - XCopyArea(xw.dpy, (Drawable)im->pixmap, xw.buf, gc, 0, 0, im->width, im->height, borderpx + im->x * win.cw, borderpx + im->y * win.ch); + destx = borderpx + im->x * win.cw; + desty = borderpx + im->y * win.ch; #endif // ANYSIZE_PATCH + if (im->clipmask) { + XSetClipMask(xw.dpy, gc, (Drawable)im->clipmask); + XSetClipOrigin(xw.dpy, gc, destx, desty); + } + XCopyArea(xw.dpy, (Drawable)im->pixmap, xw.buf, gc, 0, 0, width, height, destx, desty); XFreeGC(xw.dpy, gc); - } #endif // SIXEL_PATCH #if !SINGLE_DRAWABLE_BUFFER_PATCH XCopyArea(xw.dpy, xw.buf, xw.win, dc.gc, 0, 0, win.w, win.h, 0, 0); #endif // SINGLE_DRAWABLE_BUFFER_PATCH - XSetForeground(xw.dpy, dc.gc, - dc.col[IS_SET(MODE_REVERSE)? - defaultfg : defaultbg].pixel); + XSetForeground(xw.dpy, dc.gc, dc.col[IS_SET(MODE_REVERSE) ? defaultfg : defaultbg].pixel); } void @@ -3249,7 +3537,7 @@ kpress(XEvent *ev) Shortcut *bp; #if HIDECURSOR_PATCH - if (xw.pointerisvisible) { + if (xw.pointerisvisible && hidecursor) { #if OPENURLONCLICK_PATCH #if ANYSIZE_PATCH int x = e->x - win.hborderpx; @@ -3283,7 +3571,25 @@ kpress(XEvent *ev) } else { len = XLookupString(e, buf, sizeof buf, &ksym, NULL); } - #if KEYBOARDSELECT_PATCH + + #if KEYBOARDSELECT_PATCH && REFLOW_PATCH + if (IS_SET(MODE_KBDSELECT) ) { + if (kbds_issearchmode()) { + for (bp = shortcuts; bp < shortcuts + LEN(shortcuts); bp++) { + if (ksym == bp->keysym && match(bp->mod, e->state) && + (!bp->screen || bp->screen == screen) && + (bp->func == clippaste || bp->func == selpaste)) { + bp->func(&(bp->arg)); + return; + } + } + } + if (match(XK_NO_MOD, e->state) || + (XK_Shift_L | XK_Shift_R) & e->state ) + win.mode ^= kbds_keyboardhandler(ksym, buf, len, 0); + return; + } + #elif KEYBOARDSELECT_PATCH if ( IS_SET(MODE_KBDSELECT) ) { if ( match(XK_NO_MOD, e->state) || (XK_Shift_L | XK_Shift_R) & e->state ) @@ -3291,13 +3597,6 @@ kpress(XEvent *ev) return; } #endif // KEYBOARDSELECT_PATCH - #if VIM_BROWSE_PATCH - if (IS_SET(MODE_NORMAL)) { - if (kPressHist(buf, len, match(ControlMask, e->state), &ksym) - == finish) normalMode(); - return; - } - #endif // VIM_BROWSE_PATCH screen = tisaltscr() ? S_ALT : S_PRI; @@ -3547,17 +3846,17 @@ usage(void) " [-d path]" #endif // WORKINGDIR_PATCH " [-f font] [-g geometry]" - " [-n name] [-o file]\n" - " [-T title] [-t title] [-w windowid]" - " [[-e] command [args ...]]\n" - " %s [-aiv] [-c class]" + " [-n name] [-o file]\n" + " [-T title] [-t title] [-w windowid]" + " [[-e] command [args ...]]\n" + " %s [-aiv] [-c class]" #if WORKINGDIR_PATCH " [-d path]" #endif // WORKINGDIR_PATCH " [-f font] [-g geometry]" - " [-n name] [-o file]\n" - " [-T title] [-t title] [-w windowid] -l line" - " [stty_args ...]\n", argv0, argv0); + " [-n name] [-o file]\n" + " [-T title] [-t title] [-w windowid] -l line" + " [stty_args ...]\n", argv0, argv0); } int @@ -3598,7 +3897,17 @@ main(int argc, char *argv[]) case 'g': xw.gm = XParseGeometry(EARGF(usage()), &xw.l, &xw.t, &cols, &rows); + #if ANYGEOMETRY_PATCH + geometry = CellGeometry; + #endif // ANYGEOMETRY_PATCH break; + #if ANYGEOMETRY_PATCH + case 'G': + xw.gm = XParseGeometry(EARGF(usage()), + &xw.l, &xw.t, &width, &height); + geometry = PixelGeometry; + break; + #endif // ANYGEOMETRY_PATCH case 'i': xw.isfixed = 1; break; @@ -3643,13 +3952,32 @@ run: config_init(xw.dpy); #endif // XRESOURCES_PATCH + #if LIGATURES_PATCH + hbcreatebuffer(); + #endif // LIGATURES_PATCH + + #if ANYGEOMETRY_PATCH + switch (geometry) { + case CellGeometry: + xinit(cols, rows); + break; + case PixelGeometry: + xinit(width, height); + cols = (win.w - 2 * borderpx) / win.cw; + rows = (win.h - 2 * borderpx) / win.ch; + break; + } + #endif // ANYGEOMETRY_PATCH + cols = MAX(cols, 1); rows = MAX(rows, 1); #if ALPHA_PATCH && ALPHA_FOCUS_HIGHLIGHT_PATCH defaultbg = MAX(LEN(colorname), 256); #endif // ALPHA_FOCUS_HIGHLIGHT_PATCH tnew(cols, rows); + #if !ANYGEOMETRY_PATCH xinit(cols, rows); + #endif // ANYGEOMETRY_PATCH #if BACKGROUND_IMAGE_PATCH bginit(); #endif // BACKGROUND_IMAGE_PATCH @@ -3660,6 +3988,9 @@ run: die("Can't change to working directory %s\n", opt_dir); #endif // WORKINGDIR_PATCH run(); + #if LIGATURES_PATCH + hbdestroybuffer(); + #endif // LIGATURES_PATCH return 0; } diff --git a/tabbed-flexipatch/Makefile b/tabbed-flexipatch/Makefile index 2db479f..669d6fc 100644 --- a/tabbed-flexipatch/Makefile +++ b/tabbed-flexipatch/Makefile @@ -1,69 +1,76 @@ -# tabbed - tabbing interface -# See LICENSE file for copyright and license details. +.POSIX: -include config.mk +NAME = tabbed +VERSION = 0.8 + +# Uncomment this for the alpha patch / ALPHA_PATCH +LDFLAGS = -lXrender + +# paths +PREFIX = /usr/local +MANPREFIX = ${PREFIX}/share/man +DOCPREFIX = ${PREFIX}/share/doc/${NAME} + +# use system flags. +TABBED_CFLAGS = -I/usr/X11R6/include -I/usr/include/freetype2 ${CFLAGS} +TABBED_LDFLAGS = -L/usr/X11R6/lib -lX11 -lfontconfig -lXft ${LDFLAGS} +TABBED_CPPFLAGS = -DVERSION=\"${VERSION}\" -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=700L + +# OpenBSD (uncomment) +#TABBED_CFLAGS = -I/usr/X11R6/include -I/usr/X11R6/include/freetype2 ${CFLAGS} SRC = tabbed.c xembed.c OBJ = ${SRC:.c=.o} BIN = ${OBJ:.o=} +MAN1 = ${BIN:=.1} +HDR = arg.h config.def.h +DOC = LICENSE README +CC = cc -all: options ${BIN} - -options: - @echo tabbed build options: - @echo "CFLAGS = ${CFLAGS}" - @echo "LDFLAGS = ${LDFLAGS}" - @echo "CC = ${CC}" +all: ${BIN} .c.o: - @echo CC $< - @${CC} -c ${CFLAGS} $< + ${CC} -o $@ -c $< ${TABBED_CFLAGS} ${TABBED_CPPFLAGS} -${OBJ}: config.h config.mk patches.h +${OBJ}: config.h config.h: - @echo creating $@ from config.def.h - @cp config.def.h $@ + cp config.def.h $@ patches.h: - @echo creating $@ from patches.def.h - @cp patches.def.h $@ + cp patches.def.h $@ .o: - @echo CC -o $@ - @${CC} -o $@ $< ${LDFLAGS} + ${CC} -o $@ $< ${TABBED_LDFLAGS} clean: - @echo cleaning - @rm -f ${BIN} ${OBJ} tabbed-${VERSION}.tar.gz + rm -f ${BIN} ${OBJ} "${NAME}-${VERSION}.tar.gz" dist: clean - @echo creating dist tarball - @mkdir -p tabbed-${VERSION} - @cp -R LICENSE Makefile README config.def.h config.mk \ - tabbed.1 arg.h ${SRC} tabbed-${VERSION} - @tar -cf tabbed-${VERSION}.tar tabbed-${VERSION} - @gzip tabbed-${VERSION}.tar - @rm -rf tabbed-${VERSION} + mkdir -p "${NAME}-${VERSION}" + cp -fR Makefile ${MAN1} ${DOC} ${HDR} ${SRC} "${NAME}-${VERSION}" + tar -cf - "${NAME}-${VERSION}" | gzip -c > "${NAME}-${VERSION}.tar.gz" + rm -rf ${NAME}-${VERSION} install: all - @echo installing executable files to ${DESTDIR}${PREFIX}/bin - @mkdir -p "${DESTDIR}${PREFIX}/bin" - @cp -f ${BIN} "${DESTDIR}${PREFIX}/bin" - @chmod 755 "${DESTDIR}${PREFIX}/bin/tabbed" - @echo installing manual pages to ${DESTDIR}${MANPREFIX}/man1 - @mkdir -p "${DESTDIR}${MANPREFIX}/man1" - @sed "s/VERSION/${VERSION}/g" < tabbed.1 > "${DESTDIR}${MANPREFIX}/man1/tabbed.1" - @chmod 644 "${DESTDIR}${MANPREFIX}/man1/tabbed.1" - @sed "s/VERSION/${VERSION}/g" < xembed.1 > "${DESTDIR}${MANPREFIX}/man1/xembed.1" - @chmod 644 "${DESTDIR}${MANPREFIX}/man1/xembed.1" + # installing executable files. + mkdir -p "${DESTDIR}${PREFIX}/bin" + cp -f ${BIN} "${DESTDIR}${PREFIX}/bin" + for f in ${BIN}; do chmod 755 "${DESTDIR}${PREFIX}/bin/$$f"; done + # installing doc files. + mkdir -p "${DESTDIR}${DOCPREFIX}" + cp -f README "${DESTDIR}${DOCPREFIX}" + # installing manual pages for general commands: section 1. + mkdir -p "${DESTDIR}${MANPREFIX}/man1" + for m in ${MAN1}; do sed "s/VERSION/${VERSION}/g" < $$m > "${DESTDIR}${MANPREFIX}/man1/$$m"; done uninstall: - @echo removing executable files from ${DESTDIR}${PREFIX}/bin - @rm -f "${DESTDIR}${PREFIX}/bin/tabbed" - @rm -f "${DESTDIR}${PREFIX}/bin/xembed" - @echo removing manual pages from ${DESTDIR}${MANPREFIX}/man1 - @rm -f "${DESTDIR}${MANPREFIX}/man1/tabbed.1" - @rm -f "${DESTDIR}${MANPREFIX}/man1/xembed.1" + # removing executable files. + for f in ${BIN}; do rm -f "${DESTDIR}${PREFIX}/bin/$$f"; done + # removing doc files. + rm -f "${DESTDIR}${DOCPREFIX}/README" + # removing manual pages. + for m in ${MAN1}; do rm -f "${DESTDIR}${MANPREFIX}/man1/$$m"; done + -rmdir "${DESTDIR}${DOCPREFIX}" -.PHONY: all options clean dist install uninstall +.PHONY: all clean dist install uninstall diff --git a/tabbed-flexipatch/README.md b/tabbed-flexipatch/README.md index bb9ca57..ef08be5 100644 --- a/tabbed-flexipatch/README.md +++ b/tabbed-flexipatch/README.md @@ -1,4 +1,4 @@ -Similar to [dwm-flexipatch](https://github.com/bakkeby/dwm-flexipatch) this tabbed 0.7 (5ddbc73, 2022-10-05) project has a different take on patching. It uses preprocessor directives to decide whether or not to include a patch during build time. Essentially this means that this build, for better or worse, contains both the patched _and_ the original code. The aim being that you can select which patches to include and the build will contain that code and nothing more. +Similar to [dwm-flexipatch](https://github.com/bakkeby/dwm-flexipatch) this tabbed 0.8 (7215169, 2024-03-19) project has a different take on patching. It uses preprocessor directives to decide whether or not to include a patch during build time. Essentially this means that this build, for better or worse, contains both the patched _and_ the original code. The aim being that you can select which patches to include and the build will contain that code and nothing more. For example to include the `alpha` patch then you would only need to flip this setting from 0 to 1 in [patches.h](https://github.com/bakkeby/tabbed-flexipatch/blob/master/patches.def.h): ```c @@ -15,6 +15,8 @@ Refer to [https://tools.suckless.org/tabbed/](https://tools.suckless.org/tabbed/ ### Changelog: +2023-10-26 - Added the separator, drag, basenames, move-clamped and xresources reload patches + 2022-03-14 - Added the awesomebar patch 2021-07-29 - Added the bar-height and xresources patches @@ -39,6 +41,9 @@ Refer to [https://tools.suckless.org/tabbed/](https://tools.suckless.org/tabbed/ - [bar-height](https://tools.suckless.org/tabbed/patches/bar-height/) - allows the height of the bar to be manually specified + - [basenames](https://tools.suckless.org/tabbed/patches/basenames/) + - show only the basename of the tabbed title + - [bottomtabs](https://github.com/bakkeby/patches/blob/master/tabbed/tabbed-bottomtabs-0.6-20200512-dabf6a2.diff) - moves the tabs / bar to the bottom of the tabbed window @@ -48,6 +53,9 @@ Refer to [https://tools.suckless.org/tabbed/](https://tools.suckless.org/tabbed/ - [clientnumber](https://tools.suckless.org/tabbed/patches/clientnumber/) - prints the position number of the client before the window title + - [drag](https://tools.suckless.org/tabbed/patches/drag/) + - adds support for dragging tabs left and right using the mouse + - [hidetabs](https://tools.suckless.org/tabbed/patches/hidetabs/) - this patch hides all the tabs and only shows them when Mod+Shift is pressed @@ -62,5 +70,17 @@ Refer to [https://tools.suckless.org/tabbed/](https://tools.suckless.org/tabbed/ - [keyrelease](https://tools.suckless.org/tabbed/patches/keyrelease/) - this patch enables for function handling on KeyRelease events + - [move-clamped](https://tools.suckless.org/tabbed/patches/move-clamped/) + - makes tabbed interpret large position numbers as the largest known position + - allows for `Ctrl-9`, for example, to always select the rightmost tab, even if there are only + 4 tabs + + - [separator](https://tools.suckless.org/tabbed/patches/separator/) + - adds a decorator separator to the beginning of each tab + - [xresources](https://tools.suckless.org/tabbed/patches/xresources/) - allows tabbed colors to be defined via Xresources + + - [xresources-reload](https://tools.suckless.org/tabbed/patches/xresources-with-reload-signal/) + - xresources with signal reloading, allows resources to be reloaded during runtime using + the USR1 kill signal diff --git a/tabbed-flexipatch/config.def.h b/tabbed-flexipatch/config.def.h index 92de326..cfc968e 100644 --- a/tabbed-flexipatch/config.def.h +++ b/tabbed-flexipatch/config.def.h @@ -1,26 +1,22 @@ /* See LICENSE file for copyright and license details. */ /* appearance */ -static char font[] = "Hack Nerd Font:size=12"; -static char* normbgcolor = "#222222"; -static char* normfgcolor = "#cccccc"; -static char* selbgcolor = "#555555"; -static char* selfgcolor = "#ffffff"; -static char* urgbgcolor = "#111111"; -static char* urgfgcolor = "#cc0000"; -static const char before[] = "<"; -static const char after[] = ">"; -static const char titletrim[] = "..."; -#if AWESOMEBAR_PATCH -static int tabwidth = 200; -#else -static const int tabwidth = 200; -#endif // AWESOMEBAR_PATCH -static const Bool foreground = True; -static Bool urgentswitch = False; -#if SEPERATOR_PATCH -static const int separator = 1; -#endif // SEPERATOR_PATCH +static char font[] = "Hack Nerd Font:size=12"; +static char* normbgcolor = "#222222"; +static char* normfgcolor = "#cccccc"; +static char* selbgcolor = "#555555"; +static char* selfgcolor = "#ffffff"; +static char* urgbgcolor = "#111111"; +static char* urgfgcolor = "#cc0000"; +static char before[] = "<"; +static char after[] = ">"; +static char titletrim[] = "..."; +static int tabwidth = 200; +static int foreground = 1; +static int urgentswitch = 0; +#if SEPARATOR_PATCH +static int separator = 4; +#endif // SEPARATOR_PATCH #if BAR_HEIGHT_PATCH static const int barheight = 0; /* 0 means derive by font (default), otherwise absolute height */ diff --git a/tabbed-flexipatch/config.mk b/tabbed-flexipatch/config.mk deleted file mode 100644 index 8bd9dab..0000000 --- a/tabbed-flexipatch/config.mk +++ /dev/null @@ -1,36 +0,0 @@ -# tabbed version -VERSION = 0.7 - -# Customize below to fit your system - -# paths -PREFIX = /usr/local -MANPREFIX = ${PREFIX}/share/man - -X11INC = /usr/X11R6/include -X11LIB = /usr/X11R6/lib - -# freetype -FREETYPELIBS = -lfontconfig -lXft -FREETYPEINC = /usr/include/freetype2 -# OpenBSD (uncomment) -#FREETYPEINC = ${X11INC}/freetype2 - -# Uncomment this for the alpha patch / ALPHA_PATCH -XRENDER = -lXrender - -# includes and libs -INCS = -I. -I/usr/include -I$(X11INC) -I${FREETYPEINC} -LIBS = -L/usr/lib -lc -L${X11LIB} -lX11 ${FREETYPELIBS} ${XRENDER} - -# flags -CPPFLAGS = -DVERSION=\"${VERSION}\" -D_DEFAULT_SOURCE -CFLAGS = -std=c99 -pedantic -Wall -Os ${INCS} ${CPPFLAGS} -LDFLAGS = -s ${LIBS} - -# Solaris -#CFLAGS = -fast ${INCS} -DVERSION=\"${VERSION}\" -#LDFLAGS = ${LIBS} - -# compiler and linker -CC = cc diff --git a/tabbed-flexipatch/patch/basename.c b/tabbed-flexipatch/patch/basename.c new file mode 100644 index 0000000..b94e01a --- /dev/null +++ b/tabbed-flexipatch/patch/basename.c @@ -0,0 +1,10 @@ +static Bool basenametitles = False; + +char * +getbasename(const char *name) +{ + char *pos = strrchr(name, '/'); + if (pos) + return pos+1; + return (char *)name; +} diff --git a/tabbed-flexipatch/patch/basename.h b/tabbed-flexipatch/patch/basename.h new file mode 100644 index 0000000..14b9105 --- /dev/null +++ b/tabbed-flexipatch/patch/basename.h @@ -0,0 +1 @@ +static char *getbasename(const char *name); diff --git a/tabbed-flexipatch/patch/drag.c b/tabbed-flexipatch/patch/drag.c index e8ed39b..4eda8a8 100644 --- a/tabbed-flexipatch/patch/drag.c +++ b/tabbed-flexipatch/patch/drag.c @@ -31,4 +31,4 @@ motionnotify(const XEvent *e) break; } } -} +} \ No newline at end of file diff --git a/tabbed-flexipatch/patch/include.c b/tabbed-flexipatch/patch/include.c index c87d004..9f8165f 100644 --- a/tabbed-flexipatch/patch/include.c +++ b/tabbed-flexipatch/patch/include.c @@ -1,4 +1,7 @@ /* Patches */ +#if BASENAME_PATCH +#include "basename.c" +#endif #if DRAG_PATCH #include "drag.c" #endif @@ -13,4 +16,4 @@ #endif #if XRESOURCES_PATCH #include "xresources.c" -#endif +#endif \ No newline at end of file diff --git a/tabbed-flexipatch/patch/include.h b/tabbed-flexipatch/patch/include.h index 6411530..ca05d54 100644 --- a/tabbed-flexipatch/patch/include.h +++ b/tabbed-flexipatch/patch/include.h @@ -1,4 +1,7 @@ /* Patches */ +#if BASENAME_PATCH +#include "basename.h" +#endif #if DRAG_PATCH #include "drag.h" #endif @@ -13,4 +16,4 @@ #endif #if XRESOURCES_PATCH #include "xresources.h" -#endif +#endif \ No newline at end of file diff --git a/tabbed-flexipatch/patch/xresources.c b/tabbed-flexipatch/patch/xresources.c index 5316869..e606f78 100644 --- a/tabbed-flexipatch/patch/xresources.c +++ b/tabbed-flexipatch/patch/xresources.c @@ -4,6 +4,10 @@ config_init(void) char *resm; XrmDatabase db; ResourcePref *p; + Display *dpy; + + if(!(dpy = XOpenDisplay(NULL))) + die("Can't open display\n"); XrmInitialize(); resm = XResourceManagerString(dpy); @@ -47,4 +51,29 @@ resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *dst) break; } return 0; -} \ No newline at end of file +} + +#if XRESOURCES_RELOAD_PATCH +static int colors_changed = 0; + +void +xrdb_reload(int sig) +{ + config_init(); + colors_changed = 1; + signal(SIGUSR1, xrdb_reload); +} + +void +writecolors(void) +{ + dc.norm[ColBG] = getcolor(normbgcolor); + dc.norm[ColFG] = getcolor(normfgcolor); + dc.sel[ColBG] = getcolor(selbgcolor); + dc.sel[ColFG] = getcolor(selfgcolor); + dc.urg[ColBG] = getcolor(urgbgcolor); + dc.urg[ColFG] = getcolor(urgfgcolor); + + colors_changed = 0; +} +#endif // XRESOURCES_RELOAD_PATCH diff --git a/tabbed-flexipatch/patch/xresources.h b/tabbed-flexipatch/patch/xresources.h index 35c094b..c27fbd4 100644 --- a/tabbed-flexipatch/patch/xresources.h +++ b/tabbed-flexipatch/patch/xresources.h @@ -14,4 +14,9 @@ typedef struct { } ResourcePref; static void config_init(void); -static int resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *dst); \ No newline at end of file +static int resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *dst); + +#if XRESOURCES_RELOAD_PATCH +static void xrdb_reload(int sig); +static void writecolors(void); +#endif // XRESOURCES_RELOAD_PATCH diff --git a/tabbed-flexipatch/patches.def.h b/tabbed-flexipatch/patches.def.h index 63bc950..c869d61 100644 --- a/tabbed-flexipatch/patches.def.h +++ b/tabbed-flexipatch/patches.def.h @@ -31,6 +31,11 @@ */ #define BAR_HEIGHT_PATCH 1 +/* Only show the basename of the tabbed title; useful with zathura. Toggle with -b. + * https://tools.suckless.org/tabbed/patches/basenames/ + */ +#define BASENAME_PATCH 1 + /* This patch moves the tabs / bar to the bottom of the tabbed window. * https://github.com/bakkeby/patches/blob/master/tabbed/tabbed-bottomtabs-0.6-20200512-dabf6a2.diff */ @@ -42,18 +47,12 @@ */ #define CENTER_PATCH 1 -/* With this patch, tabbed interprets large position numbers as the largest known position. - * This allows Ctrl-9, for example, to always select the rightmost tab, even if there are only 4 tabs. - * https://tools.suckless.org/tabbed/patches/move-clamped/ - */ -#define CLAMPEDMOVE_PATCH 1 - /* This patch prints the position number of the client before the window title. * https://tools.suckless.org/tabbed/patches/clientnumber/ */ #define CLIENTNUMBER_PATCH 1 -/* Support dragging tabs left and right with the mouse. +/* Adds support for dragging tabs left and right using the mouse. * https://tools.suckless.org/tabbed/patches/drag/ */ #define DRAG_PATCH 1 @@ -105,4 +104,14 @@ /* This patch allows tabbed colors to be defined via Xresources. * https://tools.suckless.org/tabbed/patches/xresources/ */ -#define XRESOURCES_PATCH 1 +#define XRESOURCES_PATCH 0 + +/* Expansion of the resources patch above, allows resources to be reloaded during + * runtime by using a USR1 kill signal. + * + * Example use: + * pidof tabbed | xargs kill -s USR1 + * + * https://tools.suckless.org/tabbed/patches/xresources-with-reload-signal/ + */ +#define XRESOURCES_RELOAD_PATCH 0 diff --git a/tabbed-flexipatch/tabbed.c b/tabbed-flexipatch/tabbed.c index ccfe59e..7a1cfb2 100644 --- a/tabbed-flexipatch/tabbed.c +++ b/tabbed-flexipatch/tabbed.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -96,6 +97,9 @@ typedef struct { typedef struct { char name[256]; + #if BASENAME_PATCH + char *basename; + #endif // BASENAME_PATCH Window win; int tabx; Bool urgent; @@ -141,7 +145,6 @@ static void run(void); static void sendxembed(int c, long msg, long detail, long d1, long d2); static void setcmd(int argc, char *argv[], int); static void setup(void); -static void sigchld(int unused); static void spawn(const Arg *arg); static int textnw(const char *text, unsigned int len); static void toggle(const Arg *arg); @@ -384,6 +387,11 @@ drawbar(void) int by = 0; #endif // BOTTOM_TABS_PATCH + #if XRESOURCES_PATCH && XRESOURCES_RELOAD_PATCH + if (colors_changed) + writecolors(); + #endif // XRESOURCES_RELOAD_PATCH + #if AUTOHIDE_PATCH || HIDETABS_PATCH #if AUTOHIDE_PATCH && HIDETABS_PATCH nbh = barvisibility && nclients > 1 ? vbh : 0; @@ -459,10 +467,16 @@ drawbar(void) } else { col = clients[c]->urgent ? dc.urg : dc.norm; } - #if CLIENTNUMBER_PATCH + #if CLIENTNUMBER_PATCH && BASENAME_PATCH + snprintf(tabtitle, sizeof(tabtitle), "%d: %s", + c + 1, basenametitles ? clients[c]->basename : clients[c]->name); + drawtext(tabtitle, col); + #elif CLIENTNUMBER_PATCH snprintf(tabtitle, sizeof(tabtitle), "%d: %s", c + 1, clients[c]->name); drawtext(tabtitle, col); + #elif BASENAME_PATCH + drawtext(basenametitles ? clients[c]->basename : clients[c]->name, col); #else drawtext(clients[c]->name, col); #endif // CLIENTNUMBER_PATCH @@ -479,19 +493,22 @@ drawtext(const char *text, XftColor col[ColLast]) int i, j, x, y, h, len, olen; char buf[256]; XftDraw *d; - #if SEPERATOR_PATCH + #if SEPARATOR_PATCH XRectangle tab = { dc.x+separator, dc.y, dc.w-separator, dc.h }; XRectangle sep = { dc.x, dc.y, separator, dc.h }; - #else - XRectangle r = { dc.x, dc.y, dc.w, dc.h }; - #endif // SEPERATOR_PATCH + + if (separator) { + XSetForeground(dpy, dc.gc, col[ColFG].pixel); + XFillRectangles(dpy, dc.drawable, dc.gc, &sep, 1); + } XSetForeground(dpy, dc.gc, col[ColBG].pixel); - #if SEPERATOR_PATCH XFillRectangles(dpy, dc.drawable, dc.gc, &tab, 1); #else + XRectangle r = { dc.x, dc.y, dc.w, dc.h }; + XSetForeground(dpy, dc.gc, col[ColBG].pixel); XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1); - #endif // SEPERATOR_PATCH + #endif // SEPARATOR_PATCH if (!text) return; @@ -941,15 +958,8 @@ maprequest(const XEvent *e) void move(const Arg *arg) { - #if CLAMPEDMOVE_PATCH - int i; - i = arg->i < nclients ? arg->i : nclients - 1; - if (i >= 0) - focus(i); - #else - if (arg->i >= 0 && arg->i < nclients) - focus(arg->i); - #endif // CLAMPEDMOVE_PATCH + if (arg->i >= 0 && arg->i < nclients) + focus(arg->i); } void @@ -1149,9 +1159,16 @@ setup(void) XWMHints *wmh; XClassHint class_hint; XSizeHints *size_hint; + struct sigaction sa; - /* clean up any zombies immediately */ - sigchld(0); + /* do not transform children into zombies when they terminate */ + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_NOCLDSTOP | SA_NOCLDWAIT | SA_RESTART; + sa.sa_handler = SIG_IGN; + sigaction(SIGCHLD, &sa, NULL); + + /* clean up any zombies that might have been inherited */ + while (waitpid(-1, NULL, WNOHANG) > 0); /* init screen */ screen = DefaultScreen(dpy); @@ -1284,12 +1301,10 @@ setup(void) KeyReleaseMask | #endif // KEYRELEASE_PATCH PropertyChangeMask | StructureNotifyMask | - #if DRAG_PATCH - SubstructureRedirectMask | ButtonMotionMask - #else - SubstructureRedirectMask - #endif // DRAG_PATCH - ); + #if DRAG_PATCH + ButtonMotionMask | + #endif // DRAG_PATCH + SubstructureRedirectMask); xerrorxlib = XSetErrorHandler(xerror); class_hint.res_name = wmname; @@ -1334,23 +1349,22 @@ setup(void) focus(-1); } -void -sigchld(int unused) -{ - if (signal(SIGCHLD, sigchld) == SIG_ERR) - die("%s: cannot install SIGCHLD handler", argv0); - - while (0 < waitpid(-1, NULL, WNOHANG)); -} - void spawn(const Arg *arg) { + struct sigaction sa; + if (fork() == 0) { if(dpy) close(ConnectionNumber(dpy)); setsid(); + + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sa.sa_handler = SIG_DFL; + sigaction(SIGCHLD, &sa, NULL); + if (arg && arg->v) { execvp(((char **)arg->v)[0], (char **)arg->v); fprintf(stderr, "%s: execvp %s", argv0, @@ -1473,6 +1487,10 @@ updatetitle(int c) sizeof(clients[c]->name))) gettextprop(clients[c]->win, XA_WM_NAME, clients[c]->name, sizeof(clients[c]->name)); + #if BASENAME_PATCH + if (basenametitles) + clients[c]->basename = getbasename(clients[c]->name); + #endif // BASENAME_PATCH if (sel == c) xsettitle(win, clients[c]->name); drawbar(); @@ -1524,7 +1542,11 @@ xsettitle(Window w, const char *str) void usage(void) { - die("usage: %s [-dfksv] [-g geometry] [-n name] [-p [s+/-]pos]\n" + die("usage: %s [-" + #if BASENAME_PATCH + "b" + #endif // BASENAME_PATCH + "dfksv] [-g geometry] [-n name] [-p [s+/-]pos]\n" " [-r narg] [-o color] [-O color] [-t color] [-T color]\n" " [-u color] [-U color] command...\n", argv0); } @@ -1589,6 +1611,11 @@ main(int argc, char *argv[]) case 'u': urgbgcolor = EARGF(usage()); break; + #if BASENAME_PATCH + case 'b': + basenametitles = True; + break; + #endif // BASENAME_PATCH case 'v': die("tabbed-"VERSION", © 2009-2016 tabbed engineers, " "see LICENSE for details.\n"); @@ -1612,6 +1639,9 @@ main(int argc, char *argv[]) #if XRESOURCES_PATCH config_init(); + #if XRESOURCES_RELOAD_PATCH + signal(SIGUSR1, xrdb_reload); + #endif // XRESOURCES_RELOAD_PATCH #endif // XRESOURCES_PATCH setup(); printf("0x%lx\n", win);