Compare commits
7 Commits
Author | SHA1 | Date |
---|---|---|
Jef Roosens | 0a41016245 | |
Jef Roosens | 010fb66cb6 | |
Jef Roosens | 25af8ba5fc | |
Jef Roosens | a13536d0c7 | |
Jef Roosens | 1052dd6244 | |
Jef Roosens | 32184c498c | |
Jef Roosens | b6b60550d2 |
|
@ -0,0 +1 @@
|
|||
IndentWidth: 4
|
|
@ -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
122
Makefile
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
52
src/arg.h
52
src/arg.h
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
|
|
3652
src/st/st.c
3652
src/st/st.c
File diff suppressed because it is too large
Load Diff
72
src/st/st.h
72
src/st/st.h
|
@ -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 *, ...);
|
||||
|
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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
|
40
src/win.h
40
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);
|
||||
|
|
Reference in New Issue