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 SRC_DIR := src
BUILD_DIR := build BUILD_DIR := build
RELEASE_DIR := $(BUILD_DIR)/release RELEASE_DIR := $(BUILD_DIR)/release
DEBUG_DIR := $(BUILD_DIR)/debug DEBUG_DIR := $(BUILD_DIR)/debug
MINSIZEREL_DIR := $(BUILD_DIR)/min_size_rel
BINARY := stj BINARY := stj
CORES := $(shell nproc --all) CORES := $(shell nproc --all)
PREFIX := /usr/local PREFIX := /usr/local
MANPREFIX := $(PREFIX)/share/man MANPREFIX := $(PREFIX)/share/man
SHELL := $(shell which sh)
all: debug all: debug
.PHONY: all .PHONY: all
# Installation & removal # =====INSTALL & UNINSTALL=====
install: release install: release
mkdir -p $(DESTDIR)$(PREFIX)/bin @ mkdir -p '$(DESTDIR)$(PREFIX)/bin'
cp -f build/release/stj $(DESTDIR)$(PREFIX)/bin @ cp -f '$(RELEASE_DIR)/$(BINARY)' '$(DESTDIR)$(PREFIX)/bin'
chmod 755 $(DESTDIR)$(PREFIX)/bin/stj @ chmod 755 '$(DESTDIR)$(PREFIX)/bin/$(BINARY)'
mkdir -p $(DESTDIR)$(MANPREFIX)/man1 @ mkdir -p '$(DESTDIR)$(MANPREFIX)/man1'
sed "s/VERSION/$(VERSION)/g" < data/stj.1 > $(DESTDIR)$(MANPREFIX)/man1/stj.1 @ sed "s/VERSION/$(VERSION)/g" < 'data/stj.1' > '$(DESTDIR)$(MANPREFIX)/man1/$(BINARY).1'
chmod 644 $(DESTDIR)$(MANPREFIX)/man1/stj.1 @ chmod 644 '$(DESTDIR)$(MANPREFIX)/man1/$(BINARY).1'
tic -sx data/stj.info @ tic -sx 'data/stj.info'
cp -f data/stj.desktop $(DESTDIR)$(PREFIX)/share/applications @ cp -f 'data/$(BINARY).desktop' '$(DESTDIR)$(PREFIX)/share/applications'
.PHONY: install
uninstall: uninstall:
rm -f $(DESTDIR)$(PREFIX)/bin/stj @ rm -f '$(DESTDIR)$(PREFIX)/bin/$(BINARY)'
rm -f $(DESTDIR)$(MANPREFIX)/man1/stj.1 @ rm -f '$(DESTDIR)$(MANPREFIX)/man1/$(BINARY).1'
rm -f $(DESTDIR)$(PREFIX)/share/applications/stj.desktop @ rm -f '$(DESTDIR)$(PREFIX)/share/applications/$(BINARY).desktop'
.PHONY: uninstall
# Full clean # =====DEBUG=====
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_DIR)/Makefile debug: $(DEBUG_DIR)/Makefile
@ make -C '$(DEBUG_DIR)' -j'$(CORES)' && \ @ make -C '$(DEBUG_DIR)' -j'$(CORES)' && \
ln -sf '$(DEBUG_DIR)/$(BINARY)' ./'$(BINARY)' ln -sf '$(DEBUG_DIR)/$(BINARY)' ./'$(BINARY)'
@ -74,6 +49,48 @@ $(DEBUG_DIR)/Makefile: $(SRC_DIR)/CMakeLists.txt
-DCMAKE_BUILD_TYPE=Debug \ -DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON -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: clean-debug:
@ rm -rf '$(DEBUG_DIR)' @ rm -rf '$(DEBUG_DIR)'
.PHONY: clean-debug .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) set(CMAKE_BUILD_TYPE Release)
endif() endif()
set(SYSTEM_TYPE x64)
# =====COMPILER=====
# =====COMMON SETTINGS=====
set(CMAKE_C_COMPILER "clang-11") set(CMAKE_C_COMPILER "clang-11")
set(CMAKE_C_STANDARD 11) set(CMAKE_C_STANDARD 11)
project(stj VERSION 0.1) project(stj VERSION 0.1)
# =====COMPILE FLAGS=====
add_definitions(-DVERSION="${CMAKE_PROJECT_VERSION}" -D_XOPEN_SOURCE=600) 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 # =====BUILD TYPES=====
# -O3 gets added automatically by CMake # Debug
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Werror -march=native -pedantic-errors") 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===== # =====EXECUTABLE=====
@ -40,16 +44,20 @@ find_package(Freetype 2 REQUIRED)
target_include_directories(stj PRIVATE "${FREETYPE_INCLUDE_DIRS}") target_include_directories(stj PRIVATE "${FREETYPE_INCLUDE_DIRS}")
target_link_libraries(stj PRIVATE "${FREETYPE_LIBRARIES}") 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_include_directories(stj PRIVATE "${Fontconfig_INCLUDE_DIRS}")
target_link_libraries(stj PRIVATE "${Fontconfig_LIBRARIES}") target_link_libraries(stj PRIVATE "${Fontconfig_LIBRARIES}")
find_package(X11 REQUIRED) find_package(X11 REQUIRED)
target_include_directories(stj PRIVATE "${X11_INCLUDE_DIR}") target_include_directories(stj PRIVATE "${X11_INCLUDE_DIR}")
target_link_libraries(stj PRIVATE "${X11_LIBRARIES}") 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 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 util)
target_link_libraries(stj PRIVATE Xft)
target_link_libraries(stj PRIVATE Xrender)

View File

@ -6,14 +6,14 @@
#ifndef ARG_H #ifndef ARG_H
#define ARG_H #define ARG_H
extern char *argv0; extern char* argv0;
/* use main(int argc, char *argv[]) */ /* use main(int argc, char *argv[]) */
#define ARGBEGIN \ #define ARGBEGIN \
for (argv0 = *argv, argv++, argc--; \ for (argv0 = *argv, argv++, argc--; \
argv[0] && argv[0][0] == '-' && argv[0][1]; argc--, argv++) { \ argv[0] && argv[0][0] == '-' && argv[0][1]; argc--, argv++) { \
char argc_; \ char argc_; \
char **argv_; \ char** argv_; \
int brk_; \ int brk_; \
if (argv[0][1] == '-' && argv[0][2] == '\0') { \ if (argv[0][1] == '-' && argv[0][2] == '\0') { \
argv++; \ argv++; \
@ -35,13 +35,13 @@ extern char *argv0;
#define EARGF(x) \ #define EARGF(x) \
((argv[0][i_ + 1] == '\0' && argv[1] == NULL) \ ((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]) \ : (brk_ = 1, (argv[0][i_ + 1] != '\0') ? (&argv[0][i_ + 1]) \
: (argc--, argv++, argv[0]))) : (argc--, argv++, argv[0])))
#define ARGF() \ #define ARGF() \
((argv[0][i_ + 1] == '\0' && argv[1] == NULL) \ ((argv[0][i_ + 1] == '\0' && argv[1] == NULL) \
? (char *)0 \ ? (char*)0 \
: (brk_ = 1, (argv[0][i_ + 1] != '\0') ? (&argv[0][i_ + 1]) \ : (brk_ = 1, (argv[0][i_ + 1] != '\0') ? (&argv[0][i_ + 1]) \
: (argc--, argv++, argv[0]))) : (argc--, argv++, argv[0])))

View File

@ -5,7 +5,8 @@
* *
* font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html * 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; static int borderpx = 2;
/* /*
@ -16,14 +17,14 @@ static int borderpx = 2;
* 4: value of shell in /etc/passwd * 4: value of shell in /etc/passwd
* 5: value of shell in config.h * 5: value of shell in config.h
*/ */
static char *shell = "/bin/sh"; static char* shell = "/bin/sh";
char *utmp = NULL; char* utmp = NULL;
/* scroll program: to enable use a string like "scroll" */ /* scroll program: to enable use a string like "scroll" */
char *scroll = NULL; char* scroll = NULL;
char *stty_args = "stty raw pass8 nl -echo -iexten -cstopb 38400"; char* stty_args = "stty raw pass8 nl -echo -iexten -cstopb 38400";
/* identification sequence returned in DA and DECID */ /* identification sequence returned in DA and DECID */
char *vtiden = "\033[?6c"; char* vtiden = "\033[?6c";
/* Kerning / character bounding-box multipliers */ /* Kerning / character bounding-box multipliers */
static float cwscale = 1.0; static float cwscale = 1.0;
@ -34,7 +35,7 @@ static float chscale = 1.0;
* *
* More advanced example: L" `'\"()[]{}" * More advanced example: L" `'\"()[]{}"
*/ */
wchar_t *worddelimiters = L" "; wchar_t* worddelimiters = L" ";
/* selection timeouts (in milliseconds) */ /* selection timeouts (in milliseconds) */
static unsigned int doubleclicktimeout = 300; static unsigned int doubleclicktimeout = 300;
@ -74,7 +75,7 @@ static unsigned int cursorthickness = 2;
static int bellvolume = 0; static int bellvolume = 0;
/* default TERM value */ /* default TERM value */
char *termname = "st-256color"; char* termname = "st-256color";
/* /*
* spaces per tab * spaces per tab
@ -94,7 +95,7 @@ char *termname = "st-256color";
unsigned int tabspaces = 8; unsigned int tabspaces = 8;
/* Terminal colors (16 first used in escape sequence) */ /* Terminal colors (16 first used in escape sequence) */
static const char *colorname[] = { static const char* colorname[] = {
/* 8 normal colors */ /* 8 normal colors */
"black", "black",
"red3", "red3",

View File

@ -5,7 +5,8 @@
* *
* font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html * 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; static int borderpx = 2;
/* /*
@ -16,14 +17,14 @@ static int borderpx = 2;
* 4: value of shell in /etc/passwd * 4: value of shell in /etc/passwd
* 5: value of shell in config.h * 5: value of shell in config.h
*/ */
static char *shell = "/bin/sh"; static char* shell = "/bin/sh";
char *utmp = NULL; char* utmp = NULL;
/* scroll program: to enable use a string like "scroll" */ /* scroll program: to enable use a string like "scroll" */
char *scroll = NULL; char* scroll = NULL;
char *stty_args = "stty raw pass8 nl -echo -iexten -cstopb 38400"; char* stty_args = "stty raw pass8 nl -echo -iexten -cstopb 38400";
/* identification sequence returned in DA and DECID */ /* identification sequence returned in DA and DECID */
char *vtiden = "\033[?6c"; char* vtiden = "\033[?6c";
/* Kerning / character bounding-box multipliers */ /* Kerning / character bounding-box multipliers */
static float cwscale = 1.0; static float cwscale = 1.0;
@ -34,7 +35,7 @@ static float chscale = 1.0;
* *
* More advanced example: L" `'\"()[]{}" * More advanced example: L" `'\"()[]{}"
*/ */
wchar_t *worddelimiters = L" "; wchar_t* worddelimiters = L" ";
/* selection timeouts (in milliseconds) */ /* selection timeouts (in milliseconds) */
static unsigned int doubleclicktimeout = 300; static unsigned int doubleclicktimeout = 300;
@ -74,7 +75,7 @@ static unsigned int cursorthickness = 2;
static int bellvolume = 0; static int bellvolume = 0;
/* default TERM value */ /* default TERM value */
char *termname = "st-256color"; char* termname = "st-256color";
/* /*
* spaces per tab * spaces per tab
@ -94,7 +95,7 @@ char *termname = "st-256color";
unsigned int tabspaces = 8; unsigned int tabspaces = 8;
/* Terminal colors (16 first used in escape sequence) */ /* Terminal colors (16 first used in escape sequence) */
static const char *colorname[] = { static const char* colorname[] = {
/* 8 normal colors */ /* 8 normal colors */
"black", "black",
"red3", "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 "../win.h"
#include "macros.h" #include "macros.h"
#include "selection.h"
#include "st.h" #include "st.h"
#include "utf8.h"
#if defined(__linux) #if defined(__linux)
#include <pty.h> #include <pty.h>
@ -30,8 +32,6 @@
#endif #endif
/* Arbitrary sizes */ /* Arbitrary sizes */
#define UTF_INVALID 0xFFFD
#define UTF_SIZE 4
#define ESC_BUF_SIZ (128 * UTF_SIZE) #define ESC_BUF_SIZ (128 * UTF_SIZE)
#define ESC_ARG_SIZ 16 #define ESC_ARG_SIZ 16
#define STR_BUF_SIZ ESC_BUF_SIZ #define STR_BUF_SIZ ESC_BUF_SIZ
@ -89,31 +89,13 @@ typedef struct {
char state; char state;
} TCursor; } 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 */ /* Internal representation of the screen */
typedef struct { typedef struct {
int row; /* nb row */ int row; /* nb row */
int col; /* nb col */ int col; /* nb col */
Line *line; /* screen */ Line* line; /* screen */
Line *alt; /* alternate screen */ Line* alt; /* alternate screen */
int *dirty; /* dirtyness of lines */ int* dirty; /* dirtyness of lines */
TCursor c; /* cursor */ TCursor c; /* cursor */
int ocx; /* old cursor col */ int ocx; /* old cursor col */
int ocy; /* old cursor row */ int ocy; /* old cursor row */
@ -124,7 +106,7 @@ typedef struct {
char trantbl[4]; /* charset table translation */ char trantbl[4]; /* charset table translation */
int charset; /* current charset */ int charset; /* current charset */
int icharset; /* selected charset for sequence */ int icharset; /* selected charset for sequence */
int *tabs; int* tabs;
Rune lastc; /* last printed char outside of sequence, 0 if control */ Rune lastc; /* last printed char outside of sequence, 0 if control */
} Term; } Term;
@ -143,17 +125,17 @@ typedef struct {
/* ESC type [[ [<priv>] <arg> [;]] <mode>] ESC '\' */ /* ESC type [[ [<priv>] <arg> [;]] <mode>] ESC '\' */
typedef struct { typedef struct {
char type; /* ESC type ... */ char type; /* ESC type ... */
char *buf; /* allocated raw string */ char* buf; /* allocated raw string */
size_t siz; /* allocation size */ size_t siz; /* allocation size */
size_t len; /* raw string length */ size_t len; /* raw string length */
char *args[STR_ARG_SIZ]; char* args[STR_ARG_SIZ];
int narg; /* nb of args */ int narg; /* nb of args */
} STREscape; } STREscape;
static void execsh(char *, char **); static void execsh(char*, char**);
static void stty(char **); static void stty(char**);
static void sigchld(int); static void sigchld(int);
static void ttywriteraw(const char *, size_t); static void ttywriteraw(const char*, size_t);
static void csidump(void); static void csidump(void);
static void csihandle(void); static void csihandle(void);
@ -165,7 +147,7 @@ static void strhandle(void);
static void strparse(void); static void strparse(void);
static void strreset(void); static void strreset(void);
static void tprinter(char *, size_t); static void tprinter(char*, size_t);
static void tdumpsel(void); static void tdumpsel(void);
static void tdumpline(int); static void tdumpline(int);
static void tdump(void); static void tdump(void);
@ -184,154 +166,104 @@ static void tputc(Rune);
static void treset(void); static void treset(void);
static void tscrollup(int, int); static void tscrollup(int, int);
static void tscrolldown(int, int); static void tscrolldown(int, int);
static void tsetattr(int *, int); static void tsetattr(int*, int);
static void tsetchar(Rune, Glyph *, int, int); static void tsetchar(Rune, Glyph*, int, int);
static void tsetdirt(int, int); static void tsetdirt(int, int);
static void tsetscroll(int, int); static void tsetscroll(int, int);
static void tswapscreen(void); static void tswapscreen(void);
static void tsetmode(int, int, int *, int); static void tsetmode(int, int, int*, int);
static int twrite(const char *, int, int); static int twrite(const char*, int, int);
static void tfulldirt(void); static void tfulldirt(void);
static void tcontrolcode(uchar); static void tcontrolcode(uchar);
static void tdectest(char); static void tdectest(char);
static void tdefutf8(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 tdeftran(char);
static void tstrsequence(uchar); static void tstrsequence(uchar);
static void drawregion(int, int, int, int); static void drawregion(int, int, int, int);
static void selnormalize(void); static char* base64dec(const char*);
static void selscroll(int, int); static char base64dec_getc(const char**);
static void selsnap(int *, int *, int);
static size_t utf8decode(const char *, Rune *, size_t); static ssize_t xwrite(int, const char*, 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);
/* Globals */ /* Globals */
static Term term; static Term term;
static Selection sel;
static CSIEscape csiescseq; static CSIEscape csiescseq;
static STREscape strescseq; static STREscape strescseq;
static int iofd = 1; static int iofd = 1;
static int cmdfd; static int cmdfd;
static pid_t pid; 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}; * Same as write, but ensures that all bytes are written to the descriptor
static Rune utfmin[UTF_SIZE + 1] = {0, 0, 0x80, 0x800, 0x10000}; * (write sometimes isn't able to write all bytes)
static Rune utfmax[UTF_SIZE + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; *
* @param p_file_desc file descriptor to write to; same logic as write
ssize_t xwrite(int fd, const char *s, size_t len) { * @param p_str char array to write to the file descriptor
size_t aux = len; * @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; ssize_t result;
while (len > 0) { while (p_nbytes > 0) {
result = write(fd, s, len); result = write(p_file_desc, p_str, p_nbytes);
// This means an error occured in write, so it passes the error along // This means an error occured in write, so it passes the error along
if (result < 0) if (result < 0)
return result; return result;
len -= result; p_nbytes -= (size_t)result;
s += 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) { * same as malloc, but kill the program if it fails
void *ptr; *
* @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)); die("malloc: %s\n", strerror(errno));
return ptr; return ptr;
} }
// Same as realloc, but stops entire program if malloc fails /**
void *safe_realloc(void *ptr, size_t len) { * same as realloc, but kill the program if it fails
if ((ptr = realloc(ptr, len)) == NULL) *
* @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)); 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)); die("strdup: %s\n", strerror(errno));
return s; return p_str;
}
size_t utf8decode(const char *chr, Rune *u, size_t chr_len) {
size_t i, j, len, type;
Rune udecoded;
*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;
} }
static const char base64_digits[] = { 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, 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)) while (**src && !isprint(**src))
(*src)++; (*src)++;
return **src ? *((*src)++) : '='; /* emulate padding if string ends */ return **src ? *((*src)++) : '='; /* emulate padding if string ends */
} }
char *base64dec(const char *src) { char* base64dec(const char* src) {
size_t in_len = strlen(src); size_t in_len = strlen(src);
char *result, *dst; char * result, *dst;
if (in_len % 4) if (in_len % 4)
in_len += 4 - (in_len % 4); in_len += 4 - (in_len % 4);
@ -385,12 +317,6 @@ char *base64dec(const char *src) {
return result; return result;
} }
void selinit(void) {
sel.mode = SEL_IDLE;
sel.snap = 0;
sel.ob.x = -1;
}
int tlinelen(int y) { int tlinelen(int y) {
int i = term.col; 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; 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) { int selected(int x, int y) {
if (sel.mode == SEL_EMPTY || sel.ob.x == -1 || if (sel.mode == SEL_EMPTY || sel.ob.x == -1 ||
sel.alt != IS_SET(MODE_ALTSCREEN)) sel.alt != IS_SET(MODE_ALTSCREEN))
return 0; return 0;
if (sel.type == SEL_RECTANGULAR) 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); (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 newx, newy, xt, yt;
int delim, prevdelim; int delim, prevdelim;
Glyph *gp, *prevgp; Glyph *gp, *prevgp;
@ -553,8 +455,8 @@ void selsnap(int *x, int *y, int direction) {
} }
} }
char *getsel(void) { char* getsel(void) {
char *str, *ptr; char * str, *ptr;
int y, bufsize, lastx, linelen; int y, bufsize, lastx, linelen;
Glyph *gp, *last; Glyph *gp, *last;
@ -606,15 +508,7 @@ char *getsel(void) {
return str; return str;
} }
void selclear(void) { void die(const char* errstr, ...) {
if (sel.ob.x == -1)
return;
sel.mode = SEL_IDLE;
sel.ob.x = -1;
tsetdirt(sel.nb.y, sel.ne.y);
}
void die(const char *errstr, ...) {
va_list ap; va_list ap;
va_start(ap, errstr); va_start(ap, errstr);
@ -623,9 +517,9 @@ void die(const char *errstr, ...) {
exit(1); exit(1);
} }
void execsh(char *cmd, char **args) { void execsh(char* cmd, char** args) {
char *sh, *prog, *arg; char * sh, *prog, *arg;
const struct passwd *pw; const struct passwd* pw;
errno = 0; errno = 0;
if ((pw = getpwuid(getuid())) == NULL) { if ((pw = getpwuid(getuid())) == NULL) {
@ -651,7 +545,7 @@ void execsh(char *cmd, char **args) {
prog = sh; prog = sh;
arg = NULL; arg = NULL;
} }
DEFAULT(args, ((char *[]){prog, arg, NULL})); DEFAULT(args, ((char*[]){prog, arg, NULL}));
unsetenv("COLUMNS"); unsetenv("COLUMNS");
unsetenv("LINES"); unsetenv("LINES");
@ -690,7 +584,7 @@ void sigchld(int a) {
_exit(0); _exit(0);
} }
void stty(char **args) { void stty(char** args) {
char cmd[_POSIX_ARG_MAX], **p, *q, *s; char cmd[_POSIX_ARG_MAX], **p, *q, *s;
size_t n, siz; size_t n, siz;
@ -712,7 +606,7 @@ void stty(char **args) {
perror("Couldn't call stty"); 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; int m, s;
if (out) { if (out) {
@ -792,8 +686,8 @@ size_t ttyread(void) {
} }
} }
void ttywrite(const char *s, size_t n, int may_echo) { void ttywrite(const char* s, size_t n, int may_echo) {
const char *next; const char* next;
if (may_echo && IS_SET(MODE_ECHO)) if (may_echo && IS_SET(MODE_ECHO))
twrite(s, n, 1); 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; fd_set wfd, rfd;
ssize_t r; ssize_t r;
size_t lim = 256; size_t lim = 256;
@ -971,7 +865,7 @@ void tnew(int col, int row) {
} }
void tswapscreen(void) { void tswapscreen(void) {
Line *tmp = term.line; Line* tmp = term.line;
term.line = term.alt; term.line = term.alt;
term.alt = tmp; term.alt = tmp;
@ -1015,24 +909,6 @@ void tscrollup(int orig, int n) {
selscroll(orig, -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) { void tnewline(int first_col) {
int y = term.c.y; int y = term.c.y;
@ -1045,7 +921,7 @@ void tnewline(int first_col) {
} }
void csiparse(void) { void csiparse(void) {
char *p = csiescseq.buf, *np; char * p = csiescseq.buf, *np;
long int v; long int v;
csiescseq.narg = 0; csiescseq.narg = 0;
@ -1092,8 +968,8 @@ void tmoveto(int x, int y) {
term.c.y = LIMIT(y, miny, maxy); term.c.y = LIMIT(y, miny, maxy);
} }
void tsetchar(Rune u, Glyph *attr, int x, int y) { void tsetchar(Rune u, Glyph* attr, int x, int y) {
static char *vt100_0[62] = { static char* vt100_0[62] = {
/* 0x41 - 0x7e */ /* 0x41 - 0x7e */
"", "", "", "", "", "", "", /* A - G */ "", "", "", "", "", "", "", /* A - G */
0, 0, 0, 0, 0, 0, 0, 0, /* H - O */ 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) { void tclearregion(int x1, int y1, int x2, int y2) {
int x, y, temp; int x, y, temp;
Glyph *gp; Glyph* gp;
if (x1 > x2) if (x1 > x2)
temp = x1, x1 = x2, x2 = temp; temp = x1, x1 = x2, x2 = temp;
@ -1157,7 +1033,7 @@ void tclearregion(int x1, int y1, int x2, int y2) {
void tdeletechar(int n) { void tdeletechar(int n) {
int dst, src, size; int dst, src, size;
Glyph *line; Glyph* line;
LIMIT(n, 0, term.col - term.c.x); LIMIT(n, 0, term.col - term.c.x);
@ -1172,7 +1048,7 @@ void tdeletechar(int n) {
void tinsertblank(int n) { void tinsertblank(int n) {
int dst, src, size; int dst, src, size;
Glyph *line; Glyph* line;
LIMIT(n, 0, term.col - term.c.x); LIMIT(n, 0, term.col - term.c.x);
@ -1195,14 +1071,15 @@ void tdeleteline(int n) {
tscrollup(term.c.y, 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; int32_t idx = -1;
uint r, g, b; uint r, g, b;
switch (attr[*npar + 1]) { switch (attr[*npar + 1]) {
case 2: /* direct color in RGB space */ case 2: /* direct color in RGB space */
if (*npar + 4 >= l) { 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); *npar);
break; break;
} }
@ -1217,7 +1094,8 @@ int32_t tdefcolor(int *attr, int *npar, int l) {
break; break;
case 5: /* indexed color */ case 5: /* indexed color */
if (*npar + 2 >= l) { 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); *npar);
break; break;
} }
@ -1239,7 +1117,7 @@ int32_t tdefcolor(int *attr, int *npar, int l) {
return idx; return idx;
} }
void tsetattr(int *attr, int l) { void tsetattr(int* attr, int l) {
int i; int i;
int32_t idx; int32_t idx;
@ -1247,8 +1125,8 @@ void tsetattr(int *attr, int l) {
switch (attr[i]) { switch (attr[i]) {
case 0: case 0:
term.c.attr.mode &= term.c.attr.mode &=
~(ATTR_BOLD | ATTR_FAINT | ATTR_ITALIC | ATTR_UNDERLINE | ATTR_BLINK | ~(ATTR_BOLD | ATTR_FAINT | ATTR_ITALIC | ATTR_UNDERLINE |
ATTR_REVERSE | ATTR_INVISIBLE | ATTR_STRUCK); ATTR_BLINK | ATTR_REVERSE | ATTR_INVISIBLE | ATTR_STRUCK);
term.c.attr.fg = defaultfg; term.c.attr.fg = defaultfg;
term.c.attr.bg = defaultbg; term.c.attr.bg = defaultbg;
break; break;
@ -1323,7 +1201,8 @@ void tsetattr(int *attr, int l) {
} else if (BETWEEN(attr[i], 100, 107)) { } else if (BETWEEN(attr[i], 100, 107)) {
term.c.attr.bg = attr[i] - 100 + 8; term.c.attr.bg = attr[i] - 100 + 8;
} else { } else {
fprintf(stderr, "erresc(default): gfx attr %d unknown\n", attr[i]); fprintf(stderr, "erresc(default): gfx attr %d unknown\n",
attr[i]);
csidump(); csidump();
} }
break; break;
@ -1345,7 +1224,7 @@ void tsetscroll(int t, int b) {
term.bot = 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; int alt, *lim;
for (lim = args + narg; args < lim; ++args) { for (lim = args + narg; args < lim; ++args) {
@ -1441,7 +1320,8 @@ void tsetmode(int priv, int set, int *args, int narg) {
codes. */ codes. */
break; break;
default: default:
fprintf(stderr, "erresc: unknown private set/reset mode %d\n", *args); fprintf(stderr, "erresc: unknown private set/reset mode %d\n",
*args);
break; break;
} }
} else { } else {
@ -1619,7 +1499,8 @@ void csihandle(void) {
break; break;
case 'X': /* ECH -- Erase <n> char */ case 'X': /* ECH -- Erase <n> char */
DEFAULT(csiescseq.arg[0], 1); 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; break;
case 'P': /* DCH -- Delete <n> char */ case 'P': /* DCH -- Delete <n> char */
DEFAULT(csiescseq.arg[0], 1); DEFAULT(csiescseq.arg[0], 1);
@ -1641,8 +1522,8 @@ void csihandle(void) {
break; break;
case 'n': /* DSR Device Status Report (cursor position) */ case 'n': /* DSR Device Status Report (cursor position) */
if (csiescseq.arg[0] == 6) { if (csiescseq.arg[0] == 6) {
len = len = snprintf(buf, sizeof(buf), "\033[%i;%iR", term.c.y + 1,
snprintf(buf, sizeof(buf), "\033[%i;%iR", term.c.y + 1, term.c.x + 1); term.c.x + 1);
ttywrite(buf, len, 0); ttywrite(buf, len, 0);
} }
break; break;
@ -1772,7 +1653,7 @@ void strhandle(void) {
void strparse(void) { void strparse(void) {
int c; int c;
char *p = strescseq.buf; char* p = strescseq.buf;
strescseq.narg = 0; strescseq.narg = 0;
strescseq.buf[strescseq.len] = '\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)) if (tcsendbreak(cmdfd, 0))
perror("Error sending break"); 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) { if (iofd != -1 && xwrite(iofd, s, len) < 0) {
perror("Error writing to output file"); perror("Error writing to output file");
close(iofd); 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) { void tdumpsel(void) {
char *ptr; char* ptr;
if ((ptr = getsel())) { if ((ptr = getsel())) {
tprinter(ptr, strlen(ptr)); tprinter(ptr, strlen(ptr));
@ -1895,7 +1776,7 @@ void tdefutf8(char ascii) {
void tdeftran(char ascii) { void tdeftran(char ascii) {
static char cs[] = "0B"; static char cs[] = "0B";
static int vcs[] = {CS_GRAPHIC0, CS_USA}; static int vcs[] = {CS_GRAPHIC0, CS_USA};
char *p; char* p;
if ((p = strchr(cs, ascii)) == NULL) { if ((p = strchr(cs, ascii)) == NULL) {
fprintf(stderr, "esc unhandled charset: ESC ( %c\n", ascii); fprintf(stderr, "esc unhandled charset: ESC ( %c\n", ascii);
@ -2108,8 +1989,8 @@ int eschandle(uchar ascii) {
strhandle(); strhandle();
break; break;
default: default:
fprintf(stderr, "erresc: unknown sequence ESC 0x%02X '%c'\n", (uchar)ascii, fprintf(stderr, "erresc: unknown sequence ESC 0x%02X '%c'\n",
isprint(ascii) ? ascii : '.'); (uchar)ascii, isprint(ascii) ? ascii : '.');
break; break;
} }
return 1; return 1;
@ -2119,7 +2000,7 @@ void tputc(Rune u) {
char c[UTF_SIZE]; char c[UTF_SIZE];
int control; int control;
int width, len; int width, len;
Glyph *gp; Glyph* gp;
control = ISCONTROL(u); control = ISCONTROL(u);
if (u < 127 || !IS_SET(MODE_UTF8)) { 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; int charsize;
Rune u; Rune u;
int n; int n;
@ -2283,7 +2164,7 @@ void tresize(int col, int row) {
int i; int i;
int minrow = MIN(row, term.row); int minrow = MIN(row, term.row);
int mincol = MIN(col, term.col); int mincol = MIN(col, term.col);
int *bp; int* bp;
TCursor c; TCursor c;
if (col < 1 || row < 1) { if (col < 1 || row < 1) {

View File

@ -3,9 +3,12 @@
#ifndef ST_H #ifndef ST_H
#define ST_H #define ST_H
#include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <sys/types.h> #include <sys/types.h>
#include <stddef.h>
#include "types.h"
#include "utf8.h"
enum glyph_attribute { enum glyph_attribute {
ATTR_NULL = 0, ATTR_NULL = 0,
@ -23,29 +26,6 @@ enum glyph_attribute {
ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT, 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_ #define Glyph Glyph_
typedef struct { typedef struct {
Rune u; /* character code */ Rune u; /* character code */
@ -54,34 +34,34 @@ typedef struct {
uint32_t bg; /* background */ uint32_t bg; /* background */
} Glyph; } Glyph;
typedef Glyph *Line; typedef Glyph* Line;
typedef union { typedef union {
int i; int i;
uint ui; uint ui;
float f; float f;
const void *v; const void* v;
const char *s; const char* s;
} Arg; } Arg;
void die(const char *, ...); void die(const char*, ...);
void redraw(void); void redraw(void);
void draw(void); void draw(void);
void printscreen(const Arg *); void printscreen(const Arg*);
void printsel(const Arg *); void printsel(const Arg*);
void sendbreak(const Arg *); void sendbreak(const Arg*);
void toggleprinter(const Arg *); void toggleprinter(const Arg*);
int tattrset(int); int tattrset(int);
void tnew(int, int); void tnew(int, int);
void tresize(int, int); void tresize(int, int);
void tsetdirtattr(int); void tsetdirtattr(int);
void ttyhangup(void); void ttyhangup(void);
int ttynew(char *, char *, char *, char **); int ttynew(char*, char*, char*, char**);
size_t ttyread(void); size_t ttyread(void);
void ttyresize(int, int); void ttyresize(int, int);
void ttywrite(const char *, size_t, int); void ttywrite(const char*, size_t, int);
void resettitle(void); void resettitle(void);
@ -90,23 +70,23 @@ void selinit(void);
void selstart(int, int, int); void selstart(int, int, int);
void selextend(int, int, int, int); void selextend(int, int, int, int);
int selected(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_malloc(size_t);
void *safe_realloc(void *, size_t); void* safe_realloc(void*, size_t);
char *safe_strdup(char *); char* safe_strdup(char*);
/* config.h globals */ /* config.h globals */
extern char *utmp; extern char* utmp;
extern char *scroll; extern char* scroll;
extern char *stty_args; extern char* stty_args;
extern char *vtiden; extern char* vtiden;
extern wchar_t *worddelimiters; extern wchar_t* worddelimiters;
extern int allowaltscreen; extern int allowaltscreen;
extern int allowwindowops; extern int allowwindowops;
extern char *termname; extern char* termname;
extern unsigned int tabspaces; extern unsigned int tabspaces;
extern unsigned int defaultfg; extern unsigned int defaultfg;
extern unsigned int defaultbg; 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 xdrawline(Line, int, int, int);
void xfinishdraw(void); void xfinishdraw(void);
void xloadcols(void); void xloadcols(void);
int xsetcolorname(int, const char *); int xsetcolorname(int, const char*);
void xseticontitle(char *); void xseticontitle(char*);
void xsettitle(char *); void xsettitle(char*);
int xsetcursor(int); int xsetcursor(int);
void xsetmode(int, unsigned int); void xsetmode(int, unsigned int);
void xsetpointermotion(int); void xsetpointermotion(int);
void xsetsel(char *); void xsetsel(char*);
int xstartdraw(void); int xstartdraw(void);
void xximspot(int, int); void xximspot(int, int);

332
src/x.c
View File

@ -15,7 +15,7 @@
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
char *argv0; char* argv0;
#include "arg.h" #include "arg.h"
#include "st/macros.h" #include "st/macros.h"
#include "st/st.h" #include "st/st.h"
@ -25,14 +25,14 @@ char *argv0;
typedef struct { typedef struct {
uint mod; uint mod;
KeySym keysym; KeySym keysym;
void (*func)(const Arg *); void (*func)(const Arg*);
const Arg arg; const Arg arg;
} Shortcut; } Shortcut;
typedef struct { typedef struct {
uint mod; uint mod;
uint button; uint button;
void (*func)(const Arg *); void (*func)(const Arg*);
const Arg arg; const Arg arg;
uint release; uint release;
} MouseShortcut; } MouseShortcut;
@ -40,7 +40,7 @@ typedef struct {
typedef struct { typedef struct {
KeySym k; KeySym k;
uint mask; uint mask;
char *s; char* s;
/* three-valued logic variables: 0 indifferent, 1 on, -1 off */ /* three-valued logic variables: 0 indifferent, 1 on, -1 off */
signed char appkey; /* application keypad */ signed char appkey; /* application keypad */
signed char appcursor; /* application cursor */ signed char appcursor; /* application cursor */
@ -52,14 +52,14 @@ typedef struct {
#define XK_SWITCH_MOD (1 << 13) #define XK_SWITCH_MOD (1 << 13)
/* function definitions used in config.h */ /* function definitions used in config.h */
static void clipcopy(const Arg *); static void clipcopy(const Arg*);
static void clippaste(const Arg *); static void clippaste(const Arg*);
static void numlock(const Arg *); static void numlock(const Arg*);
static void selpaste(const Arg *); static void selpaste(const Arg*);
static void zoom(const Arg *); static void zoom(const Arg*);
static void zoomabs(const Arg *); static void zoomabs(const Arg*);
static void zoomreset(const Arg *); static void zoomreset(const Arg*);
static void ttysend(const Arg *); static void ttysend(const Arg*);
/* config.h for applying patches and the configuration. */ /* config.h for applying patches and the configuration. */
#include "config.h" #include "config.h"
@ -74,7 +74,7 @@ static void ttysend(const Arg *);
#define TRUEGREEN(x) (((x)&0xff00)) #define TRUEGREEN(x) (((x)&0xff00))
#define TRUEBLUE(x) (((x)&0xff) << 8) #define TRUEBLUE(x) (((x)&0xff) << 8)
typedef XftDraw *Draw; typedef XftDraw* Draw;
typedef XftColor Color; typedef XftColor Color;
typedef XftGlyphFontSpec GlyphFontSpec; typedef XftGlyphFontSpec GlyphFontSpec;
@ -89,11 +89,11 @@ typedef struct {
} TermWindow; } TermWindow;
typedef struct { typedef struct {
Display *dpy; Display* dpy;
Colormap cmap; Colormap cmap;
Window win; Window win;
Drawable buf; Drawable buf;
GlyphFontSpec *specbuf; /* font spec buffer used for rendering */ GlyphFontSpec* specbuf; /* font spec buffer used for rendering */
Atom xembed, wmdeletewin, netwmname, netwmiconname, netwmpid; Atom xembed, wmdeletewin, netwmname, netwmiconname, netwmpid;
struct { struct {
XIM xim; XIM xim;
@ -102,7 +102,7 @@ typedef struct {
XVaNestedList spotlist; XVaNestedList spotlist;
} ime; } ime;
Draw draw; Draw draw;
Visual *vis; Visual* vis;
XSetWindowAttributes attrs; XSetWindowAttributes attrs;
int scr; int scr;
int isfixed; /* is fixed geometry? */ int isfixed; /* is fixed geometry? */
@ -112,7 +112,7 @@ typedef struct {
typedef struct { typedef struct {
Atom xtarget; Atom xtarget;
char *primary, *clipboard; char * primary, *clipboard;
struct timespec tclick1; struct timespec tclick1;
struct timespec tclick2; struct timespec tclick2;
} XSelection; } XSelection;
@ -128,70 +128,69 @@ typedef struct {
int badweight; int badweight;
short lbearing; short lbearing;
short rbearing; short rbearing;
XftFont *match; XftFont* match;
FcFontSet *set; FcFontSet* set;
FcPattern *pattern; FcPattern* pattern;
} Font; } Font;
/* Drawing Context */ /* Drawing Context */
typedef struct { typedef struct {
Color *col; Color* col;
size_t collen; size_t collen;
Font font, bfont, ifont, ibfont; Font font, bfont, ifont, ibfont;
GC gc; GC gc;
} DC; } DC;
static inline ushort sixd_to_16bit(int); static inline ushort sixd_to_16bit(int);
static int xmakeglyphfontspecs(XftGlyphFontSpec *, const Glyph *, int, int, static int xmakeglyphfontspecs(XftGlyphFontSpec*, const Glyph*, int, int, int);
int); static void xdrawglyphfontspecs(const XftGlyphFontSpec*, Glyph, int, int, int);
static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, int);
static void xdrawglyph(Glyph, int, int); static void xdrawglyph(Glyph, int, int);
static void xclear(int, int, int, int); static void xclear(int, int, int, int);
static int xgeommasktogravity(int); static int xgeommasktogravity(int);
static int ximopen(Display *); static int ximopen(Display*);
static void ximinstantiate(Display *, XPointer, XPointer); static void ximinstantiate(Display*, XPointer, XPointer);
static void ximdestroy(XIM, XPointer, XPointer); static void ximdestroy(XIM, XPointer, XPointer);
static int xicdestroy(XIC, XPointer, XPointer); static int xicdestroy(XIC, XPointer, XPointer);
static void xinit(int, int); static void xinit(int, int);
static void cresize(int, int); static void cresize(int, int);
static void xresize(int, int); static void xresize(int, int);
static void xhints(void); static void xhints(void);
static int xloadcolor(int, const char *, Color *); static int xloadcolor(int, const char*, Color*);
static int xloadfont(Font *, FcPattern *); static int xloadfont(Font*, FcPattern*);
static void xloadfonts(char *, double); static void xloadfonts(char*, double);
static void xunloadfont(Font *); static void xunloadfont(Font*);
static void xunloadfonts(void); static void xunloadfonts(void);
static void xsetenv(void); static void xsetenv(void);
static void xseturgency(int); static void xseturgency(int);
static int evcol(XEvent *); static int evcol(XEvent*);
static int evrow(XEvent *); static int evrow(XEvent*);
static void expose(XEvent *); static void expose(XEvent*);
static void visibility(XEvent *); static void visibility(XEvent*);
static void unmap(XEvent *); static void unmap(XEvent*);
static void kpress(XEvent *); static void kpress(XEvent*);
static void cmessage(XEvent *); static void cmessage(XEvent*);
static void resize(XEvent *); static void resize(XEvent*);
static void focus(XEvent *); static void focus(XEvent*);
static uint buttonmask(uint); static uint buttonmask(uint);
static int mouseaction(XEvent *, uint); static int mouseaction(XEvent*, uint);
static void brelease(XEvent *); static void brelease(XEvent*);
static void bpress(XEvent *); static void bpress(XEvent*);
static void bmotion(XEvent *); static void bmotion(XEvent*);
static void propnotify(XEvent *); static void propnotify(XEvent*);
static void selnotify(XEvent *); static void selnotify(XEvent*);
static void selclear_(XEvent *); static void selclear_(XEvent*);
static void selrequest(XEvent *); static void selrequest(XEvent*);
static void setsel(char *, Time); static void setsel(char*, Time);
static void mousesel(XEvent *, int); static void mousesel(XEvent*, int);
static void mousereport(XEvent *); static void mousereport(XEvent*);
static char *kmap(KeySym, uint); static char* kmap(KeySym, uint);
static int match(uint, uint); static int match(uint, uint);
static void run(void); static void run(void);
static void usage(void); static void usage(void);
static void (*handler[LASTEvent])(XEvent *) = { static void (*handler[LASTEvent])(XEvent*) = {
[KeyPress] = kpress, [KeyPress] = kpress,
[ClientMessage] = cmessage, [ClientMessage] = cmessage,
[ConfigureNotify] = resize, [ConfigureNotify] = resize,
@ -227,31 +226,31 @@ static TermWindow win;
enum { FRC_NORMAL, FRC_ITALIC, FRC_BOLD, FRC_ITALICBOLD }; enum { FRC_NORMAL, FRC_ITALIC, FRC_BOLD, FRC_ITALICBOLD };
typedef struct { typedef struct {
XftFont *font; XftFont* font;
int flags; int flags;
Rune unicodep; Rune unicodep;
} Fontcache; } Fontcache;
/* Fontcache is an array now. A new font will be appended to the array. */ /* 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 frclen = 0;
static int frccap = 0; static int frccap = 0;
static char *usedfont = NULL; static char* usedfont = NULL;
static double usedfontsize = 0; static double usedfontsize = 0;
static double defaultfontsize = 0; static double defaultfontsize = 0;
static char *opt_class = NULL; static char* opt_class = NULL;
static char **opt_cmd = NULL; static char** opt_cmd = NULL;
static char *opt_embed = NULL; static char* opt_embed = NULL;
static char *opt_font = NULL; static char* opt_font = NULL;
static char *opt_io = NULL; static char* opt_io = NULL;
static char *opt_line = NULL; static char* opt_line = NULL;
static char *opt_name = NULL; static char* opt_name = NULL;
static char *opt_title = NULL; static char* opt_title = NULL;
static int oldbutton = 3; /* button event on startup: 3 = release */ static int oldbutton = 3; /* button event on startup: 3 = release */
void clipcopy(const Arg *dummy) { void clipcopy(const Arg* dummy) {
Atom clipboard; Atom clipboard;
free(xsel.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; Atom clipboard;
clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0);
@ -272,21 +271,21 @@ void clippaste(const Arg *dummy) {
CurrentTime); CurrentTime);
} }
void selpaste(const Arg *dummy) { void selpaste(const Arg* dummy) {
XConvertSelection(xw.dpy, XA_PRIMARY, xsel.xtarget, XA_PRIMARY, xw.win, XConvertSelection(xw.dpy, XA_PRIMARY, xsel.xtarget, XA_PRIMARY, xw.win,
CurrentTime); 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; Arg larg;
larg.f = usedfontsize + arg->f; larg.f = usedfontsize + arg->f;
zoomabs(&larg); zoomabs(&larg);
} }
void zoomabs(const Arg *arg) { void zoomabs(const Arg* arg) {
xunloadfonts(); xunloadfonts();
xloadfonts(usedfont, arg->f); xloadfonts(usedfont, arg->f);
cresize(0, 0); cresize(0, 0);
@ -294,7 +293,7 @@ void zoomabs(const Arg *arg) {
xhints(); xhints();
} }
void zoomreset(const Arg *arg) { void zoomreset(const Arg* arg) {
Arg larg; Arg larg;
if (defaultfontsize > 0) { 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; int x = e->xbutton.x - borderpx;
LIMIT(x, 0, win.tw - 1); LIMIT(x, 0, win.tw - 1);
return x / win.cw; return x / win.cw;
} }
int evrow(XEvent *e) { int evrow(XEvent* e) {
int y = e->xbutton.y - borderpx; int y = e->xbutton.y - borderpx;
LIMIT(y, 0, win.th - 1); LIMIT(y, 0, win.th - 1);
return y / win.ch; return y / win.ch;
} }
void mousesel(XEvent *e, int done) { void mousesel(XEvent* e, int done) {
int type, seltype = SEL_REGULAR; int type, seltype = SEL_REGULAR;
uint state = e->xbutton.state & ~(Button1Mask | forcemousemod); uint state = e->xbutton.state & ~(Button1Mask | forcemousemod);
@ -332,7 +331,7 @@ void mousesel(XEvent *e, int done) {
setsel(getsel(), e->xbutton.time); 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, int len, x = evcol(e), y = evrow(e), button = e->xbutton.button,
state = e->xbutton.state; state = e->xbutton.state;
char buf[40]; char buf[40];
@ -374,16 +373,17 @@ void mousereport(XEvent *e) {
} }
if (!IS_SET(MODE_MOUSEX10)) { 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); ((state & ControlMask) ? 16 : 0);
} }
if (IS_SET(MODE_MOUSESGR)) { if (IS_SET(MODE_MOUSESGR)) {
len = snprintf(buf, sizeof(buf), "\033[<%d;%d;%d%c", button, x + 1, y + 1, len = snprintf(buf, sizeof(buf), "\033[<%d;%d;%d%c", button, x + 1,
e->xbutton.type == ButtonRelease ? 'm' : 'M'); y + 1, e->xbutton.type == ButtonRelease ? 'm' : 'M');
} else if (x < 223 && y < 223) { } else if (x < 223 && y < 223) {
len = snprintf(buf, sizeof(buf), "\033[M%c%c%c", 32 + button, 32 + x + 1, len = snprintf(buf, sizeof(buf), "\033[M%c%c%c", 32 + button,
32 + y + 1); 32 + x + 1, 32 + y + 1);
} else { } else {
return; return;
} }
@ -400,8 +400,8 @@ uint buttonmask(uint button) {
: 0; : 0;
} }
int mouseaction(XEvent *e, uint release) { int mouseaction(XEvent* e, uint release) {
MouseShortcut *ms; MouseShortcut* ms;
/* ignore Button<N>mask for Button<N> - it's set on release */ /* ignore Button<N>mask for Button<N> - it's set on release */
uint state = e->xbutton.state & ~buttonmask(e->xbutton.button); uint state = e->xbutton.state & ~buttonmask(e->xbutton.button);
@ -418,7 +418,7 @@ int mouseaction(XEvent *e, uint release) {
return 0; return 0;
} }
void bpress(XEvent *e) { void bpress(XEvent* e) {
struct timespec now; struct timespec now;
int snap; int snap;
@ -450,8 +450,8 @@ void bpress(XEvent *e) {
} }
} }
void propnotify(XEvent *e) { void propnotify(XEvent* e) {
XPropertyEvent *xpev; XPropertyEvent* xpev;
Atom clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); Atom clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0);
xpev = &e->xproperty; xpev = &e->xproperty;
@ -461,7 +461,7 @@ void propnotify(XEvent *e) {
} }
} }
void selnotify(XEvent *e) { void selnotify(XEvent* e) {
ulong nitems, ofs, rem; ulong nitems, ofs, rem;
int format; int format;
uchar *data, *last, *repl; uchar *data, *last, *repl;
@ -479,9 +479,9 @@ void selnotify(XEvent *e) {
return; return;
do { do {
if (XGetWindowProperty(xw.dpy, xw.win, property, ofs, BUFSIZ / 4, False, if (XGetWindowProperty(xw.dpy, xw.win, property, ofs, BUFSIZ / 4,
AnyPropertyType, &type, &format, &nitems, &rem, False, AnyPropertyType, &type, &format, &nitems,
&data)) { &rem, &data)) {
fprintf(stderr, "Clipboard allocation failed\n"); fprintf(stderr, "Clipboard allocation failed\n");
return; return;
} }
@ -528,7 +528,7 @@ void selnotify(XEvent *e) {
if (IS_SET(MODE_BRCKTPASTE) && ofs == 0) if (IS_SET(MODE_BRCKTPASTE) && ofs == 0)
ttywrite("\033[200~", 6, 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) if (IS_SET(MODE_BRCKTPASTE) && rem == 0)
ttywrite("\033[201~", 6, 0); ttywrite("\033[201~", 6, 0);
XFree(data); XFree(data);
@ -545,15 +545,15 @@ void selnotify(XEvent *e) {
void xclipcopy(void) { clipcopy(NULL); } void xclipcopy(void) { clipcopy(NULL); }
void selclear_(XEvent *e) { selclear(); } void selclear_(XEvent* e) { selclear(); }
void selrequest(XEvent *e) { void selrequest(XEvent* e) {
XSelectionRequestEvent *xsre; XSelectionRequestEvent* xsre;
XSelectionEvent xev; XSelectionEvent xev;
Atom xa_targets, string, clipboard; Atom xa_targets, string, clipboard;
char *seltext; char* seltext;
xsre = (XSelectionRequestEvent *)e; xsre = (XSelectionRequestEvent*)e;
xev.type = SelectionNotify; xev.type = SelectionNotify;
xev.requestor = xsre->requestor; xev.requestor = xsre->requestor;
xev.selection = xsre->selection; xev.selection = xsre->selection;
@ -569,8 +569,8 @@ void selrequest(XEvent *e) {
if (xsre->target == xa_targets) { if (xsre->target == xa_targets) {
/* respond with the supported type */ /* respond with the supported type */
string = xsel.xtarget; string = xsel.xtarget;
XChangeProperty(xsre->display, xsre->requestor, xsre->property, XA_ATOM, 32, XChangeProperty(xsre->display, xsre->requestor, xsre->property,
PropModeReplace, (uchar *)&string, 1); XA_ATOM, 32, PropModeReplace, (uchar*)&string, 1);
xev.property = xsre->property; xev.property = xsre->property;
} else if (xsre->target == xsel.xtarget || xsre->target == XA_STRING) { } else if (xsre->target == xsel.xtarget || xsre->target == XA_STRING) {
/* /*
@ -583,23 +583,24 @@ void selrequest(XEvent *e) {
} else if (xsre->selection == clipboard) { } else if (xsre->selection == clipboard) {
seltext = xsel.clipboard; seltext = xsel.clipboard;
} else { } else {
fprintf(stderr, "Unhandled clipboard selection 0x%lx\n", xsre->selection); fprintf(stderr, "Unhandled clipboard selection 0x%lx\n",
xsre->selection);
return; return;
} }
if (seltext != NULL) { if (seltext != NULL) {
XChangeProperty(xsre->display, xsre->requestor, xsre->property, XChangeProperty(xsre->display, xsre->requestor, xsre->property,
xsre->target, 8, PropModeReplace, (uchar *)seltext, xsre->target, 8, PropModeReplace, (uchar*)seltext,
strlen(seltext)); strlen(seltext));
xev.property = xsre->property; xev.property = xsre->property;
} }
} }
/* all done, send a notification to the listener */ /* 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"); fprintf(stderr, "Error sending SelectionNotify event\n");
} }
void setsel(char *str, Time t) { void setsel(char* str, Time t) {
if (!str) if (!str)
return; return;
@ -611,9 +612,9 @@ void setsel(char *str, Time t) {
selclear(); 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)) { if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) {
mousereport(e); mousereport(e);
return; return;
@ -625,7 +626,7 @@ void brelease(XEvent *e) {
mousesel(e, 1); mousesel(e, 1);
} }
void bmotion(XEvent *e) { void bmotion(XEvent* e) {
if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) {
mousereport(e); mousereport(e);
return; return;
@ -657,8 +658,8 @@ void xresize(int col, int row) {
win.th = row * win.ch; win.th = row * win.ch;
XFreePixmap(xw.dpy, xw.buf); XFreePixmap(xw.dpy, xw.buf);
xw.buf = xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h,
XCreatePixmap(xw.dpy, xw.win, win.w, win.h, DefaultDepth(xw.dpy, xw.scr)); DefaultDepth(xw.dpy, xw.scr));
XftDrawChange(xw.draw, xw.buf); XftDrawChange(xw.draw, xw.buf);
xclear(0, 0, win.w, win.h); 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; } 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}; XRenderColor color = {.alpha = 0xffff};
if (!name) { if (!name) {
@ -692,7 +693,7 @@ int xloadcolor(int i, const char *name, Color *ncolor) {
void xloadcols(void) { void xloadcols(void) {
int i; int i;
static int loaded; static int loaded;
Color *cp; Color* cp;
if (loaded) { if (loaded) {
for (cp = dc.col; cp < &dc.col[dc.collen]; ++cp) for (cp = dc.col; cp < &dc.col[dc.collen]; ++cp)
@ -712,7 +713,7 @@ void xloadcols(void) {
loaded = 1; loaded = 1;
} }
int xsetcolorname(int x, const char *name) { int xsetcolorname(int x, const char* name) {
Color ncolor; Color ncolor;
if (!BETWEEN(x, 0, dc.collen)) if (!BETWEEN(x, 0, dc.collen))
@ -739,7 +740,7 @@ void xhints(void) {
XClassHint class = {opt_name ? opt_name : termname, XClassHint class = {opt_name ? opt_name : termname,
opt_class ? opt_class : termname}; opt_class ? opt_class : termname};
XWMHints wm = {.flags = InputHint, .input = 1}; XWMHints wm = {.flags = InputHint, .input = 1};
XSizeHints *sizeh; XSizeHints* sizeh;
sizeh = XAllocSizeHints(); sizeh = XAllocSizeHints();
@ -781,9 +782,9 @@ int xgeommasktogravity(int mask) {
return SouthEastGravity; return SouthEastGravity;
} }
int xloadfont(Font *f, FcPattern *pattern) { int xloadfont(Font* f, FcPattern* pattern) {
FcPattern *configured; FcPattern* configured;
FcPattern *match; FcPattern* match;
FcResult result; FcResult result;
XGlyphInfo extents; XGlyphInfo extents;
int wantattr, haveattr; 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); strlen(ascii_printable), &extents);
f->set = NULL; f->set = NULL;
@ -853,14 +854,14 @@ int xloadfont(Font *f, FcPattern *pattern) {
return 0; return 0;
} }
void xloadfonts(char *fontstr, double fontsize) { void xloadfonts(char* fontstr, double fontsize) {
FcPattern *pattern; FcPattern* pattern;
double fontval; double fontval;
if (fontstr[0] == '-') if (fontstr[0] == '-')
pattern = XftXlfdParse(fontstr, False, False); pattern = XftXlfdParse(fontstr, False, False);
else else
pattern = FcNameParse((FcChar8 *)fontstr); pattern = FcNameParse((FcChar8*)fontstr);
if (!pattern) if (!pattern)
die("can't open font %s\n", fontstr); die("can't open font %s\n", fontstr);
@ -920,7 +921,7 @@ void xloadfonts(char *fontstr, double fontsize) {
FcPatternDestroy(pattern); FcPatternDestroy(pattern);
} }
void xunloadfont(Font *f) { void xunloadfont(Font* f) {
XftFontClose(xw.dpy, f->match); XftFontClose(xw.dpy, f->match);
FcPatternDestroy(f->pattern); FcPatternDestroy(f->pattern);
if (f->set) if (f->set)
@ -938,7 +939,7 @@ void xunloadfonts(void) {
xunloadfont(&dc.ibfont); xunloadfont(&dc.ibfont);
} }
int ximopen(Display *dpy) { int ximopen(Display* dpy) {
XIMCallback imdestroy = {.client_data = NULL, .callback = ximdestroy}; XIMCallback imdestroy = {.client_data = NULL, .callback = ximdestroy};
XICCallback icdestroy = {.client_data = NULL, .callback = xicdestroy}; XICCallback icdestroy = {.client_data = NULL, .callback = xicdestroy};
@ -950,12 +951,13 @@ int ximopen(Display *dpy) {
fprintf(stderr, "XSetIMValues: " fprintf(stderr, "XSetIMValues: "
"Could not set XNDestroyCallback.\n"); "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) { if (xw.ime.xic == NULL) {
xw.ime.xic = XCreateIC(xw.ime.xim, XNInputStyle, xw.ime.xic = XCreateIC(
XIMPreeditNothing | XIMStatusNothing, XNClientWindow, xw.ime.xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
xw.win, XNDestroyCallback, &icdestroy, NULL); XNClientWindow, xw.win, XNDestroyCallback, &icdestroy, NULL);
} }
if (xw.ime.xic == NULL) if (xw.ime.xic == NULL)
fprintf(stderr, "XCreateIC: Could not create input context.\n"); fprintf(stderr, "XCreateIC: Could not create input context.\n");
@ -963,10 +965,10 @@ int ximopen(Display *dpy) {
return 1; return 1;
} }
void ximinstantiate(Display *dpy, XPointer client, XPointer call) { void ximinstantiate(Display* dpy, XPointer client, XPointer call) {
if (ximopen(dpy)) if (ximopen(dpy))
XUnregisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, ximinstantiate, XUnregisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL,
NULL); ximinstantiate, NULL);
} }
void ximdestroy(XIM xim, XPointer client, XPointer call) { void ximdestroy(XIM xim, XPointer client, XPointer call) {
@ -1033,8 +1035,8 @@ void xinit(int cols, int rows) {
memset(&gcvalues, 0, sizeof(gcvalues)); memset(&gcvalues, 0, sizeof(gcvalues));
gcvalues.graphics_exposures = False; gcvalues.graphics_exposures = False;
dc.gc = XCreateGC(xw.dpy, parent, GCGraphicsExposures, &gcvalues); dc.gc = XCreateGC(xw.dpy, parent, GCGraphicsExposures, &gcvalues);
xw.buf = xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h,
XCreatePixmap(xw.dpy, xw.win, win.w, win.h, DefaultDepth(xw.dpy, xw.scr)); DefaultDepth(xw.dpy, xw.scr));
XSetForeground(xw.dpy, dc.gc, dc.col[defaultbg].pixel); XSetForeground(xw.dpy, dc.gc, dc.col[defaultbg].pixel);
XFillRectangle(xw.dpy, xw.buf, dc.gc, 0, 0, win.w, win.h); 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 */ /* input methods */
if (!ximopen(xw.dpy)) { if (!ximopen(xw.dpy)) {
XRegisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, ximinstantiate, XRegisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL,
NULL); ximinstantiate, NULL);
} }
/* white cursor, black outline */ /* white cursor, black outline */
@ -1075,8 +1077,8 @@ void xinit(int cols, int rows) {
XSetWMProtocols(xw.dpy, xw.win, &xw.wmdeletewin, 1); XSetWMProtocols(xw.dpy, xw.win, &xw.wmdeletewin, 1);
xw.netwmpid = XInternAtom(xw.dpy, "_NET_WM_PID", False); xw.netwmpid = XInternAtom(xw.dpy, "_NET_WM_PID", False);
XChangeProperty(xw.dpy, xw.win, xw.netwmpid, XA_CARDINAL, 32, PropModeReplace, XChangeProperty(xw.dpy, xw.win, xw.netwmpid, XA_CARDINAL, 32,
(uchar *)&thispid, 1); PropModeReplace, (uchar*)&thispid, 1);
win.mode = MODE_NUMLOCK; win.mode = MODE_NUMLOCK;
resettitle(); resettitle();
@ -1093,19 +1095,19 @@ void xinit(int cols, int rows) {
xsel.xtarget = XA_STRING; 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) { int x, int y) {
float winx = borderpx + x * win.cw, winy = borderpx + y * win.ch, xp, yp; float winx = borderpx + x * win.cw, winy = borderpx + y * win.ch, xp, yp;
ushort mode, prevmode = USHRT_MAX; ushort mode, prevmode = USHRT_MAX;
Font *font = &dc.font; Font* font = &dc.font;
int frcflags = FRC_NORMAL; int frcflags = FRC_NORMAL;
float runewidth = win.cw; float runewidth = win.cw;
Rune rune; Rune rune;
FT_UInt glyphidx; FT_UInt glyphidx;
FcResult fcres; FcResult fcres;
FcPattern *fcpattern, *fontpattern; FcPattern *fcpattern, *fontpattern;
FcFontSet *fcsets[] = {NULL}; FcFontSet* fcsets[] = {NULL};
FcCharSet *fccharset; FcCharSet* fccharset;
int i, f, numspecs = 0; int i, f, numspecs = 0;
for (i = 0, xp = winx, yp = winy + font->ascent; i < len; ++i) { 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) if (glyphidx && frc[f].flags == frcflags)
break; break;
/* We got a default font for a not found glyph. */ /* 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; break;
} }
} }
@ -1218,12 +1221,12 @@ int xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len,
return numspecs; 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 x, int y) {
int charlen = len * ((base.mode & ATTR_WIDE) ? 2 : 1); int charlen = len * ((base.mode & ATTR_WIDE) ? 2 : 1);
int winx = borderpx + x * win.cw, winy = borderpx + y * win.ch, int winx = borderpx + x * win.cw, winy = borderpx + y * win.ch,
width = charlen * win.cw; width = charlen * win.cw;
Color *fg, *bg, *temp, revfg, revbg, truefg, truebg; Color * fg, *bg, *temp, revfg, revbg, truefg, truebg;
XRenderColor colfg, colbg; XRenderColor colfg, colbg;
XRectangle r; XRectangle r;
@ -1310,10 +1313,12 @@ void xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len,
/* Intelligent cleaning up of the borders. */ /* Intelligent cleaning up of the borders. */
if (x == 0) { if (x == 0) {
xclear(0, (y == 0) ? 0 : winy, borderpx, 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) { 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))); ((winy + win.ch >= borderpx + win.th) ? win.h : (winy + win.ch)));
} }
if (y == 0) if (y == 0)
@ -1340,7 +1345,8 @@ void xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len,
} }
if (base.mode & ATTR_STRUCK) { 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. */ /* 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. * 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)) { if (IS_SET(MODE_REVERSE)) {
g.mode |= ATTR_REVERSE; g.mode |= ATTR_REVERSE;
@ -1434,7 +1441,7 @@ void xsetenv(void) {
setenv("WINDOWID", buf, 1); setenv("WINDOWID", buf, 1);
} }
void xseticontitle(char *p) { void xseticontitle(char* p) {
XTextProperty prop; XTextProperty prop;
DEFAULT(p, opt_title); DEFAULT(p, opt_title);
@ -1444,7 +1451,7 @@ void xseticontitle(char *p) {
XFree(prop.value); XFree(prop.value);
} }
void xsettitle(char *p) { void xsettitle(char* p) {
XTextProperty prop; XTextProperty prop;
DEFAULT(p, opt_title); 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) { void xdrawline(Line line, int x1, int y1, int x2) {
int i, x, ox, numspecs; int i, x, ox, numspecs;
Glyph base, new; Glyph base, new;
XftGlyphFontSpec *specs = xw.specbuf; XftGlyphFontSpec* specs = xw.specbuf;
numspecs = xmakeglyphfontspecs(specs, &line[x1], x2 - x1, x1, y1); numspecs = xmakeglyphfontspecs(specs, &line[x1], x2 - x1, x1, y1);
i = ox = 0; i = ox = 0;
@ -1501,15 +1508,15 @@ void xximspot(int x, int y) {
XSetICValues(xw.ime.xic, XNPreeditAttributes, xw.ime.spotlist, NULL); XSetICValues(xw.ime.xic, XNPreeditAttributes, xw.ime.spotlist, NULL);
} }
void expose(XEvent *ev) { redraw(); } void expose(XEvent* ev) { redraw(); }
void visibility(XEvent *ev) { void visibility(XEvent* ev) {
XVisibilityEvent *e = &ev->xvisibility; XVisibilityEvent* e = &ev->xvisibility;
MODBIT(win.mode, e->state != VisibilityFullyObscured, MODE_VISIBLE); MODBIT(win.mode, e->state != VisibilityFullyObscured, MODE_VISIBLE);
} }
void unmap(XEvent *ev) { win.mode &= ~MODE_VISIBLE; } void unmap(XEvent* ev) { win.mode &= ~MODE_VISIBLE; }
void xsetpointermotion(int set) { void xsetpointermotion(int set) {
MODBIT(xw.attrs.event_mask, set, PointerMotionMask); MODBIT(xw.attrs.event_mask, set, PointerMotionMask);
@ -1531,7 +1538,7 @@ int xsetcursor(int cursor) {
} }
void xseturgency(int add) { void xseturgency(int add) {
XWMHints *h = XGetWMHints(xw.dpy, xw.win); XWMHints* h = XGetWMHints(xw.dpy, xw.win);
MODBIT(h->flags, add, XUrgencyHint); MODBIT(h->flags, add, XUrgencyHint);
XSetWMHints(xw.dpy, xw.win, h); XSetWMHints(xw.dpy, xw.win, h);
@ -1545,8 +1552,8 @@ void xbell(void) {
XkbBell(xw.dpy, xw.win, bellvolume, (Atom)NULL); XkbBell(xw.dpy, xw.win, bellvolume, (Atom)NULL);
} }
void focus(XEvent *ev) { void focus(XEvent* ev) {
XFocusChangeEvent *e = &ev->xfocus; XFocusChangeEvent* e = &ev->xfocus;
if (e->mode == NotifyGrab) if (e->mode == NotifyGrab)
return; return;
@ -1571,8 +1578,8 @@ int match(uint mask, uint state) {
return mask == XK_ANY_MOD || mask == (state & ~ignoremod); return mask == XK_ANY_MOD || mask == (state & ~ignoremod);
} }
char *kmap(KeySym k, uint state) { char* kmap(KeySym k, uint state) {
Key *kp; Key* kp;
int i; int i;
/* Check for mapped keys out of X11 function keys. */ /* Check for mapped keys out of X11 function keys. */
@ -1606,14 +1613,14 @@ char *kmap(KeySym k, uint state) {
return NULL; return NULL;
} }
void kpress(XEvent *ev) { void kpress(XEvent* ev) {
XKeyEvent *e = &ev->xkey; XKeyEvent* e = &ev->xkey;
KeySym ksym; KeySym ksym;
char buf[64], *customkey; char buf[64], *customkey;
int len; int len;
Rune c; Rune c;
Status status; Status status;
Shortcut *bp; Shortcut* bp;
if (IS_SET(MODE_KBDLOCK)) if (IS_SET(MODE_KBDLOCK))
return; return;
@ -1654,7 +1661,7 @@ void kpress(XEvent *ev) {
ttywrite(buf, len, 1); ttywrite(buf, len, 1);
} }
void cmessage(XEvent *e) { void cmessage(XEvent* e) {
/* /*
* See xembed specs * See xembed specs
* http://standards.freedesktop.org/xembed-spec/xembed-spec-latest.html * 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) if (e->xconfigure.width == win.w && e->xconfigure.height == win.h)
return; return;
@ -1754,7 +1761,8 @@ void run(void) {
trigger = now; trigger = now;
drawing = 1; drawing = 1;
} }
timeout = (maxlatency - TIMEDIFF(now, trigger)) / maxlatency * minlatency; timeout = (maxlatency - TIMEDIFF(now, trigger)) / maxlatency *
minlatency;
if (timeout > 0) if (timeout > 0)
continue; /* we have time, try to find idle */ continue; /* we have time, try to find idle */
} }
@ -1791,7 +1799,7 @@ void usage(void) {
argv0, argv0); argv0, argv0);
} }
int main(int argc, char *argv[]) { int main(int argc, char* argv[]) {
xw.l = xw.t = 0; xw.l = xw.t = 0;
xw.isfixed = False; xw.isfixed = False;
xsetcursor(cursorshape); xsetcursor(cursorshape);