Skip to content

Commit c168d82

Browse files
authored
initial commit
0 parents  commit c168d82

File tree

7 files changed

+1240
-0
lines changed

7 files changed

+1240
-0
lines changed

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
Copyright (c) 2024 Steffen Illhardt
2+
3+
MIT License
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

NOTICE.md

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# NOTICES ABOUT THIRD PARTY CODE
2+
Do Not Translate or Localize
3+
4+
This software incorporates material from third parties.
5+
6+
## terminal
7+
8+
**Source**: [https://github.com/microsoft/terminal](https://github.com/microsoft/terminal)
9+
10+
### License
11+
12+
```
13+
Copyright (c) Microsoft Corporation. All rights reserved.
14+
15+
MIT License
16+
17+
Permission is hereby granted, free of charge, to any person obtaining a copy
18+
of this software and associated documentation files (the "Software"), to deal
19+
in the Software without restriction, including without limitation the rights
20+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
21+
copies of the Software, and to permit persons to whom the Software is
22+
furnished to do so, subject to the following conditions:
23+
24+
The above copyright notice and this permission notice shall be included in all
25+
copies or substantial portions of the Software.
26+
27+
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
30+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
31+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
32+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33+
SOFTWARE.
34+
```
35+
36+
## Flexible and Economical UTF-8 Decoder
37+
38+
**Source**: [https://bjoern.hoehrmann.de/utf-8/decoder/dfa/](https://bjoern.hoehrmann.de/utf-8/decoder/dfa/)
39+
40+
### License
41+
42+
```
43+
Copyright (c) 2008-2010 Bjoern Hoehrmann <bjoern@hoehrmann.de>
44+
45+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
46+
47+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
48+
49+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
50+
```
51+

README.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
## **`wtswidth` - Windows Terminal string width**
2+
3+
The purpose of this C library along with the released utility is to count the number of columns required to represent a string in the [Windows Terminal](https://github.com/microsoft/terminal).
4+
You may use it if you want to perform some kind of tabulation or centering of text where it is necessary to know upfront how much space a string is going to occupy in the window.
5+
<br>
6+
🔴 <span style="color:red">**NOTE**</span> 🔴 The code won't work properly for Windows Terminal releases before version 1.22.
7+
<br>
8+
*Why is this?*
9+
Recently, Windows Terminal made a huge step towards better Unicode support and Unicode correctness. This is something that I can't appreciate enough. A series of major "minor refactorings" (© @lhecker 😄) have been made to achieve that.
10+
The name `wtswidth` intentionally sounds similar to the POSIX function `wcswidth()`. However, measuring the display width of a string in Windows Terminal is now not only based on the sum of expected widths of codepoints like in `wcswidth()`. The string context is taken into account, too. This leads to a far better measuring of clustered graphemes.
11+
<br>
12+
13+
*But what does that mean?*
14+
Let's just perform some comparisons:
15+
16+
| **string** | **C syntax** | `wtswidth` **(this)** | `wcswidth()` **(wchar.h GCC)** |
17+
| :--- | :--- | :---: | :---: |
18+
| `abc` | L"abc" | 3 | 3 ✔ |
19+
| `हिन्दी` | L"\u0939\u093F\u0928\u094D\u0926\u0940" | 3 | 5 ❌ |
20+
| `😄` | L"\U0001F604" | 2 | 2 ✔ |
21+
| `🙋🏻‍♂️` | L"\U0001F64B\U0001F3FB\u200D\u2642\uFE0F" | 2 | 5 ❌ |
22+
| `❤️` | L"\u2764\uFE0F" | 2 | 1 ❌ |
23+
24+
However, this does not quite demonstrate how it looks like in the terminal.
25+
That's a screenshot of a test script in Windows Terminal Canary Version 1.22.2291.0:
26+
![test output](./screenshot_v1.22.2291.0.png)
27+
As you can see, the measured width matches the displayed width of the strings each.
28+
I doubt it's perfect. But due to the lack of any standardization we can't even evaluate how close to perfection it actually is. At least a proposal was already submitted to the UTC (see
29+
[Proper Complex Script Support in Text Terminals.](https://www.unicode.org/L2/L2023/23107-terminal-suppt.pdf)) of how this should be ideally implemented.
30+
<br>
31+
32+
### **Most of this is not my intellectual property.**
33+
34+
It is basically a copy of the recently revised code for this purpose in Microsoft's open source repository. All credits go to their Terminal team and contributors. I used this code in order to actually get the same results as the internally performed measurements. For more information refer to the comments in the source files.
35+
Furthermore I modified Björn Höhrmann's "Flexible and Economical UTF-8 Decoder" to process UTF-8 input.
36+
37+
See: [Third Party Licenses](./NOTICE.md)
38+
39+
<br>

main.c

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// Copyright (c) 2024 Steffen Illhardt,
2+
// Licensed under the MIT license ( https://opensource.org/license/mit/ ).
3+
4+
#include <stdio.h>
5+
#include <string.h>
6+
#include <wchar.h>
7+
#include "wtswidth.h"
8+
9+
static inline void help()
10+
{
11+
static const char msg[] =
12+
"* 'wtswidth' - Windows Terminal string width *\n"
13+
"Count the number of columns required to represent a string in the Windows Terminal.\n"
14+
"The return value is the width as the number of character cells the string occupies.\n"
15+
"In case the wrong syntax is used, this message is displayed and -1 is returned.\n\n"
16+
"Usage:\n"
17+
"wtswidth \"string to measure\"\n\n";
18+
19+
fwrite(msg, 1, sizeof(msg) - 1, stderr);
20+
}
21+
22+
#if defined(_WIN32) || defined(__CYGWIN__)
23+
// On Windows, the command line is always available as wide string anyway. So we just use that.
24+
# include <windows.h>
25+
int main(void)
26+
{
27+
int argc = 0;
28+
wchar_t **const argv = CommandLineToArgvW(GetCommandLineW(), &argc);
29+
if (argc != 2)
30+
{
31+
LocalFree(argv);
32+
help();
33+
return -1;
34+
}
35+
36+
const int totalWidth = wts16width((const char16_t *)argv[1], wcslen(argv[1]));
37+
LocalFree(argv);
38+
return totalWidth;
39+
}
40+
#else
41+
// On *nix we assume to get UTF-8 as this is virtually standard.
42+
int main(int argc, char *argv[])
43+
{
44+
if (argc != 2)
45+
{
46+
help();
47+
return -1;
48+
}
49+
50+
return wts8width(argv[1], strlen(argv[1]));
51+
}
52+
#endif

screenshot_v1.22.2291.0.png

250 KB
Loading

0 commit comments

Comments
 (0)