error.[ch]: fix keyword usage
[0verkill.git] / editor.c
blobecafdc649dac59f6b9a1e2003af08cf1d62d4be6
1 #include <signal.h>
2 #include <errno.h>
3 #include <unistd.h>
4 #include <stdio.h>
5 #include <stdlib.h>
7 #include "sprite.h"
8 #include "console.h"
9 #include "blit.h"
10 #include "data.h"
11 #include "cfg.h"
12 #include "hash.h"
13 #include "time.h"
14 #include "error.h"
16 /* defines for help */
17 #define HELP_WIDTH 78
18 #define HELP_HEIGHT 22
19 #define HELP_X ((SCREEN_X-2-HELP_WIDTH)>>1)
20 #define HELP_Y ((SCREEN_Y-2-HELP_HEIGHT)>>1)
23 unsigned long id; /* id of last object */
24 int xoffset=0,yoffset=0; /* coordinates of upper left corner of the screen */
25 int x=0,y=0; /* cursor coordinates on the screen */
26 int oldx=0,oldy=0; /* old cursor position */
28 struct object_list objects;
29 struct object_list *last_obj;
30 int level_number;
33 void catch_signal(int sig_num)
35 c_shutdown();
36 exit(sig_num);
40 void catch_sigsegv(int sig_num)
42 c_shutdown();
43 raise(SIGSEGV);
44 exit(sig_num);
48 void set_sigint(void)
50 struct sigaction sa_old;
51 struct sigaction sa_new;
53 sa_new.sa_handler = catch_signal;
54 sigemptyset(&sa_new.sa_mask);
55 sa_new.sa_flags = 0;
56 sigaction(SIGINT,&sa_new,&sa_old);
57 sigaction(SIGQUIT,&sa_new,&sa_old);
58 sigaction(SIGTERM,&sa_new,&sa_old);
59 sigaction(SIGABRT,&sa_new,&sa_old);
60 sigaction(SIGILL,&sa_new,&sa_old);
61 sigaction(SIGFPE,&sa_new,&sa_old);
62 sigaction(SIGBUS,&sa_new,&sa_old);
64 sa_new.sa_handler = catch_sigsegv;
65 sigemptyset(&sa_new.sa_mask);
66 sa_new.sa_flags = 0;
67 sigaction(SIGSEGV,&sa_new,&sa_old);
71 /* shows the help window */
72 void help(void)
74 draw_frame(HELP_X,HELP_Y,HELP_WIDTH,HELP_HEIGHT,14);
75 print2screen(HELP_X+((HELP_WIDTH-4)>>1),HELP_Y+1,12,"HELP");
76 print2screen(HELP_X+((HELP_WIDTH-9)>>1),HELP_Y+3,11,"SCROLLING");
78 /* cursor moving help */
79 print2screen(HELP_X+8,HELP_Y+4,4,"CURSOR MOVING:");
80 print2screen(HELP_X+13,HELP_Y+5,8,"UP");
81 print2screen(HELP_X+12,HELP_Y+6,8,"[/\\]");
82 print2screen(HELP_X+2,HELP_Y+7,8,"LEFT [<-] [\\/] [->] RIGHT");
83 print2screen(HELP_X+12,HELP_Y+8,8,"DOWN");
85 /* screen moving help */
86 print2screen(HELP_X+31,HELP_Y+4,4,"SCROLLING (NUMPAD!):");
87 print2screen(HELP_X+39,HELP_Y+5,8,"UP");
88 print2screen(HELP_X+39,HELP_Y+6,8,"[8]");
89 print2screen(HELP_X+31,HELP_Y+7,8,"LEFT [4] [6] RIGHT");
90 print2screen(HELP_X+39,HELP_Y+8,8,"[2]");
91 print2screen(HELP_X+38,HELP_Y+9,8,"DOWN");
93 /* item moving help */
94 print2screen(HELP_X+60,HELP_Y+4,4,"ITEM MOVING:");
95 print2screen(HELP_X+65,HELP_Y+5,8,"UP");
96 print2screen(HELP_X+64,HELP_Y+6,8,"[W]");
97 print2screen(HELP_X+55,HELP_Y+7,8,"LEFT [A] [S] [D] RIGHT");
98 print2screen(HELP_X+64,HELP_Y+8,8,"DOWN");
100 /* now the keys */
101 print2screen(HELP_X+((HELP_WIDTH-4)>>1),HELP_Y+11,11,"KEYS");
102 print2screen(HELP_X+((HELP_WIDTH-11)>>1),HELP_Y+12,8,"BUILD - [N]");
103 print2screen(HELP_X+((HELP_WIDTH-12)>>1),HELP_Y+13,8,"DELETE - [X]");
104 print2screen(HELP_X+((HELP_WIDTH-19)>>1),HELP_Y+14,8,"TYPE CHANGE - [TAB], [T] (+ [SHIFT] =reverse)");
105 print2screen(HELP_X+((HELP_WIDTH-11)>>1),HELP_Y+15,8,"SAVE - [F2]");
106 print2screen(HELP_X+((HELP_WIDTH-11)>>1),HELP_Y+16,8,"HELP - [F1]");
107 print2screen(HELP_X+((HELP_WIDTH-26)>>1),HELP_Y+17,8,"ITEM CHANGE - ([+] and [-])");
109 blit_screen(1);
110 sleep(2);
115 /* load static data */
116 void load_room(char * filename)
118 FILE * stream;
119 static char line[1024];
120 char *p,*q,*name;
121 int n,x,y,t;
123 if (!(stream=fopen(filename,"rb")))
125 char msg[256];
126 snprintf(msg,sizeof(msg),"Can't open file \"%s\"!\n",filename);
127 ERROR(msg);
128 EXIT(1);
130 while(fgets(line,1024,stream))
132 p=line;
133 _skip_ws(&p);
134 for (name=p;(*p)!=' '&&(*p)!=9&&(*p)!=10&&(*p);p++);
135 if (!(*p))continue;
136 *p=0;p++;
137 _skip_ws(&p);
138 t=*p;
139 p++;
140 _skip_ws(&p);
141 x=strtol(p,&q,0);
142 _skip_ws(&q);
143 y=strtol(q,&p,0);
144 if (find_sprite(name,&n))
146 char msg[256];
147 snprintf(msg,sizeof(msg),"Unknown bitmap name \"%s\"!\n",name);
148 ERROR(msg);
149 EXIT(1);
151 new_obj(id,t,0,n,0,0,x,y,0,0,0);
152 id++;
154 fclose(stream);
159 /* draw view */
160 void draw_scene(void)
162 struct object_list *p;
164 for(p=&objects;p->next;p=p->next)
167 p->next->member.anim_pos++;
168 p->next->member.anim_pos%=sprites[p->next->member.sprite].n_steps;
169 put_sprite(
170 p->next->member.x-xoffset,
171 p->next->member.y-yoffset,
172 sprites[p->next->member.sprite].positions+sprites[p->next->member.sprite].steps[p->next->member.anim_pos],0
178 /* find object under cursor */
179 struct it * find_object(void)
181 struct object_list *p;
182 #define O p->next->member
184 for(p=&objects;p->next;p=p->next)
186 if (
187 O.x<=x+xoffset&&
188 O.x+sprites[O.sprite].positions[0].lines[0].len-1>=x+xoffset&&
189 O.y<=y+yoffset&&
190 O.y+sprites[O.sprite].positions[0].n-1>=y+yoffset
192 return &(p->next->member);
194 return 0;
198 /* next type when 't' is pressed */
199 int next_type(int type)
201 /* static objects: b, f, j, i, w */
202 /* dynamic objects: N, F, B, S, U, R, 1, 2, 3, 4, 5, M, A, I, K */
203 switch(type)
205 case 'b': return 'f';
206 case 'f': return 'j';
207 case 'j': return 'i';
208 case 'i': return 'w';
209 case 'w': return 'N';
210 case 'N': return 'F';
211 case 'F': return 'B';
212 case 'B': return 'S';
213 case 'S': return 'U';
214 case 'U': return 'R';
215 case 'R': return '1';
216 case '1': return '2';
217 case '2': return '3';
218 case '3': return '4';
219 case '4': return '5';
220 case '5': return 'M';
221 case 'M': return 'A';
222 case 'A': return 'I';
223 case 'I': return 'K';
225 default: return 'b';
230 /* prev type when 'T' is pressed */
231 int prev_type(int type)
233 /* static objects: b, f, j, i, w */
234 /* dynamic objects: N, F, B, S, U, R, 1, 2, 3, 4, 5, M, A, I, K */
235 /* but now in reverse order */
236 switch(type)
238 case 'b': return 'K';
239 case 'f': return 'b';
240 case 'j': return 'f';
241 case 'i': return 'j';
242 case 'w': return 'i';
243 case 'N': return 'w';
244 case 'F': return 'N';
245 case 'B': return 'F';
246 case 'S': return 'B';
247 case 'U': return 'S';
248 case 'R': return 'U';
249 case '1': return 'R';
250 case '2': return '1';
251 case '3': return '2';
252 case '4': return '3';
253 case '5': return '4';
254 case 'M': return '5';
255 case 'A': return 'M';
256 case 'I': return 'A';
258 default: return 'I';
263 /* save level */
264 void save_data(void)
266 FILE *data, *dynamic;
267 struct object_list *p;
268 static char txt[1024];
269 char *LEVEL=load_level(level_number);
271 snprintf(txt,1024,"%s%s%s",DATA_PATH,LEVEL,STATIC_DATA_SUFFIX);
272 data=fopen(txt,"w");
273 if (!data)
275 char msg[256];
276 snprintf(msg,256,"Can't create file \"%s\"\n",txt);
277 ERROR(msg);
278 EXIT(1);
281 snprintf(txt,1024,"%s%s%s",DATA_PATH,LEVEL,DYNAMIC_DATA_SUFFIX);
282 mem_free(LEVEL);
283 dynamic=fopen(txt,"w");
284 if (!dynamic)
286 char msg[256];
287 snprintf(msg,256,"Can't create file \"%s\"\n",txt);
288 ERROR(msg);
289 EXIT(1);
292 #define O p->next->member
294 for(p=&objects;p->next;p=p->next)
296 snprintf(txt,sizeof(txt),"%s %c %d %d\n",sprite_names[O.sprite],O.type,O.x,O.y);
297 switch (O.type)
299 case 'b':
300 case 'w':
301 case 'i':
302 case 'j':
303 case 'f':
304 fputs(txt,data);
305 break;
307 default:
308 fputs(txt,dynamic);
309 break;
312 fclose(data);
313 fclose(dynamic);
318 /* change size of the screen */
319 void sigwinch_handler(int signum)
321 signum=signum;
322 resize_screen();
323 #ifdef WIN32
324 c_shutdown();
325 c_init(SCREEN_X,SCREEN_Y);
326 #endif
327 c_cls();
328 c_refresh();
329 #ifndef WIN32
330 #ifdef SIGWINCH
331 signal(SIGWINCH,sigwinch_handler);
332 #endif
333 #endif
337 void clear_memory(void)
339 struct object_list *o;
341 for (o=&objects;o->next;)
342 delete_obj(o->next->member.id);
344 free_area();
345 free_sprites(0);
346 shutdown_sprites();
350 int main(int argc, char**argv)
352 int update=1;
353 unsigned char bg=' ';
354 unsigned char color=0;
356 unsigned int cur_obj=0;
357 unsigned char cur_type='w';
359 struct it* obj=0;
360 char txt[256];
361 unsigned long_long last_time;
362 char *LEVEL;
364 chdir_to_data_files();
365 set_sigint();
367 while(1)
369 int a;
370 char *c;
372 a=getopt(argc, argv, "hl:");
373 switch(a)
375 case EOF:
376 goto done;
378 case '?':
379 case ':':
380 exit(1);
382 case 'h':
383 printf(
384 "0verkill editor\n"
385 "Usage: editor [-h] [-l <level number>]\n"
387 exit(0);
389 case 'l':
390 level_number=strtoul(optarg,&c,10);
391 if (*c){ERROR("Error: Not a number.\n");EXIT(1);}
392 if (errno==ERANGE)
394 if (!level_number){ERROR("Error: Number underflow.\n");EXIT(1);}
395 else {ERROR("Error: Number overflow.\n");EXIT(1);}
397 break;
400 done:
402 last_obj=&objects;
404 #ifdef SIGWINCH
405 signal(SIGWINCH,sigwinch_handler);
406 #endif
407 c_get_size(&SCREEN_X,&SCREEN_Y);
408 hash_table_init();
409 init_sprites();
410 init_area();
411 LEVEL=load_level(level_number);
412 if (!LEVEL){fprintf(stderr,"Can't load level number %d\n",level_number);exit(1);}
413 snprintf(txt,256,"%s%s%s",DATA_PATH,LEVEL,LEVEL_SPRITES_SUFFIX);
414 load_sprites(txt);
415 snprintf(txt,256,"%s%s%s",DATA_PATH,LEVEL,STATIC_DATA_SUFFIX);
416 load_room(txt);
417 snprintf(txt,256,"%s%s%s",DATA_PATH,LEVEL,DYNAMIC_DATA_SUFFIX);
418 mem_free(LEVEL);
419 load_room(txt);
421 c_init(SCREEN_X,SCREEN_Y);
422 c_cursor(C_HIDE);
423 update=1;
424 again:
425 last_time=get_time();
427 clear_screen();
428 draw_scene();
429 blit_screen(1);
431 if (!update)
433 c_goto(oldx,oldy);
434 c_setcolor(color);
435 c_putc(bg?bg:' ');
437 color=screen_a[x+y*SCREEN_X];
438 bg=screen[x+y*SCREEN_X];
440 c_goto(x,y);
441 c_setcolor(15);
442 c_print("+");
444 obj=find_object();
445 c_clear(0,SCREEN_Y-1,SCREEN_X-2,SCREEN_Y-1);
446 c_goto(0,SCREEN_Y-1);
447 c_setcolor(11);
448 c_print("X: ");
449 snprintf(txt,sizeof(txt),"% 4d ",x+xoffset);
450 c_setcolor(7);
451 c_print(txt);
452 c_setcolor(11);
453 c_print("Y: ");
454 snprintf(txt,sizeof(txt),"% 4d ",y+yoffset);
455 c_setcolor(7);
456 c_print(txt);
457 c_setcolor(11);
458 c_print("OBJECT: ");
459 snprintf(txt,sizeof(txt),"%-.20s ",obj?(char*)(sprite_names[obj->sprite]):"----");
460 c_setcolor(7);
461 c_print(txt);
462 c_setcolor(11);
463 c_print("TYPE: ");
464 snprintf(txt,sizeof(txt),"%c ",obj?obj->type:'-');
465 c_setcolor(7);
466 c_print(txt);
467 update=0;
468 oldx=x;
469 oldy=y;
470 c_refresh();
472 c_update_kbd();
474 if (c_pressed(K_NUM4)||c_pressed('4'))
476 xoffset-=SCREEN_X>>2;
477 if (xoffset<0)xoffset=0;
478 else update=1;
481 if (c_pressed(K_NUM6)||c_pressed('6'))
483 xoffset+=SCREEN_X>>2;
484 if (xoffset>AREA_X-1-(SCREEN_X>>1))xoffset=AREA_X-1-(SCREEN_X>>1);
485 update=1;
488 if (c_pressed(K_NUM8)||c_pressed('8'))
490 yoffset-=SCREEN_Y>>2;
491 if (yoffset<0)yoffset=0;
492 update=1;
495 if (c_pressed(K_NUM2)||c_pressed('2'))
497 yoffset+=SCREEN_Y>>2;
498 if (yoffset>AREA_Y-1-(SCREEN_Y>>1))yoffset=AREA_Y-1-(SCREEN_Y>>1);
499 update=1;
502 if (c_pressed('q')||c_pressed(K_ESCAPE))
504 c_shutdown();
505 clear_memory();
506 check_memory_leaks();
507 exit(0);
510 if (c_pressed(K_RIGHT))
512 x++;
513 if (x>SCREEN_X-1||x+xoffset>AREA_X-1)x=0;
516 if (c_pressed(K_LEFT))
518 x--;
519 if (x<0)x=SCREEN_X-1;
520 if (x+xoffset>AREA_X-1)x=AREA_X-1-xoffset;
523 if (c_pressed(K_DOWN))
525 y++;
526 if (y>SCREEN_Y-1||y+yoffset>AREA_Y-1)y=0;
529 if (c_pressed(K_UP))
531 y--;
532 if (y<0)y=SCREEN_Y-1;
533 if (y+yoffset>AREA_Y-1)y=AREA_Y-1-yoffset;
536 if (c_pressed(K_F1))
538 help();
539 clear_screen();
540 draw_scene();
541 blit_screen(1);
544 if (c_was_pressed('x'))
545 if (obj)
547 delete_obj(obj->id);
548 update=1;
551 if (c_was_pressed('=')||c_was_pressed(K_NUM_PLUS)|c_was_pressed(K_PGUP))
552 if (obj)
554 obj->sprite++;
555 cur_obj=obj->sprite;
556 obj->sprite%=n_sprites;
557 update=1;
560 if (c_was_pressed('a')||((c_pressed(K_LEFT_SHIFT)||c_pressed(K_RIGHT_SHIFT))&&c_pressed('a')))
561 if (obj)
563 obj->x--;
564 x--;
565 if (obj->x<0)obj->x=0;
566 update=1;
569 if (c_was_pressed('d')||((c_pressed(K_LEFT_SHIFT)||c_pressed(K_RIGHT_SHIFT))&&c_pressed('d')))
570 if (obj)
572 obj->x++;
573 x++;
574 if (obj->x>AREA_X-1)obj->x=AREA_X-1;
575 update=1;
578 if (c_was_pressed('w')||((c_pressed(K_LEFT_SHIFT)||c_pressed(K_RIGHT_SHIFT))&&c_pressed('w')))
579 if (obj)
581 obj->y--;
582 y--;
583 if (obj->y<0)obj->y=0;
584 update=1;
587 if (c_was_pressed('s')||((c_pressed(K_LEFT_SHIFT)||c_pressed(K_RIGHT_SHIFT))&&c_pressed('s')))
588 if (obj)
590 obj->y++;
591 y++;
592 if (obj->y>AREA_Y-1)obj->y=AREA_Y-1;
593 update=1;
596 if (c_was_pressed('-')||c_was_pressed(K_NUM_MINUS)||c_was_pressed(K_PGDOWN))
597 if (obj)
599 if (!obj->sprite)obj->sprite=n_sprites-1;
600 else obj->sprite--;
601 cur_obj=obj->sprite;
602 update=1;
605 if ((c_pressed(K_LEFT_SHIFT)||c_pressed(K_RIGHT_SHIFT))&&(c_was_pressed('t')||c_was_pressed(K_TAB)))
606 if (obj)
608 obj->type=prev_type(obj->type);
609 cur_type=obj->type;
610 update=1;
613 if (!c_pressed(K_LEFT_SHIFT)&&!c_pressed(K_RIGHT_SHIFT)&&(c_was_pressed('t')||c_was_pressed(K_TAB)))
614 if (obj)
616 obj->type=next_type(obj->type);
617 cur_type=obj->type;
618 update=1;
621 if (c_was_pressed('n')||c_was_pressed(K_ENTER))
623 new_obj(id,cur_type,0,cur_obj,0,0,x+xoffset,y+yoffset,0,0,0);
624 id++;
625 update=1;
628 if (c_was_pressed(K_F2))
629 save_data();
631 sleep_until(last_time+1000000/35);
632 goto again;