Compare commits

...
This repository has been archived on 2021-04-22. You can view files and clone it, but cannot push or open issues/pull-requests.

7 Commits

13 changed files with 3440 additions and 3304 deletions

1
.clang-format 100644
View File

@ -0,0 +1 @@
IndentWidth: 4

34
CHANGELOG.md 100644
View File

@ -0,0 +1,34 @@
# Upcoming
## v1.0
* Switched build to CMake
* Completely overhauled code structure
* Add a desktop entry when installing
based on [desktopentry](https://st.suckless.org/patches/desktopentry/)
## 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/)
* 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/)
## v1.2
* 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/)
## v1.3
* 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/)

122
Makefile
View File

@ -1,67 +1,39 @@
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
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
# 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:
@ find src/ -iname '*.c' -or -iname '*.h' | xargs clang-format --style=file -i

View File

@ -5,27 +5,31 @@ if (NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
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} -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")
# Release flags
# -O3 gets added automatically by CMake
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Werror -march=native -pedantic-errors")
# =====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
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
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O3 -Werror -pedantic-errors")
# =====EXECUTABLE=====
@ -39,8 +43,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 +54,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)

View File

@ -10,39 +10,39 @@ 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_)
for (argv0 = *argv, argv++, argc--; \
argv[0] && argv[0][0] == '-' && argv[0][1]; argc--, argv++) { \
char argc_; \
char **argv_; \
int brk_; \
if (argv[0][1] == '-' && argv[0][2] == '\0') { \
argv++; \
argc--; \
break; \
} \
int i_; \
for (i_ = 1, brk_ = 0, argv_ = argv; argv[0][i_] && !brk_; i_++) { \
if (argv_ != argv) \
break; \
argc_ = argv[0][i_]; \
switch (argc_)
#define ARGEND \
} \
}
} \
}
#define ARGC() argc_
#define EARGF(x) \
((argv[0][i_ + 1] == '\0' && argv[1] == NULL) \
? ((x), abort(), (char *)0) \
: (brk_ = 1, (argv[0][i_ + 1] != '\0') ? (&argv[0][i_ + 1]) \
: (argc--, argv++, argv[0])))
((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])))
((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

View File

@ -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))

File diff suppressed because it is too large Load Diff

View File

@ -3,65 +3,51 @@
#ifndef ST_H
#define ST_H
#include <stddef.h>
#include <stdint.h>
#include <sys/types.h>
#include <stddef.h>
#include "types.h"
#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_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
};
typedef unsigned char uchar;
typedef unsigned int uint;
typedef unsigned long ulong;
typedef unsigned short ushort;
typedef uint_least32_t Rune;
enum selection_snap { SNAP_WORD = 1, SNAP_LINE = 2 };
#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 *, ...);

9
src/st/types.h 100644
View File

@ -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

103
src/st/utf8.c 100644
View File

@ -0,0 +1,103 @@
#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;
}

17
src/st/utf8.h 100644
View File

@ -0,0 +1,17 @@
#ifndef UTF8_H
#define UTF8_H
#include <stdint.h>
#include <stdlib.h>
#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

View File

@ -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);

2599
src/x.c

File diff suppressed because it is too large Load Diff