Compare commits

..

11 Commits

24 changed files with 3978 additions and 3842 deletions

149
.clang-format 100644
View File

@ -0,0 +1,149 @@
---
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: Left
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
...

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

View File

@ -0,0 +1,3 @@
#!/usr/bin/env sh
make clean

View File

@ -0,0 +1,3 @@
#!/usr/bin/env sh
make format

36
CHANGELOG.md 100644
View File

@ -0,0 +1,36 @@
# Upcoming
## v1.0
* 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/)
## 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/)
## v2.0
* 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/)

109
Makefile
View File

@ -1,67 +1,42 @@
# =====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
SHELL := $(shell which sh)
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 +49,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 src/*.c src/*.h

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} -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=====
@ -40,16 +44,20 @@ find_package(Freetype 2 REQUIRED)
target_include_directories(stj PRIVATE "${FREETYPE_INCLUDE_DIRS}")
target_link_libraries(stj PRIVATE "${FREETYPE_LIBRARIES}")
find_package(Fontconfig REQUIRED)
find_package(Fontconfig 2 REQUIRED)
target_include_directories(stj PRIVATE "${Fontconfig_INCLUDE_DIRS}")
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)
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

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

View File

@ -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;
/*
@ -16,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;
@ -34,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;
@ -74,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
@ -94,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",

View File

@ -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;
/*
@ -16,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;
@ -34,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;
@ -74,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
@ -94,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",

68
src/st/selection.c 100644
View File

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

36
src/st/selection.h 100644
View File

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

View File

@ -19,7 +19,9 @@
#include "../win.h"
#include "macros.h"
#include "selection.h"
#include "st.h"
#include "utf8.h"
#if defined(__linux)
#include <pty.h>
@ -30,8 +32,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
@ -89,31 +89,13 @@ 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 */
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 */
@ -124,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;
@ -143,17 +125,17 @@ typedef struct {
/* ESC type [[ [<priv>] <arg> [;]] <mode>] 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);
@ -165,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);
@ -184,154 +166,104 @@ 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 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**);
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 **);
static ssize_t xwrite(int, const char *, size_t);
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;
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};
ssize_t xwrite(int fd, const char *s, size_t len) {
size_t aux = len;
/**
* 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;
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)))
if (!(ptr = malloc(p_len)))
die("malloc: %s\n", strerror(errno));
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)
/**
* 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)
/**
* 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;
}
size_t utf8decode(const char *chr, Rune *u, size_t chr_len) {
size_t i, j, len, type;
Rune udecoded;
*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;
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);
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)
;
return i;
return p_str;
}
static const char base64_digits[] = {
@ -350,15 +282,15 @@ 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;
char * result, *dst;
if (in_len % 4)
in_len += 4 - (in_len % 4);
@ -385,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;
@ -446,45 +372,21 @@ 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))
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) {
void selsnap(int* x, int* y, int direction) {
int newx, newy, xt, yt;
int delim, prevdelim;
Glyph *gp, *prevgp;
@ -553,8 +455,8 @@ void selsnap(int *x, int *y, int direction) {
}
}
char *getsel(void) {
char *str, *ptr;
char* getsel(void) {
char * str, *ptr;
int y, bufsize, lastx, linelen;
Glyph *gp, *last;
@ -606,15 +508,7 @@ 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, ...) {
void die(const char* errstr, ...) {
va_list ap;
va_start(ap, errstr);
@ -623,9 +517,9 @@ void die(const char *errstr, ...) {
exit(1);
}
void execsh(char *cmd, char **args) {
char *sh, *prog, *arg;
const struct passwd *pw;
void execsh(char* cmd, char** args) {
char * sh, *prog, *arg;
const struct passwd* pw;
errno = 0;
if ((pw = getpwuid(getuid())) == NULL) {
@ -651,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");
@ -690,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;
@ -712,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) {
@ -792,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);
@ -818,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;
@ -971,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;
@ -1015,24 +909,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;
@ -1045,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;
@ -1092,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 */
@ -1129,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;
@ -1157,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);
@ -1172,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);
@ -1195,14 +1071,15 @@ 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;
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;
}
@ -1217,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;
}
@ -1239,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;
@ -1247,8 +1125,8 @@ void tsetattr(int *attr, int l) {
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);
~(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;
@ -1323,7 +1201,8 @@ void tsetattr(int *attr, int l) {
} 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]);
fprintf(stderr, "erresc(default): gfx attr %d unknown\n",
attr[i]);
csidump();
}
break;
@ -1345,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) {
@ -1441,7 +1320,8 @@ void tsetmode(int priv, int set, int *args, int narg) {
codes. */
break;
default:
fprintf(stderr, "erresc: unknown private set/reset mode %d\n", *args);
fprintf(stderr, "erresc: unknown private set/reset mode %d\n",
*args);
break;
}
} else {
@ -1619,7 +1499,8 @@ void csihandle(void) {
break;
case 'X': /* ECH -- Erase <n> char */
DEFAULT(csiescseq.arg[0], 1);
tclearregion(term.c.x, term.c.y, term.c.x + csiescseq.arg[0] - 1, term.c.y);
tclearregion(term.c.x, term.c.y, term.c.x + csiescseq.arg[0] - 1,
term.c.y);
break;
case 'P': /* DCH -- Delete <n> char */
DEFAULT(csiescseq.arg[0], 1);
@ -1641,8 +1522,8 @@ void csihandle(void) {
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);
len = snprintf(buf, sizeof(buf), "\033[%i;%iR", term.c.y + 1,
term.c.x + 1);
ttywrite(buf, len, 0);
}
break;
@ -1772,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';
@ -1822,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);
@ -1835,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));
@ -1895,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);
@ -2108,8 +1989,8 @@ int eschandle(uchar ascii) {
strhandle();
break;
default:
fprintf(stderr, "erresc: unknown sequence ESC 0x%02X '%c'\n", (uchar)ascii,
isprint(ascii) ? ascii : '.');
fprintf(stderr, "erresc: unknown sequence ESC 0x%02X '%c'\n",
(uchar)ascii, isprint(ascii) ? ascii : '.');
break;
}
return 1;
@ -2119,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)) {
@ -2249,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;
@ -2283,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) {

View File

@ -3,9 +3,12 @@
#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,
@ -23,29 +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
};
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 {
Rune u; /* character code */
@ -54,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);
@ -90,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;

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

105
src/st/utf8.c 100644
View File

@ -0,0 +1,105 @@
#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

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

332
src/x.c
View File

@ -15,7 +15,7 @@
#include <time.h>
#include <unistd.h>
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? */
@ -112,7 +112,7 @@ typedef struct {
typedef struct {
Atom xtarget;
char *primary, *clipboard;
char * primary, *clipboard;
struct timespec tclick1;
struct timespec tclick2;
} XSelection;
@ -128,70 +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,
@ -227,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);
@ -264,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);
@ -272,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);
@ -294,7 +293,7 @@ void zoomabs(const Arg *arg) {
xhints();
}
void zoomreset(const Arg *arg) {
void zoomreset(const Arg* arg) {
Arg larg;
if (defaultfontsize > 0) {
@ -303,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);
@ -332,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];
@ -374,16 +373,17 @@ void mousereport(XEvent *e) {
}
if (!IS_SET(MODE_MOUSEX10)) {
button += ((state & ShiftMask) ? 4 : 0) + ((state & Mod4Mask) ? 8 : 0) +
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');
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);
len = snprintf(buf, sizeof(buf), "\033[M%c%c%c", 32 + button,
32 + x + 1, 32 + y + 1);
} else {
return;
}
@ -400,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 Button<N>mask for Button<N> - it's set on release */
uint state = e->xbutton.state & ~buttonmask(e->xbutton.button);
@ -418,7 +418,7 @@ int mouseaction(XEvent *e, uint release) {
return 0;
}
void bpress(XEvent *e) {
void bpress(XEvent* e) {
struct timespec now;
int snap;
@ -450,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;
@ -461,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;
@ -479,9 +479,9 @@ void selnotify(XEvent *e) {
return;
do {
if (XGetWindowProperty(xw.dpy, xw.win, property, ofs, BUFSIZ / 4, False,
AnyPropertyType, &type, &format, &nitems, &rem,
&data)) {
if (XGetWindowProperty(xw.dpy, xw.win, property, ofs, BUFSIZ / 4,
False, AnyPropertyType, &type, &format, &nitems,
&rem, &data)) {
fprintf(stderr, "Clipboard allocation failed\n");
return;
}
@ -528,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);
@ -545,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;
@ -569,8 +569,8 @@ void selrequest(XEvent *e) {
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);
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) {
/*
@ -583,23 +583,24 @@ void selrequest(XEvent *e) {
} else if (xsre->selection == clipboard) {
seltext = xsel.clipboard;
} else {
fprintf(stderr, "Unhandled clipboard selection 0x%lx\n", xsre->selection);
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,
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;
@ -611,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;
@ -625,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;
@ -657,8 +658,8 @@ void xresize(int col, int row) {
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));
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);
@ -668,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) {
@ -692,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)
@ -712,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))
@ -739,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();
@ -781,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;
@ -836,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;
@ -853,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);
@ -920,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)
@ -938,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};
@ -950,12 +951,13 @@ int ximopen(Display *dpy) {
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);
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");
@ -963,10 +965,10 @@ 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);
XUnregisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL,
ximinstantiate, NULL);
}
void ximdestroy(XIM xim, XPointer client, XPointer call) {
@ -1033,8 +1035,8 @@ void xinit(int cols, int rows) {
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));
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);
@ -1046,8 +1048,8 @@ void xinit(int cols, int rows) {
/* input methods */
if (!ximopen(xw.dpy)) {
XRegisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, ximinstantiate,
NULL);
XRegisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL,
ximinstantiate, NULL);
}
/* white cursor, black outline */
@ -1075,8 +1077,8 @@ void xinit(int cols, int rows) {
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);
XChangeProperty(xw.dpy, xw.win, xw.netwmpid, XA_CARDINAL, 32,
PropModeReplace, (uchar*)&thispid, 1);
win.mode = MODE_NUMLOCK;
resettitle();
@ -1093,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) {
@ -1155,7 +1157,8 @@ int xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len,
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) {
if (!glyphidx && frc[f].flags == frcflags &&
frc[f].unicodep == rune) {
break;
}
}
@ -1218,12 +1221,12 @@ 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,
width = charlen * win.cw;
Color *fg, *bg, *temp, revfg, revbg, truefg, truebg;
Color * fg, *bg, *temp, revfg, revbg, truefg, truebg;
XRenderColor colfg, colbg;
XRectangle r;
@ -1310,10 +1313,12 @@ void xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len,
/* 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));
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,
xclear(
winx + width, (y == 0) ? 0 : winy, win.w,
((winy + win.ch >= borderpx + win.th) ? win.h : (winy + win.ch)));
}
if (y == 0)
@ -1340,7 +1345,8 @@ void xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len,
}
if (base.mode & ATTR_STRUCK) {
XftDrawRect(xw.draw, fg, winx, winy + 2 * dc.font.ascent / 3, width, 1);
XftDrawRect(xw.draw, fg, winx, winy + 2 * dc.font.ascent / 3, width,
1);
}
/* Reset clip to none. */
@ -1369,7 +1375,8 @@ void xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og) {
/*
* Select the right color for the right mode.
*/
g.mode &= ATTR_BOLD | ATTR_ITALIC | ATTR_UNDERLINE | ATTR_STRUCK | ATTR_WIDE;
g.mode &=
ATTR_BOLD | ATTR_ITALIC | ATTR_UNDERLINE | ATTR_STRUCK | ATTR_WIDE;
if (IS_SET(MODE_REVERSE)) {
g.mode |= ATTR_REVERSE;
@ -1434,7 +1441,7 @@ void xsetenv(void) {
setenv("WINDOWID", buf, 1);
}
void xseticontitle(char *p) {
void xseticontitle(char* p) {
XTextProperty prop;
DEFAULT(p, opt_title);
@ -1444,7 +1451,7 @@ void xseticontitle(char *p) {
XFree(prop.value);
}
void xsettitle(char *p) {
void xsettitle(char* p) {
XTextProperty prop;
DEFAULT(p, opt_title);
@ -1459,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;
@ -1501,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);
@ -1531,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);
@ -1545,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;
@ -1571,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. */
@ -1606,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;
@ -1654,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
@ -1672,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;
@ -1754,7 +1761,8 @@ void run(void) {
trigger = now;
drawing = 1;
}
timeout = (maxlatency - TIMEDIFF(now, trigger)) / maxlatency * minlatency;
timeout = (maxlatency - TIMEDIFF(now, trigger)) / maxlatency *
minlatency;
if (timeout > 0)
continue; /* we have time, try to find idle */
}
@ -1791,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);