Compare commits
1 Commits
split-sele
...
master
Author | SHA1 | Date |
---|---|---|
Jef Roosens | d42d786aa4 |
149
.clang-format
149
.clang-format
|
@ -1,149 +0,0 @@
|
||||||
---
|
|
||||||
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
|
|
||||||
...
|
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
<!---
|
||||||
|
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
|
|
@ -0,0 +1,38 @@
|
||||||
|
<!--
|
||||||
|
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
|
|
@ -0,0 +1,36 @@
|
||||||
|
<!--
|
||||||
|
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
|
|
@ -0,0 +1,35 @@
|
||||||
|
<!--
|
||||||
|
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
|
|
@ -0,0 +1,30 @@
|
||||||
|
<!--
|
||||||
|
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
|
|
@ -1,3 +0,0 @@
|
||||||
#!/usr/bin/env sh
|
|
||||||
|
|
||||||
make clean
|
|
|
@ -1,3 +0,0 @@
|
||||||
#!/usr/bin/env sh
|
|
||||||
|
|
||||||
make format
|
|
36
CHANGELOG.md
36
CHANGELOG.md
|
@ -1,36 +0,0 @@
|
||||||
# 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
109
Makefile
|
@ -1,42 +1,67 @@
|
||||||
# =====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
|
||||||
|
|
||||||
|
|
||||||
# =====INSTALL & UNINSTALL=====
|
# Installation & removal
|
||||||
install: release
|
install: release
|
||||||
@ mkdir -p '$(DESTDIR)$(PREFIX)/bin'
|
mkdir -p $(DESTDIR)$(PREFIX)/bin
|
||||||
@ cp -f '$(RELEASE_DIR)/$(BINARY)' '$(DESTDIR)$(PREFIX)/bin'
|
cp -f build/release/stj $(DESTDIR)$(PREFIX)/bin
|
||||||
@ chmod 755 '$(DESTDIR)$(PREFIX)/bin/$(BINARY)'
|
chmod 755 $(DESTDIR)$(PREFIX)/bin/stj
|
||||||
@ mkdir -p '$(DESTDIR)$(MANPREFIX)/man1'
|
mkdir -p $(DESTDIR)$(MANPREFIX)/man1
|
||||||
@ sed "s/VERSION/$(VERSION)/g" < 'data/stj.1' > '$(DESTDIR)$(MANPREFIX)/man1/$(BINARY).1'
|
sed "s/VERSION/$(VERSION)/g" < data/stj.1 > $(DESTDIR)$(MANPREFIX)/man1/stj.1
|
||||||
@ chmod 644 '$(DESTDIR)$(MANPREFIX)/man1/$(BINARY).1'
|
chmod 644 $(DESTDIR)$(MANPREFIX)/man1/stj.1
|
||||||
@ tic -sx 'data/stj.info'
|
tic -sx data/stj.info
|
||||||
@ cp -f 'data/$(BINARY).desktop' '$(DESTDIR)$(PREFIX)/share/applications'
|
cp -f data/stj.desktop $(DESTDIR)$(PREFIX)/share/applications
|
||||||
.PHONY: install
|
|
||||||
|
|
||||||
uninstall:
|
uninstall:
|
||||||
@ rm -f '$(DESTDIR)$(PREFIX)/bin/$(BINARY)'
|
rm -f $(DESTDIR)$(PREFIX)/bin/stj
|
||||||
@ rm -f '$(DESTDIR)$(MANPREFIX)/man1/$(BINARY).1'
|
rm -f $(DESTDIR)$(MANPREFIX)/man1/stj.1
|
||||||
@ rm -f '$(DESTDIR)$(PREFIX)/share/applications/$(BINARY).desktop'
|
rm -f $(DESTDIR)$(PREFIX)/share/applications/stj.desktop
|
||||||
.PHONY: uninstall
|
|
||||||
|
|
||||||
|
|
||||||
# =====DEBUG=====
|
# 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_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)'
|
||||||
|
@ -49,48 +74,6 @@ $(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
|
|
||||||
|
|
|
@ -5,31 +5,27 @@ 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")
|
||||||
|
|
||||||
# =====BUILD TYPES=====
|
# Release flags
|
||||||
# Debug
|
# -O3 gets added automatically by CMake
|
||||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wall -O0 -fsanitize=address -fno-omit-frame-pointer")
|
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Werror -march=native -pedantic-errors")
|
||||||
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=====
|
||||||
|
@ -44,20 +40,16 @@ 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 2 REQUIRED)
|
find_package(Fontconfig 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)
|
||||||
# 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 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)
|
||||||
|
|
|
@ -5,8 +5,7 @@
|
||||||
*
|
*
|
||||||
* font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html
|
* font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html
|
||||||
*/
|
*/
|
||||||
static char* font =
|
static char *font = "Liberation Mono:pixelsize=12:antialias=true:autohint=true";
|
||||||
"Liberation Mono:pixelsize=12:antialias=true:autohint=true";
|
|
||||||
static int borderpx = 2;
|
static int borderpx = 2;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -5,8 +5,7 @@
|
||||||
*
|
*
|
||||||
* font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html
|
* font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html
|
||||||
*/
|
*/
|
||||||
static char* font =
|
static char *font = "Liberation Mono:pixelsize=12:antialias=true:autohint=true";
|
||||||
"Liberation Mono:pixelsize=12:antialias=true:autohint=true";
|
|
||||||
static int borderpx = 2;
|
static int borderpx = 2;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -1,68 +0,0 @@
|
||||||
#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;
|
|
||||||
}
|
|
|
@ -1,36 +0,0 @@
|
||||||
#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
|
|
251
src/st/st.c
251
src/st/st.c
|
@ -19,9 +19,7 @@
|
||||||
|
|
||||||
#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>
|
||||||
|
@ -32,6 +30,8 @@
|
||||||
#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,6 +89,24 @@ 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 */
|
||||||
|
@ -183,6 +201,15 @@ static void tstrsequence(uchar);
|
||||||
|
|
||||||
static void drawregion(int, int, int, int);
|
static void drawregion(int, int, int, int);
|
||||||
|
|
||||||
|
static void selnormalize(void);
|
||||||
|
static void selscroll(int, int);
|
||||||
|
static void selsnap(int *, int *, int);
|
||||||
|
|
||||||
|
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(const char *);
|
||||||
static char base64dec_getc(const char **);
|
static char base64dec_getc(const char **);
|
||||||
|
|
||||||
|
@ -190,80 +217,121 @@ 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};
|
||||||
* Same as write, but ensures that all bytes are written to the descriptor
|
static uchar utfmask[UTF_SIZE + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8};
|
||||||
* (write sometimes isn't able to write all bytes)
|
static Rune utfmin[UTF_SIZE + 1] = {0, 0, 0x80, 0x800, 0x10000};
|
||||||
*
|
static Rune utfmax[UTF_SIZE + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF};
|
||||||
* @param p_file_desc file descriptor to write to; same logic as write
|
|
||||||
* @param p_str char array to write to the file descriptor
|
ssize_t xwrite(int fd, const char *s, size_t len) {
|
||||||
* @param p_nbytes amount of bytes to write
|
size_t aux = len;
|
||||||
* @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 (p_nbytes > 0) {
|
while (len > 0) {
|
||||||
result = write(p_file_desc, p_str, p_nbytes);
|
result = write(fd, s, len);
|
||||||
|
|
||||||
// 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;
|
||||||
|
|
||||||
p_nbytes -= (size_t)result;
|
len -= result;
|
||||||
p_str += result;
|
s += result;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (ssize_t)aux;
|
return aux;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// Same as malloc, but stops entire program if malloc fails
|
||||||
* same as malloc, but kill the program if it fails
|
void *safe_malloc(size_t len) {
|
||||||
*
|
|
||||||
* @param p_len bytes to allocate
|
|
||||||
* @return pointer to allocated memory
|
|
||||||
*/
|
|
||||||
void* safe_malloc(size_t p_len) {
|
|
||||||
void *ptr;
|
void *ptr;
|
||||||
|
|
||||||
if (!(ptr = malloc(p_len)))
|
if (!(ptr = malloc(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
|
||||||
* same as realloc, but kill the program if it fails
|
void *safe_realloc(void *ptr, size_t len) {
|
||||||
*
|
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 p_ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
char *safe_strdup(char *s) {
|
||||||
* same as strdup, but kill the program if it fails
|
if ((s = strdup(s)) == NULL)
|
||||||
*
|
|
||||||
* @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 p_str;
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char base64_digits[] = {
|
static const char base64_digits[] = {
|
||||||
|
@ -317,6 +385,12 @@ 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;
|
||||||
|
|
||||||
|
@ -372,17 +446,41 @@ 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) &&
|
return BETWEEN(y, sel.nb.y, sel.ne.y) && BETWEEN(x, sel.nb.x, sel.ne.x);
|
||||||
BETWEEN(x, sel.nb.x, sel.ne.x);
|
|
||||||
|
|
||||||
return BETWEEN(y, sel.nb.y, sel.ne.y) &&
|
return BETWEEN(y, sel.nb.y, sel.ne.y) && (y != sel.nb.y || x >= sel.nb.x) &&
|
||||||
(y != sel.nb.y || x >= sel.nb.x) &&
|
|
||||||
(y != sel.ne.y || x <= sel.ne.x);
|
(y != sel.ne.y || x <= sel.ne.x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -508,6 +606,14 @@ char* getsel(void) {
|
||||||
return str;
|
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_list ap;
|
||||||
|
|
||||||
|
@ -909,6 +1015,24 @@ 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;
|
||||||
|
|
||||||
|
@ -1078,8 +1202,7 @@ int32_t tdefcolor(int* attr, int* npar, int l) {
|
||||||
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,
|
fprintf(stderr, "erresc(38): Incorrect number of parameters (%d)\n",
|
||||||
"erresc(38): Incorrect number of parameters (%d)\n",
|
|
||||||
*npar);
|
*npar);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1094,8 +1217,7 @@ 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,
|
fprintf(stderr, "erresc(38): Incorrect number of parameters (%d)\n",
|
||||||
"erresc(38): Incorrect number of parameters (%d)\n",
|
|
||||||
*npar);
|
*npar);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1125,8 +1247,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_BOLD | ATTR_FAINT | ATTR_ITALIC | ATTR_UNDERLINE | ATTR_BLINK |
|
||||||
ATTR_BLINK | ATTR_REVERSE | ATTR_INVISIBLE | ATTR_STRUCK);
|
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;
|
||||||
|
@ -1201,8 +1323,7 @@ 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",
|
fprintf(stderr, "erresc(default): gfx attr %d unknown\n", attr[i]);
|
||||||
attr[i]);
|
|
||||||
csidump();
|
csidump();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1320,8 +1441,7 @@ 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",
|
fprintf(stderr, "erresc: unknown private set/reset mode %d\n", *args);
|
||||||
*args);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1499,8 +1619,7 @@ 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,
|
tclearregion(term.c.x, term.c.y, term.c.x + csiescseq.arg[0] - 1, term.c.y);
|
||||||
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);
|
||||||
|
@ -1522,8 +1641,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 = snprintf(buf, sizeof(buf), "\033[%i;%iR", term.c.y + 1,
|
len =
|
||||||
term.c.x + 1);
|
snprintf(buf, sizeof(buf), "\033[%i;%iR", term.c.y + 1, term.c.x + 1);
|
||||||
ttywrite(buf, len, 0);
|
ttywrite(buf, len, 0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1989,8 +2108,8 @@ int eschandle(uchar ascii) {
|
||||||
strhandle();
|
strhandle();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "erresc: unknown sequence ESC 0x%02X '%c'\n",
|
fprintf(stderr, "erresc: unknown sequence ESC 0x%02X '%c'\n", (uchar)ascii,
|
||||||
(uchar)ascii, isprint(ascii) ? ascii : '.');
|
isprint(ascii) ? ascii : '.');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
|
|
28
src/st/st.h
28
src/st/st.h
|
@ -3,12 +3,9 @@
|
||||||
#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,
|
||||||
|
@ -26,6 +23,29 @@ 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 */
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
#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
105
src/st/utf8.c
|
@ -1,105 +0,0 @@
|
||||||
#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;
|
|
||||||
}
|
|
|
@ -1,17 +0,0 @@
|
||||||
#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
|
|
74
src/x.c
74
src/x.c
|
@ -142,7 +142,8 @@ typedef struct {
|
||||||
} DC;
|
} DC;
|
||||||
|
|
||||||
static inline ushort sixd_to_16bit(int);
|
static inline ushort sixd_to_16bit(int);
|
||||||
static int xmakeglyphfontspecs(XftGlyphFontSpec*, const Glyph*, int, int, int);
|
static int xmakeglyphfontspecs(XftGlyphFontSpec *, const Glyph *, 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);
|
||||||
|
@ -373,17 +374,16 @@ void mousereport(XEvent* e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IS_SET(MODE_MOUSEX10)) {
|
if (!IS_SET(MODE_MOUSEX10)) {
|
||||||
button += ((state & ShiftMask) ? 4 : 0) +
|
button += ((state & ShiftMask) ? 4 : 0) + ((state & Mod4Mask) ? 8 : 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,
|
len = snprintf(buf, sizeof(buf), "\033[<%d;%d;%d%c", button, x + 1, y + 1,
|
||||||
y + 1, e->xbutton.type == ButtonRelease ? 'm' : 'M');
|
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,
|
len = snprintf(buf, sizeof(buf), "\033[M%c%c%c", 32 + button, 32 + x + 1,
|
||||||
32 + x + 1, 32 + y + 1);
|
32 + y + 1);
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -479,9 +479,9 @@ void selnotify(XEvent* e) {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (XGetWindowProperty(xw.dpy, xw.win, property, ofs, BUFSIZ / 4,
|
if (XGetWindowProperty(xw.dpy, xw.win, property, ofs, BUFSIZ / 4, False,
|
||||||
False, AnyPropertyType, &type, &format, &nitems,
|
AnyPropertyType, &type, &format, &nitems, &rem,
|
||||||
&rem, &data)) {
|
&data)) {
|
||||||
fprintf(stderr, "Clipboard allocation failed\n");
|
fprintf(stderr, "Clipboard allocation failed\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -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,
|
XChangeProperty(xsre->display, xsre->requestor, xsre->property, XA_ATOM, 32,
|
||||||
XA_ATOM, 32, PropModeReplace, (uchar*)&string, 1);
|
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,8 +583,7 @@ 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",
|
fprintf(stderr, "Unhandled clipboard selection 0x%lx\n", xsre->selection);
|
||||||
xsre->selection);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (seltext != NULL) {
|
if (seltext != NULL) {
|
||||||
|
@ -658,8 +657,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 = XCreatePixmap(xw.dpy, xw.win, win.w, win.h,
|
xw.buf =
|
||||||
DefaultDepth(xw.dpy, xw.scr));
|
XCreatePixmap(xw.dpy, xw.win, win.w, win.h, 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);
|
||||||
|
|
||||||
|
@ -951,13 +950,12 @@ int ximopen(Display* dpy) {
|
||||||
fprintf(stderr, "XSetIMValues: "
|
fprintf(stderr, "XSetIMValues: "
|
||||||
"Could not set XNDestroyCallback.\n");
|
"Could not set XNDestroyCallback.\n");
|
||||||
|
|
||||||
xw.ime.spotlist =
|
xw.ime.spotlist = XVaCreateNestedList(0, XNSpotLocation, &xw.ime.spot, NULL);
|
||||||
XVaCreateNestedList(0, XNSpotLocation, &xw.ime.spot, NULL);
|
|
||||||
|
|
||||||
if (xw.ime.xic == NULL) {
|
if (xw.ime.xic == NULL) {
|
||||||
xw.ime.xic = XCreateIC(
|
xw.ime.xic = XCreateIC(xw.ime.xim, XNInputStyle,
|
||||||
xw.ime.xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
|
XIMPreeditNothing | XIMStatusNothing, XNClientWindow,
|
||||||
XNClientWindow, xw.win, XNDestroyCallback, &icdestroy, NULL);
|
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");
|
||||||
|
@ -967,8 +965,8 @@ int ximopen(Display* dpy) {
|
||||||
|
|
||||||
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,
|
XUnregisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, ximinstantiate,
|
||||||
ximinstantiate, NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ximdestroy(XIM xim, XPointer client, XPointer call) {
|
void ximdestroy(XIM xim, XPointer client, XPointer call) {
|
||||||
|
@ -1035,8 +1033,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 = XCreatePixmap(xw.dpy, xw.win, win.w, win.h,
|
xw.buf =
|
||||||
DefaultDepth(xw.dpy, xw.scr));
|
XCreatePixmap(xw.dpy, xw.win, win.w, win.h, 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);
|
||||||
|
|
||||||
|
@ -1048,8 +1046,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,
|
XRegisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, ximinstantiate,
|
||||||
ximinstantiate, NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* white cursor, black outline */
|
/* white cursor, black outline */
|
||||||
|
@ -1077,8 +1075,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,
|
XChangeProperty(xw.dpy, xw.win, xw.netwmpid, XA_CARDINAL, 32, PropModeReplace,
|
||||||
PropModeReplace, (uchar*)&thispid, 1);
|
(uchar *)&thispid, 1);
|
||||||
|
|
||||||
win.mode = MODE_NUMLOCK;
|
win.mode = MODE_NUMLOCK;
|
||||||
resettitle();
|
resettitle();
|
||||||
|
@ -1157,8 +1155,7 @@ 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 &&
|
if (!glyphidx && frc[f].flags == frcflags && frc[f].unicodep == rune) {
|
||||||
frc[f].unicodep == rune) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1313,12 +1310,10 @@ 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 + ((winy + win.ch >= borderpx + win.th) ? win.h : 0));
|
||||||
((winy + win.ch >= borderpx + win.th) ? win.h : 0));
|
|
||||||
}
|
}
|
||||||
if (winx + width >= borderpx + win.tw) {
|
if (winx + width >= borderpx + win.tw) {
|
||||||
xclear(
|
xclear(winx + width, (y == 0) ? 0 : winy, win.w,
|
||||||
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)
|
||||||
|
@ -1345,8 +1340,7 @@ 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,
|
XftDrawRect(xw.draw, fg, winx, winy + 2 * dc.font.ascent / 3, width, 1);
|
||||||
1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reset clip to none. */
|
/* Reset clip to none. */
|
||||||
|
@ -1375,8 +1369,7 @@ 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 &=
|
g.mode &= ATTR_BOLD | ATTR_ITALIC | ATTR_UNDERLINE | ATTR_STRUCK | ATTR_WIDE;
|
||||||
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;
|
||||||
|
@ -1761,8 +1754,7 @@ void run(void) {
|
||||||
trigger = now;
|
trigger = now;
|
||||||
drawing = 1;
|
drawing = 1;
|
||||||
}
|
}
|
||||||
timeout = (maxlatency - TIMEDIFF(now, trigger)) / maxlatency *
|
timeout = (maxlatency - TIMEDIFF(now, trigger)) / maxlatency * minlatency;
|
||||||
minlatency;
|
|
||||||
if (timeout > 0)
|
if (timeout > 0)
|
||||||
continue; /* we have time, try to find idle */
|
continue; /* we have time, try to find idle */
|
||||||
}
|
}
|
||||||
|
|
Reference in New Issue