Browse code

Port to SDL3

Dario Rodriguez authored on 16/10/2024 18:40:40
Showing 5 changed files
... ...
@@ -1,4 +1,5 @@
1 1
 *.reu
2
+errors.txt
2 3
 toolchain-zig
3 4
 toolchain-zig-dl
4 5
 toolchain-emscripten
... ...
@@ -1,6 +1,6 @@
1 1
 CC=gcc
2
-CFLAGS=-Wall -g -I/usr/include/SDL2 -DLINUX
3
-LDFLAGS=-lSDL2_ttf -lSDL2
2
+CFLAGS=-Wall -g -Isdl3/SDL-preview-3.1.3/include -Isdl3/SDL_ttf/include -DLINUX
3
+LDFLAGS=sdl3/libSDL3.so sdl3/libSDL3_ttf.so
4 4
 
5 5
 all: boxui_demo_helloworld boxui_demo_helloworld.exe boxui_demo_helloworld.html
6 6
 
... ...
@@ -24,14 +24,14 @@ boxui-windows.o: boxui.c boxui.h notosans_regular_ttf.c notosans_regular_ttf.h
24 24
 # boxui-html.o: html5
25 25
 
26 26
 boxui-html.o: boxui.c boxui.h notosans_regular_ttf.c notosans_regular_ttf.h
27
-	sh -c ". toolchain-emscripten/env.sh ; emcc -g -Wall -s USE_SDL=2 -s USE_SDL_TTF=2 boxui.c -c -o boxui-html.o"
27
+	sh -c ". toolchain-emscripten/env.sh ; emcc -g -Wall -s USE_SDL=3 -s USE_SDL_TTF=3 boxui.c -c -o boxui-html.o"
28 28
 
29 29
 # boxui_demo_helloworld: linux
30 30
 
31 31
 boxui_demo_helloworld.o: boxui_demo_helloworld.c boxui.h
32 32
 
33 33
 boxui_demo_helloworld: boxui.o boxui_demo_helloworld.o
34
-	gcc boxui_demo_helloworld.o boxui.o -o boxui_demo_helloworld -lSDL2_ttf -lSDL2
34
+	gcc boxui_demo_helloworld.o boxui.o $(LDFLAGS) -o boxui_demo_helloworld 
35 35
 
36 36
 # boxui_demo_helloworld: windows
37 37
 
... ...
@@ -44,10 +44,10 @@ boxui_demo_helloworld.exe: boxui-icon_256x256.png boxui-windows.o boxui_demo_hel
44 44
 # boxui_demo_helloworld: html5
45 45
 
46 46
 boxui_demo_helloworld-html.o: boxui_demo_helloworld.c
47
-	sh -c ". toolchain-emscripten/env.sh ; emcc -g -Wall -s USE_SDL=2 -s USE_SDL_TTF=2 boxui_demo_helloworld.c -c -o boxui_demo_helloworld-html.o"
47
+	sh -c ". toolchain-emscripten/env.sh ; emcc -g -Wall -s USE_SDL=3 -s USE_SDL_TTF=3 boxui_demo_helloworld.c -c -o boxui_demo_helloworld-html.o"
48 48
 
49 49
 boxui_demo_helloworld.html: boxui-html.template boxui-html.o boxui_demo_helloworld-html.o
50
-	sh -c ". toolchain-emscripten/env.sh ; emcc boxui_demo_helloworld-html.o boxui-html.o -o boxui_demo_helloworld.html -s USE_SDL=2 -s USE_SDL_TTF=2 && sed s/PROGRAMNAME/boxui_demo_helloworld/g < boxui-html.template > boxui_demo_helloworld.html && zip -pr boxui_demo_helloworld-html.zip boxui_demo_helloworld.html boxui_demo_helloworld.js boxui_demo_helloworld.wasm"
50
+	sh -c ". toolchain-emscripten/env.sh ; emcc boxui_demo_helloworld-html.o boxui-html.o -o boxui_demo_helloworld.html -s USE_SDL=3 -s USE_SDL_TTF=3 && sed s/PROGRAMNAME/boxui_demo_helloworld/g < boxui-html.template > boxui_demo_helloworld.html && zip -pr boxui_demo_helloworld-html.zip boxui_demo_helloworld.html boxui_demo_helloworld.js boxui_demo_helloworld.wasm"
51 51
 
52 52
 clean:
53 53
 	rm -f *.o *.js *.html *.wasm *.exe \
... ...
@@ -1,10 +1,10 @@
1 1
 /*
2 2
  * boxui.c
3 3
  *
4
- * Multiplatform UI library for SDL2.
4
+ * Multiplatform UI library for SDL3.
5 5
  *
6
- * (c) 2023 Dario Rodriguez <antartica@box-ui.org>
7
- * Licensed under the terms of the GNU GPL v3.
6
+ * (c) 2023-2024 Dario Rodriguez <antartica@box-ui.org>
7
+ * Licensed under the terms of the MIT/X license.
8 8
  */
9 9
 
10 10
 #include <stdio.h>
... ...
@@ -13,287 +13,337 @@
13 13
 #include <string.h>
14 14
 #include <time.h>
15 15
 #include <signal.h>
16
+#include <stdarg.h>
16 17
 
17
-#include "SDL.h"
18
-#include "SDL_rwops.h"
19
-#include "SDL_ttf.h"
18
+#include "SDL3/SDL.h"
19
+#include "SDL3/SDL_iostream.h"
20
+#include "SDL3_ttf/SDL_ttf.h"
20 21
 
21 22
 #include "boxui.h"
22 23
 
23 24
 #include "notosans_regular_ttf.c"
24 25
 
25
-#define DEFAULT_FPS 30
26
+#define DEFAULTFONTSIZE 16
27
+
28
+#define MAXPENDINGSIGNAL 64
29
+#define BLOCKSIGNALACTION 16
30
+#define BLOCKWINDOW 8
31
+
32
+#ifdef DEBUG_BOXUI
33
+#define DEBUGFPRINTF(a) fprintf a
34
+#else
35
+#define DEBUGFPRINTF(a)
36
+#endif
37
+
38
+typedef enum datatype_t {
39
+        datatype_literal=0, /* inline string */
40
+        datatype_escapedquotedliteral, /* (only used when parsing) inline quoted string */
41
+        datatype_quotedliteral, /* quoted string (%s or unescaping escapedquotedliteral) */
42
+        datatype_integer, /* (only used when parsing) %i */
43
+        datatype_textvariable, /* %s%i */
44
+        datatype_asset, /* %p%i%i */
45
+        datatype_callback, /* %p%p */
46
+} datatype_t;
47
+
48
+typedef struct signalaction_t {
49
+        int nsignal;
50
+        char *actionstr;
51
+} signalaction_t;
52
+
53
+typedef struct signaldata_t {
54
+        int readpos;
55
+        int writepos;
56
+        int buf[MAXPENDINGSIGNAL];
57
+        int sizeactions;
58
+        int usedactions;
59
+        signalaction_t *actions;
60
+} signaldata_t;
26 61
 
27 62
 typedef struct intboxui_t {
28
-        char *title;
29
-        int defaultw,defaulth;
30
-        int fps;
31
-        long long fpsepoch;
32
-        long long fpsepochframeno;
33
-        void *userptr;
34
-        int isdirty;
35
-        long long lastrenderedframeno;
36
-        int sizeafterbuf;
37
-        int usedafterbuf;
38
-        char *afterbuf;
39
-        /* temporary members (to be able to test) */
40
-        int screenw;
41
-        int screenh;
42
-        SDL_Window *win;
63
+        SDL_Window *window;
43 64
         SDL_Renderer *renderer;
44
-        SDL_RWops *defaultfontdata;
65
+        int width;
66
+        int height;
67
+        signaldata_t signaldata;
68
+        SDL_IOStream *defaultfontdata;
45 69
         TTF_Font *defaultfont;
46
-        int defaultfontheight;
47 70
         int defaultfontwidth;
71
+        int defaultfontheight;
72
+        void *userptr;
73
+        int isdirty;
74
+        int haschanged;
75
+        SDL_Texture *texture;
76
+        /* temporary members (to be able to test) */
48 77
         char currenttext[1024];
49 78
         char currentclickevent[1024];
50 79
         char currentactionstr[1024];
51 80
         int flag_currentactionstrused;
52
-        /* end of temporary members (to be able to test) */
53 81
 } intboxui_t;
54 82
 
55
-int intboxui_waittick(intboxui_t *boxui);
56
-int intboxui_render(intboxui_t *boxui);
57
-int intboxui_after_doexpired(intboxui_t *boxui);
83
+static void intboxui_signalhandler_gen(int nsignal, int is_set, intboxui_t *boxuiset);
84
+static int intboxui_render(intboxui_t *boxui);
85
+static char *intboxuiutil_getnext(char *data, int *posdata, va_list valist, int *resl, datatype_t *datatype, char **ptr1, char **ptr2, int *int1, int *int2, int *in_error);
86
+static char *datatypedup_literalquotedliteral(datatype_t datatype, char *ptr1, char *ptr2, int int1, int int2);
87
+static int datatypedup_int(datatype_t datatype, char *ptr1, char *ptr2, int int1, int int2, int defaultint, int *in_error);
88
+static int datatypedup_istrue(datatype_t datatype, char *ptr1, char *ptr2, int int1, int int2, int *in_error);
89
+static int memstrcmp(char *ptr, int l, char *str);
58 90
 
59 91
 boxui_t *
60
-boxui_init(char *title,int defaultw, int defaulth, int flags)
92
+boxui_init(SDL_Window *window, SDL_Renderer *renderer, int width, int height)
61 93
 {
62 94
         intboxui_t *boxui;
63
-        title=(title==NULL)?"":title;
64
-        if((boxui=malloc(sizeof(intboxui_t)))==NULL)
95
+        if((boxui=malloc(sizeof(intboxui_t)))==NULL) {
96
+                SDL_Log("boxui: insufficient memory for main structure\n");
65 97
                 return(NULL); /* insuf. mem for boxui struct */
66
-        memset(boxui,0,sizeof(intboxui_t));
67
-        if((boxui->title=strdup(title))==NULL) {
68
-                boxui_free((boxui_t *)boxui),boxui=NULL;
69
-                return(NULL); /* insuf. mem for title string */
70
-        }
71
-        /* temporary initialization (to be able to test) */
72
-        if(SDL_Init(SDL_INIT_VIDEO)<0
73
-          || (boxui->win=SDL_CreateWindow(title,
74
-            SDL_WINDOWPOS_UNDEFINED,SDL_WINDOWPOS_UNDEFINED,
75
-            defaultw,defaulth,0))==NULL
76
-          || (boxui->renderer=SDL_CreateRenderer(boxui->win,-1,
77
-            SDL_RENDERER_ACCELERATED|SDL_RENDERER_PRESENTVSYNC))==NULL) {
78
-                boxui_free(boxui),boxui=NULL;
79
-                return(NULL); /* ERROR: Couldn't init video */
80
-        }
81
-        boxui->screenw=defaultw,boxui->screenh=defaulth;
82
-        if((boxui->defaultfontdata=SDL_RWFromConstMem(notosans_regular_ttf,notosans_regular_ttf_len))==NULL
83
-          || TTF_Init()==-1) {
84
-                boxui_free(boxui),boxui=NULL;
85
-                return(NULL); /* ERROR: Couldn't init font data */
86 98
         }
87
-        SDL_RWseek(boxui->defaultfontdata,0,RW_SEEK_SET);
88
-        if(boxui->defaultfontdata==NULL
89
-          || (boxui->defaultfont=TTF_OpenFontRW(boxui->defaultfontdata,0,/* default font size */ 16))==NULL) {
99
+        memset(boxui,0,sizeof(intboxui_t));
100
+        if(!TTF_Init()
101
+          || (boxui->defaultfontdata=SDL_IOFromConstMem(notosans_regular_ttf,notosans_regular_ttf_len))==NULL
102
+          || (boxui->defaultfont=TTF_OpenFontIO(boxui->defaultfontdata,0,DEFAULTFONTSIZE))==NULL
103
+        ) {
90 104
                 boxui_free(boxui),boxui=NULL;
91
-                return(NULL); /* ERROR: Couldn't init defaultfont */
105
+                SDL_Log("boxui: Couldn't initialize TTF: %s\n",SDL_GetError());
106
+                return(NULL);
92 107
         }
108
+        boxui->window=window;
109
+        boxui->renderer=renderer;
110
+        boxui->width=width;
111
+        boxui->height=height;
112
+        boxui->isdirty=1;
93 113
         /* font width and height */
94 114
         {
95
-                SDL_Surface *s;
96
-                SDL_Color c={0,0,0,0};
115
+                int w,h;
97 116
                 /* width */
98
-                if((s=TTF_RenderUTF8_Blended(boxui->defaultfont,"m",c))==NULL) {
99
-                        boxui_free(boxui),boxui=NULL;
100
-                        return(NULL); /* ERROR: Couldn't query font width */
101
-                }
102
-                boxui->defaultfontwidth=s->w;
103
-                SDL_FreeSurface(s),s=NULL;
117
+                TTF_GetStringSize(boxui->defaultfont,"m",0,&w,&h);
118
+                boxui->defaultfontwidth=w;
104 119
                 /* height */
105
-                if((s=TTF_RenderUTF8_Blended(boxui->defaultfont,"gjpqy_",c))==NULL) {
106
-                        boxui_free(boxui),boxui=NULL;
107
-                        return(NULL); /* ERROR: Couldn't query font height */
108
-                }
109
-                boxui->defaultfontheight=s->h;
110
-                SDL_FreeSurface(s),s=NULL;
120
+                boxui->defaultfontheight=TTF_GetFontHeight(boxui->defaultfont);
111 121
         }
112
-        /* end of temporary initialization (to be able to test) */
113
-        /* return the struct */
114 122
         return((boxui_t *)boxui);
115 123
 }
116 124
 
117 125
 void
118 126
 boxui_free(boxui_t *paramboxui)
119 127
 {
120
-        intboxui_t *boxui=(intboxui_t *)paramboxui;
121
-        if(boxui==NULL)
122
-                return; /* sanity check failed */
123
-        if(boxui->title!=NULL)
124
-                free(boxui->title),boxui->title=NULL;
125
-        /* temporary initialization freeing */
128
+        int i;
129
+        intboxui_t *boxui;
130
+        if((boxui=(intboxui_t *)paramboxui)==NULL)
131
+                return; /* nothing to do */
132
+        intboxui_signalhandler_gen(0,1,NULL);
133
+        if(boxui->signaldata.actions!=NULL) {
134
+                signalaction_t *action;
135
+                for(i=0,action=boxui->signaldata.actions
136
+                  ;i<boxui->signaldata.usedactions
137
+                  ;i++,action++
138
+                ) {
139
+                        if(action->actionstr!=NULL)
140
+                                free(action->actionstr),action->actionstr=NULL;
141
+                }
142
+                free(boxui->signaldata.actions),boxui->signaldata.actions=NULL,boxui->signaldata.sizeactions=boxui->signaldata.usedactions=0;
143
+        }
126 144
         if(boxui->defaultfont!=NULL)
127 145
                 TTF_CloseFont(boxui->defaultfont),boxui->defaultfont=NULL;
128
-        if(TTF_WasInit())
129
-                TTF_Quit();
130 146
         if(boxui->defaultfontdata!=NULL)
131
-                SDL_FreeRW(boxui->defaultfontdata),boxui->defaultfontdata=NULL;
132
-        if(boxui->renderer!=NULL)
133
-                SDL_DestroyRenderer(boxui->renderer),boxui->renderer=NULL;
134
-        if(boxui->win!=NULL)
135
-                SDL_DestroyWindow(boxui->win),boxui->win=NULL;
136
-        SDL_Quit();
137
-        /* end of temporary initialization freeing */
138
-        free(boxui),boxui=NULL,paramboxui=NULL;
147
+                SDL_CloseIO(boxui->defaultfontdata),boxui->defaultfontdata=NULL;
148
+        if(boxui->texture!=NULL)
149
+                SDL_DestroyTexture(boxui->texture),boxui->texture=NULL;
150
+        free(boxui),boxui=NULL;
139 151
         return;
140 152
 }
141 153
 
142 154
 int
143
-boxui_setuserptr(boxui_t *paramboxui, void *userptr)
155
+boxui_resize(boxui_t *paramboxui, int width, int height)
144 156
 {
145 157
         intboxui_t *boxui=(intboxui_t *)paramboxui;
146
-        if(boxui==NULL)
147
-                return(-1); /* sanity check failed */
148
-        boxui->userptr=userptr;
158
+        if(boxui==NULL) {
159
+                /* XXX (OLD): DEBUGFPRINTF((stderr,"WARNING: %s%s%i: boxui_resize: called with NULL boxui", (filedubug!=NULL)?filedebug:"",(filedubug!=NULL)?":":"",linedebug)); */
160
+                return(-1);
161
+        }
162
+        boxui->width=width;
163
+        boxui->height=height;
164
+        boxui->isdirty=1;
149 165
         return(0);
150
-
151
-}
152
-
153
-void *
154
-boxui_getuserptr(boxui_t *paramboxui)
155
-{
156
-        intboxui_t *boxui=(intboxui_t *)paramboxui;
157
-        if(boxui==NULL)
158
-                return(NULL); /* sanity check failed */
159
-        return(boxui->userptr);
160 166
 }
161 167
 
162 168
 int
163
-boxui_setfps(boxui_t *paramboxui, int fps)
169
+boxui_setuserptr(boxui_t *boxui, void *userptr)
164 170
 {
165
-        intboxui_t *boxui=(intboxui_t *)paramboxui;
166
-        if(boxui==NULL || fps<1)
167
-                return(-1); /* sanity check failed */
168
-        boxui->fps=fps;
169
-#if SDL_VERSION_ATLEAST(2,0,18)
170
-        boxui->fpsepoch=(long long)SDL_GetTicks64();
171
-#else
172
-        boxui->fpsepoch=(long long)SDL_GetTicks();
173
-#endif
174
-        boxui->fpsepochframeno=boxui->lastrenderedframeno;
171
+        if(boxui==NULL)
172
+                return(-1);
173
+        ((intboxui_t *)boxui)->userptr=userptr;
175 174
         return(0);
176 175
 }
177 176
 
178
-int
179
-boxui_getfps(boxui_t *paramboxui)
177
+void *
178
+boxui_getuserptr(boxui_t *boxui)
180 179
 {
181
-        intboxui_t *boxui=(intboxui_t *)paramboxui;
182 180
         if(boxui==NULL)
183
-                return(DEFAULT_FPS); /* sanity check failed */
184
-        return((boxui->fps==0)?DEFAULT_FPS:boxui->fps);
181
+                return(NULL);
182
+        return(((intboxui_t *)boxui)->userptr);
185 183
 }
186 184
 
187
-
188
-
189
-int
190
-boxui_tick(boxui_t *paramboxui)
185
+static void
186
+intboxui_signalhandler_gen(int nsignal, int is_set, intboxui_t *boxuiset)
191 187
 {
192
-        intboxui_t *boxui=(intboxui_t *)paramboxui;
193
-        if(boxui==NULL) {
194
-                SDL_Delay(1);
195
-                return(-1); /* sanity check failed */
196
-        }
197
-        if(boxui->isdirty) {
198
-                boxui_ghostrender((boxui_t *)boxui);
199
-                intboxui_waittick(boxui);
200
-                intboxui_render(boxui);
201
-        } else {
202
-                intboxui_waittick(boxui);
188
+        static signaldata_t *signaldata;
189
+        int pos;
190
+        if(is_set) {
191
+                signaldata=(boxuiset!=NULL)?&(boxuiset->signaldata):NULL;
192
+                return;
203 193
         }
204
-        boxui->lastrenderedframeno++;
205
-        return(0);
194
+        if(signaldata==NULL)
195
+                return; /* no handler */
196
+        pos=signaldata->writepos;
197
+        pos%=MAXPENDINGSIGNAL;
198
+        signaldata->buf[pos]=nsignal;
199
+        pos++;
200
+        pos%=MAXPENDINGSIGNAL;
201
+        signaldata->writepos=pos;
202
+        return;
206 203
 }
207 204
 
208
-int
209
-boxui_ghostrender(boxui_t *boxui)
205
+void
206
+intboxui_signalhandler(int nsignal)
210 207
 {
211
-#warning TODO
212
-        return(-1);
208
+        intboxui_signalhandler_gen(nsignal, 0, NULL);
209
+        return;
213 210
 }
214 211
 
215 212
 int
216
-boxui_refreshevents(boxui_t *paramboxui)
213
+boxui_setsignal(boxui_t *paramboxui, int nsignal, char *actionstr)
217 214
 {
218 215
         intboxui_t *boxui=(intboxui_t *)paramboxui;
219
-        if(boxui==NULL)
216
+        int i;
217
+        signaldata_t *signaldata;
218
+        char *newstr;
219
+        if(boxui==NULL || actionstr==NULL)
220 220
                 return(-1); /* sanity check failed */
221
-        SDL_PumpEvents();
221
+        intboxui_signalhandler_gen(0,1,boxui);
222
+        signaldata=&(((intboxui_t*)boxui)->signaldata);
223
+        /* check if signal already registered */
224
+        for(i=0;i<signaldata->usedactions;i++) {
225
+                if(signaldata->actions[i].nsignal==nsignal) {
226
+                        if(strcmp(actionstr,signaldata->actions[i].actionstr)==0)
227
+                                return(0); /* already configured */
228
+                        if((newstr=strdup(actionstr))==NULL)
229
+                                return(-1); /* mem. insuf. */
230
+                        free(signaldata->actions[i].actionstr),signaldata->actions[i].actionstr=NULL;
231
+                        signaldata->actions[i].actionstr=newstr;
232
+                        return(0); /* all done */
233
+                }
234
+        }
235
+        /* enlarge array if necessary */
236
+        if(signaldata->usedactions==signaldata->sizeactions) {
237
+                signalaction_t *newactions;
238
+                int reqsize=sizeof(signalaction_t)*(signaldata->sizeactions+BLOCKSIGNALACTION);
239
+                if((newactions=realloc(signaldata->actions,reqsize))==NULL)
240
+                        return(-1); /* mem. insuf. */
241
+                signaldata->actions=newactions,newactions=NULL;
242
+                memset(signaldata->actions+signaldata->sizeactions,0,sizeof(signalaction_t)*BLOCKSIGNALACTION);
243
+                signaldata->sizeactions+=BLOCKSIGNALACTION;
244
+        }
245
+        /* add element */
246
+        if((signaldata->actions[signaldata->usedactions].actionstr=strdup(actionstr))==NULL)
247
+                return(-1); /* mem. insuf. */
248
+        signaldata->actions[signaldata->usedactions].nsignal=nsignal;
249
+        signaldata->usedactions++;
250
+        /* install signal handler */
222 251
         return(0);
223 252
 }
224 253
 
225 254
 int
226
-boxui_getevent(boxui_t *paramboxui, SDL_Event *event)
255
+boxui_event(boxui_t *paramboxui, SDL_Event *event)
227 256
 {
257
+#warning TODO: we do not have the position of the texture in the window
228 258
         intboxui_t *boxui=(intboxui_t *)paramboxui;
229 259
         if(boxui==NULL || event==NULL)
230 260
                 return(-1); /* sanity check failed */
231
-        while(SDL_PeepEvents(event,1,SDL_GETEVENT,SDL_FIRSTEVENT,SDL_LASTEVENT)>0) {
261
+        if(event->type==SDL_EVENT_WINDOW_SHOWN
262
+          || event->type==SDL_EVENT_WINDOW_EXPOSED
263
+          || event->type==SDL_EVENT_WINDOW_RESIZED
264
+          || event->type==SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED
265
+          || event->type==SDL_EVENT_WINDOW_MINIMIZED
266
+          || event->type==SDL_EVENT_WINDOW_MAXIMIZED
267
+          || event->type==SDL_EVENT_WINDOW_RESTORED
268
+          || event->type==SDL_EVENT_WINDOW_OCCLUDED
269
+          || event->type==SDL_EVENT_WINDOW_ENTER_FULLSCREEN
270
+          || event->type==SDL_EVENT_WINDOW_LEAVE_FULLSCREEN
271
+        ) {
272
+                boxui->isdirty=1;
273
+        } else
232 274
 #if 1
233
-                /* test */
234
-                if(event->type==SDL_MOUSEBUTTONUP) {
235
-                        if(boxui->currentclickevent[0]!='\0') {
236
-                                boxui_putactionstr((boxui_t *)boxui,boxui->currentclickevent,NULL);
237
-                                continue; /* we have used the event */
238
-                        }
275
+        /* test */
276
+               if(event->type==SDL_EVENT_MOUSE_BUTTON_UP) {
277
+                if(boxui->currentclickevent[0]!='\0') {
278
+                        boxui_putaction((boxui_t *)boxui,boxui->currentclickevent,NULL);
239 279
                 }
240
-                /* end of test */
241
-#endif
242
-                return(0); /* event found and put into "event" */
243 280
         }
244
-        return(-1); /* no events remaining */
281
+        /* end of test */
282
+#endif
283
+        return(0);
245 284
 }
246 285
 
247 286
 int
248
-boxui_event_isquit(boxui_t *paramboxui, SDL_Event *event)
287
+boxui_tick(boxui_t *paramboxui)
249 288
 {
250 289
         intboxui_t *boxui=(intboxui_t *)paramboxui;
251
-        if(boxui==NULL || event==NULL)
252
-                return(0); /* sanity check failed */
253
-        if(event->type==SDL_WINDOWEVENT && event->window.event==SDL_WINDOWEVENT_CLOSE)
254
-                return(1);
290
+        if(boxui==NULL)
291
+                return(-1); /* sanity check failed */
292
+        if(boxui->isdirty)
293
+                intboxui_render(boxui);
255 294
         return(0);
256 295
 }
296
+
257 297
 int
258
-boxui_event_iskeydown(boxui_t *paramboxui, SDL_Event *event, int *keycode)
298
+boxui_haschanged(boxui_t *paramboxui)
259 299
 {
260 300
         intboxui_t *boxui=(intboxui_t *)paramboxui;
261
-        if(boxui==NULL || event==NULL)
301
+        if(boxui==NULL)
262 302
                 return(0); /* sanity check failed */
263
-        if(event->type==SDL_KEYDOWN) {
264
-                if(keycode!=NULL)
265
-                        *keycode=event->key.keysym.sym;
266
-                return(1);
267
-        }
268
-        return(0);
303
+        return(boxui->isdirty || boxui->haschanged);
269 304
 }
270 305
 
271
-int
272
-boxui_event_isresize(boxui_t *paramboxui, SDL_Event *event, int *neww, int *newh)
306
+SDL_Texture *
307
+boxui_gettexture(boxui_t *paramboxui)
273 308
 {
274 309
         intboxui_t *boxui=(intboxui_t *)paramboxui;
275
-        if(boxui==NULL || event==NULL)
276
-                return(0); /* sanity check failed */
277
-        if(event->type==SDL_WINDOWEVENT_RESIZED
278
-          || event->type==SDL_WINDOWEVENT_SIZE_CHANGED) {
279
-                if(neww!=NULL)
280
-                        *neww=event->window.data1;
281
-                if(newh!=NULL)
282
-                        *newh=event->window.data2;
283
-                return(1);
310
+        if(boxui==NULL)
311
+                return(NULL);
312
+#if 0
313
+fprintf(stderr,"GETTEXTURE\n");
314
+#endif
315
+        if(boxui->texture==NULL || boxui->isdirty) {
316
+                boxui->isdirty=1;
317
+                boxui_tick((boxui_t *) boxui);
318
+                if(boxui->texture==NULL) {
319
+                        SDL_Log("boxui: Couldn't generate texture\n");
320
+                        return(NULL);
321
+                }
284 322
         }
285
-        return(0);
323
+        boxui->haschanged=0;
324
+        return(boxui->texture);
286 325
 }
287 326
 
288
-void
289
-boxui_resize(boxui_t *boxui, int neww, int newh)
327
+
328
+
329
+char *
330
+boxui_getaction(boxui_t *paramboxui, char **actiondata)
290 331
 {
332
+        intboxui_t *boxui=(intboxui_t *)paramboxui;
333
+        if(boxui==NULL)
334
+                return(NULL); /* sanity check failed */
335
+        /* test */
336
+        if(boxui->flag_currentactionstrused || boxui->currentactionstr[0]=='\0')
337
+                return(NULL);
338
+        boxui->flag_currentactionstrused=1;
339
+        return(boxui->currentactionstr);
340
+        /* end of test */
291 341
 #warning TODO
292
-        return;
342
+        return(NULL);
293 343
 }
294 344
 
295 345
 int
296
-boxui_putactionstr(boxui_t *paramboxui, char *firstelem, ...)
346
+boxui_putaction(boxui_t *paramboxui, char *firstelem, ...)
297 347
 {
298 348
         intboxui_t *boxui=(intboxui_t *)paramboxui;
299 349
         if(boxui==NULL || firstelem==NULL)
... ...
@@ -307,22 +357,6 @@ boxui_putactionstr(boxui_t *paramboxui, char *firstelem, ...)
307 357
         return(-1);
308 358
 }
309 359
 
310
-char *
311
-boxui_getactionstr(boxui_t *paramboxui, char **secondelemtoend)
312
-{
313
-        intboxui_t *boxui=(intboxui_t *)paramboxui;
314
-        if(boxui==NULL)
315
-                return(NULL); /* sanity check failed */
316
-        /* test */
317
-        if(boxui->flag_currentactionstrused || boxui->currentactionstr[0]=='\0')
318
-                return(NULL);
319
-        boxui->flag_currentactionstrused=1;
320
-        return(boxui->currentactionstr);
321
-        /* end of test */
322
-#warning TODO
323
-        return(NULL);
324
-}
325
-
326 360
 char *
327 361
 boxui_add(boxui_t *paramboxui, char *filedebug, int linedebug, char *classwiname, char *format, ...)
328 362
 {
... ...
@@ -332,9 +366,9 @@ boxui_add(boxui_t *paramboxui, char *filedebug, int linedebug, char *classwiname
332 366
         /* test */
333 367
         if(strchr(format,'%')==NULL)
334 368
                 boxui_config(boxui,NULL,-1,classwiname,format);
369
+        return(classwiname);
335 370
         /* end of test */
336 371
 #warning TODO
337
-        return(NULL);
338 372
 }
339 373
 
340 374
 char *
... ...
@@ -371,86 +405,266 @@ boxui_config(boxui_t *paramboxui, char *filedebug, int linedebug, char *winame,
371 405
 
372 406
                 }
373 407
         }
408
+        return(winame);
374 409
         /* end of test */
375 410
 #warning TODO
376
-        return(NULL);
377 411
 }
378 412
 
379
-char *
380
-boxui_pack(boxui_t *boxui, char *filedebug, int linedebug, char *winame, char *format, ...)
413
+int
414
+boxuiutil_datacmp(char *datastr,char *key,char *value)
381 415
 {
382 416
 #warning TODO
383
-        return(NULL);
417
+        return(-1);
384 418
 }
385 419
 
386 420
 int
387
-intboxui_waittick(intboxui_t *paramboxui)
421
+boxui_pack(boxui_t *boxui, char *filedebug, int linedebug, char *winame, char *format, ...)
388 422
 {
389
-        long long delay;
390
-        intboxui_t *boxui=(intboxui_t *)paramboxui;
391
-        if(boxui==NULL) {
392
-                SDL_Delay(1);
393
-                return(-1); /* sanity check failed */
394
-        }
395
-#if SDL_VERSION_ATLEAST(2,0,18)
396
-        delay=((long long)SDL_GetTicks64());
397
-#else
398
-        delay=((long long)SDL_GetTicks());
399
-#endif
400
-        delay-=boxui->fpsepoch;
401
-        delay=(((boxui->lastrenderedframeno-boxui->fpsepochframeno)+1)*1000/((boxui->fps==0)?DEFAULT_FPS:boxui->fps))-delay;
402
-        if(delay>0) {
403
-                SDL_Delay(delay);
404
-        } else if(delay<-1000) {
405
-                /* reset epoch if unsyncronized by more than 1s */
406
-#if SDL_VERSION_ATLEAST(2,0,18)
407
-                boxui->fpsepoch=((long long)SDL_GetTicks64());
408
-#else
409
-                boxui->fpsepoch=((long long)SDL_GetTicks());
410
-#endif
411
-                boxui->fpsepochframeno=boxui->lastrenderedframeno;
412
-        }
413
-        intboxui_after_doexpired(boxui);
423
+#warning TODO
414 424
         return(0);
415 425
 }
416 426
 
417
-int
427
+static int
418 428
 intboxui_render(intboxui_t *paramboxui)
419 429
 {
420 430
         intboxui_t *boxui=(intboxui_t *)paramboxui;
421 431
         if(boxui==NULL)
422 432
                 return(-1); /* sanity check failed */
423 433
         /* test */
434
+#if 0
435
+fprintf(stderr,"RENDER: START\n");
436
+#endif
437
+        if(boxui->texture==NULL) {
438
+                if((boxui->texture=SDL_CreateTexture(boxui->renderer,SDL_PIXELFORMAT_RGBA8888,SDL_TEXTUREACCESS_TARGET,boxui->width,boxui->height))==NULL) {
439
+                        SDL_Log("boxui: couldn't create output texture\n");
440
+                        return(-1);
441
+                }
442
+        }
443
+        SDL_SetRenderTarget(boxui->renderer,boxui->texture);
424 444
         SDL_SetRenderDrawColor(boxui->renderer,0xff,0xff,0xff,0xff);
425 445
         SDL_RenderClear(boxui->renderer);
426 446
         if(boxui->currenttext[0]!='\0') {
427 447
                 SDL_Surface *fgsurface=NULL;
428
-                SDL_Texture *fg=NULL;
429
-                SDL_Rect dstrect;
430
-                SDL_Color c={0x00,0x00,0x00,0xff};
431
-                if((fgsurface=TTF_RenderUTF8_Blended(boxui->defaultfont,boxui->currenttext,c))!=NULL
432
-                  && (fg=SDL_CreateTextureFromSurface(boxui->renderer,fgsurface))!=NULL) {
433
-                        dstrect.x=(boxui->screenw-fgsurface->w)/2;
434
-                        dstrect.y=(boxui->screenh-fgsurface->h)/2;
448
+                SDL_Texture *fgtexture=NULL;
449
+                SDL_FRect dstrect;
450
+                SDL_Color bg={0x00,0x00,0x00,0x00};
451
+                SDL_Color fg={0x00,0x00,0x00,0xff};
452
+                if((fgsurface=TTF_RenderText_Shaded(boxui->defaultfont,boxui->currenttext,0,fg,bg))!=NULL
453
+                  && (fgtexture=SDL_CreateTextureFromSurface(boxui->renderer,fgsurface))!=NULL) {
454
+#if 0
455
+fprintf(stderr,"RENDER: text (w:%i h:%i)\n",fgsurface->w,fgsurface->h);
456
+#endif
457
+                        dstrect.x=(boxui->width-fgsurface->w)/2;
458
+                        dstrect.y=(boxui->height-fgsurface->h)/2;
435 459
                         dstrect.w=fgsurface->w,dstrect.h=fgsurface->h;
436
-                        SDL_RenderCopy(boxui->renderer,fg,NULL,&dstrect);
460
+#if 0
461
+fprintf(stderr,"RENDER: text (w:%i h:%i) dstrect:%ix%i+%i+%i\n",fgsurface->w,fgsurface->h,dstrect.w,dstrect.h,dstrect.x,dstrect.y);
462
+#endif
463
+                        SDL_RenderTexture(boxui->renderer,fgtexture,NULL,&dstrect);
437 464
                 }
438 465
                 if(fgsurface!=NULL)
439
-                        SDL_FreeSurface(fgsurface),fgsurface=NULL;
440
-                if(fg!=NULL)
441
-                        SDL_DestroyTexture(fg),fg=NULL;
466
+                        SDL_DestroySurface(fgsurface),fgsurface=NULL;
467
+                if(fgtexture!=NULL)
468
+                        SDL_DestroyTexture(fgtexture),fgtexture=NULL;
442 469
         }
443
-        SDL_RenderPresent(boxui->renderer);
470
+        SDL_SetRenderTarget(boxui->renderer,NULL);
444 471
         boxui->isdirty=0;
472
+        boxui->haschanged=1;
473
+#if 0
474
+fprintf(stderr,"RENDER: START\n");
475
+#endif
445 476
         /* end of test */
446 477
 #warning TODO
447 478
         return(0);
448 479
 }
449 480
 
450
-int
451
-intboxui_after_doexpired(intboxui_t *boxui)
481
+
482
+static char *
483
+intboxuiutil_getnext(char *data, int *posdata, va_list valist, int *resl, datatype_t *datatype, char **ptr1, char **ptr2, int *int1, int *int2, int *in_error)
452 484
 {
453
-#warning TODO
485
+        char *ptr;
486
+        char *res;
487
+        ptr=data+*posdata;
488
+        /* skip trailing spaces */
489
+        while(*ptr==' ')
490
+                ptr++;
491
+        if(*ptr!='-') {
492
+                *in_error=1;
493
+                DEBUGFPRINTF((stderr,"WARNING: intboxuiutil_getnext(): wrong data in \"%s\", analyzing \"%s\", '-' not found at \"%s\"\n",data,data+*posdata,ptr));
494
+                return(NULL);
495
+        }
496
+        /* get keyword (including the '-') */
497
+        res=ptr;
498
+        while(*ptr!=' ' && *ptr!='\0')
499
+                ptr++;
500
+        *resl=ptr-res;
501
+        /* skip the space */
502
+        ptr++;
503
+        /* get value */
504
+        if(*ptr!='\"' && *ptr!='%') {
505
+                *datatype=datatype_literal;
506
+                *ptr1=ptr;
507
+                while(*ptr!=' ' && *ptr!='\0')
508
+                        ptr++;
509
+
510
+                *int1=ptr-*ptr1;
511
+        } else if(*ptr=='\"') {
512
+                int flag_esc;
513
+                *datatype=datatype_escapedquotedliteral;
514
+                ptr++;
515
+                *ptr1=ptr;
516
+                for(flag_esc=0;!(flag_esc==0 && *ptr=='\"') && *ptr!='\0';ptr++) {
517
+                        if(flag_esc)
518
+                                flag_esc=0;
519
+                        else if(*ptr=='\\')
520
+                                flag_esc=1;
521
+                }
522
+                if(*ptr!='\"') {
523
+                        *in_error=1;
524
+                        DEBUGFPRINTF((stderr,"WARNING: intboxuiutil_getnext(): wrong data in \"%s\", analyzing \"%s\", unterminated string at \"%s\"\n",data,data+*posdata,*ptr1));
525
+                        return(NULL);
526
+                }
527
+                *int1=ptr-*ptr1;
528
+                ptr++;
529
+        } else if(ptr[0]=='%' && ptr[1]=='s' && (ptr[2]=='\0' || ptr[2]==' ')) {
530
+                *datatype=datatype_quotedliteral;
531
+                *ptr1=va_arg(valist, char *);
532
+                *int1=strlen(*ptr1);
533
+                ptr+=2;
534
+        } else if(ptr[0]=='%' && ptr[1]=='i' && (ptr[2]=='\0' || ptr[2]==' ')) {
535
+                *datatype=datatype_integer;
536
+                *int1=va_arg(valist, int);
537
+                ptr+=2;
538
+        } else if(ptr[0]=='%' && ptr[1]=='s' && ptr[2]=='%' && ptr[3]=='i' && (ptr[4]=='\0' || ptr[4]==' ')) {
539
+                *datatype=datatype_textvariable;
540
+                *ptr1=va_arg(valist, char *);
541
+                *int1=va_arg(valist, int);
542
+                ptr+=4;
543
+        } else if(ptr[0]=='%' && ptr[1]=='p' && ptr[2]=='%' && ptr[3]=='i' && ptr[4]=='%' && ptr[5]=='i' && (ptr[6]=='\0' || ptr[6]==' ')) {
544
+                *datatype=datatype_asset;
545
+                *ptr1=va_arg(valist, char *);
546
+                *int1=va_arg(valist, int);
547
+                *int2=va_arg(valist, int);
548
+                ptr+=6;
549
+        } else if(ptr[0]=='%' && ptr[1]=='p' && ptr[2]=='%' && ptr[3]=='p' && (ptr[4]=='\0' || ptr[4]==' ')) {
550
+                *datatype=datatype_callback;
551
+                *ptr1=va_arg(valist, char *);
552
+                *ptr2=va_arg(valist, char *);
553
+                ptr+=4;
554
+        } else {
555
+                *in_error=1;
556
+                DEBUGFPRINTF((stderr,"WARNING: intboxuiutil_getnext(): wrong data in \"%s\", analyzing \"%s\", unrecognized value type at \"%s\"\n",data,data+*posdata,ptr));
557
+                return(NULL);
558
+        }
559
+        /* save the current position and return the key */
560
+        *posdata=ptr-data;
561
+        return(res);
562
+}
563
+
564
+static char *
565
+datatypedup_literalquotedliteral(datatype_t datatype, char *ptr1, char *ptr2, int int1, int int2)
566
+{
567
+        char *res,*aux;
568
+        int t,i;
569
+        int flag_esc;
570
+        res=NULL;
571
+        int req;
572
+        /* two passes; first calculates needed storage space, second copies the data */
573
+        for(t=0,req=0;t<2;t++) {
574
+                if(datatype==datatype_literal || datatype==datatype_quotedliteral) {
575
+                        req=int1+1;
576
+                        if(t) {
577
+                                memcpy(res,ptr1,req);
578
+                                ptr1[int1]='\0';
579
+                        }
580
+                } else if(datatype==datatype_escapedquotedliteral) {
581
+                        for(req=0,aux=ptr1,flag_esc=0,i=0;!(flag_esc==0 && *aux=='\"') && *aux!='\0' && i<int1;aux++) {
582
+                                if(flag_esc) {
583
+                                        if(t)
584
+                                                res[req]=*aux;
585
+                                        req++;
586
+                                        flag_esc=0;
587
+                                } else if(*aux=='\\') {
588
+                                        flag_esc=1;
589
+                                } else {
590
+                                        if(t)
591
+                                                res[req]=*aux;
592
+                                        req++;
593
+                                }
594
+                        }
595
+                        if(t)
596
+                                res[req]='\0';
597
+                        req++;
598
+                } else if(datatype==datatype_integer) {
599
+                        int l=req;
600
+                        for(i=int1,req=0;i>0 || req==0;) {
601
+                                if(t)
602
+                                        res[(l-2)-req]=(i%10)+'0';
603
+                                req++;
604
+                                i/=10;
605
+                        }
606
+                        if(t)
607
+                                res[l-1]='\0';
608
+                        req++;
609
+                } else {
610
+                        return(NULL); /* type is not amenable to strdup */
611
+                }
612
+                if(t==0) {
613
+                        if((res=malloc(req))==NULL)
614
+                                return(NULL); /* insuf. mem. */
615
+                }
616
+        }
617
+        return(res);
618
+}
619
+
620
+static int
621
+datatypedup_int(datatype_t datatype, char *ptr1, char *ptr2, int int1, int int2, int defaultint, int *in_error)
622
+{
623
+        if(in_error!=NULL)
624
+                *in_error=0;
625
+        if(datatype==datatype_integer)
626
+                return(int1);
627
+        else if(datatype==datatype_literal || datatype==datatype_escapedquotedliteral || datatype==datatype_quotedliteral) {
628
+                int i,res;
629
+                if(int1==0)
630
+                        return(defaultint); /* no data */
631
+                for(i=0,res=0;i<int1;i++) {
632
+                        if(!(ptr1[i]>='0' && ptr1[i]<='9')) {
633
+                                if(in_error!=NULL)
634
+                                        *in_error=1;
635
+                                return(defaultint);
636
+                        }
637
+                        res=(res*10)+(ptr1[i]-'0');
638
+                }
639
+                return(res);
640
+        }
641
+        if(in_error!=NULL)
642
+                *in_error=1;
643
+        return(defaultint);
644
+}
645
+
646
+static int
647
+datatypedup_istrue(datatype_t datatype, char *ptr1, char *ptr2, int int1, int int2, int *in_error)
648
+{
649
+        if(in_error!=NULL)
650
+                *in_error=0;
651
+        if(datatype==datatype_literal || datatype==datatype_escapedquotedliteral || datatype==datatype_quotedliteral) {
652
+                if(memstrcmp(ptr1,int1,"true")==0)
653
+                        return(1);
654
+                return(0);
655
+        }
656
+        if(in_error!=NULL)
657
+                *in_error=1;
454 658
         return(0);
455 659
 }
456 660
 
661
+static int
662
+memstrcmp(char *ptr, int l, char *str)
663
+{
664
+        int res;
665
+        res=memcmp(ptr,str,l);
666
+        if(res==0 && str[l]=='\0')
667
+                return(0);
668
+        return((res==0)?1:res);
669
+}
670
+
... ...
@@ -1,18 +1,18 @@
1 1
 /*
2
- * boxui.c
2
+ * boxui.h
3 3
  *
4
- * Multiplatform UI library for SDL2.
4
+ * Multiplatform UI library for SDL3.
5 5
  *
6 6
  * HEADER FILE
7 7
  *
8
- * (c) 2023 Dario Rodriguez <antartica@box-ui.org>
8
+ * (c) 2023-2024 Dario Rodriguez <antartica@box-ui.org>
9 9
  * Licensed under the terms of the GNU GPL v3.
10 10
  */
11 11
 
12 12
 #ifndef BOXUI_H
13 13
 #define BOXUI_H
14 14
 
15
-#include "SDL.h"
15
+#include "SDL3/SDL.h"
16 16
 
17 17
 typedef void boxui_t;
18 18
 
... ...
@@ -25,35 +25,33 @@ typedef void boxui_t;
25 25
 #define DEBUG_FPRINTF(a)
26 26
 #endif
27 27
 
28
-boxui_t *boxui_init(char *title,int defaultw, int defaulth, int flags);
28
+boxui_t *boxui_init(SDL_Window *window, SDL_Renderer *renderer, int width, int height);
29 29
 void boxui_free(boxui_t *boxui);
30 30
 
31
+int boxui_resize(boxui_t *boxui, int width, int height);
32
+
31 33
 int boxui_setuserptr(boxui_t *boxui, void *userptr);
32 34
 void *boxui_getuserptr(boxui_t *boxui);
33 35
 
34
-int boxui_setfps(boxui_t *boxui, int fps);
35
-int boxui_getfps(boxui_t *boxui);
36
+int boxui_setsignal(boxui_t *boxui, int signalno, char *actionstr);
37
+
38
+int boxui_event(boxui_t *boxui, SDL_Event *event);
39
+
36 40
 int boxui_tick(boxui_t *boxui);
37
-int boxui_ghostrender(boxui_t *boxui);
38 41
 
39
-int boxui_refreshevents(boxui_t *boxui);
40
-int boxui_getevent(boxui_t *boxui, SDL_Event *event);
42
+int boxui_haschanged(boxui_t *paramboxui);
41 43
 
42
-int boxui_event_isquit(boxui_t *boxui, SDL_Event *event);
43
-int boxui_event_iskeydown(boxui_t *boxui, SDL_Event *event, int *keycode);
44
-int boxui_event_isresize(boxui_t *boxui, SDL_Event *event, int *neww, int *newh);
44
+SDL_Texture *boxui_gettexture(boxui_t *boxui);
45 45
 
46
-void boxui_resize(boxui_t *boxui, int neww, int newh);
46
+char *boxui_getevent(boxui_t *boxui, char **eventdata);
47
+char *boxui_getaction(boxui_t *boxui, char **actiondata);
47 48
 
48 49
 #ifndef __GNUC__
49
-int boxui_putactionstr(boxui_t *boxui, char *firstelem, ...);
50
+int boxui_putaction(boxui_t *boxui, char *firstelem, ...);
50 51
 #else
51
-        int boxui_putactionstr(boxui_t *boxui, char *firstelem, ...) __attribute__((sentinel));
52
+        int boxui_putaction(boxui_t *boxui, char *firstelem, ...) __attribute__((sentinel));
52 53
 #endif
53 54
 
54
-char *boxui_getactionstr(boxui_t *boxui, char **secondelemtoend);
55
-
56
-
57 55
 #ifndef __GNUC__
58 56
 char *boxui_add(boxui_t *boxui, char *filedebug, int linedebug, char *classwiname, char *format, ...);
59 57
 char *boxui_config(boxui_t *boxui, char *filedebug, int linedebug, char *winame, char *format, ...);
... ...
@@ -62,12 +60,35 @@ char *boxui_config(boxui_t *boxui, char *filedebug, int linedebug, char *winame,
62 60
         char *boxui_config(boxui_t *boxui, char *filedebug, int linedebug, char *winame, char *format, ...) __attribute__((format(printf,5,6)));
63 61
 #endif
64 62
 
63
+int boxuiutil_datacmp(char *datastr,char *key,char *value);
64
+
65 65
 #ifndef __GNUC__
66
-char *boxui_pack(boxui_t *boxui, char *filedebug, int linedebug, char *winame, char *format, ...);
66
+int boxui_pack(boxui_t *boxui, char *filedebug, int linedebug, char *winame, char *format, ...);
67 67
 #else
68
-        char *boxui_pack(boxui_t *boxui, char *filedebug, int linedebug, char *winame, char *format, ...) __attribute__((format(printf,5,6)));
68
+        int boxui_pack(boxui_t *boxui, char *filedebug, int linedebug, char *winame, char *format, ...) __attribute__((format(printf,5,6)));
69 69
 #endif
70 70
 
71
+#if 0 //if0
72
+int boxui_setfps(boxui_t *boxui, int fps);
73
+int boxui_getfps(boxui_t *boxui);
74
+int boxui_tick(boxui_t *boxui);
75
+int boxui_ghostrender(boxui_t *boxui);
76
+
77
+int boxui_refreshevents(boxui_t *boxui);
78
+int boxui_getevent(boxui_t *boxui, SDL_Event *event);
79
+
80
+int boxui_event_isquit(boxui_t *boxui, SDL_Event *event);
81
+int boxui_event_iskeydown(boxui_t *boxui, SDL_Event *event, int *keycode);
82
+int boxui_event_isresize(boxui_t *boxui, SDL_Event *event, int *neww, int *newh);
83
+
84
+void boxui_resize(boxui_t *boxui, int neww, int newh);
85
+
86
+char *boxui_getactionstr(boxui_t *boxui, char **secondelemtoend);
87
+
88
+
89
+
90
+#endif //if0
91
+
71 92
 
72 93
 
73 94
 #endif
... ...
@@ -1,138 +1,114 @@
1 1
 /*
2 2
  * boxui_demo_helloworld.c
3 3
  *
4
- * Box-UI small example with best practices.
4
+ * box-ui small example with best practices.
5 5
  *
6
- * (c) 2023 Dario Rodriguez <antartica@whereismybit.com>
6
+ * (c) 2024 Dario Rodriguez <antartica@whereismybit.com>
7 7
  * This program is licensed under the terms of the MIT/X license.
8 8
  */
9 9
 
10
-#ifdef EMSCRIPTEN
11
-#include <emscripten.h>
12
-#endif
10
+
13 11
 #include <stdio.h>
14 12
 #include <stdlib.h>
15 13
 #include <unistd.h>
16 14
 #include <string.h>
17
-#include <time.h>
18 15
 #include <signal.h>
16
+
17
+#define SDL_MAIN_USE_CALLBACKS 1
18
+#include <SDL3/SDL.h>
19
+#include <SDL3/SDL_main.h>
20
+
19 21
 #include "boxui.h"
20 22
 
21
-#define DEFAULT_SCREENW 640
22
-#define DEFAULT_SCREENH 480
23
+#define DEFAULT_SCREENW 800
24
+#define DEFAULT_SCREENH 600
23 25
 
24 26
 typedef struct mydata_t {
25
-        int flag_exit;
27
+        SDL_Window *window;
28
+        SDL_Renderer *renderer;
26 29
         boxui_t *boxui;
27 30
 } mydata_t;
28 31
 
29
-volatile int flag_sigint;
30
-static void sigint(int n);
31
-static int install_signal(int n,void (*f)(int));
32
-
33
-mydata_t *mydata_init(void);
34
-void mydata_free(mydata_t *mydata);
35
-int main_loop_iteration(mydata_t *mydata);
36
-
37
-int
38
-main(int argc, char *argv[])
39
-{
40
-        mydata_t *mydata;
41
-        if((mydata=mydata_init())==NULL) {
42
-                DEBUG_FPRINTF((stderr,"Couldn't init\n"));
43
-                return(-1); /* couldn't init */
44
-        }
45
-        flag_sigint=0;
46
-        install_signal(SIGINT,sigint);
47
-        while(flag_sigint==0 && mydata->flag_exit==0 && mydata->boxui!=NULL) {
48
-#ifdef EMSCRIPTEN
49
-                emscripten_set_main_loop_arg((void (*)(void *))main_loop_iteration,(void *) mydata,boxui_getfps(mydata->boxui),1);
50
-#else
51
-                main_loop_iteration(mydata);
52
-#endif
53
-        }
54
-        mydata_free(mydata),mydata=NULL;
55
-        return(0);
56
-}
57
-
58
-static int
59
-install_signal(int n,void (*f)(int))
60
-{
61
-#ifndef LINUX
62
-        return(-1);
63
-#else
64
-        struct sigaction sact;
65
-        sact.sa_handler=f;
66
-        sigemptyset(&sact.sa_mask);
67
-        sact.sa_flags=0;
68
-        return(sigaction(n,&sact,0));
69
-#endif
70
-}
71
-
72
-static void
73
-sigint(int n)
74
-{
75
-        flag_sigint++;
76
-}
77
-
78
-mydata_t *
79
-mydata_init(void)
32
+SDL_AppResult
33
+SDL_AppInit(void **appstate, int argc, char *argv[])
80 34
 {
81 35
         boxui_t *boxui;
82
-        mydata_t *mydata;
36
+        static mydata_t realmydata,*mydata;
83 37
         char *p;
84
-        if((mydata=malloc(sizeof(mydata_t)))==NULL)
85
-                return(NULL);
86
-        memset(mydata,0,sizeof(mydata_t));
87
-        if((mydata->boxui=boxui=boxui_init("boxui demo helloworld",DEFAULT_SCREENW,DEFAULT_SCREENH,0))==NULL
88
-          || boxui_setuserptr(boxui,mydata)!=0) {
89
-                mydata_free(mydata),mydata=NULL;
90
-                return(NULL);
38
+        char *strerror;
39
+
40
+        memset(&realmydata,0,sizeof(realmydata));
41
+        mydata=&realmydata;
42
+        SDL_SetAppMetadata("Boxui demo simplified", "1.0", "org.box-ui.com.example.camera-read-and-draw");
43
+        if((strerror="SDL_init")==NULL
44
+         || !SDL_Init(SDL_INIT_VIDEO)
45
+         || (strerror="SDL_CreateWindowAndRenderer")==NULL
46
+         || !SDL_CreateWindowAndRenderer("boxui demo helloworld",DEFAULT_SCREENW,DEFAULT_SCREENH,0,&mydata->window,&mydata->renderer)
47
+         || (strerror="boxui")==NULL
48
+         || (boxui=mydata->boxui=boxui_init(mydata->window,mydata->renderer,DEFAULT_SCREENW,DEFAULT_SCREENH))==NULL
49
+         || (strerror="boxui_add")==NULL
50
+         || (p=boxui_add(boxui,_F,_L,"label:.label","-text \"Hello World!\" -click labelclicked"))==NULL
51
+         || (strerror="boxui_pack")==NULL
52
+         || boxui_pack(boxui,_F,_L,p,"-side top -fill both -expand true -anchor center")!=0) {
53
+                SDL_Log("ERROR: Couldn't init UI: %s failed\n",strerror);
54
+                return SDL_APP_FAILURE;
91 55
         }
92
-        /* initial UI config */
93
-        p=boxui_add(boxui,_F,_L,"label:.l","-text \"Hello World!\" -click changetext");
94
-        boxui_pack(boxui,_F,_L,p,"-side top -fill both -expand true");
95
-        return(mydata);
56
+        boxui_setuserptr(boxui,mydata);
57
+        boxui_setsignal(boxui,SIGINT,"sigint");
58
+        *appstate=(void *)mydata;
59
+        return SDL_APP_CONTINUE;
96 60
 }
97 61
 
98
-void
99
-mydata_free(mydata_t *mydata)
62
+/* NOTE: SDL_AppEvent may get called concurrently with SDL_AppEvent() for events not pushed on the main thread. */
63
+SDL_AppResult
64
+SDL_AppEvent(void *appstate, SDL_Event *event)
100 65
 {
101
-        boxui_t *boxui;
102
-        if(mydata==NULL)
103
-                return;
104
-        if((boxui=mydata->boxui)!=NULL) {
105
-                boxui_setuserptr(boxui,NULL);
106
-                boxui_free(boxui),boxui=NULL,mydata->boxui=NULL;
66
+        mydata_t *mydata=(mydata_t *)appstate;
67
+        if(event->type==SDL_EVENT_QUIT) {
68
+                return SDL_APP_SUCCESS; /* exit program with code 0 (ok) */
69
+        } else if(event->type==SDL_EVENT_WINDOW_RESIZED) {
70
+                boxui_resize(mydata->boxui,event->window.data1,event->window.data1);
71
+        } else if(event->type==SDL_EVENT_KEY_DOWN && event->key.key==SDLK_ESCAPE) {
72
+                return SDL_APP_SUCCESS; /* ESC key pressed, exit program with code 0 (ok) */
73
+        } else {
74
+                boxui_event(mydata->boxui,event);
107 75
         }
108
-        free(mydata),mydata=NULL;
109
-        return;
76
+        return SDL_APP_CONTINUE;  /* don't exit program */
110 77
 }
111 78
 
112
-int
113
-main_loop_iteration(mydata_t *mydata)
79
+SDL_AppResult
80
+SDL_AppIterate(void *appstate)
114 81
 {
82
+        mydata_t *mydata=(mydata_t *)appstate;
115 83
         boxui_t *boxui;
116
-        SDL_Event event;
117
-        int keycode,neww,newh;
118
-        char *actionstr,*actionparams;
84
+        char *action,*actiondata;
119 85
         if(mydata==NULL || (boxui=mydata->boxui)==NULL)
120
-                return(-1);
121
-        boxui_tick(boxui);
122
-        boxui_refreshevents(boxui);
123
-        while(boxui_getevent(boxui,&event)==0) {
124
-                /* standard events */
125
-                if(boxui_event_isquit(boxui,&event))
126
-                        mydata->flag_exit=1;
127
-                if(boxui_event_iskeydown(boxui,&event,&keycode) && keycode==SDLK_ESCAPE)
128
-                        mydata->flag_exit=1;
129
-                if(boxui_event_isresize(boxui,&event,&neww,&newh))
130
-                        boxui_resize(boxui,neww,newh);
86
+                return SDL_APP_FAILURE; /* internal error, exit loop */
87
+        /* actions */
88
+        while((action=boxui_getaction(boxui,&actiondata))!=NULL) {
89
+                if(strcmp(action,"sigint")==0) {
90
+                        return SDL_APP_SUCCESS; /* interrupted by user, exit program with code 0 (ok) */
91
+                } else if(strcmp(action,"labelclicked")==0) {
92
+                        boxui_config(mydata->boxui,_F,_L,".label","-text \"Hello again!\"");
93
+                }
131 94
         }
132
-        while((actionstr=boxui_getactionstr(boxui,&actionparams))!=NULL) {
133
-                if(strcmp(actionstr,"changetext")==0)
134
-                        boxui_config(boxui,_F,_L,".l","-text \"Hello again!\"");
95
+        /* rendering */
96
+        boxui_tick(mydata->boxui);
97
+        if(boxui_haschanged(mydata->boxui)) {
98
+                SDL_Texture *texture;
99
+                texture=boxui_gettexture(mydata->boxui);
100
+                SDL_SetRenderDrawColor(mydata->renderer, 0x99, 0x99, 0x99, 255);
101
+                SDL_RenderClear(mydata->renderer);
102
+                SDL_RenderTexture(mydata->renderer, texture, NULL, NULL);
103
+                SDL_RenderPresent(mydata->renderer);
135 104
         }
136
-        return(0);
105
+        return SDL_APP_CONTINUE;  /* don't exit program */
106
+}
107
+
108
+void SDL_AppQuit(void *appstate, SDL_AppResult result)
109
+{
110
+    mydata_t *mydata=(mydata_t *)appstate;
111
+    if(mydata!=NULL)
112
+        boxui_free(mydata->boxui),mydata->boxui=NULL;
137 113
 }
138 114