+16
.editorconfig
+16
.editorconfig
···
1
+
root = true
2
+
3
+
[*.{c,h}]
4
+
charset = utf-8
5
+
end_of_line = lf
6
+
indent_style = tab
7
+
insert_final_newline = true
8
+
trim_trailing_whitespace = true
9
+
10
+
[*.{lua}]
11
+
charset = utf-8
12
+
end_of_line = lf
13
+
indent_style = space
14
+
indent_size = 2
15
+
insert_final_newline = true
16
+
trim_trailing_whitespace = true
-19
LICENSE
-19
LICENSE
···
1
-
Copyright (c) 2020 rxi
2
-
3
-
Permission is hereby granted, free of charge, to any person obtaining a copy of
4
-
this software and associated documentation files (the "Software"), to deal in
5
-
the Software without restriction, including without limitation the rights to
6
-
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7
-
of the Software, and to permit persons to whom the Software is furnished to do
8
-
so, subject to the following conditions:
9
-
10
-
The above copyright notice and this permission notice shall be included in all
11
-
copies or substantial portions of the Software.
12
-
13
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
-
SOFTWARE.
-41
README.md
-41
README.md
···
1
-
# lite
2
-

3
-
4
-
A lightweight text editor written in Lua
5
-
6
-
* **[Get lite](https://github.com/rxi/lite/releases/latest)** โ Download
7
-
for Windows and Linux
8
-
* **[Get started](doc/usage.md)** โ A quick overview on how to get started
9
-
* **[Get plugins](https://github.com/rxi/lite-plugins)** โ Add additional
10
-
functionality
11
-
* **[Get color themes](https://github.com/rxi/lite-colors)** โ Add additional colors
12
-
themes
13
-
14
-
## Overview
15
-
lite is a lightweight text editor written mostly in Lua โ it aims to provide
16
-
something practical, pretty, *small* and fast, implemented as simply as
17
-
possible; easy to modify and extend, or to use without doing either.
18
-
19
-
## Customization
20
-
Additional functionality can be added through plugins which are available from
21
-
the [plugins repository](https://github.com/rxi/lite-plugins); additional color
22
-
themes can be found in the [colors repository](https://github.com/rxi/lite-colors).
23
-
The editor can be customized by making changes to the
24
-
[user module](data/user/init.lua).
25
-
26
-
## Building
27
-
You can build the project yourself on Linux using the `build.sh` script
28
-
or on Windows using the `build.bat` script *([MinGW](https://nuwen.net/mingw.html) is required)*.
29
-
Note that the project does not need to be rebuilt if you are only making changes
30
-
to the Lua portion of the code.
31
-
32
-
## Contributing
33
-
Any additional functionality that can be added through a plugin should be done
34
-
so as a plugin, after which a pull request to the
35
-
[plugins repository](https://github.com/rxi/lite-plugins) can be made. In hopes
36
-
of remaining lightweight, pull requests adding additional functionality to the
37
-
core will likely not be merged. Bug reports and bug fixes are welcome.
38
-
39
-
## License
40
-
This project is free software; you can redistribute it and/or modify it under
41
-
the terms of the MIT license. See [LICENSE](LICENSE) for details.
+1
-1
build.sh
+1
-1
build.sh
+4
-1
data/user/init.lua
+4
-1
data/user/init.lua
···
5
5
local config = require "core.config"
6
6
local style = require "core.style"
7
7
8
+
config.tab_type = "hard"
9
+
config.indent_size = 8
10
+
8
11
-- light theme:
9
-
-- require "user.colors.summer"
12
+
require "user.colors.fall"
10
13
11
14
-- key binding:
12
15
-- keymap.add { ["ctrl+escape"] = "core:quit" }
+41
doc/original-readme.md
+41
doc/original-readme.md
···
1
+
# lite
2
+

3
+
4
+
A lightweight text editor written in Lua
5
+
6
+
* **[Get lite](https://github.com/rxi/lite/releases/latest)** โ Download
7
+
for Windows and Linux
8
+
* **[Get started](doc/usage.md)** โ A quick overview on how to get started
9
+
* **[Get plugins](https://github.com/rxi/lite-plugins)** โ Add additional
10
+
functionality
11
+
* **[Get color themes](https://github.com/rxi/lite-colors)** โ Add additional colors
12
+
themes
13
+
14
+
## Overview
15
+
lite is a lightweight text editor written mostly in Lua โ it aims to provide
16
+
something practical, pretty, *small* and fast, implemented as simply as
17
+
possible; easy to modify and extend, or to use without doing either.
18
+
19
+
## Customization
20
+
Additional functionality can be added through plugins which are available from
21
+
the [plugins repository](https://github.com/rxi/lite-plugins); additional color
22
+
themes can be found in the [colors repository](https://github.com/rxi/lite-colors).
23
+
The editor can be customized by making changes to the
24
+
[user module](data/user/init.lua).
25
+
26
+
## Building
27
+
You can build the project yourself on Linux using the `build.sh` script
28
+
or on Windows using the `build.bat` script *([MinGW](https://nuwen.net/mingw.html) is required)*.
29
+
Note that the project does not need to be rebuilt if you are only making changes
30
+
to the Lua portion of the code.
31
+
32
+
## Contributing
33
+
Any additional functionality that can be added through a plugin should be done
34
+
so as a plugin, after which a pull request to the
35
+
[plugins repository](https://github.com/rxi/lite-plugins) can be made. In hopes
36
+
of remaining lightweight, pull requests adding additional functionality to the
37
+
core will likely not be merged. Bug reports and bug fixes are welcome.
38
+
39
+
## License
40
+
This project is free software; you can redistribute it and/or modify it under
41
+
the terms of the MIT license. See [LICENSE](LICENSE) for details.
+53
license
+53
license
···
1
+
=== emmeline/lite: MIT License ===
2
+
3
+
Copyright (c) 2025 emmeline
4
+
5
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+
this software and associated documentation files (the "Software"), to deal in
7
+
the Software without restriction, including without limitation the rights to
8
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9
+
of the Software, and to permit persons to whom the Software is furnished to do
10
+
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.
22
+
23
+
=== rxi/lite: MIT License ===
24
+
25
+
Copyright (c) 2020 rxi
26
+
27
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
28
+
this software and associated documentation files (the "Software"), to deal in
29
+
the Software without restriction, including without limitation the rights to
30
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
31
+
of the Software, and to permit persons to whom the Software is furnished to do
32
+
so, subject to the following conditions:
33
+
34
+
The above copyright notice and this permission notice shall be included in all
35
+
copies or substantial portions of the Software.
36
+
37
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
38
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
39
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
40
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
41
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
42
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
43
+
SOFTWARE.
44
+
45
+
=== lua 5.4.8: MIT License ===
46
+
47
+
Copyright ยฉ 1994โ2025 Lua.org, PUC-Rio.
48
+
49
+
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:
50
+
51
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
52
+
53
+
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.
+31
readme
+31
readme
···
1
+
lite (emmeline's fork)
2
+
======================
3
+
4
+
A fork of the [lite](https://github.com/rxi/lite) editor by rxi.
5
+
6
+
A lightweight editor written in Lua.
7
+
8
+
Usage: <doc/usage.md>
9
+
Plugins: <https://github.com/rxi/lite-plugins>
10
+
Themes: <https://github.com/rxi/lite-colors>
11
+
12
+
Build
13
+
-----
14
+
15
+
$ git clone https://tangled.org/emmeline.girlkisser.top/lite
16
+
$ cd lite
17
+
$ ./build.sh
18
+
$ ln -s $(pwd)/lite ~/.local/bin/
19
+
$ lite .
20
+
21
+
Changes
22
+
-------
23
+
24
+
- [x] Reformat to my code style :p
25
+
- [x] Update to SDL 3
26
+
- [ ] Use LuaJIT
27
+
28
+
License
29
+
-------
30
+
31
+
MIT License
+9
-7
src/api/api.c
+9
-7
src/api/api.c
···
6
6
7
7
8
8
static const luaL_Reg libs[] = {
9
-
{ "system", luaopen_system },
10
-
{ "renderer", luaopen_renderer },
11
-
{ NULL, NULL }
9
+
{ "system", luaopen_system },
10
+
{ "renderer", luaopen_renderer },
11
+
{ NULL, NULL }
12
12
};
13
13
14
-
void api_load_libs(lua_State *L) {
15
-
for (int i = 0; libs[i].name; i++) {
16
-
luaL_requiref(L, libs[i].name, libs[i].func, 1);
17
-
}
14
+
void api_load_libs(lua_State *L)
15
+
{
16
+
for (int i = 0 ; libs[i].name ; i++)
17
+
{
18
+
luaL_requiref(L, libs[i].name, libs[i].func, 1);
19
+
}
18
20
}
+78
-70
src/api/renderer.c
+78
-70
src/api/renderer.c
···
3
3
#include "rencache.h"
4
4
5
5
6
-
static RenColor checkcolor(lua_State *L, int idx, int def) {
7
-
RenColor color;
8
-
if (lua_isnoneornil(L, idx)) {
9
-
return (RenColor) { def, def, def, 255 };
10
-
}
11
-
lua_rawgeti(L, idx, 1);
12
-
lua_rawgeti(L, idx, 2);
13
-
lua_rawgeti(L, idx, 3);
14
-
lua_rawgeti(L, idx, 4);
15
-
color.r = luaL_checknumber(L, -4);
16
-
color.g = luaL_checknumber(L, -3);
17
-
color.b = luaL_checknumber(L, -2);
18
-
color.a = luaL_optnumber(L, -1, 255);
19
-
lua_pop(L, 4);
20
-
return color;
6
+
static RenColor checkcolor(lua_State *L, int idx, int def)
7
+
{
8
+
RenColor color;
9
+
if (lua_isnoneornil(L, idx))
10
+
return (RenColor){ def, def, def, 255 };
11
+
lua_rawgeti(L, idx, 1);
12
+
lua_rawgeti(L, idx, 2);
13
+
lua_rawgeti(L, idx, 3);
14
+
lua_rawgeti(L, idx, 4);
15
+
color.r = luaL_checknumber(L, -4);
16
+
color.g = luaL_checknumber(L, -3);
17
+
color.b = luaL_checknumber(L, -2);
18
+
color.a = luaL_optnumber(L, -1, 255);
19
+
lua_pop(L, 4);
20
+
return color;
21
21
}
22
22
23
23
24
-
static int f_show_debug(lua_State *L) {
25
-
luaL_checkany(L, 1);
26
-
rencache_show_debug(lua_toboolean(L, 1));
27
-
return 0;
24
+
static int f_show_debug(lua_State *L)
25
+
{
26
+
luaL_checkany(L, 1);
27
+
rencache_show_debug(lua_toboolean(L, 1));
28
+
return 0;
28
29
}
29
30
30
31
31
-
static int f_get_size(lua_State *L) {
32
-
int w, h;
33
-
ren_get_size(&w, &h);
34
-
lua_pushnumber(L, w);
35
-
lua_pushnumber(L, h);
36
-
return 2;
32
+
static int f_get_size(lua_State *L)
33
+
{
34
+
int w, h;
35
+
ren_get_size(&w, &h);
36
+
lua_pushnumber(L, w);
37
+
lua_pushnumber(L, h);
38
+
return 2;
37
39
}
38
40
39
41
40
-
static int f_begin_frame(lua_State *L) {
41
-
rencache_begin_frame();
42
-
return 0;
42
+
static int f_begin_frame(lua_State *L)
43
+
{
44
+
rencache_begin_frame();
45
+
return 0;
43
46
}
44
47
45
48
46
-
static int f_end_frame(lua_State *L) {
47
-
rencache_end_frame();
48
-
return 0;
49
+
static int f_end_frame(lua_State *L)
50
+
{
51
+
rencache_end_frame();
52
+
return 0;
49
53
}
50
54
51
55
52
-
static int f_set_clip_rect(lua_State *L) {
53
-
RenRect rect;
54
-
rect.x = luaL_checknumber(L, 1);
55
-
rect.y = luaL_checknumber(L, 2);
56
-
rect.width = luaL_checknumber(L, 3);
57
-
rect.height = luaL_checknumber(L, 4);
58
-
rencache_set_clip_rect(rect);
59
-
return 0;
56
+
static int f_set_clip_rect(lua_State *L)
57
+
{
58
+
RenRect rect;
59
+
rect.x = luaL_checknumber(L, 1);
60
+
rect.y = luaL_checknumber(L, 2);
61
+
rect.width = luaL_checknumber(L, 3);
62
+
rect.height = luaL_checknumber(L, 4);
63
+
rencache_set_clip_rect(rect);
64
+
return 0;
60
65
}
61
66
62
67
63
-
static int f_draw_rect(lua_State *L) {
64
-
RenRect rect;
65
-
rect.x = luaL_checknumber(L, 1);
66
-
rect.y = luaL_checknumber(L, 2);
67
-
rect.width = luaL_checknumber(L, 3);
68
-
rect.height = luaL_checknumber(L, 4);
69
-
RenColor color = checkcolor(L, 5, 255);
70
-
rencache_draw_rect(rect, color);
71
-
return 0;
68
+
static int f_draw_rect(lua_State *L)
69
+
{
70
+
RenRect rect;
71
+
rect.x = luaL_checknumber(L, 1);
72
+
rect.y = luaL_checknumber(L, 2);
73
+
rect.width = luaL_checknumber(L, 3);
74
+
rect.height = luaL_checknumber(L, 4);
75
+
RenColor color = checkcolor(L, 5, 255);
76
+
rencache_draw_rect(rect, color);
77
+
return 0;
72
78
}
73
79
74
80
75
-
static int f_draw_text(lua_State *L) {
76
-
RenFont **font = luaL_checkudata(L, 1, API_TYPE_FONT);
77
-
const char *text = luaL_checkstring(L, 2);
78
-
int x = luaL_checknumber(L, 3);
79
-
int y = luaL_checknumber(L, 4);
80
-
RenColor color = checkcolor(L, 5, 255);
81
-
x = rencache_draw_text(*font, text, x, y, color);
82
-
lua_pushnumber(L, x);
83
-
return 1;
81
+
static int f_draw_text(lua_State *L)
82
+
{
83
+
RenFont **font = luaL_checkudata(L, 1, API_TYPE_FONT);
84
+
const char *text = luaL_checkstring(L, 2);
85
+
int x = luaL_checknumber(L, 3);
86
+
int y = luaL_checknumber(L, 4);
87
+
RenColor color = checkcolor(L, 5, 255);
88
+
x = rencache_draw_text(*font, text, x, y, color);
89
+
lua_pushnumber(L, x);
90
+
return 1;
84
91
}
85
92
86
93
87
94
static const luaL_Reg lib[] = {
88
-
{ "show_debug", f_show_debug },
89
-
{ "get_size", f_get_size },
90
-
{ "begin_frame", f_begin_frame },
91
-
{ "end_frame", f_end_frame },
92
-
{ "set_clip_rect", f_set_clip_rect },
93
-
{ "draw_rect", f_draw_rect },
94
-
{ "draw_text", f_draw_text },
95
-
{ NULL, NULL }
95
+
{ "show_debug", f_show_debug },
96
+
{ "get_size", f_get_size },
97
+
{ "begin_frame", f_begin_frame },
98
+
{ "end_frame", f_end_frame },
99
+
{ "set_clip_rect", f_set_clip_rect },
100
+
{ "draw_rect", f_draw_rect },
101
+
{ "draw_text", f_draw_text },
102
+
{ NULL, NULL }
96
103
};
97
104
98
105
99
106
int luaopen_renderer_font(lua_State *L);
100
107
101
-
int luaopen_renderer(lua_State *L) {
102
-
luaL_newlib(L, lib);
103
-
luaopen_renderer_font(L);
104
-
lua_setfield(L, -2, "font");
105
-
return 1;
108
+
int luaopen_renderer(lua_State *L)
109
+
{
110
+
luaL_newlib(L, lib);
111
+
luaopen_renderer_font(L);
112
+
lua_setfield(L, -2, "font");
113
+
return 1;
106
114
}
+46
-38
src/api/renderer_font.c
+46
-38
src/api/renderer_font.c
···
3
3
#include "rencache.h"
4
4
5
5
6
-
static int f_load(lua_State *L) {
7
-
const char *filename = luaL_checkstring(L, 1);
8
-
float size = luaL_checknumber(L, 2);
9
-
RenFont **self = lua_newuserdata(L, sizeof(*self));
10
-
luaL_setmetatable(L, API_TYPE_FONT);
11
-
*self = ren_load_font(filename, size);
12
-
if (!*self) { luaL_error(L, "failed to load font"); }
13
-
return 1;
6
+
static int f_load(lua_State *L)
7
+
{
8
+
const char *filename = luaL_checkstring(L, 1);
9
+
float size = luaL_checknumber(L, 2);
10
+
RenFont **self = lua_newuserdata(L, sizeof(*self));
11
+
luaL_setmetatable(L, API_TYPE_FONT);
12
+
*self = ren_load_font(filename, size);
13
+
if (!*self)
14
+
luaL_error(L, "failed to load font");
15
+
return 1;
14
16
}
15
17
16
18
17
-
static int f_set_tab_width(lua_State *L) {
18
-
RenFont **self = luaL_checkudata(L, 1, API_TYPE_FONT);
19
-
int n = luaL_checknumber(L, 2);
20
-
ren_set_font_tab_width(*self, n);
21
-
return 0;
19
+
static int f_set_tab_width(lua_State *L)
20
+
{
21
+
RenFont **self = luaL_checkudata(L, 1, API_TYPE_FONT);
22
+
int n = luaL_checknumber(L, 2);
23
+
ren_set_font_tab_width(*self, n);
24
+
return 0;
22
25
}
23
26
24
27
25
-
static int f_gc(lua_State *L) {
26
-
RenFont **self = luaL_checkudata(L, 1, API_TYPE_FONT);
27
-
if (*self) { rencache_free_font(*self); }
28
-
return 0;
28
+
static int f_gc(lua_State *L)
29
+
{
30
+
RenFont **self = luaL_checkudata(L, 1, API_TYPE_FONT);
31
+
if (*self)
32
+
rencache_free_font(*self);
33
+
return 0;
29
34
}
30
35
31
36
32
-
static int f_get_width(lua_State *L) {
33
-
RenFont **self = luaL_checkudata(L, 1, API_TYPE_FONT);
34
-
const char *text = luaL_checkstring(L, 2);
35
-
lua_pushnumber(L, ren_get_font_width(*self, text) );
36
-
return 1;
37
+
static int f_get_width(lua_State *L)
38
+
{
39
+
RenFont **self = luaL_checkudata(L, 1, API_TYPE_FONT);
40
+
const char *text = luaL_checkstring(L, 2);
41
+
lua_pushnumber(L, ren_get_font_width(*self, text) );
42
+
return 1;
37
43
}
38
44
39
45
40
-
static int f_get_height(lua_State *L) {
41
-
RenFont **self = luaL_checkudata(L, 1, API_TYPE_FONT);
42
-
lua_pushnumber(L, ren_get_font_height(*self) );
43
-
return 1;
46
+
static int f_get_height(lua_State *L)
47
+
{
48
+
RenFont **self = luaL_checkudata(L, 1, API_TYPE_FONT);
49
+
lua_pushnumber(L, ren_get_font_height(*self) );
50
+
return 1;
44
51
}
45
52
46
53
47
54
static const luaL_Reg lib[] = {
48
-
{ "__gc", f_gc },
49
-
{ "load", f_load },
50
-
{ "set_tab_width", f_set_tab_width },
51
-
{ "get_width", f_get_width },
52
-
{ "get_height", f_get_height },
53
-
{ NULL, NULL }
55
+
{ "__gc", f_gc },
56
+
{ "load", f_load },
57
+
{ "set_tab_width", f_set_tab_width },
58
+
{ "get_width", f_get_width },
59
+
{ "get_height", f_get_height },
60
+
{ NULL, NULL }
54
61
};
55
62
56
-
int luaopen_renderer_font(lua_State *L) {
57
-
luaL_newmetatable(L, API_TYPE_FONT);
58
-
luaL_setfuncs(L, lib, 0);
59
-
lua_pushvalue(L, -1);
60
-
lua_setfield(L, -2, "__index");
61
-
return 1;
63
+
int luaopen_renderer_font(lua_State *L)
64
+
{
65
+
luaL_newmetatable(L, API_TYPE_FONT);
66
+
luaL_setfuncs(L, lib, 0);
67
+
lua_pushvalue(L, -1);
68
+
lua_setfield(L, -2, "__index");
69
+
return 1;
62
70
}
+333
-292
src/api/system.c
+333
-292
src/api/system.c
···
1
-
#include <SDL2/SDL.h>
1
+
#include <SDL3/SDL.h>
2
2
#include <stdbool.h>
3
+
#include <stdlib.h>
3
4
#include <ctype.h>
4
5
#include <dirent.h>
5
6
#include <unistd.h>
···
8
9
#include "api.h"
9
10
#include "rencache.h"
10
11
#ifdef _WIN32
11
-
#include <windows.h>
12
+
# include <windows.h>
12
13
#endif
13
14
14
15
extern SDL_Window *window;
15
16
16
17
17
-
static const char* button_name(int button) {
18
-
switch (button) {
19
-
case 1 : return "left";
20
-
case 2 : return "middle";
21
-
case 3 : return "right";
22
-
default : return "?";
23
-
}
18
+
static const char* button_name(int button)
19
+
{
20
+
switch (button)
21
+
{
22
+
case 1 : return "left";
23
+
case 2 : return "middle";
24
+
case 3 : return "right";
25
+
default : return "?";
26
+
}
24
27
}
25
28
26
29
27
-
static char* key_name(char *dst, int sym) {
28
-
strcpy(dst, SDL_GetKeyName(sym));
29
-
char *p = dst;
30
-
while (*p) {
31
-
*p = tolower(*p);
32
-
p++;
33
-
}
34
-
return dst;
30
+
static char* key_name(char *dst, int sym)
31
+
{
32
+
strcpy(dst, SDL_GetKeyName(sym));
33
+
char *p = dst;
34
+
while (*p)
35
+
{
36
+
*p = tolower(*p);
37
+
p++;
38
+
}
39
+
return dst;
35
40
}
36
41
37
42
38
-
static int f_poll_event(lua_State *L) {
39
-
char buf[16];
40
-
int mx, my, wx, wy;
41
-
SDL_Event e;
43
+
static int f_poll_event(lua_State *L)
44
+
{
45
+
char buf[16];
46
+
float mx, my;
47
+
int wx, wy;
48
+
SDL_Event e;
42
49
43
50
top:
44
-
if ( !SDL_PollEvent(&e) ) {
45
-
return 0;
46
-
}
51
+
if (!SDL_PollEvent(&e))
52
+
return 0;
53
+
54
+
switch (e.type)
55
+
{
56
+
case SDL_EVENT_QUIT :
57
+
lua_pushstring(L, "quit");
58
+
return 1;
59
+
60
+
case SDL_EVENT_WINDOW_RESIZED:
61
+
lua_pushstring(L, "resized");
62
+
lua_pushnumber(L, e.window.data1);
63
+
lua_pushnumber(L, e.window.data2);
64
+
return 3;
47
65
48
-
switch (e.type) {
49
-
case SDL_QUIT:
50
-
lua_pushstring(L, "quit");
51
-
return 1;
66
+
case SDL_EVENT_WINDOW_EXPOSED:
67
+
rencache_invalidate();
68
+
lua_pushstring(L, "exposed");
69
+
return 1;
52
70
53
-
case SDL_WINDOWEVENT:
54
-
if (e.window.event == SDL_WINDOWEVENT_RESIZED) {
55
-
lua_pushstring(L, "resized");
56
-
lua_pushnumber(L, e.window.data1);
57
-
lua_pushnumber(L, e.window.data2);
58
-
return 3;
59
-
} else if (e.window.event == SDL_WINDOWEVENT_EXPOSED) {
60
-
rencache_invalidate();
61
-
lua_pushstring(L, "exposed");
62
-
return 1;
63
-
}
64
-
/* on some systems, when alt-tabbing to the window SDL will queue up
65
-
** several KEYDOWN events for the `tab` key; we flush all keydown
66
-
** events on focus so these are discarded */
67
-
if (e.window.event == SDL_WINDOWEVENT_FOCUS_GAINED) {
68
-
SDL_FlushEvent(SDL_KEYDOWN);
69
-
}
70
-
goto top;
71
+
case SDL_EVENT_WINDOW_FOCUS_GAINED:
72
+
/* on some systems, when alt-tabbing to the window SDL will queue up
73
+
** several KEYDOWN events for the `tab` key; we flush all keydown
74
+
** events on focus so these are discarded */
75
+
SDL_FlushEvent(SDL_EVENT_KEY_DOWN);
76
+
goto top;
71
77
72
-
case SDL_DROPFILE:
73
-
SDL_GetGlobalMouseState(&mx, &my);
74
-
SDL_GetWindowPosition(window, &wx, &wy);
75
-
lua_pushstring(L, "filedropped");
76
-
lua_pushstring(L, e.drop.file);
77
-
lua_pushnumber(L, mx - wx);
78
-
lua_pushnumber(L, my - wy);
79
-
SDL_free(e.drop.file);
80
-
return 4;
78
+
case SDL_EVENT_DROP_FILE :
79
+
SDL_GetGlobalMouseState(&mx, &my);
80
+
SDL_GetWindowPosition(window, &wx, &wy);
81
+
lua_pushstring(L, "filedropped");
82
+
lua_pushstring(L, e.drop.data);
83
+
lua_pushnumber(L, mx - wx);
84
+
lua_pushnumber(L, my - wy);
85
+
return 4;
81
86
82
-
case SDL_KEYDOWN:
83
-
lua_pushstring(L, "keypressed");
84
-
lua_pushstring(L, key_name(buf, e.key.keysym.sym));
85
-
return 2;
87
+
case SDL_EVENT_KEY_DOWN :
88
+
lua_pushstring(L, "keypressed");
89
+
lua_pushstring(L, key_name(buf, e.key.key));
90
+
return 2;
86
91
87
-
case SDL_KEYUP:
88
-
lua_pushstring(L, "keyreleased");
89
-
lua_pushstring(L, key_name(buf, e.key.keysym.sym));
90
-
return 2;
92
+
case SDL_EVENT_KEY_UP :
93
+
lua_pushstring(L, "keyreleased");
94
+
lua_pushstring(L, key_name(buf, e.key.key));
95
+
return 2;
91
96
92
-
case SDL_TEXTINPUT:
93
-
lua_pushstring(L, "textinput");
94
-
lua_pushstring(L, e.text.text);
95
-
return 2;
97
+
case SDL_EVENT_TEXT_INPUT :
98
+
lua_pushstring(L, "textinput");
99
+
lua_pushstring(L, e.text.text);
100
+
return 2;
96
101
97
-
case SDL_MOUSEBUTTONDOWN:
98
-
if (e.button.button == 1) { SDL_CaptureMouse(1); }
99
-
lua_pushstring(L, "mousepressed");
100
-
lua_pushstring(L, button_name(e.button.button));
101
-
lua_pushnumber(L, e.button.x);
102
-
lua_pushnumber(L, e.button.y);
103
-
lua_pushnumber(L, e.button.clicks);
104
-
return 5;
102
+
case SDL_EVENT_MOUSE_BUTTON_DOWN :
103
+
if (e.button.button == 1)
104
+
SDL_CaptureMouse(1);
105
+
lua_pushstring(L, "mousepressed");
106
+
lua_pushstring(L, button_name(e.button.button));
107
+
lua_pushnumber(L, e.button.x);
108
+
lua_pushnumber(L, e.button.y);
109
+
lua_pushnumber(L, e.button.clicks);
110
+
return 5;
105
111
106
-
case SDL_MOUSEBUTTONUP:
107
-
if (e.button.button == 1) { SDL_CaptureMouse(0); }
108
-
lua_pushstring(L, "mousereleased");
109
-
lua_pushstring(L, button_name(e.button.button));
110
-
lua_pushnumber(L, e.button.x);
111
-
lua_pushnumber(L, e.button.y);
112
-
return 4;
112
+
case SDL_EVENT_MOUSE_BUTTON_UP :
113
+
if (e.button.button == 1)
114
+
SDL_CaptureMouse(0);
115
+
lua_pushstring(L, "mousereleased");
116
+
lua_pushstring(L, button_name(e.button.button));
117
+
lua_pushnumber(L, e.button.x);
118
+
lua_pushnumber(L, e.button.y);
119
+
return 4;
113
120
114
-
case SDL_MOUSEMOTION:
115
-
lua_pushstring(L, "mousemoved");
116
-
lua_pushnumber(L, e.motion.x);
117
-
lua_pushnumber(L, e.motion.y);
118
-
lua_pushnumber(L, e.motion.xrel);
119
-
lua_pushnumber(L, e.motion.yrel);
120
-
return 5;
121
+
case SDL_EVENT_MOUSE_MOTION :
122
+
lua_pushstring(L, "mousemoved");
123
+
lua_pushnumber(L, e.motion.x);
124
+
lua_pushnumber(L, e.motion.y);
125
+
lua_pushnumber(L, e.motion.xrel);
126
+
lua_pushnumber(L, e.motion.yrel);
127
+
return 5;
121
128
122
-
case SDL_MOUSEWHEEL:
123
-
lua_pushstring(L, "mousewheel");
124
-
lua_pushnumber(L, e.wheel.y);
125
-
return 2;
129
+
case SDL_EVENT_MOUSE_WHEEL :
130
+
lua_pushstring(L, "mousewheel");
131
+
lua_pushnumber(L, e.wheel.y);
132
+
return 2;
126
133
127
-
default:
128
-
goto top;
129
-
}
134
+
default:
135
+
goto top;
136
+
}
130
137
131
-
return 0;
138
+
return 0;
132
139
}
133
140
134
141
135
-
static int f_wait_event(lua_State *L) {
136
-
double n = luaL_checknumber(L, 1);
137
-
lua_pushboolean(L, SDL_WaitEventTimeout(NULL, n * 1000));
138
-
return 1;
142
+
static int f_wait_event(lua_State *L)
143
+
{
144
+
double n = luaL_checknumber(L, 1);
145
+
lua_pushboolean(L, SDL_WaitEventTimeout(NULL, n * 1000));
146
+
return 1;
139
147
}
140
148
141
149
142
-
static SDL_Cursor* cursor_cache[SDL_SYSTEM_CURSOR_HAND + 1];
150
+
static SDL_Cursor* cursor_cache[SDL_SYSTEM_CURSOR_POINTER + 1];
143
151
144
152
static const char *cursor_opts[] = {
145
-
"arrow",
146
-
"ibeam",
147
-
"sizeh",
148
-
"sizev",
149
-
"hand",
150
-
NULL
153
+
"arrow",
154
+
"ibeam",
155
+
"sizeh",
156
+
"sizev",
157
+
"hand",
158
+
NULL
151
159
};
152
160
153
161
static const int cursor_enums[] = {
154
-
SDL_SYSTEM_CURSOR_ARROW,
155
-
SDL_SYSTEM_CURSOR_IBEAM,
156
-
SDL_SYSTEM_CURSOR_SIZEWE,
157
-
SDL_SYSTEM_CURSOR_SIZENS,
158
-
SDL_SYSTEM_CURSOR_HAND
162
+
SDL_SYSTEM_CURSOR_DEFAULT,
163
+
SDL_SYSTEM_CURSOR_TEXT,
164
+
SDL_SYSTEM_CURSOR_EW_RESIZE,
165
+
SDL_SYSTEM_CURSOR_NS_RESIZE,
166
+
SDL_SYSTEM_CURSOR_POINTER
159
167
};
160
168
161
-
static int f_set_cursor(lua_State *L) {
162
-
int opt = luaL_checkoption(L, 1, "arrow", cursor_opts);
163
-
int n = cursor_enums[opt];
164
-
SDL_Cursor *cursor = cursor_cache[n];
165
-
if (!cursor) {
166
-
cursor = SDL_CreateSystemCursor(n);
167
-
cursor_cache[n] = cursor;
168
-
}
169
-
SDL_SetCursor(cursor);
170
-
return 0;
169
+
static int f_set_cursor(lua_State *L)
170
+
{
171
+
int opt = luaL_checkoption(L, 1, "arrow", cursor_opts);
172
+
int n = cursor_enums[opt];
173
+
SDL_Cursor *cursor = cursor_cache[n];
174
+
if (!cursor)
175
+
{
176
+
cursor = SDL_CreateSystemCursor(n);
177
+
cursor_cache[n] = cursor;
178
+
}
179
+
SDL_SetCursor(cursor);
180
+
return 0;
171
181
}
172
182
173
183
174
-
static int f_set_window_title(lua_State *L) {
175
-
const char *title = luaL_checkstring(L, 1);
176
-
SDL_SetWindowTitle(window, title);
177
-
return 0;
184
+
static int f_set_window_title(lua_State *L)
185
+
{
186
+
const char *title = luaL_checkstring(L, 1);
187
+
SDL_SetWindowTitle(window, title);
188
+
return 0;
178
189
}
179
190
180
191
181
192
static const char *window_opts[] = { "normal", "maximized", "fullscreen", 0 };
182
193
enum { WIN_NORMAL, WIN_MAXIMIZED, WIN_FULLSCREEN };
183
194
184
-
static int f_set_window_mode(lua_State *L) {
185
-
int n = luaL_checkoption(L, 1, "normal", window_opts);
186
-
SDL_SetWindowFullscreen(window,
187
-
n == WIN_FULLSCREEN ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0);
188
-
if (n == WIN_NORMAL) { SDL_RestoreWindow(window); }
189
-
if (n == WIN_MAXIMIZED) { SDL_MaximizeWindow(window); }
190
-
return 0;
195
+
static int f_set_window_mode(lua_State *L)
196
+
{
197
+
int n = luaL_checkoption(L, 1, "normal", window_opts);
198
+
SDL_SetWindowFullscreen(window, n == WIN_FULLSCREEN ? SDL_WINDOW_FULLSCREEN : 0);
199
+
if (n == WIN_NORMAL)
200
+
SDL_RestoreWindow(window);
201
+
if (n == WIN_MAXIMIZED)
202
+
SDL_MaximizeWindow(window);
203
+
return 0;
191
204
}
192
205
193
206
194
-
static int f_window_has_focus(lua_State *L) {
195
-
unsigned flags = SDL_GetWindowFlags(window);
196
-
lua_pushboolean(L, flags & SDL_WINDOW_INPUT_FOCUS);
197
-
return 1;
207
+
static int f_window_has_focus(lua_State *L)
208
+
{
209
+
unsigned flags = SDL_GetWindowFlags(window);
210
+
lua_pushboolean(L, flags & SDL_WINDOW_INPUT_FOCUS);
211
+
return 1;
198
212
}
199
213
200
214
201
-
static int f_show_confirm_dialog(lua_State *L) {
202
-
const char *title = luaL_checkstring(L, 1);
203
-
const char *msg = luaL_checkstring(L, 2);
215
+
static int f_show_confirm_dialog(lua_State *L)
216
+
{
217
+
const char *title = luaL_checkstring(L, 1);
218
+
const char *msg = luaL_checkstring(L, 2);
204
219
205
-
#if _WIN32
206
-
int id = MessageBox(0, msg, title, MB_YESNO | MB_ICONWARNING);
207
-
lua_pushboolean(L, id == IDYES);
220
+
# if _WIN32
221
+
int id = MessageBox(0, msg, title, MB_YESNO | MB_ICONWARNING);
222
+
lua_pushboolean(L, id == IDYES);
223
+
# else
224
+
SDL_MessageBoxButtonData buttons[] = {
225
+
{ SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT, 1, "Yes" },
226
+
{ SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT, 0, "No" },
227
+
};
228
+
SDL_MessageBoxData data = {
229
+
.title = title,
230
+
.message = msg,
231
+
.numbuttons = 2,
232
+
.buttons = buttons,
233
+
};
234
+
int buttonid;
235
+
SDL_ShowMessageBox(&data, &buttonid);
236
+
lua_pushboolean(L, buttonid == 1);
237
+
# endif
208
238
209
-
#else
210
-
SDL_MessageBoxButtonData buttons[] = {
211
-
{ SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT, 1, "Yes" },
212
-
{ SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT, 0, "No" },
213
-
};
214
-
SDL_MessageBoxData data = {
215
-
.title = title,
216
-
.message = msg,
217
-
.numbuttons = 2,
218
-
.buttons = buttons,
219
-
};
220
-
int buttonid;
221
-
SDL_ShowMessageBox(&data, &buttonid);
222
-
lua_pushboolean(L, buttonid == 1);
223
-
#endif
224
-
return 1;
239
+
return 1;
225
240
}
226
241
227
242
228
-
static int f_chdir(lua_State *L) {
229
-
const char *path = luaL_checkstring(L, 1);
230
-
int err = chdir(path);
231
-
if (err) { luaL_error(L, "chdir() failed"); }
232
-
return 0;
243
+
static int f_chdir(lua_State *L)
244
+
{
245
+
const char *path = luaL_checkstring(L, 1);
246
+
int err = chdir(path);
247
+
if (err)
248
+
luaL_error(L, "chdir() failed");
249
+
return 0;
233
250
}
234
251
235
252
236
-
static int f_list_dir(lua_State *L) {
237
-
const char *path = luaL_checkstring(L, 1);
253
+
static int f_list_dir(lua_State *L)
254
+
{
255
+
const char *path = luaL_checkstring(L, 1);
238
256
239
-
DIR *dir = opendir(path);
240
-
if (!dir) {
241
-
lua_pushnil(L);
242
-
lua_pushstring(L, strerror(errno));
243
-
return 2;
244
-
}
257
+
DIR *dir = opendir(path);
258
+
if (!dir)
259
+
{
260
+
lua_pushnil(L);
261
+
lua_pushstring(L, strerror(errno));
262
+
return 2;
263
+
}
245
264
246
-
lua_newtable(L);
247
-
int i = 1;
248
-
struct dirent *entry;
249
-
while ( (entry = readdir(dir)) ) {
250
-
if (strcmp(entry->d_name, "." ) == 0) { continue; }
251
-
if (strcmp(entry->d_name, "..") == 0) { continue; }
252
-
lua_pushstring(L, entry->d_name);
253
-
lua_rawseti(L, -2, i);
254
-
i++;
255
-
}
265
+
lua_newtable(L);
266
+
int i = 1;
267
+
struct dirent *entry;
268
+
while ((entry = readdir(dir)))
269
+
{
270
+
if (strcmp(entry->d_name, "." ) == 0 || strcmp(entry->d_name, "..") == 0)
271
+
continue;
272
+
lua_pushstring(L, entry->d_name);
273
+
lua_rawseti(L, -2, i);
274
+
i++;
275
+
}
256
276
257
-
closedir(dir);
258
-
return 1;
277
+
closedir(dir);
278
+
return 1;
259
279
}
260
280
261
281
262
282
#ifdef _WIN32
263
-
#include <windows.h>
264
-
#define realpath(x, y) _fullpath(y, x, MAX_PATH)
283
+
# include <windows.h>
284
+
# define realpath(x, y) _fullpath(y, x, MAX_PATH)
265
285
#endif
266
286
267
-
static int f_absolute_path(lua_State *L) {
268
-
const char *path = luaL_checkstring(L, 1);
269
-
char *res = realpath(path, NULL);
270
-
if (!res) { return 0; }
271
-
lua_pushstring(L, res);
272
-
free(res);
273
-
return 1;
287
+
static int f_absolute_path(lua_State *L)
288
+
{
289
+
const char *path = luaL_checkstring(L, 1);
290
+
char *res = realpath(path, NULL);
291
+
if (!res)
292
+
return 0;
293
+
lua_pushstring(L, res);
294
+
free(res);
295
+
return 1;
274
296
}
275
297
276
298
277
-
static int f_get_file_info(lua_State *L) {
278
-
const char *path = luaL_checkstring(L, 1);
299
+
static int f_get_file_info(lua_State *L)
300
+
{
301
+
const char *path = luaL_checkstring(L, 1);
279
302
280
-
struct stat s;
281
-
int err = stat(path, &s);
282
-
if (err < 0) {
283
-
lua_pushnil(L);
284
-
lua_pushstring(L, strerror(errno));
285
-
return 2;
286
-
}
303
+
struct stat s;
304
+
int err = stat(path, &s);
305
+
if (err < 0)
306
+
{
307
+
lua_pushnil(L);
308
+
lua_pushstring(L, strerror(errno));
309
+
return 2;
310
+
}
287
311
288
-
lua_newtable(L);
289
-
lua_pushnumber(L, s.st_mtime);
290
-
lua_setfield(L, -2, "modified");
312
+
lua_newtable(L);
313
+
lua_pushnumber(L, s.st_mtime);
314
+
lua_setfield(L, -2, "modified");
291
315
292
-
lua_pushnumber(L, s.st_size);
293
-
lua_setfield(L, -2, "size");
316
+
lua_pushnumber(L, s.st_size);
317
+
lua_setfield(L, -2, "size");
294
318
295
-
if (S_ISREG(s.st_mode)) {
296
-
lua_pushstring(L, "file");
297
-
} else if (S_ISDIR(s.st_mode)) {
298
-
lua_pushstring(L, "dir");
299
-
} else {
300
-
lua_pushnil(L);
301
-
}
302
-
lua_setfield(L, -2, "type");
319
+
if (S_ISREG(s.st_mode))
320
+
lua_pushstring(L, "file");
321
+
else if (S_ISDIR(s.st_mode))
322
+
lua_pushstring(L, "dir");
323
+
else
324
+
lua_pushnil(L);
325
+
lua_setfield(L, -2, "type");
303
326
304
-
return 1;
327
+
return 1;
305
328
}
306
329
307
330
308
-
static int f_get_clipboard(lua_State *L) {
309
-
char *text = SDL_GetClipboardText();
310
-
if (!text) { return 0; }
311
-
lua_pushstring(L, text);
312
-
SDL_free(text);
313
-
return 1;
331
+
static int f_get_clipboard(lua_State *L)
332
+
{
333
+
char *text = SDL_GetClipboardText();
334
+
if (!text)
335
+
return 0;
336
+
lua_pushstring(L, text);
337
+
SDL_free(text);
338
+
return 1;
314
339
}
315
340
316
341
317
-
static int f_set_clipboard(lua_State *L) {
318
-
const char *text = luaL_checkstring(L, 1);
319
-
SDL_SetClipboardText(text);
320
-
return 0;
342
+
static int f_set_clipboard(lua_State *L)
343
+
{
344
+
const char *text = luaL_checkstring(L, 1);
345
+
SDL_SetClipboardText(text);
346
+
return 0;
321
347
}
322
348
323
349
324
-
static int f_get_time(lua_State *L) {
325
-
double n = SDL_GetPerformanceCounter() / (double) SDL_GetPerformanceFrequency();
326
-
lua_pushnumber(L, n);
327
-
return 1;
350
+
static int f_get_time(lua_State *L)
351
+
{
352
+
double n = SDL_GetPerformanceCounter() / (double) SDL_GetPerformanceFrequency();
353
+
lua_pushnumber(L, n);
354
+
return 1;
328
355
}
329
356
330
357
331
-
static int f_sleep(lua_State *L) {
332
-
double n = luaL_checknumber(L, 1);
333
-
SDL_Delay(n * 1000);
334
-
return 0;
358
+
static int f_sleep(lua_State *L)
359
+
{
360
+
double n = luaL_checknumber(L, 1);
361
+
SDL_Delay(n * 1000);
362
+
return 0;
335
363
}
336
364
337
365
338
-
static int f_exec(lua_State *L) {
339
-
size_t len;
340
-
const char *cmd = luaL_checklstring(L, 1, &len);
341
-
char *buf = malloc(len + 32);
342
-
if (!buf) { luaL_error(L, "buffer allocation failed"); }
343
-
#if _WIN32
344
-
sprintf(buf, "cmd /c \"%s\"", cmd);
345
-
WinExec(buf, SW_HIDE);
346
-
#else
347
-
sprintf(buf, "%s &", cmd);
348
-
int res = system(buf);
349
-
(void) res;
350
-
#endif
351
-
free(buf);
352
-
return 0;
366
+
static int f_exec(lua_State *L)
367
+
{
368
+
size_t len;
369
+
const char *cmd = luaL_checklstring(L, 1, &len);
370
+
char *buf = malloc(len + 32);
371
+
if (!buf)
372
+
luaL_error(L, "buffer allocation failed");
373
+
374
+
# if _WIN32
375
+
sprintf(buf, "cmd /c \"%s\"", cmd);
376
+
WinExec(buf, SW_HIDE);
377
+
# else
378
+
sprintf(buf, "%s &", cmd);
379
+
int res = system(buf);
380
+
(void)res;
381
+
# endif
382
+
383
+
free(buf);
384
+
return 0;
353
385
}
354
386
355
387
356
-
static int f_fuzzy_match(lua_State *L) {
357
-
const char *str = luaL_checkstring(L, 1);
358
-
const char *ptn = luaL_checkstring(L, 2);
359
-
int score = 0;
360
-
int run = 0;
388
+
static int f_fuzzy_match(lua_State *L)
389
+
{
390
+
const char *str = luaL_checkstring(L, 1);
391
+
const char *ptn = luaL_checkstring(L, 2);
392
+
int score = 0;
393
+
int run = 0;
361
394
362
-
while (*str && *ptn) {
363
-
while (*str == ' ') { str++; }
364
-
while (*ptn == ' ') { ptn++; }
365
-
if (tolower(*str) == tolower(*ptn)) {
366
-
score += run * 10 - (*str != *ptn);
367
-
run++;
368
-
ptn++;
369
-
} else {
370
-
score -= 10;
371
-
run = 0;
372
-
}
373
-
str++;
374
-
}
375
-
if (*ptn) { return 0; }
395
+
while (*str && *ptn)
396
+
{
397
+
while (*str == ' ')
398
+
str++;
399
+
while (*ptn == ' ')
400
+
ptn++;
401
+
if (tolower(*str) == tolower(*ptn))
402
+
{
403
+
score += run * 10 - (*str != *ptn);
404
+
run++;
405
+
ptn++;
406
+
}
407
+
else
408
+
{
409
+
score -= 10;
410
+
run = 0;
411
+
}
412
+
str++;
413
+
}
414
+
if (*ptn)
415
+
return 0;
376
416
377
-
lua_pushnumber(L, score - (int) strlen(str));
378
-
return 1;
417
+
lua_pushnumber(L, score - (int) strlen(str));
418
+
return 1;
379
419
}
380
420
381
421
382
422
static const luaL_Reg lib[] = {
383
-
{ "poll_event", f_poll_event },
384
-
{ "wait_event", f_wait_event },
385
-
{ "set_cursor", f_set_cursor },
386
-
{ "set_window_title", f_set_window_title },
387
-
{ "set_window_mode", f_set_window_mode },
388
-
{ "window_has_focus", f_window_has_focus },
389
-
{ "show_confirm_dialog", f_show_confirm_dialog },
390
-
{ "chdir", f_chdir },
391
-
{ "list_dir", f_list_dir },
392
-
{ "absolute_path", f_absolute_path },
393
-
{ "get_file_info", f_get_file_info },
394
-
{ "get_clipboard", f_get_clipboard },
395
-
{ "set_clipboard", f_set_clipboard },
396
-
{ "get_time", f_get_time },
397
-
{ "sleep", f_sleep },
398
-
{ "exec", f_exec },
399
-
{ "fuzzy_match", f_fuzzy_match },
400
-
{ NULL, NULL }
423
+
{ "poll_event", f_poll_event },
424
+
{ "wait_event", f_wait_event },
425
+
{ "set_cursor", f_set_cursor },
426
+
{ "set_window_title", f_set_window_title },
427
+
{ "set_window_mode", f_set_window_mode },
428
+
{ "window_has_focus", f_window_has_focus },
429
+
{ "show_confirm_dialog", f_show_confirm_dialog },
430
+
{ "chdir", f_chdir },
431
+
{ "list_dir", f_list_dir },
432
+
{ "absolute_path", f_absolute_path },
433
+
{ "get_file_info", f_get_file_info },
434
+
{ "get_clipboard", f_get_clipboard },
435
+
{ "set_clipboard", f_set_clipboard },
436
+
{ "get_time", f_get_time },
437
+
{ "sleep", f_sleep },
438
+
{ "exec", f_exec },
439
+
{ "fuzzy_match", f_fuzzy_match },
440
+
{ NULL, NULL }
401
441
};
402
442
403
443
404
-
int luaopen_system(lua_State *L) {
405
-
luaL_newlib(L, lib);
406
-
return 1;
444
+
int luaopen_system(lua_State *L)
445
+
{
446
+
luaL_newlib(L, lib);
447
+
return 1;
407
448
}
+103
-108
src/main.c
+103
-108
src/main.c
···
1
1
#include <stdio.h>
2
-
#include <SDL2/SDL.h>
2
+
#include <stdlib.h>
3
+
#include <SDL3/SDL.h>
3
4
#include "api/api.h"
4
5
#include "renderer.h"
5
6
6
7
#ifdef _WIN32
7
-
#include <windows.h>
8
+
# include <windows.h>
8
9
#elif __linux__
9
-
#include <unistd.h>
10
+
# include <unistd.h>
10
11
#elif __APPLE__
11
-
#include <mach-o/dyld.h>
12
+
# include <mach-o/dyld.h>
12
13
#endif
13
14
14
15
15
16
SDL_Window *window;
16
17
17
18
18
-
static double get_scale(void) {
19
-
float dpi;
20
-
SDL_GetDisplayDPI(0, NULL, &dpi, NULL);
21
-
#if _WIN32
22
-
return dpi / 96.0;
23
-
#else
24
-
return 1.0;
25
-
#endif
19
+
static double get_scale(void)
20
+
{
21
+
return (double)SDL_min(SDL_GetDisplayContentScale(SDL_GetPrimaryDisplay()), 1.0);
26
22
}
27
23
28
-
29
-
static void get_exe_filename(char *buf, int sz) {
30
-
#if _WIN32
31
-
int len = GetModuleFileName(NULL, buf, sz - 1);
32
-
buf[len] = '\0';
33
-
#elif __linux__
34
-
char path[512];
35
-
sprintf(path, "/proc/%d/exe", getpid());
36
-
int len = readlink(path, buf, sz - 1);
37
-
buf[len] = '\0';
38
-
#elif __APPLE__
39
-
unsigned size = sz;
40
-
_NSGetExecutablePath(buf, &size);
41
-
#else
42
-
strcpy(buf, "./lite");
43
-
#endif
24
+
static void get_exe_filename(char *buf, int sz)
25
+
{
26
+
# if _WIN32
27
+
int len = GetModuleFileName(NULL, buf, sz - 1);
28
+
buf[len] = '\0';
29
+
# elif __linux__
30
+
char path[512];
31
+
sprintf(path, "/proc/%d/exe", getpid());
32
+
int len = readlink(path, buf, sz - 1);
33
+
buf[len] = '\0';
34
+
# elif __APPLE__
35
+
unsigned size = sz;
36
+
_NSGetExecutablePath(buf, &size);
37
+
# else
38
+
strcpy(buf, "./lite");
39
+
# endif
44
40
}
45
41
46
42
47
-
static void init_window_icon(void) {
48
-
#ifndef _WIN32
49
-
#include "../icon.inl"
50
-
(void) icon_rgba_len; /* unused */
51
-
SDL_Surface *surf = SDL_CreateRGBSurfaceFrom(
52
-
icon_rgba, 64, 64,
53
-
32, 64 * 4,
54
-
0x000000ff,
55
-
0x0000ff00,
56
-
0x00ff0000,
57
-
0xff000000);
58
-
SDL_SetWindowIcon(window, surf);
59
-
SDL_FreeSurface(surf);
60
-
#endif
43
+
static void init_window_icon(void)
44
+
{
45
+
# ifndef _WIN32
46
+
# include "../icon.inl"
47
+
(void) icon_rgba_len; /* unused */
48
+
SDL_Surface *surf = SDL_CreateSurfaceFrom(64, 64, SDL_PIXELFORMAT_ABGR8888, icon_rgba, 64 * 4);
49
+
SDL_SetWindowIcon(window, surf);
50
+
SDL_DestroySurface(surf);
51
+
# endif
61
52
}
62
53
63
54
64
-
int main(int argc, char **argv) {
65
-
#ifdef _WIN32
66
-
HINSTANCE lib = LoadLibrary("user32.dll");
67
-
int (*SetProcessDPIAware)() = (void*) GetProcAddress(lib, "SetProcessDPIAware");
68
-
SetProcessDPIAware();
69
-
#endif
55
+
int main(int argc, char **argv)
56
+
{
57
+
# ifdef _WIN32
58
+
HINSTANCE lib = LoadLibrary("user32.dll");
59
+
int (*SetProcessDPIAware)() = (void *)GetProcAddress(lib, "SetProcessDPIAware");
60
+
SetProcessDPIAware();
61
+
# endif
70
62
71
-
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS);
72
-
SDL_EnableScreenSaver();
73
-
SDL_EventState(SDL_DROPFILE, SDL_ENABLE);
74
-
atexit(SDL_Quit);
63
+
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS);
64
+
SDL_EnableScreenSaver();
65
+
SDL_SetEventEnabled(SDL_EVENT_DROP_FILE, true);
66
+
atexit(SDL_Quit);
75
67
76
-
#ifdef SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR /* Available since 2.0.8 */
77
-
SDL_SetHint(SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, "0");
78
-
#endif
79
-
#if SDL_VERSION_ATLEAST(2, 0, 5)
80
-
SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1");
81
-
#endif
68
+
SDL_SetHint(SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, "0");
69
+
SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1");
82
70
83
-
SDL_DisplayMode dm;
84
-
SDL_GetCurrentDisplayMode(0, &dm);
71
+
const SDL_DisplayMode *dm = SDL_GetCurrentDisplayMode(SDL_GetPrimaryDisplay());
72
+
window = SDL_CreateWindow("", (int)(dm->w * 0.8), (int)(dm->h * 0.8), SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIGH_PIXEL_DENSITY | SDL_WINDOW_HIDDEN);
73
+
if (!window)
74
+
{
75
+
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Failed to create window: %s\n", SDL_GetError());
76
+
return EXIT_FAILURE;
77
+
}
78
+
init_window_icon();
79
+
ren_init(window);
85
80
86
-
window = SDL_CreateWindow(
87
-
"", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, dm.w * 0.8, dm.h * 0.8,
88
-
SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_HIDDEN);
89
-
init_window_icon();
90
-
ren_init(window);
81
+
if (!SDL_StartTextInput(window))
82
+
{
83
+
# ifndef _WIN32
84
+
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "ERROR: failed SDL_StartTextInput() - text entry may not work");
85
+
# endif
86
+
}
91
87
92
88
93
-
lua_State *L = luaL_newstate();
94
-
luaL_openlibs(L);
95
-
api_load_libs(L);
89
+
lua_State *L = luaL_newstate();
90
+
luaL_openlibs(L);
91
+
api_load_libs(L);
96
92
93
+
lua_newtable(L);
94
+
for (int i = 0 ; i < argc ; i++)
95
+
{
96
+
lua_pushstring(L, argv[i]);
97
+
lua_rawseti(L, -2, i + 1);
98
+
}
99
+
lua_setglobal(L, "ARGS");
97
100
98
-
lua_newtable(L);
99
-
for (int i = 0; i < argc; i++) {
100
-
lua_pushstring(L, argv[i]);
101
-
lua_rawseti(L, -2, i + 1);
102
-
}
103
-
lua_setglobal(L, "ARGS");
101
+
lua_pushstring(L, "1.11");
102
+
lua_setglobal(L, "VERSION");
104
103
105
-
lua_pushstring(L, "1.11");
106
-
lua_setglobal(L, "VERSION");
104
+
lua_pushstring(L, SDL_GetPlatform());
105
+
lua_setglobal(L, "PLATFORM");
107
106
108
-
lua_pushstring(L, SDL_GetPlatform());
109
-
lua_setglobal(L, "PLATFORM");
107
+
lua_pushnumber(L, get_scale());
108
+
lua_setglobal(L, "SCALE");
110
109
111
-
lua_pushnumber(L, get_scale());
112
-
lua_setglobal(L, "SCALE");
110
+
char exename[2048];
111
+
get_exe_filename(exename, sizeof(exename));
112
+
lua_pushstring(L, exename);
113
+
lua_setglobal(L, "EXEFILE");
113
114
114
-
char exename[2048];
115
-
get_exe_filename(exename, sizeof(exename));
116
-
lua_pushstring(L, exename);
117
-
lua_setglobal(L, "EXEFILE");
118
-
119
-
120
-
(void) luaL_dostring(L,
121
-
"local core\n"
122
-
"xpcall(function()\n"
123
-
" SCALE = tonumber(os.getenv(\"LITE_SCALE\")) or SCALE\n"
124
-
" PATHSEP = package.config:sub(1, 1)\n"
125
-
" EXEDIR = EXEFILE:match(\"^(.+)[/\\\\].*$\")\n"
126
-
" package.path = EXEDIR .. '/data/?.lua;' .. package.path\n"
127
-
" package.path = EXEDIR .. '/data/?/init.lua;' .. package.path\n"
128
-
" core = require('core')\n"
129
-
" core.init()\n"
130
-
" core.run()\n"
131
-
"end, function(err)\n"
132
-
" print('Error: ' .. tostring(err))\n"
133
-
" print(debug.traceback(nil, 2))\n"
134
-
" if core and core.on_error then\n"
135
-
" pcall(core.on_error, err)\n"
136
-
" end\n"
137
-
" os.exit(1)\n"
138
-
"end)");
115
+
(void) luaL_dostring(L,
116
+
"local core\n"
117
+
"xpcall(function()\n"
118
+
" SCALE = tonumber(os.getenv(\"LITE_SCALE\")) or SCALE\n"
119
+
" PATHSEP = package.config:sub(1, 1)\n"
120
+
" EXEDIR = EXEFILE:match(\"^(.+)[/\\\\].*$\")\n"
121
+
" package.path = EXEDIR .. '/data/?.lua;' .. package.path\n"
122
+
" package.path = EXEDIR .. '/data/?/init.lua;' .. package.path\n"
123
+
" core = require('core')\n"
124
+
" core.init()\n"
125
+
" core.run()\n"
126
+
"end, function(err)\n"
127
+
" print('Error: ' .. tostring(err))\n"
128
+
" print(debug.traceback(nil, 2))\n"
129
+
" if core and core.on_error then\n"
130
+
" pcall(core.on_error, err)\n"
131
+
" end\n"
132
+
" os.exit(1)\n"
133
+
"end)");
139
134
140
135
141
-
lua_close(L);
142
-
SDL_DestroyWindow(window);
136
+
lua_close(L);
137
+
SDL_DestroyWindow(window);
143
138
144
-
return EXIT_SUCCESS;
139
+
return EXIT_SUCCESS;
145
140
}
+265
-197
src/rencache.c
+265
-197
src/rencache.c
···
11
11
#define CELL_SIZE 96
12
12
#define COMMAND_BUF_SIZE (1024 * 512)
13
13
14
-
enum { FREE_FONT, SET_CLIP, DRAW_TEXT, DRAW_RECT };
14
+
enum
15
+
{
16
+
FREE_FONT,
17
+
SET_CLIP,
18
+
DRAW_TEXT,
19
+
DRAW_RECT
20
+
};
15
21
16
-
typedef struct {
17
-
int type, size;
18
-
RenRect rect;
19
-
RenColor color;
20
-
RenFont *font;
21
-
int tab_width;
22
-
char text[0];
22
+
typedef struct
23
+
{
24
+
int type, size;
25
+
RenRect rect;
26
+
RenColor color;
27
+
RenFont *font;
28
+
int tab_width;
29
+
char text[0];
23
30
} Command;
24
31
25
32
···
40
47
/* 32bit fnv-1a hash */
41
48
#define HASH_INITIAL 2166136261
42
49
43
-
static void hash(unsigned *h, const void *data, int size) {
44
-
const unsigned char *p = data;
45
-
while (size--) {
46
-
*h = (*h ^ *p++) * 16777619;
47
-
}
50
+
static void hash(unsigned *h, const void *data, int size)
51
+
{
52
+
const unsigned char *p = data;
53
+
while (size--)
54
+
{
55
+
*h = (*h ^ *p++) * 16777619;
56
+
}
48
57
}
49
58
50
59
51
-
static inline int cell_idx(int x, int y) {
52
-
return x + y * CELLS_X;
60
+
static inline int cell_idx(int x, int y)
61
+
{
62
+
return x + y * CELLS_X;
53
63
}
54
64
55
65
56
-
static inline bool rects_overlap(RenRect a, RenRect b) {
57
-
return b.x + b.width >= a.x && b.x <= a.x + a.width
58
-
&& b.y + b.height >= a.y && b.y <= a.y + a.height;
66
+
static inline bool rects_overlap(RenRect a, RenRect b)
67
+
{
68
+
return b.x + b.width >= a.x &&
69
+
b.x <= a.x + a.width &&
70
+
b.y + b.height >= a.y &&
71
+
b.y <= a.y + a.height;
59
72
}
60
73
61
74
62
-
static RenRect intersect_rects(RenRect a, RenRect b) {
63
-
int x1 = max(a.x, b.x);
64
-
int y1 = max(a.y, b.y);
65
-
int x2 = min(a.x + a.width, b.x + b.width);
66
-
int y2 = min(a.y + a.height, b.y + b.height);
67
-
return (RenRect) { x1, y1, max(0, x2 - x1), max(0, y2 - y1) };
75
+
static RenRect intersect_rects(RenRect a, RenRect b)
76
+
{
77
+
int x1 = max(a.x, b.x);
78
+
int y1 = max(a.y, b.y);
79
+
int x2 = min(a.x + a.width, b.x + b.width);
80
+
int y2 = min(a.y + a.height, b.y + b.height);
81
+
return (RenRect){ x1, y1, max(0, x2 - x1), max(0, y2 - y1) };
68
82
}
69
83
70
84
71
-
static RenRect merge_rects(RenRect a, RenRect b) {
72
-
int x1 = min(a.x, b.x);
73
-
int y1 = min(a.y, b.y);
74
-
int x2 = max(a.x + a.width, b.x + b.width);
75
-
int y2 = max(a.y + a.height, b.y + b.height);
76
-
return (RenRect) { x1, y1, x2 - x1, y2 - y1 };
85
+
static RenRect merge_rects(RenRect a, RenRect b)
86
+
{
87
+
int x1 = min(a.x, b.x);
88
+
int y1 = min(a.y, b.y);
89
+
int x2 = max(a.x + a.width, b.x + b.width);
90
+
int y2 = max(a.y + a.height, b.y + b.height);
91
+
return (RenRect){ x1, y1, x2 - x1, y2 - y1 };
77
92
}
78
93
79
94
80
-
static Command* push_command(int type, int size) {
81
-
Command *cmd = (Command*) (command_buf + command_buf_idx);
82
-
int n = command_buf_idx + size;
83
-
if (n > COMMAND_BUF_SIZE) {
84
-
fprintf(stderr, "Warning: (" __FILE__ "): exhausted command buffer\n");
85
-
return NULL;
86
-
}
87
-
command_buf_idx = n;
88
-
memset(cmd, 0, sizeof(Command));
89
-
cmd->type = type;
90
-
cmd->size = size;
91
-
return cmd;
95
+
static Command* push_command(int type, int size)
96
+
{
97
+
Command *cmd = (Command *)(command_buf + command_buf_idx);
98
+
int n = command_buf_idx + size;
99
+
if (n > COMMAND_BUF_SIZE)
100
+
{
101
+
fprintf(stderr, "Warning: (" __FILE__ "): exhausted command buffer\n");
102
+
return NULL;
103
+
}
104
+
command_buf_idx = n;
105
+
memset(cmd, 0, sizeof(Command));
106
+
cmd->type = type;
107
+
cmd->size = size;
108
+
return cmd;
92
109
}
93
110
94
111
95
-
static bool next_command(Command **prev) {
96
-
if (*prev == NULL) {
97
-
*prev = (Command*) command_buf;
98
-
} else {
99
-
*prev = (Command*) (((char*) *prev) + (*prev)->size);
100
-
}
101
-
return *prev != ((Command*) (command_buf + command_buf_idx));
112
+
static bool next_command(Command **prev)
113
+
{
114
+
if (*prev == NULL)
115
+
{
116
+
*prev = (Command *)command_buf;
117
+
}
118
+
else
119
+
{
120
+
*prev = (Command *)(((char *)*prev) + (*prev)->size);
121
+
}
122
+
123
+
return *prev != ((Command *)(command_buf + command_buf_idx));
102
124
}
103
125
104
126
105
-
void rencache_show_debug(bool enable) {
106
-
show_debug = enable;
127
+
void rencache_show_debug(bool enable)
128
+
{
129
+
show_debug = enable;
107
130
}
108
131
109
132
110
-
void rencache_free_font(RenFont *font) {
111
-
Command *cmd = push_command(FREE_FONT, sizeof(Command));
112
-
if (cmd) { cmd->font = font; }
133
+
void rencache_free_font(RenFont *font)
134
+
{
135
+
Command *cmd = push_command(FREE_FONT, sizeof(Command));
136
+
if (cmd)
137
+
{
138
+
cmd->font = font;
139
+
}
113
140
}
114
141
115
142
116
-
void rencache_set_clip_rect(RenRect rect) {
117
-
Command *cmd = push_command(SET_CLIP, sizeof(Command));
118
-
if (cmd) { cmd->rect = intersect_rects(rect, screen_rect); }
143
+
void rencache_set_clip_rect(RenRect rect)
144
+
{
145
+
Command *cmd = push_command(SET_CLIP, sizeof(Command));
146
+
if (cmd)
147
+
{
148
+
cmd->rect = intersect_rects(rect, screen_rect);
149
+
}
119
150
}
120
151
121
152
122
-
void rencache_draw_rect(RenRect rect, RenColor color) {
123
-
if (!rects_overlap(screen_rect, rect)) { return; }
124
-
Command *cmd = push_command(DRAW_RECT, sizeof(Command));
125
-
if (cmd) {
126
-
cmd->rect = rect;
127
-
cmd->color = color;
128
-
}
153
+
void rencache_draw_rect(RenRect rect, RenColor color)
154
+
{
155
+
if (!rects_overlap(screen_rect, rect))
156
+
{
157
+
return;
158
+
}
159
+
Command *cmd = push_command(DRAW_RECT, sizeof(Command));
160
+
if (cmd)
161
+
{
162
+
cmd->rect = rect;
163
+
cmd->color = color;
164
+
}
129
165
}
130
166
131
167
132
-
int rencache_draw_text(RenFont *font, const char *text, int x, int y, RenColor color) {
133
-
RenRect rect;
134
-
rect.x = x;
135
-
rect.y = y;
136
-
rect.width = ren_get_font_width(font, text);
137
-
rect.height = ren_get_font_height(font);
168
+
int rencache_draw_text(RenFont *font, const char *text, int x, int y, RenColor color)
169
+
{
170
+
RenRect rect;
171
+
rect.x = x;
172
+
rect.y = y;
173
+
rect.width = ren_get_font_width(font, text);
174
+
rect.height = ren_get_font_height(font);
138
175
139
-
if (rects_overlap(screen_rect, rect)) {
140
-
int sz = strlen(text) + 1;
141
-
Command *cmd = push_command(DRAW_TEXT, sizeof(Command) + sz);
142
-
if (cmd) {
143
-
memcpy(cmd->text, text, sz);
144
-
cmd->color = color;
145
-
cmd->font = font;
146
-
cmd->rect = rect;
147
-
cmd->tab_width = ren_get_font_tab_width(font);
148
-
}
149
-
}
176
+
if (rects_overlap(screen_rect, rect))
177
+
{
178
+
int sz = strlen(text) + 1;
179
+
Command *cmd = push_command(DRAW_TEXT, sizeof(Command) + sz);
180
+
if (cmd)
181
+
{
182
+
memcpy(cmd->text, text, sz);
183
+
cmd->color = color;
184
+
cmd->font = font;
185
+
cmd->rect = rect;
186
+
cmd->tab_width = ren_get_font_tab_width(font);
187
+
}
188
+
}
150
189
151
-
return x + rect.width;
190
+
return x + rect.width;
152
191
}
153
192
154
193
155
-
void rencache_invalidate(void) {
156
-
memset(cells_prev, 0xff, sizeof(cells_buf1));
194
+
void rencache_invalidate(void)
195
+
{
196
+
memset(cells_prev, 0xff, sizeof(cells_buf1));
157
197
}
158
198
159
199
160
-
void rencache_begin_frame(void) {
161
-
/* reset all cells if the screen width/height has changed */
162
-
int w, h;
163
-
ren_get_size(&w, &h);
164
-
if (screen_rect.width != w || h != screen_rect.height) {
165
-
screen_rect.width = w;
166
-
screen_rect.height = h;
167
-
rencache_invalidate();
168
-
}
200
+
void rencache_begin_frame(void)
201
+
{
202
+
/* reset all cells if the screen width/height has changed */
203
+
int w, h;
204
+
ren_get_size(&w, &h);
205
+
if (screen_rect.width != w || h != screen_rect.height)
206
+
{
207
+
screen_rect.width = w;
208
+
screen_rect.height = h;
209
+
rencache_invalidate();
210
+
}
169
211
}
170
212
171
213
172
-
static void update_overlapping_cells(RenRect r, unsigned h) {
173
-
int x1 = r.x / CELL_SIZE;
174
-
int y1 = r.y / CELL_SIZE;
175
-
int x2 = (r.x + r.width) / CELL_SIZE;
176
-
int y2 = (r.y + r.height) / CELL_SIZE;
214
+
static void update_overlapping_cells(RenRect r, unsigned h)
215
+
{
216
+
int x1 = r.x / CELL_SIZE;
217
+
int y1 = r.y / CELL_SIZE;
218
+
int x2 = (r.x + r.width) / CELL_SIZE;
219
+
int y2 = (r.y + r.height) / CELL_SIZE;
177
220
178
-
for (int y = y1; y <= y2; y++) {
179
-
for (int x = x1; x <= x2; x++) {
180
-
int idx = cell_idx(x, y);
181
-
hash(&cells[idx], &h, sizeof(h));
182
-
}
183
-
}
221
+
for (int y = y1 ; y <= y2 ; y++)
222
+
{
223
+
for (int x = x1 ; x <= x2 ; x++)
224
+
{
225
+
int idx = cell_idx(x, y);
226
+
hash(&cells[idx], &h, sizeof(h));
227
+
}
228
+
}
184
229
}
185
230
186
231
187
-
static void push_rect(RenRect r, int *count) {
188
-
/* try to merge with existing rectangle */
189
-
for (int i = *count - 1; i >= 0; i--) {
190
-
RenRect *rp = &rect_buf[i];
191
-
if (rects_overlap(*rp, r)) {
192
-
*rp = merge_rects(*rp, r);
193
-
return;
194
-
}
195
-
}
196
-
/* couldn't merge with previous rectangle: push */
197
-
rect_buf[(*count)++] = r;
232
+
static void push_rect(RenRect r, int *count)
233
+
{
234
+
/* try to merge with existing rectangle */
235
+
for (int i = *count - 1 ; i >= 0 ; i--)
236
+
{
237
+
RenRect *rp = &rect_buf[i];
238
+
if (rects_overlap(*rp, r))
239
+
{
240
+
*rp = merge_rects(*rp, r);
241
+
return;
242
+
}
243
+
}
244
+
/* couldn't merge with previous rectangle: push */
245
+
rect_buf[(*count)++] = r;
198
246
}
199
247
200
248
201
-
void rencache_end_frame(void) {
202
-
/* update cells from commands */
203
-
Command *cmd = NULL;
204
-
RenRect cr = screen_rect;
205
-
while (next_command(&cmd)) {
206
-
if (cmd->type == SET_CLIP) { cr = cmd->rect; }
207
-
RenRect r = intersect_rects(cmd->rect, cr);
208
-
if (r.width == 0 || r.height == 0) { continue; }
209
-
unsigned h = HASH_INITIAL;
210
-
hash(&h, cmd, cmd->size);
211
-
update_overlapping_cells(r, h);
212
-
}
249
+
void rencache_end_frame(void)
250
+
{
251
+
/* update cells from commands */
252
+
Command *cmd = NULL;
253
+
RenRect cr = screen_rect;
254
+
while (next_command(&cmd))
255
+
{
256
+
if (cmd->type == SET_CLIP)
257
+
{
258
+
cr = cmd->rect;
259
+
}
260
+
RenRect r = intersect_rects(cmd->rect, cr);
261
+
if (r.width == 0 || r.height == 0)
262
+
{
263
+
continue;
264
+
}
265
+
unsigned h = HASH_INITIAL;
266
+
hash(&h, cmd, cmd->size);
267
+
update_overlapping_cells(r, h);
268
+
}
213
269
214
-
/* push rects for all cells changed from last frame, reset cells */
215
-
int rect_count = 0;
216
-
int max_x = screen_rect.width / CELL_SIZE + 1;
217
-
int max_y = screen_rect.height / CELL_SIZE + 1;
218
-
for (int y = 0; y < max_y; y++) {
219
-
for (int x = 0; x < max_x; x++) {
220
-
/* compare previous and current cell for change */
221
-
int idx = cell_idx(x, y);
222
-
if (cells[idx] != cells_prev[idx]) {
223
-
push_rect((RenRect) { x, y, 1, 1 }, &rect_count);
224
-
}
225
-
cells_prev[idx] = HASH_INITIAL;
226
-
}
227
-
}
270
+
/* push rects for all cells changed from last frame, reset cells */
271
+
int rect_count = 0;
272
+
int max_x = screen_rect.width / CELL_SIZE + 1;
273
+
int max_y = screen_rect.height / CELL_SIZE + 1;
274
+
for (int y = 0 ; y < max_y; y++)
275
+
{
276
+
for (int x = 0 ; x < max_x ; x++)
277
+
{
278
+
/* compare previous and current cell for change */
279
+
int idx = cell_idx(x, y);
280
+
if (cells[idx] != cells_prev[idx])
281
+
{
282
+
push_rect((RenRect) { x, y, 1, 1 }, &rect_count);
283
+
}
284
+
cells_prev[idx] = HASH_INITIAL;
285
+
}
286
+
}
228
287
229
-
/* expand rects from cells to pixels */
230
-
for (int i = 0; i < rect_count; i++) {
231
-
RenRect *r = &rect_buf[i];
232
-
r->x *= CELL_SIZE;
233
-
r->y *= CELL_SIZE;
234
-
r->width *= CELL_SIZE;
235
-
r->height *= CELL_SIZE;
236
-
*r = intersect_rects(*r, screen_rect);
237
-
}
288
+
/* expand rects from cells to pixels */
289
+
for (int i = 0; i < rect_count; i++)
290
+
{
291
+
RenRect *r = &rect_buf[i];
292
+
r->x *= CELL_SIZE;
293
+
r->y *= CELL_SIZE;
294
+
r->width *= CELL_SIZE;
295
+
r->height *= CELL_SIZE;
296
+
*r = intersect_rects(*r, screen_rect);
297
+
}
238
298
239
-
/* redraw updated regions */
240
-
bool has_free_commands = false;
241
-
for (int i = 0; i < rect_count; i++) {
242
-
/* draw */
243
-
RenRect r = rect_buf[i];
244
-
ren_set_clip_rect(r);
299
+
/* redraw updated regions */
300
+
bool has_free_commands = false;
301
+
for (int i = 0; i < rect_count; i++)
302
+
{
303
+
/* draw */
304
+
RenRect r = rect_buf[i];
305
+
ren_set_clip_rect(r);
245
306
246
-
cmd = NULL;
247
-
while (next_command(&cmd)) {
248
-
switch (cmd->type) {
249
-
case FREE_FONT:
250
-
has_free_commands = true;
251
-
break;
252
-
case SET_CLIP:
253
-
ren_set_clip_rect(intersect_rects(cmd->rect, r));
254
-
break;
255
-
case DRAW_RECT:
256
-
ren_draw_rect(cmd->rect, cmd->color);
257
-
break;
258
-
case DRAW_TEXT:
259
-
ren_set_font_tab_width(cmd->font, cmd->tab_width);
260
-
ren_draw_text(cmd->font, cmd->text, cmd->rect.x, cmd->rect.y, cmd->color);
261
-
break;
262
-
}
263
-
}
307
+
cmd = NULL;
308
+
while (next_command(&cmd))
309
+
{
310
+
switch (cmd->type)
311
+
{
312
+
case FREE_FONT:
313
+
has_free_commands = true;
314
+
break;
315
+
case SET_CLIP:
316
+
ren_set_clip_rect(intersect_rects(cmd->rect, r));
317
+
break;
318
+
case DRAW_RECT:
319
+
ren_draw_rect(cmd->rect, cmd->color);
320
+
break;
321
+
case DRAW_TEXT:
322
+
ren_set_font_tab_width(cmd->font, cmd->tab_width);
323
+
ren_draw_text(cmd->font, cmd->text, cmd->rect.x, cmd->rect.y, cmd->color);
324
+
break;
325
+
}
326
+
}
264
327
265
-
if (show_debug) {
266
-
RenColor color = { rand(), rand(), rand(), 50 };
267
-
ren_draw_rect(r, color);
268
-
}
269
-
}
328
+
if (show_debug)
329
+
{
330
+
RenColor color = { rand(), rand(), rand(), 50 };
331
+
ren_draw_rect(r, color);
332
+
}
333
+
}
270
334
271
-
/* update dirty rects */
272
-
if (rect_count > 0) {
273
-
ren_update_rects(rect_buf, rect_count);
274
-
}
335
+
/* update dirty rects */
336
+
if (rect_count > 0)
337
+
{
338
+
ren_update_rects(rect_buf, rect_count);
339
+
}
275
340
276
-
/* free fonts */
277
-
if (has_free_commands) {
278
-
cmd = NULL;
279
-
while (next_command(&cmd)) {
280
-
if (cmd->type == FREE_FONT) {
281
-
ren_free_font(cmd->font);
282
-
}
283
-
}
284
-
}
341
+
/* free fonts */
342
+
if (has_free_commands)
343
+
{
344
+
cmd = NULL;
345
+
while (next_command(&cmd))
346
+
{
347
+
if (cmd->type == FREE_FONT)
348
+
{
349
+
ren_free_font(cmd->font);
350
+
}
351
+
}
352
+
}
285
353
286
-
/* swap cell buffer and reset */
287
-
unsigned *tmp = cells;
288
-
cells = cells_prev;
289
-
cells_prev = tmp;
290
-
command_buf_idx = 0;
354
+
/* swap cell buffer and reset */
355
+
unsigned *tmp = cells;
356
+
cells = cells_prev;
357
+
cells_prev = tmp;
358
+
command_buf_idx = 0;
291
359
}
+298
-249
src/renderer.c
+298
-249
src/renderer.c
···
7
7
8
8
#define MAX_GLYPHSET 256
9
9
10
-
struct RenImage {
11
-
RenColor *pixels;
12
-
int width, height;
10
+
struct RenImage
11
+
{
12
+
RenColor *pixels;
13
+
int width, height;
13
14
};
14
15
15
-
typedef struct {
16
-
RenImage *image;
17
-
stbtt_bakedchar glyphs[256];
16
+
typedef struct
17
+
{
18
+
RenImage *image;
19
+
stbtt_bakedchar glyphs[256];
18
20
} GlyphSet;
19
21
20
-
struct RenFont {
21
-
void *data;
22
-
stbtt_fontinfo stbfont;
23
-
GlyphSet *sets[MAX_GLYPHSET];
24
-
float size;
25
-
int height;
22
+
struct RenFont
23
+
{
24
+
void *data;
25
+
stbtt_fontinfo stbfont;
26
+
GlyphSet *sets[MAX_GLYPHSET];
27
+
float size;
28
+
int height;
26
29
};
27
30
28
31
29
32
static SDL_Window *window;
30
-
static struct { int left, top, right, bottom; } clip;
33
+
static struct
34
+
{
35
+
int left, top, right, bottom;
36
+
} clip;
31
37
32
38
33
-
static void* check_alloc(void *ptr) {
34
-
if (!ptr) {
35
-
fprintf(stderr, "Fatal error: memory allocation failed\n");
36
-
exit(EXIT_FAILURE);
37
-
}
38
-
return ptr;
39
+
static void* check_alloc(void *ptr)
40
+
{
41
+
if (!ptr)
42
+
{
43
+
fprintf(stderr, "Fatal error: memory allocation failed\n");
44
+
exit(EXIT_FAILURE);
45
+
}
46
+
return ptr;
39
47
}
40
48
41
49
42
-
static const char* utf8_to_codepoint(const char *p, unsigned *dst) {
43
-
unsigned res, n;
44
-
switch (*p & 0xf0) {
45
-
case 0xf0 : res = *p & 0x07; n = 3; break;
46
-
case 0xe0 : res = *p & 0x0f; n = 2; break;
47
-
case 0xd0 :
48
-
case 0xc0 : res = *p & 0x1f; n = 1; break;
49
-
default : res = *p; n = 0; break;
50
-
}
51
-
while (n--) {
52
-
res = (res << 6) | (*(++p) & 0x3f);
53
-
}
54
-
*dst = res;
55
-
return p + 1;
50
+
static const char* utf8_to_codepoint(const char *p, unsigned *dst)
51
+
{
52
+
unsigned res, n;
53
+
switch (*p & 0xf0)
54
+
{
55
+
case 0xf0 : res = *p & 0x07; n = 3; break;
56
+
case 0xe0 : res = *p & 0x0f; n = 2; break;
57
+
case 0xd0 :
58
+
case 0xc0 : res = *p & 0x1f; n = 1; break;
59
+
default : res = *p; n = 0; break;
60
+
}
61
+
while (n--)
62
+
res = (res << 6) | (*(++p) & 0x3f);
63
+
*dst = res;
64
+
return p + 1;
56
65
}
57
66
58
67
59
-
void ren_init(SDL_Window *win) {
60
-
assert(win);
61
-
window = win;
62
-
SDL_Surface *surf = SDL_GetWindowSurface(window);
63
-
ren_set_clip_rect( (RenRect) { 0, 0, surf->w, surf->h } );
68
+
void ren_init(SDL_Window *win)
69
+
{
70
+
assert(win);
71
+
window = win;
72
+
SDL_Surface *surf = SDL_GetWindowSurface(window);
73
+
ren_set_clip_rect((RenRect){ 0, 0, surf->w, surf->h });
64
74
}
65
75
66
76
67
-
void ren_update_rects(RenRect *rects, int count) {
68
-
SDL_UpdateWindowSurfaceRects(window, (SDL_Rect*) rects, count);
69
-
static bool initial_frame = true;
70
-
if (initial_frame) {
71
-
SDL_ShowWindow(window);
72
-
initial_frame = false;
73
-
}
77
+
void ren_update_rects(RenRect *rects, int count)
78
+
{
79
+
SDL_UpdateWindowSurfaceRects(window, (SDL_Rect *)rects, count);
80
+
static bool initial_frame = true;
81
+
if (initial_frame)
82
+
{
83
+
SDL_ShowWindow(window);
84
+
initial_frame = false;
85
+
}
74
86
}
75
87
76
88
77
-
void ren_set_clip_rect(RenRect rect) {
78
-
clip.left = rect.x;
79
-
clip.top = rect.y;
80
-
clip.right = rect.x + rect.width;
81
-
clip.bottom = rect.y + rect.height;
89
+
void ren_set_clip_rect(RenRect rect)
90
+
{
91
+
clip.left = rect.x;
92
+
clip.top = rect.y;
93
+
clip.right = rect.x + rect.width;
94
+
clip.bottom = rect.y + rect.height;
82
95
}
83
96
84
97
85
-
void ren_get_size(int *x, int *y) {
86
-
SDL_Surface *surf = SDL_GetWindowSurface(window);
87
-
*x = surf->w;
88
-
*y = surf->h;
98
+
void ren_get_size(int *x, int *y)
99
+
{
100
+
SDL_Surface *surf = SDL_GetWindowSurface(window);
101
+
*x = surf->w;
102
+
*y = surf->h;
89
103
}
90
104
91
105
92
-
RenImage* ren_new_image(int width, int height) {
93
-
assert(width > 0 && height > 0);
94
-
RenImage *image = malloc(sizeof(RenImage) + width * height * sizeof(RenColor));
95
-
check_alloc(image);
96
-
image->pixels = (void*) (image + 1);
97
-
image->width = width;
98
-
image->height = height;
99
-
return image;
106
+
RenImage* ren_new_image(int width, int height)
107
+
{
108
+
assert(width > 0 && height > 0);
109
+
RenImage *image = malloc(sizeof(RenImage) + width * height * sizeof(RenColor));
110
+
check_alloc(image);
111
+
image->pixels = (void *)(image + 1);
112
+
image->width = width;
113
+
image->height = height;
114
+
return image;
100
115
}
101
116
102
117
103
-
void ren_free_image(RenImage *image) {
104
-
free(image);
118
+
void ren_free_image(RenImage *image)
119
+
{
120
+
free(image);
105
121
}
106
122
107
123
108
-
static GlyphSet* load_glyphset(RenFont *font, int idx) {
109
-
GlyphSet *set = check_alloc(calloc(1, sizeof(GlyphSet)));
124
+
static GlyphSet* load_glyphset(RenFont *font, int idx)
125
+
{
126
+
GlyphSet *set = check_alloc(calloc(1, sizeof(GlyphSet)));
110
127
111
-
/* init image */
112
-
int width = 128;
113
-
int height = 128;
128
+
/* init image */
129
+
int width = 128;
130
+
int height = 128;
114
131
retry:
115
-
set->image = ren_new_image(width, height);
132
+
set->image = ren_new_image(width, height);
116
133
117
-
/* load glyphs */
118
-
float s =
119
-
stbtt_ScaleForMappingEmToPixels(&font->stbfont, 1) /
120
-
stbtt_ScaleForPixelHeight(&font->stbfont, 1);
121
-
int res = stbtt_BakeFontBitmap(
122
-
font->data, 0, font->size * s, (void*) set->image->pixels,
123
-
width, height, idx * 256, 256, set->glyphs);
134
+
/* load glyphs */
135
+
float s =
136
+
stbtt_ScaleForMappingEmToPixels(&font->stbfont, 1) /
137
+
stbtt_ScaleForPixelHeight(&font->stbfont, 1);
138
+
int res = stbtt_BakeFontBitmap(
139
+
font->data, 0, font->size * s, (void *)set->image->pixels,
140
+
width, height, idx * 256, 256, set->glyphs);
124
141
125
-
/* retry with a larger image buffer if the buffer wasn't large enough */
126
-
if (res < 0) {
127
-
width *= 2;
128
-
height *= 2;
129
-
ren_free_image(set->image);
130
-
goto retry;
131
-
}
142
+
/* retry with a larger image buffer if the buffer wasn't large enough */
143
+
if (res < 0)
144
+
{
145
+
width *= 2;
146
+
height *= 2;
147
+
ren_free_image(set->image);
148
+
goto retry;
149
+
}
132
150
133
-
/* adjust glyph yoffsets and xadvance */
134
-
int ascent, descent, linegap;
135
-
stbtt_GetFontVMetrics(&font->stbfont, &ascent, &descent, &linegap);
136
-
float scale = stbtt_ScaleForMappingEmToPixels(&font->stbfont, font->size);
137
-
int scaled_ascent = ascent * scale + 0.5;
138
-
for (int i = 0; i < 256; i++) {
139
-
set->glyphs[i].yoff += scaled_ascent;
140
-
set->glyphs[i].xadvance = floor(set->glyphs[i].xadvance);
141
-
}
151
+
/* adjust glyph yoffsets and xadvance */
152
+
int ascent, descent, linegap;
153
+
stbtt_GetFontVMetrics(&font->stbfont, &ascent, &descent, &linegap);
154
+
float scale = stbtt_ScaleForMappingEmToPixels(&font->stbfont, font->size);
155
+
int scaled_ascent = ascent * scale + 0.5;
156
+
for (int i = 0; i < 256; i++)
157
+
{
158
+
set->glyphs[i].yoff += scaled_ascent;
159
+
set->glyphs[i].xadvance = floor(set->glyphs[i].xadvance);
160
+
}
142
161
143
-
/* convert 8bit data to 32bit */
144
-
for (int i = width * height - 1; i >= 0; i--) {
145
-
uint8_t n = *((uint8_t*) set->image->pixels + i);
146
-
set->image->pixels[i] = (RenColor) { .r = 255, .g = 255, .b = 255, .a = n };
147
-
}
162
+
/* convert 8bit data to 32bit */
163
+
for (int i = width * height - 1; i >= 0; i--)
164
+
{
165
+
uint8_t n = *((uint8_t *)set->image->pixels + i);
166
+
set->image->pixels[i] = (RenColor) { .r = 255, .g = 255, .b = 255, .a = n };
167
+
}
148
168
149
-
return set;
169
+
return set;
150
170
}
151
171
152
172
153
-
static GlyphSet* get_glyphset(RenFont *font, int codepoint) {
154
-
int idx = (codepoint >> 8) % MAX_GLYPHSET;
155
-
if (!font->sets[idx]) {
156
-
font->sets[idx] = load_glyphset(font, idx);
157
-
}
158
-
return font->sets[idx];
173
+
static GlyphSet* get_glyphset(RenFont *font, int codepoint)
174
+
{
175
+
int idx = (codepoint >> 8) % MAX_GLYPHSET;
176
+
if (!font->sets[idx])
177
+
font->sets[idx] = load_glyphset(font, idx);
178
+
return font->sets[idx];
159
179
}
160
180
161
181
162
-
RenFont* ren_load_font(const char *filename, float size) {
163
-
RenFont *font = NULL;
164
-
FILE *fp = NULL;
182
+
RenFont* ren_load_font(const char *filename, float size)
183
+
{
184
+
RenFont *font = NULL;
185
+
FILE *fp = NULL;
165
186
166
-
/* init font */
167
-
font = check_alloc(calloc(1, sizeof(RenFont)));
168
-
font->size = size;
187
+
/* init font */
188
+
font = check_alloc(calloc(1, sizeof(RenFont)));
189
+
font->size = size;
169
190
170
-
/* load font into buffer */
171
-
fp = fopen(filename, "rb");
172
-
if (!fp) { return NULL; }
173
-
/* get size */
174
-
fseek(fp, 0, SEEK_END); int buf_size = ftell(fp); fseek(fp, 0, SEEK_SET);
175
-
/* load */
176
-
font->data = check_alloc(malloc(buf_size));
177
-
int _ = fread(font->data, 1, buf_size, fp); (void) _;
178
-
fclose(fp);
179
-
fp = NULL;
191
+
/* load font into buffer */
192
+
fp = fopen(filename, "rb");
193
+
if (!fp)
194
+
return NULL;
195
+
/* get size */
196
+
fseek(fp, 0, SEEK_END);
197
+
int buf_size = ftell(fp);
198
+
fseek(fp, 0, SEEK_SET);
199
+
/* load */
200
+
font->data = check_alloc(malloc(buf_size));
201
+
(void)fread(font->data, 1, buf_size, fp);
202
+
fclose(fp);
203
+
fp = NULL;
180
204
181
-
/* init stbfont */
182
-
int ok = stbtt_InitFont(&font->stbfont, font->data, 0);
183
-
if (!ok) { goto fail; }
205
+
/* init stbfont */
206
+
int ok = stbtt_InitFont(&font->stbfont, font->data, 0);
207
+
if (!ok)
208
+
goto fail;
184
209
185
-
/* get height and scale */
186
-
int ascent, descent, linegap;
187
-
stbtt_GetFontVMetrics(&font->stbfont, &ascent, &descent, &linegap);
188
-
float scale = stbtt_ScaleForMappingEmToPixels(&font->stbfont, size);
189
-
font->height = (ascent - descent + linegap) * scale + 0.5;
210
+
/* get height and scale */
211
+
int ascent, descent, linegap;
212
+
stbtt_GetFontVMetrics(&font->stbfont, &ascent, &descent, &linegap);
213
+
float scale = stbtt_ScaleForMappingEmToPixels(&font->stbfont, size);
214
+
font->height = (ascent - descent + linegap) * scale + 0.5;
190
215
191
-
/* make tab and newline glyphs invisible */
192
-
stbtt_bakedchar *g = get_glyphset(font, '\n')->glyphs;
193
-
g['\t'].x1 = g['\t'].x0;
194
-
g['\n'].x1 = g['\n'].x0;
216
+
/* make tab and newline glyphs invisible */
217
+
stbtt_bakedchar *g = get_glyphset(font, '\n')->glyphs;
218
+
g['\t'].x1 = g['\t'].x0;
219
+
g['\n'].x1 = g['\n'].x0;
195
220
196
-
return font;
221
+
return font;
197
222
198
223
fail:
199
-
if (fp) { fclose(fp); }
200
-
if (font) { free(font->data); }
201
-
free(font);
202
-
return NULL;
224
+
if (fp)
225
+
fclose(fp);
226
+
if (font)
227
+
free(font->data);
228
+
free(font);
229
+
return NULL;
203
230
}
204
231
205
232
206
-
void ren_free_font(RenFont *font) {
207
-
for (int i = 0; i < MAX_GLYPHSET; i++) {
208
-
GlyphSet *set = font->sets[i];
209
-
if (set) {
210
-
ren_free_image(set->image);
211
-
free(set);
212
-
}
213
-
}
214
-
free(font->data);
215
-
free(font);
233
+
void ren_free_font(RenFont *font)
234
+
{
235
+
for (int i = 0 ; i < MAX_GLYPHSET ; i++)
236
+
{
237
+
GlyphSet *set = font->sets[i];
238
+
if (set)
239
+
{
240
+
ren_free_image(set->image);
241
+
free(set);
242
+
}
243
+
}
244
+
free(font->data);
245
+
free(font);
216
246
}
217
247
218
248
219
-
void ren_set_font_tab_width(RenFont *font, int n) {
220
-
GlyphSet *set = get_glyphset(font, '\t');
221
-
set->glyphs['\t'].xadvance = n;
249
+
void ren_set_font_tab_width(RenFont *font, int n)
250
+
{
251
+
GlyphSet *set = get_glyphset(font, '\t');
252
+
set->glyphs['\t'].xadvance = n;
222
253
}
223
254
224
255
225
-
int ren_get_font_tab_width(RenFont *font) {
226
-
GlyphSet *set = get_glyphset(font, '\t');
227
-
return set->glyphs['\t'].xadvance;
256
+
int ren_get_font_tab_width(RenFont *font)
257
+
{
258
+
GlyphSet *set = get_glyphset(font, '\t');
259
+
return set->glyphs['\t'].xadvance;
228
260
}
229
261
230
262
231
-
int ren_get_font_width(RenFont *font, const char *text) {
232
-
int x = 0;
233
-
const char *p = text;
234
-
unsigned codepoint;
235
-
while (*p) {
236
-
p = utf8_to_codepoint(p, &codepoint);
237
-
GlyphSet *set = get_glyphset(font, codepoint);
238
-
stbtt_bakedchar *g = &set->glyphs[codepoint & 0xff];
239
-
x += g->xadvance;
240
-
}
241
-
return x;
263
+
int ren_get_font_width(RenFont *font, const char *text)
264
+
{
265
+
int x = 0;
266
+
const char *p = text;
267
+
unsigned codepoint;
268
+
while (*p)
269
+
{
270
+
p = utf8_to_codepoint(p, &codepoint);
271
+
GlyphSet *set = get_glyphset(font, codepoint);
272
+
stbtt_bakedchar *g = &set->glyphs[codepoint & 0xff];
273
+
x += g->xadvance;
274
+
}
275
+
return x;
242
276
}
243
277
244
278
245
-
int ren_get_font_height(RenFont *font) {
246
-
return font->height;
279
+
int ren_get_font_height(RenFont *font)
280
+
{
281
+
return font->height;
247
282
}
248
283
249
284
250
-
static inline RenColor blend_pixel(RenColor dst, RenColor src) {
251
-
int ia = 0xff - src.a;
252
-
dst.r = ((src.r * src.a) + (dst.r * ia)) >> 8;
253
-
dst.g = ((src.g * src.a) + (dst.g * ia)) >> 8;
254
-
dst.b = ((src.b * src.a) + (dst.b * ia)) >> 8;
255
-
return dst;
285
+
static inline RenColor blend_pixel(RenColor dst, RenColor src)
286
+
{
287
+
int ia = 0xff - src.a;
288
+
dst.r = ((src.r * src.a) + (dst.r * ia)) >> 8;
289
+
dst.g = ((src.g * src.a) + (dst.g * ia)) >> 8;
290
+
dst.b = ((src.b * src.a) + (dst.b * ia)) >> 8;
291
+
return dst;
256
292
}
257
293
258
294
259
-
static inline RenColor blend_pixel2(RenColor dst, RenColor src, RenColor color) {
260
-
src.a = (src.a * color.a) >> 8;
261
-
int ia = 0xff - src.a;
262
-
dst.r = ((src.r * color.r * src.a) >> 16) + ((dst.r * ia) >> 8);
263
-
dst.g = ((src.g * color.g * src.a) >> 16) + ((dst.g * ia) >> 8);
264
-
dst.b = ((src.b * color.b * src.a) >> 16) + ((dst.b * ia) >> 8);
265
-
return dst;
295
+
static inline RenColor blend_pixel2(RenColor dst, RenColor src, RenColor color)
296
+
{
297
+
src.a = (src.a * color.a) >> 8;
298
+
int ia = 0xff - src.a;
299
+
dst.r = ((src.r * color.r * src.a) >> 16) + ((dst.r * ia) >> 8);
300
+
dst.g = ((src.g * color.g * src.a) >> 16) + ((dst.g * ia) >> 8);
301
+
dst.b = ((src.b * color.b * src.a) >> 16) + ((dst.b * ia) >> 8);
302
+
return dst;
266
303
}
267
304
268
305
269
-
#define rect_draw_loop(expr) \
270
-
for (int j = y1; j < y2; j++) { \
271
-
for (int i = x1; i < x2; i++) { \
272
-
*d = expr; \
273
-
d++; \
274
-
} \
275
-
d += dr; \
276
-
}
306
+
#define rect_draw_loop(expr) \
307
+
for (int j = y1 ; j < y2 ; j++) \
308
+
{ \
309
+
for (int i = x1 ; i < x2 ; i++) \
310
+
{ \
311
+
*d = expr; \
312
+
d++; \
313
+
} \
314
+
d += dr; \
315
+
}
277
316
278
-
void ren_draw_rect(RenRect rect, RenColor color) {
279
-
if (color.a == 0) { return; }
317
+
void ren_draw_rect(RenRect rect, RenColor color)
318
+
{
319
+
if (color.a == 0)
320
+
return;
280
321
281
-
int x1 = rect.x < clip.left ? clip.left : rect.x;
282
-
int y1 = rect.y < clip.top ? clip.top : rect.y;
283
-
int x2 = rect.x + rect.width;
284
-
int y2 = rect.y + rect.height;
285
-
x2 = x2 > clip.right ? clip.right : x2;
286
-
y2 = y2 > clip.bottom ? clip.bottom : y2;
322
+
int x1 = rect.x < clip.left ? clip.left : rect.x;
323
+
int y1 = rect.y < clip.top ? clip.top : rect.y;
324
+
int x2 = rect.x + rect.width;
325
+
int y2 = rect.y + rect.height;
326
+
x2 = x2 > clip.right ? clip.right : x2;
327
+
y2 = y2 > clip.bottom ? clip.bottom : y2;
287
328
288
-
SDL_Surface *surf = SDL_GetWindowSurface(window);
289
-
RenColor *d = (RenColor*) surf->pixels;
290
-
d += x1 + y1 * surf->w;
291
-
int dr = surf->w - (x2 - x1);
329
+
SDL_Surface *surf = SDL_GetWindowSurface(window);
330
+
RenColor *d = (RenColor *)surf->pixels;
331
+
d += x1 + y1 * surf->w;
332
+
int dr = surf->w - (x2 - x1);
292
333
293
-
if (color.a == 0xff) {
294
-
rect_draw_loop(color);
295
-
} else {
296
-
rect_draw_loop(blend_pixel(*d, color));
297
-
}
334
+
if (color.a == 0xff)
335
+
{
336
+
rect_draw_loop(color);
337
+
}
338
+
else
339
+
{
340
+
rect_draw_loop(blend_pixel(*d, color));
341
+
}
298
342
}
299
343
300
344
301
-
void ren_draw_image(RenImage *image, RenRect *sub, int x, int y, RenColor color) {
302
-
if (color.a == 0) { return; }
345
+
void ren_draw_image(RenImage *image, RenRect *sub, int x, int y, RenColor color)
346
+
{
347
+
if (color.a == 0)
348
+
return;
303
349
304
-
/* clip */
305
-
int n;
306
-
if ((n = clip.left - x) > 0) { sub->width -= n; sub->x += n; x += n; }
307
-
if ((n = clip.top - y) > 0) { sub->height -= n; sub->y += n; y += n; }
308
-
if ((n = x + sub->width - clip.right ) > 0) { sub->width -= n; }
309
-
if ((n = y + sub->height - clip.bottom) > 0) { sub->height -= n; }
350
+
/* clip */
351
+
int n;
352
+
if ((n = clip.left - x) > 0) { sub->width -= n; sub->x += n; x += n; }
353
+
if ((n = clip.top - y) > 0) { sub->height -= n; sub->y += n; y += n; }
354
+
if ((n = x + sub->width - clip.right ) > 0) { sub->width -= n; }
355
+
if ((n = y + sub->height - clip.bottom) > 0) { sub->height -= n; }
310
356
311
-
if (sub->width <= 0 || sub->height <= 0) {
312
-
return;
313
-
}
357
+
if (sub->width <= 0 || sub->height <= 0)
358
+
return;
314
359
315
-
/* draw */
316
-
SDL_Surface *surf = SDL_GetWindowSurface(window);
317
-
RenColor *s = image->pixels;
318
-
RenColor *d = (RenColor*) surf->pixels;
319
-
s += sub->x + sub->y * image->width;
320
-
d += x + y * surf->w;
321
-
int sr = image->width - sub->width;
322
-
int dr = surf->w - sub->width;
360
+
/* draw */
361
+
SDL_Surface *surf = SDL_GetWindowSurface(window);
362
+
RenColor *s = image->pixels;
363
+
RenColor *d = (RenColor *)surf->pixels;
364
+
s += sub->x + sub->y * image->width;
365
+
d += x + y * surf->w;
366
+
int sr = image->width - sub->width;
367
+
int dr = surf->w - sub->width;
323
368
324
-
for (int j = 0; j < sub->height; j++) {
325
-
for (int i = 0; i < sub->width; i++) {
326
-
*d = blend_pixel2(*d, *s, color);
327
-
d++;
328
-
s++;
329
-
}
330
-
d += dr;
331
-
s += sr;
332
-
}
369
+
for (int j = 0; j < sub->height; j++)
370
+
{
371
+
for (int i = 0; i < sub->width; i++)
372
+
{
373
+
*d = blend_pixel2(*d, *s, color);
374
+
d++;
375
+
s++;
376
+
}
377
+
d += dr;
378
+
s += sr;
379
+
}
333
380
}
334
381
335
382
336
-
int ren_draw_text(RenFont *font, const char *text, int x, int y, RenColor color) {
337
-
RenRect rect;
338
-
const char *p = text;
339
-
unsigned codepoint;
340
-
while (*p) {
341
-
p = utf8_to_codepoint(p, &codepoint);
342
-
GlyphSet *set = get_glyphset(font, codepoint);
343
-
stbtt_bakedchar *g = &set->glyphs[codepoint & 0xff];
344
-
rect.x = g->x0;
345
-
rect.y = g->y0;
346
-
rect.width = g->x1 - g->x0;
347
-
rect.height = g->y1 - g->y0;
348
-
ren_draw_image(set->image, &rect, x + g->xoff, y + g->yoff, color);
349
-
x += g->xadvance;
350
-
}
351
-
return x;
383
+
int ren_draw_text(RenFont *font, const char *text, int x, int y, RenColor color)
384
+
{
385
+
RenRect rect;
386
+
const char *p = text;
387
+
unsigned codepoint;
388
+
while (*p)
389
+
{
390
+
p = utf8_to_codepoint(p, &codepoint);
391
+
GlyphSet *set = get_glyphset(font, codepoint);
392
+
stbtt_bakedchar *g = &set->glyphs[codepoint & 0xff];
393
+
rect.x = g->x0;
394
+
rect.y = g->y0;
395
+
rect.width = g->x1 - g->x0;
396
+
rect.height = g->y1 - g->y0;
397
+
ren_draw_image(set->image, &rect, x + g->xoff, y + g->yoff, color);
398
+
x += g->xadvance;
399
+
}
400
+
return x;
352
401
}
+11
-3
src/renderer.h
+11
-3
src/renderer.h
···
1
1
#ifndef RENDERER_H
2
2
#define RENDERER_H
3
3
4
-
#include <SDL2/SDL.h>
4
+
#include <SDL3/SDL.h>
5
+
#include <stdlib.h>
5
6
#include <stdint.h>
6
7
7
8
typedef struct RenImage RenImage;
8
9
typedef struct RenFont RenFont;
9
10
10
-
typedef struct { uint8_t b, g, r, a; } RenColor;
11
-
typedef struct { int x, y, width, height; } RenRect;
11
+
typedef struct
12
+
{
13
+
uint8_t b, g, r, a;
14
+
} RenColor;
15
+
16
+
typedef struct
17
+
{
18
+
int x, y, width, height;
19
+
} RenRect;
12
20
13
21
14
22
void ren_init(SDL_Window *win);