1 /******************************************************************************
2 * This file is part of TinTin++ *
3 * *
4 * Copyright 2004-2020 Igor van den Hoven *
5 * *
6 * TinTin++ is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 3 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with TinTin++. If not, see https://www.gnu.org/licenses. *
18 ******************************************************************************/
19
20 /******************************************************************************
21 * T I N T I N + + *
22 * *
23 * coded by Igor van den Hoven 2004 *
24 ******************************************************************************/
25
26
27 #include "tintin.h"
28
29 #define DO_CLASS(class) struct session *class(struct session *ses, struct listnode *node, char *arg1, char *arg2)
30
31 extern DO_CLASS(class_assign);
32 extern DO_CLASS(class_clear);
33 extern DO_CLASS(class_close);
34 extern DO_CLASS(class_kill);
35 extern DO_CLASS(class_list);
36 extern DO_CLASS(class_load);
37 extern DO_CLASS(class_open);
38 extern DO_CLASS(class_read);
39 extern DO_CLASS(class_save);
40 extern DO_CLASS(class_size);
41 extern DO_CLASS(class_write);
42
43 typedef struct session *CLASS(struct session *ses, struct listnode *node, char *arg1, char *arg2);
44
45 struct class_type
46 {
47 char * name;
48 CLASS * fun;
49 };
50
51 struct class_type class_table[] =
52 {
53 { "ASSIGN", class_assign },
54 { "CLEAR", class_clear },
55 { "CLOSE", class_close },
56 { "KILL", class_kill },
57 { "LIST", class_list },
58 { "LOAD", class_load },
59 { "OPEN", class_open },
60 { "READ", class_read },
61 { "SAVE", class_save },
62 { "SIZE", class_size },
63 { "WRITE", class_write },
64 { "", NULL },
65 };
66
67 int count_class(struct session *ses, struct listnode *group);
68
DO_COMMAND(do_class)69 DO_COMMAND(do_class)
70 {
71 int i;
72 struct listroot *root;
73 struct listnode *node;
74
75 root = ses->list[LIST_CLASS];
76
77 arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
78 arg = sub_arg_in_braces(ses, arg, arg2, GET_ONE, SUB_VAR|SUB_FUN);
79 arg = sub_arg_in_braces(ses, arg, arg3, GET_ALL, SUB_VAR|SUB_FUN);
80
81 if (*arg1 == 0)
82 {
83 tintin_header(ses, 80, " CLASSES ");
84
85 for (root->update = 0 ; root->update < root->used ; root->update++)
86 {
87 node = root->list[root->update];
88
89 tintin_printf2(ses, "%-20s %4d %6s %6s %3d", node->arg1, count_class(ses, node), !strcmp(ses->group, node->arg1) ? "ACTIVE" : "", atoi(node->arg3) ? "OPEN" : "CLOSED", atoi(node->arg3));
90 }
91 }
92 else if (*arg2 == 0)
93 {
94 class_list(ses, NULL, arg1, arg2);
95 }
96 else
97 {
98 for (i = 0 ; *class_table[i].name ; i++)
99 {
100 if (is_abbrev(arg2, class_table[i].name))
101 {
102 break;
103 }
104 }
105
106 if (*class_table[i].name == 0)
107 {
108 show_error(ses, LIST_COMMAND, "#SYNTAX: CLASS {name} {OPEN|CLEAR|CLOSE|READ|SIZE|WRITE|KILL}.", arg1, capitalize(arg2));
109 }
110 else
111 {
112 node = search_node_list(ses->list[LIST_CLASS], arg1);
113
114 if (node == NULL)
115 {
116 show_info(ses, LIST_CLASS, "#INFO: CLASS {%s} CREATED", arg1);
117
118 check_all_events(ses, EVENT_FLAG_CLASS, 0, 1, "CLASS CREATED", arg1);
119 check_all_events(ses, EVENT_FLAG_CLASS, 1, 1, "CLASS CREATED %s", arg1, arg1);
120
121 node = update_node_list(ses->list[LIST_CLASS], arg1, "", arg3, "");
122 }
123 class_table[i].fun(ses, node, arg1, arg3);
124 }
125 }
126 return ses;
127 }
128
129
count_class(struct session * ses,struct listnode * group)130 int count_class(struct session *ses, struct listnode *group)
131 {
132 int list, cnt, index;
133
134 for (cnt = list = 0 ; list < LIST_MAX ; list++)
135 {
136 if (!HAS_BIT(ses->list[list]->flags, LIST_FLAG_CLASS))
137 {
138 continue;
139 }
140
141 for (index = 0 ; index < ses->list[list]->used ; index++)
142 {
143 if (!strcmp(ses->list[list]->list[index]->group, group->arg1))
144 {
145 cnt++;
146 }
147 }
148 }
149 return cnt;
150 }
151
DO_CLASS(class_assign)152 DO_CLASS(class_assign)
153 {
154 char *tmp = ses->group;
155
156 ses->group = strdup(arg1);
157
158 script_driver(ses, LIST_COMMAND, arg2);
159
160 free(ses->group);
161
162 ses->group = tmp;
163
164 return ses;
165 }
166
DO_CLASS(class_clear)167 DO_CLASS(class_clear)
168 {
169 int type, index;
170
171 check_all_events(ses, EVENT_FLAG_CLASS, 0, 1, "CLASS CLEAR", ses->group);
172 check_all_events(ses, EVENT_FLAG_CLASS, 1, 1, "CLASS CLEAR %s", ses->group, ses->group);
173
174 for (type = 0 ; type < LIST_MAX ; type++)
175 {
176 if (!HAS_BIT(ses->list[type]->flags, LIST_FLAG_CLASS))
177 {
178 continue;
179 }
180
181 for (index = 0 ; index < ses->list[type]->used ; index++)
182 {
183 if (!strcmp(ses->list[type]->list[index]->group, arg1))
184 {
185 delete_index_list(ses->list[type], index--);
186 }
187 }
188 }
189
190 show_message(ses, LIST_CLASS, "#CLASS {%s} HAS BEEN CLEARED.", arg1);
191
192 if (!strcmp(ses->group, arg1))
193 {
194 class_close(ses, node, arg1, arg2);
195 }
196
197 return ses;
198 }
199
DO_CLASS(class_close)200 DO_CLASS(class_close)
201 {
202 node = search_node_list(ses->list[LIST_CLASS], arg1);
203
204 if (node == NULL)
205 {
206 show_message(ses, LIST_CLASS, "#CLASS {%s} NO LONGER EXIST.", arg1);
207 }
208 else
209 {
210 if (atoi(node->arg3) == 0)
211 {
212 show_message(ses, LIST_CLASS, "#CLASS {%s} IS ALREADY CLOSED.", arg1);
213 }
214 else
215 {
216 show_message(ses, LIST_CLASS, "#CLASS {%s} HAS BEEN CLOSED.", arg1);
217
218 update_node_list(ses->list[LIST_CLASS], arg1, "", "0", node->arg4);
219
220 if (!strcmp(ses->group, arg1))
221 {
222 check_all_events(ses, EVENT_FLAG_CLASS, 0, 1, "CLASS DEACTIVATED", ses->group);
223 check_all_events(ses, EVENT_FLAG_CLASS, 1, 1, "CLASS DEACTIVATED %s", ses->group, ses->group);
224
225 node = ses->list[LIST_CLASS]->list[0];
226
227 if (atoi(node->arg3))
228 {
229 RESTRING(ses->group, node->arg1);
230
231 show_message(ses, LIST_CLASS, "#CLASS {%s} HAS BEEN ACTIVATED.", node->arg1);
232
233 check_all_events(ses, EVENT_FLAG_CLASS, 0, 1, "CLASS ACTIVATED", node->arg1);
234 check_all_events(ses, EVENT_FLAG_CLASS, 1, 1, "CLASS ACTIVATED %s", arg1, arg1);
235 }
236 else
237 {
238 RESTRING(ses->group, "");
239 }
240 }
241 }
242 }
243 return ses;
244 }
245
246
DO_CLASS(class_list)247 DO_CLASS(class_list)
248 {
249 int i, j;
250
251 if (search_node_list(ses->list[LIST_CLASS], arg1))
252 {
253 tintin_header(ses, 80, " %s ", arg1);
254
255 for (i = 0 ; i < LIST_MAX ; i++)
256 {
257 if (!HAS_BIT(ses->list[i]->flags, LIST_FLAG_CLASS))
258 {
259 continue;
260 }
261
262 if (*arg2 && !is_abbrev(arg2, list_table[i].name) && !is_abbrev(arg2, list_table[i].name_multi))
263 {
264 continue;
265 }
266
267 for (j = 0 ; j < ses->list[i]->used ; j++)
268 {
269 if (!strcmp(ses->list[i]->list[j]->group, arg1))
270 {
271 show_node(ses->list[i], ses->list[i]->list[j], 0);
272 }
273 }
274 }
275 }
276 else
277 {
278 show_error(ses, LIST_CLASS, "#CLASS {%s} DOES NOT EXIST.", arg1);
279 }
280 return ses;
281 }
282
283
DO_CLASS(class_kill)284 DO_CLASS(class_kill)
285 {
286 int group;
287
288 class_clear(ses, node, arg1, arg2);
289
290 group = search_index_list(ses->list[LIST_CLASS], arg1, NULL);
291
292 delete_index_list(ses->list[LIST_CLASS], group);
293
294 check_all_events(ses, EVENT_FLAG_CLASS, 0, 1, "CLASS DESTROYED", arg1);
295 check_all_events(ses, EVENT_FLAG_CLASS, 1, 1, "CLASS DESTROYED %s", arg1, arg1);
296
297 show_message(ses, LIST_CLASS, "#CLASS {%s} HAS BEEN KILLED.", arg1);
298
299 return ses;
300 }
301
DO_CLASS(class_load)302 DO_CLASS(class_load)
303 {
304 FILE *file;
305
306 if (node->data == NULL)
307 {
308 show_error(ses, LIST_CLASS, "#CLASS {%s} DOES NOT HAVE ANY DATA SAVED.", arg1);
309
310 return ses;
311 }
312
313 file = fmemopen(node->data, (size_t) atoi(node->arg4), "r");
314
315 read_file(ses, file, arg1);
316
317 check_all_events(ses, EVENT_FLAG_CLASS, 0, 1, "CLASS LOAD", arg1);
318 check_all_events(ses, EVENT_FLAG_CLASS, 1, 1, "CLASS LOAD %s", arg1, arg1);
319
320 show_message(ses, LIST_CLASS, "#CLASS {%s} HAS BEEN LOADED FROM MEMORY.", arg1);
321
322 return ses;
323 }
324
DO_CLASS(class_open)325 DO_CLASS(class_open)
326 {
327 int count;
328
329 if (!strcmp(ses->group, arg1))
330 {
331 show_message(ses, LIST_CLASS, "#CLASS {%s} IS ALREADY OPENED AND ACTIVATED.", arg1);
332 }
333 else
334 {
335 if (*ses->group)
336 {
337 check_all_events(ses, EVENT_FLAG_CLASS, 0, 1, "CLASS DEACTIVATED", ses->group);
338 check_all_events(ses, EVENT_FLAG_CLASS, 1, 1, "CLASS DEACTIVATED %s", ses->group, ses->group);
339 }
340 RESTRING(ses->group, arg1);
341
342 count = atoi(ses->list[LIST_CLASS]->list[0]->arg3);
343
344 update_node_list(ses->list[LIST_CLASS], arg1, "", ntos(--count), node->arg4);
345
346 show_message(ses, LIST_CLASS, "#CLASS {%s} HAS BEEN OPENED AND ACTIVATED.", arg1);
347
348 check_all_events(ses, EVENT_FLAG_CLASS, 0, 1, "CLASS ACTIVATED", arg1);
349 check_all_events(ses, EVENT_FLAG_CLASS, 1, 1, "CLASS ACTIVATED %s", arg1, arg1);
350 }
351
352 return ses;
353 }
354
355
DO_CLASS(class_read)356 DO_CLASS(class_read)
357 {
358 class_open(ses, node, arg1, arg2);
359
360 command(ses, do_read, "{%s}", arg2);
361
362 class_close(ses, node, arg1, arg2);
363
364 return ses;
365 }
366
DO_CLASS(class_save)367 DO_CLASS(class_save)
368 {
369 FILE *file;
370 size_t len;
371 int list, index;
372
373 file = open_memstream(&node->data, (size_t *) &len);
374
375 fprintf(file, "%cCLASS {%s} OPEN\n\n", gtd->tintin_char, arg1);
376
377 for (list = 0 ; list < LIST_MAX ; list++)
378 {
379 if (!HAS_BIT(ses->list[list]->flags, LIST_FLAG_CLASS))
380 {
381 continue;
382 }
383
384 for (index = 0 ; index < ses->list[list]->used ; index++)
385 {
386 if (!strcmp(ses->list[list]->list[index]->group, arg1))
387 {
388 write_node(ses, list, ses->list[list]->list[index], file);
389 }
390 }
391 }
392
393 fprintf(file, "\n%cCLASS {%s} CLOSE\n", gtd->tintin_char, arg1);
394
395 fclose(file);
396
397 str_cpy_printf(&node->arg4, "%d", len);
398
399 show_message(ses, LIST_CLASS, "#CLASS {%s} HAS BEEN SAVED TO MEMORY.", arg1);
400
401 return ses;
402 }
403
DO_CLASS(class_size)404 DO_CLASS(class_size)
405 {
406 if (*arg1 == 0 || *arg2 == 0)
407 {
408 show_error(ses, LIST_CLASS, "#SYNTAX: #CLASS {<class name>} SIZE {<variable>}.");
409
410 return ses;
411 }
412
413 set_nest_node_ses(ses, arg2, "%d", count_class(ses, node));
414
415 return ses;
416 }
417
418
DO_CLASS(class_write)419 DO_CLASS(class_write)
420 {
421 FILE *file;
422 int list, index;
423
424 if (*arg2 == 0 || (file = fopen(arg2, "w")) == NULL)
425 {
426 show_error(ses, LIST_CLASS, "#ERROR: #CLASS WRITE {%s} - COULDN'T OPEN FILE TO WRITE.", arg2);
427
428 return ses;
429 }
430
431 fprintf(file, "%cCLASS {%s} OPEN\n\n", gtd->tintin_char, arg1);
432
433 for (list = 0 ; list < LIST_MAX ; list++)
434 {
435 if (!HAS_BIT(ses->list[list]->flags, LIST_FLAG_CLASS))
436 {
437 continue;
438 }
439
440 for (index = 0 ; index < ses->list[list]->used ; index++)
441 {
442 if (!strcmp(ses->list[list]->list[index]->group, arg1))
443 {
444 write_node(ses, list, ses->list[list]->list[index], file);
445 }
446 }
447 }
448
449 fprintf(file, "\n%cCLASS {%s} CLOSE\n", gtd->tintin_char, arg1);
450
451 fclose(file);
452
453 show_message(ses, LIST_CLASS, "#CLASS {%s} HAS BEEN WRITTEN TO FILE.", arg1);
454
455 return ses;
456 }
457