💾 Archived View for gemini.rmf-dev.com › repo › Vaati › VgmiTL › files › 17a80db90c69a1763e09a0c87d7… captured on 2022-07-16 at 17:13:26. Gemini links have been rewritten to link to archived content
-=-=-=-=-=-=-
0 #include "scheme.h"
1 #include "gemini.h"
2 #include "cert.h"
3 #include <tinyscheme/scheme.h>
4 #include <tinyscheme/scheme-private.h>
5 #include <time.h>
6 #include <string.h>
7 #include <stdlib.h>
8 #include <pthread.h>
9
10 pointer unix_sec(scheme *sc, pointer args) {
11 if (args != sc->NIL) {
12 // error
13 return sc->F;
14 }
15 return mk_integer(sc, time(NULL));
16 }
17
18 pointer set_element_text(scheme *sc, pointer args) {
19 int i = 0;
20 char* id = NULL;
21 char* str_value = NULL;
22 while (args != sc->NIL) {
23 pointer arg;
24 if (i == 0 && is_string(arg = pair_car(args))) {
25 id = string_value(arg);
26 } else if (i == 1) {
27 struct gmi_tab* tab = NULL;
28 for (int i=0; i < client.tabs_count; i++) {
29 if (client.tabs[i].ctx == sc) {
30 tab = &client.tabs[i];
31 break;
32 }
33 }
34 if (!tab) return sc->F;
35 if (is_string(arg = pair_car(args)))
36 str_value = string_value(arg);
37 else if (is_integer(arg = pair_car(args))) {
38 char buf[32];
39 if (is_real(arg))
40 snprintf(buf, sizeof(buf), "%!f(MISSING)", rvalue(arg));
41 else
42 snprintf(buf, sizeof(buf), "%!l(MISSING)d", ivalue(arg));
43 str_value = string_value(mk_string(sc, buf));
44 } else
45 return sc->F;
46
47 for (int i = 0; i < tab->page.objs_count; i++) {
48 if (!strcmp(tab->page.objs[i].id, id)) {
49 tab->page.objs[i].value = str_value;
50 client.refresh = 1;
51 return sc->T;
52 }
53 }
54
55 return sc->F;
56 } else
57 return sc->F;
58 args = pair_cdr(args);
59 i++;
60 }
61 return sc->F;
62 }
63
64 struct ffunction {
65 pointer (*func)(scheme*, pointer);
66 const char* name;
67 };
68
69 struct interval {
70 long msec;
71 pointer lambda;
72 struct timespec called;
73 long id;
74 int active;
75 struct gmi_tab* tab;
76 };
77
78 struct interval intervals[1024];
79 int interval_counts = 0;
80
81 void* interval_thread(void* ptr) {
82 while (!client.shutdown) {
83 struct timespec current;
84 for (int i = 0; i < interval_counts; i++) {
85 struct interval* iv = &intervals[i];
86 if (!iv->active) continue;
87 clock_gettime(CLOCK_MONOTONIC_RAW, ¤t);
88 if (((current.tv_sec - iv->called.tv_sec)*1000000000 +
89 current.tv_nsec - iv->called.tv_nsec)/1000000 > iv->msec) {
90 pointer args =
91 cons(iv->tab->ctx,
92 mk_integer(iv->tab->ctx, iv->id),
93 iv->tab->ctx->NIL);
94 scheme_call(iv->tab->ctx, iv->lambda, args);
95 clock_gettime(CLOCK_MONOTONIC_RAW, &iv->called);
96 }
97 }
98 struct timespec ts = {0, 1000000};
99 nanosleep(&ts, NULL);
100 }
101 return ptr;
102 }
103
104 pointer interval(scheme *sc, pointer args) {
105 int i = 0;
106 int msec = 0;
107 while (args != sc->NIL) {
108 pointer arg;
109 if (i == 0 && is_integer(arg = pair_car(args))) {
110 msec = rvalue(arg);
111 }
112 else if (i == 1 && is_closure(arg = pair_car(args))) {
113 struct interval* iv = &intervals[interval_counts];
114 iv->lambda = arg;
115 iv->msec = msec;
116 iv->active = 1;
117 iv->tab = NULL;
118 for (int i=0; i < client.tabs_count; i++) {
119 if (client.tabs[i].ctx == sc) {
120 iv->tab = &client.tabs[i];
121 break;
122 }
123 }
124 if (!iv->tab) return sc->F;
125 clock_gettime(CLOCK_MONOTONIC_RAW, &iv->called);
126 interval_counts++;
127 return mk_integer(sc, interval_counts-1);
128 } else
129 return sc->F;
130 args = pair_cdr(args);
131 i++;
132 }
133 return sc->F;
134 }
135
136 pointer interval_stop(scheme *sc, pointer args) {
137 pointer arg;
138 if (!is_integer(arg = pair_car(args))) {
139 // error
140 return sc->F;
141 }
142 long id = rvalue(arg);
143 if (id >= (signed)sizeof(intervals)) {
144 // error
145 return sc->F;
146 }
147 intervals[id].active = 0;
148 return sc->T;
149 }
150
151 struct ffunction functions[] = {
152 {unix_sec, "unix-sec"},
153 {interval, "interval"},
154 {interval_stop, "stop-interval"},
155 {set_element_text, "set-element-text"}
156 };
157
158 pthread_t interval_t;
159 int scm_init() {
160 return pthread_create(&interval_t, NULL, (void *(*)(void*))interval_thread, NULL);
161 }
162
163 int scm_free() {
164 return pthread_join(interval_t, NULL);
165 }
166
167 int scm_init_tab(struct gmi_tab* tab) {
168 if (tab->ctx) scheme_deinit(tab->ctx);
169 tab->ctx = scheme_init_new();
170 char buf[1024];
171
172 int len = getcachefolder(buf, sizeof(buf));
173 snprintf(&buf[len], sizeof(buf)-len, "/output_%!p(MISSING).log", (void*)tab);
174 FILE* f = fopen(buf, "w");
175 if (f)
176 scheme_set_output_port_file(tab->ctx, f);
177
178 for (size_t i=0; i < sizeof(functions)/sizeof(struct ffunction); i++)
179 scheme_define(
180 tab->ctx,
181 tab->ctx->global_env,
182 mk_symbol(tab->ctx, functions[i].name),
183 mk_foreign_func(tab->ctx, functions[i].func));
184
185 return 0;
186 }
187