1 /* $Header: /home/yav/catty/fkiss/RCS/kisseve.c,v 1.34 2000/10/17 05:00:59 yav Exp $
2 * KISS event extension
3 * written by yav <yav@bigfoot.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 *
19 * CAUTION!
20 * Experiment of event extension, NOT STANDARD!
21 * These extensions are ONLY for checking technical problems.
22 * Now we are reseaching:
23 * Which functions users need?
24 * What is smart, eazy, simple description style?
25 * These problems are resolved, we'll define advanced KISS officially.
26 * BUT, THAT'S FUNCTIONS AND DESCRIPTION STYLE WILL BE DIFFERENT FROM THIS!
27 *
28 *;@EventHandler ; event extension identifier
29 *;@never() ; never happen, ignore
30 *;@initialize() ; startup event (before reading datas)
31 *;@ ; Caution! at this event
32 *;@ ; nop, debug, shell, unmap actions available.
33 *;@ ; Don't use other actions!
34 *;@ nop() ; No operation
35 *;@ debug("here!\n") ; print string to stderr for debug
36 *;@ ; arg1 string to print
37 *;@ shell("echo Hello `whoami`") ; shell
38 *;@ ; arg1 string passed to shell
39 *;@ ; Caution! No compatibility (OS depend),
40 *;@ ; and this function makes SECURITY HOLE.
41 *;@ ; So, by default this function is disabled.
42 *;@ ; ONLY -eventshell option is specified,
43 *;@ ; this function is enabled.
44 *;@ unmap("facered.cel") ; unmap cell
45 *;@begin() ; begin event (at window is mapped)
46 *;@ timer(1, 3000) ; setup timer
47 *;@ ; (same as randomtimer(arg1, arg2, 1))
48 *;@ randomtimer(1, 3000, 5000) ; setup timer at random
49 *;@ ; After arg2+(rand()%arg3) milliseconds,
50 *;@ ; event alarm(arg1) will be happen.
51 *;@ ; arg1 timer channel number [0, 63]
52 *;@ ; arg2 time (milli-second)
53 *;@ ; 0 <= arg2 <= 32767 (0:disable timer)
54 *;@ ; arg3 range of random time (milli-second)
55 *;@ ; 1 <= arg3 <= 32768-arg2
56 *;@end() ; end event ([quit] is selected)
57 *;@ sound("bye.au") ; play PCM sound
58 *;@ ; arg1 pcm filename (Sun Audio file)
59 *;@alarm(1) ; timer alarm
60 *;@ ; arg1 timer channel number [0, 63]
61 *;@press("vast.cel") ; mouse button press
62 *;@ ; arg1 cell filename or object mark
63 *;@ map("facered.cel") ; map cell
64 *;@ ; arg1 cell filename
65 *;@release("vast.cel") ; mouse button release
66 *;@ ; arg1 cell filename or object mark
67 *;@ unmap("facered.cel") ; unmap cell
68 *;@ ; arg1 cell filename
69 *;@catch(#1) ; catch object
70 *;@ ; arg1 cell filename or object mark
71 *;@ altmap("panties.cel") ; alternate map/unmap cell
72 *;@ ; arg1 cell filename
73 *;@ altmap("panties2.cel")
74 *;@drop(#1) ; release object
75 *;@ ; arg1 cell filename or object mark
76 *;@ altmap("panties.cel")
77 *;@ altmap("panties2.cel")
78 *;@fixcatch(#1) ; catch fixed object
79 *;@ ; arg1 cell filename or object mark
80 *;@ sound("iyaan.au")
81 *;@fixdrop(#1) ; release fixed object (and object return)
82 *;@ ; arg1 cell filename or object mark
83 *;@ move(#1, 10, -2) ; move object
84 *;@ ; arg1 object mark
85 *;@ ; arg2 delta x (pixel)
86 *;@ ; arg3 delta y (pixel)
87 *;@unfix(#1) ; fix value is cleared! pesi pesi done.
88 *;@ ; arg1 cell filename or object mark
89 *;@ changeset(2) ; change set
90 *;@ ; arg1 destination set number [0, setcnt-1]
91 *;@ changecol(2) ; change color group
92 *;@ ; arg1 destination color number [0, palcnt-1]
93 *;@set(1) ; set changed
94 *;@ ; arg1 set number
95 *;@col(1) ; color group changed
96 *;@ ; arg1 color number
97 *;@ quit() ; quit
98 *;@ transparent("a.cel", 8) ; change transparency rate
99 *;@ ; arg1 cell filename
100 *;@ ; arg2 transparency rate add value [-256, 256]
101 *;@ windowsize(-200, -100) ; change top level window size
102 *;@ ; and viewport position is re-centered
103 *;@ ; arg1 width add value (pixel)
104 *;@ ; arg2 height add value (pixel)
105 *;@ viewport(16, 8) ; change viewport position
106 *;@ ; arg1 viewport position x add value (pixel)
107 *;@ ; arg2 viewport position y add value (pixel)
108 *
109 * number
110 * 10 decimal number
111 * 010 (= 8) octal number heading "0"
112 * 0x10 (= 16) hexadecimal number heading "0x"
113 * string
114 * "Sample string" Any string is quoted by double quotation marks.
115 * "\t<- Tab" \t Tab
116 * "Newline ->\n" \n Newline
117 * "\\<-Backslash" \\ Backslash
118 * "\"<- Doublequote" \" Double quotation mark
119 * "\$ <- dollar" \$ Dollar mark
120 * Don't use other \ escaped character!
121 * object mark
122 * #10 Object mark is "#" started number.
123 *
124 */
125
126 char id_kisseve[] = "$Id: kisseve.c,v 1.34 2000/10/17 05:00:59 yav Exp $";
127
128 #include <X11/Xos.h>
129 #include <X11/Xlib.h>
130 #include <stdio.h>
131 #include "config.h"
132 #include "headers.h"
133 #include "fkiss.h"
134 #include "work.h"
135 #include "timer.h"
136 #define PUBLIC_KISSEVE_C
137 #include "extern.h"
138
139
140 /* #define WARN_ACTION 64 -- warn if more actions for one event */
141 /* #define WARN_EVENT 64 -- warn if more event number, now in extern.h */
142 /* #define WARN_SOUNDFILE 64 -- warn if more soundfiles, now in extern.h */
143 /* #define WARN_TIMER 64 -- warn if more timer channels, now in extern.h */
144 /* #define MAXACTION 256 -- maximum action for one event (-> extern.h)*/
145 /* #define MAXEVENT 256 -- maximum event, now in extern.h */
146 /* #define MAXSOUNDFILE 256 -- maximum sound file, now in extern.h */
147 /* #define MAXTIMER 256 -- maximum timer channel, now in extern.h */
148
149
150 /* argument type */
151 #define OT_CEL 1 /* Cell */
152 #define OT_OBJ 2 /* Object */
153 #define OT_SND 3 /* Sound */
154 #define OT_NUM 4 /* Number */
155 #define OT_STR 5 /* String */
156 #define OT_TCH 6 /* Timer channel number */
157 #define OT_SET 7 /* Set number */
158 #define OT_COL 8 /* Color group number */
159
160 #define EOBJN 3 /* maximum number of event arguments */
161 #define AOBJN 3 /* maximum number of action arguments */
162 #if (EOBJN > AOBJN)
163 # define MAXARGN EOBJN
164 #else
165 # define MAXARGN AOBJN
166 #endif
167
168 typedef struct {
169 short type; /* argument type */
170 short no; /* argument code */
171 char *name; /* filename */
172 } EVOBJ; /* argument structure */
173
174 typedef struct {
175 short n; /* action type */
176 EVOBJ aobj[AOBJN]; /* argument */
177 } ACTION;
178
179
180 typedef struct {
181 short elineno; /* cnf line number */
182 short evtype; /* event type */
183 EVOBJ eobj[EOBJN]; /* event argument */
184 short alineno; /* cnf line number action */
185 short actn; /* number of actions (<= MAXACTION) */
186 /* nothing changed with alineno, but it is:*/
187 /* cnf line number of LAST action of event */
188 /* (maybe this is not like it should be ?) */
189 ACTION *act; /* actions */
190 } EVT;
191
192 typedef struct {
193 int channel;
194 struct TMV alarmtime;
195 struct TMV starttime;
196 } TIMER;
197
198
199 static Bool event_ok = False;
200 static EVT *evtbl = NULL; /* event table */
201 static int soundn = 0; /* number of sound files (<= MAXSOUNDFILE) */
202 static char **soundlist = NULL;
203 static TIMER *timertbl = NULL;
204 static int timertbln = 0;
205 static int active_timer; /* number of active timer-channels */
206
207 typedef struct {
208 struct TMV tm0; /* event occured time */
209 long event_delay; /* event delay milliseconds */
210 int redraw_xtop, redraw_ytop;
211 int redraw_xend, redraw_yend;
212 } EVW;
213
214 /* global buffer for error messages, such as "file not found" */
215 static char G_ERRbuf[80] = { '\0', /* fill up the rest */ };
216
217 /* keyword table */
218 typedef struct {
219 char *str; /* keyword */
220 short n; /* code */
221 char argt[MAXARGN+1]; /* argument type (+1 for terminater 0) */
222 } KEYWORD_TABLE;
223
224 #define KTBL(code,name,pt0,pt1,pt2,pt3) \
225 {name, code, {pt0, pt1, pt2, pt3}}
226
227 static KEYWORD_TABLE event_syntax[] = {
228 /* code keyword pt0 pt1 pt2 pt3 */
229 KTBL(EVE_NEVER, "never", 0, 0, 0, 0),
230 KTBL(EVE_INITIALIZE, "initialize", 0, 0, 0, 0),
231 KTBL(EVE_ALARM, "alarm", OT_TCH, 0, 0, 0),
232 KTBL(EVE_BEGIN, "begin", 0, 0, 0, 0),
233 KTBL(EVE_END, "end", 0, 0, 0, 0),
234 KTBL(EVE_PRESS, "press", OT_CEL, 0, 0, 0),
235 KTBL(EVE_RELEASE, "release", OT_CEL, 0, 0, 0),
236 KTBL(EVE_CATCH, "catch", OT_CEL, 0, 0, 0),
237 KTBL(EVE_DROP, "drop", OT_CEL, 0, 0, 0),
238 KTBL(EVE_FIXCATCH, "fixcatch", OT_CEL, 0, 0, 0),
239 KTBL(EVE_FIXDROP, "fixdrop", OT_CEL, 0, 0, 0),
240 KTBL(EVE_UNFIX, "unfix", OT_CEL, 0, 0, 0),
241 KTBL(EVE_SET, "set", OT_SET, 0, 0, 0),
242 KTBL(EVE_COL, "col", OT_COL, 0, 0, 0),
243 KTBL(EVE_IN, "in", OT_OBJ, OT_OBJ, 0, 0),
244 KTBL(EVE_OUT, "out", OT_OBJ, OT_OBJ, 0, 0),
245 KTBL(EVE_STILLIN, "stillin", OT_OBJ, OT_OBJ, 0, 0),
246 KTBL(EVE_STILLOUT, "stillout", OT_OBJ, OT_OBJ, 0, 0),
247 KTBL(EVE_COLLIDE, "collide", OT_CEL, OT_CEL, 0, 0),
248 KTBL(EVE_APART, "apart", OT_CEL, OT_CEL, 0, 0),
249 KTBL(EVE_VERSION, "version", OT_NUM, 0, 0, 0),
250 KTBL(ACT_NOP, "nop", 0, 0, 0, 0),
251 KTBL(ACT_DEBUG, "debug", OT_STR, 0, 0, 0),
252 KTBL(ACT_SHELL, "shell", OT_STR, 0, 0, 0),
253 KTBL(ACT_UNMAP, "unmap", OT_CEL, 0, 0, 0),
254 KTBL(ACT_MAP, "map", OT_CEL, 0, 0, 0),
255 KTBL(ACT_ALTMAP, "altmap", OT_CEL, 0, 0, 0),
256 KTBL(ACT_MOVE, "move", OT_OBJ, OT_NUM, OT_NUM, 0),
257 KTBL(ACT_SOUND, "sound", OT_SND, 0, 0, 0),
258 KTBL(ACT_TIMER, "timer", OT_TCH, OT_NUM, 0, 0),
259 KTBL(ACT_RANDOMTIMER, "randomtimer", OT_TCH, OT_NUM, OT_NUM, 0),
260 KTBL(ACT_QUIT, "quit", 0, 0, 0, 0),
261 KTBL(ACT_CHANGESET, "changeset", OT_SET, 0, 0, 0),
262 KTBL(ACT_CHANGECOL, "changecol", OT_COL, 0, 0, 0),
263 KTBL(ACT_TRANSPARENT, "transparent", OT_CEL, OT_NUM, 0, 0),
264 KTBL(ACT_WINDOWSIZE, "windowsize", OT_NUM, OT_NUM, 0, 0),
265 KTBL(ACT_VIEWPORT, "viewport", OT_NUM, OT_NUM, 0, 0),
266 KTBL(ACT_IFFIXED, "iffixed", OT_OBJ, OT_TCH, OT_NUM, 0),
267 KTBL(ACT_IFNOTFIXED, "ifnotfixed", OT_OBJ, OT_TCH, OT_NUM, 0),
268 KTBL(ACT_IFMAPPED, "ifmapped", OT_CEL, OT_TCH, OT_NUM, 0),
269 KTBL(ACT_IFNOTMAPPED, "ifnotmapped", OT_CEL, OT_TCH, OT_NUM, 0),
270 KTBL(ACT_IFMOVED, "ifmoved", OT_OBJ, OT_TCH, OT_NUM, 0),
271 KTBL(ACT_IFNOTMOVED, "ifnotmoved", OT_OBJ, OT_TCH, OT_NUM, 0),
272 KTBL(ACT_SETFIX, "setfix", OT_OBJ, OT_NUM, 0, 0),
273 KTBL(ACT_MOVEBYX, "movebyx", OT_OBJ, OT_OBJ, OT_NUM, 0),
274 KTBL(ACT_MOVEBYY, "movebyy", OT_OBJ, OT_OBJ, OT_NUM, 0),
275 KTBL(ACT_MOVETO, "moveto", OT_OBJ, OT_NUM, OT_NUM, 0),
276 KTBL(ACT_MOVERANDX, "moverandx", OT_OBJ, OT_NUM, OT_NUM, 0),
277 KTBL(ACT_MOVERANDY, "moverandy", OT_OBJ, OT_NUM, OT_NUM, 0),
278 KTBL(ACT_MOVETORAND, "movetorand", OT_OBJ, 0, 0, 0),
279 KTBL(ACT_MUSIC, "music", OT_SND, 0, 0, 0),
280 KTBL(ACT_NOTIFY, "notify", OT_STR, 0, 0, 0),
281 KTBL(-1, NULL, 0, 0, 0, 0)
282 };
283
284 #define get_syntax(code) (event_syntax + ((code) & ~(BIT_EVENT|BIT_ACTION)))
285
parse_keyword(str)286 int parse_keyword(str)
287 char *str;
288 {
289 KEYWORD_TABLE *p;
290
291 for (p = event_syntax; p->n >= 0; p++) {
292 if (strcmp(str, p->str) == 0)
293 return p->n;
294 }
295 return -1; /* keyword not found */
296 }
297
298
eval_env(str)299 char *eval_env(str)
300 char *str; /* Caution! str destroyed */
301 {
302 char *p;
303 char *ep;
304 int mode;
305
306 p = str;
307 mode = 0;
308 while (!mode && *p) {
309 switch (*p) {
310 case '-':
311 case '=':
312 case '+':
313 case '?':
314 mode = *p;
315 case ':': /* Quick hack, no check ":str" */
316 *p = '\0';
317 /* FALL THROUGH */
318 default:
319 p++;
320 break;
321 }
322 }
323 ep = getenv(str);
324 switch (mode) {
325 case '=':
326 if (ep == NULL) {
327 ep = ks_strdup(p);
328 setenv(str, ep, 0);
329 }
330 break;
331 case '-':
332 if (ep == NULL)
333 ep = ks_strdup(p);
334 break;
335 case '+':
336 if (ep != NULL)
337 ep = ks_strdup(p);
338 break;
339 case '?':
340 if (ep == NULL) {
341 if (!*p)
342 p = "parameter null or not set";
343 fprintf(stderr, "%s: %s: %s\n", *oargv, str, p);
344 }
345 break;
346 }
347 if (ep == NULL)
348 ep = "";
349 return ep; /* Caution! Cannot to free this */
350 }
351
352 /* parse_string - parse string
353 * str
354 * >"hello\tworld Here we go!"
355 * buf (len = 8)
356 * 012345 67
357 * >hello w
358 *
359 * return malloced buffer address
360 *
361 * Analyze:
362 * Heading quotation mark ("/! look quote_charset[])
363 * '\' escaped character (\t \r \n \" \\)
364 * $USER or ${USER} replaced to environment variable "USER"
365 *
366 */
parse_string(p,charset)367 char *parse_string(p, charset)
368 char **p; /* string ptr to parse */
369 char *charset; /* available character set (not quoted)
370 * (NULL:all)
371 */
372 {
373 int c;
374 int quote; /* quote character (0:Not quoted) */
375 Bool escaped; /* \ escaped flag */
376 Bool inkanji; /* at Kanji 2nd byte flag */
377 int in_env, env_brace;
378 LSTR str;
379 LSTR env_name;
380 static char quote_charset[] = "\"/!";
381
382 lstr_init(&str);
383 lstr_init(&env_name);
384 in_env = env_brace = 0;
385 inkanji = escaped = False;
386 quote = (**p && index(quote_charset, **p) != NULL) ? *(*p)++ : 0;
387 while ((c = **p) != '\0') {
388 ++*p;
389 if (escaped) {
390 switch (c) {
391 case 'n': /* Newline */
392 c = '\n';
393 break;
394 case 'r': /* CR */
395 c = '\r';
396 break;
397 case 't': /* Tab */
398 c = '\t';
399 break;
400 default: /* " or \ or $ */
401 break;
402 }
403 escaped = False;
404 } else {
405 if (!inkanji) {
406 if (c == '\\') {
407 escaped = True; /* Escape character */
408 continue;
409 }
410 if (in_env) {
411 if ((env_brace && c == '}') || (!env_brace && !is_alnum(c) && c != '_')) {
412 in_env = 0;
413 lstr_cat(&str, eval_env(env_name.buf));
414 free(env_name.buf);
415 lstr_init(&env_name);
416 if (!env_brace)
417 lstr_ch(&str, c);
418 env_brace = 0;
419 } else {
420 lstr_ch(&env_name, c);
421 }
422 continue;
423 }
424 if (c == '$') { /* Shell variable? */
425 in_env = 1;
426 if (**p == '{') {
427 ++*p;
428 env_brace = 1;
429 } else {
430 env_brace = 0;
431 }
432 continue;
433 }
434 if (quote) {
435 if (c == quote)
436 break; /* quoted, terminated only quote char */
437 } else {
438 if (charset != NULL && index(charset, c) == NULL)
439 break;
440 }
441 }
442 }
443 lstr_ch(&str, c);
444 inkanji = inkanji ? 0 : is_sjis_1st(c & 0xff);
445 }
446 if (inkanji) { /* Kanji 2nd byte? */
447 /* --*p; */
448 lstr_bs(&str);
449 }
450 if (in_env) {
451 lstr_cat(&str, eval_env(env_name.buf));
452 free(env_name.buf);
453 }
454 return str.buf;
455 }
456
457 /*
458 * get token
459 * return malloced token buffer
460 */
get_token(p)461 char *get_token(p)
462 char **p; /* string address to parse */
463 {
464 static char token_set[] =
465 "#-+/.0123456789_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
466
467 while (**p && (**p != '"') && (index(token_set, **p) == NULL))
468 ++*p;
469 return parse_string(p, token_set);
470 }
471
472
addhit(c1,c2)473 void addhit(c1, c2)
474 int c1;
475 int c2;
476 {
477 int hn;
478 HITP *hp;
479 int i;
480
481 hn = (cell+c1)->hitn;
482 hp = (cell+c1)->hitp;
483 for (i = 0; i < hn; i++) {
484 if ((hp + i)->n == c2)
485 return;
486 }
487 if (hp == NULL)
488 hp = (HITP *)ks_malloc(sizeof(*hp));
489 else
490 hp = (HITP *)ks_realloc(hp, (hn + 1) * sizeof(*hp));
491 (hp + hn)->n = c2;
492 (hp + hn)->s = 0;
493 (cell+c1)->hitn = ++hn;
494 (cell+c1)->hitp = hp;
495 }
496
addobjhit(o1,o2)497 void addobjhit(o1, o2)
498 int o1;
499 int o2;
500 {
501 int hn;
502 HITP *hp;
503 int i;
504
505 hn = (object+o1)->ohitn;
506 hp = (object+o1)->ohitp;
507 for (i = 0; i < hn; i++) {
508 if ((hp + i)->n == o2)
509 return;
510 }
511 if (hp == NULL)
512 hp = (HITP *)ks_malloc(sizeof(*hp));
513 else
514 hp = (HITP *)ks_realloc(hp, (hn + 1) * sizeof(*hp));
515 (hp + hn)->n = o2;
516 (hp + hn)->s = 0;
517 (object+o1)->ohitn = ++hn;
518 (object+o1)->ohitp = hp;
519 }
520
init_hitck1(p)521 void init_hitck1(p)
522 EVT *p;
523 {
524 switch (p->evtype) {
525 case EVE_COLLIDE:
526 case EVE_APART:
527 if (p->eobj[0].type != OT_CEL) {
528 msg("W (%d) init_hitck: Not Cel '%s'!\n",
529 p->elineno, p->eobj[0].name);
530 } else if (p->eobj[1].type != OT_CEL) {
531 msg("W (%d) init_hitck: Not Cel '%s'!\n",
532 p->elineno, p->eobj[1].name);
533 } else {
534 addhit(p->eobj[0].no, p->eobj[1].no);
535 addhit(p->eobj[1].no, p->eobj[0].no);
536 }
537 break;
538 case EVE_IN:
539 case EVE_STILLIN:
540 case EVE_OUT:
541 case EVE_STILLOUT:
542 if (p->eobj[0].type != OT_OBJ) {
543 msg("W (%d) init_hitck: Not object '%s'!\n",
544 p->elineno, p->eobj[0].name);
545 } else if (p->eobj[1].type != OT_OBJ) {
546 msg("W (%d) init_hitck: Not object '%s'!\n",
547 p->elineno, p->eobj[1].name);
548 } else {
549 addobjhit(p->eobj[0].no, p->eobj[1].no);
550 addobjhit(p->eobj[1].no, p->eobj[0].no);
551 }
552 break;
553 }
554 }
555
init_hitck()556 void init_hitck()
557 {
558 int i;
559 EVT *p;
560
561 for (p = evtbl, i = 0; i < evn; p++, i++) {
562 init_hitck1(p);
563 }
564 }
565
566 /* cnf_event - parse event description line in KISS configuration file
567 */
cnf_event(p,lineno)568 int cnf_event(p, lineno)
569 char *p;
570 int lineno; /* cnf line number (from 1) */
571 {
572 int i, n, r;
573 char *token;
574 static EVT *evp = NULL;
575
576 if (evtbl == NULL) {
577 if ( ! (evtbl = (EVT *)malloc(sizeof(EVT)*MAXEVENT)) ) {
578 msgset("E out of core while allocating %d bytes for %d events !\n",
579 sizeof(EVT)*MAXEVENT, MAXEVENT);
580 }
581 /* if we reach this point, all went fine */
582 }
583 r = 0;
584 while (*p) {
585 token = get_token(&p);
586 if (!*token) {
587 free(token);
588 break;
589 }
590 n = parse_keyword(token);
591 if (n < 0) {
592 msgset("W ``%s'' unknown keyword.\n", token);
593 free(token);
594 return -1; /* keyword error */
595 }
596 free(token);
597 if (n & BIT_EVENT) {
598 if (evn >= WARN_EVENT) {
599 msgset("W events over %d!\n", WARN_EVENT);
600 r = -1; /* event over error */
601 }
602 if (evn >= MAXEVENT) {
603 MAXEVENT++;
604 /* allocating enough core for 1 event more : */
605 if ( ! (evtbl = (EVT *)realloc(evtbl,sizeof(EVT)*MAXEVENT)) ) {
606 msgset("E out of core while allocating %d bytes for %d events !\n",
607 sizeof(EVT)*MAXEVENT, MAXEVENT);
608 }
609 /* if we reach this point, all went fine */
610 }
611 evp = evtbl + evn++;
612 evp->elineno = lineno;
613 evp->evtype = n;
614 for (i = 0; get_syntax(n)->argt[i]; i++) {
615 evp->eobj[i].name = get_token(&p);
616 }
617 evp->actn = 0;
618 /* allocating core for exactly 1 action (the first) */
619 if ( ! (evp->act = (ACTION *)malloc(sizeof(ACTION))) ) {
620 msgset("E out of core while allocating %d bytes for 1 action !\n",
621 sizeof(ACTION));
622 }
623 } else if (n & BIT_ACTION) {
624 int atmp = 0;
625 ACTION *ap_tmp = NULL;
626 if ( !evp ) {
627 msgset("W action without an event.\n");
628 return -1;
629 }
630 atmp = evp->actn + 2;
631 evp->alineno = lineno;
632 if (evp->actn >= WARN_ACTION) {
633 msgset("W actions over %d!\n", WARN_ACTION);
634 r = -1; /* action over error */
635 }
636 if (evp->actn >= MAXACTION) {
637 msgset("W actions over %d, action ignored!\n", MAXACTION);
638 return -1; /* no space to store action, abort! */
639 }
640 evp->act[evp->actn].n = n;
641 for (i = 0; get_syntax(n)->argt[i]; i++) {
642 evp->act[evp->actn].aobj[i].name = get_token(&p);
643 }
644 /* allocating core for 1 action more */
645 ap_tmp = (ACTION *)realloc(evp->act,sizeof(ACTION)*atmp);
646 if ( ! ap_tmp ) {
647 msgset( "E out of core while allocating %d bytes for %d actions !\n",
648 sizeof(ACTION), atmp);
649 } else { /* this may be unneccesary, but I'm unsure and it doesn't hurt */
650 evp->act = ap_tmp;
651 }
652 evp->actn++;
653 debug_printf("evp->actn=%d,\n", evp->actn);
654 }
655 }
656 return r; /* return error code */
657 }
658
get_named_sound(name)659 int get_named_sound(name)
660 char *name;
661 {
662 int i;
663
664 for (i = 0; i < soundn; i++) {
665 if (strcmp(*(soundlist+i), name) == 0)
666 {
667 debug_printf("<SL:%d>\n", i);
668 return i;
669 }
670 }
671 for (i = 0; i < soundn; i++) {
672 if (strcmp_dos_filename(*(soundlist+i), name) == 0) {
673 if (warncase) {
674 msg("W use sound file ``%s'' instead of ``%s''\n",
675 *(soundlist+i), name);
676 }
677 debug_printf("<SF:%s,%s>\n", *(soundlist+i),name);
678 return i;
679 }
680 }
681 return -1; /* not found */
682 }
683
get_named_cell(name)684 int get_named_cell(name)
685 char *name;
686 {
687 int i;
688
689 for (i = 0; i < celcnt; i++) {
690 if (strcmp((cell+i)->filename, name) == 0)
691 return i;
692 }
693 for (i = 0; i < celcnt; i++) {
694 if (strcmp_dos_filename((cell+i)->filename, name) == 0) {
695 if (warncase) {
696 msg("W use cel file ``%s'' instead of ``%s''\n",
697 (cell+i)->filename, name);
698 }
699 return i;
700 }
701 }
702 return -1; /* not found */
703 }
704
705 /* return registrated objno */
regist_object(type,str,errorcode)706 int regist_object(type, str, errorcode)
707 int type; /* object type */
708 char *str;
709 int *errorcode; /* return error code */
710 {
711 int r;
712
713 r = strtol(str, NULL, 0);
714 switch (type) {
715 case OT_SND:
716 if (soundn >= WARN_SOUNDFILE) {
717 msg("W sound files over %d!\n", WARN_SOUNDFILE);
718 *errorcode = 1;
719 }
720 if (soundn >= MAXSOUNDFILE) {
721 *errorcode = -1;
722 return -1; /* sound file over error */
723 }
724 *(soundlist+soundn++) = ks_strdup(str);
725 return soundn-1;
726 case OT_TCH:
727 #if 0
728 if (r < 0 || r >= MAXTIMER) {
729 msg("W timer channel must be 0 to %d, ignoring timer channel %d !\n",
730 MAXTIMER, r);
731 *errorcode = r = -1;
732 }
733 #endif
734 if (r < 0 || r >= WARN_TIMER) {
735 msg("W timer channels over %d!\n", WARN_TIMER);
736 *errorcode = 1;
737 }
738 break;
739 case OT_SET:
740 if (r < 0 || r >= 10) {
741 msg("W set number must be 0 to %d!\n", setcnt-1);
742 msg("W ignore set number %d.\n", r);
743 *errorcode = r = -1;
744 }
745 break;
746 case OT_COL:
747 if (r < 0 || r >= 10) {
748 msg("W col number must be 0 to %d!\n", palcnt-1);
749 msg("W ignore col number %d.\n", r);
750 *errorcode = r = -1;
751 }
752 break;
753 case OT_NUM:
754 case OT_STR:
755 break;
756 default:
757 *errorcode = r = -1; /* error */
758 }
759 return r;
760 }
761
762 /* return error code
763 * == 0 : no error
764 * > 0 : warning
765 * < 0 : error
766 */
parse_argument(p,str,rtype)767 int parse_argument(p, str, rtype)
768 EVOBJ *p; /* p->type, p->no update */
769 char *str;
770 int rtype; /* default type */
771 {
772 int r;
773
774 r = 0;
775 if (rtype != OT_STR) {
776 switch(*str) {
777 case '#':
778 p->type = OT_OBJ;
779 p->no = strtol(str+1, NULL, 10);
780 break;
781 default:
782 p->type = OT_CEL;
783 p->no = get_named_cell(str);
784 if (p->no < 0) {
785 p->type = OT_SND;
786 p->no = get_named_sound(str);
787 }
788 break;
789 }
790 }
791 if (p->no < 0) {
792 p->type = rtype;
793 p->no = regist_object(rtype, str, &r);
794 sprintf(G_ERRbuf,"''%s'' is not part of any object", str);
795 debug_printf(" obj(%d,%d)=[%s]", p->type, p->no, str);
796 if (p->no < 0 && rtype != OT_NUM && rtype != OT_STR)
797 p->type = -1;
798 } else {
799 debug_printf(" obj(%d,%d)", p->type, p->no);
800 }
801 return r;
802 }
803
804 /* return : line number error detected (0 no error) */
compile_event(n)805 int compile_event(n)
806 int n;
807 {
808 int j, k;
809 int r, errline;
810 EVT *ep;
811 ACTION *ap;
812
813 if (!n) {
814 /* first line allocate work area */
815 soundlist = (char **)ks_malloc(sizeof(char *)*MAXSOUNDFILE);
816 timertbl = (TIMER *)ks_malloc(sizeof(TIMER)*MAXTIMER);
817 timertbln = MAXTIMER;
818 active_timer = 0;
819 /* reset all timers */
820 bzero((char *)timertbl, sizeof(TIMER)*MAXTIMER);
821 }
822 ep = evtbl + n;
823 debug_printf("%6d,%6d:\tevent %d: %s(",
824 ep->elineno, ep->alineno, n, get_syntax(ep->evtype)->str);
825 errline = 0; /* reset error line */
826 for (j = 0; get_syntax(ep->evtype)->argt[j]; j++) {
827 debug_printf("%s%s", !j?"":",", ep->eobj[j].name);
828 r = parse_argument(&ep->eobj[j], ep->eobj[j].name,
829 get_syntax(ep->evtype)->argt[j]);
830 if (r && ep->eobj[j].type != OT_NUM && ep->eobj[j].type != OT_STR) {
831 errline = ep->elineno;
832 if (r < 0) {
833 ep->evtype = 0; /* ignore this event */
834 return errline; /* abort compile */
835 }
836 }
837 }
838 debug_printf(").\n");
839
840 for (ap = ep->act, j = 0; j < ep->actn; ap++, j++) {
841 debug_printf("%6d,%6d:\t action %d: %s(",
842 ep->elineno, ep->alineno, j, get_syntax(ap->n)->str);
843 for (k = 0; get_syntax(ap->n)->argt[k]; k++) {
844 debug_printf("%s%s", !k?"":",", ap->aobj[k].name);
845 r = parse_argument(&ap->aobj[k], ap->aobj[k].name,
846 get_syntax(ap->n)->argt[k]);
847 if (r < 0 && ! debug_mode)
848 msg("W (somewhere between line%6d and line%6d)\n\t\t%s!\n",
849 ep->elineno, ep->alineno, G_ERRbuf);
850 if (r && ap->aobj[k].type != OT_NUM && ap->aobj[k].type != OT_STR) {
851 errline = ep->alineno;
852 if (r < 0)
853 ap->n = ACT_NOP; /* ignore this action */
854 }
855 }
856 debug_printf(").\n");
857 }
858 return errline;
859 }
860
init_redraw_area(evw)861 void init_redraw_area(evw)
862 EVW *evw;
863 {
864 evw->redraw_xtop = imgw;
865 evw->redraw_ytop = imgh;
866 evw->redraw_xend = evw->redraw_yend = 0;
867 }
868
add_redraw_area(evw,x,y,w,h)869 void add_redraw_area(evw, x, y, w, h)
870 EVW *evw;
871 int x;
872 int y;
873 int w;
874 int h;
875 {
876 if (x < evw->redraw_xtop)
877 evw->redraw_xtop = x;
878 if (y < evw->redraw_ytop)
879 evw->redraw_ytop = y;
880 if (x + w > evw->redraw_xend)
881 evw->redraw_xend = x + w;
882 if (y + h > evw->redraw_yend)
883 evw->redraw_yend = y + h;
884 }
885
update_redraw_area(evw)886 void update_redraw_area(evw)
887 EVW *evw;
888 {
889 int w, h;
890
891 w = evw->redraw_xend - evw->redraw_xtop;
892 h = evw->redraw_yend - evw->redraw_ytop;
893 if (w > 0 && h > 0)
894 redraw_cells(evw->redraw_xtop, evw->redraw_ytop, w, h);
895 }
896
delete_timer(ch)897 void delete_timer(ch)
898 int ch;
899 {
900 int i, n;
901 TIMER *p;
902
903 for (p = timertbl, i = 0; i < active_timer; p++, i++) {
904 if (p->channel == ch) {
905 n = active_timer - i - 1;
906 if (n > 0) {
907 bcopy(p+1, p, sizeof(*p)*n);
908 }
909 --active_timer;
910 break;
911 }
912 }
913 }
914
915 /* set timer
916 * starttime = tm0 - event_delay
917 */
set_timer(evw,ch,n)918 void set_timer(evw, ch, n)
919 EVW *evw;
920 int ch;
921 int n;
922 {
923 int i;
924 TIMER *p;
925 TIMER tm;
926
927 delete_timer(ch);
928 if (n == 0 && !wkiss_bug_emulation)
929 return;
930
931 bcopy(&evw->tm0, &tm.starttime, sizeof(struct TMV));
932 add_time(&tm.starttime, -evw->event_delay);
933 bcopy(&tm.starttime, &tm.alarmtime, sizeof(struct TMV));
934 add_time(&tm.alarmtime, n);
935
936 if (active_timer >= timertbln) {
937 timertbln++;
938 timertbl = (TIMER *)ks_realloc(timertbl, sizeof(TIMER)*timertbln);
939 }
940 for (p = timertbl, i = 0; i < active_timer; p++, i++) {
941 if (diff_time(&p->alarmtime, &tm.alarmtime) > 0)
942 break;
943 }
944 i = active_timer - i;
945 if (i > 0) {
946 bcopy(p, p+1, sizeof(TIMER)*i);
947 }
948 bcopy(&tm, p, sizeof(TIMER));
949 p->channel = ch;
950 active_timer++;
951 }
952
953 /* change cell mapping status
954 * return 0: No need to update image
955 */
change_cel_mapping0(evw,p,status)956 int change_cel_mapping0(evw, p, status)
957 EVW *evw;
958 CELL *p;
959 int status;
960 {
961 int n;
962
963 switch (status) {
964 case ACT_UNMAP: /* unmap */
965 if (p->unmap)
966 return 0; /* already unmapped */
967 p->unmap = 1;
968 break;
969 case ACT_MAP: /* map */
970 if (!p->unmap)
971 return 0; /* already mapped */
972 p->unmap = 0;
973 break;
974 case ACT_ALTMAP: /* altmap */
975 p->unmap ^= 1;
976 break;
977 default: /* ??? unknown mode ??? */
978 return 0;
979 }
980 debug_printf("! %s [%s] !\n", p->unmap ? "unmap" : "map", p->filename);
981 if (!p->setflag[cset])
982 return 0; /* no need to update image */
983 n = p->obj;
984 add_redraw_area(evw,
985 (kset[cset].obj+n)->x + p->ofsx,
986 (kset[cset].obj+n)->y + p->ofsy,
987 p->width, p->height);
988 return 1; /* cel mapping status is changed! */
989 }
990
change_cel_mapping(p,status)991 int change_cel_mapping(p, status)
992 CELL *p;
993 int status;
994 {
995 EVW evw;
996 int r;
997
998 init_redraw_area(&evw);
999 r = change_cel_mapping0(&evw, p, status);
1000 update_redraw_area(&evw);
1001 return r;
1002 }
1003
change_aobj_mapping(evw,p,status)1004 int change_aobj_mapping(evw, p, status)
1005 EVW *evw;
1006 EVOBJ *p;
1007 int status;
1008 {
1009 int i, r;
1010
1011 r = 0;
1012 switch(p->type) {
1013 case OT_CEL:
1014 r = change_cel_mapping0(evw, cell+p->no, status);
1015 break;
1016 case OT_OBJ:
1017 for (i = 0; i < celcnt; i++)
1018 if ((cell+i)->obj == p->no)
1019 r |= change_cel_mapping0(evw, cell+i, status);
1020 break;
1021 default:
1022 msg("W change_aobj_mapping: type %d cannot to change mapping\n", p->type);
1023 break;
1024 }
1025 return r;
1026 }
1027
1028 /* change cell transparency level
1029 * return 0: No need to update image
1030 */
change_cel_transparency(evw,p,d)1031 int change_cel_transparency(evw, p, d)
1032 EVW *evw;
1033 CELL *p;
1034 int d; /* transparency add value */
1035 {
1036 int n;
1037
1038 n = p->transparency + d;
1039 if (n < 0)
1040 n = 0;
1041 else if (n > 256)
1042 n = 256;
1043 if (n == p->transparency)
1044 return 0; /* transparency level is not changed! */
1045 debug_printf("! transparency [%s] %d -> %d !\n",
1046 p->filename, p->transparency, n);
1047 if (p->clip == 0) {
1048 p->transparency = n;
1049 return 0; /* just set transparency. transclip */
1050 } /* will be set after we load clip */
1051 set_transparency(p, n);
1052 if (!p->setflag[cset] || p->unmap)
1053 return 0; /* no need to update image */
1054 add_redraw_area(evw,
1055 (kset[cset].obj+p->obj)->x + p->ofsx,
1056 (kset[cset].obj+p->obj)->y + p->ofsy,
1057 p->width, p->height);
1058 return 1; /* cel mapping status is changed! */
1059 }
1060
change_aobj_transparency(evw,p,n)1061 int change_aobj_transparency(evw, p, n)
1062 EVW *evw;
1063 EVOBJ *p;
1064 int n;
1065 {
1066 int i, r;
1067
1068 r = 0;
1069 switch(p->type) {
1070 case OT_CEL:
1071 r = change_cel_transparency(evw, cell+p->no, n);
1072 break;
1073 case OT_OBJ:
1074 for (i = 0; i < celcnt; i++)
1075 if ((cell+i)->obj == p->no)
1076 r |= change_cel_transparency(evw, cell+i, n);
1077 break;
1078 default:
1079 msg("W change_aobj_transparency: type %d cannot to change transparency\n", p->type);
1080 break;
1081 }
1082 return r;
1083 }
1084
cond_set_timer(evw,ap)1085 void cond_set_timer(evw, ap)
1086 EVW *evw;
1087 ACTION *ap;
1088 {
1089 int f;
1090
1091 f = 0;
1092 switch (ap->n) {
1093 case ACT_IFMOVED:
1094 f = ((kset[cset].obj+ap->aobj[0].no)->x !=
1095 (kset[cset].obj+ap->aobj[0].no)->ox ||
1096 (kset[cset].obj+ap->aobj[0].no)->y !=
1097 (kset[cset].obj+ap->aobj[0].no)->oy);
1098 break;
1099 case ACT_IFNOTMOVED:
1100 f = ((kset[cset].obj+ap->aobj[0].no)->x ==
1101 (kset[cset].obj+ap->aobj[0].no)->ox &&
1102 (kset[cset].obj+ap->aobj[0].no)->y ==
1103 (kset[cset].obj+ap->aobj[0].no)->oy);
1104 break;
1105 case ACT_IFFIXED:
1106 f = ((object + ap->aobj[0].no)->pesi >= (object + ap->aobj[0].no)->fix);
1107 break;
1108 case ACT_IFNOTFIXED:
1109 f = ((object + ap->aobj[0].no)->pesi < (object + ap->aobj[0].no)->fix);
1110 break;
1111 case ACT_IFMAPPED:
1112 f = !(cell + ap->aobj[0].no)->unmap;
1113 break;
1114 case ACT_IFNOTMAPPED:
1115 f = (cell + ap->aobj[0].no)->unmap;
1116 break;
1117 }
1118 if (!f)
1119 return;
1120
1121 set_timer(evw, ap->aobj[1].no, ap->aobj[2].no);
1122 debug_printf("! %s(%d,%d,%d) ",
1123 get_syntax(ap->n)->str,
1124 ap->aobj[0].no, ap->aobj[1].no, ap->aobj[2].no);
1125 if (ap->aobj[2].no)
1126 debug_printf("%.19s.%06ld ",
1127 ctime(&(timertbl+ap->aobj[1].no)->starttime.tv_sec),
1128 (timertbl+ap->aobj[1].no)->starttime.tv_usec);
1129 debug_printf(" !\n");
1130 }
1131
act_move(evw,ap)1132 int act_move(evw, ap)
1133 EVW *evw;
1134 ACTION *ap;
1135 {
1136 int x, y;
1137 int n, r;
1138 int i;
1139 EVHITWK hit;
1140 AREA ar;
1141 extern EVHITWK mouse_move_hit; /* fkiss.c */
1142 extern int moving_object; /* fkiss.c */
1143 int mo;
1144
1145 r = 0;
1146 n = ap->aobj[0].no;
1147 if (ap->aobj[0].type == OT_CEL)
1148 n = (cell+n)->obj;
1149 mo = moving_object;
1150 if (mo >= 0) {
1151 moving_object = -1;
1152 move_object_end(&mouse_move_hit);
1153 }
1154 move_object_start(&hit, n);
1155 x = (kset[cset].obj+n)->x;
1156 y = (kset[cset].obj+n)->y;
1157 switch (ap->n) {
1158 case ACT_MOVE:
1159 x += ap->aobj[1].no;
1160 y += ap->aobj[2].no;
1161 break;
1162 case ACT_MOVEBYX:
1163 x = (kset[cset].obj+ap->aobj[1].no)->x + ap->aobj[2].no;
1164 break;
1165 case ACT_MOVEBYY:
1166 y = (kset[cset].obj+ap->aobj[1].no)->y + ap->aobj[2].no;
1167 break;
1168 case ACT_MOVETO:
1169 x = ap->aobj[1].no;
1170 y = ap->aobj[2].no;
1171 break;
1172 case ACT_MOVERANDX:
1173 i = ap->aobj[2].no - ap->aobj[1].no ;
1174 if (i > 0)
1175 x += ap->aobj[1].no + ks_rand() % (i+1);
1176 break;
1177 case ACT_MOVERANDY:
1178 i = ap->aobj[2].no - ap->aobj[1].no;
1179 if (i > 0)
1180 y += ap->aobj[1].no + ks_rand() % (i+1);
1181 break;
1182 case ACT_MOVETORAND:
1183 i = imgw - (object+n)->width;
1184 if (i > 0)
1185 x = ks_rand() % (i+1);
1186 i = imgh - (object+n)->height;
1187 if (i > 0)
1188 y = ks_rand() % (i+1);
1189 break;
1190 }
1191 if (move_object2(n, x, y,&ar)) {
1192 add_redraw_area(evw, ar.x, ar.y, ar.w, ar.h);
1193 r |= ACTBIT_MAP;
1194 debug_printf("! %s(%d,%d,%d) !\n", get_syntax(ap->n)->str, n, x, y);
1195 }
1196 move_object_end(&hit);
1197 if (mo >= 0) {
1198 move_object_start(&mouse_move_hit, mo);
1199 moving_object = mo;
1200 }
1201 return r;
1202 }
1203
1204 /*
1205 * return changed status infrmation bits
1206 * ACTBIT_SOUND:on sound played
1207 * ACTBIT_MAP:on cell mapping status changed, need to update image
1208 */
event_action(evw,p,r)1209 int event_action(evw, p, r)
1210 EVW *evw;
1211 EVT *p;
1212 int r;
1213 {
1214 int i, n;
1215 int mapping_action;
1216 int newset, newcol;
1217 int w, h;
1218 ACTION *ap;
1219
1220 newset = newcol = -1;
1221 for (ap = p->act, i = 0; i < p->actn; ap++, i++) {
1222 n = mapping_action = 0;
1223 switch(ap->n) {
1224 case ACT_MUSIC:
1225 case ACT_SOUND:
1226 debug_printf("! sound(%s) !\n", *(soundlist+ap->aobj[0].no));
1227 bg_play(*(soundlist+ap->aobj[0].no));
1228 r |= ACTBIT_SOUND;
1229 break;
1230 case ACT_MAP:
1231 case ACT_UNMAP:
1232 case ACT_ALTMAP:
1233 mapping_action = ap->n;
1234 break;
1235 case ACT_CHANGESET:
1236 newset = ap->aobj[0].no;
1237 break;
1238 case ACT_CHANGECOL:
1239 newcol = ap->aobj[0].no;
1240 break;
1241 case ACT_RANDOMTIMER:
1242 if (ap->aobj[1].no && ap->aobj[2].no)
1243 n = ks_rand() % ap->aobj[2].no;
1244 /* FALL THROUGH */
1245 case ACT_TIMER:
1246 n += ap->aobj[1].no;
1247 set_timer(evw, ap->aobj[0].no, n);
1248 debug_printf("! timer(%d,%d) ", ap->aobj[0].no, n);
1249 if (n)
1250 debug_printf("%.19s.%06ld ",
1251 ctime(&(timertbl+ap->aobj[0].no)->starttime.tv_sec),
1252 (timertbl+ap->aobj[0].no)->starttime.tv_usec);
1253 debug_printf(" !\n");
1254 break;
1255 case ACT_IFMOVED:
1256 case ACT_IFNOTMOVED:
1257 case ACT_IFFIXED:
1258 case ACT_IFNOTFIXED:
1259 case ACT_IFMAPPED:
1260 case ACT_IFNOTMAPPED:
1261 cond_set_timer(evw, ap);
1262 break;
1263 case ACT_SETFIX:
1264 debug_printf("! setfix(%d,%d) !\n", ap->aobj[0].no, ap->aobj[1].no);
1265 (object + ap->aobj[0].no)->fix = ap->aobj[1].no;
1266 /* (object + ap->aobj[0].no)->pesi = 0; */
1267 if (!ap->aobj[1].no) {
1268 kissevent_handler2(EVE_UNFIX, ap->aobj[0].no, 1);
1269 }
1270 break;
1271 case ACT_MOVE:
1272 case ACT_MOVEBYX:
1273 case ACT_MOVEBYY:
1274 case ACT_MOVETO:
1275 case ACT_MOVERANDX:
1276 case ACT_MOVERANDY:
1277 case ACT_MOVETORAND:
1278 r |= act_move(evw, ap);
1279 break;
1280 case ACT_TRANSPARENT:
1281 debug_printf("! transparent(%d,%d) !\n", ap->aobj[0].no, ap->aobj[1].no);
1282 if (change_aobj_transparency(evw, &ap->aobj[0], ap->aobj[1].no))
1283 r |= ACTBIT_MAP;
1284 break;
1285 case ACT_WINDOWSIZE:
1286 debug_printf("! windowsize(%d,%d) !\n", ap->aobj[0].no, ap->aobj[1].no);
1287 w = topw + ap->aobj[0].no;
1288 if (w < 1)
1289 w = 1;
1290 h = toph + ap->aobj[1].no;
1291 if (h < 1)
1292 h = 1;
1293 XResizeWindow(dsp, topwin, w, h);
1294 break;
1295 case ACT_VIEWPORT:
1296 debug_printf("! viewport(%d,%d) !\n", ap->aobj[0].no, ap->aobj[1].no);
1297 scrdx = -ap->aobj[0].no;
1298 scrdy = -ap->aobj[1].no;
1299 break;
1300 case ACT_SHELL:
1301 debug_printf("! shell(%s) !\n", ap->aobj[0].name);
1302 if (enable_event_shell)
1303 bg_shell(ap->aobj[0].name);
1304 break;
1305 case ACT_NOTIFY:
1306 debug_printf("! notify(%s) !\n", ap->aobj[0].name);
1307 fputs(ap->aobj[0].name, stderr);
1308 break;
1309 case ACT_DEBUG:
1310 debug_printf("! debug(%s) !\n", ap->aobj[0].name);
1311 fputs(ap->aobj[0].name, stderr);
1312 break;
1313 case ACT_QUIT:
1314 debug_printf("! quit !\n");
1315 change_menu_func(1); /* Quit */
1316 break;
1317 default:
1318 break;
1319 }
1320 if (mapping_action) {
1321 /* EVHITWK hit; */
1322
1323 n = ap->aobj[0].no;
1324 if (ap->aobj[0].type == OT_CEL)
1325 n = (cell + n)->obj;
1326 /* move_object_start(&hit, n); */
1327 if (change_aobj_mapping(evw, &ap->aobj[0], mapping_action)) {
1328 r |= ACTBIT_MAP;
1329 }
1330 /* move_object_end(&hit); */
1331 }
1332 }
1333 if (newset != -1 || newcol != -1)
1334 change_setpal(newset, newcol);
1335 return r;
1336 }
1337
1338
handler_sub(evw,type,arg,arg2)1339 int handler_sub(evw, type, arg, arg2)
1340 EVW *evw;
1341 int type;
1342 int arg;
1343 int arg2;
1344 {
1345 int i, r, n;
1346 int f, noredraw;
1347 EVT *ep;
1348
1349 debug_printf("event: %s, arg: %d,%d at %.19s.%06ld\n",
1350 get_syntax(type)->str, arg, arg2,
1351 ctime(&evw->tm0.tv_sec), evw->tm0.tv_usec);
1352 init_redraw_area(evw);
1353 r = noredraw = 0;
1354 for (ep = evtbl, i = 0; i < evn; ep++, i++) {
1355 if (ep->evtype != type)
1356 continue; /* no match, check next */
1357 n = arg;
1358 #if 0
1359 /* EMK's changes */
1360 if (type == EVE_SET || type == EVE_COL)
1361 noredraw = 1;
1362 #endif
1363 switch (type) {
1364 case EVE_INITIALIZE:
1365 noredraw = 1;
1366 /* FALL THROUGH */
1367 case EVE_BEGIN:
1368 case EVE_END:
1369 f = 1;
1370 break;
1371 case EVE_UNFIX:
1372 if (arg2) {
1373 f = (ep->eobj[0].type == OT_OBJ && ep->eobj[0].no == n);
1374 break;
1375 }
1376 /* FALL THROUGH */
1377 case EVE_PRESS:
1378 case EVE_RELEASE:
1379 case EVE_CATCH:
1380 case EVE_DROP:
1381 case EVE_FIXCATCH:
1382 case EVE_FIXDROP:
1383 if (ep->eobj[0].type == OT_OBJ && n >= 0)
1384 n = (cell+n)->obj;
1385 /* FALL THROUGH */
1386 case EVE_ALARM:
1387 case EVE_SET:
1388 case EVE_COL:
1389 f = (n == ep->eobj[0].no);
1390 break;
1391 case EVE_VERSION:
1392 f = (n >= ep->eobj[0].no);
1393 break;
1394 case EVE_COLLIDE:
1395 case EVE_APART:
1396 case EVE_IN:
1397 case EVE_STILLIN:
1398 case EVE_OUT:
1399 case EVE_STILLOUT:
1400 f = (n == ep->eobj[0].no && arg2 == ep->eobj[1].no)
1401 || (n == ep->eobj[1].no && arg2 == ep->eobj[0].no);
1402 break;
1403 default: /* others, Not implemented */
1404 f = 0;
1405 break;
1406 }
1407 if (f)
1408 r |= event_action(evw, ep, r);
1409 }
1410 if (r & ACTBIT_MAP && !noredraw) /* cell mapping status changed? */
1411 update_redraw_area(evw);
1412 return r;
1413 }
1414
kissevent_handler2(type,arg,arg2)1415 int kissevent_handler2(type, arg, arg2)
1416 int type;
1417 int arg;
1418 int arg2;
1419 {
1420 EVW evw;
1421
1422 if (!event_ok)
1423 return 0;
1424 current_time(&evw.tm0);
1425 evw.event_delay = 0;
1426 return handler_sub(&evw, type, arg, arg2);
1427 }
1428
kissevent_handler(type,arg)1429 int kissevent_handler(type, arg)
1430 int type;
1431 int arg;
1432 {
1433 return kissevent_handler2(type, arg, 0);
1434 }
1435
1436 /* initialise random seed */
init_rand()1437 void init_rand()
1438 {
1439 int i;
1440 struct TMV tm0;
1441
1442 i = randseed;
1443 if (!i) {
1444 current_time(&tm0);
1445 i = tm0.tv_sec;
1446 }
1447 ks_srand(i);
1448 }
1449
1450 typedef struct {
1451 long filesize;
1452 char *pathname;
1453 } SOUND_SORT_TABLE;
1454
sound_cache_prio(p0,p1)1455 int sound_cache_prio(p0, p1)
1456 SOUND_SORT_TABLE *p0;
1457 SOUND_SORT_TABLE *p1;
1458 {
1459 return p0->filesize - p1->filesize;
1460 }
1461
1462 /* preload sound data to cache buffer
1463 * from small to big size sound file
1464 */
preload_sound_cache()1465 void preload_sound_cache()
1466 {
1467 int i;
1468 SOUND_SORT_TABLE *sstbl, *p;
1469 long total;
1470 char *buf;
1471
1472 if (!sound_mode)
1473 return;
1474 /* check True sound file name */
1475 for (i = 0; i < soundn; i++) {
1476 buf = ks_filename(*(soundlist+i));
1477 if (buf) {
1478 free(*(soundlist+i));
1479 *(soundlist+i) = buf;
1480 }
1481 }
1482 sstbl = (SOUND_SORT_TABLE *)malloc(sizeof(SOUND_SORT_TABLE) * soundn);
1483 if (sstbl == NULL)
1484 return;
1485 for (p = sstbl, i = 0; i < soundn; p++, i++) {
1486 p->pathname = *(soundlist+i);
1487 p->filesize = sound_filesize(*(soundlist+i));
1488 }
1489 qsort(sstbl, soundn, sizeof(SOUND_SORT_TABLE), sound_cache_prio);
1490 total = 0;
1491 for (p = sstbl, i = 0; i < soundn; p++, i++) {
1492 if (p->filesize < 0)
1493 continue; /* unknown size, ignore */
1494 if (total + p->filesize > sound_cache_limit)
1495 break; /* total size over limit! */
1496 if (sound_cache(p->pathname) >= 0) {
1497 debug_printf("preload sound file ``%s''\t(%8ld bytes).\n",
1498 p->pathname, p->filesize);
1499 total += p->filesize;
1500 }
1501 }
1502 debug_printf("preloaded sound total %8ld bytes (limit %8ld bytes).\n",
1503 total, sound_cache_limit);
1504 free(sstbl);
1505 }
1506
kissevent_initialize()1507 int kissevent_initialize()
1508 {
1509 init_rand();
1510 preload_sound_cache();
1511 event_ok = True;
1512 kissevent_handler(EVE_INITIALIZE, 0);
1513 return 0;
1514 }
1515
kissevent_timer()1516 void kissevent_timer()
1517 {
1518 int i, ch;
1519 EVW evw;
1520
1521 if (!event_ok || !active_timer)
1522 return; /* active timer channel is not exist */
1523 current_time(&evw.tm0);
1524 for (i = 0; i < active_timer; i++) {
1525 evw.event_delay = diff_time(&evw.tm0, &(timertbl+i)->alarmtime);
1526 if (evw.event_delay >= 0) {
1527 debug_printf("event_delay = %ld\n", evw.event_delay);
1528 ch = (timertbl+i)->channel;
1529 /* reset timer */
1530 delete_timer(ch);
1531 handler_sub(&evw, EVE_ALARM, ch, 0);
1532 break;
1533 }
1534 }
1535 }
1536
get_sleep_time()1537 int get_sleep_time()
1538 {
1539 int i, r;
1540 long lefttime;
1541 TIMER *p;
1542 struct TMV tm0;
1543
1544 r = sleep_tick;
1545 if (!event_ok || !active_timer)
1546 return r; /* active timer channel is not exist */
1547 current_time(&tm0);
1548 for (p = timertbl, i = 0; i < active_timer; p++, i++) {
1549 lefttime = diff_time(&p->alarmtime, &tm0);
1550 if (lefttime < 0)
1551 return 0; /* time over! Don't sleep */
1552 if (r > lefttime)
1553 r = lefttime;
1554 }
1555 return r;
1556 }
1557
1558 /* End of file */
1559