From 32184c498cfef96079014dd7e14e1968baf0440f Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Tue, 1 Dec 2020 18:27:35 +0100 Subject: [PATCH 01/11] Added changelog/roadmap --- CHANGELOG.md | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..92e2575 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,34 @@ +# Upcoming +## v0.1 +* Switched build to CMake +* Completely overhauled code structure + +## v0.2 +* Configurable transparency (focused and unfocused) + based on [alpha](https://st.suckless.org/patches/alpha/) and + [alpha focus highlight](https://st.suckless.org/patches/alpha_focus_highlight/) +* Proper resizing (aka don't snap to nearest character size) + based on [anysize](https://st.suckless.org/patches/anysize/) +* Copy to clipboard on selection + based on [one clipboard](https://st.suckless.org/patches/clipboard/) +* Add a desktop entry when installing + based on [desktopentry](https://st.suckless.org/patches/desktopentry/) + +## v0.3 +* Add better/gapless rendering of lines/blocks + based on [boxdraw](https://st.suckless.org/patches/boxdraw/) +* Add support for multiple fonts + based on [font2](https://st.suckless.org/patches/font2/) +* Hide cursor when working in the terminal + based on [hidecursor](https://st.suckless.org/patches/hidecursor/) + +## v0.4 +* Add ligature support + based on [ligature support](https://st.suckless.org/patches/ligatures/) +* Support for multiple color pallets +* Paste on right click +* Scrollback support +* Center lines smaller than max height + based on [vertcenter](https://st.suckless.org/patches/vertcenter/) +* Visual bell + based on [visualbell](https://st.suckless.org/patches/visualbell/) From 1052dd6244b2c267e6222953c86940d8c6a1ddc2 Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Wed, 2 Dec 2020 12:40:21 +0100 Subject: [PATCH 02/11] Added correct formatting; started docstrings; added min size rel build --- .clang-format | 1 + Makefile | 100 +- src/CMakeLists.txt | 31 +- src/st/macros.h | 4 +- src/st/st.c | 3681 ++++++++++++++++++++++---------------------- src/st/st.h | 62 +- 6 files changed, 1970 insertions(+), 1909 deletions(-) create mode 100644 .clang-format diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..39f9642 --- /dev/null +++ b/.clang-format @@ -0,0 +1 @@ +IndentWidth: 4 diff --git a/Makefile b/Makefile index 0e49af7..5ba4d9a 100644 --- a/Makefile +++ b/Makefile @@ -1,17 +1,20 @@ -SRC_DIR := src -BUILD_DIR := build -RELEASE_DIR := $(BUILD_DIR)/release -DEBUG_DIR := $(BUILD_DIR)/debug -BINARY := stj -CORES := $(shell nproc --all) -PREFIX := /usr/local -MANPREFIX := $(PREFIX)/share/man +# =====CONFIG===== +SRC_DIR := src +BUILD_DIR := build +RELEASE_DIR := $(BUILD_DIR)/release +DEBUG_DIR := $(BUILD_DIR)/debug +MINSIZEREL_DIR := $(BUILD_DIR)/min_size_rel +BINARY := stj +CORES := $(shell nproc --all) +PREFIX := /usr/local +MANPREFIX := $(PREFIX)/share/man + all: debug .PHONY: all -# Installation & removal +# =====INSTALL & UNINSTALL===== install: release mkdir -p $(DESTDIR)$(PREFIX)/bin cp -f build/release/stj $(DESTDIR)$(PREFIX)/bin @@ -21,47 +24,16 @@ install: release chmod 644 $(DESTDIR)$(MANPREFIX)/man1/stj.1 tic -sx data/stj.info cp -f data/stj.desktop $(DESTDIR)$(PREFIX)/share/applications +.PHONY: install uninstall: rm -f $(DESTDIR)$(PREFIX)/bin/stj rm -f $(DESTDIR)$(MANPREFIX)/man1/stj.1 rm -f $(DESTDIR)$(PREFIX)/share/applications/stj.desktop +.PHONY: uninstall -# Full clean -clean: - @ [ ! -e '$(BINARY)' ] || rm '$(BINARY)' - @ rm -rf '$(BUILD_DIR)' -.PHONY: clean - - -# Release -run-release: release - @ ./'$(RELEASE_DIR)/$(BINARY)' -.PHONY: run-release - -release: $(RELEASE_DIR)/Makefile - @ make -C '$(RELEASE_DIR)' -j'$(CORES)' && \ - ln -sf '$(RELEASE_DIR)'/'$(BINARY)' ./'$(BINARY)' -.PHONY: release - -$(RELEASE_DIR)/Makefile: $(SRC_DIR)/CMakeLists.txt - @ cmake \ - -H'$(SRC_DIR)' \ - -B'$(RELEASE_DIR)' \ - -DCMAKE_BUILD_TYPE=Release \ - -DCMAKE_EXPORT_COMPILE_COMMANDS=ON - -clean-release: - @ rm -rf '$(RELEASE_DIR)' -.PHONY: clean-release - - -# Debug -run-debug: debug - @ ./'$(DEBUG_DIR)/$(BINARY)' -.PHONY: run-debug - +# =====DEBUG===== debug: $(DEBUG_DIR)/Makefile @ make -C '$(DEBUG_DIR)' -j'$(CORES)' && \ ln -sf '$(DEBUG_DIR)/$(BINARY)' ./'$(BINARY)' @@ -74,6 +46,48 @@ $(DEBUG_DIR)/Makefile: $(SRC_DIR)/CMakeLists.txt -DCMAKE_BUILD_TYPE=Debug \ -DCMAKE_EXPORT_COMPILE_COMMANDS=ON + +# =====RELEASE===== +release: $(RELEASE_DIR)/Makefile + @ make -C '$(RELEASE_DIR)' -j'$(CORES)' && \ + ln -sf '$(RELEASE_DIR)'/'$(BINARY)' ./'$(BINARY)' +.PHONY: release + +$(RELEASE_DIR)/Makefile: $(SRC_DIR)/CMakeLists.txt + @ cmake \ + -H'$(SRC_DIR)' \ + -B'$(RELEASE_DIR)' \ + -DCMAKE_BUILD_TYPE=Release \ + + +# =====MINIMUM SIZE RELEASE===== +minsizerel: $(MINSIZEREL_DIR)/Makefile + @ make -C '$(MINSIZEREL_DIR)' -j'$(CORES)' && \ + ln -sf '$(MINSIZEREL_DIR)'/'$(BINARY)' ./'$(BINARY)' +.PHONY: minsizerel + +$(MINSIZEREL_DIR)/Makefile: $(SRC_DIR)/CMakeLists.txt + @ cmake \ + -H'$(SRC_DIR)' \ + -B'$(MINSIZEREL_DIR)' \ + -DCMAKE_BUILD_TYPE=MinSizeRel \ + + +# =====CLEANING===== +clean: + @ [ ! -e '$(BINARY)' ] || rm '$(BINARY)' + @ rm -rf '$(BUILD_DIR)' +.PHONY: clean + +clean-release: + @ rm -rf '$(RELEASE_DIR)' +.PHONY: clean-release + clean-debug: @ rm -rf '$(DEBUG_DIR)' .PHONY: clean-debug + + +# =====FORMAT CODE===== +format: + @ clang-format -i --style=file src/**/*.c src/**/*.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index aa01809..3070223 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -5,6 +5,8 @@ if (NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Release) endif() +set(SYSTEM_TYPE x64) + # =====COMPILER===== set(CMAKE_C_COMPILER "clang-11") @@ -19,13 +21,21 @@ add_definitions(-DVERSION="${CMAKE_PROJECT_VERSION}" -D_XOPEN_SOURCE=600) # Debug flags # -g flag gets auto-added by CMake for the debug build -set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wall -O0 -march=native") -set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address") -set(CMAKE_LINKER_FLAGS_DEBUG "${CMAKE_LINKER_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address -pedantic") +set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -g -Weverything -O0 -fsanitize=address -fno-omit-frame-pointer") +set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address -pedantic") + +# Arch doesn't use static libraries +if(NOT EXISTS "/etc/arch-release") + set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -static-libasan") + set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} -static-libasan") +endif() # Release flags -# -O3 gets added automatically by CMake -set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Werror -march=native -pedantic-errors") +set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O3 -Werror -pedantic-errors") + +# MinSizeRel flags +# This one's just here for fun +set(CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL} -Oz -Werror -pedantic-errors") # =====EXECUTABLE===== @@ -39,8 +49,10 @@ add_executable(stj x.c "${st_SRC}" "${main_SRC}") find_package(Freetype 2 REQUIRED) target_include_directories(stj PRIVATE "${FREETYPE_INCLUDE_DIRS}") target_link_libraries(stj PRIVATE "${FREETYPE_LIBRARIES}") +target_link_libraries(stj PRIVATE Xft) +target_link_libraries(stj PRIVATE Xrender) -find_package(Fontconfig REQUIRED) +find_package(Fontconfig 2 REQUIRED) target_include_directories(stj PRIVATE "${Fontconfig_INCLUDE_DIRS}") target_link_libraries(stj PRIVATE "${Fontconfig_LIBRARIES}") @@ -48,8 +60,9 @@ find_package(X11 REQUIRED) target_include_directories(stj PRIVATE "${X11_INCLUDE_DIR}") target_link_libraries(stj PRIVATE "${X11_LIBRARIES}") +# Normally provided with clang target_link_libraries(stj PRIVATE m) -target_link_libraries(stj PRIVATE rt) +# I'm not sure if I actually need this, so keeping it here for reference +# target_link_libraries(stj PRIVATE rt) + target_link_libraries(stj PRIVATE util) -target_link_libraries(stj PRIVATE Xft) -target_link_libraries(stj PRIVATE Xrender) diff --git a/src/st/macros.h b/src/st/macros.h index eebc4d0..56ab7a7 100644 --- a/src/st/macros.h +++ b/src/st/macros.h @@ -9,9 +9,9 @@ #define DEFAULT(a, b) (a) = (a) ? (a) : (b) #define LIMIT(x, a, b) (x) = (x) < (a) ? (a) : (x) > (b) ? (b) : (x) #define ATTRCMP(a, b) \ - ((a).mode != (b).mode || (a).fg != (b).fg || (a).bg != (b).bg) + ((a).mode != (b).mode || (a).fg != (b).fg || (a).bg != (b).bg) #define TIMEDIFF(t1, t2) \ - ((t1.tv_sec - t2.tv_sec) * 1000 + (t1.tv_nsec - t2.tv_nsec) / 1E6) + ((t1.tv_sec - t2.tv_sec) * 1000 + (t1.tv_nsec - t2.tv_nsec) / 1E6) #define MODBIT(x, set, bit) ((set) ? ((x) |= (bit)) : ((x) &= ~(bit))) #define TRUECOLOR(r, g, b) (1 << 24 | (r) << 16 | (g) << 8 | (b)) diff --git a/src/st/st.c b/src/st/st.c index cbe4058..8d2a202 100644 --- a/src/st/st.c +++ b/src/st/st.c @@ -45,109 +45,109 @@ #define ISDELIM(u) (u && wcschr(worddelimiters, u)) enum term_mode { - MODE_WRAP = 1 << 0, - MODE_INSERT = 1 << 1, - MODE_ALTSCREEN = 1 << 2, - MODE_CRLF = 1 << 3, - MODE_ECHO = 1 << 4, - MODE_PRINT = 1 << 5, - MODE_UTF8 = 1 << 6, + MODE_WRAP = 1 << 0, + MODE_INSERT = 1 << 1, + MODE_ALTSCREEN = 1 << 2, + MODE_CRLF = 1 << 3, + MODE_ECHO = 1 << 4, + MODE_PRINT = 1 << 5, + MODE_UTF8 = 1 << 6, }; enum cursor_movement { CURSOR_SAVE, CURSOR_LOAD }; enum cursor_state { - CURSOR_DEFAULT = 0, - CURSOR_WRAPNEXT = 1, - CURSOR_ORIGIN = 2 + CURSOR_DEFAULT = 0, + CURSOR_WRAPNEXT = 1, + CURSOR_ORIGIN = 2 }; enum charset { - CS_GRAPHIC0, - CS_GRAPHIC1, - CS_UK, - CS_USA, - CS_MULTI, - CS_GER, - CS_FIN + CS_GRAPHIC0, + CS_GRAPHIC1, + CS_UK, + CS_USA, + CS_MULTI, + CS_GER, + CS_FIN }; enum escape_state { - ESC_START = 1, - ESC_CSI = 2, - ESC_STR = 4, /* DCS, OSC, PM, APC */ - ESC_ALTCHARSET = 8, - ESC_STR_END = 16, /* a final string was encountered */ - ESC_TEST = 32, /* Enter in test mode */ - ESC_UTF8 = 64, + ESC_START = 1, + ESC_CSI = 2, + ESC_STR = 4, /* DCS, OSC, PM, APC */ + ESC_ALTCHARSET = 8, + ESC_STR_END = 16, /* a final string was encountered */ + ESC_TEST = 32, /* Enter in test mode */ + ESC_UTF8 = 64, }; typedef struct { - Glyph attr; /* current char attributes */ - int x; - int y; - char state; + Glyph attr; /* current char attributes */ + int x; + int y; + char state; } TCursor; typedef struct { - int mode; - int type; - int snap; - /* - * Selection variables: - * nb – normalized coordinates of the beginning of the selection - * ne – normalized coordinates of the end of the selection - * ob – original coordinates of the beginning of the selection - * oe – original coordinates of the end of the selection - */ - struct { - int x, y; - } nb, ne, ob, oe; + int mode; + int type; + int snap; + /* + * Selection variables: + * nb – normalized coordinates of the beginning of the selection + * ne – normalized coordinates of the end of the selection + * ob – original coordinates of the beginning of the selection + * oe – original coordinates of the end of the selection + */ + struct { + int x, y; + } nb, ne, ob, oe; - int alt; + int alt; } Selection; /* Internal representation of the screen */ typedef struct { - int row; /* nb row */ - int col; /* nb col */ - Line *line; /* screen */ - Line *alt; /* alternate screen */ - int *dirty; /* dirtyness of lines */ - TCursor c; /* cursor */ - int ocx; /* old cursor col */ - int ocy; /* old cursor row */ - int top; /* top scroll limit */ - int bot; /* bottom scroll limit */ - int mode; /* terminal mode flags */ - int esc; /* escape state flags */ - char trantbl[4]; /* charset table translation */ - int charset; /* current charset */ - int icharset; /* selected charset for sequence */ - int *tabs; - Rune lastc; /* last printed char outside of sequence, 0 if control */ + int row; /* nb row */ + int col; /* nb col */ + Line *line; /* screen */ + Line *alt; /* alternate screen */ + int *dirty; /* dirtyness of lines */ + TCursor c; /* cursor */ + int ocx; /* old cursor col */ + int ocy; /* old cursor row */ + int top; /* top scroll limit */ + int bot; /* bottom scroll limit */ + int mode; /* terminal mode flags */ + int esc; /* escape state flags */ + char trantbl[4]; /* charset table translation */ + int charset; /* current charset */ + int icharset; /* selected charset for sequence */ + int *tabs; + Rune lastc; /* last printed char outside of sequence, 0 if control */ } Term; /* CSI Escape sequence structs */ /* ESC '[' [[ [] [;]] []] */ typedef struct { - char buf[ESC_BUF_SIZ]; /* raw string */ - size_t len; /* raw string length */ - char priv; - int arg[ESC_ARG_SIZ]; - int narg; /* nb of args */ - char mode[2]; + char buf[ESC_BUF_SIZ]; /* raw string */ + size_t len; /* raw string length */ + char priv; + int arg[ESC_ARG_SIZ]; + int narg; /* nb of args */ + char mode[2]; } CSIEscape; /* STR Escape sequence structs */ /* ESC type [[ [] [;]] ] ESC '\' */ typedef struct { - char type; /* ESC type ... */ - char *buf; /* allocated raw string */ - size_t siz; /* allocation size */ - size_t len; /* raw string length */ - char *args[STR_ARG_SIZ]; - int narg; /* nb of args */ + char type; /* ESC type ... */ + char *buf; /* allocated raw string */ + size_t siz; /* allocation size */ + size_t len; /* raw string length */ + char *args[STR_ARG_SIZ]; + int narg; /* nb of args */ } STREscape; static void execsh(char *, char **); @@ -229,109 +229,148 @@ static uchar utfmask[UTF_SIZE + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; static Rune utfmin[UTF_SIZE + 1] = {0, 0, 0x80, 0x800, 0x10000}; static Rune utfmax[UTF_SIZE + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; -ssize_t xwrite(int fd, const char *s, size_t len) { - size_t aux = len; - ssize_t result; +/** + * Same as write, but ensures that all bytes are written to the descriptor + * (write sometimes isn't able to write all bytes) + * + * @param p_file_desc file descriptor to write to; same logic as write + * @param p_str char array to write to the file descriptor + * @param p_nbytes amount of bytes to write + * @return p_nbytes if the write was successful, otherwise return negative error + * value of write + */ +ssize_t xwrite(int p_file_desc, const char *p_str, size_t p_nbytes) { + size_t aux = p_nbytes; + ssize_t result; - while (len > 0) { - result = write(fd, s, len); + while (p_nbytes > 0) { + result = write(p_file_desc, p_str, p_nbytes); - // This means an error occured in write, so it passes the error along - if (result < 0) - return result; + // This means an error occured in write, so it passes the error along + if (result < 0) + return result; - len -= result; - s += result; - } + p_nbytes -= (size_t)result; + p_str += result; + } - return aux; + return (ssize_t)aux; } -// Same as malloc, but stops entire program if malloc fails -void *safe_malloc(size_t len) { - void *ptr; +/** + * same as malloc, but kill the program if it fails + * + * @param p_len bytes to allocate + * @return pointer to allocated memory + */ +void *safe_malloc(size_t p_len) { + void *ptr; - if (!(ptr = malloc(len))) - die("malloc: %s\n", strerror(errno)); + if (!(ptr = malloc(p_len))) + die("malloc: %s\n", strerror(errno)); - return ptr; + return ptr; } -// Same as realloc, but stops entire program if malloc fails -void *safe_realloc(void *ptr, size_t len) { - if ((ptr = realloc(ptr, len)) == NULL) - die("realloc: %s\n", strerror(errno)); +/** + * same as realloc, but kill the program if it fails + * + * @param p_ptr pointer to re-allocate + * @param p_len bytes to re-allocate + * @return pointer to re-allocated memory + */ +void *safe_realloc(void *p_ptr, size_t p_len) { + if ((p_ptr = realloc(p_ptr, p_len)) == NULL) + die("realloc: %s\n", strerror(errno)); - return ptr; + return p_ptr; } -char *safe_strdup(char *s) { - if ((s = strdup(s)) == NULL) - die("strdup: %s\n", strerror(errno)); +/** + * same as strdup, but kill the program if it fails + * + * @param p_str string to copy + * @return pointer to copy of original string + */ +char *safe_strdup(char *p_str) { + if ((p_str = strdup(p_str)) == NULL) + die("strdup: %s\n", strerror(errno)); - return s; + return p_str; } -size_t utf8decode(const char *chr, Rune *u, size_t chr_len) { - size_t i, j, len, type; - Rune udecoded; +/** + * Decode a given char array into a utf8 Rune + * + * @param p_char char array to decode + * @param p_rune rune pointer to decode to + * @param p_char_len length of the char array + * @return size of the decoded rune + */ +size_t utf8decode(const char *p_char, Rune *p_rune, size_t p_char_len) { + size_t decoded_len, type; + Rune rune_decoded; + + *p_rune = UTF_INVALID; + if (!p_char_len) // chr_len is 0, so just return 0 + return 0; + + rune_decoded = utf8decodebyte(p_char[0], &decoded_len); + if (!BETWEEN(decoded_len, 1, UTF_SIZE)) + return 1; + + size_t i, j; + for (i = 1, j = 1; i < p_char_len && j < decoded_len; ++i, ++j) { + rune_decoded = (rune_decoded << 6) | utf8decodebyte(p_char[i], &type); + + if (type != 0) + return j; + } + + if (j < decoded_len) + return 0; + + *p_rune = rune_decoded; + utf8validate(p_rune, decoded_len); + + return decoded_len; +} + +Rune utf8decodebyte(char p_char, size_t *i) { + + for (*i = 0; *i < LEN(utfmask); ++(*i)) { + if (((uchar)p_char & utfmask[*i]) == utfbyte[*i]) + return (uchar)p_char & ~utfmask[*i]; + } - *u = UTF_INVALID; - if (!chr_len) // chr_len is 0, so just return 0 return 0; - - udecoded = utf8decodebyte(chr[0], &len); - if (!BETWEEN(len, 1, UTF_SIZE)) - return 1; - - for (i = 1, j = 1; i < chr_len && j < len; ++i, ++j) { - udecoded = (udecoded << 6) | utf8decodebyte(chr[i], &type); - if (type != 0) - return j; - } - - if (j < len) - return 0; - - *u = udecoded; - utf8validate(u, len); - - return len; -} - -Rune utf8decodebyte(char c, size_t *i) { - for (*i = 0; *i < LEN(utfmask); ++(*i)) - if (((uchar)c & utfmask[*i]) == utfbyte[*i]) - return (uchar)c & ~utfmask[*i]; - - return 0; } size_t utf8encode(Rune u, char *c) { - size_t len, i; + size_t len, i; - len = utf8validate(&u, 0); - if (len > UTF_SIZE) - return 0; + len = utf8validate(&u, 0); + if (len > UTF_SIZE) + return 0; - for (i = len - 1; i != 0; --i) { - c[i] = utf8encodebyte(u, 0); - u >>= 6; - } - c[0] = utf8encodebyte(u, len); + for (i = len - 1; i != 0; --i) { + c[i] = utf8encodebyte(u, 0); + u >>= 6; + } + c[0] = utf8encodebyte(u, len); - return len; + return len; } char utf8encodebyte(Rune u, size_t i) { return utfbyte[i] | (u & ~utfmask[i]); } size_t utf8validate(Rune *u, size_t i) { - if (!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF)) - *u = UTF_INVALID; - for (i = 1; *u > utfmax[i]; ++i) - ; + if (!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF)) + *u = UTF_INVALID; + for (i = 1; *u > utfmax[i]; ++i) + ; - return i; + return i; } static const char base64_digits[] = { @@ -351,1488 +390,1492 @@ static const char base64_digits[] = { 0, 0, 0, 0, 0, 0, 0, 0}; char base64dec_getc(const char **src) { - while (**src && !isprint(**src)) - (*src)++; - return **src ? *((*src)++) : '='; /* emulate padding if string ends */ + while (**src && !isprint(**src)) + (*src)++; + return **src ? *((*src)++) : '='; /* emulate padding if string ends */ } char *base64dec(const char *src) { - size_t in_len = strlen(src); - char *result, *dst; + size_t in_len = strlen(src); + char *result, *dst; - if (in_len % 4) - in_len += 4 - (in_len % 4); - result = dst = safe_malloc(in_len / 4 * 3 + 1); - while (*src) { - int a = base64_digits[(unsigned char)base64dec_getc(&src)]; - int b = base64_digits[(unsigned char)base64dec_getc(&src)]; - int c = base64_digits[(unsigned char)base64dec_getc(&src)]; - int d = base64_digits[(unsigned char)base64dec_getc(&src)]; + if (in_len % 4) + in_len += 4 - (in_len % 4); + result = dst = safe_malloc(in_len / 4 * 3 + 1); + while (*src) { + int a = base64_digits[(unsigned char)base64dec_getc(&src)]; + int b = base64_digits[(unsigned char)base64dec_getc(&src)]; + int c = base64_digits[(unsigned char)base64dec_getc(&src)]; + int d = base64_digits[(unsigned char)base64dec_getc(&src)]; - /* invalid input. 'a' can be -1, e.g. if src is "\n" (c-str) */ - if (a == -1 || b == -1) - break; + /* invalid input. 'a' can be -1, e.g. if src is "\n" (c-str) */ + if (a == -1 || b == -1) + break; - *dst++ = (a << 2) | ((b & 0x30) >> 4); - if (c == -1) - break; - *dst++ = ((b & 0x0f) << 4) | ((c & 0x3c) >> 2); - if (d == -1) - break; - *dst++ = ((c & 0x03) << 6) | d; - } - *dst = '\0'; - return result; + *dst++ = (a << 2) | ((b & 0x30) >> 4); + if (c == -1) + break; + *dst++ = ((b & 0x0f) << 4) | ((c & 0x3c) >> 2); + if (d == -1) + break; + *dst++ = ((c & 0x03) << 6) | d; + } + *dst = '\0'; + return result; } void selinit(void) { - sel.mode = SEL_IDLE; - sel.snap = 0; - sel.ob.x = -1; + sel.mode = SEL_IDLE; + sel.snap = 0; + sel.ob.x = -1; } int tlinelen(int y) { - int i = term.col; + int i = term.col; + + if (term.line[y][i - 1].mode & ATTR_WRAP) + return i; + + while (i > 0 && term.line[y][i - 1].u == ' ') + --i; - if (term.line[y][i - 1].mode & ATTR_WRAP) return i; - - while (i > 0 && term.line[y][i - 1].u == ' ') - --i; - - return i; } void selstart(int col, int row, int snap) { - selclear(); - sel.mode = SEL_EMPTY; - sel.type = SEL_REGULAR; - sel.alt = IS_SET(MODE_ALTSCREEN); - sel.snap = snap; - sel.oe.x = sel.ob.x = col; - sel.oe.y = sel.ob.y = row; - selnormalize(); + selclear(); + sel.mode = SEL_EMPTY; + sel.type = SEL_REGULAR; + sel.alt = IS_SET(MODE_ALTSCREEN); + sel.snap = snap; + sel.oe.x = sel.ob.x = col; + sel.oe.y = sel.ob.y = row; + selnormalize(); - if (sel.snap != 0) - sel.mode = SEL_READY; - tsetdirt(sel.nb.y, sel.ne.y); + if (sel.snap != 0) + sel.mode = SEL_READY; + tsetdirt(sel.nb.y, sel.ne.y); } void selextend(int col, int row, int type, int done) { - int oldey, oldex, oldsby, oldsey, oldtype; + int oldey, oldex, oldsby, oldsey, oldtype; - if (sel.mode == SEL_IDLE) - return; - if (done && sel.mode == SEL_EMPTY) { - selclear(); - return; - } + if (sel.mode == SEL_IDLE) + return; + if (done && sel.mode == SEL_EMPTY) { + selclear(); + return; + } - oldey = sel.oe.y; - oldex = sel.oe.x; - oldsby = sel.nb.y; - oldsey = sel.ne.y; - oldtype = sel.type; + oldey = sel.oe.y; + oldex = sel.oe.x; + oldsby = sel.nb.y; + oldsey = sel.ne.y; + oldtype = sel.type; - sel.oe.x = col; - sel.oe.y = row; - selnormalize(); - sel.type = type; + sel.oe.x = col; + sel.oe.y = row; + selnormalize(); + sel.type = type; - if (oldey != sel.oe.y || oldex != sel.oe.x || oldtype != sel.type || - sel.mode == SEL_EMPTY) - tsetdirt(MIN(sel.nb.y, oldsby), MAX(sel.ne.y, oldsey)); + if (oldey != sel.oe.y || oldex != sel.oe.x || oldtype != sel.type || + sel.mode == SEL_EMPTY) + tsetdirt(MIN(sel.nb.y, oldsby), MAX(sel.ne.y, oldsey)); - sel.mode = done ? SEL_IDLE : SEL_READY; + sel.mode = done ? SEL_IDLE : SEL_READY; } void selnormalize(void) { - int i; + int i; - if (sel.type == SEL_REGULAR && sel.ob.y != sel.oe.y) { - sel.nb.x = sel.ob.y < sel.oe.y ? sel.ob.x : sel.oe.x; - sel.ne.x = sel.ob.y < sel.oe.y ? sel.oe.x : sel.ob.x; - } else { - sel.nb.x = MIN(sel.ob.x, sel.oe.x); - sel.ne.x = MAX(sel.ob.x, sel.oe.x); - } - sel.nb.y = MIN(sel.ob.y, sel.oe.y); - sel.ne.y = MAX(sel.ob.y, sel.oe.y); + if (sel.type == SEL_REGULAR && sel.ob.y != sel.oe.y) { + sel.nb.x = sel.ob.y < sel.oe.y ? sel.ob.x : sel.oe.x; + sel.ne.x = sel.ob.y < sel.oe.y ? sel.oe.x : sel.ob.x; + } else { + sel.nb.x = MIN(sel.ob.x, sel.oe.x); + sel.ne.x = MAX(sel.ob.x, sel.oe.x); + } + sel.nb.y = MIN(sel.ob.y, sel.oe.y); + sel.ne.y = MAX(sel.ob.y, sel.oe.y); - selsnap(&sel.nb.x, &sel.nb.y, -1); - selsnap(&sel.ne.x, &sel.ne.y, +1); + selsnap(&sel.nb.x, &sel.nb.y, -1); + selsnap(&sel.ne.x, &sel.ne.y, +1); - /* expand selection over line breaks */ - if (sel.type == SEL_RECTANGULAR) - return; - i = tlinelen(sel.nb.y); - if (i < sel.nb.x) - sel.nb.x = i; - if (tlinelen(sel.ne.y) <= sel.ne.x) - sel.ne.x = term.col - 1; + /* expand selection over line breaks */ + if (sel.type == SEL_RECTANGULAR) + return; + i = tlinelen(sel.nb.y); + if (i < sel.nb.x) + sel.nb.x = i; + if (tlinelen(sel.ne.y) <= sel.ne.x) + sel.ne.x = term.col - 1; } int selected(int x, int y) { - if (sel.mode == SEL_EMPTY || sel.ob.x == -1 || - sel.alt != IS_SET(MODE_ALTSCREEN)) - return 0; + if (sel.mode == SEL_EMPTY || sel.ob.x == -1 || + sel.alt != IS_SET(MODE_ALTSCREEN)) + return 0; - if (sel.type == SEL_RECTANGULAR) - return BETWEEN(y, sel.nb.y, sel.ne.y) && BETWEEN(x, sel.nb.x, sel.ne.x); + if (sel.type == SEL_RECTANGULAR) + return BETWEEN(y, sel.nb.y, sel.ne.y) && BETWEEN(x, sel.nb.x, sel.ne.x); - return BETWEEN(y, sel.nb.y, sel.ne.y) && (y != sel.nb.y || x >= sel.nb.x) && - (y != sel.ne.y || x <= sel.ne.x); + return BETWEEN(y, sel.nb.y, sel.ne.y) && (y != sel.nb.y || x >= sel.nb.x) && + (y != sel.ne.y || x <= sel.ne.x); } void selsnap(int *x, int *y, int direction) { - int newx, newy, xt, yt; - int delim, prevdelim; - Glyph *gp, *prevgp; + int newx, newy, xt, yt; + int delim, prevdelim; + Glyph *gp, *prevgp; - switch (sel.snap) { - case SNAP_WORD: - /* - * Snap around if the word wraps around at the end or - * beginning of a line. - */ - prevgp = &term.line[*y][*x]; - prevdelim = ISDELIM(prevgp->u); - for (;;) { - newx = *x + direction; - newy = *y; - if (!BETWEEN(newx, 0, term.col - 1)) { - newy += direction; - newx = (newx + term.col) % term.col; - if (!BETWEEN(newy, 0, term.row - 1)) - break; + switch (sel.snap) { + case SNAP_WORD: + /* + * Snap around if the word wraps around at the end or + * beginning of a line. + */ + prevgp = &term.line[*y][*x]; + prevdelim = ISDELIM(prevgp->u); + for (;;) { + newx = *x + direction; + newy = *y; + if (!BETWEEN(newx, 0, term.col - 1)) { + newy += direction; + newx = (newx + term.col) % term.col; + if (!BETWEEN(newy, 0, term.row - 1)) + break; - if (direction > 0) - yt = *y, xt = *x; - else - yt = newy, xt = newx; - if (!(term.line[yt][xt].mode & ATTR_WRAP)) - break; - } + if (direction > 0) + yt = *y, xt = *x; + else + yt = newy, xt = newx; + if (!(term.line[yt][xt].mode & ATTR_WRAP)) + break; + } - if (newx >= tlinelen(newy)) - break; + if (newx >= tlinelen(newy)) + break; - gp = &term.line[newy][newx]; - delim = ISDELIM(gp->u); - if (!(gp->mode & ATTR_WDUMMY) && - (delim != prevdelim || (delim && gp->u != prevgp->u))) - break; + gp = &term.line[newy][newx]; + delim = ISDELIM(gp->u); + if (!(gp->mode & ATTR_WDUMMY) && + (delim != prevdelim || (delim && gp->u != prevgp->u))) + break; - *x = newx; - *y = newy; - prevgp = gp; - prevdelim = delim; - } - break; - case SNAP_LINE: - /* - * Snap around if the the previous line or the current one - * has set ATTR_WRAP at its end. Then the whole next or - * previous line will be selected. - */ - *x = (direction < 0) ? 0 : term.col - 1; - if (direction < 0) { - for (; *y > 0; *y += direction) { - if (!(term.line[*y - 1][term.col - 1].mode & ATTR_WRAP)) { - break; + *x = newx; + *y = newy; + prevgp = gp; + prevdelim = delim; } - } - } else if (direction > 0) { - for (; *y < term.row - 1; *y += direction) { - if (!(term.line[*y][term.col - 1].mode & ATTR_WRAP)) { - break; + break; + case SNAP_LINE: + /* + * Snap around if the the previous line or the current one + * has set ATTR_WRAP at its end. Then the whole next or + * previous line will be selected. + */ + *x = (direction < 0) ? 0 : term.col - 1; + if (direction < 0) { + for (; *y > 0; *y += direction) { + if (!(term.line[*y - 1][term.col - 1].mode & ATTR_WRAP)) { + break; + } + } + } else if (direction > 0) { + for (; *y < term.row - 1; *y += direction) { + if (!(term.line[*y][term.col - 1].mode & ATTR_WRAP)) { + break; + } + } } - } + break; } - break; - } } char *getsel(void) { - char *str, *ptr; - int y, bufsize, lastx, linelen; - Glyph *gp, *last; + char *str, *ptr; + int y, bufsize, lastx, linelen; + Glyph *gp, *last; - if (sel.ob.x == -1) - return NULL; + if (sel.ob.x == -1) + return NULL; - bufsize = (term.col + 1) * (sel.ne.y - sel.nb.y + 1) * UTF_SIZE; - ptr = str = safe_malloc(bufsize); + bufsize = (term.col + 1) * (sel.ne.y - sel.nb.y + 1) * UTF_SIZE; + ptr = str = safe_malloc(bufsize); - /* append every set & selected glyph to the selection */ - for (y = sel.nb.y; y <= sel.ne.y; y++) { - if ((linelen = tlinelen(y)) == 0) { - *ptr++ = '\n'; - continue; + /* append every set & selected glyph to the selection */ + for (y = sel.nb.y; y <= sel.ne.y; y++) { + if ((linelen = tlinelen(y)) == 0) { + *ptr++ = '\n'; + continue; + } + + if (sel.type == SEL_RECTANGULAR) { + gp = &term.line[y][sel.nb.x]; + lastx = sel.ne.x; + } else { + gp = &term.line[y][sel.nb.y == y ? sel.nb.x : 0]; + lastx = (sel.ne.y == y) ? sel.ne.x : term.col - 1; + } + last = &term.line[y][MIN(lastx, linelen - 1)]; + while (last >= gp && last->u == ' ') + --last; + + for (; gp <= last; ++gp) { + if (gp->mode & ATTR_WDUMMY) + continue; + + ptr += utf8encode(gp->u, ptr); + } + + /* + * Copy and pasting of line endings is inconsistent + * in the inconsistent terminal and GUI world. + * The best solution seems like to produce '\n' when + * something is copied from st and convert '\n' to + * '\r', when something to be pasted is received by + * st. + * FIXME: Fix the computer world. + */ + if ((y < sel.ne.y || lastx >= linelen) && + (!(last->mode & ATTR_WRAP) || sel.type == SEL_RECTANGULAR)) + *ptr++ = '\n'; } - - if (sel.type == SEL_RECTANGULAR) { - gp = &term.line[y][sel.nb.x]; - lastx = sel.ne.x; - } else { - gp = &term.line[y][sel.nb.y == y ? sel.nb.x : 0]; - lastx = (sel.ne.y == y) ? sel.ne.x : term.col - 1; - } - last = &term.line[y][MIN(lastx, linelen - 1)]; - while (last >= gp && last->u == ' ') - --last; - - for (; gp <= last; ++gp) { - if (gp->mode & ATTR_WDUMMY) - continue; - - ptr += utf8encode(gp->u, ptr); - } - - /* - * Copy and pasting of line endings is inconsistent - * in the inconsistent terminal and GUI world. - * The best solution seems like to produce '\n' when - * something is copied from st and convert '\n' to - * '\r', when something to be pasted is received by - * st. - * FIXME: Fix the computer world. - */ - if ((y < sel.ne.y || lastx >= linelen) && - (!(last->mode & ATTR_WRAP) || sel.type == SEL_RECTANGULAR)) - *ptr++ = '\n'; - } - *ptr = 0; - return str; + *ptr = 0; + return str; } void selclear(void) { - if (sel.ob.x == -1) - return; - sel.mode = SEL_IDLE; - sel.ob.x = -1; - tsetdirt(sel.nb.y, sel.ne.y); + if (sel.ob.x == -1) + return; + sel.mode = SEL_IDLE; + sel.ob.x = -1; + tsetdirt(sel.nb.y, sel.ne.y); } void die(const char *errstr, ...) { - va_list ap; + va_list ap; - va_start(ap, errstr); - vfprintf(stderr, errstr, ap); - va_end(ap); - exit(1); + va_start(ap, errstr); + vfprintf(stderr, errstr, ap); + va_end(ap); + exit(1); } void execsh(char *cmd, char **args) { - char *sh, *prog, *arg; - const struct passwd *pw; + char *sh, *prog, *arg; + const struct passwd *pw; - errno = 0; - if ((pw = getpwuid(getuid())) == NULL) { - if (errno) - die("getpwuid: %s\n", strerror(errno)); - else - die("who are you?\n"); - } + errno = 0; + if ((pw = getpwuid(getuid())) == NULL) { + if (errno) + die("getpwuid: %s\n", strerror(errno)); + else + die("who are you?\n"); + } - if ((sh = getenv("SHELL")) == NULL) - sh = (pw->pw_shell[0]) ? pw->pw_shell : cmd; + if ((sh = getenv("SHELL")) == NULL) + sh = (pw->pw_shell[0]) ? pw->pw_shell : cmd; - if (args) { - prog = args[0]; - arg = NULL; - } else if (scroll) { - prog = scroll; - arg = utmp ? utmp : sh; - } else if (utmp) { - prog = utmp; - arg = NULL; - } else { - prog = sh; - arg = NULL; - } - DEFAULT(args, ((char *[]){prog, arg, NULL})); + if (args) { + prog = args[0]; + arg = NULL; + } else if (scroll) { + prog = scroll; + arg = utmp ? utmp : sh; + } else if (utmp) { + prog = utmp; + arg = NULL; + } else { + prog = sh; + arg = NULL; + } + DEFAULT(args, ((char *[]){prog, arg, NULL})); - unsetenv("COLUMNS"); - unsetenv("LINES"); - unsetenv("TERMCAP"); - setenv("LOGNAME", pw->pw_name, 1); - setenv("USER", pw->pw_name, 1); - setenv("SHELL", sh, 1); - setenv("HOME", pw->pw_dir, 1); - setenv("TERM", termname, 1); + unsetenv("COLUMNS"); + unsetenv("LINES"); + unsetenv("TERMCAP"); + setenv("LOGNAME", pw->pw_name, 1); + setenv("USER", pw->pw_name, 1); + setenv("SHELL", sh, 1); + setenv("HOME", pw->pw_dir, 1); + setenv("TERM", termname, 1); - signal(SIGCHLD, SIG_DFL); - signal(SIGHUP, SIG_DFL); - signal(SIGINT, SIG_DFL); - signal(SIGQUIT, SIG_DFL); - signal(SIGTERM, SIG_DFL); - signal(SIGALRM, SIG_DFL); + signal(SIGCHLD, SIG_DFL); + signal(SIGHUP, SIG_DFL); + signal(SIGINT, SIG_DFL); + signal(SIGQUIT, SIG_DFL); + signal(SIGTERM, SIG_DFL); + signal(SIGALRM, SIG_DFL); - execvp(prog, args); - _exit(1); + execvp(prog, args); + _exit(1); } void sigchld(int a) { - int stat; - pid_t p; + int stat; + pid_t p; - if ((p = waitpid(pid, &stat, WNOHANG)) < 0) - die("waiting for pid %hd failed: %s\n", pid, strerror(errno)); + if ((p = waitpid(pid, &stat, WNOHANG)) < 0) + die("waiting for pid %hd failed: %s\n", pid, strerror(errno)); - if (pid != p) - return; + if (pid != p) + return; - if (WIFEXITED(stat) && WEXITSTATUS(stat)) - die("child exited with status %d\n", WEXITSTATUS(stat)); - else if (WIFSIGNALED(stat)) - die("child terminated due to signal %d\n", WTERMSIG(stat)); - _exit(0); + if (WIFEXITED(stat) && WEXITSTATUS(stat)) + die("child exited with status %d\n", WEXITSTATUS(stat)); + else if (WIFSIGNALED(stat)) + die("child terminated due to signal %d\n", WTERMSIG(stat)); + _exit(0); } void stty(char **args) { - char cmd[_POSIX_ARG_MAX], **p, *q, *s; - size_t n, siz; + char cmd[_POSIX_ARG_MAX], **p, *q, *s; + size_t n, siz; - if ((n = strlen(stty_args)) > sizeof(cmd) - 1) - die("incorrect stty parameters\n"); - memcpy(cmd, stty_args, n); - q = cmd + n; - siz = sizeof(cmd) - n; - for (p = args; p && (s = *p); ++p) { - if ((n = strlen(s)) > siz - 1) - die("stty parameter length too long\n"); - *q++ = ' '; - memcpy(q, s, n); - q += n; - siz -= n + 1; - } - *q = '\0'; - if (system(cmd) != 0) - perror("Couldn't call stty"); + if ((n = strlen(stty_args)) > sizeof(cmd) - 1) + die("incorrect stty parameters\n"); + memcpy(cmd, stty_args, n); + q = cmd + n; + siz = sizeof(cmd) - n; + for (p = args; p && (s = *p); ++p) { + if ((n = strlen(s)) > siz - 1) + die("stty parameter length too long\n"); + *q++ = ' '; + memcpy(q, s, n); + q += n; + siz -= n + 1; + } + *q = '\0'; + if (system(cmd) != 0) + perror("Couldn't call stty"); } int ttynew(char *line, char *cmd, char *out, char **args) { - int m, s; + int m, s; - if (out) { - term.mode |= MODE_PRINT; - iofd = (!strcmp(out, "-")) ? 1 : open(out, O_WRONLY | O_CREAT, 0666); - if (iofd < 0) { - fprintf(stderr, "Error opening %s:%s\n", out, strerror(errno)); + if (out) { + term.mode |= MODE_PRINT; + iofd = (!strcmp(out, "-")) ? 1 : open(out, O_WRONLY | O_CREAT, 0666); + if (iofd < 0) { + fprintf(stderr, "Error opening %s:%s\n", out, strerror(errno)); + } } - } - if (line) { - if ((cmdfd = open(line, O_RDWR)) < 0) - die("open line '%s' failed: %s\n", line, strerror(errno)); - dup2(cmdfd, 0); - stty(args); + if (line) { + if ((cmdfd = open(line, O_RDWR)) < 0) + die("open line '%s' failed: %s\n", line, strerror(errno)); + dup2(cmdfd, 0); + stty(args); + return cmdfd; + } + + /* seems to work fine on linux, openbsd and freebsd */ + if (openpty(&m, &s, NULL, NULL, NULL) < 0) + die("openpty failed: %s\n", strerror(errno)); + + switch (pid = fork()) { + case -1: + die("fork failed: %s\n", strerror(errno)); + break; + case 0: + close(iofd); + setsid(); /* create a new process group */ + dup2(s, 0); + dup2(s, 1); + dup2(s, 2); + if (ioctl(s, TIOCSCTTY, NULL) < 0) + die("ioctl TIOCSCTTY failed: %s\n", strerror(errno)); + close(s); + close(m); +#ifdef __OpenBSD__ + if (pledge("stdio getpw proc exec", NULL) == -1) + die("pledge\n"); +#endif + execsh(cmd, args); + break; + default: +#ifdef __OpenBSD__ + if (pledge("stdio rpath tty proc", NULL) == -1) + die("pledge\n"); +#endif + close(s); + cmdfd = m; + signal(SIGCHLD, sigchld); + break; + } return cmdfd; - } - - /* seems to work fine on linux, openbsd and freebsd */ - if (openpty(&m, &s, NULL, NULL, NULL) < 0) - die("openpty failed: %s\n", strerror(errno)); - - switch (pid = fork()) { - case -1: - die("fork failed: %s\n", strerror(errno)); - break; - case 0: - close(iofd); - setsid(); /* create a new process group */ - dup2(s, 0); - dup2(s, 1); - dup2(s, 2); - if (ioctl(s, TIOCSCTTY, NULL) < 0) - die("ioctl TIOCSCTTY failed: %s\n", strerror(errno)); - close(s); - close(m); -#ifdef __OpenBSD__ - if (pledge("stdio getpw proc exec", NULL) == -1) - die("pledge\n"); -#endif - execsh(cmd, args); - break; - default: -#ifdef __OpenBSD__ - if (pledge("stdio rpath tty proc", NULL) == -1) - die("pledge\n"); -#endif - close(s); - cmdfd = m; - signal(SIGCHLD, sigchld); - break; - } - return cmdfd; } size_t ttyread(void) { - static char buf[BUFSIZ]; - static int buflen = 0; - int ret, written; + static char buf[BUFSIZ]; + static int buflen = 0; + int ret, written; - /* append read bytes to unprocessed bytes */ - ret = read(cmdfd, buf + buflen, LEN(buf) - buflen); + /* append read bytes to unprocessed bytes */ + ret = read(cmdfd, buf + buflen, LEN(buf) - buflen); - switch (ret) { - case 0: - exit(0); - case -1: - die("couldn't read from shell: %s\n", strerror(errno)); - default: - buflen += ret; - written = twrite(buf, buflen, 0); - buflen -= written; - /* keep any incomplete UTF-8 byte sequence for the next call */ - if (buflen > 0) - memmove(buf, buf + written, buflen); - return ret; - } + switch (ret) { + case 0: + exit(0); + case -1: + die("couldn't read from shell: %s\n", strerror(errno)); + default: + buflen += ret; + written = twrite(buf, buflen, 0); + buflen -= written; + /* keep any incomplete UTF-8 byte sequence for the next call */ + if (buflen > 0) + memmove(buf, buf + written, buflen); + return ret; + } } void ttywrite(const char *s, size_t n, int may_echo) { - const char *next; + const char *next; - if (may_echo && IS_SET(MODE_ECHO)) - twrite(s, n, 1); + if (may_echo && IS_SET(MODE_ECHO)) + twrite(s, n, 1); - if (!IS_SET(MODE_CRLF)) { - ttywriteraw(s, n); - return; - } - - /* This is similar to how the kernel handles ONLCR for ttys */ - while (n > 0) { - if (*s == '\r') { - next = s + 1; - ttywriteraw("\r\n", 2); - } else { - next = memchr(s, '\r', n); - DEFAULT(next, s + n); - ttywriteraw(s, next - s); + if (!IS_SET(MODE_CRLF)) { + ttywriteraw(s, n); + return; + } + + /* This is similar to how the kernel handles ONLCR for ttys */ + while (n > 0) { + if (*s == '\r') { + next = s + 1; + ttywriteraw("\r\n", 2); + } else { + next = memchr(s, '\r', n); + DEFAULT(next, s + n); + ttywriteraw(s, next - s); + } + n -= next - s; + s = next; } - n -= next - s; - s = next; - } } void ttywriteraw(const char *s, size_t n) { - fd_set wfd, rfd; - ssize_t r; - size_t lim = 256; + fd_set wfd, rfd; + ssize_t r; + size_t lim = 256; - /* - * Remember that we are using a pty, which might be a modem line. - * Writing too much will clog the line. That's why we are doing this - * dance. - * FIXME: Migrate the world to Plan 9. - */ - while (n > 0) { - FD_ZERO(&wfd); - FD_ZERO(&rfd); - FD_SET(cmdfd, &wfd); - FD_SET(cmdfd, &rfd); + /* + * Remember that we are using a pty, which might be a modem line. + * Writing too much will clog the line. That's why we are doing this + * dance. + * FIXME: Migrate the world to Plan 9. + */ + while (n > 0) { + FD_ZERO(&wfd); + FD_ZERO(&rfd); + FD_SET(cmdfd, &wfd); + FD_SET(cmdfd, &rfd); - /* Check if we can write. */ - if (pselect(cmdfd + 1, &rfd, &wfd, NULL, NULL, NULL) < 0) { - if (errno == EINTR) - continue; - die("select failed: %s\n", strerror(errno)); + /* Check if we can write. */ + if (pselect(cmdfd + 1, &rfd, &wfd, NULL, NULL, NULL) < 0) { + if (errno == EINTR) + continue; + die("select failed: %s\n", strerror(errno)); + } + if (FD_ISSET(cmdfd, &wfd)) { + /* + * Only write the bytes written by ttywrite() or the + * default of 256. This seems to be a reasonable value + * for a serial line. Bigger values might clog the I/O. + */ + if ((r = write(cmdfd, s, (n < lim) ? n : lim)) < 0) + goto write_error; + if (r < n) { + /* + * We weren't able to write out everything. + * This means the buffer is getting full + * again. Empty it. + */ + if (n < lim) + lim = ttyread(); + n -= r; + s += r; + } else { + /* All bytes have been written. */ + break; + } + } + if (FD_ISSET(cmdfd, &rfd)) + lim = ttyread(); } - if (FD_ISSET(cmdfd, &wfd)) { - /* - * Only write the bytes written by ttywrite() or the - * default of 256. This seems to be a reasonable value - * for a serial line. Bigger values might clog the I/O. - */ - if ((r = write(cmdfd, s, (n < lim) ? n : lim)) < 0) - goto write_error; - if (r < n) { - /* - * We weren't able to write out everything. - * This means the buffer is getting full - * again. Empty it. - */ - if (n < lim) - lim = ttyread(); - n -= r; - s += r; - } else { - /* All bytes have been written. */ - break; - } - } - if (FD_ISSET(cmdfd, &rfd)) - lim = ttyread(); - } - return; + return; write_error: - die("write error on tty: %s\n", strerror(errno)); + die("write error on tty: %s\n", strerror(errno)); } void ttyresize(int tw, int th) { - struct winsize w; + struct winsize w; - w.ws_row = term.row; - w.ws_col = term.col; - w.ws_xpixel = tw; - w.ws_ypixel = th; - if (ioctl(cmdfd, TIOCSWINSZ, &w) < 0) - fprintf(stderr, "Couldn't set window size: %s\n", strerror(errno)); + w.ws_row = term.row; + w.ws_col = term.col; + w.ws_xpixel = tw; + w.ws_ypixel = th; + if (ioctl(cmdfd, TIOCSWINSZ, &w) < 0) + fprintf(stderr, "Couldn't set window size: %s\n", strerror(errno)); } void ttyhangup() { - /* Send SIGHUP to shell */ - kill(pid, SIGHUP); + /* Send SIGHUP to shell */ + kill(pid, SIGHUP); } int tattrset(int attr) { - int i, j; + int i, j; - for (i = 0; i < term.row - 1; i++) { - for (j = 0; j < term.col - 1; j++) { - if (term.line[i][j].mode & attr) - return 1; + for (i = 0; i < term.row - 1; i++) { + for (j = 0; j < term.col - 1; j++) { + if (term.line[i][j].mode & attr) + return 1; + } } - } - return 0; + return 0; } void tsetdirt(int top, int bot) { - int i; + int i; - LIMIT(top, 0, term.row - 1); - LIMIT(bot, 0, term.row - 1); + LIMIT(top, 0, term.row - 1); + LIMIT(bot, 0, term.row - 1); - for (i = top; i <= bot; i++) - term.dirty[i] = 1; + for (i = top; i <= bot; i++) + term.dirty[i] = 1; } void tsetdirtattr(int attr) { - int i, j; + int i, j; - for (i = 0; i < term.row - 1; i++) { - for (j = 0; j < term.col - 1; j++) { - if (term.line[i][j].mode & attr) { - tsetdirt(i, i); - break; - } + for (i = 0; i < term.row - 1; i++) { + for (j = 0; j < term.col - 1; j++) { + if (term.line[i][j].mode & attr) { + tsetdirt(i, i); + break; + } + } } - } } void tfulldirt(void) { tsetdirt(0, term.row - 1); } void tcursor(int mode) { - static TCursor c[2]; - int alt = IS_SET(MODE_ALTSCREEN); + static TCursor c[2]; + int alt = IS_SET(MODE_ALTSCREEN); - if (mode == CURSOR_SAVE) { - c[alt] = term.c; - } else if (mode == CURSOR_LOAD) { - term.c = c[alt]; - tmoveto(c[alt].x, c[alt].y); - } + if (mode == CURSOR_SAVE) { + c[alt] = term.c; + } else if (mode == CURSOR_LOAD) { + term.c = c[alt]; + tmoveto(c[alt].x, c[alt].y); + } } void treset(void) { - uint i; + uint i; - term.c = (TCursor){{.mode = ATTR_NULL, .fg = defaultfg, .bg = defaultbg}, - .x = 0, - .y = 0, - .state = CURSOR_DEFAULT}; + term.c = (TCursor){{.mode = ATTR_NULL, .fg = defaultfg, .bg = defaultbg}, + .x = 0, + .y = 0, + .state = CURSOR_DEFAULT}; - memset(term.tabs, 0, term.col * sizeof(*term.tabs)); - for (i = tabspaces; i < term.col; i += tabspaces) - term.tabs[i] = 1; - term.top = 0; - term.bot = term.row - 1; - term.mode = MODE_WRAP | MODE_UTF8; - memset(term.trantbl, CS_USA, sizeof(term.trantbl)); - term.charset = 0; + memset(term.tabs, 0, term.col * sizeof(*term.tabs)); + for (i = tabspaces; i < term.col; i += tabspaces) + term.tabs[i] = 1; + term.top = 0; + term.bot = term.row - 1; + term.mode = MODE_WRAP | MODE_UTF8; + memset(term.trantbl, CS_USA, sizeof(term.trantbl)); + term.charset = 0; - for (i = 0; i < 2; i++) { - tmoveto(0, 0); - tcursor(CURSOR_SAVE); - tclearregion(0, 0, term.col - 1, term.row - 1); - tswapscreen(); - } + for (i = 0; i < 2; i++) { + tmoveto(0, 0); + tcursor(CURSOR_SAVE); + tclearregion(0, 0, term.col - 1, term.row - 1); + tswapscreen(); + } } void tnew(int col, int row) { - term = (Term){.c = {.attr = {.fg = defaultfg, .bg = defaultbg}}}; - tresize(col, row); - treset(); + term = (Term){.c = {.attr = {.fg = defaultfg, .bg = defaultbg}}}; + tresize(col, row); + treset(); } void tswapscreen(void) { - Line *tmp = term.line; + Line *tmp = term.line; - term.line = term.alt; - term.alt = tmp; - term.mode ^= MODE_ALTSCREEN; - tfulldirt(); + term.line = term.alt; + term.alt = tmp; + term.mode ^= MODE_ALTSCREEN; + tfulldirt(); } void tscrolldown(int orig, int n) { - int i; - Line temp; + int i; + Line temp; - LIMIT(n, 0, term.bot - orig + 1); + LIMIT(n, 0, term.bot - orig + 1); - tsetdirt(orig, term.bot - n); - tclearregion(0, term.bot - n + 1, term.col - 1, term.bot); + tsetdirt(orig, term.bot - n); + tclearregion(0, term.bot - n + 1, term.col - 1, term.bot); - for (i = term.bot; i >= orig + n; i--) { - temp = term.line[i]; - term.line[i] = term.line[i - n]; - term.line[i - n] = temp; - } + for (i = term.bot; i >= orig + n; i--) { + temp = term.line[i]; + term.line[i] = term.line[i - n]; + term.line[i - n] = temp; + } - selscroll(orig, n); + selscroll(orig, n); } void tscrollup(int orig, int n) { - int i; - Line temp; + int i; + Line temp; - LIMIT(n, 0, term.bot - orig + 1); + LIMIT(n, 0, term.bot - orig + 1); - tclearregion(0, orig, term.col - 1, orig + n - 1); - tsetdirt(orig + n, term.bot); + tclearregion(0, orig, term.col - 1, orig + n - 1); + tsetdirt(orig + n, term.bot); - for (i = orig; i <= term.bot - n; i++) { - temp = term.line[i]; - term.line[i] = term.line[i + n]; - term.line[i + n] = temp; - } + for (i = orig; i <= term.bot - n; i++) { + temp = term.line[i]; + term.line[i] = term.line[i + n]; + term.line[i + n] = temp; + } - selscroll(orig, -n); + selscroll(orig, -n); } void selscroll(int orig, int n) { - if (sel.ob.x == -1) - return; + if (sel.ob.x == -1) + return; - if (BETWEEN(sel.nb.y, orig, term.bot) != BETWEEN(sel.ne.y, orig, term.bot)) { - selclear(); - } else if (BETWEEN(sel.nb.y, orig, term.bot)) { - sel.ob.y += n; - sel.oe.y += n; - if (sel.ob.y < term.top || sel.ob.y > term.bot || sel.oe.y < term.top || - sel.oe.y > term.bot) { - selclear(); - } else { - selnormalize(); + if (BETWEEN(sel.nb.y, orig, term.bot) != + BETWEEN(sel.ne.y, orig, term.bot)) { + selclear(); + } else if (BETWEEN(sel.nb.y, orig, term.bot)) { + sel.ob.y += n; + sel.oe.y += n; + if (sel.ob.y < term.top || sel.ob.y > term.bot || sel.oe.y < term.top || + sel.oe.y > term.bot) { + selclear(); + } else { + selnormalize(); + } } - } } void tnewline(int first_col) { - int y = term.c.y; + int y = term.c.y; - if (y == term.bot) { - tscrollup(term.top, 1); - } else { - y++; - } - tmoveto(first_col ? 0 : term.c.x, y); + if (y == term.bot) { + tscrollup(term.top, 1); + } else { + y++; + } + tmoveto(first_col ? 0 : term.c.x, y); } void csiparse(void) { - char *p = csiescseq.buf, *np; - long int v; + char *p = csiescseq.buf, *np; + long int v; - csiescseq.narg = 0; - if (*p == '?') { - csiescseq.priv = 1; - p++; - } + csiescseq.narg = 0; + if (*p == '?') { + csiescseq.priv = 1; + p++; + } - csiescseq.buf[csiescseq.len] = '\0'; - while (p < csiescseq.buf + csiescseq.len) { - np = NULL; - v = strtol(p, &np, 10); - if (np == p) - v = 0; - if (v == LONG_MAX || v == LONG_MIN) - v = -1; - csiescseq.arg[csiescseq.narg++] = v; - p = np; - if (*p != ';' || csiescseq.narg == ESC_ARG_SIZ) - break; - p++; - } - csiescseq.mode[0] = *p++; - csiescseq.mode[1] = (p < csiescseq.buf + csiescseq.len) ? *p : '\0'; + csiescseq.buf[csiescseq.len] = '\0'; + while (p < csiescseq.buf + csiescseq.len) { + np = NULL; + v = strtol(p, &np, 10); + if (np == p) + v = 0; + if (v == LONG_MAX || v == LONG_MIN) + v = -1; + csiescseq.arg[csiescseq.narg++] = v; + p = np; + if (*p != ';' || csiescseq.narg == ESC_ARG_SIZ) + break; + p++; + } + csiescseq.mode[0] = *p++; + csiescseq.mode[1] = (p < csiescseq.buf + csiescseq.len) ? *p : '\0'; } /* for absolute user moves, when decom is set */ void tmoveato(int x, int y) { - tmoveto(x, y + ((term.c.state & CURSOR_ORIGIN) ? term.top : 0)); + tmoveto(x, y + ((term.c.state & CURSOR_ORIGIN) ? term.top : 0)); } void tmoveto(int x, int y) { - int miny, maxy; + int miny, maxy; - if (term.c.state & CURSOR_ORIGIN) { - miny = term.top; - maxy = term.bot; - } else { - miny = 0; - maxy = term.row - 1; - } - term.c.state &= ~CURSOR_WRAPNEXT; - term.c.x = LIMIT(x, 0, term.col - 1); - term.c.y = LIMIT(y, miny, maxy); + if (term.c.state & CURSOR_ORIGIN) { + miny = term.top; + maxy = term.bot; + } else { + miny = 0; + maxy = term.row - 1; + } + term.c.state &= ~CURSOR_WRAPNEXT; + term.c.x = LIMIT(x, 0, term.col - 1); + term.c.y = LIMIT(y, miny, maxy); } void tsetchar(Rune u, Glyph *attr, int x, int y) { - static char *vt100_0[62] = { - /* 0x41 - 0x7e */ - "↑", "↓", "→", "←", "█", "▚", "☃", /* A - G */ - 0, 0, 0, 0, 0, 0, 0, 0, /* H - O */ - 0, 0, 0, 0, 0, 0, 0, 0, /* P - W */ - 0, 0, 0, 0, 0, 0, 0, " ", /* X - _ */ - "◆", "▒", "␉", "␌", "␍", "␊", "°", "±", /* ` - g */ - "␤", "␋", "┘", "┐", "┌", "└", "┼", "⎺", /* h - o */ - "⎻", "─", "⎼", "⎽", "├", "┤", "┴", "┬", /* p - w */ - "│", "≤", "≥", "π", "≠", "£", "·", /* x - ~ */ - }; + static char *vt100_0[62] = { + /* 0x41 - 0x7e */ + "↑", "↓", "→", "←", "█", "▚", "☃", /* A - G */ + 0, 0, 0, 0, 0, 0, 0, 0, /* H - O */ + 0, 0, 0, 0, 0, 0, 0, 0, /* P - W */ + 0, 0, 0, 0, 0, 0, 0, " ", /* X - _ */ + "◆", "▒", "␉", "␌", "␍", "␊", "°", "±", /* ` - g */ + "␤", "␋", "┘", "┐", "┌", "└", "┼", "⎺", /* h - o */ + "⎻", "─", "⎼", "⎽", "├", "┤", "┴", "┬", /* p - w */ + "│", "≤", "≥", "π", "≠", "£", "·", /* x - ~ */ + }; - /* - * The table is proudly stolen from rxvt. - */ - if (term.trantbl[term.charset] == CS_GRAPHIC0 && BETWEEN(u, 0x41, 0x7e) && - vt100_0[u - 0x41]) - utf8decode(vt100_0[u - 0x41], &u, UTF_SIZE); + /* + * The table is proudly stolen from rxvt. + */ + if (term.trantbl[term.charset] == CS_GRAPHIC0 && BETWEEN(u, 0x41, 0x7e) && + vt100_0[u - 0x41]) + utf8decode(vt100_0[u - 0x41], &u, UTF_SIZE); - if (term.line[y][x].mode & ATTR_WIDE) { - if (x + 1 < term.col) { - term.line[y][x + 1].u = ' '; - term.line[y][x + 1].mode &= ~ATTR_WDUMMY; + if (term.line[y][x].mode & ATTR_WIDE) { + if (x + 1 < term.col) { + term.line[y][x + 1].u = ' '; + term.line[y][x + 1].mode &= ~ATTR_WDUMMY; + } + } else if (term.line[y][x].mode & ATTR_WDUMMY) { + term.line[y][x - 1].u = ' '; + term.line[y][x - 1].mode &= ~ATTR_WIDE; } - } else if (term.line[y][x].mode & ATTR_WDUMMY) { - term.line[y][x - 1].u = ' '; - term.line[y][x - 1].mode &= ~ATTR_WIDE; - } - term.dirty[y] = 1; - term.line[y][x] = *attr; - term.line[y][x].u = u; + term.dirty[y] = 1; + term.line[y][x] = *attr; + term.line[y][x].u = u; } void tclearregion(int x1, int y1, int x2, int y2) { - int x, y, temp; - Glyph *gp; + int x, y, temp; + Glyph *gp; - if (x1 > x2) - temp = x1, x1 = x2, x2 = temp; - if (y1 > y2) - temp = y1, y1 = y2, y2 = temp; + if (x1 > x2) + temp = x1, x1 = x2, x2 = temp; + if (y1 > y2) + temp = y1, y1 = y2, y2 = temp; - LIMIT(x1, 0, term.col - 1); - LIMIT(x2, 0, term.col - 1); - LIMIT(y1, 0, term.row - 1); - LIMIT(y2, 0, term.row - 1); + LIMIT(x1, 0, term.col - 1); + LIMIT(x2, 0, term.col - 1); + LIMIT(y1, 0, term.row - 1); + LIMIT(y2, 0, term.row - 1); - for (y = y1; y <= y2; y++) { - term.dirty[y] = 1; - for (x = x1; x <= x2; x++) { - gp = &term.line[y][x]; - if (selected(x, y)) - selclear(); - gp->fg = term.c.attr.fg; - gp->bg = term.c.attr.bg; - gp->mode = 0; - gp->u = ' '; + for (y = y1; y <= y2; y++) { + term.dirty[y] = 1; + for (x = x1; x <= x2; x++) { + gp = &term.line[y][x]; + if (selected(x, y)) + selclear(); + gp->fg = term.c.attr.fg; + gp->bg = term.c.attr.bg; + gp->mode = 0; + gp->u = ' '; + } } - } } void tdeletechar(int n) { - int dst, src, size; - Glyph *line; + int dst, src, size; + Glyph *line; - LIMIT(n, 0, term.col - term.c.x); + LIMIT(n, 0, term.col - term.c.x); - dst = term.c.x; - src = term.c.x + n; - size = term.col - src; - line = term.line[term.c.y]; + dst = term.c.x; + src = term.c.x + n; + size = term.col - src; + line = term.line[term.c.y]; - memmove(&line[dst], &line[src], size * sizeof(Glyph)); - tclearregion(term.col - n, term.c.y, term.col - 1, term.c.y); + memmove(&line[dst], &line[src], size * sizeof(Glyph)); + tclearregion(term.col - n, term.c.y, term.col - 1, term.c.y); } void tinsertblank(int n) { - int dst, src, size; - Glyph *line; + int dst, src, size; + Glyph *line; - LIMIT(n, 0, term.col - term.c.x); + LIMIT(n, 0, term.col - term.c.x); - dst = term.c.x + n; - src = term.c.x; - size = term.col - dst; - line = term.line[term.c.y]; + dst = term.c.x + n; + src = term.c.x; + size = term.col - dst; + line = term.line[term.c.y]; - memmove(&line[dst], &line[src], size * sizeof(Glyph)); - tclearregion(src, term.c.y, dst - 1, term.c.y); + memmove(&line[dst], &line[src], size * sizeof(Glyph)); + tclearregion(src, term.c.y, dst - 1, term.c.y); } void tinsertblankline(int n) { - if (BETWEEN(term.c.y, term.top, term.bot)) - tscrolldown(term.c.y, n); + if (BETWEEN(term.c.y, term.top, term.bot)) + tscrolldown(term.c.y, n); } void tdeleteline(int n) { - if (BETWEEN(term.c.y, term.top, term.bot)) - tscrollup(term.c.y, n); + if (BETWEEN(term.c.y, term.top, term.bot)) + tscrollup(term.c.y, n); } int32_t tdefcolor(int *attr, int *npar, int l) { - int32_t idx = -1; - uint r, g, b; + int32_t idx = -1; + uint r, g, b; - switch (attr[*npar + 1]) { - case 2: /* direct color in RGB space */ - if (*npar + 4 >= l) { - fprintf(stderr, "erresc(38): Incorrect number of parameters (%d)\n", - *npar); - break; + switch (attr[*npar + 1]) { + case 2: /* direct color in RGB space */ + if (*npar + 4 >= l) { + fprintf(stderr, "erresc(38): Incorrect number of parameters (%d)\n", + *npar); + break; + } + r = attr[*npar + 2]; + g = attr[*npar + 3]; + b = attr[*npar + 4]; + *npar += 4; + if (!BETWEEN(r, 0, 255) || !BETWEEN(g, 0, 255) || !BETWEEN(b, 0, 255)) + fprintf(stderr, "erresc: bad rgb color (%u,%u,%u)\n", r, g, b); + else + idx = TRUECOLOR(r, g, b); + break; + case 5: /* indexed color */ + if (*npar + 2 >= l) { + fprintf(stderr, "erresc(38): Incorrect number of parameters (%d)\n", + *npar); + break; + } + *npar += 2; + if (!BETWEEN(attr[*npar], 0, 255)) + fprintf(stderr, "erresc: bad fgcolor %d\n", attr[*npar]); + else + idx = attr[*npar]; + break; + case 0: /* implemented defined (only foreground) */ + case 1: /* transparent */ + case 3: /* direct color in CMY space */ + case 4: /* direct color in CMYK space */ + default: + fprintf(stderr, "erresc(38): gfx attr %d unknown\n", attr[*npar]); + break; } - r = attr[*npar + 2]; - g = attr[*npar + 3]; - b = attr[*npar + 4]; - *npar += 4; - if (!BETWEEN(r, 0, 255) || !BETWEEN(g, 0, 255) || !BETWEEN(b, 0, 255)) - fprintf(stderr, "erresc: bad rgb color (%u,%u,%u)\n", r, g, b); - else - idx = TRUECOLOR(r, g, b); - break; - case 5: /* indexed color */ - if (*npar + 2 >= l) { - fprintf(stderr, "erresc(38): Incorrect number of parameters (%d)\n", - *npar); - break; - } - *npar += 2; - if (!BETWEEN(attr[*npar], 0, 255)) - fprintf(stderr, "erresc: bad fgcolor %d\n", attr[*npar]); - else - idx = attr[*npar]; - break; - case 0: /* implemented defined (only foreground) */ - case 1: /* transparent */ - case 3: /* direct color in CMY space */ - case 4: /* direct color in CMYK space */ - default: - fprintf(stderr, "erresc(38): gfx attr %d unknown\n", attr[*npar]); - break; - } - return idx; + return idx; } void tsetattr(int *attr, int l) { - int i; - int32_t idx; + int i; + int32_t idx; - for (i = 0; i < l; i++) { - switch (attr[i]) { - case 0: - term.c.attr.mode &= - ~(ATTR_BOLD | ATTR_FAINT | ATTR_ITALIC | ATTR_UNDERLINE | ATTR_BLINK | - ATTR_REVERSE | ATTR_INVISIBLE | ATTR_STRUCK); - term.c.attr.fg = defaultfg; - term.c.attr.bg = defaultbg; - break; - case 1: - term.c.attr.mode |= ATTR_BOLD; - break; - case 2: - term.c.attr.mode |= ATTR_FAINT; - break; - case 3: - term.c.attr.mode |= ATTR_ITALIC; - break; - case 4: - term.c.attr.mode |= ATTR_UNDERLINE; - break; - case 5: /* slow blink */ - /* FALLTHROUGH */ - case 6: /* rapid blink */ - term.c.attr.mode |= ATTR_BLINK; - break; - case 7: - term.c.attr.mode |= ATTR_REVERSE; - break; - case 8: - term.c.attr.mode |= ATTR_INVISIBLE; - break; - case 9: - term.c.attr.mode |= ATTR_STRUCK; - break; - case 22: - term.c.attr.mode &= ~(ATTR_BOLD | ATTR_FAINT); - break; - case 23: - term.c.attr.mode &= ~ATTR_ITALIC; - break; - case 24: - term.c.attr.mode &= ~ATTR_UNDERLINE; - break; - case 25: - term.c.attr.mode &= ~ATTR_BLINK; - break; - case 27: - term.c.attr.mode &= ~ATTR_REVERSE; - break; - case 28: - term.c.attr.mode &= ~ATTR_INVISIBLE; - break; - case 29: - term.c.attr.mode &= ~ATTR_STRUCK; - break; - case 38: - if ((idx = tdefcolor(attr, &i, l)) >= 0) - term.c.attr.fg = idx; - break; - case 39: - term.c.attr.fg = defaultfg; - break; - case 48: - if ((idx = tdefcolor(attr, &i, l)) >= 0) - term.c.attr.bg = idx; - break; - case 49: - term.c.attr.bg = defaultbg; - break; - default: - if (BETWEEN(attr[i], 30, 37)) { - term.c.attr.fg = attr[i] - 30; - } else if (BETWEEN(attr[i], 40, 47)) { - term.c.attr.bg = attr[i] - 40; - } else if (BETWEEN(attr[i], 90, 97)) { - term.c.attr.fg = attr[i] - 90 + 8; - } else if (BETWEEN(attr[i], 100, 107)) { - term.c.attr.bg = attr[i] - 100 + 8; - } else { - fprintf(stderr, "erresc(default): gfx attr %d unknown\n", attr[i]); - csidump(); - } - break; + for (i = 0; i < l; i++) { + switch (attr[i]) { + case 0: + term.c.attr.mode &= + ~(ATTR_BOLD | ATTR_FAINT | ATTR_ITALIC | ATTR_UNDERLINE | + ATTR_BLINK | ATTR_REVERSE | ATTR_INVISIBLE | ATTR_STRUCK); + term.c.attr.fg = defaultfg; + term.c.attr.bg = defaultbg; + break; + case 1: + term.c.attr.mode |= ATTR_BOLD; + break; + case 2: + term.c.attr.mode |= ATTR_FAINT; + break; + case 3: + term.c.attr.mode |= ATTR_ITALIC; + break; + case 4: + term.c.attr.mode |= ATTR_UNDERLINE; + break; + case 5: /* slow blink */ + /* FALLTHROUGH */ + case 6: /* rapid blink */ + term.c.attr.mode |= ATTR_BLINK; + break; + case 7: + term.c.attr.mode |= ATTR_REVERSE; + break; + case 8: + term.c.attr.mode |= ATTR_INVISIBLE; + break; + case 9: + term.c.attr.mode |= ATTR_STRUCK; + break; + case 22: + term.c.attr.mode &= ~(ATTR_BOLD | ATTR_FAINT); + break; + case 23: + term.c.attr.mode &= ~ATTR_ITALIC; + break; + case 24: + term.c.attr.mode &= ~ATTR_UNDERLINE; + break; + case 25: + term.c.attr.mode &= ~ATTR_BLINK; + break; + case 27: + term.c.attr.mode &= ~ATTR_REVERSE; + break; + case 28: + term.c.attr.mode &= ~ATTR_INVISIBLE; + break; + case 29: + term.c.attr.mode &= ~ATTR_STRUCK; + break; + case 38: + if ((idx = tdefcolor(attr, &i, l)) >= 0) + term.c.attr.fg = idx; + break; + case 39: + term.c.attr.fg = defaultfg; + break; + case 48: + if ((idx = tdefcolor(attr, &i, l)) >= 0) + term.c.attr.bg = idx; + break; + case 49: + term.c.attr.bg = defaultbg; + break; + default: + if (BETWEEN(attr[i], 30, 37)) { + term.c.attr.fg = attr[i] - 30; + } else if (BETWEEN(attr[i], 40, 47)) { + term.c.attr.bg = attr[i] - 40; + } else if (BETWEEN(attr[i], 90, 97)) { + term.c.attr.fg = attr[i] - 90 + 8; + } else if (BETWEEN(attr[i], 100, 107)) { + term.c.attr.bg = attr[i] - 100 + 8; + } else { + fprintf(stderr, "erresc(default): gfx attr %d unknown\n", + attr[i]); + csidump(); + } + break; + } } - } } void tsetscroll(int t, int b) { - int temp; + int temp; - LIMIT(t, 0, term.row - 1); - LIMIT(b, 0, term.row - 1); - if (t > b) { - temp = t; - t = b; - b = temp; - } - term.top = t; - term.bot = b; + LIMIT(t, 0, term.row - 1); + LIMIT(b, 0, term.row - 1); + if (t > b) { + temp = t; + t = b; + b = temp; + } + term.top = t; + term.bot = b; } void tsetmode(int priv, int set, int *args, int narg) { - int alt, *lim; + int alt, *lim; - for (lim = args + narg; args < lim; ++args) { - if (priv) { - switch (*args) { - case 1: /* DECCKM -- Cursor key */ - xsetmode(set, MODE_APPCURSOR); - break; - case 5: /* DECSCNM -- Reverse video */ - xsetmode(set, MODE_REVERSE); - break; - case 6: /* DECOM -- Origin */ - MODBIT(term.c.state, set, CURSOR_ORIGIN); - tmoveato(0, 0); - break; - case 7: /* DECAWM -- Auto wrap */ - MODBIT(term.mode, set, MODE_WRAP); - break; - case 0: /* Error (IGNORED) */ - case 2: /* DECANM -- ANSI/VT52 (IGNORED) */ - case 3: /* DECCOLM -- Column (IGNORED) */ - case 4: /* DECSCLM -- Scroll (IGNORED) */ - case 8: /* DECARM -- Auto repeat (IGNORED) */ - case 18: /* DECPFF -- Printer feed (IGNORED) */ - case 19: /* DECPEX -- Printer extent (IGNORED) */ - case 42: /* DECNRCM -- National characters (IGNORED) */ - case 12: /* att610 -- Start blinking cursor (IGNORED) */ - break; - case 25: /* DECTCEM -- Text Cursor Enable Mode */ - xsetmode(!set, MODE_HIDE); - break; - case 9: /* X10 mouse compatibility mode */ - xsetpointermotion(0); - xsetmode(0, MODE_MOUSE); - xsetmode(set, MODE_MOUSEX10); - break; - case 1000: /* 1000: report button press */ - xsetpointermotion(0); - xsetmode(0, MODE_MOUSE); - xsetmode(set, MODE_MOUSEBTN); - break; - case 1002: /* 1002: report motion on button press */ - xsetpointermotion(0); - xsetmode(0, MODE_MOUSE); - xsetmode(set, MODE_MOUSEMOTION); - break; - case 1003: /* 1003: enable all mouse motions */ - xsetpointermotion(set); - xsetmode(0, MODE_MOUSE); - xsetmode(set, MODE_MOUSEMANY); - break; - case 1004: /* 1004: send focus events to tty */ - xsetmode(set, MODE_FOCUS); - break; - case 1006: /* 1006: extended reporting mode */ - xsetmode(set, MODE_MOUSESGR); - break; - case 1034: - xsetmode(set, MODE_8BIT); - break; - case 1049: /* swap screen & set/restore cursor as xterm */ - if (!allowaltscreen) - break; - tcursor((set) ? CURSOR_SAVE : CURSOR_LOAD); - /* FALLTHROUGH */ - case 47: /* swap screen */ - case 1047: - if (!allowaltscreen) - break; - alt = IS_SET(MODE_ALTSCREEN); - if (alt) { - tclearregion(0, 0, term.col - 1, term.row - 1); + for (lim = args + narg; args < lim; ++args) { + if (priv) { + switch (*args) { + case 1: /* DECCKM -- Cursor key */ + xsetmode(set, MODE_APPCURSOR); + break; + case 5: /* DECSCNM -- Reverse video */ + xsetmode(set, MODE_REVERSE); + break; + case 6: /* DECOM -- Origin */ + MODBIT(term.c.state, set, CURSOR_ORIGIN); + tmoveato(0, 0); + break; + case 7: /* DECAWM -- Auto wrap */ + MODBIT(term.mode, set, MODE_WRAP); + break; + case 0: /* Error (IGNORED) */ + case 2: /* DECANM -- ANSI/VT52 (IGNORED) */ + case 3: /* DECCOLM -- Column (IGNORED) */ + case 4: /* DECSCLM -- Scroll (IGNORED) */ + case 8: /* DECARM -- Auto repeat (IGNORED) */ + case 18: /* DECPFF -- Printer feed (IGNORED) */ + case 19: /* DECPEX -- Printer extent (IGNORED) */ + case 42: /* DECNRCM -- National characters (IGNORED) */ + case 12: /* att610 -- Start blinking cursor (IGNORED) */ + break; + case 25: /* DECTCEM -- Text Cursor Enable Mode */ + xsetmode(!set, MODE_HIDE); + break; + case 9: /* X10 mouse compatibility mode */ + xsetpointermotion(0); + xsetmode(0, MODE_MOUSE); + xsetmode(set, MODE_MOUSEX10); + break; + case 1000: /* 1000: report button press */ + xsetpointermotion(0); + xsetmode(0, MODE_MOUSE); + xsetmode(set, MODE_MOUSEBTN); + break; + case 1002: /* 1002: report motion on button press */ + xsetpointermotion(0); + xsetmode(0, MODE_MOUSE); + xsetmode(set, MODE_MOUSEMOTION); + break; + case 1003: /* 1003: enable all mouse motions */ + xsetpointermotion(set); + xsetmode(0, MODE_MOUSE); + xsetmode(set, MODE_MOUSEMANY); + break; + case 1004: /* 1004: send focus events to tty */ + xsetmode(set, MODE_FOCUS); + break; + case 1006: /* 1006: extended reporting mode */ + xsetmode(set, MODE_MOUSESGR); + break; + case 1034: + xsetmode(set, MODE_8BIT); + break; + case 1049: /* swap screen & set/restore cursor as xterm */ + if (!allowaltscreen) + break; + tcursor((set) ? CURSOR_SAVE : CURSOR_LOAD); + /* FALLTHROUGH */ + case 47: /* swap screen */ + case 1047: + if (!allowaltscreen) + break; + alt = IS_SET(MODE_ALTSCREEN); + if (alt) { + tclearregion(0, 0, term.col - 1, term.row - 1); + } + if (set ^ alt) /* set is always 1 or 0 */ + tswapscreen(); + if (*args != 1049) + break; + /* FALLTHROUGH */ + case 1048: + tcursor((set) ? CURSOR_SAVE : CURSOR_LOAD); + break; + case 2004: /* 2004: bracketed paste mode */ + xsetmode(set, MODE_BRCKTPASTE); + break; + /* Not implemented mouse modes. See comments there. */ + case 1001: /* mouse highlight mode; can hang the + terminal by design when implemented. */ + case 1005: /* UTF-8 mouse mode; will confuse + applications not supporting UTF-8 + and luit. */ + case 1015: /* urxvt mangled mouse mode; incompatible + and can be mistaken for other control + codes. */ + break; + default: + fprintf(stderr, "erresc: unknown private set/reset mode %d\n", + *args); + break; + } + } else { + switch (*args) { + case 0: /* Error (IGNORED) */ + break; + case 2: + xsetmode(set, MODE_KBDLOCK); + break; + case 4: /* IRM -- Insertion-replacement */ + MODBIT(term.mode, set, MODE_INSERT); + break; + case 12: /* SRM -- Send/Receive */ + MODBIT(term.mode, !set, MODE_ECHO); + break; + case 20: /* LNM -- Linefeed/new line */ + MODBIT(term.mode, set, MODE_CRLF); + break; + default: + fprintf(stderr, "erresc: unknown set/reset mode %d\n", *args); + break; + } } - if (set ^ alt) /* set is always 1 or 0 */ - tswapscreen(); - if (*args != 1049) - break; - /* FALLTHROUGH */ - case 1048: - tcursor((set) ? CURSOR_SAVE : CURSOR_LOAD); - break; - case 2004: /* 2004: bracketed paste mode */ - xsetmode(set, MODE_BRCKTPASTE); - break; - /* Not implemented mouse modes. See comments there. */ - case 1001: /* mouse highlight mode; can hang the - terminal by design when implemented. */ - case 1005: /* UTF-8 mouse mode; will confuse - applications not supporting UTF-8 - and luit. */ - case 1015: /* urxvt mangled mouse mode; incompatible - and can be mistaken for other control - codes. */ - break; - default: - fprintf(stderr, "erresc: unknown private set/reset mode %d\n", *args); - break; - } - } else { - switch (*args) { - case 0: /* Error (IGNORED) */ - break; - case 2: - xsetmode(set, MODE_KBDLOCK); - break; - case 4: /* IRM -- Insertion-replacement */ - MODBIT(term.mode, set, MODE_INSERT); - break; - case 12: /* SRM -- Send/Receive */ - MODBIT(term.mode, !set, MODE_ECHO); - break; - case 20: /* LNM -- Linefeed/new line */ - MODBIT(term.mode, set, MODE_CRLF); - break; - default: - fprintf(stderr, "erresc: unknown set/reset mode %d\n", *args); - break; - } } - } } void csihandle(void) { - char buf[40]; - int len; + char buf[40]; + int len; - switch (csiescseq.mode[0]) { - default: - unknown: - fprintf(stderr, "erresc: unknown csi "); - csidump(); - /* die(""); */ - break; - case '@': /* ICH -- Insert blank char */ - DEFAULT(csiescseq.arg[0], 1); - tinsertblank(csiescseq.arg[0]); - break; - case 'A': /* CUU -- Cursor Up */ - DEFAULT(csiescseq.arg[0], 1); - tmoveto(term.c.x, term.c.y - csiescseq.arg[0]); - break; - case 'B': /* CUD -- Cursor Down */ - case 'e': /* VPR --Cursor Down */ - DEFAULT(csiescseq.arg[0], 1); - tmoveto(term.c.x, term.c.y + csiescseq.arg[0]); - break; - case 'i': /* MC -- Media Copy */ - switch (csiescseq.arg[0]) { - case 0: - tdump(); - break; - case 1: - tdumpline(term.c.y); - break; - case 2: - tdumpsel(); - break; - case 4: - term.mode &= ~MODE_PRINT; - break; - case 5: - term.mode |= MODE_PRINT; - break; - } - break; - case 'c': /* DA -- Device Attributes */ - if (csiescseq.arg[0] == 0) - ttywrite(vtiden, strlen(vtiden), 0); - break; - case 'b': /* REP -- if last char is printable print it more times */ - DEFAULT(csiescseq.arg[0], 1); - if (term.lastc) - while (csiescseq.arg[0]-- > 0) - tputc(term.lastc); - break; - case 'C': /* CUF -- Cursor Forward */ - case 'a': /* HPR -- Cursor Forward */ - DEFAULT(csiescseq.arg[0], 1); - tmoveto(term.c.x + csiescseq.arg[0], term.c.y); - break; - case 'D': /* CUB -- Cursor Backward */ - DEFAULT(csiescseq.arg[0], 1); - tmoveto(term.c.x - csiescseq.arg[0], term.c.y); - break; - case 'E': /* CNL -- Cursor Down and first col */ - DEFAULT(csiescseq.arg[0], 1); - tmoveto(0, term.c.y + csiescseq.arg[0]); - break; - case 'F': /* CPL -- Cursor Up and first col */ - DEFAULT(csiescseq.arg[0], 1); - tmoveto(0, term.c.y - csiescseq.arg[0]); - break; - case 'g': /* TBC -- Tabulation clear */ - switch (csiescseq.arg[0]) { - case 0: /* clear current tab stop */ - term.tabs[term.c.x] = 0; - break; - case 3: /* clear all the tabs */ - memset(term.tabs, 0, term.col * sizeof(*term.tabs)); - break; + switch (csiescseq.mode[0]) { default: - goto unknown; + unknown: + fprintf(stderr, "erresc: unknown csi "); + csidump(); + /* die(""); */ + break; + case '@': /* ICH -- Insert blank char */ + DEFAULT(csiescseq.arg[0], 1); + tinsertblank(csiescseq.arg[0]); + break; + case 'A': /* CUU -- Cursor Up */ + DEFAULT(csiescseq.arg[0], 1); + tmoveto(term.c.x, term.c.y - csiescseq.arg[0]); + break; + case 'B': /* CUD -- Cursor Down */ + case 'e': /* VPR --Cursor Down */ + DEFAULT(csiescseq.arg[0], 1); + tmoveto(term.c.x, term.c.y + csiescseq.arg[0]); + break; + case 'i': /* MC -- Media Copy */ + switch (csiescseq.arg[0]) { + case 0: + tdump(); + break; + case 1: + tdumpline(term.c.y); + break; + case 2: + tdumpsel(); + break; + case 4: + term.mode &= ~MODE_PRINT; + break; + case 5: + term.mode |= MODE_PRINT; + break; + } + break; + case 'c': /* DA -- Device Attributes */ + if (csiescseq.arg[0] == 0) + ttywrite(vtiden, strlen(vtiden), 0); + break; + case 'b': /* REP -- if last char is printable print it more times */ + DEFAULT(csiescseq.arg[0], 1); + if (term.lastc) + while (csiescseq.arg[0]-- > 0) + tputc(term.lastc); + break; + case 'C': /* CUF -- Cursor Forward */ + case 'a': /* HPR -- Cursor Forward */ + DEFAULT(csiescseq.arg[0], 1); + tmoveto(term.c.x + csiescseq.arg[0], term.c.y); + break; + case 'D': /* CUB -- Cursor Backward */ + DEFAULT(csiescseq.arg[0], 1); + tmoveto(term.c.x - csiescseq.arg[0], term.c.y); + break; + case 'E': /* CNL -- Cursor Down and first col */ + DEFAULT(csiescseq.arg[0], 1); + tmoveto(0, term.c.y + csiescseq.arg[0]); + break; + case 'F': /* CPL -- Cursor Up and first col */ + DEFAULT(csiescseq.arg[0], 1); + tmoveto(0, term.c.y - csiescseq.arg[0]); + break; + case 'g': /* TBC -- Tabulation clear */ + switch (csiescseq.arg[0]) { + case 0: /* clear current tab stop */ + term.tabs[term.c.x] = 0; + break; + case 3: /* clear all the tabs */ + memset(term.tabs, 0, term.col * sizeof(*term.tabs)); + break; + default: + goto unknown; + } + break; + case 'G': /* CHA -- Move to */ + case '`': /* HPA */ + DEFAULT(csiescseq.arg[0], 1); + tmoveto(csiescseq.arg[0] - 1, term.c.y); + break; + case 'H': /* CUP -- Move to */ + case 'f': /* HVP */ + DEFAULT(csiescseq.arg[0], 1); + DEFAULT(csiescseq.arg[1], 1); + tmoveato(csiescseq.arg[1] - 1, csiescseq.arg[0] - 1); + break; + case 'I': /* CHT -- Cursor Forward Tabulation tab stops */ + DEFAULT(csiescseq.arg[0], 1); + tputtab(csiescseq.arg[0]); + break; + case 'J': /* ED -- Clear screen */ + switch (csiescseq.arg[0]) { + case 0: /* below */ + tclearregion(term.c.x, term.c.y, term.col - 1, term.c.y); + if (term.c.y < term.row - 1) { + tclearregion(0, term.c.y + 1, term.col - 1, term.row - 1); + } + break; + case 1: /* above */ + if (term.c.y > 1) + tclearregion(0, 0, term.col - 1, term.c.y - 1); + tclearregion(0, term.c.y, term.c.x, term.c.y); + break; + case 2: /* all */ + tclearregion(0, 0, term.col - 1, term.row - 1); + break; + default: + goto unknown; + } + break; + case 'K': /* EL -- Clear line */ + switch (csiescseq.arg[0]) { + case 0: /* right */ + tclearregion(term.c.x, term.c.y, term.col - 1, term.c.y); + break; + case 1: /* left */ + tclearregion(0, term.c.y, term.c.x, term.c.y); + break; + case 2: /* all */ + tclearregion(0, term.c.y, term.col - 1, term.c.y); + break; + } + break; + case 'S': /* SU -- Scroll line up */ + DEFAULT(csiescseq.arg[0], 1); + tscrollup(term.top, csiescseq.arg[0]); + break; + case 'T': /* SD -- Scroll line down */ + DEFAULT(csiescseq.arg[0], 1); + tscrolldown(term.top, csiescseq.arg[0]); + break; + case 'L': /* IL -- Insert blank lines */ + DEFAULT(csiescseq.arg[0], 1); + tinsertblankline(csiescseq.arg[0]); + break; + case 'l': /* RM -- Reset Mode */ + tsetmode(csiescseq.priv, 0, csiescseq.arg, csiescseq.narg); + break; + case 'M': /* DL -- Delete lines */ + DEFAULT(csiescseq.arg[0], 1); + tdeleteline(csiescseq.arg[0]); + break; + case 'X': /* ECH -- Erase char */ + DEFAULT(csiescseq.arg[0], 1); + tclearregion(term.c.x, term.c.y, term.c.x + csiescseq.arg[0] - 1, + term.c.y); + break; + case 'P': /* DCH -- Delete char */ + DEFAULT(csiescseq.arg[0], 1); + tdeletechar(csiescseq.arg[0]); + break; + case 'Z': /* CBT -- Cursor Backward Tabulation tab stops */ + DEFAULT(csiescseq.arg[0], 1); + tputtab(-csiescseq.arg[0]); + break; + case 'd': /* VPA -- Move to */ + DEFAULT(csiescseq.arg[0], 1); + tmoveato(term.c.x, csiescseq.arg[0] - 1); + break; + case 'h': /* SM -- Set terminal mode */ + tsetmode(csiescseq.priv, 1, csiescseq.arg, csiescseq.narg); + break; + case 'm': /* SGR -- Terminal attribute (color) */ + tsetattr(csiescseq.arg, csiescseq.narg); + break; + case 'n': /* DSR – Device Status Report (cursor position) */ + if (csiescseq.arg[0] == 6) { + len = snprintf(buf, sizeof(buf), "\033[%i;%iR", term.c.y + 1, + term.c.x + 1); + ttywrite(buf, len, 0); + } + break; + case 'r': /* DECSTBM -- Set Scrolling Region */ + if (csiescseq.priv) { + goto unknown; + } else { + DEFAULT(csiescseq.arg[0], 1); + DEFAULT(csiescseq.arg[1], term.row); + tsetscroll(csiescseq.arg[0] - 1, csiescseq.arg[1] - 1); + tmoveato(0, 0); + } + break; + case 's': /* DECSC -- Save cursor position (ANSI.SYS) */ + tcursor(CURSOR_SAVE); + break; + case 'u': /* DECRC -- Restore cursor position (ANSI.SYS) */ + tcursor(CURSOR_LOAD); + break; + case ' ': + switch (csiescseq.mode[1]) { + case 'q': /* DECSCUSR -- Set Cursor Style */ + if (xsetcursor(csiescseq.arg[0])) + goto unknown; + break; + default: + goto unknown; + } + break; } - break; - case 'G': /* CHA -- Move to */ - case '`': /* HPA */ - DEFAULT(csiescseq.arg[0], 1); - tmoveto(csiescseq.arg[0] - 1, term.c.y); - break; - case 'H': /* CUP -- Move to */ - case 'f': /* HVP */ - DEFAULT(csiescseq.arg[0], 1); - DEFAULT(csiescseq.arg[1], 1); - tmoveato(csiescseq.arg[1] - 1, csiescseq.arg[0] - 1); - break; - case 'I': /* CHT -- Cursor Forward Tabulation tab stops */ - DEFAULT(csiescseq.arg[0], 1); - tputtab(csiescseq.arg[0]); - break; - case 'J': /* ED -- Clear screen */ - switch (csiescseq.arg[0]) { - case 0: /* below */ - tclearregion(term.c.x, term.c.y, term.col - 1, term.c.y); - if (term.c.y < term.row - 1) { - tclearregion(0, term.c.y + 1, term.col - 1, term.row - 1); - } - break; - case 1: /* above */ - if (term.c.y > 1) - tclearregion(0, 0, term.col - 1, term.c.y - 1); - tclearregion(0, term.c.y, term.c.x, term.c.y); - break; - case 2: /* all */ - tclearregion(0, 0, term.col - 1, term.row - 1); - break; - default: - goto unknown; - } - break; - case 'K': /* EL -- Clear line */ - switch (csiescseq.arg[0]) { - case 0: /* right */ - tclearregion(term.c.x, term.c.y, term.col - 1, term.c.y); - break; - case 1: /* left */ - tclearregion(0, term.c.y, term.c.x, term.c.y); - break; - case 2: /* all */ - tclearregion(0, term.c.y, term.col - 1, term.c.y); - break; - } - break; - case 'S': /* SU -- Scroll line up */ - DEFAULT(csiescseq.arg[0], 1); - tscrollup(term.top, csiescseq.arg[0]); - break; - case 'T': /* SD -- Scroll line down */ - DEFAULT(csiescseq.arg[0], 1); - tscrolldown(term.top, csiescseq.arg[0]); - break; - case 'L': /* IL -- Insert blank lines */ - DEFAULT(csiescseq.arg[0], 1); - tinsertblankline(csiescseq.arg[0]); - break; - case 'l': /* RM -- Reset Mode */ - tsetmode(csiescseq.priv, 0, csiescseq.arg, csiescseq.narg); - break; - case 'M': /* DL -- Delete lines */ - DEFAULT(csiescseq.arg[0], 1); - tdeleteline(csiescseq.arg[0]); - break; - case 'X': /* ECH -- Erase char */ - DEFAULT(csiescseq.arg[0], 1); - tclearregion(term.c.x, term.c.y, term.c.x + csiescseq.arg[0] - 1, term.c.y); - break; - case 'P': /* DCH -- Delete char */ - DEFAULT(csiescseq.arg[0], 1); - tdeletechar(csiescseq.arg[0]); - break; - case 'Z': /* CBT -- Cursor Backward Tabulation tab stops */ - DEFAULT(csiescseq.arg[0], 1); - tputtab(-csiescseq.arg[0]); - break; - case 'd': /* VPA -- Move to */ - DEFAULT(csiescseq.arg[0], 1); - tmoveato(term.c.x, csiescseq.arg[0] - 1); - break; - case 'h': /* SM -- Set terminal mode */ - tsetmode(csiescseq.priv, 1, csiescseq.arg, csiescseq.narg); - break; - case 'm': /* SGR -- Terminal attribute (color) */ - tsetattr(csiescseq.arg, csiescseq.narg); - break; - case 'n': /* DSR – Device Status Report (cursor position) */ - if (csiescseq.arg[0] == 6) { - len = - snprintf(buf, sizeof(buf), "\033[%i;%iR", term.c.y + 1, term.c.x + 1); - ttywrite(buf, len, 0); - } - break; - case 'r': /* DECSTBM -- Set Scrolling Region */ - if (csiescseq.priv) { - goto unknown; - } else { - DEFAULT(csiescseq.arg[0], 1); - DEFAULT(csiescseq.arg[1], term.row); - tsetscroll(csiescseq.arg[0] - 1, csiescseq.arg[1] - 1); - tmoveato(0, 0); - } - break; - case 's': /* DECSC -- Save cursor position (ANSI.SYS) */ - tcursor(CURSOR_SAVE); - break; - case 'u': /* DECRC -- Restore cursor position (ANSI.SYS) */ - tcursor(CURSOR_LOAD); - break; - case ' ': - switch (csiescseq.mode[1]) { - case 'q': /* DECSCUSR -- Set Cursor Style */ - if (xsetcursor(csiescseq.arg[0])) - goto unknown; - break; - default: - goto unknown; - } - break; - } } void csidump(void) { - size_t i; - uint c; + size_t i; + uint c; - fprintf(stderr, "ESC["); - for (i = 0; i < csiescseq.len; i++) { - c = csiescseq.buf[i] & 0xff; - if (isprint(c)) { - putc(c, stderr); - } else if (c == '\n') { - fprintf(stderr, "(\\n)"); - } else if (c == '\r') { - fprintf(stderr, "(\\r)"); - } else if (c == 0x1b) { - fprintf(stderr, "(\\e)"); - } else { - fprintf(stderr, "(%02x)", c); + fprintf(stderr, "ESC["); + for (i = 0; i < csiescseq.len; i++) { + c = csiescseq.buf[i] & 0xff; + if (isprint(c)) { + putc(c, stderr); + } else if (c == '\n') { + fprintf(stderr, "(\\n)"); + } else if (c == '\r') { + fprintf(stderr, "(\\r)"); + } else if (c == 0x1b) { + fprintf(stderr, "(\\e)"); + } else { + fprintf(stderr, "(%02x)", c); + } } - } - putc('\n', stderr); + putc('\n', stderr); } void csireset(void) { memset(&csiescseq, 0, sizeof(csiescseq)); } void strhandle(void) { - char *p = NULL, *dec; - int j, narg, par; + char *p = NULL, *dec; + int j, narg, par; - term.esc &= ~(ESC_STR_END | ESC_STR); - strparse(); - par = (narg = strescseq.narg) ? atoi(strescseq.args[0]) : 0; + term.esc &= ~(ESC_STR_END | ESC_STR); + strparse(); + par = (narg = strescseq.narg) ? atoi(strescseq.args[0]) : 0; - switch (strescseq.type) { - case ']': /* OSC -- Operating System Command */ - switch (par) { - case 0: - if (narg > 1) { - xsettitle(strescseq.args[1]); - xseticontitle(strescseq.args[1]); - } - return; - case 1: - if (narg > 1) - xseticontitle(strescseq.args[1]); - return; - case 2: - if (narg > 1) - xsettitle(strescseq.args[1]); - return; - case 52: - if (narg > 2 && allowwindowops) { - dec = base64dec(strescseq.args[2]); - if (dec) { - xsetsel(dec); - xclipcopy(); - } else { - fprintf(stderr, "erresc: invalid base64\n"); + switch (strescseq.type) { + case ']': /* OSC -- Operating System Command */ + switch (par) { + case 0: + if (narg > 1) { + xsettitle(strescseq.args[1]); + xseticontitle(strescseq.args[1]); + } + return; + case 1: + if (narg > 1) + xseticontitle(strescseq.args[1]); + return; + case 2: + if (narg > 1) + xsettitle(strescseq.args[1]); + return; + case 52: + if (narg > 2 && allowwindowops) { + dec = base64dec(strescseq.args[2]); + if (dec) { + xsetsel(dec); + xclipcopy(); + } else { + fprintf(stderr, "erresc: invalid base64\n"); + } + } + return; + case 4: /* color set */ + if (narg < 3) + break; + p = strescseq.args[2]; + /* FALLTHROUGH */ + case 104: /* color reset, here p = NULL */ + j = (narg > 1) ? atoi(strescseq.args[1]) : -1; + if (xsetcolorname(j, p)) { + if (par == 104 && narg <= 1) + return; /* color reset without parameter */ + fprintf(stderr, "erresc: invalid color j=%d, p=%s\n", j, + p ? p : "(null)"); + } else { + /* + * TODO if defaultbg color is changed, borders + * are dirty + */ + redraw(); + } + return; } - } - return; - case 4: /* color set */ - if (narg < 3) break; - p = strescseq.args[2]; - /* FALLTHROUGH */ - case 104: /* color reset, here p = NULL */ - j = (narg > 1) ? atoi(strescseq.args[1]) : -1; - if (xsetcolorname(j, p)) { - if (par == 104 && narg <= 1) - return; /* color reset without parameter */ - fprintf(stderr, "erresc: invalid color j=%d, p=%s\n", j, - p ? p : "(null)"); - } else { - /* - * TODO if defaultbg color is changed, borders - * are dirty - */ - redraw(); - } - return; + case 'k': /* old title set compatibility */ + xsettitle(strescseq.args[0]); + return; + case 'P': /* DCS -- Device Control String */ + case '_': /* APC -- Application Program Command */ + case '^': /* PM -- Privacy Message */ + return; } - break; - case 'k': /* old title set compatibility */ - xsettitle(strescseq.args[0]); - return; - case 'P': /* DCS -- Device Control String */ - case '_': /* APC -- Application Program Command */ - case '^': /* PM -- Privacy Message */ - return; - } - fprintf(stderr, "erresc: unknown str "); - strdump(); + fprintf(stderr, "erresc: unknown str "); + strdump(); } void strparse(void) { - int c; - char *p = strescseq.buf; + int c; + char *p = strescseq.buf; - strescseq.narg = 0; - strescseq.buf[strescseq.len] = '\0'; + strescseq.narg = 0; + strescseq.buf[strescseq.len] = '\0'; - if (*p == '\0') - return; + if (*p == '\0') + return; - while (strescseq.narg < STR_ARG_SIZ) { - strescseq.args[strescseq.narg++] = p; - while ((c = *p) != ';' && c != '\0') - ++p; - if (c == '\0') - return; - *p++ = '\0'; - } + while (strescseq.narg < STR_ARG_SIZ) { + strescseq.args[strescseq.narg++] = p; + while ((c = *p) != ';' && c != '\0') + ++p; + if (c == '\0') + return; + *p++ = '\0'; + } } void strdump(void) { - size_t i; - uint c; + size_t i; + uint c; - fprintf(stderr, "ESC%c", strescseq.type); - for (i = 0; i < strescseq.len; i++) { - c = strescseq.buf[i] & 0xff; - if (c == '\0') { - putc('\n', stderr); - return; - } else if (isprint(c)) { - putc(c, stderr); - } else if (c == '\n') { - fprintf(stderr, "(\\n)"); - } else if (c == '\r') { - fprintf(stderr, "(\\r)"); - } else if (c == 0x1b) { - fprintf(stderr, "(\\e)"); - } else { - fprintf(stderr, "(%02x)", c); + fprintf(stderr, "ESC%c", strescseq.type); + for (i = 0; i < strescseq.len; i++) { + c = strescseq.buf[i] & 0xff; + if (c == '\0') { + putc('\n', stderr); + return; + } else if (isprint(c)) { + putc(c, stderr); + } else if (c == '\n') { + fprintf(stderr, "(\\n)"); + } else if (c == '\r') { + fprintf(stderr, "(\\r)"); + } else if (c == 0x1b) { + fprintf(stderr, "(\\e)"); + } else { + fprintf(stderr, "(%02x)", c); + } } - } - fprintf(stderr, "ESC\\\n"); + fprintf(stderr, "ESC\\\n"); } void strreset(void) { - strescseq = (STREscape){ - .buf = safe_realloc(strescseq.buf, STR_BUF_SIZ), - .siz = STR_BUF_SIZ, - }; + strescseq = (STREscape){ + .buf = safe_realloc(strescseq.buf, STR_BUF_SIZ), + .siz = STR_BUF_SIZ, + }; } void sendbreak(const Arg *arg) { - if (tcsendbreak(cmdfd, 0)) - perror("Error sending break"); + if (tcsendbreak(cmdfd, 0)) + perror("Error sending break"); } void tprinter(char *s, size_t len) { - if (iofd != -1 && xwrite(iofd, s, len) < 0) { - perror("Error writing to output file"); - close(iofd); - iofd = -1; - } + if (iofd != -1 && xwrite(iofd, s, len) < 0) { + perror("Error writing to output file"); + close(iofd); + iofd = -1; + } } void toggleprinter(const Arg *arg) { term.mode ^= MODE_PRINT; } @@ -1842,192 +1885,192 @@ void printscreen(const Arg *arg) { tdump(); } void printsel(const Arg *arg) { tdumpsel(); } void tdumpsel(void) { - char *ptr; + char *ptr; - if ((ptr = getsel())) { - tprinter(ptr, strlen(ptr)); - free(ptr); - } + if ((ptr = getsel())) { + tprinter(ptr, strlen(ptr)); + free(ptr); + } } void tdumpline(int n) { - char buf[UTF_SIZE]; - Glyph *bp, *end; + char buf[UTF_SIZE]; + Glyph *bp, *end; - bp = &term.line[n][0]; - end = &bp[MIN(tlinelen(n), term.col) - 1]; - if (bp != end || bp->u != ' ') { - for (; bp <= end; ++bp) - tprinter(buf, utf8encode(bp->u, buf)); - } - tprinter("\n", 1); + bp = &term.line[n][0]; + end = &bp[MIN(tlinelen(n), term.col) - 1]; + if (bp != end || bp->u != ' ') { + for (; bp <= end; ++bp) + tprinter(buf, utf8encode(bp->u, buf)); + } + tprinter("\n", 1); } void tdump(void) { - int i; + int i; - for (i = 0; i < term.row; ++i) - tdumpline(i); + for (i = 0; i < term.row; ++i) + tdumpline(i); } void tputtab(int n) { - uint x = term.c.x; + uint x = term.c.x; - if (n > 0) { - while (x < term.col && n--) - for (++x; x < term.col && !term.tabs[x]; ++x) - /* nothing */; - } else if (n < 0) { - while (x > 0 && n++) - for (--x; x > 0 && !term.tabs[x]; --x) - /* nothing */; - } - term.c.x = LIMIT(x, 0, term.col - 1); + if (n > 0) { + while (x < term.col && n--) + for (++x; x < term.col && !term.tabs[x]; ++x) + /* nothing */; + } else if (n < 0) { + while (x > 0 && n++) + for (--x; x > 0 && !term.tabs[x]; --x) + /* nothing */; + } + term.c.x = LIMIT(x, 0, term.col - 1); } void tdefutf8(char ascii) { - if (ascii == 'G') - term.mode |= MODE_UTF8; - else if (ascii == '@') - term.mode &= ~MODE_UTF8; + if (ascii == 'G') + term.mode |= MODE_UTF8; + else if (ascii == '@') + term.mode &= ~MODE_UTF8; } void tdeftran(char ascii) { - static char cs[] = "0B"; - static int vcs[] = {CS_GRAPHIC0, CS_USA}; - char *p; + static char cs[] = "0B"; + static int vcs[] = {CS_GRAPHIC0, CS_USA}; + char *p; - if ((p = strchr(cs, ascii)) == NULL) { - fprintf(stderr, "esc unhandled charset: ESC ( %c\n", ascii); - } else { - term.trantbl[term.icharset] = vcs[p - cs]; - } + if ((p = strchr(cs, ascii)) == NULL) { + fprintf(stderr, "esc unhandled charset: ESC ( %c\n", ascii); + } else { + term.trantbl[term.icharset] = vcs[p - cs]; + } } void tdectest(char c) { - int x, y; + int x, y; - if (c == '8') { /* DEC screen alignment test. */ - for (x = 0; x < term.col; ++x) { - for (y = 0; y < term.row; ++y) - tsetchar('E', &term.c.attr, x, y); + if (c == '8') { /* DEC screen alignment test. */ + for (x = 0; x < term.col; ++x) { + for (y = 0; y < term.row; ++y) + tsetchar('E', &term.c.attr, x, y); + } } - } } void tstrsequence(uchar c) { - switch (c) { - case 0x90: /* DCS -- Device Control String */ - c = 'P'; - break; - case 0x9f: /* APC -- Application Program Command */ - c = '_'; - break; - case 0x9e: /* PM -- Privacy Message */ - c = '^'; - break; - case 0x9d: /* OSC -- Operating System Command */ - c = ']'; - break; - } - strreset(); - strescseq.type = c; - term.esc |= ESC_STR; + switch (c) { + case 0x90: /* DCS -- Device Control String */ + c = 'P'; + break; + case 0x9f: /* APC -- Application Program Command */ + c = '_'; + break; + case 0x9e: /* PM -- Privacy Message */ + c = '^'; + break; + case 0x9d: /* OSC -- Operating System Command */ + c = ']'; + break; + } + strreset(); + strescseq.type = c; + term.esc |= ESC_STR; } void tcontrolcode(uchar ascii) { - switch (ascii) { - case '\t': /* HT */ - tputtab(1); - return; - case '\b': /* BS */ - tmoveto(term.c.x - 1, term.c.y); - return; - case '\r': /* CR */ - tmoveto(0, term.c.y); - return; - case '\f': /* LF */ - case '\v': /* VT */ - case '\n': /* LF */ - /* go to first col if the mode is set */ - tnewline(IS_SET(MODE_CRLF)); - return; - case '\a': /* BEL */ - if (term.esc & ESC_STR_END) { - /* backwards compatibility to xterm */ - strhandle(); - } else { - xbell(); + switch (ascii) { + case '\t': /* HT */ + tputtab(1); + return; + case '\b': /* BS */ + tmoveto(term.c.x - 1, term.c.y); + return; + case '\r': /* CR */ + tmoveto(0, term.c.y); + return; + case '\f': /* LF */ + case '\v': /* VT */ + case '\n': /* LF */ + /* go to first col if the mode is set */ + tnewline(IS_SET(MODE_CRLF)); + return; + case '\a': /* BEL */ + if (term.esc & ESC_STR_END) { + /* backwards compatibility to xterm */ + strhandle(); + } else { + xbell(); + } + break; + case '\033': /* ESC */ + csireset(); + term.esc &= ~(ESC_CSI | ESC_ALTCHARSET | ESC_TEST); + term.esc |= ESC_START; + return; + case '\016': /* SO (LS1 -- Locking shift 1) */ + case '\017': /* SI (LS0 -- Locking shift 0) */ + term.charset = 1 - (ascii - '\016'); + return; + case '\032': /* SUB */ + tsetchar('?', &term.c.attr, term.c.x, term.c.y); + /* FALLTHROUGH */ + case '\030': /* CAN */ + csireset(); + break; + case '\005': /* ENQ (IGNORED) */ + case '\000': /* NUL (IGNORED) */ + case '\021': /* XON (IGNORED) */ + case '\023': /* XOFF (IGNORED) */ + case 0177: /* DEL (IGNORED) */ + return; + case 0x80: /* TODO: PAD */ + case 0x81: /* TODO: HOP */ + case 0x82: /* TODO: BPH */ + case 0x83: /* TODO: NBH */ + case 0x84: /* TODO: IND */ + break; + case 0x85: /* NEL -- Next line */ + tnewline(1); /* always go to first col */ + break; + case 0x86: /* TODO: SSA */ + case 0x87: /* TODO: ESA */ + break; + case 0x88: /* HTS -- Horizontal tab stop */ + term.tabs[term.c.x] = 1; + break; + case 0x89: /* TODO: HTJ */ + case 0x8a: /* TODO: VTS */ + case 0x8b: /* TODO: PLD */ + case 0x8c: /* TODO: PLU */ + case 0x8d: /* TODO: RI */ + case 0x8e: /* TODO: SS2 */ + case 0x8f: /* TODO: SS3 */ + case 0x91: /* TODO: PU1 */ + case 0x92: /* TODO: PU2 */ + case 0x93: /* TODO: STS */ + case 0x94: /* TODO: CCH */ + case 0x95: /* TODO: MW */ + case 0x96: /* TODO: SPA */ + case 0x97: /* TODO: EPA */ + case 0x98: /* TODO: SOS */ + case 0x99: /* TODO: SGCI */ + break; + case 0x9a: /* DECID -- Identify Terminal */ + ttywrite(vtiden, strlen(vtiden), 0); + break; + case 0x9b: /* TODO: CSI */ + case 0x9c: /* TODO: ST */ + break; + case 0x90: /* DCS -- Device Control String */ + case 0x9d: /* OSC -- Operating System Command */ + case 0x9e: /* PM -- Privacy Message */ + case 0x9f: /* APC -- Application Program Command */ + tstrsequence(ascii); + return; } - break; - case '\033': /* ESC */ - csireset(); - term.esc &= ~(ESC_CSI | ESC_ALTCHARSET | ESC_TEST); - term.esc |= ESC_START; - return; - case '\016': /* SO (LS1 -- Locking shift 1) */ - case '\017': /* SI (LS0 -- Locking shift 0) */ - term.charset = 1 - (ascii - '\016'); - return; - case '\032': /* SUB */ - tsetchar('?', &term.c.attr, term.c.x, term.c.y); - /* FALLTHROUGH */ - case '\030': /* CAN */ - csireset(); - break; - case '\005': /* ENQ (IGNORED) */ - case '\000': /* NUL (IGNORED) */ - case '\021': /* XON (IGNORED) */ - case '\023': /* XOFF (IGNORED) */ - case 0177: /* DEL (IGNORED) */ - return; - case 0x80: /* TODO: PAD */ - case 0x81: /* TODO: HOP */ - case 0x82: /* TODO: BPH */ - case 0x83: /* TODO: NBH */ - case 0x84: /* TODO: IND */ - break; - case 0x85: /* NEL -- Next line */ - tnewline(1); /* always go to first col */ - break; - case 0x86: /* TODO: SSA */ - case 0x87: /* TODO: ESA */ - break; - case 0x88: /* HTS -- Horizontal tab stop */ - term.tabs[term.c.x] = 1; - break; - case 0x89: /* TODO: HTJ */ - case 0x8a: /* TODO: VTS */ - case 0x8b: /* TODO: PLD */ - case 0x8c: /* TODO: PLU */ - case 0x8d: /* TODO: RI */ - case 0x8e: /* TODO: SS2 */ - case 0x8f: /* TODO: SS3 */ - case 0x91: /* TODO: PU1 */ - case 0x92: /* TODO: PU2 */ - case 0x93: /* TODO: STS */ - case 0x94: /* TODO: CCH */ - case 0x95: /* TODO: MW */ - case 0x96: /* TODO: SPA */ - case 0x97: /* TODO: EPA */ - case 0x98: /* TODO: SOS */ - case 0x99: /* TODO: SGCI */ - break; - case 0x9a: /* DECID -- Identify Terminal */ - ttywrite(vtiden, strlen(vtiden), 0); - break; - case 0x9b: /* TODO: CSI */ - case 0x9c: /* TODO: ST */ - break; - case 0x90: /* DCS -- Device Control String */ - case 0x9d: /* OSC -- Operating System Command */ - case 0x9e: /* PM -- Privacy Message */ - case 0x9f: /* APC -- Application Program Command */ - tstrsequence(ascii); - return; - } - /* only CAN, SUB, \a and C1 chars interrupt a sequence */ - term.esc &= ~(ESC_STR_END | ESC_STR); + /* only CAN, SUB, \a and C1 chars interrupt a sequence */ + term.esc &= ~(ESC_STR_END | ESC_STR); } /* @@ -2035,368 +2078,368 @@ void tcontrolcode(uchar ascii) { * more characters for this sequence, otherwise 0 */ int eschandle(uchar ascii) { - switch (ascii) { - case '[': - term.esc |= ESC_CSI; - return 0; - case '#': - term.esc |= ESC_TEST; - return 0; - case '%': - term.esc |= ESC_UTF8; - return 0; - case 'P': /* DCS -- Device Control String */ - case '_': /* APC -- Application Program Command */ - case '^': /* PM -- Privacy Message */ - case ']': /* OSC -- Operating System Command */ - case 'k': /* old title set compatibility */ - tstrsequence(ascii); - return 0; - case 'n': /* LS2 -- Locking shift 2 */ - case 'o': /* LS3 -- Locking shift 3 */ - term.charset = 2 + (ascii - 'n'); - break; - case '(': /* GZD4 -- set primary charset G0 */ - case ')': /* G1D4 -- set secondary charset G1 */ - case '*': /* G2D4 -- set tertiary charset G2 */ - case '+': /* G3D4 -- set quaternary charset G3 */ - term.icharset = ascii - '('; - term.esc |= ESC_ALTCHARSET; - return 0; - case 'D': /* IND -- Linefeed */ - if (term.c.y == term.bot) { - tscrollup(term.top, 1); - } else { - tmoveto(term.c.x, term.c.y + 1); + switch (ascii) { + case '[': + term.esc |= ESC_CSI; + return 0; + case '#': + term.esc |= ESC_TEST; + return 0; + case '%': + term.esc |= ESC_UTF8; + return 0; + case 'P': /* DCS -- Device Control String */ + case '_': /* APC -- Application Program Command */ + case '^': /* PM -- Privacy Message */ + case ']': /* OSC -- Operating System Command */ + case 'k': /* old title set compatibility */ + tstrsequence(ascii); + return 0; + case 'n': /* LS2 -- Locking shift 2 */ + case 'o': /* LS3 -- Locking shift 3 */ + term.charset = 2 + (ascii - 'n'); + break; + case '(': /* GZD4 -- set primary charset G0 */ + case ')': /* G1D4 -- set secondary charset G1 */ + case '*': /* G2D4 -- set tertiary charset G2 */ + case '+': /* G3D4 -- set quaternary charset G3 */ + term.icharset = ascii - '('; + term.esc |= ESC_ALTCHARSET; + return 0; + case 'D': /* IND -- Linefeed */ + if (term.c.y == term.bot) { + tscrollup(term.top, 1); + } else { + tmoveto(term.c.x, term.c.y + 1); + } + break; + case 'E': /* NEL -- Next line */ + tnewline(1); /* always go to first col */ + break; + case 'H': /* HTS -- Horizontal tab stop */ + term.tabs[term.c.x] = 1; + break; + case 'M': /* RI -- Reverse index */ + if (term.c.y == term.top) { + tscrolldown(term.top, 1); + } else { + tmoveto(term.c.x, term.c.y - 1); + } + break; + case 'Z': /* DECID -- Identify Terminal */ + ttywrite(vtiden, strlen(vtiden), 0); + break; + case 'c': /* RIS -- Reset to initial state */ + treset(); + resettitle(); + xloadcols(); + break; + case '=': /* DECPAM -- Application keypad */ + xsetmode(1, MODE_APPKEYPAD); + break; + case '>': /* DECPNM -- Normal keypad */ + xsetmode(0, MODE_APPKEYPAD); + break; + case '7': /* DECSC -- Save Cursor */ + tcursor(CURSOR_SAVE); + break; + case '8': /* DECRC -- Restore Cursor */ + tcursor(CURSOR_LOAD); + break; + case '\\': /* ST -- String Terminator */ + if (term.esc & ESC_STR_END) + strhandle(); + break; + default: + fprintf(stderr, "erresc: unknown sequence ESC 0x%02X '%c'\n", + (uchar)ascii, isprint(ascii) ? ascii : '.'); + break; } - break; - case 'E': /* NEL -- Next line */ - tnewline(1); /* always go to first col */ - break; - case 'H': /* HTS -- Horizontal tab stop */ - term.tabs[term.c.x] = 1; - break; - case 'M': /* RI -- Reverse index */ - if (term.c.y == term.top) { - tscrolldown(term.top, 1); - } else { - tmoveto(term.c.x, term.c.y - 1); - } - break; - case 'Z': /* DECID -- Identify Terminal */ - ttywrite(vtiden, strlen(vtiden), 0); - break; - case 'c': /* RIS -- Reset to initial state */ - treset(); - resettitle(); - xloadcols(); - break; - case '=': /* DECPAM -- Application keypad */ - xsetmode(1, MODE_APPKEYPAD); - break; - case '>': /* DECPNM -- Normal keypad */ - xsetmode(0, MODE_APPKEYPAD); - break; - case '7': /* DECSC -- Save Cursor */ - tcursor(CURSOR_SAVE); - break; - case '8': /* DECRC -- Restore Cursor */ - tcursor(CURSOR_LOAD); - break; - case '\\': /* ST -- String Terminator */ - if (term.esc & ESC_STR_END) - strhandle(); - break; - default: - fprintf(stderr, "erresc: unknown sequence ESC 0x%02X '%c'\n", (uchar)ascii, - isprint(ascii) ? ascii : '.'); - break; - } - return 1; + return 1; } void tputc(Rune u) { - char c[UTF_SIZE]; - int control; - int width, len; - Glyph *gp; + char c[UTF_SIZE]; + int control; + int width, len; + Glyph *gp; - control = ISCONTROL(u); - if (u < 127 || !IS_SET(MODE_UTF8)) { - c[0] = u; - width = len = 1; - } else { - len = utf8encode(u, c); - if (!control && (width = wcwidth(u)) == -1) - width = 1; - } - - if (IS_SET(MODE_PRINT)) - tprinter(c, len); - - /* - * STR sequence must be checked before anything else - * because it uses all following characters until it - * receives a ESC, a SUB, a ST or any other C1 control - * character. - */ - if (term.esc & ESC_STR) { - if (u == '\a' || u == 030 || u == 032 || u == 033 || ISCONTROLC1(u)) { - term.esc &= ~(ESC_START | ESC_STR); - term.esc |= ESC_STR_END; - goto check_control_code; + control = ISCONTROL(u); + if (u < 127 || !IS_SET(MODE_UTF8)) { + c[0] = u; + width = len = 1; + } else { + len = utf8encode(u, c); + if (!control && (width = wcwidth(u)) == -1) + width = 1; } - if (strescseq.len + len >= strescseq.siz) { - /* - * Here is a bug in terminals. If the user never sends - * some code to stop the str or esc command, then st - * will stop responding. But this is better than - * silently failing with unknown characters. At least - * then users will report back. - * - * In the case users ever get fixed, here is the code: - */ - /* - * term.esc = 0; - * strhandle(); - */ - if (strescseq.siz > (SIZE_MAX - UTF_SIZE) / 2) + if (IS_SET(MODE_PRINT)) + tprinter(c, len); + + /* + * STR sequence must be checked before anything else + * because it uses all following characters until it + * receives a ESC, a SUB, a ST or any other C1 control + * character. + */ + if (term.esc & ESC_STR) { + if (u == '\a' || u == 030 || u == 032 || u == 033 || ISCONTROLC1(u)) { + term.esc &= ~(ESC_START | ESC_STR); + term.esc |= ESC_STR_END; + goto check_control_code; + } + + if (strescseq.len + len >= strescseq.siz) { + /* + * Here is a bug in terminals. If the user never sends + * some code to stop the str or esc command, then st + * will stop responding. But this is better than + * silently failing with unknown characters. At least + * then users will report back. + * + * In the case users ever get fixed, here is the code: + */ + /* + * term.esc = 0; + * strhandle(); + */ + if (strescseq.siz > (SIZE_MAX - UTF_SIZE) / 2) + return; + strescseq.siz *= 2; + strescseq.buf = safe_realloc(strescseq.buf, strescseq.siz); + } + + memmove(&strescseq.buf[strescseq.len], c, len); + strescseq.len += len; return; - strescseq.siz *= 2; - strescseq.buf = safe_realloc(strescseq.buf, strescseq.siz); } - memmove(&strescseq.buf[strescseq.len], c, len); - strescseq.len += len; - return; - } - check_control_code: - /* - * Actions of control codes must be performed as soon they arrive - * because they can be embedded inside a control sequence, and - * they must not cause conflicts with sequences. - */ - if (control) { - tcontrolcode(u); /* - * control codes are not shown ever + * Actions of control codes must be performed as soon they arrive + * because they can be embedded inside a control sequence, and + * they must not cause conflicts with sequences. */ - if (!term.esc) - term.lastc = 0; - return; - } else if (term.esc & ESC_START) { - if (term.esc & ESC_CSI) { - csiescseq.buf[csiescseq.len++] = u; - if (BETWEEN(u, 0x40, 0x7E) || - csiescseq.len >= sizeof(csiescseq.buf) - 1) { - term.esc = 0; - csiparse(); - csihandle(); - } - return; - } else if (term.esc & ESC_UTF8) { - tdefutf8(u); - } else if (term.esc & ESC_ALTCHARSET) { - tdeftran(u); - } else if (term.esc & ESC_TEST) { - tdectest(u); - } else { - if (!eschandle(u)) + if (control) { + tcontrolcode(u); + /* + * control codes are not shown ever + */ + if (!term.esc) + term.lastc = 0; + return; + } else if (term.esc & ESC_START) { + if (term.esc & ESC_CSI) { + csiescseq.buf[csiescseq.len++] = u; + if (BETWEEN(u, 0x40, 0x7E) || + csiescseq.len >= sizeof(csiescseq.buf) - 1) { + term.esc = 0; + csiparse(); + csihandle(); + } + return; + } else if (term.esc & ESC_UTF8) { + tdefutf8(u); + } else if (term.esc & ESC_ALTCHARSET) { + tdeftran(u); + } else if (term.esc & ESC_TEST) { + tdectest(u); + } else { + if (!eschandle(u)) + return; + /* sequence already finished */ + } + term.esc = 0; + /* + * All characters which form part of a sequence are not + * printed + */ return; - /* sequence already finished */ } - term.esc = 0; - /* - * All characters which form part of a sequence are not - * printed - */ - return; - } - if (selected(term.c.x, term.c.y)) - selclear(); + if (selected(term.c.x, term.c.y)) + selclear(); - gp = &term.line[term.c.y][term.c.x]; - if (IS_SET(MODE_WRAP) && (term.c.state & CURSOR_WRAPNEXT)) { - gp->mode |= ATTR_WRAP; - tnewline(1); gp = &term.line[term.c.y][term.c.x]; - } - - if (IS_SET(MODE_INSERT) && term.c.x + width < term.col) - memmove(gp + width, gp, (term.col - term.c.x - width) * sizeof(Glyph)); - - if (term.c.x + width > term.col) { - tnewline(1); - gp = &term.line[term.c.y][term.c.x]; - } - - tsetchar(u, &term.c.attr, term.c.x, term.c.y); - term.lastc = u; - - if (width == 2) { - gp->mode |= ATTR_WIDE; - if (term.c.x + 1 < term.col) { - gp[1].u = '\0'; - gp[1].mode = ATTR_WDUMMY; + if (IS_SET(MODE_WRAP) && (term.c.state & CURSOR_WRAPNEXT)) { + gp->mode |= ATTR_WRAP; + tnewline(1); + gp = &term.line[term.c.y][term.c.x]; + } + + if (IS_SET(MODE_INSERT) && term.c.x + width < term.col) + memmove(gp + width, gp, (term.col - term.c.x - width) * sizeof(Glyph)); + + if (term.c.x + width > term.col) { + tnewline(1); + gp = &term.line[term.c.y][term.c.x]; + } + + tsetchar(u, &term.c.attr, term.c.x, term.c.y); + term.lastc = u; + + if (width == 2) { + gp->mode |= ATTR_WIDE; + if (term.c.x + 1 < term.col) { + gp[1].u = '\0'; + gp[1].mode = ATTR_WDUMMY; + } + } + if (term.c.x + width < term.col) { + tmoveto(term.c.x + width, term.c.y); + } else { + term.c.state |= CURSOR_WRAPNEXT; } - } - if (term.c.x + width < term.col) { - tmoveto(term.c.x + width, term.c.y); - } else { - term.c.state |= CURSOR_WRAPNEXT; - } } int twrite(const char *buf, int buflen, int show_ctrl) { - int charsize; - Rune u; - int n; + int charsize; + Rune u; + int n; - for (n = 0; n < buflen; n += charsize) { - if (IS_SET(MODE_UTF8)) { - /* process a complete utf8 char */ - charsize = utf8decode(buf + n, &u, buflen - n); - if (charsize == 0) - break; - } else { - u = buf[n] & 0xFF; - charsize = 1; + for (n = 0; n < buflen; n += charsize) { + if (IS_SET(MODE_UTF8)) { + /* process a complete utf8 char */ + charsize = utf8decode(buf + n, &u, buflen - n); + if (charsize == 0) + break; + } else { + u = buf[n] & 0xFF; + charsize = 1; + } + if (show_ctrl && ISCONTROL(u)) { + if (u & 0x80) { + u &= 0x7f; + tputc('^'); + tputc('['); + } else if (u != '\n' && u != '\r' && u != '\t') { + u ^= 0x40; + tputc('^'); + } + } + tputc(u); } - if (show_ctrl && ISCONTROL(u)) { - if (u & 0x80) { - u &= 0x7f; - tputc('^'); - tputc('['); - } else if (u != '\n' && u != '\r' && u != '\t') { - u ^= 0x40; - tputc('^'); - } - } - tputc(u); - } - return n; + return n; } void tresize(int col, int row) { - int i; - int minrow = MIN(row, term.row); - int mincol = MIN(col, term.col); - int *bp; - TCursor c; + int i; + int minrow = MIN(row, term.row); + int mincol = MIN(col, term.col); + int *bp; + TCursor c; - if (col < 1 || row < 1) { - fprintf(stderr, "tresize: error resizing to %dx%d\n", col, row); - return; - } - - /* - * slide screen to keep cursor where we expect it - - * tscrollup would work here, but we can optimize to - * memmove because we're freeing the earlier lines - */ - for (i = 0; i <= term.c.y - row; i++) { - free(term.line[i]); - free(term.alt[i]); - } - /* ensure that both src and dst are not NULL */ - if (i > 0) { - memmove(term.line, term.line + i, row * sizeof(Line)); - memmove(term.alt, term.alt + i, row * sizeof(Line)); - } - for (i += row; i < term.row; i++) { - free(term.line[i]); - free(term.alt[i]); - } - - /* resize to new height */ - term.line = safe_realloc(term.line, row * sizeof(Line)); - term.alt = safe_realloc(term.alt, row * sizeof(Line)); - term.dirty = safe_realloc(term.dirty, row * sizeof(*term.dirty)); - term.tabs = safe_realloc(term.tabs, col * sizeof(*term.tabs)); - - /* resize each row to new width, zero-pad if needed */ - for (i = 0; i < minrow; i++) { - term.line[i] = safe_realloc(term.line[i], col * sizeof(Glyph)); - term.alt[i] = safe_realloc(term.alt[i], col * sizeof(Glyph)); - } - - /* allocate any new rows */ - for (/* i = minrow */; i < row; i++) { - term.line[i] = safe_malloc(col * sizeof(Glyph)); - term.alt[i] = safe_malloc(col * sizeof(Glyph)); - } - if (col > term.col) { - bp = term.tabs + term.col; - - memset(bp, 0, sizeof(*term.tabs) * (col - term.col)); - while (--bp > term.tabs && !*bp) - /* nothing */; - for (bp += tabspaces; bp < term.tabs + col; bp += tabspaces) - *bp = 1; - } - /* update terminal size */ - term.col = col; - term.row = row; - /* reset scrolling region */ - tsetscroll(0, row - 1); - /* make use of the LIMIT in tmoveto */ - tmoveto(term.c.x, term.c.y); - /* Clearing both screens (it makes dirty all lines) */ - c = term.c; - for (i = 0; i < 2; i++) { - if (mincol < col && 0 < minrow) { - tclearregion(mincol, 0, col - 1, minrow - 1); + if (col < 1 || row < 1) { + fprintf(stderr, "tresize: error resizing to %dx%d\n", col, row); + return; } - if (0 < col && minrow < row) { - tclearregion(0, minrow, col - 1, row - 1); + + /* + * slide screen to keep cursor where we expect it - + * tscrollup would work here, but we can optimize to + * memmove because we're freeing the earlier lines + */ + for (i = 0; i <= term.c.y - row; i++) { + free(term.line[i]); + free(term.alt[i]); } - tswapscreen(); - tcursor(CURSOR_LOAD); - } - term.c = c; + /* ensure that both src and dst are not NULL */ + if (i > 0) { + memmove(term.line, term.line + i, row * sizeof(Line)); + memmove(term.alt, term.alt + i, row * sizeof(Line)); + } + for (i += row; i < term.row; i++) { + free(term.line[i]); + free(term.alt[i]); + } + + /* resize to new height */ + term.line = safe_realloc(term.line, row * sizeof(Line)); + term.alt = safe_realloc(term.alt, row * sizeof(Line)); + term.dirty = safe_realloc(term.dirty, row * sizeof(*term.dirty)); + term.tabs = safe_realloc(term.tabs, col * sizeof(*term.tabs)); + + /* resize each row to new width, zero-pad if needed */ + for (i = 0; i < minrow; i++) { + term.line[i] = safe_realloc(term.line[i], col * sizeof(Glyph)); + term.alt[i] = safe_realloc(term.alt[i], col * sizeof(Glyph)); + } + + /* allocate any new rows */ + for (/* i = minrow */; i < row; i++) { + term.line[i] = safe_malloc(col * sizeof(Glyph)); + term.alt[i] = safe_malloc(col * sizeof(Glyph)); + } + if (col > term.col) { + bp = term.tabs + term.col; + + memset(bp, 0, sizeof(*term.tabs) * (col - term.col)); + while (--bp > term.tabs && !*bp) + /* nothing */; + for (bp += tabspaces; bp < term.tabs + col; bp += tabspaces) + *bp = 1; + } + /* update terminal size */ + term.col = col; + term.row = row; + /* reset scrolling region */ + tsetscroll(0, row - 1); + /* make use of the LIMIT in tmoveto */ + tmoveto(term.c.x, term.c.y); + /* Clearing both screens (it makes dirty all lines) */ + c = term.c; + for (i = 0; i < 2; i++) { + if (mincol < col && 0 < minrow) { + tclearregion(mincol, 0, col - 1, minrow - 1); + } + if (0 < col && minrow < row) { + tclearregion(0, minrow, col - 1, row - 1); + } + tswapscreen(); + tcursor(CURSOR_LOAD); + } + term.c = c; } void resettitle(void) { xsettitle(NULL); } void drawregion(int x1, int y1, int x2, int y2) { - int y; + int y; - for (y = y1; y < y2; y++) { - if (!term.dirty[y]) - continue; + for (y = y1; y < y2; y++) { + if (!term.dirty[y]) + continue; - term.dirty[y] = 0; - xdrawline(term.line[y], x1, y, x2); - } + term.dirty[y] = 0; + xdrawline(term.line[y], x1, y, x2); + } } void draw(void) { - int cx = term.c.x, ocx = term.ocx, ocy = term.ocy; + int cx = term.c.x, ocx = term.ocx, ocy = term.ocy; - if (!xstartdraw()) - return; + if (!xstartdraw()) + return; - /* adjust cursor position */ - LIMIT(term.ocx, 0, term.col - 1); - LIMIT(term.ocy, 0, term.row - 1); - if (term.line[term.ocy][term.ocx].mode & ATTR_WDUMMY) - term.ocx--; - if (term.line[term.c.y][cx].mode & ATTR_WDUMMY) - cx--; + /* adjust cursor position */ + LIMIT(term.ocx, 0, term.col - 1); + LIMIT(term.ocy, 0, term.row - 1); + if (term.line[term.ocy][term.ocx].mode & ATTR_WDUMMY) + term.ocx--; + if (term.line[term.c.y][cx].mode & ATTR_WDUMMY) + cx--; - drawregion(0, 0, term.col, term.row); - xdrawcursor(cx, term.c.y, term.line[term.c.y][cx], term.ocx, term.ocy, - term.line[term.ocy][term.ocx]); - term.ocx = cx; - term.ocy = term.c.y; - xfinishdraw(); - if (ocx != term.ocx || ocy != term.ocy) - xximspot(term.ocx, term.ocy); + drawregion(0, 0, term.col, term.row); + xdrawcursor(cx, term.c.y, term.line[term.c.y][cx], term.ocx, term.ocy, + term.line[term.ocy][term.ocx]); + term.ocx = cx; + term.ocy = term.c.y; + xfinishdraw(); + if (ocx != term.ocx || ocy != term.ocy) + xximspot(term.ocx, term.ocy); } void redraw(void) { - tfulldirt(); - draw(); + tfulldirt(); + draw(); } diff --git a/src/st/st.h b/src/st/st.h index aca352c..48d47f6 100644 --- a/src/st/st.h +++ b/src/st/st.h @@ -3,41 +3,31 @@ #ifndef ST_H #define ST_H +#include #include #include -#include enum glyph_attribute { - ATTR_NULL = 0, - ATTR_BOLD = 1 << 0, - ATTR_FAINT = 1 << 1, - ATTR_ITALIC = 1 << 2, - ATTR_UNDERLINE = 1 << 3, - ATTR_BLINK = 1 << 4, - ATTR_REVERSE = 1 << 5, - ATTR_INVISIBLE = 1 << 6, - ATTR_STRUCK = 1 << 7, - ATTR_WRAP = 1 << 8, - ATTR_WIDE = 1 << 9, - ATTR_WDUMMY = 1 << 10, - ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT, + ATTR_NULL = 0, + ATTR_BOLD = 1 << 0, + ATTR_FAINT = 1 << 1, + ATTR_ITALIC = 1 << 2, + ATTR_UNDERLINE = 1 << 3, + ATTR_BLINK = 1 << 4, + ATTR_REVERSE = 1 << 5, + ATTR_INVISIBLE = 1 << 6, + ATTR_STRUCK = 1 << 7, + ATTR_WRAP = 1 << 8, + ATTR_WIDE = 1 << 9, + ATTR_WDUMMY = 1 << 10, + ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT, }; -enum selection_mode { - SEL_IDLE = 0, - SEL_EMPTY = 1, - SEL_READY = 2 -}; +enum selection_mode { SEL_IDLE = 0, SEL_EMPTY = 1, SEL_READY = 2 }; -enum selection_type { - SEL_REGULAR = 1, - SEL_RECTANGULAR = 2 -}; +enum selection_type { SEL_REGULAR = 1, SEL_RECTANGULAR = 2 }; -enum selection_snap { - SNAP_WORD = 1, - SNAP_LINE = 2 -}; +enum selection_snap { SNAP_WORD = 1, SNAP_LINE = 2 }; typedef unsigned char uchar; typedef unsigned int uint; @@ -48,20 +38,20 @@ typedef uint_least32_t Rune; #define Glyph Glyph_ typedef struct { - Rune u; /* character code */ - ushort mode; /* attribute flags */ - uint32_t fg; /* foreground */ - uint32_t bg; /* background */ + Rune u; /* character code */ + ushort mode; /* attribute flags */ + uint32_t fg; /* foreground */ + uint32_t bg; /* background */ } Glyph; typedef Glyph *Line; typedef union { - int i; - uint ui; - float f; - const void *v; - const char *s; + int i; + uint ui; + float f; + const void *v; + const char *s; } Arg; void die(const char *, ...); From a13536d0c7dbec8fd3daccd783c877d9cf6a48ae Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Wed, 2 Dec 2020 14:26:01 +0100 Subject: [PATCH 03/11] Some refactoring --- src/st/st.c | 69 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 44 insertions(+), 25 deletions(-) diff --git a/src/st/st.c b/src/st/st.c index 8d2a202..c39ffa9 100644 --- a/src/st/st.c +++ b/src/st/st.c @@ -308,67 +308,86 @@ char *safe_strdup(char *p_str) { * @return size of the decoded rune */ size_t utf8decode(const char *p_char, Rune *p_rune, size_t p_char_len) { - size_t decoded_len, type; - Rune rune_decoded; + size_t decoded_len, type, i; + Rune decoded_rune; *p_rune = UTF_INVALID; - if (!p_char_len) // chr_len is 0, so just return 0 + if (!p_char_len) // p_char_len is 0, so just return 0 return 0; - rune_decoded = utf8decodebyte(p_char[0], &decoded_len); + decoded_rune = utf8decodebyte(p_char[0], &decoded_len); if (!BETWEEN(decoded_len, 1, UTF_SIZE)) return 1; - size_t i, j; - for (i = 1, j = 1; i < p_char_len && j < decoded_len; ++i, ++j) { - rune_decoded = (rune_decoded << 6) | utf8decodebyte(p_char[i], &type); + for (i = 1; i < p_char_len && i < decoded_len; ++i) { + decoded_rune = (decoded_rune << 6) | utf8decodebyte(p_char[i], &type); if (type != 0) - return j; + return i; } - if (j < decoded_len) + if (i < decoded_len) return 0; - *p_rune = rune_decoded; + *p_rune = decoded_rune; utf8validate(p_rune, decoded_len); return decoded_len; } -Rune utf8decodebyte(char p_char, size_t *i) { - - for (*i = 0; *i < LEN(utfmask); ++(*i)) { - if (((uchar)p_char & utfmask[*i]) == utfbyte[*i]) - return (uchar)p_char & ~utfmask[*i]; +/** + * Decode a single byte to UTF-8 + * + * @param p_char char to decode + * @param p_i counter used in internal for loop + * @return decoded rune + */ +Rune utf8decodebyte(char p_char, size_t *p_i) { + for (*p_i = 0; *p_i < LEN(utfmask); ++(*p_i)) { + if (((uchar)p_char & utfmask[*p_i]) == utfbyte[*p_i]) + return (uchar)p_char & ~utfmask[*p_i]; } return 0; } -size_t utf8encode(Rune u, char *c) { +/** + * Encode a UTF-8 rune + * + * @param p_rune rune to encode + * @param p_char char array to encode to + * @return + */ +size_t utf8encode(Rune p_rune, char *p_char) { size_t len, i; - len = utf8validate(&u, 0); + len = utf8validate(&p_rune, 0); if (len > UTF_SIZE) return 0; for (i = len - 1; i != 0; --i) { - c[i] = utf8encodebyte(u, 0); - u >>= 6; + p_char[i] = utf8encodebyte(p_rune, 0); + p_rune >>= 6; } - c[0] = utf8encodebyte(u, len); + p_char[0] = utf8encodebyte(p_rune, len); return len; } char utf8encodebyte(Rune u, size_t i) { return utfbyte[i] | (u & ~utfmask[i]); } -size_t utf8validate(Rune *u, size_t i) { - if (!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF)) - *u = UTF_INVALID; - for (i = 1; *u > utfmax[i]; ++i) - ; +/** + * Check if a given rune is a valid UTF-8 rune + * + * @param p_rune rune to validate + * @param i + */ +size_t utf8validate(Rune *p_rune, size_t i) { + if (!BETWEEN(*p_rune, utfmin[i], utfmax[i]) || BETWEEN(*p_rune, 0xD800, 0xDFFF)) + *p_rune = UTF_INVALID; + + // Count up i until you find a utfmax entry that's greater than *p_rune + for (i = 1; *p_rune > utfmax[i]; ++i); return i; } From 25af8ba5fcec5fc690469e5600835505006981de Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Wed, 2 Dec 2020 15:07:29 +0100 Subject: [PATCH 04/11] Merged stash --- CHANGELOG.md | 4 ++-- Makefile | 22 +++++++++++----------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 92e2575..3bace10 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## v0.1 * Switched build to CMake * Completely overhauled code structure +* Add a desktop entry when installing + based on [desktopentry](https://st.suckless.org/patches/desktopentry/) ## v0.2 * Configurable transparency (focused and unfocused) @@ -11,8 +13,6 @@ based on [anysize](https://st.suckless.org/patches/anysize/) * Copy to clipboard on selection based on [one clipboard](https://st.suckless.org/patches/clipboard/) -* Add a desktop entry when installing - based on [desktopentry](https://st.suckless.org/patches/desktopentry/) ## v0.3 * Add better/gapless rendering of lines/blocks diff --git a/Makefile b/Makefile index 5ba4d9a..da3b99c 100644 --- a/Makefile +++ b/Makefile @@ -16,20 +16,20 @@ all: debug # =====INSTALL & UNINSTALL===== install: release - mkdir -p $(DESTDIR)$(PREFIX)/bin - cp -f build/release/stj $(DESTDIR)$(PREFIX)/bin - chmod 755 $(DESTDIR)$(PREFIX)/bin/stj - mkdir -p $(DESTDIR)$(MANPREFIX)/man1 - sed "s/VERSION/$(VERSION)/g" < data/stj.1 > $(DESTDIR)$(MANPREFIX)/man1/stj.1 - chmod 644 $(DESTDIR)$(MANPREFIX)/man1/stj.1 - tic -sx data/stj.info - cp -f data/stj.desktop $(DESTDIR)$(PREFIX)/share/applications + @ mkdir -p '$(DESTDIR)$(PREFIX)/bin' + @ cp -f '$(RELEASE_DIR)/$(BINARY)' '$(DESTDIR)$(PREFIX)/bin' + @ chmod 755 '$(DESTDIR)$(PREFIX)/bin/$(BINARY)' + @ mkdir -p '$(DESTDIR)$(MANPREFIX)/man1' + @ sed "s/VERSION/$(VERSION)/g" < 'data/stj.1' > '$(DESTDIR)$(MANPREFIX)/man1/$(BINARY).1' + @ chmod 644 '$(DESTDIR)$(MANPREFIX)/man1/$(BINARY).1' + @ tic -sx 'data/stj.info' + @ cp -f 'data/$(BINARY).desktop' '$(DESTDIR)$(PREFIX)/share/applications' .PHONY: install uninstall: - rm -f $(DESTDIR)$(PREFIX)/bin/stj - rm -f $(DESTDIR)$(MANPREFIX)/man1/stj.1 - rm -f $(DESTDIR)$(PREFIX)/share/applications/stj.desktop + @ rm -f '$(DESTDIR)$(PREFIX)/bin/$(BINARY)' + @ rm -f '$(DESTDIR)$(MANPREFIX)/man1/$(BINARY).1' + @ rm -f '$(DESTDIR)$(PREFIX)/share/applications/$(BINARY).desktop' .PHONY: uninstall From 010fb66cb63b89ebf5bc9f9ed9b7e1d359a78f78 Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Wed, 2 Dec 2020 16:09:09 +0100 Subject: [PATCH 05/11] Split off utf8 encoding --- src/CMakeLists.txt | 18 +++----- src/st/st.c | 105 +-------------------------------------------- src/st/st.h | 9 ++-- src/st/types.h | 9 ++++ src/st/utf8.c | 101 +++++++++++++++++++++++++++++++++++++++++++ src/st/utf8.h | 17 ++++++++ 6 files changed, 137 insertions(+), 122 deletions(-) create mode 100644 src/st/types.h create mode 100644 src/st/utf8.c create mode 100644 src/st/utf8.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3070223..eccfe00 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -8,20 +8,18 @@ endif() set(SYSTEM_TYPE x64) -# =====COMPILER===== +# =====COMMON SETTINGS===== set(CMAKE_C_COMPILER "clang-11") set(CMAKE_C_STANDARD 11) - project(stj VERSION 0.1) - -# =====COMPILE FLAGS===== add_definitions(-DVERSION="${CMAKE_PROJECT_VERSION}" -D_XOPEN_SOURCE=600) -# Debug flags -# -g flag gets auto-added by CMake for the debug build -set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -g -Weverything -O0 -fsanitize=address -fno-omit-frame-pointer") + +# =====BUILD TYPES===== +# Debug +set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -g -Wall -O0 -fsanitize=address -fno-omit-frame-pointer") set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address -pedantic") # Arch doesn't use static libraries @@ -30,13 +28,9 @@ if(NOT EXISTS "/etc/arch-release") set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} -static-libasan") endif() -# Release flags +# Release set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O3 -Werror -pedantic-errors") -# MinSizeRel flags -# This one's just here for fun -set(CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL} -Oz -Werror -pedantic-errors") - # =====EXECUTABLE===== file(GLOB st_SRC "st/*.c" "st/*.h") diff --git a/src/st/st.c b/src/st/st.c index c39ffa9..4f1ee8e 100644 --- a/src/st/st.c +++ b/src/st/st.c @@ -17,6 +17,7 @@ #include #include +#include "utf8.h" #include "../win.h" #include "macros.h" #include "st.h" @@ -30,8 +31,6 @@ #endif /* Arbitrary sizes */ -#define UTF_INVALID 0xFFFD -#define UTF_SIZE 4 #define ESC_BUF_SIZ (128 * UTF_SIZE) #define ESC_ARG_SIZ 16 #define STR_BUF_SIZ ESC_BUF_SIZ @@ -205,10 +204,6 @@ static void selnormalize(void); static void selscroll(int, int); static void selsnap(int *, int *, int); -static size_t utf8decode(const char *, Rune *, size_t); -static Rune utf8decodebyte(char, size_t *); -static char utf8encodebyte(Rune, size_t); -static size_t utf8validate(Rune *, size_t); static char *base64dec(const char *); static char base64dec_getc(const char **); @@ -224,11 +219,6 @@ static int iofd = 1; static int cmdfd; static pid_t pid; -static uchar utfbyte[UTF_SIZE + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0}; -static uchar utfmask[UTF_SIZE + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; -static Rune utfmin[UTF_SIZE + 1] = {0, 0, 0x80, 0x800, 0x10000}; -static Rune utfmax[UTF_SIZE + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; - /** * Same as write, but ensures that all bytes are written to the descriptor * (write sometimes isn't able to write all bytes) @@ -299,99 +289,6 @@ char *safe_strdup(char *p_str) { return p_str; } -/** - * Decode a given char array into a utf8 Rune - * - * @param p_char char array to decode - * @param p_rune rune pointer to decode to - * @param p_char_len length of the char array - * @return size of the decoded rune - */ -size_t utf8decode(const char *p_char, Rune *p_rune, size_t p_char_len) { - size_t decoded_len, type, i; - Rune decoded_rune; - - *p_rune = UTF_INVALID; - if (!p_char_len) // p_char_len is 0, so just return 0 - return 0; - - decoded_rune = utf8decodebyte(p_char[0], &decoded_len); - if (!BETWEEN(decoded_len, 1, UTF_SIZE)) - return 1; - - for (i = 1; i < p_char_len && i < decoded_len; ++i) { - decoded_rune = (decoded_rune << 6) | utf8decodebyte(p_char[i], &type); - - if (type != 0) - return i; - } - - if (i < decoded_len) - return 0; - - *p_rune = decoded_rune; - utf8validate(p_rune, decoded_len); - - return decoded_len; -} - -/** - * Decode a single byte to UTF-8 - * - * @param p_char char to decode - * @param p_i counter used in internal for loop - * @return decoded rune - */ -Rune utf8decodebyte(char p_char, size_t *p_i) { - for (*p_i = 0; *p_i < LEN(utfmask); ++(*p_i)) { - if (((uchar)p_char & utfmask[*p_i]) == utfbyte[*p_i]) - return (uchar)p_char & ~utfmask[*p_i]; - } - - return 0; -} - -/** - * Encode a UTF-8 rune - * - * @param p_rune rune to encode - * @param p_char char array to encode to - * @return - */ -size_t utf8encode(Rune p_rune, char *p_char) { - size_t len, i; - - len = utf8validate(&p_rune, 0); - if (len > UTF_SIZE) - return 0; - - for (i = len - 1; i != 0; --i) { - p_char[i] = utf8encodebyte(p_rune, 0); - p_rune >>= 6; - } - p_char[0] = utf8encodebyte(p_rune, len); - - return len; -} - -char utf8encodebyte(Rune u, size_t i) { return utfbyte[i] | (u & ~utfmask[i]); } - -/** - * Check if a given rune is a valid UTF-8 rune - * - * @param p_rune rune to validate - * @param i - */ -size_t utf8validate(Rune *p_rune, size_t i) { - if (!BETWEEN(*p_rune, utfmin[i], utfmax[i]) || BETWEEN(*p_rune, 0xD800, 0xDFFF)) - *p_rune = UTF_INVALID; - - // Count up i until you find a utfmax entry that's greater than *p_rune - for (i = 1; *p_rune > utfmax[i]; ++i); - - return i; -} - static const char base64_digits[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, diff --git a/src/st/st.h b/src/st/st.h index 48d47f6..a5667da 100644 --- a/src/st/st.h +++ b/src/st/st.h @@ -7,6 +7,9 @@ #include #include +#include "types.h" +#include "utf8.h" + enum glyph_attribute { ATTR_NULL = 0, ATTR_BOLD = 1 << 0, @@ -29,12 +32,6 @@ enum selection_type { SEL_REGULAR = 1, SEL_RECTANGULAR = 2 }; enum selection_snap { SNAP_WORD = 1, SNAP_LINE = 2 }; -typedef unsigned char uchar; -typedef unsigned int uint; -typedef unsigned long ulong; -typedef unsigned short ushort; - -typedef uint_least32_t Rune; #define Glyph Glyph_ typedef struct { diff --git a/src/st/types.h b/src/st/types.h new file mode 100644 index 0000000..70b6794 --- /dev/null +++ b/src/st/types.h @@ -0,0 +1,9 @@ +#ifndef TYPES_H +#define TYPES_H + +typedef unsigned char uchar; +typedef unsigned int uint; +typedef unsigned long ulong; +typedef unsigned short ushort; + +#endif diff --git a/src/st/utf8.c b/src/st/utf8.c new file mode 100644 index 0000000..f6e3a08 --- /dev/null +++ b/src/st/utf8.c @@ -0,0 +1,101 @@ +#include "utf8.h" +#include "macros.h" +#include "types.h" + +static uchar utfbyte[UTF_SIZE + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0}; +static uchar utfmask[UTF_SIZE + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; +static Rune utfmin[UTF_SIZE + 1] = {0, 0, 0x80, 0x800, 0x10000}; +static Rune utfmax[UTF_SIZE + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; + +/** + * Decode a given char array into a utf8 Rune + * + * @param p_char char array to decode + * @param p_rune rune pointer to decode to + * @param p_char_len length of the char array + * @return size of the decoded rune + */ +size_t utf8decode(const char *p_char, Rune *p_rune, size_t p_char_len) { + size_t decoded_len, type, i; + Rune decoded_rune; + + *p_rune = UTF_INVALID; + if (!p_char_len) // p_char_len is 0, so just return 0 + return 0; + + decoded_rune = utf8decodebyte(p_char[0], &decoded_len); + if (!BETWEEN(decoded_len, 1, UTF_SIZE)) + return 1; + + for (i = 1; i < p_char_len && i < decoded_len; ++i) { + decoded_rune = (decoded_rune << 6) | utf8decodebyte(p_char[i], &type); + + if (type != 0) + return i; + } + + if (i < decoded_len) + return 0; + + *p_rune = decoded_rune; + utf8validate(p_rune, decoded_len); + + return decoded_len; +} + +/** + * Decode a single byte to UTF-8 + * + * @param p_char char to decode + * @param p_i counter used in internal for loop + * @return decoded rune + */ +Rune utf8decodebyte(char p_char, size_t *p_i) { + for (*p_i = 0; *p_i < LEN(utfmask); ++(*p_i)) { + if (((uchar)p_char & utfmask[*p_i]) == utfbyte[*p_i]) + return (uchar)p_char & ~utfmask[*p_i]; + } + + return 0; +} + +/** + * Encode a UTF-8 rune + * + * @param p_rune rune to encode + * @param p_char char array to encode to + * @return + */ +size_t utf8encode(Rune p_rune, char *p_char) { + size_t len, i; + + len = utf8validate(&p_rune, 0); + if (len > UTF_SIZE) + return 0; + + for (i = len - 1; i != 0; --i) { + p_char[i] = utf8encodebyte(p_rune, 0); + p_rune >>= 6; + } + p_char[0] = utf8encodebyte(p_rune, len); + + return len; +} + +char utf8encodebyte(Rune u, size_t i) { return utfbyte[i] | (u & ~utfmask[i]); } + +/** + * Check if a given rune is a valid UTF-8 rune + * + * @param p_rune rune to validate + * @param i + */ +size_t utf8validate(Rune *p_rune, size_t i) { + if (!BETWEEN(*p_rune, utfmin[i], utfmax[i]) || BETWEEN(*p_rune, 0xD800, 0xDFFF)) + *p_rune = UTF_INVALID; + + // Count up i until you find a utfmax entry that's greater than *p_rune + for (i = 1; *p_rune > utfmax[i]; ++i); + + return i; +} diff --git a/src/st/utf8.h b/src/st/utf8.h new file mode 100644 index 0000000..ed8e5c1 --- /dev/null +++ b/src/st/utf8.h @@ -0,0 +1,17 @@ +#ifndef UTF8_H +#define UTF8_H + +#include +#include + +#define UTF_INVALID 0xFFFD +#define UTF_SIZE 4 + +typedef uint_least32_t Rune; + +size_t utf8decode(const char *, Rune *, size_t); +Rune utf8decodebyte(char, size_t *); +char utf8encodebyte(Rune, size_t); +size_t utf8validate(Rune *, size_t); + +#endif From 39fd726a5144cfc1c86ab24e4fcc6eaa24525fb1 Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Thu, 3 Dec 2020 15:44:46 +0100 Subject: [PATCH 06/11] Initial split (non-working) --- CHANGELOG.md | 2 ++ src/st/selection.c | 68 ++++++++++++++++++++++++++++++++++++ src/st/selection.h | 36 +++++++++++++++++++ src/st/st.c | 86 ++-------------------------------------------- src/st/st.h | 7 ---- src/st/utf8.c | 10 +++--- src/st/utf8.h | 2 +- 7 files changed, 115 insertions(+), 96 deletions(-) create mode 100644 src/st/selection.c create mode 100644 src/st/selection.h diff --git a/CHANGELOG.md b/CHANGELOG.md index 3bace10..08769c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## v0.1 * Switched build to CMake * Completely overhauled code structure + * Separate code into logical blocks + * Purge global variables as much as possible * Add a desktop entry when installing based on [desktopentry](https://st.suckless.org/patches/desktopentry/) diff --git a/src/st/selection.c b/src/st/selection.c new file mode 100644 index 0000000..fd03117 --- /dev/null +++ b/src/st/selection.c @@ -0,0 +1,68 @@ +#include "selection.h" +#include "macros.h" + +void selnormalize() { + int i; + + if (sel.type == SEL_REGULAR && sel.ob.y != sel.oe.y) { + sel.nb.x = sel.ob.y < sel.oe.y ? sel.ob.x : sel.oe.x; + sel.ne.x = sel.ob.y < sel.oe.y ? sel.oe.x : sel.ob.x; + + } else { + sel.nb.x = MIN(sel.ob.x, sel.oe.x); + sel.ne.x = MAX(sel.ob.x, sel.oe.x); + } + + sel.nb.y = MIN(sel.ob.y, sel.oe.y); + sel.ne.y = MAX(sel.ob.y, sel.oe.y); + + selsnap(&sel.nb.x, &sel.nb.y, -1); + selsnap(&sel.ne.x, &sel.ne.y, +1); + + /* expand selection over line breaks */ + if (sel.type == SEL_RECTANGULAR) + return; + + i = tlinelen(sel.nb.y); + if (i < sel.nb.x) + sel.nb.x = i; + + if (tlinelen(sel.ne.y) <= sel.ne.x) + sel.ne.x = term.col - 1; +} + +void selscroll(int orig, int n) { + if (sel.ob.x == -1) + return; + + if (BETWEEN(sel.nb.y, orig, term.bot) != + BETWEEN(sel.ne.y, orig, term.bot)) { + selclear(); + + } else if (BETWEEN(sel.nb.y, orig, term.bot)) { + sel.ob.y += n; + sel.oe.y += n; + + if (sel.ob.y < term.top || sel.ob.y > term.bot || sel.oe.y < term.top || + sel.oe.y > term.bot) { + selclear(); + + } else { + selnormalize(); + } + } +} + +void selclear(void) { + if (sel.ob.x == -1) + return; + sel.mode = SEL_IDLE; + sel.ob.x = -1; + tsetdirt(sel.nb.y, sel.ne.y); +} + +void selinit(void) { + sel.mode = SEL_IDLE; + sel.snap = 0; + sel.ob.x = -1; +} diff --git a/src/st/selection.h b/src/st/selection.h new file mode 100644 index 0000000..97cdbe3 --- /dev/null +++ b/src/st/selection.h @@ -0,0 +1,36 @@ +#ifndef SELECTION_H +#define SELECTION_H + +enum selection_mode { SEL_IDLE = 0, SEL_EMPTY = 1, SEL_READY = 2 }; +enum selection_type { SEL_REGULAR = 1, SEL_RECTANGULAR = 2 }; +enum selection_snap { SNAP_WORD = 1, SNAP_LINE = 2 }; + +typedef struct { + int mode; + int type; + int snap; + /* + * Selection variables: + * nb – normalized coordinates of the beginning of the selection + * ne – normalized coordinates of the end of the selection + * ob – original coordinates of the beginning of the selection + * oe – original coordinates of the end of the selection + */ + struct { + int x, y; + } nb, ne, ob, oe; + + int alt; +} Selection; + +void selinit(void); +void selstart(int, int, int); +void selnormalize(); +void selscroll(int, int); +void selsnap(int *, int *, int); +void selclear(void); + +// Global variable for now +static Selection sel; + +#endif diff --git a/src/st/st.c b/src/st/st.c index 4f1ee8e..22f7fe0 100644 --- a/src/st/st.c +++ b/src/st/st.c @@ -17,10 +17,11 @@ #include #include -#include "utf8.h" #include "../win.h" #include "macros.h" +#include "selection.h" #include "st.h" +#include "utf8.h" #if defined(__linux) #include @@ -88,24 +89,6 @@ typedef struct { char state; } TCursor; -typedef struct { - int mode; - int type; - int snap; - /* - * Selection variables: - * nb – normalized coordinates of the beginning of the selection - * ne – normalized coordinates of the end of the selection - * ob – original coordinates of the beginning of the selection - * oe – original coordinates of the end of the selection - */ - struct { - int x, y; - } nb, ne, ob, oe; - - int alt; -} Selection; - /* Internal representation of the screen */ typedef struct { int row; /* nb row */ @@ -200,11 +183,6 @@ static void tstrsequence(uchar); static void drawregion(int, int, int, int); -static void selnormalize(void); -static void selscroll(int, int); -static void selsnap(int *, int *, int); - - static char *base64dec(const char *); static char base64dec_getc(const char **); @@ -212,7 +190,6 @@ static ssize_t xwrite(int, const char *, size_t); /* Globals */ static Term term; -static Selection sel; static CSIEscape csiescseq; static STREscape strescseq; static int iofd = 1; @@ -340,12 +317,6 @@ char *base64dec(const char *src) { return result; } -void selinit(void) { - sel.mode = SEL_IDLE; - sel.snap = 0; - sel.ob.x = -1; -} - int tlinelen(int y) { int i = term.col; @@ -401,32 +372,6 @@ void selextend(int col, int row, int type, int done) { sel.mode = done ? SEL_IDLE : SEL_READY; } -void selnormalize(void) { - int i; - - if (sel.type == SEL_REGULAR && sel.ob.y != sel.oe.y) { - sel.nb.x = sel.ob.y < sel.oe.y ? sel.ob.x : sel.oe.x; - sel.ne.x = sel.ob.y < sel.oe.y ? sel.oe.x : sel.ob.x; - } else { - sel.nb.x = MIN(sel.ob.x, sel.oe.x); - sel.ne.x = MAX(sel.ob.x, sel.oe.x); - } - sel.nb.y = MIN(sel.ob.y, sel.oe.y); - sel.ne.y = MAX(sel.ob.y, sel.oe.y); - - selsnap(&sel.nb.x, &sel.nb.y, -1); - selsnap(&sel.ne.x, &sel.ne.y, +1); - - /* expand selection over line breaks */ - if (sel.type == SEL_RECTANGULAR) - return; - i = tlinelen(sel.nb.y); - if (i < sel.nb.x) - sel.nb.x = i; - if (tlinelen(sel.ne.y) <= sel.ne.x) - sel.ne.x = term.col - 1; -} - int selected(int x, int y) { if (sel.mode == SEL_EMPTY || sel.ob.x == -1 || sel.alt != IS_SET(MODE_ALTSCREEN)) @@ -561,14 +506,6 @@ char *getsel(void) { return str; } -void selclear(void) { - if (sel.ob.x == -1) - return; - sel.mode = SEL_IDLE; - sel.ob.x = -1; - tsetdirt(sel.nb.y, sel.ne.y); -} - void die(const char *errstr, ...) { va_list ap; @@ -970,25 +907,6 @@ void tscrollup(int orig, int n) { selscroll(orig, -n); } -void selscroll(int orig, int n) { - if (sel.ob.x == -1) - return; - - if (BETWEEN(sel.nb.y, orig, term.bot) != - BETWEEN(sel.ne.y, orig, term.bot)) { - selclear(); - } else if (BETWEEN(sel.nb.y, orig, term.bot)) { - sel.ob.y += n; - sel.oe.y += n; - if (sel.ob.y < term.top || sel.ob.y > term.bot || sel.oe.y < term.top || - sel.oe.y > term.bot) { - selclear(); - } else { - selnormalize(); - } - } -} - void tnewline(int first_col) { int y = term.c.y; diff --git a/src/st/st.h b/src/st/st.h index a5667da..f177c08 100644 --- a/src/st/st.h +++ b/src/st/st.h @@ -26,13 +26,6 @@ enum glyph_attribute { ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT, }; -enum selection_mode { SEL_IDLE = 0, SEL_EMPTY = 1, SEL_READY = 2 }; - -enum selection_type { SEL_REGULAR = 1, SEL_RECTANGULAR = 2 }; - -enum selection_snap { SNAP_WORD = 1, SNAP_LINE = 2 }; - - #define Glyph Glyph_ typedef struct { Rune u; /* character code */ diff --git a/src/st/utf8.c b/src/st/utf8.c index f6e3a08..c9553b2 100644 --- a/src/st/utf8.c +++ b/src/st/utf8.c @@ -64,7 +64,7 @@ Rune utf8decodebyte(char p_char, size_t *p_i) { * * @param p_rune rune to encode * @param p_char char array to encode to - * @return + * @return */ size_t utf8encode(Rune p_rune, char *p_char) { size_t len, i; @@ -88,14 +88,16 @@ char utf8encodebyte(Rune u, size_t i) { return utfbyte[i] | (u & ~utfmask[i]); } * Check if a given rune is a valid UTF-8 rune * * @param p_rune rune to validate - * @param i + * @param i */ size_t utf8validate(Rune *p_rune, size_t i) { - if (!BETWEEN(*p_rune, utfmin[i], utfmax[i]) || BETWEEN(*p_rune, 0xD800, 0xDFFF)) + if (!BETWEEN(*p_rune, utfmin[i], utfmax[i]) || + BETWEEN(*p_rune, 0xD800, 0xDFFF)) *p_rune = UTF_INVALID; // Count up i until you find a utfmax entry that's greater than *p_rune - for (i = 1; *p_rune > utfmax[i]; ++i); + for (i = 1; *p_rune > utfmax[i]; ++i) + ; return i; } diff --git a/src/st/utf8.h b/src/st/utf8.h index ed8e5c1..343fd8e 100644 --- a/src/st/utf8.h +++ b/src/st/utf8.h @@ -1,8 +1,8 @@ #ifndef UTF8_H #define UTF8_H -#include #include +#include #define UTF_INVALID 0xFFFD #define UTF_SIZE 4 From 8d792bbc508fc6e3aa11d205095136d6466f2d22 Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Sat, 26 Dec 2020 11:26:08 +0100 Subject: [PATCH 07/11] Fixed clang-format; updated cmakelists --- .clang-format | 150 ++- .hooks/pre-commit | 3 + CHANGELOG.md | 8 +- Makefile | 5 +- src/CMakeLists.txt | 7 +- src/arg.h | 60 +- src/config.def.h | 19 +- src/config.h | 19 +- src/st/macros.h | 18 +- src/st/selection.c | 4 +- src/st/st.c | 372 +++--- src/st/st.h | 80 +- src/st/types.h | 6 +- src/st/utf8.c | 10 +- src/st/utf8.h | 6 +- src/win.h | 46 +- src/x.c | 2730 ++++++++++++++++++++++---------------------- 17 files changed, 1858 insertions(+), 1685 deletions(-) create mode 100755 .hooks/pre-commit diff --git a/.clang-format b/.clang-format index 39f9642..76f9685 100644 --- a/.clang-format +++ b/.clang-format @@ -1 +1,149 @@ -IndentWidth: 4 +--- +Language: Cpp +# BasedOnStyle: LLVM +AccessModifierOffset: -2 +AlignAfterOpenBracket: Align +AlignConsecutiveMacros: true +AlignConsecutiveAssignments: true +AlignConsecutiveBitFields: true +AlignConsecutiveDeclarations: true +AlignEscapedNewlines: Right +AlignOperands: Align +AlignTrailingComments: true +AllowAllArgumentsOnNextLine: true +AllowAllConstructorInitializersOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortEnumsOnASingleLine: true +AllowShortBlocksOnASingleLine: Never +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: All +AllowShortLambdasOnASingleLine: All +AllowShortIfStatementsOnASingleLine: Never +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: MultiLine +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterCaseLabel: false + AfterClass: false + AfterControlStatement: Never + AfterEnum: false + AfterFunction: false + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + AfterExternBlock: false + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Attach +BreakBeforeInheritanceComma: false +BreakInheritanceList: BeforeColon +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeColon +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +ColumnLimit: 79 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DeriveLineEnding: true +DerivePointerAlignment: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^"(llvm|llvm-c|clang|clang-c)/' + Priority: 2 + SortPriority: 0 + - Regex: '^(<|"(gtest|gmock|isl|json)/)' + Priority: 3 + SortPriority: 0 + - Regex: '.*' + Priority: 1 + SortPriority: 0 +IncludeIsMainRegex: '(Test)?$' +IncludeIsMainSourceRegex: '' +IndentCaseLabels: false +IndentCaseBlocks: false +IndentGotoLabels: true +IndentPPDirectives: None +IndentExternBlock: AfterExternBlock +IndentWidth: 4 +IndentWrappedFunctionNames: false +InsertTrailingCommas: None +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: true +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Auto +ObjCBlockIndentWidth: 2 +ObjCBreakBeforeNestedBlockParam: true +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 60 +PointerAlignment: Right +ReflowComments: true +SortIncludes: true +SortUsingDeclarations: true +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyBlock: false +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInConditionalStatement: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +SpaceBeforeSquareBrackets: false +Standard: Latest +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TabWidth: 4 +UseCRLF: false +UseTab: Never +WhitespaceSensitiveMacros: + - STRINGIZE + - PP_STRINGIZE + - BOOST_PP_STRINGIZE +... + diff --git a/.hooks/pre-commit b/.hooks/pre-commit new file mode 100755 index 0000000..6a9ebca --- /dev/null +++ b/.hooks/pre-commit @@ -0,0 +1,3 @@ +#!/usr/bin/env sh + +make format diff --git a/CHANGELOG.md b/CHANGELOG.md index 08769c4..69aed67 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,5 @@ # Upcoming -## v0.1 +## v1.0 * Switched build to CMake * Completely overhauled code structure * Separate code into logical blocks @@ -7,7 +7,7 @@ * Add a desktop entry when installing based on [desktopentry](https://st.suckless.org/patches/desktopentry/) -## v0.2 +## v1.1 * Configurable transparency (focused and unfocused) based on [alpha](https://st.suckless.org/patches/alpha/) and [alpha focus highlight](https://st.suckless.org/patches/alpha_focus_highlight/) @@ -16,7 +16,7 @@ * Copy to clipboard on selection based on [one clipboard](https://st.suckless.org/patches/clipboard/) -## v0.3 +## v1.2 * Add better/gapless rendering of lines/blocks based on [boxdraw](https://st.suckless.org/patches/boxdraw/) * Add support for multiple fonts @@ -24,7 +24,7 @@ * Hide cursor when working in the terminal based on [hidecursor](https://st.suckless.org/patches/hidecursor/) -## v0.4 +## v2.0 * Add ligature support based on [ligature support](https://st.suckless.org/patches/ligatures/) * Support for multiple color pallets diff --git a/Makefile b/Makefile index da3b99c..5a000ae 100644 --- a/Makefile +++ b/Makefile @@ -10,6 +10,9 @@ PREFIX := /usr/local MANPREFIX := $(PREFIX)/share/man +SHELL := $(shell which sh) + + all: debug .PHONY: all @@ -90,4 +93,4 @@ clean-debug: # =====FORMAT CODE===== format: - @ clang-format -i --style=file src/**/*.c src/**/*.h + @ clang-format -i --style=file src/**/*.c src/**/*.h src/*.c src/*.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index eccfe00..a92291c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -19,7 +19,7 @@ add_definitions(-DVERSION="${CMAKE_PROJECT_VERSION}" -D_XOPEN_SOURCE=600) # =====BUILD TYPES===== # Debug -set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -g -Wall -O0 -fsanitize=address -fno-omit-frame-pointer") +set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wall -O0 -fsanitize=address -fno-omit-frame-pointer") set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address -pedantic") # Arch doesn't use static libraries @@ -43,8 +43,6 @@ add_executable(stj x.c "${st_SRC}" "${main_SRC}") find_package(Freetype 2 REQUIRED) target_include_directories(stj PRIVATE "${FREETYPE_INCLUDE_DIRS}") target_link_libraries(stj PRIVATE "${FREETYPE_LIBRARIES}") -target_link_libraries(stj PRIVATE Xft) -target_link_libraries(stj PRIVATE Xrender) find_package(Fontconfig 2 REQUIRED) target_include_directories(stj PRIVATE "${Fontconfig_INCLUDE_DIRS}") @@ -53,6 +51,9 @@ target_link_libraries(stj PRIVATE "${Fontconfig_LIBRARIES}") find_package(X11 REQUIRED) target_include_directories(stj PRIVATE "${X11_INCLUDE_DIR}") target_link_libraries(stj PRIVATE "${X11_LIBRARIES}") +# TODO Find out if these are included in the above statement or not +# target_link_libraries(stj PRIVATE Xft) +# target_link_libraries(stj PRIVATE Xrender) # Normally provided with clang target_link_libraries(stj PRIVATE m) diff --git a/src/arg.h b/src/arg.h index f1c31e0..9fa5d83 100644 --- a/src/arg.h +++ b/src/arg.h @@ -9,40 +9,40 @@ extern char *argv0; /* use main(int argc, char *argv[]) */ -#define ARGBEGIN \ - for (argv0 = *argv, argv++, argc--; \ - argv[0] && argv[0][0] == '-' && argv[0][1]; argc--, argv++) { \ - char argc_; \ - char **argv_; \ - int brk_; \ - if (argv[0][1] == '-' && argv[0][2] == '\0') { \ - argv++; \ - argc--; \ - break; \ - } \ - int i_; \ - for (i_ = 1, brk_ = 0, argv_ = argv; argv[0][i_] && !brk_; i_++) { \ - if (argv_ != argv) \ - break; \ - argc_ = argv[0][i_]; \ - switch (argc_) +#define ARGBEGIN \ + for (argv0 = *argv, argv++, argc--; \ + argv[0] && argv[0][0] == '-' && argv[0][1]; argc--, argv++) { \ + char argc_; \ + char **argv_; \ + int brk_; \ + if (argv[0][1] == '-' && argv[0][2] == '\0') { \ + argv++; \ + argc--; \ + break; \ + } \ + int i_; \ + for (i_ = 1, brk_ = 0, argv_ = argv; argv[0][i_] && !brk_; i_++) { \ + if (argv_ != argv) \ + break; \ + argc_ = argv[0][i_]; \ + switch (argc_) -#define ARGEND \ - } \ - } +#define ARGEND \ + } \ + } #define ARGC() argc_ -#define EARGF(x) \ - ((argv[0][i_ + 1] == '\0' && argv[1] == NULL) \ - ? ((x), abort(), (char *)0) \ - : (brk_ = 1, (argv[0][i_ + 1] != '\0') ? (&argv[0][i_ + 1]) \ - : (argc--, argv++, argv[0]))) +#define EARGF(x) \ + ((argv[0][i_ + 1] == '\0' && argv[1] == NULL) \ + ? ((x), abort(), (char *)0) \ + : (brk_ = 1, (argv[0][i_ + 1] != '\0') ? (&argv[0][i_ + 1]) \ + : (argc--, argv++, argv[0]))) -#define ARGF() \ - ((argv[0][i_ + 1] == '\0' && argv[1] == NULL) \ - ? (char *)0 \ - : (brk_ = 1, (argv[0][i_ + 1] != '\0') ? (&argv[0][i_ + 1]) \ - : (argc--, argv++, argv[0]))) +#define ARGF() \ + ((argv[0][i_ + 1] == '\0' && argv[1] == NULL) \ + ? (char *)0 \ + : (brk_ = 1, (argv[0][i_ + 1] != '\0') ? (&argv[0][i_ + 1]) \ + : (argc--, argv++, argv[0]))) #endif diff --git a/src/config.def.h b/src/config.def.h index ab961c4..d66625c 100644 --- a/src/config.def.h +++ b/src/config.def.h @@ -5,7 +5,8 @@ * * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html */ -static char *font = "Liberation Mono:pixelsize=12:antialias=true:autohint=true"; +static char *font = + "Liberation Mono:pixelsize=12:antialias=true:autohint=true"; static int borderpx = 2; /* @@ -17,9 +18,9 @@ static int borderpx = 2; * 5: value of shell in config.h */ static char *shell = "/bin/sh"; -char *utmp = NULL; +char * utmp = NULL; /* scroll program: to enable use a string like "scroll" */ -char *scroll = NULL; +char *scroll = NULL; char *stty_args = "stty raw pass8 nl -echo -iexten -cstopb 38400"; /* identification sequence returned in DA and DECID */ @@ -126,9 +127,9 @@ static const char *colorname[] = { * Default colors (colorname index) * foreground, background, cursor, reverse cursor */ -unsigned int defaultfg = 7; -unsigned int defaultbg = 0; -static unsigned int defaultcs = 256; +unsigned int defaultfg = 7; +unsigned int defaultbg = 0; +static unsigned int defaultcs = 256; static unsigned int defaultrcs = 257; /* @@ -151,8 +152,8 @@ static unsigned int rows = 24; * Default colour and shape of the mouse cursor */ static unsigned int mouseshape = XC_xterm; -static unsigned int mousefg = 7; -static unsigned int mousebg = 0; +static unsigned int mousefg = 7; +static unsigned int mousebg = 0; /* * Color used to display font attributes when fontconfig selected a font which @@ -181,7 +182,7 @@ static MouseShortcut mshortcuts[] = { }; /* Internal keyboard shortcuts. */ -#define MODKEY Mod1Mask +#define MODKEY Mod1Mask #define TERMMOD (ControlMask | ShiftMask) static Shortcut shortcuts[] = { diff --git a/src/config.h b/src/config.h index ab961c4..d66625c 100644 --- a/src/config.h +++ b/src/config.h @@ -5,7 +5,8 @@ * * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html */ -static char *font = "Liberation Mono:pixelsize=12:antialias=true:autohint=true"; +static char *font = + "Liberation Mono:pixelsize=12:antialias=true:autohint=true"; static int borderpx = 2; /* @@ -17,9 +18,9 @@ static int borderpx = 2; * 5: value of shell in config.h */ static char *shell = "/bin/sh"; -char *utmp = NULL; +char * utmp = NULL; /* scroll program: to enable use a string like "scroll" */ -char *scroll = NULL; +char *scroll = NULL; char *stty_args = "stty raw pass8 nl -echo -iexten -cstopb 38400"; /* identification sequence returned in DA and DECID */ @@ -126,9 +127,9 @@ static const char *colorname[] = { * Default colors (colorname index) * foreground, background, cursor, reverse cursor */ -unsigned int defaultfg = 7; -unsigned int defaultbg = 0; -static unsigned int defaultcs = 256; +unsigned int defaultfg = 7; +unsigned int defaultbg = 0; +static unsigned int defaultcs = 256; static unsigned int defaultrcs = 257; /* @@ -151,8 +152,8 @@ static unsigned int rows = 24; * Default colour and shape of the mouse cursor */ static unsigned int mouseshape = XC_xterm; -static unsigned int mousefg = 7; -static unsigned int mousebg = 0; +static unsigned int mousefg = 7; +static unsigned int mousebg = 0; /* * Color used to display font attributes when fontconfig selected a font which @@ -181,7 +182,7 @@ static MouseShortcut mshortcuts[] = { }; /* Internal keyboard shortcuts. */ -#define MODKEY Mod1Mask +#define MODKEY Mod1Mask #define TERMMOD (ControlMask | ShiftMask) static Shortcut shortcuts[] = { diff --git a/src/st/macros.h b/src/st/macros.h index 56ab7a7..7f23b9a 100644 --- a/src/st/macros.h +++ b/src/st/macros.h @@ -1,20 +1,20 @@ #ifndef MACROS_H #define MACROS_H -#define MIN(a, b) ((a) < (b) ? (a) : (b)) -#define MAX(a, b) ((a) < (b) ? (b) : (a)) -#define LEN(a) (sizeof(a) / sizeof(a)[0]) +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#define MAX(a, b) ((a) < (b) ? (b) : (a)) +#define LEN(a) (sizeof(a) / sizeof(a)[0]) #define BETWEEN(x, a, b) ((a) <= (x) && (x) <= (b)) -#define DIVCEIL(n, d) (((n) + ((d)-1)) / (d)) -#define DEFAULT(a, b) (a) = (a) ? (a) : (b) -#define LIMIT(x, a, b) (x) = (x) < (a) ? (a) : (x) > (b) ? (b) : (x) -#define ATTRCMP(a, b) \ +#define DIVCEIL(n, d) (((n) + ((d)-1)) / (d)) +#define DEFAULT(a, b) (a) = (a) ? (a) : (b) +#define LIMIT(x, a, b) (x) = (x) < (a) ? (a) : (x) > (b) ? (b) : (x) +#define ATTRCMP(a, b) \ ((a).mode != (b).mode || (a).fg != (b).fg || (a).bg != (b).bg) -#define TIMEDIFF(t1, t2) \ +#define TIMEDIFF(t1, t2) \ ((t1.tv_sec - t2.tv_sec) * 1000 + (t1.tv_nsec - t2.tv_nsec) / 1E6) #define MODBIT(x, set, bit) ((set) ? ((x) |= (bit)) : ((x) &= ~(bit))) #define TRUECOLOR(r, g, b) (1 << 24 | (r) << 16 | (g) << 8 | (b)) -#define IS_TRUECOL(x) (1 << 24 & (x)) +#define IS_TRUECOL(x) (1 << 24 & (x)) #endif diff --git a/src/st/selection.c b/src/st/selection.c index fd03117..e1d695f 100644 --- a/src/st/selection.c +++ b/src/st/selection.c @@ -43,8 +43,8 @@ void selscroll(int orig, int n) { sel.ob.y += n; sel.oe.y += n; - if (sel.ob.y < term.top || sel.ob.y > term.bot || sel.oe.y < term.top || - sel.oe.y > term.bot) { + if (sel.ob.y < term.top || sel.ob.y > term.bot || + sel.oe.y < term.top || sel.oe.y > term.bot) { selclear(); } else { diff --git a/src/st/st.c b/src/st/st.c index 22f7fe0..6c169cf 100644 --- a/src/st/st.c +++ b/src/st/st.c @@ -38,28 +38,28 @@ #define STR_ARG_SIZ ESC_ARG_SIZ /* macros */ -#define IS_SET(flag) ((term.mode & (flag)) != 0) +#define IS_SET(flag) ((term.mode & (flag)) != 0) #define ISCONTROLC0(c) (BETWEEN(c, 0, 0x1f) || (c) == 0x7f) #define ISCONTROLC1(c) (BETWEEN(c, 0x80, 0x9f)) -#define ISCONTROL(c) (ISCONTROLC0(c) || ISCONTROLC1(c)) -#define ISDELIM(u) (u && wcschr(worddelimiters, u)) +#define ISCONTROL(c) (ISCONTROLC0(c) || ISCONTROLC1(c)) +#define ISDELIM(u) (u && wcschr(worddelimiters, u)) enum term_mode { - MODE_WRAP = 1 << 0, - MODE_INSERT = 1 << 1, + MODE_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_CRLF = 1 << 3, + MODE_ECHO = 1 << 4, + MODE_PRINT = 1 << 5, + MODE_UTF8 = 1 << 6, }; enum cursor_movement { CURSOR_SAVE, CURSOR_LOAD }; enum cursor_state { - CURSOR_DEFAULT = 0, + CURSOR_DEFAULT = 0, CURSOR_WRAPNEXT = 1, - CURSOR_ORIGIN = 2 + CURSOR_ORIGIN = 2 }; enum charset { @@ -73,63 +73,63 @@ enum charset { }; enum escape_state { - ESC_START = 1, - ESC_CSI = 2, - ESC_STR = 4, /* DCS, OSC, PM, APC */ + ESC_START = 1, + ESC_CSI = 2, + ESC_STR = 4, /* DCS, OSC, PM, APC */ ESC_ALTCHARSET = 8, - ESC_STR_END = 16, /* a final string was encountered */ - ESC_TEST = 32, /* Enter in test mode */ - ESC_UTF8 = 64, + ESC_STR_END = 16, /* a final string was encountered */ + ESC_TEST = 32, /* Enter in test mode */ + ESC_UTF8 = 64, }; typedef struct { Glyph attr; /* current char attributes */ - int x; - int y; - char state; + int x; + int y; + char state; } TCursor; /* Internal representation of the screen */ typedef struct { - int row; /* nb row */ - int col; /* nb col */ - Line *line; /* screen */ - Line *alt; /* alternate screen */ - int *dirty; /* dirtyness of lines */ - TCursor c; /* cursor */ - int ocx; /* old cursor col */ - int ocy; /* old cursor row */ - int top; /* top scroll limit */ - int bot; /* bottom scroll limit */ - int mode; /* terminal mode flags */ - int esc; /* escape state flags */ - char trantbl[4]; /* charset table translation */ - int charset; /* current charset */ - int icharset; /* selected charset for sequence */ - int *tabs; - Rune lastc; /* last printed char outside of sequence, 0 if control */ + int row; /* nb row */ + int col; /* nb col */ + Line * line; /* screen */ + Line * alt; /* alternate screen */ + int * dirty; /* dirtyness of lines */ + TCursor c; /* cursor */ + int ocx; /* old cursor col */ + int ocy; /* old cursor row */ + int top; /* top scroll limit */ + int bot; /* bottom scroll limit */ + int mode; /* terminal mode flags */ + int esc; /* escape state flags */ + char trantbl[4]; /* charset table translation */ + int charset; /* current charset */ + int icharset; /* selected charset for sequence */ + int * tabs; + Rune lastc; /* last printed char outside of sequence, 0 if control */ } Term; /* CSI Escape sequence structs */ /* ESC '[' [[ [] [;]] []] */ typedef struct { - char buf[ESC_BUF_SIZ]; /* raw string */ - size_t len; /* raw string length */ - char priv; - int arg[ESC_ARG_SIZ]; - int narg; /* nb of args */ - char mode[2]; + char buf[ESC_BUF_SIZ]; /* raw string */ + size_t len; /* raw string length */ + char priv; + int arg[ESC_ARG_SIZ]; + int narg; /* nb of args */ + char mode[2]; } CSIEscape; /* STR Escape sequence structs */ /* ESC type [[ [] [;]] ] ESC '\' */ typedef struct { - char type; /* ESC type ... */ - char *buf; /* allocated raw string */ - size_t siz; /* allocation size */ - size_t len; /* raw string length */ - char *args[STR_ARG_SIZ]; - int narg; /* nb of args */ + char type; /* ESC type ... */ + char * buf; /* allocated raw string */ + size_t siz; /* allocation size */ + size_t len; /* raw string length */ + char * args[STR_ARG_SIZ]; + int narg; /* nb of args */ } STREscape; static void execsh(char *, char **); @@ -141,60 +141,60 @@ static void csidump(void); static void csihandle(void); static void csiparse(void); static void csireset(void); -static int eschandle(uchar); +static int eschandle(uchar); static void strdump(void); static void strhandle(void); static void strparse(void); static void strreset(void); -static void tprinter(char *, size_t); -static void tdumpsel(void); -static void tdumpline(int); -static void tdump(void); -static void tclearregion(int, int, int, int); -static void tcursor(int); -static void tdeletechar(int); -static void tdeleteline(int); -static void tinsertblank(int); -static void tinsertblankline(int); -static int tlinelen(int); -static void tmoveto(int, int); -static void tmoveato(int, int); -static void tnewline(int); -static void tputtab(int); -static void tputc(Rune); -static void treset(void); -static void tscrollup(int, int); -static void tscrolldown(int, int); -static void tsetattr(int *, int); -static void tsetchar(Rune, Glyph *, int, int); -static void tsetdirt(int, int); -static void tsetscroll(int, int); -static void tswapscreen(void); -static void tsetmode(int, int, int *, int); -static int twrite(const char *, int, int); -static void tfulldirt(void); -static void tcontrolcode(uchar); -static void tdectest(char); -static void tdefutf8(char); +static void tprinter(char *, size_t); +static void tdumpsel(void); +static void tdumpline(int); +static void tdump(void); +static void tclearregion(int, int, int, int); +static void tcursor(int); +static void tdeletechar(int); +static void tdeleteline(int); +static void tinsertblank(int); +static void tinsertblankline(int); +static int tlinelen(int); +static void tmoveto(int, int); +static void tmoveato(int, int); +static void tnewline(int); +static void tputtab(int); +static void tputc(Rune); +static void treset(void); +static void tscrollup(int, int); +static void tscrolldown(int, int); +static void tsetattr(int *, int); +static void tsetchar(Rune, Glyph *, int, int); +static void tsetdirt(int, int); +static void tsetscroll(int, int); +static void tswapscreen(void); +static void tsetmode(int, int, int *, int); +static int twrite(const char *, int, int); +static void tfulldirt(void); +static void tcontrolcode(uchar); +static void tdectest(char); +static void tdefutf8(char); static int32_t tdefcolor(int *, int *, int); -static void tdeftran(char); -static void tstrsequence(uchar); +static void tdeftran(char); +static void tstrsequence(uchar); static void drawregion(int, int, int, int); static char *base64dec(const char *); -static char base64dec_getc(const char **); +static char base64dec_getc(const char **); static ssize_t xwrite(int, const char *, size_t); /* Globals */ -static Term term; +static Term term; static CSIEscape csiescseq; static STREscape strescseq; -static int iofd = 1; -static int cmdfd; -static pid_t pid; +static int iofd = 1; +static int cmdfd; +static pid_t pid; /** * Same as write, but ensures that all bytes are written to the descriptor @@ -203,11 +203,11 @@ static pid_t pid; * @param p_file_desc file descriptor to write to; same logic as write * @param p_str char array to write to the file descriptor * @param p_nbytes amount of bytes to write - * @return p_nbytes if the write was successful, otherwise return negative error - * value of write + * @return p_nbytes if the write was successful, otherwise return negative + * error value of write */ ssize_t xwrite(int p_file_desc, const char *p_str, size_t p_nbytes) { - size_t aux = p_nbytes; + size_t aux = p_nbytes; ssize_t result; while (p_nbytes > 0) { @@ -290,7 +290,7 @@ char base64dec_getc(const char **src) { char *base64dec(const char *src) { size_t in_len = strlen(src); - char *result, *dst; + char * result, *dst; if (in_len % 4) in_len += 4 - (in_len % 4); @@ -333,7 +333,7 @@ void selstart(int col, int row, int snap) { selclear(); sel.mode = SEL_EMPTY; sel.type = SEL_REGULAR; - sel.alt = IS_SET(MODE_ALTSCREEN); + sel.alt = IS_SET(MODE_ALTSCREEN); sel.snap = snap; sel.oe.x = sel.ob.x = col; sel.oe.y = sel.ob.y = row; @@ -354,10 +354,10 @@ void selextend(int col, int row, int type, int done) { return; } - oldey = sel.oe.y; - oldex = sel.oe.x; - oldsby = sel.nb.y; - oldsey = sel.ne.y; + oldey = sel.oe.y; + oldex = sel.oe.x; + oldsby = sel.nb.y; + oldsey = sel.ne.y; oldtype = sel.type; sel.oe.x = col; @@ -378,15 +378,17 @@ int selected(int x, int y) { return 0; if (sel.type == SEL_RECTANGULAR) - return BETWEEN(y, sel.nb.y, sel.ne.y) && BETWEEN(x, sel.nb.x, sel.ne.x); + return BETWEEN(y, sel.nb.y, sel.ne.y) && + BETWEEN(x, sel.nb.x, sel.ne.x); - return BETWEEN(y, sel.nb.y, sel.ne.y) && (y != sel.nb.y || x >= sel.nb.x) && + return BETWEEN(y, sel.nb.y, sel.ne.y) && + (y != sel.nb.y || x >= sel.nb.x) && (y != sel.ne.y || x <= sel.ne.x); } void selsnap(int *x, int *y, int direction) { - int newx, newy, xt, yt; - int delim, prevdelim; + int newx, newy, xt, yt; + int delim, prevdelim; Glyph *gp, *prevgp; switch (sel.snap) { @@ -395,7 +397,7 @@ void selsnap(int *x, int *y, int direction) { * Snap around if the word wraps around at the end or * beginning of a line. */ - prevgp = &term.line[*y][*x]; + prevgp = &term.line[*y][*x]; prevdelim = ISDELIM(prevgp->u); for (;;) { newx = *x + direction; @@ -417,15 +419,15 @@ void selsnap(int *x, int *y, int direction) { if (newx >= tlinelen(newy)) break; - gp = &term.line[newy][newx]; + gp = &term.line[newy][newx]; delim = ISDELIM(gp->u); if (!(gp->mode & ATTR_WDUMMY) && (delim != prevdelim || (delim && gp->u != prevgp->u))) break; - *x = newx; - *y = newy; - prevgp = gp; + *x = newx; + *y = newy; + prevgp = gp; prevdelim = delim; } break; @@ -454,8 +456,8 @@ void selsnap(int *x, int *y, int direction) { } char *getsel(void) { - char *str, *ptr; - int y, bufsize, lastx, linelen; + char * str, *ptr; + int y, bufsize, lastx, linelen; Glyph *gp, *last; if (sel.ob.x == -1) @@ -472,10 +474,10 @@ char *getsel(void) { } if (sel.type == SEL_RECTANGULAR) { - gp = &term.line[y][sel.nb.x]; + gp = &term.line[y][sel.nb.x]; lastx = sel.ne.x; } else { - gp = &term.line[y][sel.nb.y == y ? sel.nb.x : 0]; + gp = &term.line[y][sel.nb.y == y ? sel.nb.x : 0]; lastx = (sel.ne.y == y) ? sel.ne.x : term.col - 1; } last = &term.line[y][MIN(lastx, linelen - 1)]; @@ -516,7 +518,7 @@ void die(const char *errstr, ...) { } void execsh(char *cmd, char **args) { - char *sh, *prog, *arg; + char * sh, *prog, *arg; const struct passwd *pw; errno = 0; @@ -532,16 +534,16 @@ void execsh(char *cmd, char **args) { if (args) { prog = args[0]; - arg = NULL; + arg = NULL; } else if (scroll) { prog = scroll; - arg = utmp ? utmp : sh; + arg = utmp ? utmp : sh; } else if (utmp) { prog = utmp; - arg = NULL; + arg = NULL; } else { prog = sh; - arg = NULL; + arg = NULL; } DEFAULT(args, ((char *[]){prog, arg, NULL})); @@ -566,7 +568,7 @@ void execsh(char *cmd, char **args) { } void sigchld(int a) { - int stat; + int stat; pid_t p; if ((p = waitpid(pid, &stat, WNOHANG)) < 0) @@ -583,13 +585,13 @@ void sigchld(int a) { } void stty(char **args) { - char cmd[_POSIX_ARG_MAX], **p, *q, *s; + char cmd[_POSIX_ARG_MAX], **p, *q, *s; size_t n, siz; if ((n = strlen(stty_args)) > sizeof(cmd) - 1) die("incorrect stty parameters\n"); memcpy(cmd, stty_args, n); - q = cmd + n; + q = cmd + n; siz = sizeof(cmd) - n; for (p = args; p && (s = *p); ++p) { if ((n = strlen(s)) > siz - 1) @@ -662,8 +664,8 @@ int ttynew(char *line, char *cmd, char *out, char **args) { size_t ttyread(void) { static char buf[BUFSIZ]; - static int buflen = 0; - int ret, written; + static int buflen = 0; + int ret, written; /* append read bytes to unprocessed bytes */ ret = read(cmdfd, buf + buflen, LEN(buf) - buflen); @@ -711,9 +713,9 @@ void ttywrite(const char *s, size_t n, int may_echo) { } void ttywriteraw(const char *s, size_t n) { - fd_set wfd, rfd; + fd_set wfd, rfd; ssize_t r; - size_t lim = 256; + size_t lim = 256; /* * Remember that we are using a pty, which might be a modem line. @@ -768,8 +770,8 @@ write_error: void ttyresize(int tw, int th) { struct winsize w; - w.ws_row = term.row; - w.ws_col = term.col; + w.ws_row = term.row; + w.ws_col = term.col; w.ws_xpixel = tw; w.ws_ypixel = th; if (ioctl(cmdfd, TIOCSWINSZ, &w) < 0) @@ -821,7 +823,7 @@ void tfulldirt(void) { tsetdirt(0, term.row - 1); } void tcursor(int mode) { static TCursor c[2]; - int alt = IS_SET(MODE_ALTSCREEN); + int alt = IS_SET(MODE_ALTSCREEN); if (mode == CURSOR_SAVE) { c[alt] = term.c; @@ -835,15 +837,15 @@ void treset(void) { uint i; term.c = (TCursor){{.mode = ATTR_NULL, .fg = defaultfg, .bg = defaultbg}, - .x = 0, - .y = 0, + .x = 0, + .y = 0, .state = CURSOR_DEFAULT}; memset(term.tabs, 0, term.col * sizeof(*term.tabs)); for (i = tabspaces; i < term.col; i += tabspaces) term.tabs[i] = 1; - term.top = 0; - term.bot = term.row - 1; + term.top = 0; + term.bot = term.row - 1; term.mode = MODE_WRAP | MODE_UTF8; memset(term.trantbl, CS_USA, sizeof(term.trantbl)); term.charset = 0; @@ -866,13 +868,13 @@ void tswapscreen(void) { Line *tmp = term.line; term.line = term.alt; - term.alt = tmp; + term.alt = tmp; term.mode ^= MODE_ALTSCREEN; tfulldirt(); } void tscrolldown(int orig, int n) { - int i; + int i; Line temp; LIMIT(n, 0, term.bot - orig + 1); @@ -881,8 +883,8 @@ void tscrolldown(int orig, int n) { tclearregion(0, term.bot - n + 1, term.col - 1, term.bot); for (i = term.bot; i >= orig + n; i--) { - temp = term.line[i]; - term.line[i] = term.line[i - n]; + temp = term.line[i]; + term.line[i] = term.line[i - n]; term.line[i - n] = temp; } @@ -890,7 +892,7 @@ void tscrolldown(int orig, int n) { } void tscrollup(int orig, int n) { - int i; + int i; Line temp; LIMIT(n, 0, term.bot - orig + 1); @@ -899,8 +901,8 @@ void tscrollup(int orig, int n) { tsetdirt(orig + n, term.bot); for (i = orig; i <= term.bot - n; i++) { - temp = term.line[i]; - term.line[i] = term.line[i + n]; + temp = term.line[i]; + term.line[i] = term.line[i + n]; term.line[i + n] = temp; } @@ -919,7 +921,7 @@ void tnewline(int first_col) { } void csiparse(void) { - char *p = csiescseq.buf, *np; + char * p = csiescseq.buf, *np; long int v; csiescseq.narg = 0; @@ -931,13 +933,13 @@ void csiparse(void) { csiescseq.buf[csiescseq.len] = '\0'; while (p < csiescseq.buf + csiescseq.len) { np = NULL; - v = strtol(p, &np, 10); + v = strtol(p, &np, 10); if (np == p) v = 0; if (v == LONG_MAX || v == LONG_MIN) v = -1; csiescseq.arg[csiescseq.narg++] = v; - p = np; + p = np; if (*p != ';' || csiescseq.narg == ESC_ARG_SIZ) break; p++; @@ -996,13 +998,13 @@ void tsetchar(Rune u, Glyph *attr, int x, int y) { term.line[y][x - 1].mode &= ~ATTR_WIDE; } - term.dirty[y] = 1; - term.line[y][x] = *attr; + term.dirty[y] = 1; + term.line[y][x] = *attr; term.line[y][x].u = u; } void tclearregion(int x1, int y1, int x2, int y2) { - int x, y, temp; + int x, y, temp; Glyph *gp; if (x1 > x2) @@ -1021,22 +1023,22 @@ void tclearregion(int x1, int y1, int x2, int y2) { gp = &term.line[y][x]; if (selected(x, y)) selclear(); - gp->fg = term.c.attr.fg; - gp->bg = term.c.attr.bg; + gp->fg = term.c.attr.fg; + gp->bg = term.c.attr.bg; gp->mode = 0; - gp->u = ' '; + gp->u = ' '; } } } void tdeletechar(int n) { - int dst, src, size; + int dst, src, size; Glyph *line; LIMIT(n, 0, term.col - term.c.x); - dst = term.c.x; - src = term.c.x + n; + dst = term.c.x; + src = term.c.x + n; size = term.col - src; line = term.line[term.c.y]; @@ -1045,13 +1047,13 @@ void tdeletechar(int n) { } void tinsertblank(int n) { - int dst, src, size; + int dst, src, size; Glyph *line; LIMIT(n, 0, term.col - term.c.x); - dst = term.c.x + n; - src = term.c.x; + dst = term.c.x + n; + src = term.c.x; size = term.col - dst; line = term.line[term.c.y]; @@ -1071,12 +1073,13 @@ void tdeleteline(int n) { int32_t tdefcolor(int *attr, int *npar, int l) { int32_t idx = -1; - uint r, g, b; + uint r, g, b; switch (attr[*npar + 1]) { case 2: /* direct color in RGB space */ if (*npar + 4 >= l) { - fprintf(stderr, "erresc(38): Incorrect number of parameters (%d)\n", + fprintf(stderr, + "erresc(38): Incorrect number of parameters (%d)\n", *npar); break; } @@ -1091,7 +1094,8 @@ int32_t tdefcolor(int *attr, int *npar, int l) { break; case 5: /* indexed color */ if (*npar + 2 >= l) { - fprintf(stderr, "erresc(38): Incorrect number of parameters (%d)\n", + fprintf(stderr, + "erresc(38): Incorrect number of parameters (%d)\n", *npar); break; } @@ -1114,7 +1118,7 @@ int32_t tdefcolor(int *attr, int *npar, int l) { } void tsetattr(int *attr, int l) { - int i; + int i; int32_t idx; for (i = 0; i < l; i++) { @@ -1213,8 +1217,8 @@ void tsetscroll(int t, int b) { LIMIT(b, 0, term.row - 1); if (t > b) { temp = t; - t = b; - b = temp; + t = b; + b = temp; } term.top = t; term.bot = b; @@ -1346,7 +1350,7 @@ void tsetmode(int priv, int set, int *args, int narg) { void csihandle(void) { char buf[40]; - int len; + int len; switch (csiescseq.mode[0]) { default: @@ -1554,7 +1558,7 @@ void csihandle(void) { void csidump(void) { size_t i; - uint c; + uint c; fprintf(stderr, "ESC["); for (i = 0; i < csiescseq.len; i++) { @@ -1578,7 +1582,7 @@ void csireset(void) { memset(&csiescseq, 0, sizeof(csiescseq)); } void strhandle(void) { char *p = NULL, *dec; - int j, narg, par; + int j, narg, par; term.esc &= ~(ESC_STR_END | ESC_STR); strparse(); @@ -1648,10 +1652,10 @@ void strhandle(void) { } void strparse(void) { - int c; + int c; char *p = strescseq.buf; - strescseq.narg = 0; + strescseq.narg = 0; strescseq.buf[strescseq.len] = '\0'; if (*p == '\0') @@ -1669,7 +1673,7 @@ void strparse(void) { void strdump(void) { size_t i; - uint c; + uint c; fprintf(stderr, "ESC%c", strescseq.type); for (i = 0; i < strescseq.len; i++) { @@ -1728,10 +1732,10 @@ void tdumpsel(void) { } void tdumpline(int n) { - char buf[UTF_SIZE]; + char buf[UTF_SIZE]; Glyph *bp, *end; - bp = &term.line[n][0]; + bp = &term.line[n][0]; end = &bp[MIN(tlinelen(n), term.col) - 1]; if (bp != end || bp->u != ' ') { for (; bp <= end; ++bp) @@ -1770,9 +1774,9 @@ void tdefutf8(char ascii) { } void tdeftran(char ascii) { - static char cs[] = "0B"; - static int vcs[] = {CS_GRAPHIC0, CS_USA}; - char *p; + static char cs[] = "0B"; + static int vcs[] = {CS_GRAPHIC0, CS_USA}; + char * p; if ((p = strchr(cs, ascii)) == NULL) { fprintf(stderr, "esc unhandled charset: ESC ( %c\n", ascii); @@ -1993,14 +1997,14 @@ int eschandle(uchar ascii) { } void tputc(Rune u) { - char c[UTF_SIZE]; - int control; - int width, len; + char c[UTF_SIZE]; + int control; + int width, len; Glyph *gp; control = ISCONTROL(u); if (u < 127 || !IS_SET(MODE_UTF8)) { - c[0] = u; + c[0] = u; width = len = 1; } else { len = utf8encode(u, c); @@ -2115,7 +2119,7 @@ check_control_code: if (width == 2) { gp->mode |= ATTR_WIDE; if (term.c.x + 1 < term.col) { - gp[1].u = '\0'; + gp[1].u = '\0'; gp[1].mode = ATTR_WDUMMY; } } @@ -2127,9 +2131,9 @@ check_control_code: } int twrite(const char *buf, int buflen, int show_ctrl) { - int charsize; + int charsize; Rune u; - int n; + int n; for (n = 0; n < buflen; n += charsize) { if (IS_SET(MODE_UTF8)) { @@ -2138,7 +2142,7 @@ int twrite(const char *buf, int buflen, int show_ctrl) { if (charsize == 0) break; } else { - u = buf[n] & 0xFF; + u = buf[n] & 0xFF; charsize = 1; } if (show_ctrl && ISCONTROL(u)) { @@ -2157,10 +2161,10 @@ int twrite(const char *buf, int buflen, int show_ctrl) { } void tresize(int col, int row) { - int i; - int minrow = MIN(row, term.row); - int mincol = MIN(col, term.col); - int *bp; + int i; + int minrow = MIN(row, term.row); + int mincol = MIN(col, term.col); + int * bp; TCursor c; if (col < 1 || row < 1) { @@ -2188,21 +2192,21 @@ void tresize(int col, int row) { } /* resize to new height */ - term.line = safe_realloc(term.line, row * sizeof(Line)); - term.alt = safe_realloc(term.alt, row * sizeof(Line)); + term.line = safe_realloc(term.line, row * sizeof(Line)); + term.alt = safe_realloc(term.alt, row * sizeof(Line)); term.dirty = safe_realloc(term.dirty, row * sizeof(*term.dirty)); - term.tabs = safe_realloc(term.tabs, col * sizeof(*term.tabs)); + term.tabs = safe_realloc(term.tabs, col * sizeof(*term.tabs)); /* resize each row to new width, zero-pad if needed */ for (i = 0; i < minrow; i++) { term.line[i] = safe_realloc(term.line[i], col * sizeof(Glyph)); - term.alt[i] = safe_realloc(term.alt[i], col * sizeof(Glyph)); + term.alt[i] = safe_realloc(term.alt[i], col * sizeof(Glyph)); } /* allocate any new rows */ for (/* i = minrow */; i < row; i++) { term.line[i] = safe_malloc(col * sizeof(Glyph)); - term.alt[i] = safe_malloc(col * sizeof(Glyph)); + term.alt[i] = safe_malloc(col * sizeof(Glyph)); } if (col > term.col) { bp = term.tabs + term.col; diff --git a/src/st/st.h b/src/st/st.h index f177c08..0aaca49 100644 --- a/src/st/st.h +++ b/src/st/st.h @@ -11,35 +11,35 @@ #include "utf8.h" 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_BOLD = 1 << 0, + ATTR_FAINT = 1 << 1, + ATTR_ITALIC = 1 << 2, + ATTR_UNDERLINE = 1 << 3, + ATTR_BLINK = 1 << 4, + ATTR_REVERSE = 1 << 5, + ATTR_INVISIBLE = 1 << 6, + ATTR_STRUCK = 1 << 7, + ATTR_WRAP = 1 << 8, + ATTR_WIDE = 1 << 9, + ATTR_WDUMMY = 1 << 10, ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT, }; #define Glyph Glyph_ typedef struct { - Rune u; /* character code */ - ushort mode; /* attribute flags */ - uint32_t fg; /* foreground */ - uint32_t bg; /* background */ + Rune u; /* character code */ + ushort mode; /* attribute flags */ + uint32_t fg; /* foreground */ + uint32_t bg; /* background */ } Glyph; typedef Glyph *Line; typedef union { - int i; - uint ui; - float f; + int i; + uint ui; + float f; const void *v; const char *s; } Arg; @@ -53,23 +53,23 @@ void printsel(const Arg *); void sendbreak(const Arg *); void toggleprinter(const Arg *); -int tattrset(int); -void tnew(int, int); -void tresize(int, int); -void tsetdirtattr(int); -void ttyhangup(void); -int ttynew(char *, char *, char *, char **); +int tattrset(int); +void tnew(int, int); +void tresize(int, int); +void tsetdirtattr(int); +void ttyhangup(void); +int ttynew(char *, char *, char *, char **); size_t ttyread(void); -void ttyresize(int, int); -void ttywrite(const char *, size_t, int); +void ttyresize(int, int); +void ttywrite(const char *, size_t, int); void resettitle(void); -void selclear(void); -void selinit(void); -void selstart(int, int, int); -void selextend(int, int, int, int); -int selected(int, int); +void selclear(void); +void selinit(void); +void selstart(int, int, int); +void selextend(int, int, int, int); +int selected(int, int); char *getsel(void); size_t utf8encode(Rune, char *); @@ -79,14 +79,14 @@ void *safe_realloc(void *, size_t); char *safe_strdup(char *); /* config.h globals */ -extern char *utmp; -extern char *scroll; -extern char *stty_args; -extern char *vtiden; -extern wchar_t *worddelimiters; -extern int allowaltscreen; -extern int allowwindowops; -extern char *termname; +extern char * utmp; +extern char * scroll; +extern char * stty_args; +extern char * vtiden; +extern wchar_t * worddelimiters; +extern int allowaltscreen; +extern int allowwindowops; +extern char * termname; extern unsigned int tabspaces; extern unsigned int defaultfg; extern unsigned int defaultbg; diff --git a/src/st/types.h b/src/st/types.h index 70b6794..90f926d 100644 --- a/src/st/types.h +++ b/src/st/types.h @@ -1,9 +1,9 @@ #ifndef TYPES_H #define TYPES_H -typedef unsigned char uchar; -typedef unsigned int uint; -typedef unsigned long ulong; +typedef unsigned char uchar; +typedef unsigned int uint; +typedef unsigned long ulong; typedef unsigned short ushort; #endif diff --git a/src/st/utf8.c b/src/st/utf8.c index c9553b2..d517541 100644 --- a/src/st/utf8.c +++ b/src/st/utf8.c @@ -4,8 +4,8 @@ static uchar utfbyte[UTF_SIZE + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0}; static uchar utfmask[UTF_SIZE + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; -static Rune utfmin[UTF_SIZE + 1] = {0, 0, 0x80, 0x800, 0x10000}; -static Rune utfmax[UTF_SIZE + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; +static Rune utfmin[UTF_SIZE + 1] = {0, 0, 0x80, 0x800, 0x10000}; +static Rune utfmax[UTF_SIZE + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; /** * Decode a given char array into a utf8 Rune @@ -17,7 +17,7 @@ static Rune utfmax[UTF_SIZE + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; */ size_t utf8decode(const char *p_char, Rune *p_rune, size_t p_char_len) { size_t decoded_len, type, i; - Rune decoded_rune; + Rune decoded_rune; *p_rune = UTF_INVALID; if (!p_char_len) // p_char_len is 0, so just return 0 @@ -82,7 +82,9 @@ size_t utf8encode(Rune p_rune, char *p_char) { return len; } -char utf8encodebyte(Rune u, size_t i) { return utfbyte[i] | (u & ~utfmask[i]); } +char utf8encodebyte(Rune u, size_t i) { + return utfbyte[i] | (u & ~utfmask[i]); +} /** * Check if a given rune is a valid UTF-8 rune diff --git a/src/st/utf8.h b/src/st/utf8.h index 343fd8e..d34c3b4 100644 --- a/src/st/utf8.h +++ b/src/st/utf8.h @@ -5,13 +5,13 @@ #include #define UTF_INVALID 0xFFFD -#define UTF_SIZE 4 +#define UTF_SIZE 4 typedef uint_least32_t Rune; size_t utf8decode(const char *, Rune *, size_t); -Rune utf8decodebyte(char, size_t *); -char utf8encodebyte(Rune, size_t); +Rune utf8decodebyte(char, size_t *); +char utf8encodebyte(Rune, size_t); size_t utf8validate(Rune *, size_t); #endif diff --git a/src/win.h b/src/win.h index 6bba79f..1e41bd6 100644 --- a/src/win.h +++ b/src/win.h @@ -6,26 +6,26 @@ #include "st/st.h" enum win_mode { - MODE_VISIBLE = 1 << 0, - MODE_FOCUSED = 1 << 1, - MODE_APPKEYPAD = 1 << 2, - MODE_MOUSEBTN = 1 << 3, - MODE_MOUSEMOTION = 1 << 4, - MODE_REVERSE = 1 << 5, - MODE_KBDLOCK = 1 << 6, - MODE_HIDE = 1 << 7, - MODE_APPCURSOR = 1 << 8, - MODE_MOUSESGR = 1 << 9, - MODE_8BIT = 1 << 10, - MODE_BLINK = 1 << 11, - MODE_FBLINK = 1 << 12, - MODE_FOCUS = 1 << 13, - MODE_MOUSEX10 = 1 << 14, - MODE_MOUSEMANY = 1 << 15, - MODE_BRCKTPASTE = 1 << 16, - MODE_NUMLOCK = 1 << 17, - MODE_MOUSE = - MODE_MOUSEBTN | MODE_MOUSEMOTION | MODE_MOUSEX10 | MODE_MOUSEMANY, + MODE_VISIBLE = 1 << 0, + MODE_FOCUSED = 1 << 1, + MODE_APPKEYPAD = 1 << 2, + MODE_MOUSEBTN = 1 << 3, + MODE_MOUSEMOTION = 1 << 4, + MODE_REVERSE = 1 << 5, + MODE_KBDLOCK = 1 << 6, + MODE_HIDE = 1 << 7, + MODE_APPCURSOR = 1 << 8, + MODE_MOUSESGR = 1 << 9, + MODE_8BIT = 1 << 10, + MODE_BLINK = 1 << 11, + MODE_FBLINK = 1 << 12, + MODE_FOCUS = 1 << 13, + MODE_MOUSEX10 = 1 << 14, + MODE_MOUSEMANY = 1 << 15, + MODE_BRCKTPASTE = 1 << 16, + MODE_NUMLOCK = 1 << 17, + MODE_MOUSE = + MODE_MOUSEBTN | MODE_MOUSEMOTION | MODE_MOUSEX10 | MODE_MOUSEMANY, }; void xbell(void); @@ -34,14 +34,14 @@ void xdrawcursor(int, int, Glyph, int, int, Glyph); void xdrawline(Line, int, int, int); void xfinishdraw(void); void xloadcols(void); -int xsetcolorname(int, const char *); +int xsetcolorname(int, const char *); void xseticontitle(char *); void xsettitle(char *); -int xsetcursor(int); +int xsetcursor(int); void xsetmode(int, unsigned int); void xsetpointermotion(int); void xsetsel(char *); -int xstartdraw(void); +int xstartdraw(void); void xximspot(int, int); #endif diff --git a/src/x.c b/src/x.c index 225fc98..07bcf22 100644 --- a/src/x.c +++ b/src/x.c @@ -23,32 +23,32 @@ char *argv0; /* types used in config.h */ typedef struct { - uint mod; - KeySym keysym; - void (*func)(const Arg *); - const Arg arg; + uint mod; + KeySym keysym; + void (*func)(const Arg *); + const Arg arg; } Shortcut; typedef struct { - uint mod; - uint button; - void (*func)(const Arg *); - const Arg arg; - uint release; + uint mod; + uint button; + void (*func)(const Arg *); + const Arg arg; + uint release; } MouseShortcut; typedef struct { - KeySym k; - uint mask; - char *s; - /* three-valued logic variables: 0 indifferent, 1 on, -1 off */ - signed char appkey; /* application keypad */ - signed char appcursor; /* application cursor */ + KeySym k; + uint mask; + char * s; + /* three-valued logic variables: 0 indifferent, 1 on, -1 off */ + signed char appkey; /* application keypad */ + signed char appcursor; /* application cursor */ } Key; /* X modifiers */ -#define XK_ANY_MOD UINT_MAX -#define XK_NO_MOD 0 +#define XK_ANY_MOD UINT_MAX +#define XK_NO_MOD 0 #define XK_SWITCH_MOD (1 << 13) /* function definitions used in config.h */ @@ -65,144 +65,145 @@ static void ttysend(const Arg *); #include "config.h" /* XEMBED messages */ -#define XEMBED_FOCUS_IN 4 +#define XEMBED_FOCUS_IN 4 #define XEMBED_FOCUS_OUT 5 /* macros */ #define IS_SET(flag) ((win.mode & (flag)) != 0) -#define TRUERED(x) (((x)&0xff0000) >> 8) +#define TRUERED(x) (((x)&0xff0000) >> 8) #define TRUEGREEN(x) (((x)&0xff00)) -#define TRUEBLUE(x) (((x)&0xff) << 8) +#define TRUEBLUE(x) (((x)&0xff) << 8) -typedef XftDraw *Draw; -typedef XftColor Color; +typedef XftDraw * Draw; +typedef XftColor Color; typedef XftGlyphFontSpec GlyphFontSpec; /* Purely graphic info */ typedef struct { - int tw, th; /* tty width and height */ - int w, h; /* window width and height */ - int ch; /* char height */ - int cw; /* char width */ - int mode; /* window state/mode flags */ - int cursor; /* cursor style */ + int tw, th; /* tty width and height */ + int w, h; /* window width and height */ + int ch; /* char height */ + int cw; /* char width */ + int mode; /* window state/mode flags */ + int cursor; /* cursor style */ } TermWindow; typedef struct { - Display *dpy; - Colormap cmap; - Window win; - Drawable buf; - GlyphFontSpec *specbuf; /* font spec buffer used for rendering */ - Atom xembed, wmdeletewin, netwmname, netwmiconname, netwmpid; - struct { - XIM xim; - XIC xic; - XPoint spot; - XVaNestedList spotlist; - } ime; - Draw draw; - Visual *vis; - XSetWindowAttributes attrs; - int scr; - int isfixed; /* is fixed geometry? */ - int l, t; /* left and top offset */ - int gm; /* geometry mask */ + Display * dpy; + Colormap cmap; + Window win; + Drawable buf; + GlyphFontSpec *specbuf; /* font spec buffer used for rendering */ + Atom xembed, wmdeletewin, netwmname, netwmiconname, netwmpid; + struct { + XIM xim; + XIC xic; + XPoint spot; + XVaNestedList spotlist; + } ime; + Draw draw; + Visual * vis; + XSetWindowAttributes attrs; + int scr; + int isfixed; /* is fixed geometry? */ + int l, t; /* left and top offset */ + int gm; /* geometry mask */ } XWindow; typedef struct { - Atom xtarget; - char *primary, *clipboard; - struct timespec tclick1; - struct timespec tclick2; + Atom xtarget; + char * primary, *clipboard; + struct timespec tclick1; + struct timespec tclick2; } XSelection; /* Font structure */ #define Font Font_ typedef struct { - int height; - int width; - int ascent; - int descent; - int badslant; - int badweight; - short lbearing; - short rbearing; - XftFont *match; - FcFontSet *set; - FcPattern *pattern; + int height; + int width; + int ascent; + int descent; + int badslant; + int badweight; + short lbearing; + short rbearing; + XftFont * match; + FcFontSet *set; + FcPattern *pattern; } Font; /* Drawing Context */ typedef struct { - Color *col; - size_t collen; - Font font, bfont, ifont, ibfont; - GC gc; + Color *col; + size_t collen; + Font font, bfont, ifont, ibfont; + GC gc; } DC; static inline ushort sixd_to_16bit(int); -static int xmakeglyphfontspecs(XftGlyphFontSpec *, const Glyph *, int, int, - int); -static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, int); +static int xmakeglyphfontspecs(XftGlyphFontSpec *, const Glyph *, int, int, + int); +static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, + int); static void xdrawglyph(Glyph, int, int); static void xclear(int, int, int, int); -static int xgeommasktogravity(int); -static int ximopen(Display *); +static int xgeommasktogravity(int); +static int ximopen(Display *); static void ximinstantiate(Display *, XPointer, XPointer); static void ximdestroy(XIM, XPointer, XPointer); -static int xicdestroy(XIC, XPointer, XPointer); +static int xicdestroy(XIC, XPointer, XPointer); static void xinit(int, int); static void cresize(int, int); static void xresize(int, int); static void xhints(void); -static int xloadcolor(int, const char *, Color *); -static int xloadfont(Font *, FcPattern *); +static int xloadcolor(int, const char *, Color *); +static int xloadfont(Font *, FcPattern *); static void xloadfonts(char *, double); static void xunloadfont(Font *); static void xunloadfonts(void); static void xsetenv(void); static void xseturgency(int); -static int evcol(XEvent *); -static int evrow(XEvent *); +static int evcol(XEvent *); +static int evrow(XEvent *); -static void expose(XEvent *); -static void visibility(XEvent *); -static void unmap(XEvent *); -static void kpress(XEvent *); -static void cmessage(XEvent *); -static void resize(XEvent *); -static void focus(XEvent *); -static uint buttonmask(uint); -static int mouseaction(XEvent *, uint); -static void brelease(XEvent *); -static void bpress(XEvent *); -static void bmotion(XEvent *); -static void propnotify(XEvent *); -static void selnotify(XEvent *); -static void selclear_(XEvent *); -static void selrequest(XEvent *); -static void setsel(char *, Time); -static void mousesel(XEvent *, int); -static void mousereport(XEvent *); +static void expose(XEvent *); +static void visibility(XEvent *); +static void unmap(XEvent *); +static void kpress(XEvent *); +static void cmessage(XEvent *); +static void resize(XEvent *); +static void focus(XEvent *); +static uint buttonmask(uint); +static int mouseaction(XEvent *, uint); +static void brelease(XEvent *); +static void bpress(XEvent *); +static void bmotion(XEvent *); +static void propnotify(XEvent *); +static void selnotify(XEvent *); +static void selclear_(XEvent *); +static void selrequest(XEvent *); +static void setsel(char *, Time); +static void mousesel(XEvent *, int); +static void mousereport(XEvent *); static char *kmap(KeySym, uint); -static int match(uint, uint); +static int match(uint, uint); static void run(void); static void usage(void); static void (*handler[LASTEvent])(XEvent *) = { - [KeyPress] = kpress, - [ClientMessage] = cmessage, - [ConfigureNotify] = resize, + [KeyPress] = kpress, + [ClientMessage] = cmessage, + [ConfigureNotify] = resize, [VisibilityNotify] = visibility, - [UnmapNotify] = unmap, - [Expose] = expose, - [FocusIn] = focus, - [FocusOut] = focus, - [MotionNotify] = bmotion, - [ButtonPress] = bpress, - [ButtonRelease] = brelease, + [UnmapNotify] = unmap, + [Expose] = expose, + [FocusIn] = focus, + [FocusOut] = focus, + [MotionNotify] = bmotion, + [ButtonPress] = bpress, + [ButtonRelease] = brelease, /* * Uncomment if you want the selection to disappear when you select * something different in another window. @@ -213,13 +214,13 @@ static void (*handler[LASTEvent])(XEvent *) = { * PropertyNotify is only turned on when there is some INCR transfer * happening for the selection retrieval. */ - [PropertyNotify] = propnotify, + [PropertyNotify] = propnotify, [SelectionRequest] = selrequest, }; /* Globals */ -static DC dc; -static XWindow xw; +static DC dc; +static XWindow xw; static XSelection xsel; static TermWindow win; @@ -227,320 +228,321 @@ static TermWindow win; enum { FRC_NORMAL, FRC_ITALIC, FRC_BOLD, FRC_ITALICBOLD }; typedef struct { - XftFont *font; - int flags; - Rune unicodep; + XftFont *font; + int flags; + Rune unicodep; } Fontcache; /* Fontcache is an array now. A new font will be appended to the array. */ -static Fontcache *frc = NULL; -static int frclen = 0; -static int frccap = 0; -static char *usedfont = NULL; -static double usedfontsize = 0; -static double defaultfontsize = 0; +static Fontcache *frc = NULL; +static int frclen = 0; +static int frccap = 0; +static char * usedfont = NULL; +static double usedfontsize = 0; +static double defaultfontsize = 0; -static char *opt_class = NULL; -static char **opt_cmd = NULL; -static char *opt_embed = NULL; -static char *opt_font = NULL; -static char *opt_io = NULL; -static char *opt_line = NULL; -static char *opt_name = NULL; -static char *opt_title = NULL; +static char * opt_class = NULL; +static char **opt_cmd = NULL; +static char * opt_embed = NULL; +static char * opt_font = NULL; +static char * opt_io = NULL; +static char * opt_line = NULL; +static char * opt_name = NULL; +static char * opt_title = NULL; static int oldbutton = 3; /* button event on startup: 3 = release */ void clipcopy(const Arg *dummy) { - Atom clipboard; + Atom clipboard; - free(xsel.clipboard); - xsel.clipboard = NULL; + free(xsel.clipboard); + xsel.clipboard = NULL; - if (xsel.primary != NULL) { - xsel.clipboard = safe_strdup(xsel.primary); - clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); - XSetSelectionOwner(xw.dpy, clipboard, xw.win, CurrentTime); - } + if (xsel.primary != NULL) { + xsel.clipboard = safe_strdup(xsel.primary); + clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); + XSetSelectionOwner(xw.dpy, clipboard, xw.win, CurrentTime); + } } void clippaste(const Arg *dummy) { - Atom clipboard; + Atom clipboard; - clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); - XConvertSelection(xw.dpy, clipboard, xsel.xtarget, clipboard, xw.win, - CurrentTime); + clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); + XConvertSelection(xw.dpy, clipboard, xsel.xtarget, clipboard, xw.win, + CurrentTime); } void selpaste(const Arg *dummy) { - XConvertSelection(xw.dpy, XA_PRIMARY, xsel.xtarget, XA_PRIMARY, xw.win, - CurrentTime); + XConvertSelection(xw.dpy, XA_PRIMARY, xsel.xtarget, XA_PRIMARY, xw.win, + CurrentTime); } void numlock(const Arg *dummy) { win.mode ^= MODE_NUMLOCK; } void zoom(const Arg *arg) { - Arg larg; + Arg larg; - larg.f = usedfontsize + arg->f; - zoomabs(&larg); + larg.f = usedfontsize + arg->f; + zoomabs(&larg); } void zoomabs(const Arg *arg) { - xunloadfonts(); - xloadfonts(usedfont, arg->f); - cresize(0, 0); - redraw(); - xhints(); + xunloadfonts(); + xloadfonts(usedfont, arg->f); + cresize(0, 0); + redraw(); + xhints(); } void zoomreset(const Arg *arg) { - Arg larg; + Arg larg; - if (defaultfontsize > 0) { - larg.f = defaultfontsize; - zoomabs(&larg); - } + if (defaultfontsize > 0) { + larg.f = defaultfontsize; + zoomabs(&larg); + } } void ttysend(const Arg *arg) { ttywrite(arg->s, strlen(arg->s), 1); } int evcol(XEvent *e) { - int x = e->xbutton.x - borderpx; - LIMIT(x, 0, win.tw - 1); - return x / win.cw; + int x = e->xbutton.x - borderpx; + LIMIT(x, 0, win.tw - 1); + return x / win.cw; } int evrow(XEvent *e) { - int y = e->xbutton.y - borderpx; - LIMIT(y, 0, win.th - 1); - return y / win.ch; + int y = e->xbutton.y - borderpx; + LIMIT(y, 0, win.th - 1); + return y / win.ch; } void mousesel(XEvent *e, int done) { - int type, seltype = SEL_REGULAR; - uint state = e->xbutton.state & ~(Button1Mask | forcemousemod); + int type, seltype = SEL_REGULAR; + uint state = e->xbutton.state & ~(Button1Mask | forcemousemod); - for (type = 1; type < LEN(selmasks); ++type) { - if (match(selmasks[type], state)) { - seltype = type; - break; + for (type = 1; type < LEN(selmasks); ++type) { + if (match(selmasks[type], state)) { + seltype = type; + break; + } } - } - selextend(evcol(e), evrow(e), seltype, done); - if (done) - setsel(getsel(), e->xbutton.time); + selextend(evcol(e), evrow(e), seltype, done); + if (done) + setsel(getsel(), e->xbutton.time); } void mousereport(XEvent *e) { - int len, x = evcol(e), y = evrow(e), button = e->xbutton.button, - state = e->xbutton.state; - char buf[40]; - static int ox, oy; + int len, x = evcol(e), y = evrow(e), button = e->xbutton.button, + state = e->xbutton.state; + char buf[40]; + static int ox, oy; - /* from urxvt */ - if (e->xbutton.type == MotionNotify) { - if (x == ox && y == oy) - return; - if (!IS_SET(MODE_MOUSEMOTION) && !IS_SET(MODE_MOUSEMANY)) - return; - /* MOUSE_MOTION: no reporting if no button is pressed */ - if (IS_SET(MODE_MOUSEMOTION) && oldbutton == 3) - return; + /* from urxvt */ + if (e->xbutton.type == MotionNotify) { + if (x == ox && y == oy) + return; + if (!IS_SET(MODE_MOUSEMOTION) && !IS_SET(MODE_MOUSEMANY)) + return; + /* MOUSE_MOTION: no reporting if no button is pressed */ + if (IS_SET(MODE_MOUSEMOTION) && oldbutton == 3) + return; - button = oldbutton + 32; - ox = x; - oy = y; - } else { - if (!IS_SET(MODE_MOUSESGR) && e->xbutton.type == ButtonRelease) { - button = 3; + button = oldbutton + 32; + ox = x; + oy = y; } else { - button -= Button1; - if (button >= 3) - button += 64 - 3; + if (!IS_SET(MODE_MOUSESGR) && e->xbutton.type == ButtonRelease) { + button = 3; + } else { + button -= Button1; + if (button >= 3) + button += 64 - 3; + } + if (e->xbutton.type == ButtonPress) { + oldbutton = button; + ox = x; + oy = y; + } else if (e->xbutton.type == ButtonRelease) { + oldbutton = 3; + /* MODE_MOUSEX10: no button release reporting */ + if (IS_SET(MODE_MOUSEX10)) + return; + if (button == 64 || button == 65) + return; + } } - if (e->xbutton.type == ButtonPress) { - oldbutton = button; - ox = x; - oy = y; - } else if (e->xbutton.type == ButtonRelease) { - oldbutton = 3; - /* MODE_MOUSEX10: no button release reporting */ - if (IS_SET(MODE_MOUSEX10)) - return; - if (button == 64 || button == 65) + + if (!IS_SET(MODE_MOUSEX10)) { + button += ((state & ShiftMask) ? 4 : 0) + + ((state & Mod4Mask) ? 8 : 0) + + ((state & ControlMask) ? 16 : 0); + } + + if (IS_SET(MODE_MOUSESGR)) { + len = snprintf(buf, sizeof(buf), "\033[<%d;%d;%d%c", button, x + 1, + y + 1, e->xbutton.type == ButtonRelease ? 'm' : 'M'); + } else if (x < 223 && y < 223) { + len = snprintf(buf, sizeof(buf), "\033[M%c%c%c", 32 + button, + 32 + x + 1, 32 + y + 1); + } else { return; } - } - if (!IS_SET(MODE_MOUSEX10)) { - button += ((state & ShiftMask) ? 4 : 0) + ((state & Mod4Mask) ? 8 : 0) + - ((state & ControlMask) ? 16 : 0); - } - - if (IS_SET(MODE_MOUSESGR)) { - len = snprintf(buf, sizeof(buf), "\033[<%d;%d;%d%c", button, x + 1, y + 1, - e->xbutton.type == ButtonRelease ? 'm' : 'M'); - } else if (x < 223 && y < 223) { - len = snprintf(buf, sizeof(buf), "\033[M%c%c%c", 32 + button, 32 + x + 1, - 32 + y + 1); - } else { - return; - } - - ttywrite(buf, len, 0); + ttywrite(buf, len, 0); } uint buttonmask(uint button) { - return button == Button1 ? Button1Mask - : button == Button2 ? Button2Mask - : button == Button3 ? Button3Mask - : button == Button4 ? Button4Mask - : button == Button5 ? Button5Mask - : 0; + return button == Button1 ? Button1Mask + : button == Button2 ? Button2Mask + : button == Button3 ? Button3Mask + : button == Button4 ? Button4Mask + : button == Button5 ? Button5Mask + : 0; } int mouseaction(XEvent *e, uint release) { - MouseShortcut *ms; + MouseShortcut *ms; - /* ignore Buttonmask for Button - it's set on release */ - uint state = e->xbutton.state & ~buttonmask(e->xbutton.button); + /* ignore Buttonmask for Button - it's set on release */ + uint state = e->xbutton.state & ~buttonmask(e->xbutton.button); - for (ms = mshortcuts; ms < mshortcuts + LEN(mshortcuts); ms++) { - if (ms->release == release && ms->button == e->xbutton.button && - (match(ms->mod, state) || /* exact or forced */ - match(ms->mod, state & ~forcemousemod))) { - ms->func(&(ms->arg)); - return 1; + for (ms = mshortcuts; ms < mshortcuts + LEN(mshortcuts); ms++) { + if (ms->release == release && ms->button == e->xbutton.button && + (match(ms->mod, state) || /* exact or forced */ + match(ms->mod, state & ~forcemousemod))) { + ms->func(&(ms->arg)); + return 1; + } } - } - return 0; + return 0; } void bpress(XEvent *e) { - struct timespec now; - int snap; + struct timespec now; + int snap; - if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { - mousereport(e); - return; - } - - if (mouseaction(e, 0)) - return; - - if (e->xbutton.button == Button1) { - /* - * If the user clicks below predefined timeouts specific - * snapping behaviour is exposed. - */ - clock_gettime(CLOCK_MONOTONIC, &now); - if (TIMEDIFF(now, xsel.tclick2) <= tripleclicktimeout) { - snap = SNAP_LINE; - } else if (TIMEDIFF(now, xsel.tclick1) <= doubleclicktimeout) { - snap = SNAP_WORD; - } else { - snap = 0; + if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { + mousereport(e); + return; } - xsel.tclick2 = xsel.tclick1; - xsel.tclick1 = now; - selstart(evcol(e), evrow(e), snap); - } + if (mouseaction(e, 0)) + return; + + if (e->xbutton.button == Button1) { + /* + * If the user clicks below predefined timeouts specific + * snapping behaviour is exposed. + */ + clock_gettime(CLOCK_MONOTONIC, &now); + if (TIMEDIFF(now, xsel.tclick2) <= tripleclicktimeout) { + snap = SNAP_LINE; + } else if (TIMEDIFF(now, xsel.tclick1) <= doubleclicktimeout) { + snap = SNAP_WORD; + } else { + snap = 0; + } + xsel.tclick2 = xsel.tclick1; + xsel.tclick1 = now; + + selstart(evcol(e), evrow(e), snap); + } } void propnotify(XEvent *e) { - XPropertyEvent *xpev; - Atom clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); + XPropertyEvent *xpev; + Atom clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); - xpev = &e->xproperty; - if (xpev->state == PropertyNewValue && - (xpev->atom == XA_PRIMARY || xpev->atom == clipboard)) { - selnotify(e); - } + xpev = &e->xproperty; + if (xpev->state == PropertyNewValue && + (xpev->atom == XA_PRIMARY || xpev->atom == clipboard)) { + selnotify(e); + } } void selnotify(XEvent *e) { - ulong nitems, ofs, rem; - int format; - uchar *data, *last, *repl; - Atom type, incratom, property = None; + ulong nitems, ofs, rem; + int format; + uchar *data, *last, *repl; + Atom type, incratom, property = None; - incratom = XInternAtom(xw.dpy, "INCR", 0); + incratom = XInternAtom(xw.dpy, "INCR", 0); - ofs = 0; - if (e->type == SelectionNotify) - property = e->xselection.property; - else if (e->type == PropertyNotify) - property = e->xproperty.atom; + ofs = 0; + if (e->type == SelectionNotify) + property = e->xselection.property; + else if (e->type == PropertyNotify) + property = e->xproperty.atom; - if (property == None) - return; + if (property == None) + return; - do { - if (XGetWindowProperty(xw.dpy, xw.win, property, ofs, BUFSIZ / 4, False, - AnyPropertyType, &type, &format, &nitems, &rem, - &data)) { - fprintf(stderr, "Clipboard allocation failed\n"); - return; - } + do { + if (XGetWindowProperty(xw.dpy, xw.win, property, ofs, BUFSIZ / 4, + False, AnyPropertyType, &type, &format, &nitems, + &rem, &data)) { + fprintf(stderr, "Clipboard allocation failed\n"); + return; + } - if (e->type == PropertyNotify && nitems == 0 && rem == 0) { - /* - * If there is some PropertyNotify with no data, then - * this is the signal of the selection owner that all - * data has been transferred. We won't need to receive - * PropertyNotify events anymore. - */ - MODBIT(xw.attrs.event_mask, 0, PropertyChangeMask); - XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, &xw.attrs); - } + if (e->type == PropertyNotify && nitems == 0 && rem == 0) { + /* + * If there is some PropertyNotify with no data, then + * this is the signal of the selection owner that all + * data has been transferred. We won't need to receive + * PropertyNotify events anymore. + */ + MODBIT(xw.attrs.event_mask, 0, PropertyChangeMask); + XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, &xw.attrs); + } - if (type == incratom) { - /* - * Activate the PropertyNotify events so we receive - * when the selection owner does send us the next - * chunk of data. - */ - MODBIT(xw.attrs.event_mask, 1, PropertyChangeMask); - XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, &xw.attrs); + if (type == incratom) { + /* + * Activate the PropertyNotify events so we receive + * when the selection owner does send us the next + * chunk of data. + */ + MODBIT(xw.attrs.event_mask, 1, PropertyChangeMask); + XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, &xw.attrs); - /* - * Deleting the property is the transfer start signal. - */ - XDeleteProperty(xw.dpy, xw.win, (int)property); - continue; - } + /* + * Deleting the property is the transfer start signal. + */ + XDeleteProperty(xw.dpy, xw.win, (int)property); + continue; + } + + /* + * As seen in getsel: + * Line endings are inconsistent in the terminal and GUI world + * copy and pasting. When receiving some selection data, + * replace all '\n' with '\r'. + * FIXME: Fix the computer world. + */ + repl = data; + last = data + nitems * format / 8; + while ((repl = memchr(repl, '\n', last - repl))) { + *repl++ = '\r'; + } + + if (IS_SET(MODE_BRCKTPASTE) && ofs == 0) + ttywrite("\033[200~", 6, 0); + ttywrite((char *)data, nitems * format / 8, 1); + if (IS_SET(MODE_BRCKTPASTE) && rem == 0) + ttywrite("\033[201~", 6, 0); + XFree(data); + /* number of 32-bit chunks returned */ + ofs += nitems * format / 32; + } while (rem > 0); /* - * 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. + * Deleting the property again tells the selection owner to send the + * next data chunk in the property. */ - repl = data; - last = data + nitems * format / 8; - while ((repl = memchr(repl, '\n', last - repl))) { - *repl++ = '\r'; - } - - if (IS_SET(MODE_BRCKTPASTE) && ofs == 0) - ttywrite("\033[200~", 6, 0); - ttywrite((char *)data, nitems * format / 8, 1); - if (IS_SET(MODE_BRCKTPASTE) && rem == 0) - ttywrite("\033[201~", 6, 0); - XFree(data); - /* number of 32-bit chunks returned */ - ofs += nitems * format / 32; - } while (rem > 0); - - /* - * Deleting the property again tells the selection owner to send the - * next data chunk in the property. - */ - XDeleteProperty(xw.dpy, xw.win, (int)property); + XDeleteProperty(xw.dpy, xw.win, (int)property); } void xclipcopy(void) { clipcopy(NULL); } @@ -548,1314 +550,1322 @@ void xclipcopy(void) { clipcopy(NULL); } void selclear_(XEvent *e) { selclear(); } void selrequest(XEvent *e) { - XSelectionRequestEvent *xsre; - XSelectionEvent xev; - Atom xa_targets, string, clipboard; - char *seltext; + XSelectionRequestEvent *xsre; + XSelectionEvent xev; + Atom xa_targets, string, clipboard; + char * seltext; - xsre = (XSelectionRequestEvent *)e; - xev.type = SelectionNotify; - xev.requestor = xsre->requestor; - xev.selection = xsre->selection; - xev.target = xsre->target; - xev.time = xsre->time; - if (xsre->property == None) - xsre->property = xsre->target; + xsre = (XSelectionRequestEvent *)e; + xev.type = SelectionNotify; + xev.requestor = xsre->requestor; + xev.selection = xsre->selection; + xev.target = xsre->target; + xev.time = xsre->time; + if (xsre->property == None) + xsre->property = xsre->target; - /* reject */ - xev.property = None; + /* reject */ + xev.property = None; - xa_targets = XInternAtom(xw.dpy, "TARGETS", 0); - if (xsre->target == xa_targets) { - /* respond with the supported type */ - string = xsel.xtarget; - XChangeProperty(xsre->display, xsre->requestor, xsre->property, XA_ATOM, 32, - PropModeReplace, (uchar *)&string, 1); - xev.property = xsre->property; - } else if (xsre->target == xsel.xtarget || xsre->target == XA_STRING) { - /* - * xith XA_STRING non ascii characters may be incorrect in the - * requestor. It is not our problem, use utf8. - */ - clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); - if (xsre->selection == XA_PRIMARY) { - seltext = xsel.primary; - } else if (xsre->selection == clipboard) { - seltext = xsel.clipboard; - } else { - fprintf(stderr, "Unhandled clipboard selection 0x%lx\n", xsre->selection); - return; + xa_targets = XInternAtom(xw.dpy, "TARGETS", 0); + if (xsre->target == xa_targets) { + /* respond with the supported type */ + string = xsel.xtarget; + XChangeProperty(xsre->display, xsre->requestor, xsre->property, + XA_ATOM, 32, PropModeReplace, (uchar *)&string, 1); + xev.property = xsre->property; + } else if (xsre->target == xsel.xtarget || xsre->target == XA_STRING) { + /* + * xith XA_STRING non ascii characters may be incorrect in the + * requestor. It is not our problem, use utf8. + */ + clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); + if (xsre->selection == XA_PRIMARY) { + seltext = xsel.primary; + } else if (xsre->selection == clipboard) { + seltext = xsel.clipboard; + } else { + fprintf(stderr, "Unhandled clipboard selection 0x%lx\n", + xsre->selection); + return; + } + if (seltext != NULL) { + XChangeProperty(xsre->display, xsre->requestor, xsre->property, + xsre->target, 8, PropModeReplace, (uchar *)seltext, + strlen(seltext)); + xev.property = xsre->property; + } } - if (seltext != NULL) { - XChangeProperty(xsre->display, xsre->requestor, xsre->property, - xsre->target, 8, PropModeReplace, (uchar *)seltext, - strlen(seltext)); - xev.property = xsre->property; - } - } - /* all done, send a notification to the listener */ - if (!XSendEvent(xsre->display, xsre->requestor, 1, 0, (XEvent *)&xev)) - fprintf(stderr, "Error sending SelectionNotify event\n"); + /* all done, send a notification to the listener */ + if (!XSendEvent(xsre->display, xsre->requestor, 1, 0, (XEvent *)&xev)) + fprintf(stderr, "Error sending SelectionNotify event\n"); } void setsel(char *str, Time t) { - if (!str) - return; + if (!str) + return; - free(xsel.primary); - xsel.primary = str; + free(xsel.primary); + xsel.primary = str; - XSetSelectionOwner(xw.dpy, XA_PRIMARY, xw.win, t); - if (XGetSelectionOwner(xw.dpy, XA_PRIMARY) != xw.win) - selclear(); + XSetSelectionOwner(xw.dpy, XA_PRIMARY, xw.win, t); + if (XGetSelectionOwner(xw.dpy, XA_PRIMARY) != xw.win) + selclear(); } void xsetsel(char *str) { setsel(str, CurrentTime); } void brelease(XEvent *e) { - if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { - mousereport(e); - return; - } + if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { + mousereport(e); + return; + } - if (mouseaction(e, 1)) - return; - if (e->xbutton.button == Button1) - mousesel(e, 1); + if (mouseaction(e, 1)) + return; + if (e->xbutton.button == Button1) + mousesel(e, 1); } void bmotion(XEvent *e) { - if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { - mousereport(e); - return; - } + if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { + mousereport(e); + return; + } - mousesel(e, 0); + mousesel(e, 0); } void cresize(int width, int height) { - int col, row; + int col, row; - if (width != 0) - win.w = width; - if (height != 0) - win.h = height; + if (width != 0) + win.w = width; + if (height != 0) + win.h = height; - col = (win.w - 2 * borderpx) / win.cw; - row = (win.h - 2 * borderpx) / win.ch; - col = MAX(1, col); - row = MAX(1, row); + col = (win.w - 2 * borderpx) / win.cw; + row = (win.h - 2 * borderpx) / win.ch; + col = MAX(1, col); + row = MAX(1, row); - tresize(col, row); - xresize(col, row); - ttyresize(win.tw, win.th); + tresize(col, row); + xresize(col, row); + ttyresize(win.tw, win.th); } void xresize(int col, int row) { - win.tw = col * win.cw; - win.th = row * win.ch; + win.tw = col * win.cw; + win.th = row * win.ch; - XFreePixmap(xw.dpy, xw.buf); - xw.buf = - XCreatePixmap(xw.dpy, xw.win, win.w, win.h, DefaultDepth(xw.dpy, xw.scr)); - XftDrawChange(xw.draw, xw.buf); - xclear(0, 0, win.w, win.h); + XFreePixmap(xw.dpy, xw.buf); + xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, + DefaultDepth(xw.dpy, xw.scr)); + XftDrawChange(xw.draw, xw.buf); + xclear(0, 0, win.w, win.h); - /* resize to new width */ - xw.specbuf = safe_realloc(xw.specbuf, col * sizeof(GlyphFontSpec)); + /* resize to new width */ + xw.specbuf = safe_realloc(xw.specbuf, col * sizeof(GlyphFontSpec)); } ushort sixd_to_16bit(int x) { return x == 0 ? 0 : 0x3737 + 0x2828 * x; } int xloadcolor(int i, const char *name, Color *ncolor) { - XRenderColor color = {.alpha = 0xffff}; + XRenderColor color = {.alpha = 0xffff}; - if (!name) { - if (BETWEEN(i, 16, 255)) { /* 256 color */ - if (i < 6 * 6 * 6 + 16) { /* same colors as xterm */ - color.red = sixd_to_16bit(((i - 16) / 36) % 6); - color.green = sixd_to_16bit(((i - 16) / 6) % 6); - color.blue = sixd_to_16bit(((i - 16) / 1) % 6); - } else { /* greyscale */ - color.red = 0x0808 + 0x0a0a * (i - (6 * 6 * 6 + 16)); - color.green = color.blue = color.red; - } - return XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &color, ncolor); - } else - name = colorname[i]; - } + if (!name) { + if (BETWEEN(i, 16, 255)) { /* 256 color */ + if (i < 6 * 6 * 6 + 16) { /* same colors as xterm */ + color.red = sixd_to_16bit(((i - 16) / 36) % 6); + color.green = sixd_to_16bit(((i - 16) / 6) % 6); + color.blue = sixd_to_16bit(((i - 16) / 1) % 6); + } else { /* greyscale */ + color.red = 0x0808 + 0x0a0a * (i - (6 * 6 * 6 + 16)); + color.green = color.blue = color.red; + } + return XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &color, ncolor); + } else + name = colorname[i]; + } - return XftColorAllocName(xw.dpy, xw.vis, xw.cmap, name, ncolor); + return XftColorAllocName(xw.dpy, xw.vis, xw.cmap, name, ncolor); } void xloadcols(void) { - int i; - static int loaded; - Color *cp; + int i; + static int loaded; + Color * cp; - if (loaded) { - for (cp = dc.col; cp < &dc.col[dc.collen]; ++cp) - XftColorFree(xw.dpy, xw.vis, xw.cmap, cp); - } else { - dc.collen = MAX(LEN(colorname), 256); - dc.col = safe_malloc(dc.collen * sizeof(Color)); - } - - for (i = 0; i < dc.collen; i++) - if (!xloadcolor(i, NULL, &dc.col[i])) { - if (colorname[i]) - die("could not allocate color '%s'\n", colorname[i]); - else - die("could not allocate color %d\n", i); + if (loaded) { + for (cp = dc.col; cp < &dc.col[dc.collen]; ++cp) + XftColorFree(xw.dpy, xw.vis, xw.cmap, cp); + } else { + dc.collen = MAX(LEN(colorname), 256); + dc.col = safe_malloc(dc.collen * sizeof(Color)); } - loaded = 1; + + for (i = 0; i < dc.collen; i++) + if (!xloadcolor(i, NULL, &dc.col[i])) { + if (colorname[i]) + die("could not allocate color '%s'\n", colorname[i]); + else + die("could not allocate color %d\n", i); + } + loaded = 1; } int xsetcolorname(int x, const char *name) { - Color ncolor; + Color ncolor; - if (!BETWEEN(x, 0, dc.collen)) - return 1; + if (!BETWEEN(x, 0, dc.collen)) + return 1; - if (!xloadcolor(x, name, &ncolor)) - return 1; + if (!xloadcolor(x, name, &ncolor)) + return 1; - XftColorFree(xw.dpy, xw.vis, xw.cmap, &dc.col[x]); - dc.col[x] = ncolor; + XftColorFree(xw.dpy, xw.vis, xw.cmap, &dc.col[x]); + dc.col[x] = ncolor; - return 0; + return 0; } /* * Absolute coordinates. */ void xclear(int x1, int y1, int x2, int y2) { - XftDrawRect(xw.draw, &dc.col[IS_SET(MODE_REVERSE) ? defaultfg : defaultbg], - x1, y1, x2 - x1, y2 - y1); + XftDrawRect(xw.draw, &dc.col[IS_SET(MODE_REVERSE) ? defaultfg : defaultbg], + x1, y1, x2 - x1, y2 - y1); } void xhints(void) { - XClassHint class = {opt_name ? opt_name : termname, - opt_class ? opt_class : termname}; - XWMHints wm = {.flags = InputHint, .input = 1}; - XSizeHints *sizeh; + XClassHint class = {opt_name ? opt_name : termname, + opt_class ? opt_class : termname}; + XWMHints wm = {.flags = InputHint, .input = 1}; + XSizeHints *sizeh; - sizeh = XAllocSizeHints(); + sizeh = XAllocSizeHints(); - sizeh->flags = PSize | PResizeInc | PBaseSize | PMinSize; - sizeh->height = win.h; - sizeh->width = win.w; - sizeh->height_inc = win.ch; - sizeh->width_inc = win.cw; - sizeh->base_height = 2 * borderpx; - sizeh->base_width = 2 * borderpx; - sizeh->min_height = win.ch + 2 * borderpx; - sizeh->min_width = win.cw + 2 * borderpx; - if (xw.isfixed) { - sizeh->flags |= PMaxSize; - sizeh->min_width = sizeh->max_width = win.w; - sizeh->min_height = sizeh->max_height = win.h; - } - if (xw.gm & (XValue | YValue)) { - sizeh->flags |= USPosition | PWinGravity; - sizeh->x = xw.l; - sizeh->y = xw.t; - sizeh->win_gravity = xgeommasktogravity(xw.gm); - } + sizeh->flags = PSize | PResizeInc | PBaseSize | PMinSize; + sizeh->height = win.h; + sizeh->width = win.w; + sizeh->height_inc = win.ch; + sizeh->width_inc = win.cw; + sizeh->base_height = 2 * borderpx; + sizeh->base_width = 2 * borderpx; + sizeh->min_height = win.ch + 2 * borderpx; + sizeh->min_width = win.cw + 2 * borderpx; + if (xw.isfixed) { + sizeh->flags |= PMaxSize; + sizeh->min_width = sizeh->max_width = win.w; + sizeh->min_height = sizeh->max_height = win.h; + } + if (xw.gm & (XValue | YValue)) { + sizeh->flags |= USPosition | PWinGravity; + sizeh->x = xw.l; + sizeh->y = xw.t; + sizeh->win_gravity = xgeommasktogravity(xw.gm); + } - XSetWMProperties(xw.dpy, xw.win, NULL, NULL, NULL, 0, sizeh, &wm, &class); - XFree(sizeh); + XSetWMProperties(xw.dpy, xw.win, NULL, NULL, NULL, 0, sizeh, &wm, &class); + XFree(sizeh); } int xgeommasktogravity(int mask) { - switch (mask & (XNegative | YNegative)) { - case 0: - return NorthWestGravity; - case XNegative: - return NorthEastGravity; - case YNegative: - return SouthWestGravity; - } + switch (mask & (XNegative | YNegative)) { + case 0: + return NorthWestGravity; + case XNegative: + return NorthEastGravity; + case YNegative: + return SouthWestGravity; + } - return SouthEastGravity; + return SouthEastGravity; } int xloadfont(Font *f, FcPattern *pattern) { - FcPattern *configured; - FcPattern *match; - FcResult result; - XGlyphInfo extents; - int wantattr, haveattr; + FcPattern *configured; + FcPattern *match; + FcResult result; + XGlyphInfo extents; + int wantattr, haveattr; - /* - * Manually configure instead of calling XftMatchFont - * so that we can use the configured pattern for - * "missing glyph" lookups. - */ - configured = FcPatternDuplicate(pattern); - if (!configured) - return 1; - - FcConfigSubstitute(NULL, configured, FcMatchPattern); - XftDefaultSubstitute(xw.dpy, xw.scr, configured); - - match = FcFontMatch(NULL, configured, &result); - if (!match) { - FcPatternDestroy(configured); - return 1; - } - - if (!(f->match = XftFontOpenPattern(xw.dpy, match))) { - FcPatternDestroy(configured); - FcPatternDestroy(match); - return 1; - } - - if ((XftPatternGetInteger(pattern, "slant", 0, &wantattr) == - XftResultMatch)) { /* - * Check if xft was unable to find a font with the appropriate - * slant but gave us one anyway. Try to mitigate. + * Manually configure instead of calling XftMatchFont + * so that we can use the configured pattern for + * "missing glyph" lookups. */ - if ((XftPatternGetInteger(f->match->pattern, "slant", 0, &haveattr) != - XftResultMatch) || - haveattr < wantattr) { - f->badslant = 1; - fputs("font slant does not match\n", stderr); + configured = FcPatternDuplicate(pattern); + if (!configured) + return 1; + + FcConfigSubstitute(NULL, configured, FcMatchPattern); + XftDefaultSubstitute(xw.dpy, xw.scr, configured); + + match = FcFontMatch(NULL, configured, &result); + if (!match) { + FcPatternDestroy(configured); + return 1; } - } - if ((XftPatternGetInteger(pattern, "weight", 0, &wantattr) == - XftResultMatch)) { - if ((XftPatternGetInteger(f->match->pattern, "weight", 0, &haveattr) != - XftResultMatch) || - haveattr != wantattr) { - f->badweight = 1; - fputs("font weight does not match\n", stderr); + if (!(f->match = XftFontOpenPattern(xw.dpy, match))) { + FcPatternDestroy(configured); + FcPatternDestroy(match); + return 1; } - } - XftTextExtentsUtf8(xw.dpy, f->match, (const FcChar8 *)ascii_printable, - strlen(ascii_printable), &extents); + if ((XftPatternGetInteger(pattern, "slant", 0, &wantattr) == + XftResultMatch)) { + /* + * Check if xft was unable to find a font with the appropriate + * slant but gave us one anyway. Try to mitigate. + */ + if ((XftPatternGetInteger(f->match->pattern, "slant", 0, &haveattr) != + XftResultMatch) || + haveattr < wantattr) { + f->badslant = 1; + fputs("font slant does not match\n", stderr); + } + } - f->set = NULL; - f->pattern = configured; + if ((XftPatternGetInteger(pattern, "weight", 0, &wantattr) == + XftResultMatch)) { + if ((XftPatternGetInteger(f->match->pattern, "weight", 0, &haveattr) != + XftResultMatch) || + haveattr != wantattr) { + f->badweight = 1; + fputs("font weight does not match\n", stderr); + } + } - f->ascent = f->match->ascent; - f->descent = f->match->descent; - f->lbearing = 0; - f->rbearing = f->match->max_advance_width; + XftTextExtentsUtf8(xw.dpy, f->match, (const FcChar8 *)ascii_printable, + strlen(ascii_printable), &extents); - f->height = f->ascent + f->descent; - f->width = DIVCEIL(extents.xOff, strlen(ascii_printable)); + f->set = NULL; + f->pattern = configured; - return 0; + f->ascent = f->match->ascent; + f->descent = f->match->descent; + f->lbearing = 0; + f->rbearing = f->match->max_advance_width; + + f->height = f->ascent + f->descent; + f->width = DIVCEIL(extents.xOff, strlen(ascii_printable)); + + return 0; } void xloadfonts(char *fontstr, double fontsize) { - FcPattern *pattern; - double fontval; + FcPattern *pattern; + double fontval; - if (fontstr[0] == '-') - pattern = XftXlfdParse(fontstr, False, False); - else - pattern = FcNameParse((FcChar8 *)fontstr); + if (fontstr[0] == '-') + pattern = XftXlfdParse(fontstr, False, False); + else + pattern = FcNameParse((FcChar8 *)fontstr); - if (!pattern) - die("can't open font %s\n", fontstr); + if (!pattern) + die("can't open font %s\n", fontstr); - if (fontsize > 1) { - FcPatternDel(pattern, FC_PIXEL_SIZE); - FcPatternDel(pattern, FC_SIZE); - FcPatternAddDouble(pattern, FC_PIXEL_SIZE, (double)fontsize); - usedfontsize = fontsize; - } else { - if (FcPatternGetDouble(pattern, FC_PIXEL_SIZE, 0, &fontval) == - FcResultMatch) { - usedfontsize = fontval; - } else if (FcPatternGetDouble(pattern, FC_SIZE, 0, &fontval) == - FcResultMatch) { - usedfontsize = -1; + if (fontsize > 1) { + FcPatternDel(pattern, FC_PIXEL_SIZE); + FcPatternDel(pattern, FC_SIZE); + FcPatternAddDouble(pattern, FC_PIXEL_SIZE, (double)fontsize); + usedfontsize = fontsize; } else { - /* - * Default font size is 12, if none given. This is to - * have a known usedfontsize value. - */ - FcPatternAddDouble(pattern, FC_PIXEL_SIZE, 12); - usedfontsize = 12; + if (FcPatternGetDouble(pattern, FC_PIXEL_SIZE, 0, &fontval) == + FcResultMatch) { + usedfontsize = fontval; + } else if (FcPatternGetDouble(pattern, FC_SIZE, 0, &fontval) == + FcResultMatch) { + usedfontsize = -1; + } else { + /* + * Default font size is 12, if none given. This is to + * have a known usedfontsize value. + */ + FcPatternAddDouble(pattern, FC_PIXEL_SIZE, 12); + usedfontsize = 12; + } + defaultfontsize = usedfontsize; } - defaultfontsize = usedfontsize; - } - if (xloadfont(&dc.font, pattern)) - die("can't open font %s\n", fontstr); + if (xloadfont(&dc.font, pattern)) + die("can't open font %s\n", fontstr); - if (usedfontsize < 0) { - FcPatternGetDouble(dc.font.match->pattern, FC_PIXEL_SIZE, 0, &fontval); - usedfontsize = fontval; - if (fontsize == 0) - defaultfontsize = fontval; - } + if (usedfontsize < 0) { + FcPatternGetDouble(dc.font.match->pattern, FC_PIXEL_SIZE, 0, &fontval); + usedfontsize = fontval; + if (fontsize == 0) + defaultfontsize = fontval; + } - /* Setting character width and height. */ - win.cw = ceilf(dc.font.width * cwscale); - win.ch = ceilf(dc.font.height * chscale); + /* Setting character width and height. */ + win.cw = ceilf(dc.font.width * cwscale); + win.ch = ceilf(dc.font.height * chscale); - FcPatternDel(pattern, FC_SLANT); - FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC); - if (xloadfont(&dc.ifont, pattern)) - die("can't open font %s\n", fontstr); + FcPatternDel(pattern, FC_SLANT); + FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC); + if (xloadfont(&dc.ifont, pattern)) + die("can't open font %s\n", fontstr); - FcPatternDel(pattern, FC_WEIGHT); - FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_BOLD); - if (xloadfont(&dc.ibfont, pattern)) - die("can't open font %s\n", fontstr); + FcPatternDel(pattern, FC_WEIGHT); + FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_BOLD); + if (xloadfont(&dc.ibfont, pattern)) + die("can't open font %s\n", fontstr); - FcPatternDel(pattern, FC_SLANT); - FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ROMAN); - if (xloadfont(&dc.bfont, pattern)) - die("can't open font %s\n", fontstr); + FcPatternDel(pattern, FC_SLANT); + FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ROMAN); + if (xloadfont(&dc.bfont, pattern)) + die("can't open font %s\n", fontstr); - FcPatternDestroy(pattern); + FcPatternDestroy(pattern); } void xunloadfont(Font *f) { - XftFontClose(xw.dpy, f->match); - FcPatternDestroy(f->pattern); - if (f->set) - FcFontSetDestroy(f->set); + XftFontClose(xw.dpy, f->match); + FcPatternDestroy(f->pattern); + if (f->set) + FcFontSetDestroy(f->set); } void xunloadfonts(void) { - /* Free the loaded fonts in the font cache. */ - while (frclen > 0) - XftFontClose(xw.dpy, frc[--frclen].font); + /* Free the loaded fonts in the font cache. */ + while (frclen > 0) + XftFontClose(xw.dpy, frc[--frclen].font); - xunloadfont(&dc.font); - xunloadfont(&dc.bfont); - xunloadfont(&dc.ifont); - xunloadfont(&dc.ibfont); + xunloadfont(&dc.font); + xunloadfont(&dc.bfont); + xunloadfont(&dc.ifont); + xunloadfont(&dc.ibfont); } int ximopen(Display *dpy) { - XIMCallback imdestroy = {.client_data = NULL, .callback = ximdestroy}; - XICCallback icdestroy = {.client_data = NULL, .callback = xicdestroy}; + XIMCallback imdestroy = {.client_data = NULL, .callback = ximdestroy}; + XICCallback icdestroy = {.client_data = NULL, .callback = xicdestroy}; - xw.ime.xim = XOpenIM(xw.dpy, NULL, NULL, NULL); - if (xw.ime.xim == NULL) - return 0; + xw.ime.xim = XOpenIM(xw.dpy, NULL, NULL, NULL); + if (xw.ime.xim == NULL) + return 0; - if (XSetIMValues(xw.ime.xim, XNDestroyCallback, &imdestroy, NULL)) - fprintf(stderr, "XSetIMValues: " - "Could not set XNDestroyCallback.\n"); + if (XSetIMValues(xw.ime.xim, XNDestroyCallback, &imdestroy, NULL)) + fprintf(stderr, "XSetIMValues: " + "Could not set XNDestroyCallback.\n"); - xw.ime.spotlist = XVaCreateNestedList(0, XNSpotLocation, &xw.ime.spot, NULL); + xw.ime.spotlist = + XVaCreateNestedList(0, XNSpotLocation, &xw.ime.spot, NULL); - if (xw.ime.xic == NULL) { - xw.ime.xic = XCreateIC(xw.ime.xim, XNInputStyle, - XIMPreeditNothing | XIMStatusNothing, XNClientWindow, - xw.win, XNDestroyCallback, &icdestroy, NULL); - } - if (xw.ime.xic == NULL) - fprintf(stderr, "XCreateIC: Could not create input context.\n"); + if (xw.ime.xic == NULL) { + xw.ime.xic = XCreateIC( + xw.ime.xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing, + XNClientWindow, xw.win, XNDestroyCallback, &icdestroy, NULL); + } + if (xw.ime.xic == NULL) + fprintf(stderr, "XCreateIC: Could not create input context.\n"); - return 1; + return 1; } void ximinstantiate(Display *dpy, XPointer client, XPointer call) { - if (ximopen(dpy)) - XUnregisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, ximinstantiate, - NULL); + if (ximopen(dpy)) + XUnregisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, + ximinstantiate, NULL); } void ximdestroy(XIM xim, XPointer client, XPointer call) { - xw.ime.xim = NULL; - XRegisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, ximinstantiate, - NULL); - XFree(xw.ime.spotlist); + xw.ime.xim = NULL; + XRegisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, ximinstantiate, + NULL); + XFree(xw.ime.spotlist); } int xicdestroy(XIC xim, XPointer client, XPointer call) { - xw.ime.xic = NULL; - return 1; + xw.ime.xic = NULL; + return 1; } void xinit(int cols, int rows) { - XGCValues gcvalues; - Cursor cursor; - Window parent; - pid_t thispid = getpid(); - XColor xmousefg, xmousebg; + XGCValues gcvalues; + Cursor cursor; + Window parent; + pid_t thispid = getpid(); + XColor xmousefg, xmousebg; - if (!(xw.dpy = XOpenDisplay(NULL))) - die("can't open display\n"); - xw.scr = XDefaultScreen(xw.dpy); - xw.vis = XDefaultVisual(xw.dpy, xw.scr); + if (!(xw.dpy = XOpenDisplay(NULL))) + die("can't open display\n"); + xw.scr = XDefaultScreen(xw.dpy); + xw.vis = XDefaultVisual(xw.dpy, xw.scr); - /* font */ - if (!FcInit()) - die("could not init fontconfig.\n"); + /* font */ + if (!FcInit()) + die("could not init fontconfig.\n"); - usedfont = (opt_font == NULL) ? font : opt_font; - xloadfonts(usedfont, 0); + usedfont = (opt_font == NULL) ? font : opt_font; + xloadfonts(usedfont, 0); - /* colors */ - xw.cmap = XDefaultColormap(xw.dpy, xw.scr); - xloadcols(); + /* colors */ + xw.cmap = XDefaultColormap(xw.dpy, xw.scr); + xloadcols(); - /* adjust fixed window geometry */ - win.w = 2 * borderpx + cols * win.cw; - win.h = 2 * borderpx + rows * win.ch; - if (xw.gm & XNegative) - xw.l += DisplayWidth(xw.dpy, xw.scr) - win.w - 2; - if (xw.gm & YNegative) - xw.t += DisplayHeight(xw.dpy, xw.scr) - win.h - 2; + /* adjust fixed window geometry */ + win.w = 2 * borderpx + cols * win.cw; + win.h = 2 * borderpx + rows * win.ch; + if (xw.gm & XNegative) + xw.l += DisplayWidth(xw.dpy, xw.scr) - win.w - 2; + if (xw.gm & YNegative) + xw.t += DisplayHeight(xw.dpy, xw.scr) - win.h - 2; - /* Events */ - xw.attrs.background_pixel = dc.col[defaultbg].pixel; - xw.attrs.border_pixel = dc.col[defaultbg].pixel; - xw.attrs.bit_gravity = NorthWestGravity; - xw.attrs.event_mask = FocusChangeMask | KeyPressMask | KeyReleaseMask | - ExposureMask | VisibilityChangeMask | - StructureNotifyMask | ButtonMotionMask | - ButtonPressMask | ButtonReleaseMask; - xw.attrs.colormap = xw.cmap; + /* Events */ + xw.attrs.background_pixel = dc.col[defaultbg].pixel; + xw.attrs.border_pixel = dc.col[defaultbg].pixel; + xw.attrs.bit_gravity = NorthWestGravity; + xw.attrs.event_mask = FocusChangeMask | KeyPressMask | KeyReleaseMask | + ExposureMask | VisibilityChangeMask | + StructureNotifyMask | ButtonMotionMask | + ButtonPressMask | ButtonReleaseMask; + xw.attrs.colormap = xw.cmap; - if (!(opt_embed && (parent = strtol(opt_embed, NULL, 0)))) - parent = XRootWindow(xw.dpy, xw.scr); - xw.win = XCreateWindow(xw.dpy, parent, xw.l, xw.t, win.w, win.h, 0, - XDefaultDepth(xw.dpy, xw.scr), InputOutput, xw.vis, - CWBackPixel | CWBorderPixel | CWBitGravity | - CWEventMask | CWColormap, - &xw.attrs); + if (!(opt_embed && (parent = strtol(opt_embed, NULL, 0)))) + parent = XRootWindow(xw.dpy, xw.scr); + xw.win = XCreateWindow(xw.dpy, parent, xw.l, xw.t, win.w, win.h, 0, + XDefaultDepth(xw.dpy, xw.scr), InputOutput, xw.vis, + CWBackPixel | CWBorderPixel | CWBitGravity | + CWEventMask | CWColormap, + &xw.attrs); - memset(&gcvalues, 0, sizeof(gcvalues)); - gcvalues.graphics_exposures = False; - dc.gc = XCreateGC(xw.dpy, parent, GCGraphicsExposures, &gcvalues); - xw.buf = - XCreatePixmap(xw.dpy, xw.win, win.w, win.h, DefaultDepth(xw.dpy, xw.scr)); - XSetForeground(xw.dpy, dc.gc, dc.col[defaultbg].pixel); - XFillRectangle(xw.dpy, xw.buf, dc.gc, 0, 0, win.w, win.h); + memset(&gcvalues, 0, sizeof(gcvalues)); + gcvalues.graphics_exposures = False; + dc.gc = XCreateGC(xw.dpy, parent, GCGraphicsExposures, &gcvalues); + xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, + DefaultDepth(xw.dpy, xw.scr)); + XSetForeground(xw.dpy, dc.gc, dc.col[defaultbg].pixel); + XFillRectangle(xw.dpy, xw.buf, dc.gc, 0, 0, win.w, win.h); - /* font spec buffer */ - xw.specbuf = safe_malloc(cols * sizeof(GlyphFontSpec)); + /* font spec buffer */ + xw.specbuf = safe_malloc(cols * sizeof(GlyphFontSpec)); - /* Xft rendering context */ - xw.draw = XftDrawCreate(xw.dpy, xw.buf, xw.vis, xw.cmap); + /* Xft rendering context */ + xw.draw = XftDrawCreate(xw.dpy, xw.buf, xw.vis, xw.cmap); - /* input methods */ - if (!ximopen(xw.dpy)) { - XRegisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, ximinstantiate, - NULL); - } + /* input methods */ + if (!ximopen(xw.dpy)) { + XRegisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, + ximinstantiate, NULL); + } - /* white cursor, black outline */ - cursor = XCreateFontCursor(xw.dpy, mouseshape); - XDefineCursor(xw.dpy, xw.win, cursor); + /* white cursor, black outline */ + cursor = XCreateFontCursor(xw.dpy, mouseshape); + XDefineCursor(xw.dpy, xw.win, cursor); - if (XParseColor(xw.dpy, xw.cmap, colorname[mousefg], &xmousefg) == 0) { - xmousefg.red = 0xffff; - xmousefg.green = 0xffff; - xmousefg.blue = 0xffff; - } + if (XParseColor(xw.dpy, xw.cmap, colorname[mousefg], &xmousefg) == 0) { + xmousefg.red = 0xffff; + xmousefg.green = 0xffff; + xmousefg.blue = 0xffff; + } - if (XParseColor(xw.dpy, xw.cmap, colorname[mousebg], &xmousebg) == 0) { - xmousebg.red = 0x0000; - xmousebg.green = 0x0000; - xmousebg.blue = 0x0000; - } + if (XParseColor(xw.dpy, xw.cmap, colorname[mousebg], &xmousebg) == 0) { + xmousebg.red = 0x0000; + xmousebg.green = 0x0000; + xmousebg.blue = 0x0000; + } - XRecolorCursor(xw.dpy, cursor, &xmousefg, &xmousebg); + XRecolorCursor(xw.dpy, cursor, &xmousefg, &xmousebg); - xw.xembed = XInternAtom(xw.dpy, "_XEMBED", False); - xw.wmdeletewin = XInternAtom(xw.dpy, "WM_DELETE_WINDOW", False); - xw.netwmname = XInternAtom(xw.dpy, "_NET_WM_NAME", False); - xw.netwmiconname = XInternAtom(xw.dpy, "_NET_WM_ICON_NAME", False); - XSetWMProtocols(xw.dpy, xw.win, &xw.wmdeletewin, 1); + xw.xembed = XInternAtom(xw.dpy, "_XEMBED", False); + xw.wmdeletewin = XInternAtom(xw.dpy, "WM_DELETE_WINDOW", False); + xw.netwmname = XInternAtom(xw.dpy, "_NET_WM_NAME", False); + xw.netwmiconname = XInternAtom(xw.dpy, "_NET_WM_ICON_NAME", False); + XSetWMProtocols(xw.dpy, xw.win, &xw.wmdeletewin, 1); - xw.netwmpid = XInternAtom(xw.dpy, "_NET_WM_PID", False); - XChangeProperty(xw.dpy, xw.win, xw.netwmpid, XA_CARDINAL, 32, PropModeReplace, - (uchar *)&thispid, 1); + xw.netwmpid = XInternAtom(xw.dpy, "_NET_WM_PID", False); + XChangeProperty(xw.dpy, xw.win, xw.netwmpid, XA_CARDINAL, 32, + PropModeReplace, (uchar *)&thispid, 1); - win.mode = MODE_NUMLOCK; - resettitle(); - xhints(); - XMapWindow(xw.dpy, xw.win); - XSync(xw.dpy, False); + win.mode = MODE_NUMLOCK; + resettitle(); + xhints(); + XMapWindow(xw.dpy, xw.win); + XSync(xw.dpy, False); - clock_gettime(CLOCK_MONOTONIC, &xsel.tclick1); - clock_gettime(CLOCK_MONOTONIC, &xsel.tclick2); - xsel.primary = NULL; - xsel.clipboard = NULL; - xsel.xtarget = XInternAtom(xw.dpy, "UTF8_STRING", 0); - if (xsel.xtarget == None) - xsel.xtarget = XA_STRING; + clock_gettime(CLOCK_MONOTONIC, &xsel.tclick1); + clock_gettime(CLOCK_MONOTONIC, &xsel.tclick2); + xsel.primary = NULL; + xsel.clipboard = NULL; + xsel.xtarget = XInternAtom(xw.dpy, "UTF8_STRING", 0); + if (xsel.xtarget == None) + xsel.xtarget = XA_STRING; } int xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x, int y) { - float winx = borderpx + x * win.cw, winy = borderpx + y * win.ch, xp, yp; - ushort mode, prevmode = USHRT_MAX; - Font *font = &dc.font; - int frcflags = FRC_NORMAL; - float runewidth = win.cw; - Rune rune; - FT_UInt glyphidx; - FcResult fcres; - FcPattern *fcpattern, *fontpattern; - FcFontSet *fcsets[] = {NULL}; - FcCharSet *fccharset; - int i, f, numspecs = 0; + float winx = borderpx + x * win.cw, winy = borderpx + y * win.ch, xp, yp; + ushort mode, prevmode = USHRT_MAX; + Font * font = &dc.font; + int frcflags = FRC_NORMAL; + float runewidth = win.cw; + Rune rune; + FT_UInt glyphidx; + FcResult fcres; + FcPattern *fcpattern, *fontpattern; + FcFontSet *fcsets[] = {NULL}; + FcCharSet *fccharset; + int i, f, numspecs = 0; - for (i = 0, xp = winx, yp = winy + font->ascent; i < len; ++i) { - /* Fetch rune and mode for current glyph. */ - rune = glyphs[i].u; - mode = glyphs[i].mode; + for (i = 0, xp = winx, yp = winy + font->ascent; i < len; ++i) { + /* Fetch rune and mode for current glyph. */ + rune = glyphs[i].u; + mode = glyphs[i].mode; - /* Skip dummy wide-character spacing. */ - if (mode == ATTR_WDUMMY) - continue; + /* Skip dummy wide-character spacing. */ + if (mode == ATTR_WDUMMY) + continue; - /* Determine font for glyph if different from previous glyph. */ - if (prevmode != mode) { - prevmode = mode; - font = &dc.font; - frcflags = FRC_NORMAL; - runewidth = win.cw * ((mode & ATTR_WIDE) ? 2.0f : 1.0f); - if ((mode & ATTR_ITALIC) && (mode & ATTR_BOLD)) { - font = &dc.ibfont; - frcflags = FRC_ITALICBOLD; - } else if (mode & ATTR_ITALIC) { - font = &dc.ifont; - frcflags = FRC_ITALIC; - } else if (mode & ATTR_BOLD) { - font = &dc.bfont; - frcflags = FRC_BOLD; - } - yp = winy + font->ascent; + /* Determine font for glyph if different from previous glyph. */ + if (prevmode != mode) { + prevmode = mode; + font = &dc.font; + frcflags = FRC_NORMAL; + runewidth = win.cw * ((mode & ATTR_WIDE) ? 2.0f : 1.0f); + if ((mode & ATTR_ITALIC) && (mode & ATTR_BOLD)) { + font = &dc.ibfont; + frcflags = FRC_ITALICBOLD; + } else if (mode & ATTR_ITALIC) { + font = &dc.ifont; + frcflags = FRC_ITALIC; + } else if (mode & ATTR_BOLD) { + font = &dc.bfont; + frcflags = FRC_BOLD; + } + yp = winy + font->ascent; + } + + /* Lookup character index with default font. */ + glyphidx = XftCharIndex(xw.dpy, font->match, rune); + if (glyphidx) { + specs[numspecs].font = font->match; + specs[numspecs].glyph = glyphidx; + specs[numspecs].x = (short)xp; + specs[numspecs].y = (short)yp; + xp += runewidth; + numspecs++; + continue; + } + + /* Fallback on font cache, search the font cache for match. */ + for (f = 0; f < frclen; f++) { + glyphidx = XftCharIndex(xw.dpy, frc[f].font, rune); + /* Everything correct. */ + if (glyphidx && frc[f].flags == frcflags) + break; + /* We got a default font for a not found glyph. */ + if (!glyphidx && frc[f].flags == frcflags && + frc[f].unicodep == rune) { + break; + } + } + + /* Nothing was found. Use fontconfig to find matching font. */ + if (f >= frclen) { + if (!font->set) + font->set = FcFontSort(0, font->pattern, 1, 0, &fcres); + fcsets[0] = font->set; + + /* + * Nothing was found in the cache. Now use + * some dozen of Fontconfig calls to get the + * font for one single character. + * + * Xft and fontconfig are design failures. + */ + fcpattern = FcPatternDuplicate(font->pattern); + fccharset = FcCharSetCreate(); + + FcCharSetAddChar(fccharset, rune); + FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset); + FcPatternAddBool(fcpattern, FC_SCALABLE, 1); + + FcConfigSubstitute(0, fcpattern, FcMatchPattern); + FcDefaultSubstitute(fcpattern); + + fontpattern = FcFontSetMatch(0, fcsets, 1, fcpattern, &fcres); + + /* Allocate memory for the new cache entry. */ + if (frclen >= frccap) { + frccap += 16; + frc = safe_realloc(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++; } - /* Lookup character index with default font. */ - glyphidx = XftCharIndex(xw.dpy, font->match, rune); - if (glyphidx) { - specs[numspecs].font = font->match; - specs[numspecs].glyph = glyphidx; - specs[numspecs].x = (short)xp; - specs[numspecs].y = (short)yp; - xp += runewidth; - numspecs++; - continue; - } - - /* Fallback on font cache, search the font cache for match. */ - for (f = 0; f < frclen; f++) { - glyphidx = XftCharIndex(xw.dpy, frc[f].font, rune); - /* Everything correct. */ - if (glyphidx && frc[f].flags == frcflags) - break; - /* We got a default font for a not found glyph. */ - if (!glyphidx && frc[f].flags == frcflags && frc[f].unicodep == rune) { - break; - } - } - - /* Nothing was found. Use fontconfig to find matching font. */ - if (f >= frclen) { - if (!font->set) - font->set = FcFontSort(0, font->pattern, 1, 0, &fcres); - fcsets[0] = font->set; - - /* - * Nothing was found in the cache. Now use - * some dozen of Fontconfig calls to get the - * font for one single character. - * - * Xft and fontconfig are design failures. - */ - fcpattern = FcPatternDuplicate(font->pattern); - fccharset = FcCharSetCreate(); - - FcCharSetAddChar(fccharset, rune); - FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset); - FcPatternAddBool(fcpattern, FC_SCALABLE, 1); - - FcConfigSubstitute(0, fcpattern, FcMatchPattern); - FcDefaultSubstitute(fcpattern); - - fontpattern = FcFontSetMatch(0, fcsets, 1, fcpattern, &fcres); - - /* Allocate memory for the new cache entry. */ - if (frclen >= frccap) { - frccap += 16; - frc = safe_realloc(frc, frccap * sizeof(Fontcache)); - } - - frc[frclen].font = XftFontOpenPattern(xw.dpy, fontpattern); - if (!frc[frclen].font) - die("XftFontOpenPattern failed seeking fallback font: %s\n", - strerror(errno)); - frc[frclen].flags = frcflags; - frc[frclen].unicodep = rune; - - glyphidx = XftCharIndex(xw.dpy, frc[frclen].font, rune); - - f = frclen; - frclen++; - - FcPatternDestroy(fcpattern); - FcCharSetDestroy(fccharset); - } - - specs[numspecs].font = frc[f].font; - specs[numspecs].glyph = glyphidx; - specs[numspecs].x = (short)xp; - specs[numspecs].y = (short)yp; - xp += runewidth; - numspecs++; - } - - return numspecs; + return numspecs; } void xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y) { - int charlen = len * ((base.mode & ATTR_WIDE) ? 2 : 1); - int winx = borderpx + x * win.cw, winy = borderpx + y * win.ch, - width = charlen * win.cw; - Color *fg, *bg, *temp, revfg, revbg, truefg, truebg; - XRenderColor colfg, colbg; - XRectangle r; + int charlen = len * ((base.mode & ATTR_WIDE) ? 2 : 1); + int winx = borderpx + x * win.cw, winy = borderpx + y * win.ch, + width = charlen * win.cw; + Color * fg, *bg, *temp, revfg, revbg, truefg, truebg; + XRenderColor colfg, colbg; + XRectangle r; - /* Fallback on color display for attributes not supported by the font */ - if (base.mode & ATTR_ITALIC && base.mode & ATTR_BOLD) { - if (dc.ibfont.badslant || dc.ibfont.badweight) - base.fg = defaultattr; - } else if ((base.mode & ATTR_ITALIC && dc.ifont.badslant) || - (base.mode & ATTR_BOLD && dc.bfont.badweight)) { - base.fg = defaultattr; - } - - if (IS_TRUECOL(base.fg)) { - colfg.alpha = 0xffff; - colfg.red = TRUERED(base.fg); - colfg.green = TRUEGREEN(base.fg); - colfg.blue = TRUEBLUE(base.fg); - XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colfg, &truefg); - fg = &truefg; - } else { - fg = &dc.col[base.fg]; - } - - if (IS_TRUECOL(base.bg)) { - colbg.alpha = 0xffff; - colbg.green = TRUEGREEN(base.bg); - colbg.red = TRUERED(base.bg); - colbg.blue = TRUEBLUE(base.bg); - XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colbg, &truebg); - bg = &truebg; - } else { - bg = &dc.col[base.bg]; - } - - /* Change basic system colors [0-7] to bright system colors [8-15] */ - if ((base.mode & ATTR_BOLD_FAINT) == ATTR_BOLD && BETWEEN(base.fg, 0, 7)) - fg = &dc.col[base.fg + 8]; - - if (IS_SET(MODE_REVERSE)) { - if (fg == &dc.col[defaultfg]) { - fg = &dc.col[defaultbg]; - } else { - colfg.red = ~fg->color.red; - colfg.green = ~fg->color.green; - colfg.blue = ~fg->color.blue; - colfg.alpha = fg->color.alpha; - XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colfg, &revfg); - fg = &revfg; + /* Fallback on color display for attributes not supported by the font */ + if (base.mode & ATTR_ITALIC && base.mode & ATTR_BOLD) { + if (dc.ibfont.badslant || dc.ibfont.badweight) + base.fg = defaultattr; + } else if ((base.mode & ATTR_ITALIC && dc.ifont.badslant) || + (base.mode & ATTR_BOLD && dc.bfont.badweight)) { + base.fg = defaultattr; } - if (bg == &dc.col[defaultbg]) { - bg = &dc.col[defaultfg]; + if (IS_TRUECOL(base.fg)) { + colfg.alpha = 0xffff; + colfg.red = TRUERED(base.fg); + colfg.green = TRUEGREEN(base.fg); + colfg.blue = TRUEBLUE(base.fg); + XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colfg, &truefg); + fg = &truefg; } else { - colbg.red = ~bg->color.red; - colbg.green = ~bg->color.green; - colbg.blue = ~bg->color.blue; - colbg.alpha = bg->color.alpha; - XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colbg, &revbg); - bg = &revbg; + fg = &dc.col[base.fg]; } - } - if ((base.mode & ATTR_BOLD_FAINT) == ATTR_FAINT) { - colfg.red = fg->color.red / 2; - colfg.green = fg->color.green / 2; - colfg.blue = fg->color.blue / 2; - colfg.alpha = fg->color.alpha; - XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colfg, &revfg); - fg = &revfg; - } + if (IS_TRUECOL(base.bg)) { + colbg.alpha = 0xffff; + colbg.green = TRUEGREEN(base.bg); + colbg.red = TRUERED(base.bg); + colbg.blue = TRUEBLUE(base.bg); + XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colbg, &truebg); + bg = &truebg; + } else { + bg = &dc.col[base.bg]; + } - if (base.mode & ATTR_REVERSE) { - temp = fg; - fg = bg; - bg = temp; - } + /* Change basic system colors [0-7] to bright system colors [8-15] */ + if ((base.mode & ATTR_BOLD_FAINT) == ATTR_BOLD && BETWEEN(base.fg, 0, 7)) + fg = &dc.col[base.fg + 8]; - if (base.mode & ATTR_BLINK && win.mode & MODE_BLINK) - fg = bg; + if (IS_SET(MODE_REVERSE)) { + if (fg == &dc.col[defaultfg]) { + fg = &dc.col[defaultbg]; + } else { + colfg.red = ~fg->color.red; + colfg.green = ~fg->color.green; + colfg.blue = ~fg->color.blue; + colfg.alpha = fg->color.alpha; + XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colfg, &revfg); + fg = &revfg; + } - if (base.mode & ATTR_INVISIBLE) - fg = bg; + if (bg == &dc.col[defaultbg]) { + bg = &dc.col[defaultfg]; + } else { + colbg.red = ~bg->color.red; + colbg.green = ~bg->color.green; + colbg.blue = ~bg->color.blue; + colbg.alpha = bg->color.alpha; + XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colbg, &revbg); + bg = &revbg; + } + } - /* Intelligent cleaning up of the borders. */ - if (x == 0) { - xclear(0, (y == 0) ? 0 : winy, borderpx, - winy + win.ch + ((winy + win.ch >= borderpx + win.th) ? win.h : 0)); - } - if (winx + width >= borderpx + win.tw) { - xclear(winx + width, (y == 0) ? 0 : winy, win.w, - ((winy + win.ch >= borderpx + win.th) ? win.h : (winy + win.ch))); - } - if (y == 0) - xclear(winx, 0, winx + width, borderpx); - if (winy + win.ch >= borderpx + win.th) - xclear(winx, winy + win.ch, winx + width, win.h); + if ((base.mode & ATTR_BOLD_FAINT) == ATTR_FAINT) { + colfg.red = fg->color.red / 2; + colfg.green = fg->color.green / 2; + colfg.blue = fg->color.blue / 2; + colfg.alpha = fg->color.alpha; + XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colfg, &revfg); + fg = &revfg; + } - /* Clean up the region we want to draw to. */ - XftDrawRect(xw.draw, bg, winx, winy, width, win.ch); + if (base.mode & ATTR_REVERSE) { + temp = fg; + fg = bg; + bg = temp; + } - /* Set the clip region because Xft is sometimes dirty. */ - r.x = 0; - r.y = 0; - r.height = win.ch; - r.width = width; - XftDrawSetClipRectangles(xw.draw, winx, winy, &r, 1); + if (base.mode & ATTR_BLINK && win.mode & MODE_BLINK) + fg = bg; - /* Render the glyphs. */ - XftDrawGlyphFontSpec(xw.draw, fg, specs, len); + if (base.mode & ATTR_INVISIBLE) + fg = bg; - /* Render underline and strikethrough. */ - if (base.mode & ATTR_UNDERLINE) { - XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent + 1, width, 1); - } + /* Intelligent cleaning up of the borders. */ + if (x == 0) { + xclear(0, (y == 0) ? 0 : winy, borderpx, + winy + win.ch + + ((winy + win.ch >= borderpx + win.th) ? win.h : 0)); + } + if (winx + width >= borderpx + win.tw) { + xclear( + winx + width, (y == 0) ? 0 : winy, win.w, + ((winy + win.ch >= borderpx + win.th) ? win.h : (winy + win.ch))); + } + if (y == 0) + xclear(winx, 0, winx + width, borderpx); + if (winy + win.ch >= borderpx + win.th) + xclear(winx, winy + win.ch, winx + width, win.h); - if (base.mode & ATTR_STRUCK) { - XftDrawRect(xw.draw, fg, winx, winy + 2 * dc.font.ascent / 3, width, 1); - } + /* Clean up the region we want to draw to. */ + XftDrawRect(xw.draw, bg, winx, winy, width, win.ch); - /* Reset clip to none. */ - XftDrawSetClip(xw.draw, 0); + /* Set the clip region because Xft is sometimes dirty. */ + r.x = 0; + r.y = 0; + r.height = win.ch; + r.width = width; + XftDrawSetClipRectangles(xw.draw, winx, winy, &r, 1); + + /* Render the glyphs. */ + XftDrawGlyphFontSpec(xw.draw, fg, specs, len); + + /* Render underline and strikethrough. */ + if (base.mode & ATTR_UNDERLINE) { + XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent + 1, width, 1); + } + + if (base.mode & ATTR_STRUCK) { + XftDrawRect(xw.draw, fg, winx, winy + 2 * dc.font.ascent / 3, width, + 1); + } + + /* Reset clip to none. */ + XftDrawSetClip(xw.draw, 0); } void xdrawglyph(Glyph g, int x, int y) { - int numspecs; - XftGlyphFontSpec spec; + int numspecs; + XftGlyphFontSpec spec; - numspecs = xmakeglyphfontspecs(&spec, &g, 1, x, y); - xdrawglyphfontspecs(&spec, g, numspecs, x, y); + numspecs = xmakeglyphfontspecs(&spec, &g, 1, x, y); + xdrawglyphfontspecs(&spec, g, numspecs, x, y); } void xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og) { - Color drawcol; + Color drawcol; - /* remove the old cursor */ - if (selected(ox, oy)) - og.mode ^= ATTR_REVERSE; - xdrawglyph(og, ox, oy); + /* remove the old cursor */ + if (selected(ox, oy)) + og.mode ^= ATTR_REVERSE; + xdrawglyph(og, ox, oy); - if (IS_SET(MODE_HIDE)) - return; + if (IS_SET(MODE_HIDE)) + return; - /* - * Select the right color for the right mode. - */ - g.mode &= ATTR_BOLD | ATTR_ITALIC | ATTR_UNDERLINE | ATTR_STRUCK | ATTR_WIDE; + /* + * Select the right color for the right mode. + */ + g.mode &= + ATTR_BOLD | ATTR_ITALIC | ATTR_UNDERLINE | ATTR_STRUCK | ATTR_WIDE; - if (IS_SET(MODE_REVERSE)) { - g.mode |= ATTR_REVERSE; - g.bg = defaultfg; - if (selected(cx, cy)) { - drawcol = dc.col[defaultcs]; - g.fg = defaultrcs; + if (IS_SET(MODE_REVERSE)) { + g.mode |= ATTR_REVERSE; + g.bg = defaultfg; + if (selected(cx, cy)) { + drawcol = dc.col[defaultcs]; + g.fg = defaultrcs; + } else { + drawcol = dc.col[defaultrcs]; + g.fg = defaultcs; + } } else { - drawcol = dc.col[defaultrcs]; - g.fg = defaultcs; + if (selected(cx, cy)) { + g.fg = defaultfg; + g.bg = defaultrcs; + } else { + g.fg = defaultbg; + g.bg = defaultcs; + } + drawcol = dc.col[g.bg]; } - } else { - if (selected(cx, cy)) { - g.fg = defaultfg; - g.bg = defaultrcs; - } else { - g.fg = defaultbg; - g.bg = defaultcs; - } - drawcol = dc.col[g.bg]; - } - /* draw the new one */ - if (IS_SET(MODE_FOCUSED)) { - switch (win.cursor) { - case 7: /* st extension */ - g.u = 0x2603; /* snowman (U+2603) */ - /* FALLTHROUGH */ - case 0: /* Blinking Block */ - case 1: /* Blinking Block (Default) */ - case 2: /* Steady Block */ - xdrawglyph(g, cx, cy); - break; - case 3: /* Blinking Underline */ - case 4: /* Steady Underline */ - XftDrawRect(xw.draw, &drawcol, borderpx + cx * win.cw, - borderpx + (cy + 1) * win.ch - cursorthickness, win.cw, - cursorthickness); - break; - case 5: /* Blinking bar */ - case 6: /* Steady bar */ - XftDrawRect(xw.draw, &drawcol, borderpx + cx * win.cw, - borderpx + cy * win.ch, cursorthickness, win.ch); - break; + /* draw the new one */ + if (IS_SET(MODE_FOCUSED)) { + switch (win.cursor) { + case 7: /* st extension */ + g.u = 0x2603; /* snowman (U+2603) */ + /* FALLTHROUGH */ + case 0: /* Blinking Block */ + case 1: /* Blinking Block (Default) */ + case 2: /* Steady Block */ + xdrawglyph(g, cx, cy); + break; + case 3: /* Blinking Underline */ + case 4: /* Steady Underline */ + XftDrawRect(xw.draw, &drawcol, borderpx + cx * win.cw, + borderpx + (cy + 1) * win.ch - cursorthickness, win.cw, + cursorthickness); + break; + case 5: /* Blinking bar */ + case 6: /* Steady bar */ + XftDrawRect(xw.draw, &drawcol, borderpx + cx * win.cw, + borderpx + cy * win.ch, cursorthickness, win.ch); + break; + } + } else { + XftDrawRect(xw.draw, &drawcol, borderpx + cx * win.cw, + borderpx + cy * win.ch, win.cw - 1, 1); + XftDrawRect(xw.draw, &drawcol, borderpx + cx * win.cw, + borderpx + cy * win.ch, 1, win.ch - 1); + XftDrawRect(xw.draw, &drawcol, borderpx + (cx + 1) * win.cw - 1, + borderpx + cy * win.ch, 1, win.ch - 1); + XftDrawRect(xw.draw, &drawcol, borderpx + cx * win.cw, + borderpx + (cy + 1) * win.ch - 1, win.cw, 1); } - } else { - XftDrawRect(xw.draw, &drawcol, borderpx + cx * win.cw, - borderpx + cy * win.ch, win.cw - 1, 1); - XftDrawRect(xw.draw, &drawcol, borderpx + cx * win.cw, - borderpx + cy * win.ch, 1, win.ch - 1); - XftDrawRect(xw.draw, &drawcol, borderpx + (cx + 1) * win.cw - 1, - borderpx + cy * win.ch, 1, win.ch - 1); - XftDrawRect(xw.draw, &drawcol, borderpx + cx * win.cw, - borderpx + (cy + 1) * win.ch - 1, win.cw, 1); - } } void xsetenv(void) { - char buf[sizeof(long) * 8 + 1]; + char buf[sizeof(long) * 8 + 1]; - snprintf(buf, sizeof(buf), "%lu", xw.win); - setenv("WINDOWID", buf, 1); + snprintf(buf, sizeof(buf), "%lu", xw.win); + setenv("WINDOWID", buf, 1); } void xseticontitle(char *p) { - XTextProperty prop; - DEFAULT(p, opt_title); + XTextProperty prop; + DEFAULT(p, opt_title); - Xutf8TextListToTextProperty(xw.dpy, &p, 1, XUTF8StringStyle, &prop); - XSetWMIconName(xw.dpy, xw.win, &prop); - XSetTextProperty(xw.dpy, xw.win, &prop, xw.netwmiconname); - XFree(prop.value); + Xutf8TextListToTextProperty(xw.dpy, &p, 1, XUTF8StringStyle, &prop); + XSetWMIconName(xw.dpy, xw.win, &prop); + XSetTextProperty(xw.dpy, xw.win, &prop, xw.netwmiconname); + XFree(prop.value); } void xsettitle(char *p) { - XTextProperty prop; - DEFAULT(p, opt_title); + XTextProperty prop; + DEFAULT(p, opt_title); - Xutf8TextListToTextProperty(xw.dpy, &p, 1, XUTF8StringStyle, &prop); - XSetWMName(xw.dpy, xw.win, &prop); - XSetTextProperty(xw.dpy, xw.win, &prop, xw.netwmname); - XFree(prop.value); + Xutf8TextListToTextProperty(xw.dpy, &p, 1, XUTF8StringStyle, &prop); + XSetWMName(xw.dpy, xw.win, &prop); + XSetTextProperty(xw.dpy, xw.win, &prop, xw.netwmname); + XFree(prop.value); } int xstartdraw(void) { return IS_SET(MODE_VISIBLE); } void xdrawline(Line line, int x1, int y1, int x2) { - int i, x, ox, numspecs; - Glyph base, new; - XftGlyphFontSpec *specs = xw.specbuf; + int i, x, ox, numspecs; + Glyph base, new; + XftGlyphFontSpec *specs = xw.specbuf; - numspecs = xmakeglyphfontspecs(specs, &line[x1], x2 - x1, x1, y1); - i = ox = 0; - for (x = x1; x < x2 && i < numspecs; x++) { - new = line[x]; - if (new.mode == ATTR_WDUMMY) - continue; - if (selected(x, y1)) - new.mode ^= ATTR_REVERSE; - if (i > 0 && ATTRCMP(base, new)) { - xdrawglyphfontspecs(specs, base, i, ox, y1); - specs += i; - numspecs -= i; - i = 0; + numspecs = xmakeglyphfontspecs(specs, &line[x1], x2 - x1, x1, y1); + i = ox = 0; + for (x = x1; x < x2 && i < numspecs; x++) { + new = line[x]; + if (new.mode == ATTR_WDUMMY) + continue; + if (selected(x, y1)) + new.mode ^= ATTR_REVERSE; + if (i > 0 && ATTRCMP(base, new)) { + xdrawglyphfontspecs(specs, base, i, ox, y1); + specs += i; + numspecs -= i; + i = 0; + } + if (i == 0) { + ox = x; + base = new; + } + i++; } - if (i == 0) { - ox = x; - base = new; - } - i++; - } - if (i > 0) - xdrawglyphfontspecs(specs, base, i, ox, y1); + if (i > 0) + xdrawglyphfontspecs(specs, base, i, ox, y1); } void xfinishdraw(void) { - XCopyArea(xw.dpy, xw.buf, xw.win, dc.gc, 0, 0, win.w, win.h, 0, 0); - XSetForeground(xw.dpy, dc.gc, - dc.col[IS_SET(MODE_REVERSE) ? defaultfg : defaultbg].pixel); + XCopyArea(xw.dpy, xw.buf, xw.win, dc.gc, 0, 0, win.w, win.h, 0, 0); + XSetForeground(xw.dpy, dc.gc, + dc.col[IS_SET(MODE_REVERSE) ? defaultfg : defaultbg].pixel); } void xximspot(int x, int y) { - if (xw.ime.xic == NULL) - return; + if (xw.ime.xic == NULL) + return; - xw.ime.spot.x = borderpx + x * win.cw; - xw.ime.spot.y = borderpx + (y + 1) * win.ch; + xw.ime.spot.x = borderpx + x * win.cw; + xw.ime.spot.y = borderpx + (y + 1) * win.ch; - XSetICValues(xw.ime.xic, XNPreeditAttributes, xw.ime.spotlist, NULL); + XSetICValues(xw.ime.xic, XNPreeditAttributes, xw.ime.spotlist, NULL); } void expose(XEvent *ev) { redraw(); } void visibility(XEvent *ev) { - XVisibilityEvent *e = &ev->xvisibility; + XVisibilityEvent *e = &ev->xvisibility; - MODBIT(win.mode, e->state != VisibilityFullyObscured, MODE_VISIBLE); + MODBIT(win.mode, e->state != VisibilityFullyObscured, MODE_VISIBLE); } void unmap(XEvent *ev) { win.mode &= ~MODE_VISIBLE; } void xsetpointermotion(int set) { - MODBIT(xw.attrs.event_mask, set, PointerMotionMask); - XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, &xw.attrs); + MODBIT(xw.attrs.event_mask, set, PointerMotionMask); + XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, &xw.attrs); } void xsetmode(int set, unsigned int flags) { - int mode = win.mode; - MODBIT(win.mode, set, flags); - if ((win.mode & MODE_REVERSE) != (mode & MODE_REVERSE)) - redraw(); + int mode = win.mode; + MODBIT(win.mode, set, flags); + if ((win.mode & MODE_REVERSE) != (mode & MODE_REVERSE)) + redraw(); } int xsetcursor(int cursor) { - if (!BETWEEN(cursor, 0, 7)) /* 7: st extension */ - return 1; - win.cursor = cursor; - return 0; + if (!BETWEEN(cursor, 0, 7)) /* 7: st extension */ + return 1; + win.cursor = cursor; + return 0; } void xseturgency(int add) { - XWMHints *h = XGetWMHints(xw.dpy, xw.win); + XWMHints *h = XGetWMHints(xw.dpy, xw.win); - MODBIT(h->flags, add, XUrgencyHint); - XSetWMHints(xw.dpy, xw.win, h); - XFree(h); + MODBIT(h->flags, add, XUrgencyHint); + XSetWMHints(xw.dpy, xw.win, h); + XFree(h); } void xbell(void) { - if (!(IS_SET(MODE_FOCUSED))) - xseturgency(1); - if (bellvolume) - XkbBell(xw.dpy, xw.win, bellvolume, (Atom)NULL); + if (!(IS_SET(MODE_FOCUSED))) + xseturgency(1); + if (bellvolume) + XkbBell(xw.dpy, xw.win, bellvolume, (Atom)NULL); } void focus(XEvent *ev) { - XFocusChangeEvent *e = &ev->xfocus; + XFocusChangeEvent *e = &ev->xfocus; - if (e->mode == NotifyGrab) - return; + if (e->mode == NotifyGrab) + return; - if (ev->type == FocusIn) { - if (xw.ime.xic) - XSetICFocus(xw.ime.xic); - win.mode |= MODE_FOCUSED; - xseturgency(0); - if (IS_SET(MODE_FOCUS)) - ttywrite("\033[I", 3, 0); - } else { - if (xw.ime.xic) - XUnsetICFocus(xw.ime.xic); - win.mode &= ~MODE_FOCUSED; - if (IS_SET(MODE_FOCUS)) - ttywrite("\033[O", 3, 0); - } + if (ev->type == FocusIn) { + if (xw.ime.xic) + XSetICFocus(xw.ime.xic); + win.mode |= MODE_FOCUSED; + xseturgency(0); + if (IS_SET(MODE_FOCUS)) + ttywrite("\033[I", 3, 0); + } else { + if (xw.ime.xic) + XUnsetICFocus(xw.ime.xic); + win.mode &= ~MODE_FOCUSED; + if (IS_SET(MODE_FOCUS)) + ttywrite("\033[O", 3, 0); + } } int match(uint mask, uint state) { - return mask == XK_ANY_MOD || mask == (state & ~ignoremod); + return mask == XK_ANY_MOD || mask == (state & ~ignoremod); } char *kmap(KeySym k, uint state) { - Key *kp; - int i; + Key *kp; + int i; - /* Check for mapped keys out of X11 function keys. */ - for (i = 0; i < LEN(mappedkeys); i++) { - if (mappedkeys[i] == k) - break; - } - if (i == LEN(mappedkeys)) { - if ((k & 0xFFFF) < 0xFD00) - return NULL; - } + /* Check for mapped keys out of X11 function keys. */ + for (i = 0; i < LEN(mappedkeys); i++) { + if (mappedkeys[i] == k) + break; + } + if (i == LEN(mappedkeys)) { + if ((k & 0xFFFF) < 0xFD00) + return NULL; + } - for (kp = key; kp < key + LEN(key); kp++) { - if (kp->k != k) - continue; + for (kp = key; kp < key + LEN(key); kp++) { + if (kp->k != k) + continue; - if (!match(kp->mask, state)) - continue; + if (!match(kp->mask, state)) + continue; - if (IS_SET(MODE_APPKEYPAD) ? kp->appkey < 0 : kp->appkey > 0) - continue; - if (IS_SET(MODE_NUMLOCK) && kp->appkey == 2) - continue; + if (IS_SET(MODE_APPKEYPAD) ? kp->appkey < 0 : kp->appkey > 0) + continue; + if (IS_SET(MODE_NUMLOCK) && kp->appkey == 2) + continue; - if (IS_SET(MODE_APPCURSOR) ? kp->appcursor < 0 : kp->appcursor > 0) - continue; + if (IS_SET(MODE_APPCURSOR) ? kp->appcursor < 0 : kp->appcursor > 0) + continue; - return kp->s; - } + return kp->s; + } - return NULL; + return NULL; } void kpress(XEvent *ev) { - XKeyEvent *e = &ev->xkey; - KeySym ksym; - char buf[64], *customkey; - int len; - Rune c; - Status status; - Shortcut *bp; + XKeyEvent *e = &ev->xkey; + KeySym ksym; + char buf[64], *customkey; + int len; + Rune c; + Status status; + Shortcut * bp; - if (IS_SET(MODE_KBDLOCK)) - return; + if (IS_SET(MODE_KBDLOCK)) + return; - if (xw.ime.xic) - len = XmbLookupString(xw.ime.xic, e, buf, sizeof buf, &ksym, &status); - else - len = XLookupString(e, buf, sizeof buf, &ksym, NULL); - /* 1. shortcuts */ - for (bp = shortcuts; bp < shortcuts + LEN(shortcuts); bp++) { - if (ksym == bp->keysym && match(bp->mod, e->state)) { - bp->func(&(bp->arg)); - return; + if (xw.ime.xic) + len = XmbLookupString(xw.ime.xic, e, buf, sizeof buf, &ksym, &status); + else + len = XLookupString(e, buf, sizeof buf, &ksym, NULL); + /* 1. shortcuts */ + for (bp = shortcuts; bp < shortcuts + LEN(shortcuts); bp++) { + if (ksym == bp->keysym && match(bp->mod, e->state)) { + bp->func(&(bp->arg)); + return; + } } - } - /* 2. custom keys from config.h */ - if ((customkey = kmap(ksym, e->state))) { - ttywrite(customkey, strlen(customkey), 1); - return; - } - - /* 3. composed string from input method */ - if (len == 0) - return; - if (len == 1 && e->state & Mod1Mask) { - if (IS_SET(MODE_8BIT)) { - if (*buf < 0177) { - c = *buf | 0x80; - len = utf8encode(c, buf); - } - } else { - buf[1] = buf[0]; - buf[0] = '\033'; - len = 2; + /* 2. custom keys from config.h */ + if ((customkey = kmap(ksym, e->state))) { + ttywrite(customkey, strlen(customkey), 1); + return; } - } - ttywrite(buf, len, 1); + + /* 3. composed string from input method */ + if (len == 0) + return; + if (len == 1 && e->state & Mod1Mask) { + if (IS_SET(MODE_8BIT)) { + if (*buf < 0177) { + c = *buf | 0x80; + len = utf8encode(c, buf); + } + } else { + buf[1] = buf[0]; + buf[0] = '\033'; + len = 2; + } + } + ttywrite(buf, len, 1); } void cmessage(XEvent *e) { - /* - * See xembed specs - * http://standards.freedesktop.org/xembed-spec/xembed-spec-latest.html - */ - if (e->xclient.message_type == xw.xembed && e->xclient.format == 32) { - if (e->xclient.data.l[1] == XEMBED_FOCUS_IN) { - win.mode |= MODE_FOCUSED; - xseturgency(0); - } else if (e->xclient.data.l[1] == XEMBED_FOCUS_OUT) { - win.mode &= ~MODE_FOCUSED; + /* + * See xembed specs + * http://standards.freedesktop.org/xembed-spec/xembed-spec-latest.html + */ + if (e->xclient.message_type == xw.xembed && e->xclient.format == 32) { + if (e->xclient.data.l[1] == XEMBED_FOCUS_IN) { + win.mode |= MODE_FOCUSED; + xseturgency(0); + } else if (e->xclient.data.l[1] == XEMBED_FOCUS_OUT) { + win.mode &= ~MODE_FOCUSED; + } + } else if (e->xclient.data.l[0] == xw.wmdeletewin) { + ttyhangup(); + exit(0); } - } else if (e->xclient.data.l[0] == xw.wmdeletewin) { - ttyhangup(); - exit(0); - } } void resize(XEvent *e) { - if (e->xconfigure.width == win.w && e->xconfigure.height == win.h) - return; + if (e->xconfigure.width == win.w && e->xconfigure.height == win.h) + return; - cresize(e->xconfigure.width, e->xconfigure.height); + cresize(e->xconfigure.width, e->xconfigure.height); } void run(void) { - XEvent ev; - int w = win.w, h = win.h; - fd_set rfd; - int xfd = XConnectionNumber(xw.dpy), ttyfd, xev, drawing; - struct timespec seltv, *tv, now, lastblink, trigger; - double timeout; + XEvent ev; + int w = win.w, h = win.h; + fd_set rfd; + int xfd = XConnectionNumber(xw.dpy), ttyfd, xev, drawing; + struct timespec seltv, *tv, now, lastblink, trigger; + double timeout; - /* Waiting for window mapping */ - do { - XNextEvent(xw.dpy, &ev); - /* - * This XFilterEvent call is required because of XOpenIM. It - * does filter out the key event and some client message for - * the input method too. - */ - if (XFilterEvent(&ev, None)) - continue; - if (ev.type == ConfigureNotify) { - w = ev.xconfigure.width; - h = ev.xconfigure.height; + /* Waiting for window mapping */ + do { + XNextEvent(xw.dpy, &ev); + /* + * This XFilterEvent call is required because of XOpenIM. It + * does filter out the key event and some client message for + * the input method too. + */ + if (XFilterEvent(&ev, None)) + continue; + if (ev.type == ConfigureNotify) { + w = ev.xconfigure.width; + h = ev.xconfigure.height; + } + } while (ev.type != MapNotify); + + ttyfd = ttynew(opt_line, shell, opt_io, opt_cmd); + cresize(w, h); + + for (timeout = -1, drawing = 0, lastblink = (struct timespec){0};;) { + FD_ZERO(&rfd); + FD_SET(ttyfd, &rfd); + FD_SET(xfd, &rfd); + + if (XPending(xw.dpy)) + timeout = 0; /* existing events might not set xfd */ + + seltv.tv_sec = timeout / 1E3; + seltv.tv_nsec = 1E6 * (timeout - 1E3 * seltv.tv_sec); + tv = timeout >= 0 ? &seltv : NULL; + + if (pselect(MAX(xfd, ttyfd) + 1, &rfd, NULL, NULL, tv, NULL) < 0) { + if (errno == EINTR) + continue; + die("select failed: %s\n", strerror(errno)); + } + clock_gettime(CLOCK_MONOTONIC, &now); + + if (FD_ISSET(ttyfd, &rfd)) + ttyread(); + + xev = 0; + while (XPending(xw.dpy)) { + xev = 1; + XNextEvent(xw.dpy, &ev); + if (XFilterEvent(&ev, None)) + continue; + if (handler[ev.type]) + (handler[ev.type])(&ev); + } + + /* + * To reduce flicker and tearing, when new content or event + * triggers drawing, we first wait a bit to ensure we got + * everything, and if nothing new arrives - we draw. + * We start with trying to wait minlatency ms. If more content + * arrives sooner, we retry with shorter and shorter periods, + * and eventually draw even without idle after maxlatency ms. + * Typically this results in low latency while interacting, + * maximum latency intervals during `cat huge.txt`, and perfect + * sync with periodic updates from animations/key-repeats/etc. + */ + if (FD_ISSET(ttyfd, &rfd) || xev) { + if (!drawing) { + trigger = now; + drawing = 1; + } + timeout = (maxlatency - TIMEDIFF(now, trigger)) / maxlatency * + minlatency; + if (timeout > 0) + continue; /* we have time, try to find idle */ + } + + /* idle detected or maxlatency exhausted -> draw */ + timeout = -1; + if (blinktimeout && tattrset(ATTR_BLINK)) { + timeout = blinktimeout - TIMEDIFF(now, lastblink); + if (timeout <= 0) { + if (-timeout > blinktimeout) /* start visible */ + win.mode |= MODE_BLINK; + win.mode ^= MODE_BLINK; + tsetdirtattr(ATTR_BLINK); + lastblink = now; + timeout = blinktimeout; + } + } + + draw(); + XFlush(xw.dpy); + drawing = 0; } - } while (ev.type != MapNotify); - - ttyfd = ttynew(opt_line, shell, opt_io, opt_cmd); - cresize(w, h); - - for (timeout = -1, drawing = 0, lastblink = (struct timespec){0};;) { - FD_ZERO(&rfd); - FD_SET(ttyfd, &rfd); - FD_SET(xfd, &rfd); - - if (XPending(xw.dpy)) - timeout = 0; /* existing events might not set xfd */ - - seltv.tv_sec = timeout / 1E3; - seltv.tv_nsec = 1E6 * (timeout - 1E3 * seltv.tv_sec); - tv = timeout >= 0 ? &seltv : NULL; - - if (pselect(MAX(xfd, ttyfd) + 1, &rfd, NULL, NULL, tv, NULL) < 0) { - if (errno == EINTR) - continue; - die("select failed: %s\n", strerror(errno)); - } - clock_gettime(CLOCK_MONOTONIC, &now); - - if (FD_ISSET(ttyfd, &rfd)) - ttyread(); - - xev = 0; - while (XPending(xw.dpy)) { - xev = 1; - XNextEvent(xw.dpy, &ev); - if (XFilterEvent(&ev, None)) - continue; - if (handler[ev.type]) - (handler[ev.type])(&ev); - } - - /* - * To reduce flicker and tearing, when new content or event - * triggers drawing, we first wait a bit to ensure we got - * everything, and if nothing new arrives - we draw. - * We start with trying to wait minlatency ms. If more content - * arrives sooner, we retry with shorter and shorter periods, - * and eventually draw even without idle after maxlatency ms. - * Typically this results in low latency while interacting, - * maximum latency intervals during `cat huge.txt`, and perfect - * sync with periodic updates from animations/key-repeats/etc. - */ - if (FD_ISSET(ttyfd, &rfd) || xev) { - if (!drawing) { - trigger = now; - drawing = 1; - } - timeout = (maxlatency - TIMEDIFF(now, trigger)) / maxlatency * minlatency; - if (timeout > 0) - continue; /* we have time, try to find idle */ - } - - /* idle detected or maxlatency exhausted -> draw */ - timeout = -1; - if (blinktimeout && tattrset(ATTR_BLINK)) { - timeout = blinktimeout - TIMEDIFF(now, lastblink); - if (timeout <= 0) { - if (-timeout > blinktimeout) /* start visible */ - win.mode |= MODE_BLINK; - win.mode ^= MODE_BLINK; - tsetdirtattr(ATTR_BLINK); - lastblink = now; - timeout = blinktimeout; - } - } - - draw(); - XFlush(xw.dpy); - drawing = 0; - } } void usage(void) { - die("usage: %s [-aiv] [-c class] [-f font] [-g geometry]" - " [-n name] [-o file]\n" - " [-T title] [-t title] [-w windowid]" - " [[-e] command [args ...]]\n" - " %s [-aiv] [-c class] [-f font] [-g geometry]" - " [-n name] [-o file]\n" - " [-T title] [-t title] [-w windowid] -l line" - " [stty_args ...]\n", - argv0, argv0); + die("usage: %s [-aiv] [-c class] [-f font] [-g geometry]" + " [-n name] [-o file]\n" + " [-T title] [-t title] [-w windowid]" + " [[-e] command [args ...]]\n" + " %s [-aiv] [-c class] [-f font] [-g geometry]" + " [-n name] [-o file]\n" + " [-T title] [-t title] [-w windowid] -l line" + " [stty_args ...]\n", + argv0, argv0); } int main(int argc, char *argv[]) { - xw.l = xw.t = 0; - xw.isfixed = False; - xsetcursor(cursorshape); + xw.l = xw.t = 0; + xw.isfixed = False; + xsetcursor(cursorshape); - ARGBEGIN { - case 'a': - allowaltscreen = 0; - break; - case 'c': - opt_class = EARGF(usage()); - break; - case 'e': - if (argc > 0) - --argc, ++argv; - goto run; - case 'f': - opt_font = EARGF(usage()); - break; - case 'g': - xw.gm = XParseGeometry(EARGF(usage()), &xw.l, &xw.t, &cols, &rows); - break; - case 'i': - xw.isfixed = 1; - break; - case 'o': - opt_io = EARGF(usage()); - break; - case 'l': - opt_line = EARGF(usage()); - break; - case 'n': - opt_name = EARGF(usage()); - break; - case 't': - case 'T': - opt_title = EARGF(usage()); - break; - case 'w': - opt_embed = EARGF(usage()); - break; - case 'v': - die("%s\n", VERSION); - break; - default: - usage(); - } - ARGEND; + ARGBEGIN { + case 'a': + allowaltscreen = 0; + break; + case 'c': + opt_class = EARGF(usage()); + break; + case 'e': + if (argc > 0) + --argc, ++argv; + goto run; + case 'f': + opt_font = EARGF(usage()); + break; + case 'g': + xw.gm = XParseGeometry(EARGF(usage()), &xw.l, &xw.t, &cols, &rows); + break; + case 'i': + xw.isfixed = 1; + break; + case 'o': + opt_io = EARGF(usage()); + break; + case 'l': + opt_line = EARGF(usage()); + break; + case 'n': + opt_name = EARGF(usage()); + break; + case 't': + case 'T': + opt_title = EARGF(usage()); + break; + case 'w': + opt_embed = EARGF(usage()); + break; + case 'v': + die("%s\n", VERSION); + break; + default: + usage(); + } + ARGEND; run: - if (argc > 0) /* eat all remaining arguments */ - opt_cmd = argv; + if (argc > 0) /* eat all remaining arguments */ + opt_cmd = argv; - if (!opt_title) - opt_title = (opt_line || !opt_cmd) ? "st" : opt_cmd[0]; + if (!opt_title) + opt_title = (opt_line || !opt_cmd) ? "st" : opt_cmd[0]; - setlocale(LC_CTYPE, ""); - XSetLocaleModifiers(""); - cols = MAX(cols, 1); - rows = MAX(rows, 1); - tnew(cols, rows); - xinit(cols, rows); - xsetenv(); - selinit(); - run(); + setlocale(LC_CTYPE, ""); + XSetLocaleModifiers(""); + cols = MAX(cols, 1); + rows = MAX(rows, 1); + tnew(cols, rows); + xinit(cols, rows); + xsetenv(); + selinit(); + run(); - return 0; + return 0; } From d42d786aa44e796401964a54246c256610b15b58 Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Sat, 26 Dec 2020 11:47:31 +0100 Subject: [PATCH 08/11] Added issue templates --- .gitlab/issue_templates/Bug.md | 47 +++++++++++++++++++++ .gitlab/issue_templates/Documentation.md | 38 +++++++++++++++++ .gitlab/issue_templates/Feature Proposal.md | 36 ++++++++++++++++ .gitlab/issue_templates/Implementation.md | 35 +++++++++++++++ .gitlab/issue_templates/Refactoring.md | 30 +++++++++++++ 5 files changed, 186 insertions(+) create mode 100644 .gitlab/issue_templates/Bug.md create mode 100644 .gitlab/issue_templates/Documentation.md create mode 100644 .gitlab/issue_templates/Feature Proposal.md create mode 100644 .gitlab/issue_templates/Implementation.md create mode 100644 .gitlab/issue_templates/Refactoring.md diff --git a/.gitlab/issue_templates/Bug.md b/.gitlab/issue_templates/Bug.md new file mode 100644 index 0000000..89e0be2 --- /dev/null +++ b/.gitlab/issue_templates/Bug.md @@ -0,0 +1,47 @@ + + +### Summary + + + +### Steps to reproduce + + + +### Example Project + + + +### What is the current *bug* behavior? + + + +### What is the expected *correct* behavior? + + + +### Relevant logs and/or screenshots + + + +### Possible fixes + + + +/label ~bug diff --git a/.gitlab/issue_templates/Documentation.md b/.gitlab/issue_templates/Documentation.md new file mode 100644 index 0000000..6023f14 --- /dev/null +++ b/.gitlab/issue_templates/Documentation.md @@ -0,0 +1,38 @@ + + +### Problem to solve + + + +### Further details + + + +### Proposal + + + +### Who can address the issue + + + +/label ~documentation diff --git a/.gitlab/issue_templates/Feature Proposal.md b/.gitlab/issue_templates/Feature Proposal.md new file mode 100644 index 0000000..4588056 --- /dev/null +++ b/.gitlab/issue_templates/Feature Proposal.md @@ -0,0 +1,36 @@ + + +### Problem to solve + + + +### Intended users + + + +### User experience goal + + + +### Proposal + + + +### Further details + + + +### Documentation + + + +### Links / references + + + +/label ~devops:: ~group: ~Category: + +/label ~feature diff --git a/.gitlab/issue_templates/Implementation.md b/.gitlab/issue_templates/Implementation.md new file mode 100644 index 0000000..2444b71 --- /dev/null +++ b/.gitlab/issue_templates/Implementation.md @@ -0,0 +1,35 @@ + + +## Why are we doing this work + + +## Relevant links + + +## Non-functional requirements + + +- [ ] Documentation: +- [ ] Feature flag: +- [ ] Performance: +- [ ] Testing: + +## Implementation plan + + +- [ ] + +/label ~implementation diff --git a/.gitlab/issue_templates/Refactoring.md b/.gitlab/issue_templates/Refactoring.md new file mode 100644 index 0000000..f5ce004 --- /dev/null +++ b/.gitlab/issue_templates/Refactoring.md @@ -0,0 +1,30 @@ + + +## Summary + + +## Improvements + + +## Risks + + +## Involved components + + +## Optional: Intended side effects + + +/label ~maintenance From f315834f030b737e9e80a640fe7f10db2f59e310 Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Sat, 26 Dec 2020 12:28:34 +0100 Subject: [PATCH 09/11] Put pointers in the correct spot --- .clang-format | 2 +- src/arg.h | 8 +- src/config.def.h | 18 ++-- src/config.h | 18 ++-- src/st/selection.h | 2 +- src/st/st.c | 112 +++++++++---------- src/st/st.h | 42 ++++---- src/st/utf8.c | 8 +- src/st/utf8.h | 6 +- src/win.h | 8 +- src/x.c | 262 ++++++++++++++++++++++----------------------- 11 files changed, 242 insertions(+), 244 deletions(-) diff --git a/.clang-format b/.clang-format index 76f9685..baf8e54 100644 --- a/.clang-format +++ b/.clang-format @@ -111,7 +111,7 @@ PenaltyBreakString: 1000 PenaltyBreakTemplateDeclaration: 10 PenaltyExcessCharacter: 1000000 PenaltyReturnTypeOnItsOwnLine: 60 -PointerAlignment: Right +PointerAlignment: Left ReflowComments: true SortIncludes: true SortUsingDeclarations: true diff --git a/src/arg.h b/src/arg.h index 9fa5d83..3c88eb9 100644 --- a/src/arg.h +++ b/src/arg.h @@ -6,14 +6,14 @@ #ifndef ARG_H #define ARG_H -extern char *argv0; +extern char* argv0; /* use main(int argc, char *argv[]) */ #define ARGBEGIN \ for (argv0 = *argv, argv++, argc--; \ argv[0] && argv[0][0] == '-' && argv[0][1]; argc--, argv++) { \ char argc_; \ - char **argv_; \ + char** argv_; \ int brk_; \ if (argv[0][1] == '-' && argv[0][2] == '\0') { \ argv++; \ @@ -35,13 +35,13 @@ extern char *argv0; #define EARGF(x) \ ((argv[0][i_ + 1] == '\0' && argv[1] == NULL) \ - ? ((x), abort(), (char *)0) \ + ? ((x), abort(), (char*)0) \ : (brk_ = 1, (argv[0][i_ + 1] != '\0') ? (&argv[0][i_ + 1]) \ : (argc--, argv++, argv[0]))) #define ARGF() \ ((argv[0][i_ + 1] == '\0' && argv[1] == NULL) \ - ? (char *)0 \ + ? (char*)0 \ : (brk_ = 1, (argv[0][i_ + 1] != '\0') ? (&argv[0][i_ + 1]) \ : (argc--, argv++, argv[0]))) diff --git a/src/config.def.h b/src/config.def.h index d66625c..e732dec 100644 --- a/src/config.def.h +++ b/src/config.def.h @@ -5,7 +5,7 @@ * * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html */ -static char *font = +static char* font = "Liberation Mono:pixelsize=12:antialias=true:autohint=true"; static int borderpx = 2; @@ -17,14 +17,14 @@ static int borderpx = 2; * 4: value of shell in /etc/passwd * 5: value of shell in config.h */ -static char *shell = "/bin/sh"; -char * utmp = NULL; +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"; +char* scroll = NULL; +char* stty_args = "stty raw pass8 nl -echo -iexten -cstopb 38400"; /* identification sequence returned in DA and DECID */ -char *vtiden = "\033[?6c"; +char* vtiden = "\033[?6c"; /* Kerning / character bounding-box multipliers */ static float cwscale = 1.0; @@ -35,7 +35,7 @@ static float chscale = 1.0; * * More advanced example: L" `'\"()[]{}" */ -wchar_t *worddelimiters = L" "; +wchar_t* worddelimiters = L" "; /* selection timeouts (in milliseconds) */ static unsigned int doubleclicktimeout = 300; @@ -75,7 +75,7 @@ static unsigned int cursorthickness = 2; static int bellvolume = 0; /* default TERM value */ -char *termname = "st-256color"; +char* termname = "st-256color"; /* * spaces per tab @@ -95,7 +95,7 @@ char *termname = "st-256color"; unsigned int tabspaces = 8; /* Terminal colors (16 first used in escape sequence) */ -static const char *colorname[] = { +static const char* colorname[] = { /* 8 normal colors */ "black", "red3", diff --git a/src/config.h b/src/config.h index d66625c..e732dec 100644 --- a/src/config.h +++ b/src/config.h @@ -5,7 +5,7 @@ * * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html */ -static char *font = +static char* font = "Liberation Mono:pixelsize=12:antialias=true:autohint=true"; static int borderpx = 2; @@ -17,14 +17,14 @@ static int borderpx = 2; * 4: value of shell in /etc/passwd * 5: value of shell in config.h */ -static char *shell = "/bin/sh"; -char * utmp = NULL; +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"; +char* scroll = NULL; +char* stty_args = "stty raw pass8 nl -echo -iexten -cstopb 38400"; /* identification sequence returned in DA and DECID */ -char *vtiden = "\033[?6c"; +char* vtiden = "\033[?6c"; /* Kerning / character bounding-box multipliers */ static float cwscale = 1.0; @@ -35,7 +35,7 @@ static float chscale = 1.0; * * More advanced example: L" `'\"()[]{}" */ -wchar_t *worddelimiters = L" "; +wchar_t* worddelimiters = L" "; /* selection timeouts (in milliseconds) */ static unsigned int doubleclicktimeout = 300; @@ -75,7 +75,7 @@ static unsigned int cursorthickness = 2; static int bellvolume = 0; /* default TERM value */ -char *termname = "st-256color"; +char* termname = "st-256color"; /* * spaces per tab @@ -95,7 +95,7 @@ char *termname = "st-256color"; unsigned int tabspaces = 8; /* Terminal colors (16 first used in escape sequence) */ -static const char *colorname[] = { +static const char* colorname[] = { /* 8 normal colors */ "black", "red3", diff --git a/src/st/selection.h b/src/st/selection.h index 97cdbe3..c361d69 100644 --- a/src/st/selection.h +++ b/src/st/selection.h @@ -27,7 +27,7 @@ void selinit(void); void selstart(int, int, int); void selnormalize(); void selscroll(int, int); -void selsnap(int *, int *, int); +void selsnap(int*, int*, int); void selclear(void); // Global variable for now diff --git a/src/st/st.c b/src/st/st.c index 6c169cf..687f888 100644 --- a/src/st/st.c +++ b/src/st/st.c @@ -93,9 +93,9 @@ typedef struct { typedef struct { int row; /* nb row */ int col; /* nb col */ - Line * line; /* screen */ - Line * alt; /* alternate screen */ - int * dirty; /* dirtyness of lines */ + Line* line; /* screen */ + Line* alt; /* alternate screen */ + int* dirty; /* dirtyness of lines */ TCursor c; /* cursor */ int ocx; /* old cursor col */ int ocy; /* old cursor row */ @@ -106,7 +106,7 @@ typedef struct { char trantbl[4]; /* charset table translation */ int charset; /* current charset */ int icharset; /* selected charset for sequence */ - int * tabs; + int* tabs; Rune lastc; /* last printed char outside of sequence, 0 if control */ } Term; @@ -125,17 +125,17 @@ typedef struct { /* ESC type [[ [] [;]] ] ESC '\' */ typedef struct { char type; /* ESC type ... */ - char * buf; /* allocated raw string */ + char* buf; /* allocated raw string */ size_t siz; /* allocation size */ size_t len; /* raw string length */ - char * args[STR_ARG_SIZ]; + char* args[STR_ARG_SIZ]; int narg; /* nb of args */ } STREscape; -static void execsh(char *, char **); -static void stty(char **); +static void execsh(char*, char**); +static void stty(char**); static void sigchld(int); -static void ttywriteraw(const char *, size_t); +static void ttywriteraw(const char*, size_t); static void csidump(void); static void csihandle(void); @@ -147,7 +147,7 @@ static void strhandle(void); static void strparse(void); static void strreset(void); -static void tprinter(char *, size_t); +static void tprinter(char*, size_t); static void tdumpsel(void); static void tdumpline(int); static void tdump(void); @@ -166,27 +166,27 @@ static void tputc(Rune); static void treset(void); static void tscrollup(int, int); static void tscrolldown(int, int); -static void tsetattr(int *, int); -static void tsetchar(Rune, Glyph *, int, int); +static void tsetattr(int*, int); +static void tsetchar(Rune, Glyph*, int, int); static void tsetdirt(int, int); static void tsetscroll(int, int); static void tswapscreen(void); -static void tsetmode(int, int, int *, int); -static int twrite(const char *, int, int); +static void tsetmode(int, int, int*, int); +static int twrite(const char*, int, int); static void tfulldirt(void); static void tcontrolcode(uchar); static void tdectest(char); static void tdefutf8(char); -static int32_t tdefcolor(int *, int *, int); +static int32_t tdefcolor(int*, int*, int); static void tdeftran(char); static void tstrsequence(uchar); static void drawregion(int, int, int, int); -static char *base64dec(const char *); -static char base64dec_getc(const char **); +static char* base64dec(const char*); +static char base64dec_getc(const char**); -static ssize_t xwrite(int, const char *, size_t); +static ssize_t xwrite(int, const char*, size_t); /* Globals */ static Term term; @@ -206,7 +206,7 @@ static pid_t pid; * @return p_nbytes if the write was successful, otherwise return negative * error value of write */ -ssize_t xwrite(int p_file_desc, const char *p_str, size_t p_nbytes) { +ssize_t xwrite(int p_file_desc, const char* p_str, size_t p_nbytes) { size_t aux = p_nbytes; ssize_t result; @@ -230,8 +230,8 @@ ssize_t xwrite(int p_file_desc, const char *p_str, size_t p_nbytes) { * @param p_len bytes to allocate * @return pointer to allocated memory */ -void *safe_malloc(size_t p_len) { - void *ptr; +void* safe_malloc(size_t p_len) { + void* ptr; if (!(ptr = malloc(p_len))) die("malloc: %s\n", strerror(errno)); @@ -246,7 +246,7 @@ void *safe_malloc(size_t p_len) { * @param p_len bytes to re-allocate * @return pointer to re-allocated memory */ -void *safe_realloc(void *p_ptr, size_t p_len) { +void* safe_realloc(void* p_ptr, size_t p_len) { if ((p_ptr = realloc(p_ptr, p_len)) == NULL) die("realloc: %s\n", strerror(errno)); @@ -259,7 +259,7 @@ void *safe_realloc(void *p_ptr, size_t p_len) { * @param p_str string to copy * @return pointer to copy of original string */ -char *safe_strdup(char *p_str) { +char* safe_strdup(char* p_str) { if ((p_str = strdup(p_str)) == NULL) die("strdup: %s\n", strerror(errno)); @@ -282,13 +282,13 @@ static const char base64_digits[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; -char base64dec_getc(const char **src) { +char base64dec_getc(const char** src) { while (**src && !isprint(**src)) (*src)++; return **src ? *((*src)++) : '='; /* emulate padding if string ends */ } -char *base64dec(const char *src) { +char* base64dec(const char* src) { size_t in_len = strlen(src); char * result, *dst; @@ -386,7 +386,7 @@ int selected(int x, int y) { (y != sel.ne.y || x <= sel.ne.x); } -void selsnap(int *x, int *y, int direction) { +void selsnap(int* x, int* y, int direction) { int newx, newy, xt, yt; int delim, prevdelim; Glyph *gp, *prevgp; @@ -455,7 +455,7 @@ void selsnap(int *x, int *y, int direction) { } } -char *getsel(void) { +char* getsel(void) { char * str, *ptr; int y, bufsize, lastx, linelen; Glyph *gp, *last; @@ -508,7 +508,7 @@ char *getsel(void) { return str; } -void die(const char *errstr, ...) { +void die(const char* errstr, ...) { va_list ap; va_start(ap, errstr); @@ -517,9 +517,9 @@ void die(const char *errstr, ...) { exit(1); } -void execsh(char *cmd, char **args) { +void execsh(char* cmd, char** args) { char * sh, *prog, *arg; - const struct passwd *pw; + const struct passwd* pw; errno = 0; if ((pw = getpwuid(getuid())) == NULL) { @@ -545,7 +545,7 @@ void execsh(char *cmd, char **args) { prog = sh; arg = NULL; } - DEFAULT(args, ((char *[]){prog, arg, NULL})); + DEFAULT(args, ((char*[]){prog, arg, NULL})); unsetenv("COLUMNS"); unsetenv("LINES"); @@ -584,7 +584,7 @@ void sigchld(int a) { _exit(0); } -void stty(char **args) { +void stty(char** args) { char cmd[_POSIX_ARG_MAX], **p, *q, *s; size_t n, siz; @@ -606,7 +606,7 @@ void stty(char **args) { perror("Couldn't call stty"); } -int ttynew(char *line, char *cmd, char *out, char **args) { +int ttynew(char* line, char* cmd, char* out, char** args) { int m, s; if (out) { @@ -686,8 +686,8 @@ size_t ttyread(void) { } } -void ttywrite(const char *s, size_t n, int may_echo) { - const char *next; +void ttywrite(const char* s, size_t n, int may_echo) { + const char* next; if (may_echo && IS_SET(MODE_ECHO)) twrite(s, n, 1); @@ -712,7 +712,7 @@ void ttywrite(const char *s, size_t n, int may_echo) { } } -void ttywriteraw(const char *s, size_t n) { +void ttywriteraw(const char* s, size_t n) { fd_set wfd, rfd; ssize_t r; size_t lim = 256; @@ -865,7 +865,7 @@ void tnew(int col, int row) { } void tswapscreen(void) { - Line *tmp = term.line; + Line* tmp = term.line; term.line = term.alt; term.alt = tmp; @@ -968,8 +968,8 @@ void tmoveto(int x, int y) { term.c.y = LIMIT(y, miny, maxy); } -void tsetchar(Rune u, Glyph *attr, int x, int y) { - static char *vt100_0[62] = { +void tsetchar(Rune u, Glyph* attr, int x, int y) { + static char* vt100_0[62] = { /* 0x41 - 0x7e */ "↑", "↓", "→", "←", "█", "▚", "☃", /* A - G */ 0, 0, 0, 0, 0, 0, 0, 0, /* H - O */ @@ -1005,7 +1005,7 @@ void tsetchar(Rune u, Glyph *attr, int x, int y) { void tclearregion(int x1, int y1, int x2, int y2) { int x, y, temp; - Glyph *gp; + Glyph* gp; if (x1 > x2) temp = x1, x1 = x2, x2 = temp; @@ -1033,7 +1033,7 @@ void tclearregion(int x1, int y1, int x2, int y2) { void tdeletechar(int n) { int dst, src, size; - Glyph *line; + Glyph* line; LIMIT(n, 0, term.col - term.c.x); @@ -1048,7 +1048,7 @@ void tdeletechar(int n) { void tinsertblank(int n) { int dst, src, size; - Glyph *line; + Glyph* line; LIMIT(n, 0, term.col - term.c.x); @@ -1071,7 +1071,7 @@ void tdeleteline(int n) { tscrollup(term.c.y, n); } -int32_t tdefcolor(int *attr, int *npar, int l) { +int32_t tdefcolor(int* attr, int* npar, int l) { int32_t idx = -1; uint r, g, b; @@ -1117,7 +1117,7 @@ int32_t tdefcolor(int *attr, int *npar, int l) { return idx; } -void tsetattr(int *attr, int l) { +void tsetattr(int* attr, int l) { int i; int32_t idx; @@ -1224,7 +1224,7 @@ void tsetscroll(int t, int b) { term.bot = b; } -void tsetmode(int priv, int set, int *args, int narg) { +void tsetmode(int priv, int set, int* args, int narg) { int alt, *lim; for (lim = args + narg; args < lim; ++args) { @@ -1653,7 +1653,7 @@ void strhandle(void) { void strparse(void) { int c; - char *p = strescseq.buf; + char* p = strescseq.buf; strescseq.narg = 0; strescseq.buf[strescseq.len] = '\0'; @@ -1703,12 +1703,12 @@ void strreset(void) { }; } -void sendbreak(const Arg *arg) { +void sendbreak(const Arg* arg) { if (tcsendbreak(cmdfd, 0)) perror("Error sending break"); } -void tprinter(char *s, size_t len) { +void tprinter(char* s, size_t len) { if (iofd != -1 && xwrite(iofd, s, len) < 0) { perror("Error writing to output file"); close(iofd); @@ -1716,14 +1716,14 @@ void tprinter(char *s, size_t len) { } } -void toggleprinter(const Arg *arg) { term.mode ^= MODE_PRINT; } +void toggleprinter(const Arg* arg) { term.mode ^= MODE_PRINT; } -void printscreen(const Arg *arg) { tdump(); } +void printscreen(const Arg* arg) { tdump(); } -void printsel(const Arg *arg) { tdumpsel(); } +void printsel(const Arg* arg) { tdumpsel(); } void tdumpsel(void) { - char *ptr; + char* ptr; if ((ptr = getsel())) { tprinter(ptr, strlen(ptr)); @@ -1776,7 +1776,7 @@ void tdefutf8(char ascii) { void tdeftran(char ascii) { static char cs[] = "0B"; static int vcs[] = {CS_GRAPHIC0, CS_USA}; - char * p; + char* p; if ((p = strchr(cs, ascii)) == NULL) { fprintf(stderr, "esc unhandled charset: ESC ( %c\n", ascii); @@ -2000,7 +2000,7 @@ void tputc(Rune u) { char c[UTF_SIZE]; int control; int width, len; - Glyph *gp; + Glyph* gp; control = ISCONTROL(u); if (u < 127 || !IS_SET(MODE_UTF8)) { @@ -2130,7 +2130,7 @@ check_control_code: } } -int twrite(const char *buf, int buflen, int show_ctrl) { +int twrite(const char* buf, int buflen, int show_ctrl) { int charsize; Rune u; int n; @@ -2164,7 +2164,7 @@ void tresize(int col, int row) { int i; int minrow = MIN(row, term.row); int mincol = MIN(col, term.col); - int * bp; + int* bp; TCursor c; if (col < 1 || row < 1) { diff --git a/src/st/st.h b/src/st/st.h index 0aaca49..6565285 100644 --- a/src/st/st.h +++ b/src/st/st.h @@ -34,34 +34,34 @@ typedef struct { uint32_t bg; /* background */ } Glyph; -typedef Glyph *Line; +typedef Glyph* Line; typedef union { int i; uint ui; float f; - const void *v; - const char *s; + const void* v; + const char* s; } Arg; -void die(const char *, ...); +void die(const char*, ...); void redraw(void); void draw(void); -void printscreen(const Arg *); -void printsel(const Arg *); -void sendbreak(const Arg *); -void toggleprinter(const Arg *); +void printscreen(const Arg*); +void printsel(const Arg*); +void sendbreak(const Arg*); +void toggleprinter(const Arg*); int tattrset(int); void tnew(int, int); void tresize(int, int); void tsetdirtattr(int); void ttyhangup(void); -int ttynew(char *, char *, char *, char **); +int ttynew(char*, char*, char*, char**); size_t ttyread(void); void ttyresize(int, int); -void ttywrite(const char *, size_t, int); +void ttywrite(const char*, size_t, int); void resettitle(void); @@ -70,23 +70,23 @@ void selinit(void); void selstart(int, int, int); void selextend(int, int, int, int); int selected(int, int); -char *getsel(void); +char* getsel(void); -size_t utf8encode(Rune, char *); +size_t utf8encode(Rune, char*); -void *safe_malloc(size_t); -void *safe_realloc(void *, size_t); -char *safe_strdup(char *); +void* safe_malloc(size_t); +void* safe_realloc(void*, size_t); +char* safe_strdup(char*); /* config.h globals */ -extern char * utmp; -extern char * scroll; -extern char * stty_args; -extern char * vtiden; -extern wchar_t * worddelimiters; +extern char* utmp; +extern char* scroll; +extern char* stty_args; +extern char* vtiden; +extern wchar_t* worddelimiters; extern int allowaltscreen; extern int allowwindowops; -extern char * termname; +extern char* termname; extern unsigned int tabspaces; extern unsigned int defaultfg; extern unsigned int defaultbg; diff --git a/src/st/utf8.c b/src/st/utf8.c index d517541..d1079cd 100644 --- a/src/st/utf8.c +++ b/src/st/utf8.c @@ -15,7 +15,7 @@ static Rune utfmax[UTF_SIZE + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; * @param p_char_len length of the char array * @return size of the decoded rune */ -size_t utf8decode(const char *p_char, Rune *p_rune, size_t p_char_len) { +size_t utf8decode(const char* p_char, Rune* p_rune, size_t p_char_len) { size_t decoded_len, type, i; Rune decoded_rune; @@ -50,7 +50,7 @@ size_t utf8decode(const char *p_char, Rune *p_rune, size_t p_char_len) { * @param p_i counter used in internal for loop * @return decoded rune */ -Rune utf8decodebyte(char p_char, size_t *p_i) { +Rune utf8decodebyte(char p_char, size_t* p_i) { for (*p_i = 0; *p_i < LEN(utfmask); ++(*p_i)) { if (((uchar)p_char & utfmask[*p_i]) == utfbyte[*p_i]) return (uchar)p_char & ~utfmask[*p_i]; @@ -66,7 +66,7 @@ Rune utf8decodebyte(char p_char, size_t *p_i) { * @param p_char char array to encode to * @return */ -size_t utf8encode(Rune p_rune, char *p_char) { +size_t utf8encode(Rune p_rune, char* p_char) { size_t len, i; len = utf8validate(&p_rune, 0); @@ -92,7 +92,7 @@ char utf8encodebyte(Rune u, size_t i) { * @param p_rune rune to validate * @param i */ -size_t utf8validate(Rune *p_rune, size_t i) { +size_t utf8validate(Rune* p_rune, size_t i) { if (!BETWEEN(*p_rune, utfmin[i], utfmax[i]) || BETWEEN(*p_rune, 0xD800, 0xDFFF)) *p_rune = UTF_INVALID; diff --git a/src/st/utf8.h b/src/st/utf8.h index d34c3b4..6ae0f17 100644 --- a/src/st/utf8.h +++ b/src/st/utf8.h @@ -9,9 +9,9 @@ typedef uint_least32_t Rune; -size_t utf8decode(const char *, Rune *, size_t); -Rune utf8decodebyte(char, size_t *); +size_t utf8decode(const char*, Rune*, size_t); +Rune utf8decodebyte(char, size_t*); char utf8encodebyte(Rune, size_t); -size_t utf8validate(Rune *, size_t); +size_t utf8validate(Rune*, size_t); #endif diff --git a/src/win.h b/src/win.h index 1e41bd6..ef984ac 100644 --- a/src/win.h +++ b/src/win.h @@ -34,13 +34,13 @@ void xdrawcursor(int, int, Glyph, int, int, Glyph); void xdrawline(Line, int, int, int); void xfinishdraw(void); void xloadcols(void); -int xsetcolorname(int, const char *); -void xseticontitle(char *); -void xsettitle(char *); +int xsetcolorname(int, const char*); +void xseticontitle(char*); +void xsettitle(char*); int xsetcursor(int); void xsetmode(int, unsigned int); void xsetpointermotion(int); -void xsetsel(char *); +void xsetsel(char*); int xstartdraw(void); void xximspot(int, int); diff --git a/src/x.c b/src/x.c index 07bcf22..d7feaa9 100644 --- a/src/x.c +++ b/src/x.c @@ -15,7 +15,7 @@ #include #include -char *argv0; +char* argv0; #include "arg.h" #include "st/macros.h" #include "st/st.h" @@ -25,14 +25,14 @@ char *argv0; typedef struct { uint mod; KeySym keysym; - void (*func)(const Arg *); + void (*func)(const Arg*); const Arg arg; } Shortcut; typedef struct { uint mod; uint button; - void (*func)(const Arg *); + void (*func)(const Arg*); const Arg arg; uint release; } MouseShortcut; @@ -40,7 +40,7 @@ typedef struct { typedef struct { KeySym k; uint mask; - char * s; + char* s; /* three-valued logic variables: 0 indifferent, 1 on, -1 off */ signed char appkey; /* application keypad */ signed char appcursor; /* application cursor */ @@ -52,14 +52,14 @@ typedef struct { #define XK_SWITCH_MOD (1 << 13) /* function definitions used in config.h */ -static void clipcopy(const Arg *); -static void clippaste(const Arg *); -static void numlock(const Arg *); -static void selpaste(const Arg *); -static void zoom(const Arg *); -static void zoomabs(const Arg *); -static void zoomreset(const Arg *); -static void ttysend(const Arg *); +static void clipcopy(const Arg*); +static void clippaste(const Arg*); +static void numlock(const Arg*); +static void selpaste(const Arg*); +static void zoom(const Arg*); +static void zoomabs(const Arg*); +static void zoomreset(const Arg*); +static void ttysend(const Arg*); /* config.h for applying patches and the configuration. */ #include "config.h" @@ -74,7 +74,7 @@ static void ttysend(const Arg *); #define TRUEGREEN(x) (((x)&0xff00)) #define TRUEBLUE(x) (((x)&0xff) << 8) -typedef XftDraw * Draw; +typedef XftDraw* Draw; typedef XftColor Color; typedef XftGlyphFontSpec GlyphFontSpec; @@ -89,11 +89,11 @@ typedef struct { } TermWindow; typedef struct { - Display * dpy; + Display* dpy; Colormap cmap; Window win; Drawable buf; - GlyphFontSpec *specbuf; /* font spec buffer used for rendering */ + GlyphFontSpec* specbuf; /* font spec buffer used for rendering */ Atom xembed, wmdeletewin, netwmname, netwmiconname, netwmpid; struct { XIM xim; @@ -102,7 +102,7 @@ typedef struct { XVaNestedList spotlist; } ime; Draw draw; - Visual * vis; + Visual* vis; XSetWindowAttributes attrs; int scr; int isfixed; /* is fixed geometry? */ @@ -128,71 +128,69 @@ typedef struct { int badweight; short lbearing; short rbearing; - XftFont * match; - FcFontSet *set; - FcPattern *pattern; + XftFont* match; + FcFontSet* set; + FcPattern* pattern; } Font; /* Drawing Context */ typedef struct { - Color *col; + Color* col; size_t collen; Font font, bfont, ifont, ibfont; GC gc; } DC; static inline ushort sixd_to_16bit(int); -static int xmakeglyphfontspecs(XftGlyphFontSpec *, const Glyph *, int, int, - int); -static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, - int); +static int xmakeglyphfontspecs(XftGlyphFontSpec*, const Glyph*, int, int, int); +static void xdrawglyphfontspecs(const XftGlyphFontSpec*, Glyph, int, int, int); static void xdrawglyph(Glyph, int, int); static void xclear(int, int, int, int); static int xgeommasktogravity(int); -static int ximopen(Display *); -static void ximinstantiate(Display *, XPointer, XPointer); +static int ximopen(Display*); +static void ximinstantiate(Display*, XPointer, XPointer); static void ximdestroy(XIM, XPointer, XPointer); static int xicdestroy(XIC, XPointer, XPointer); static void xinit(int, int); static void cresize(int, int); static void xresize(int, int); static void xhints(void); -static int xloadcolor(int, const char *, Color *); -static int xloadfont(Font *, FcPattern *); -static void xloadfonts(char *, double); -static void xunloadfont(Font *); +static int xloadcolor(int, const char*, Color*); +static int xloadfont(Font*, FcPattern*); +static void xloadfonts(char*, double); +static void xunloadfont(Font*); static void xunloadfonts(void); static void xsetenv(void); static void xseturgency(int); -static int evcol(XEvent *); -static int evrow(XEvent *); +static int evcol(XEvent*); +static int evrow(XEvent*); -static void expose(XEvent *); -static void visibility(XEvent *); -static void unmap(XEvent *); -static void kpress(XEvent *); -static void cmessage(XEvent *); -static void resize(XEvent *); -static void focus(XEvent *); +static void expose(XEvent*); +static void visibility(XEvent*); +static void unmap(XEvent*); +static void kpress(XEvent*); +static void cmessage(XEvent*); +static void resize(XEvent*); +static void focus(XEvent*); static uint buttonmask(uint); -static int mouseaction(XEvent *, uint); -static void brelease(XEvent *); -static void bpress(XEvent *); -static void bmotion(XEvent *); -static void propnotify(XEvent *); -static void selnotify(XEvent *); -static void selclear_(XEvent *); -static void selrequest(XEvent *); -static void setsel(char *, Time); -static void mousesel(XEvent *, int); -static void mousereport(XEvent *); -static char *kmap(KeySym, uint); +static int mouseaction(XEvent*, uint); +static void brelease(XEvent*); +static void bpress(XEvent*); +static void bmotion(XEvent*); +static void propnotify(XEvent*); +static void selnotify(XEvent*); +static void selclear_(XEvent*); +static void selrequest(XEvent*); +static void setsel(char*, Time); +static void mousesel(XEvent*, int); +static void mousereport(XEvent*); +static char* kmap(KeySym, uint); static int match(uint, uint); static void run(void); static void usage(void); -static void (*handler[LASTEvent])(XEvent *) = { +static void (*handler[LASTEvent])(XEvent*) = { [KeyPress] = kpress, [ClientMessage] = cmessage, [ConfigureNotify] = resize, @@ -228,31 +226,31 @@ static TermWindow win; enum { FRC_NORMAL, FRC_ITALIC, FRC_BOLD, FRC_ITALICBOLD }; typedef struct { - XftFont *font; + XftFont* font; int flags; Rune unicodep; } Fontcache; /* Fontcache is an array now. A new font will be appended to the array. */ -static Fontcache *frc = NULL; +static Fontcache* frc = NULL; static int frclen = 0; static int frccap = 0; -static char * usedfont = NULL; +static char* usedfont = NULL; static double usedfontsize = 0; static double defaultfontsize = 0; -static char * opt_class = NULL; -static char **opt_cmd = NULL; -static char * opt_embed = NULL; -static char * opt_font = NULL; -static char * opt_io = NULL; -static char * opt_line = NULL; -static char * opt_name = NULL; -static char * opt_title = NULL; +static char* opt_class = NULL; +static char** opt_cmd = NULL; +static char* opt_embed = NULL; +static char* opt_font = NULL; +static char* opt_io = NULL; +static char* opt_line = NULL; +static char* opt_name = NULL; +static char* opt_title = NULL; static int oldbutton = 3; /* button event on startup: 3 = release */ -void clipcopy(const Arg *dummy) { +void clipcopy(const Arg* dummy) { Atom clipboard; free(xsel.clipboard); @@ -265,7 +263,7 @@ void clipcopy(const Arg *dummy) { } } -void clippaste(const Arg *dummy) { +void clippaste(const Arg* dummy) { Atom clipboard; clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); @@ -273,21 +271,21 @@ void clippaste(const Arg *dummy) { CurrentTime); } -void selpaste(const Arg *dummy) { +void selpaste(const Arg* dummy) { XConvertSelection(xw.dpy, XA_PRIMARY, xsel.xtarget, XA_PRIMARY, xw.win, CurrentTime); } -void numlock(const Arg *dummy) { win.mode ^= MODE_NUMLOCK; } +void numlock(const Arg* dummy) { win.mode ^= MODE_NUMLOCK; } -void zoom(const Arg *arg) { +void zoom(const Arg* arg) { Arg larg; larg.f = usedfontsize + arg->f; zoomabs(&larg); } -void zoomabs(const Arg *arg) { +void zoomabs(const Arg* arg) { xunloadfonts(); xloadfonts(usedfont, arg->f); cresize(0, 0); @@ -295,7 +293,7 @@ void zoomabs(const Arg *arg) { xhints(); } -void zoomreset(const Arg *arg) { +void zoomreset(const Arg* arg) { Arg larg; if (defaultfontsize > 0) { @@ -304,21 +302,21 @@ void zoomreset(const Arg *arg) { } } -void ttysend(const Arg *arg) { ttywrite(arg->s, strlen(arg->s), 1); } +void ttysend(const Arg* arg) { ttywrite(arg->s, strlen(arg->s), 1); } -int evcol(XEvent *e) { +int evcol(XEvent* e) { int x = e->xbutton.x - borderpx; LIMIT(x, 0, win.tw - 1); return x / win.cw; } -int evrow(XEvent *e) { +int evrow(XEvent* e) { int y = e->xbutton.y - borderpx; LIMIT(y, 0, win.th - 1); return y / win.ch; } -void mousesel(XEvent *e, int done) { +void mousesel(XEvent* e, int done) { int type, seltype = SEL_REGULAR; uint state = e->xbutton.state & ~(Button1Mask | forcemousemod); @@ -333,7 +331,7 @@ void mousesel(XEvent *e, int done) { setsel(getsel(), e->xbutton.time); } -void mousereport(XEvent *e) { +void mousereport(XEvent* e) { int len, x = evcol(e), y = evrow(e), button = e->xbutton.button, state = e->xbutton.state; char buf[40]; @@ -402,8 +400,8 @@ uint buttonmask(uint button) { : 0; } -int mouseaction(XEvent *e, uint release) { - MouseShortcut *ms; +int mouseaction(XEvent* e, uint release) { + MouseShortcut* ms; /* ignore Buttonmask for Button - it's set on release */ uint state = e->xbutton.state & ~buttonmask(e->xbutton.button); @@ -420,7 +418,7 @@ int mouseaction(XEvent *e, uint release) { return 0; } -void bpress(XEvent *e) { +void bpress(XEvent* e) { struct timespec now; int snap; @@ -452,8 +450,8 @@ void bpress(XEvent *e) { } } -void propnotify(XEvent *e) { - XPropertyEvent *xpev; +void propnotify(XEvent* e) { + XPropertyEvent* xpev; Atom clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); xpev = &e->xproperty; @@ -463,7 +461,7 @@ void propnotify(XEvent *e) { } } -void selnotify(XEvent *e) { +void selnotify(XEvent* e) { ulong nitems, ofs, rem; int format; uchar *data, *last, *repl; @@ -530,7 +528,7 @@ void selnotify(XEvent *e) { if (IS_SET(MODE_BRCKTPASTE) && ofs == 0) ttywrite("\033[200~", 6, 0); - ttywrite((char *)data, nitems * format / 8, 1); + ttywrite((char*)data, nitems * format / 8, 1); if (IS_SET(MODE_BRCKTPASTE) && rem == 0) ttywrite("\033[201~", 6, 0); XFree(data); @@ -547,15 +545,15 @@ void selnotify(XEvent *e) { void xclipcopy(void) { clipcopy(NULL); } -void selclear_(XEvent *e) { selclear(); } +void selclear_(XEvent* e) { selclear(); } -void selrequest(XEvent *e) { - XSelectionRequestEvent *xsre; +void selrequest(XEvent* e) { + XSelectionRequestEvent* xsre; XSelectionEvent xev; Atom xa_targets, string, clipboard; - char * seltext; + char* seltext; - xsre = (XSelectionRequestEvent *)e; + xsre = (XSelectionRequestEvent*)e; xev.type = SelectionNotify; xev.requestor = xsre->requestor; xev.selection = xsre->selection; @@ -572,7 +570,7 @@ void selrequest(XEvent *e) { /* respond with the supported type */ string = xsel.xtarget; XChangeProperty(xsre->display, xsre->requestor, xsre->property, - XA_ATOM, 32, PropModeReplace, (uchar *)&string, 1); + XA_ATOM, 32, PropModeReplace, (uchar*)&string, 1); xev.property = xsre->property; } else if (xsre->target == xsel.xtarget || xsre->target == XA_STRING) { /* @@ -591,18 +589,18 @@ void selrequest(XEvent *e) { } if (seltext != NULL) { XChangeProperty(xsre->display, xsre->requestor, xsre->property, - xsre->target, 8, PropModeReplace, (uchar *)seltext, + xsre->target, 8, PropModeReplace, (uchar*)seltext, strlen(seltext)); xev.property = xsre->property; } } /* all done, send a notification to the listener */ - if (!XSendEvent(xsre->display, xsre->requestor, 1, 0, (XEvent *)&xev)) + if (!XSendEvent(xsre->display, xsre->requestor, 1, 0, (XEvent*)&xev)) fprintf(stderr, "Error sending SelectionNotify event\n"); } -void setsel(char *str, Time t) { +void setsel(char* str, Time t) { if (!str) return; @@ -614,9 +612,9 @@ void setsel(char *str, Time t) { selclear(); } -void xsetsel(char *str) { setsel(str, CurrentTime); } +void xsetsel(char* str) { setsel(str, CurrentTime); } -void brelease(XEvent *e) { +void brelease(XEvent* e) { if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { mousereport(e); return; @@ -628,7 +626,7 @@ void brelease(XEvent *e) { mousesel(e, 1); } -void bmotion(XEvent *e) { +void bmotion(XEvent* e) { if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { mousereport(e); return; @@ -671,7 +669,7 @@ void xresize(int col, int row) { ushort sixd_to_16bit(int x) { return x == 0 ? 0 : 0x3737 + 0x2828 * x; } -int xloadcolor(int i, const char *name, Color *ncolor) { +int xloadcolor(int i, const char* name, Color* ncolor) { XRenderColor color = {.alpha = 0xffff}; if (!name) { @@ -695,7 +693,7 @@ int xloadcolor(int i, const char *name, Color *ncolor) { void xloadcols(void) { int i; static int loaded; - Color * cp; + Color* cp; if (loaded) { for (cp = dc.col; cp < &dc.col[dc.collen]; ++cp) @@ -715,7 +713,7 @@ void xloadcols(void) { loaded = 1; } -int xsetcolorname(int x, const char *name) { +int xsetcolorname(int x, const char* name) { Color ncolor; if (!BETWEEN(x, 0, dc.collen)) @@ -742,7 +740,7 @@ void xhints(void) { XClassHint class = {opt_name ? opt_name : termname, opt_class ? opt_class : termname}; XWMHints wm = {.flags = InputHint, .input = 1}; - XSizeHints *sizeh; + XSizeHints* sizeh; sizeh = XAllocSizeHints(); @@ -784,9 +782,9 @@ int xgeommasktogravity(int mask) { return SouthEastGravity; } -int xloadfont(Font *f, FcPattern *pattern) { - FcPattern *configured; - FcPattern *match; +int xloadfont(Font* f, FcPattern* pattern) { + FcPattern* configured; + FcPattern* match; FcResult result; XGlyphInfo extents; int wantattr, haveattr; @@ -839,7 +837,7 @@ int xloadfont(Font *f, FcPattern *pattern) { } } - XftTextExtentsUtf8(xw.dpy, f->match, (const FcChar8 *)ascii_printable, + XftTextExtentsUtf8(xw.dpy, f->match, (const FcChar8*)ascii_printable, strlen(ascii_printable), &extents); f->set = NULL; @@ -856,14 +854,14 @@ int xloadfont(Font *f, FcPattern *pattern) { return 0; } -void xloadfonts(char *fontstr, double fontsize) { - FcPattern *pattern; +void xloadfonts(char* fontstr, double fontsize) { + FcPattern* pattern; double fontval; if (fontstr[0] == '-') pattern = XftXlfdParse(fontstr, False, False); else - pattern = FcNameParse((FcChar8 *)fontstr); + pattern = FcNameParse((FcChar8*)fontstr); if (!pattern) die("can't open font %s\n", fontstr); @@ -923,7 +921,7 @@ void xloadfonts(char *fontstr, double fontsize) { FcPatternDestroy(pattern); } -void xunloadfont(Font *f) { +void xunloadfont(Font* f) { XftFontClose(xw.dpy, f->match); FcPatternDestroy(f->pattern); if (f->set) @@ -941,7 +939,7 @@ void xunloadfonts(void) { xunloadfont(&dc.ibfont); } -int ximopen(Display *dpy) { +int ximopen(Display* dpy) { XIMCallback imdestroy = {.client_data = NULL, .callback = ximdestroy}; XICCallback icdestroy = {.client_data = NULL, .callback = xicdestroy}; @@ -967,7 +965,7 @@ int ximopen(Display *dpy) { return 1; } -void ximinstantiate(Display *dpy, XPointer client, XPointer call) { +void ximinstantiate(Display* dpy, XPointer client, XPointer call) { if (ximopen(dpy)) XUnregisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, ximinstantiate, NULL); @@ -1080,7 +1078,7 @@ void xinit(int cols, int rows) { xw.netwmpid = XInternAtom(xw.dpy, "_NET_WM_PID", False); XChangeProperty(xw.dpy, xw.win, xw.netwmpid, XA_CARDINAL, 32, - PropModeReplace, (uchar *)&thispid, 1); + PropModeReplace, (uchar*)&thispid, 1); win.mode = MODE_NUMLOCK; resettitle(); @@ -1097,19 +1095,19 @@ void xinit(int cols, int rows) { xsel.xtarget = XA_STRING; } -int xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, +int xmakeglyphfontspecs(XftGlyphFontSpec* specs, const Glyph* glyphs, int len, int x, int y) { float winx = borderpx + x * win.cw, winy = borderpx + y * win.ch, xp, yp; ushort mode, prevmode = USHRT_MAX; - Font * font = &dc.font; + Font* font = &dc.font; int frcflags = FRC_NORMAL; float runewidth = win.cw; Rune rune; FT_UInt glyphidx; FcResult fcres; FcPattern *fcpattern, *fontpattern; - FcFontSet *fcsets[] = {NULL}; - FcCharSet *fccharset; + FcFontSet* fcsets[] = {NULL}; + FcCharSet* fccharset; int i, f, numspecs = 0; for (i = 0, xp = winx, yp = winy + font->ascent; i < len; ++i) { @@ -1223,7 +1221,7 @@ int xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, return numspecs; } -void xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, +void xdrawglyphfontspecs(const XftGlyphFontSpec* specs, Glyph base, int len, int x, int y) { int charlen = len * ((base.mode & ATTR_WIDE) ? 2 : 1); int winx = borderpx + x * win.cw, winy = borderpx + y * win.ch, @@ -1443,7 +1441,7 @@ void xsetenv(void) { setenv("WINDOWID", buf, 1); } -void xseticontitle(char *p) { +void xseticontitle(char* p) { XTextProperty prop; DEFAULT(p, opt_title); @@ -1453,7 +1451,7 @@ void xseticontitle(char *p) { XFree(prop.value); } -void xsettitle(char *p) { +void xsettitle(char* p) { XTextProperty prop; DEFAULT(p, opt_title); @@ -1468,7 +1466,7 @@ int xstartdraw(void) { return IS_SET(MODE_VISIBLE); } void xdrawline(Line line, int x1, int y1, int x2) { int i, x, ox, numspecs; Glyph base, new; - XftGlyphFontSpec *specs = xw.specbuf; + XftGlyphFontSpec* specs = xw.specbuf; numspecs = xmakeglyphfontspecs(specs, &line[x1], x2 - x1, x1, y1); i = ox = 0; @@ -1510,15 +1508,15 @@ void xximspot(int x, int y) { XSetICValues(xw.ime.xic, XNPreeditAttributes, xw.ime.spotlist, NULL); } -void expose(XEvent *ev) { redraw(); } +void expose(XEvent* ev) { redraw(); } -void visibility(XEvent *ev) { - XVisibilityEvent *e = &ev->xvisibility; +void visibility(XEvent* ev) { + XVisibilityEvent* e = &ev->xvisibility; MODBIT(win.mode, e->state != VisibilityFullyObscured, MODE_VISIBLE); } -void unmap(XEvent *ev) { win.mode &= ~MODE_VISIBLE; } +void unmap(XEvent* ev) { win.mode &= ~MODE_VISIBLE; } void xsetpointermotion(int set) { MODBIT(xw.attrs.event_mask, set, PointerMotionMask); @@ -1540,7 +1538,7 @@ int xsetcursor(int cursor) { } void xseturgency(int add) { - XWMHints *h = XGetWMHints(xw.dpy, xw.win); + XWMHints* h = XGetWMHints(xw.dpy, xw.win); MODBIT(h->flags, add, XUrgencyHint); XSetWMHints(xw.dpy, xw.win, h); @@ -1554,8 +1552,8 @@ void xbell(void) { XkbBell(xw.dpy, xw.win, bellvolume, (Atom)NULL); } -void focus(XEvent *ev) { - XFocusChangeEvent *e = &ev->xfocus; +void focus(XEvent* ev) { + XFocusChangeEvent* e = &ev->xfocus; if (e->mode == NotifyGrab) return; @@ -1580,8 +1578,8 @@ int match(uint mask, uint state) { return mask == XK_ANY_MOD || mask == (state & ~ignoremod); } -char *kmap(KeySym k, uint state) { - Key *kp; +char* kmap(KeySym k, uint state) { + Key* kp; int i; /* Check for mapped keys out of X11 function keys. */ @@ -1615,14 +1613,14 @@ char *kmap(KeySym k, uint state) { return NULL; } -void kpress(XEvent *ev) { - XKeyEvent *e = &ev->xkey; +void kpress(XEvent* ev) { + XKeyEvent* e = &ev->xkey; KeySym ksym; char buf[64], *customkey; int len; Rune c; Status status; - Shortcut * bp; + Shortcut* bp; if (IS_SET(MODE_KBDLOCK)) return; @@ -1663,7 +1661,7 @@ void kpress(XEvent *ev) { ttywrite(buf, len, 1); } -void cmessage(XEvent *e) { +void cmessage(XEvent* e) { /* * See xembed specs * http://standards.freedesktop.org/xembed-spec/xembed-spec-latest.html @@ -1681,7 +1679,7 @@ void cmessage(XEvent *e) { } } -void resize(XEvent *e) { +void resize(XEvent* e) { if (e->xconfigure.width == win.w && e->xconfigure.height == win.h) return; @@ -1801,7 +1799,7 @@ void usage(void) { argv0, argv0); } -int main(int argc, char *argv[]) { +int main(int argc, char* argv[]) { xw.l = xw.t = 0; xw.isfixed = False; xsetcursor(cursorshape); From 02213f5f5795cede2f4f626c24ab7779ff2612f1 Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Sat, 26 Dec 2020 12:47:18 +0100 Subject: [PATCH 10/11] Added post-checkout hook to clear build files --- .hooks/post-checkout | 4 ++++ 1 file changed, 4 insertions(+) create mode 100755 .hooks/post-checkout diff --git a/.hooks/post-checkout b/.hooks/post-checkout new file mode 100755 index 0000000..8c86bfc --- /dev/null +++ b/.hooks/post-checkout @@ -0,0 +1,4 @@ +#!/usr/bin/env sh + +# Remove the build directory after checking out a branch +rm -rf build > /dev/null 2>&1 From a1d3a43940fe3992d70c5eba6390c062bd4d1696 Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Sat, 26 Dec 2020 12:49:31 +0100 Subject: [PATCH 11/11] Switched to make clean for post-checkout hook --- .hooks/post-checkout | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.hooks/post-checkout b/.hooks/post-checkout index 8c86bfc..7ea126e 100755 --- a/.hooks/post-checkout +++ b/.hooks/post-checkout @@ -1,4 +1,3 @@ #!/usr/bin/env sh -# Remove the build directory after checking out a branch -rm -rf build > /dev/null 2>&1 +make clean