Compare commits

..

7 Commits

18 changed files with 3440 additions and 3490 deletions

1
.clang-format 100644
View File

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

View File

@ -1,47 +0,0 @@
<!---
Original source:
https://gitlab.com/gitlab-org/gitlab/-/blob/d6805f4fd9d0c73b23fd400bddc0900ae1c2885d/.gitlab/issue_templates/Refactoring.md
Please read this!
Before opening a new issue, make sure to search for keywords in the issues
filtered by the "regression" or "bug" label:
- https://gitlab.com/gitlab-org/gitlab/issues?label_name%5B%5D=regression
- https://gitlab.com/gitlab-org/gitlab/issues?label_name%5B%5D=bug
and verify the issue you're about to submit isn't a duplicate.
-->
### Summary
<!-- Summarize the bug encountered concisely. -->
### Steps to reproduce
<!-- Describe how one can reproduce the issue - this is very important. Please use an ordered list. -->
### Example Project
<!-- If possible, please create an example project here on GitLab.com that exhibits the problematic
behavior, and link to it here in the bug report. If you are using an older version of GitLab, this
will also determine whether the bug is fixed in a more recent version. -->
### What is the current *bug* behavior?
<!-- Describe what actually happens. -->
### What is the expected *correct* behavior?
<!-- Describe what you should see instead. -->
### Relevant logs and/or screenshots
<!-- Paste any relevant logs - please use code blocks (```) to format console output, logs, and code
as it's tough to read otherwise. -->
### Possible fixes
<!-- If you can, link to the line of code that might be responsible for the problem. -->
/label ~bug

View File

@ -1,38 +0,0 @@
<!--
Original source: https://gitlab.com/gitlab-org/gitlab/-/blob/d6805f4fd9d0c73b23fd400bddc0900ae1c2885d/.gitlab/issue_templates/Documentation.md
* Use this issue template for suggesting new docs or updates to existing docs.
Note: Doc work as part of feature development is covered in the Feature Request template.
* For issues related to features of the docs.gitlab.com site, see
https://gitlab.com/gitlab-org/gitlab-docs/issues/
* For information about documentation content and process, see
https://docs.gitlab.com/ee/development/documentation/ -->
### Problem to solve
<!-- Include the following detail as necessary:
* What product or feature(s) affected?
* What docs or doc section affected? Include links or paths.
* Is there a problem with a specific document, or a feature/process that's not addressed sufficiently in docs?
* Any other ideas or requests?
-->
### Further details
<!--
* Any concepts, procedures, reference info we could add to make it easier to use the documentation
* Include use cases, benefits, and/or goals for this work.
* If adding content: What audience is it intended for? (What roles and scenarios?)
-->
### Proposal
<!-- Further specifics for how can we solve the problem. -->
### Who can address the issue
<!-- What if any special expertise is required to resolve this issue? -->
/label ~documentation

View File

@ -1,36 +0,0 @@
<!--
Original source:
https://gitlab.com/gitlab-org/gitlab/-/blob/d6805f4fd9d0c73b23fd400bddc0900ae1c2885d/.gitlab/issue_templates/Feature%20proposal.md
-->
### Problem to solve
<!-- What problem do we solve? -->
### Intended users
<!-- Who will use this feature? -->
### User experience goal
<!-- What is the single user experience workflow this problem addresses? -->
### Proposal
<!-- How are we going to solve the problem? -->
### Further details
<!-- Include use cases, benefits, goals, or any other details that will help us understand the problem better. -->
### Documentation
<!-- What documentation needs to be added? -->
### Links / references
<!-- Useful links/references -->
/label ~devops:: ~group: ~Category:
/label ~feature

View File

@ -1,35 +0,0 @@
<!--
Original source:
https://gitlab.com/gitlab-org/gitlab/-/blob/d6805f4fd9d0c73b23fd400bddc0900ae1c2885d/.gitlab/issue_templates/Implementation.md
-->
## Why are we doing this work
<!--
A brief explanation of the why, not the what or how. Assume the reader doesn't
know the background and won't have time to dig-up information from comment
threads.
-->
## Relevant links
<!--
Information that the developer might need to refer to when implementing
the issue.
-->
## Non-functional requirements
<!-- Add details for required items and delete others. -->
- [ ] Documentation:
- [ ] Feature flag:
- [ ] Performance:
- [ ] Testing:
## Implementation plan
<!--
Steps and the parts of the code that will need to get updated. The plan can
also call-out responsibilities for other team members or teams.
-->
- [ ]
/label ~implementation

View File

@ -1,30 +0,0 @@
<!--
Original source:
https://gitlab.com/gitlab-org/gitlab/-/blob/d6805f4fd9d0c73b23fd400bddc0900ae1c2885d/.gitlab/issue_templates/Refactoring.md
-->
## Summary
<!--
Please briefly describe what part of the code base needs to be refactored.
-->
## Improvements
<!-- Explain the benefits of refactoring this code. -->
## Risks
<!--
Please list features that can break because of this refactoring and how you
intend to solve that.
-->
## Involved components
<!-- List files or directories that will be changed by the refactoring. -->
## Optional: Intended side effects
<!--
If the refactoring involves changes apart from the main improvements
(such as a better UI), list them here. It may be a good idea to create separate
issues and link them here.
-->
/label ~maintenance

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