Now I thought this was an interesting question: how do you encode a structure in 4tH - especially when you want a "builtin" structure.
In fact, it's quite easy: all STRUCT, FIELD: and END-STRUCT do is create a bunch of +CONSTANTs and a CONSTANT for the size of the structure. So if we evaluate this:
webui_event_t {
size_t window; // The window object number
size_t event_type; // Event type
char* element; // HTML element ID
size_t event_number; // Internal
size_t bind_id; // Bind ID
size_t client_id; // Client's unique ID
size_t connection_id; // Client's connection ID
char* cookies; // Client's full cookies
};
We can easily translate that to:
0 +constant window
1 +constant event_type
2 +constant element^
3 +constant event_number
4 +constant bind_id
5 +constant connection_id
6 +constant cookies^
7 constant /Event
.. and those can be easily be included in comp_4th() as constants. Now this is a trivial one - only 4tH doesn't take such long labels (although you can easily fix that by modifying a constant):
C:
enum {
WEBUI_EVENT_DISCONNECTED = 0, // 0. Window disconnection event
WEBUI_EVENT_CONNECTED, // 1. Window connection event
WEBUI_EVENT_MOUSE_CLICK, // 2. Mouse click event
WEBUI_EVENT_NAVIGATION, // 3. Window navigation event
WEBUI_EVENT_CALLBACK, // 4. Function call event
};
4tH:
0 enum EVENT_DISCONNECTED
enum EVENT_CONNECTED
enum EVENT_MOUSE_CLICK
enum EVENT_NAVIGATION
constant EVENT_CALLBACK
And now for the payload itself:
void events(webui_event_t* e) {
if(e->event_type == WEBUI_EVENT_CONNECTED)
printf("Connected. \n");
else if(e->event_type == WEBUI_EVENT_DISCONNECTED)
printf("Disconnected. \n");
else if(e->event_type == WEBUI_EVENT_MOUSE_CLICK)
printf("Click. \n");
else if(e->event_type == WEBUI_EVENT_NAVIGATION)
printf("Starting navigation to: %s \n", e->data);
}
Now it may be that someone had second thoughts, because there is no "data" member (this won't compile IMHO), so we take "element" instead.
void events(webui_event_t* e) {
if(e->event_type == WEBUI_EVENT_CONNECTED)
printf("Connected. \n");
else if(e->event_type == WEBUI_EVENT_DISCONNECTED)
printf("Disconnected. \n");
else if(e->event_type == WEBUI_EVENT_MOUSE_CLICK)
printf("Click. \n");
else if(e->event_type == WEBUI_EVENT_NAVIGATION)
printf("Starting navigation to: %s \n", e->data);
}
And this is it:
: events
dup -> event_type @
case
EVENT_CONNECTED of ." Connected. " endof
EVENT_DISCONNECTED of ." Disconnected. " endof
EVENT_MOUSE_CLICK of ." Click. " endof
EVENT_NAVIGATION of
." Starting navigation to: " dup -> element^ @ count type space
endof
endcase drop cr
;
Yes, we have to initialize the pointers by hand. I don't think C will be different, though. You can use the library and make this dynamic strings (easier and with added security):
/Event array MyEvent
64 string element
64 string cookies
element MyEvent -> element^ !
cookies MyEvent -> cookies^ !
s" button" MyEvent -> element^ @ place
Note we added a few extra labels to display (just to be sure). This is the program:
cr ." Connected.." cr
EVENT_CONNECTED MyEvent -> event_type !
MyEvent events
cr ." Disconnected.." cr
EVENT_DISCONNECTED MyEvent -> event_type !
MyEvent events
cr ." Clicking.." cr
EVENT_MOUSE_CLICK MyEvent -> event_type !
MyEvent events
cr ." Navagating.." cr
EVENT_NAVIGATION MyEvent -> event_type !
MyEvent events depth . \ yes, just to be sure.. ;-)
And this is the output:
$ pp4th -x webui.4th
Connected..
Connected.
Disconnected..
Disconnected.
Clicking..
Click.
Navagating..
Starting navigation to: button
0
Now sure, mapping the 4tH structure to the C structure is another issue. Then you copy the webui_event structure, but make all the members type cell and carefully transfer each member to a webui_event_t struct using the proper casts and conversions before issuing it to the webui API.
And that's how I would approach the issue. The callbacks are another thing - but look closely at 4tsH and see how you can use PAUSE and OUT to communicate between a 4tH programs and a C host. There is also a Wiki page on the subject at Sourceforge.
Hans Bezemer