editor: #undef O after use
[0verkill.git] / avi.c
blob9cde7ebcc81c6148ce89170de57af9c6121d01e9
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <signal.h>
6 #include "cfg.h"
7 #include "console.h"
8 #include "blit.h"
9 #include "time.h"
10 #include "help.h"
11 #include "error.h"
13 int TRI_D_ON=0;
14 int tri_d=0;
16 char line[16384];
17 /* For loading lines from ASCII files */
18 char *lptr;
19 /* Used in conjunction with "line" variable */
20 unsigned char *pos=DUMMY;
21 /* Pointer to a cube of chars containing all the positions of the avi animation
22 * The char and attributre are in a consecutive pair, first comes char, then
23 * comes attr.*/
24 int n_pos=0;
25 /* Number of valid positions in the animation */
26 int left=0,right=0,top=0,bottom=0;
27 /* left: x coord of the leftmost char
28 * right: x coord of the rightmost char +1
29 * top: y coord of the topmost char
30 * bottom: y coord of the bottommost char +1
32 int dummy;
33 /* For testing purpose only */
34 int *sequence=DUMMY;
35 /* Pointer where the sequence of which positions are played after which is
36 * stored */
37 int sequence_size;
38 /* Number of pos entries in the sequence. If the positions should be played
39 * 1,2,3,4,5,5,5,5,4,4,3,3,2,2,1,1, then sequence contains these numbers and
40 * sequence_size is 16. */
41 FILE *f;
42 /* File from which the avi is loaded and into which it is written */
43 int cursor_x, cursor_y, cursor_pos;
44 int window_size_x, window_size_y;
45 volatile int resize_needed_flag;
46 unsigned char char_block[]=" `~1!2@3#4$5%6^7&8*9(0)-_=+\\|qQwWeErRtTyYuUiIoOpP[{]}aAsSdDfFgGhHjJkKlL"
47 ";:'\"zZxXcCvVbBnNmM,<.>/?";
48 int help=0;
49 int mode=0; /* 0: command mode, 1: drawing mode */
50 int hold_mode=0;
51 int anim=0;
52 int last_color, last_char;
54 #define MY_ERROR {ERROR("Syntax error of input file\n");EXIT(-1);}
56 void load_line(void)
58 do {
59 lptr=line;
60 if (!(fgets(line,sizeof(line),f))){
61 *line=0;
62 return;
64 } while (*lptr != '#');
67 int read_number(void)
69 int retval;
70 retval=strtol(lptr,(char **)&lptr,0);
71 return retval;
74 void add_pos(int how_much)
76 n_pos+=how_much;
77 pos=mem_realloc(pos,(right-left)*(bottom-top)*2*n_pos);
78 memset(pos+(right-left)*(bottom-top)*2*(n_pos-how_much),0,2*(right-left)*(bottom-top)*how_much);
81 void resize(int new_left, int new_right, int new_top, int new_bottom);
83 /* If do_resize is 1, then out-of-range is solved as a resize. If do_resize is a
84 * zero, then a NULL value is returned. */
85 unsigned char *get_pointer(int x, int y, int p, int do_resize)
87 int offset;
88 int flag=0;
89 int new_left=left,new_right=right,new_top=top,new_bottom=bottom;
91 if (p>=n_pos){
92 add_pos(p-n_pos+1);
94 if (x<left){
95 new_left=x;
96 flag=1;
98 if (x>=right){
99 new_right=x+1;
100 flag=1;
102 if (y<top){
103 new_top=y;
104 flag=1;
106 if (y>=bottom){
107 new_bottom=y+1;
108 flag=1;
110 if (flag){
111 if (do_resize)
112 resize(new_left,new_right,new_top,new_bottom);
113 else
114 return NULL;
116 offset=p;
117 offset*=(bottom-top);
118 offset+=y-top;
119 offset*=(right-left);
120 offset+=x-left;
121 return offset*2+pos;
124 void resize(int new_left, int new_right, int new_top, int new_bottom)
126 unsigned char *new_pointer;
127 int new_length=(new_right-new_left)*2*(new_bottom-new_top)*n_pos;
128 int y,p;
129 unsigned char *lp;
130 int offset;
132 new_pointer=mem_alloc(new_length);
133 memset(new_pointer,0,new_length);
134 for (p=0;p<n_pos;p++){
135 for (y=top;y<bottom;y++){
136 lp=get_pointer(left,y,p,1);
137 offset=p;
138 offset*=(new_bottom-new_top);
139 offset+=y-new_top;
140 offset*=(new_right-new_left);
141 offset+=left-new_left;
142 offset*=2;
143 memcpy(new_pointer+offset,lp, 2*(right-left));
146 left=new_left;
147 right=new_right;
148 top=new_top;
149 bottom=new_bottom;
150 mem_free(pos);
151 pos=new_pointer;
154 void put_element(int x,int y,int pos, int chr)
156 unsigned char *ptr;
158 ptr=get_pointer(x,y,pos,1);
159 ptr[0]=chr;
162 void put_attribute(int x,int y,int pos, int chr)
164 unsigned char *ptr;
166 ptr=get_pointer(x,y,pos,1);
167 if ((chr<'0'||chr>'9')&&(chr<'a'||chr>'z')&&(chr<'A'||chr>'Z'))chr=0;
168 else{
169 if (chr>='0'&&chr<='9'){
170 chr-='0';
171 }else if (chr>='a'&&chr<='z'){
172 chr=chr-'a'+10;
173 }else if (chr>='A'&&chr<='Z'){
174 chr=chr-'A'+10;
177 ptr[1]=chr;
180 void load_avi(char *filename)
182 int xoffset=0, yoffset=-1,pos=-1,x;
184 f=fopen(filename,"r");
185 if (!f){
186 sequence=mem_realloc(sequence,sizeof(*sequence));
187 *sequence=0;
188 sequence_size=1;
189 return;
191 new_line:
192 load_line();
193 switch (*lptr++){
194 case 'p':
195 pos++;
196 xoffset=read_number();
197 if ((*lptr++)!=',') MY_ERROR;
198 yoffset=read_number();
199 yoffset--;
200 break;
202 case 0: goto done;
204 case 'l':
205 yoffset++;
206 x=xoffset;
207 while((*lptr)&&(*lptr!='\n')){
208 put_element(x,yoffset,pos,*lptr);
209 lptr++;
210 x++;
212 break;
214 case 'a':
215 x=xoffset;
216 while(*lptr&&*lptr!='\n'){
217 put_attribute(x,yoffset,pos,*lptr);
218 lptr++;
219 x++;
221 break;
223 case 's':
224 new_number:
225 sequence_size++;
226 sequence=mem_realloc(sequence,sequence_size*sizeof(*sequence));
227 sequence[sequence_size-1]=read_number();
228 if ((*lptr++)==',') goto new_number;
229 break;
232 goto new_line;
233 done:
234 fclose(f);
239 void normalize_transparency(void)
241 int length=(right-left)*(bottom-top)*n_pos;
242 unsigned char *ptr=pos;
243 for (;length;length--,ptr+=2){
245 if ((!ptr[1])||(!(*ptr)))*ptr=32;
251 void save_avi(char *filename)
253 int pos,y,x,t;
254 unsigned char *char_pointer,*attr_pointer;
255 int nonempty;
256 int state;
257 int l;
259 normalize_transparency();
260 f=fopen(filename,"w");
261 if (!f) return;
263 for (pos=0;pos<n_pos;pos++){
264 state=0;
265 t=top;
267 /* skip heading empty lines */
268 for (y=top;y<bottom;y++){
269 char_pointer=get_pointer(left,y,pos,0);
270 nonempty=right-left;
271 while((nonempty>0)&&(!char_pointer[2*nonempty-1]))
272 nonempty--;
273 if (!nonempty){
274 state++;
275 continue;
276 }else{
277 for (;state;state--)t++;
278 state=0;
279 break;
284 unsigned char *c;
285 int a;
287 l=right;
288 for (y=t;y<bottom;y++)
290 c=get_pointer(left,y,pos,0);
291 c++;
292 for (a=0;a<right-left;a++)
293 if (c[2*a])break;
294 if (a+left<l)l=a+left;
298 fprintf(f,"#%d\np%d,%d\n",pos,l,t);
300 for (y=t;y<bottom;y++){
301 char_pointer=get_pointer(l,y,pos,0);
302 attr_pointer=char_pointer+1;
303 nonempty=right-l;
304 while((nonempty>0)&&(!char_pointer[2*nonempty-1]))
305 nonempty--;
306 if (!nonempty){
307 state++;
308 continue;
309 }else{
310 for (;state;state--)
311 fprintf(f,"l\na\n");
312 state=0;
314 fprintf(f,"l");
315 for (x=nonempty;x;x--){
316 unsigned char c=*char_pointer;
318 fputc(c,f);
320 char_pointer+=2;
324 fprintf(f,"\na");
326 for (x=nonempty;x;x--){
327 unsigned char c=*attr_pointer;
329 if (c<10)c+='0';else c=c-10+'a';
331 fputc(c=='0'?' ':c,f);
333 attr_pointer+=2;
337 fprintf(f,"\n");
343 fprintf(f,"s");
345 for (pos=0;pos<sequence_size;pos++){
347 fprintf(f,"%d%s",sequence[pos],pos==sequence_size-1?"":",");
351 fprintf(f,"\n");
353 fclose(f);
357 void filter_background(void)
359 int l=SCREEN_X*SCREEN_Y;
360 unsigned char *ptr=screen;
361 unsigned char *ptr1=screen_a;
362 for (;l;l--,ptr++,ptr1++){
363 if (!*ptr1){
364 *ptr=' ';
365 *ptr1=75;
370 int get_colour(void){
371 unsigned char *ptr;
373 ptr=get_pointer(cursor_x,cursor_y,cursor_pos,1);
374 return ptr[1];
377 void print_bottom_line(void)
379 int offs=SCREEN_X*(SCREEN_Y-2);
380 char txt[32];
381 int x;
383 memset(screen_a+offs,7,SCREEN_X);
384 memset(screen+offs,' ',SCREEN_X);
385 memset(screen+offs+SCREEN_X,' ',SCREEN_X);
386 memset(screen_a+offs+SCREEN_X,0,SCREEN_X);
387 x=0;
388 print2screen(x,SCREEN_Y-2,11,mode?"DRAW":"COMMAND");x+=9;
389 print2screen(x,SCREEN_Y-2,11,anim?"ANIM":"");x+=6;
390 print2screen(x,SCREEN_Y-2,11,hold_mode?"HOLD":"");x+=6;
391 print2screen(x,SCREEN_Y-2,get_colour(),"COLOR");x+=7;
392 print2screen(x,SCREEN_Y-2,7,"POS=");x+=4;
393 snprintf(txt,32,"%d",cursor_pos);
394 print2screen(x,SCREEN_Y-2,11,txt);x+=strlen(txt)+2;
395 print2screen(x,SCREEN_Y-2,7,"[");x+=1;
396 snprintf(txt,32,"% 5d",cursor_x);
397 print2screen(x,SCREEN_Y-2,11,txt);x+=5;
398 print2screen(x,SCREEN_Y-2,7,",");x+=1;
399 snprintf(txt,32,"% 5d",cursor_y);
400 print2screen(x,SCREEN_Y-2,11,txt);x+=5;
401 print2screen(x,SCREEN_Y-2,7,"]");x+=3;
402 for (x=0;x<16;x++)
404 screen_a[offs+SCREEN_X-16+x]=x;
405 screen[offs+SCREEN_X-16+x]=x<10?'0'+x:'A'+x-10;
408 x=0;
409 print2screen(x,SCREEN_Y-1,9,"F1,O");x+=4;
410 print2screen(x,SCREEN_Y-1,7,"-help");x+=6;
411 print2screen(x,SCREEN_Y-1,9,"ENTER");x+=5;
412 print2screen(x,SCREEN_Y-1,7,"-mode");x+=6;
413 print2screen(x,SCREEN_Y-1,9,"TAB");x+=3;
414 print2screen(x,SCREEN_Y-1,7,"-hold");x+=6;
415 print2screen(x,SCREEN_Y-1,9,"Q");x+=1;
416 print2screen(x,SCREEN_Y-1,7,"-save&end");x+=10;
417 print2screen(x,SCREEN_Y-1,9,"<,>");x+=3;
418 print2screen(x,SCREEN_Y-1,7,"-shift");x+=7;
419 print2screen(x,SCREEN_Y-1,9,"[,]");x+=3;
420 print2screen(x,SCREEN_Y-1,7,"-copy pos");x+=10;
421 print2screen(x,SCREEN_Y-1,9,"-,+");x+=3;
422 print2screen(x,SCREEN_Y-1,7,"-prev/next");x+=11;
426 void print_view(void)
428 int x,y;
429 int left,right,top,bottom;
430 unsigned char dummy[2]={32,0};
431 unsigned char *pointer;
433 left=cursor_x-(window_size_x>>1);
434 top=cursor_y-(window_size_y>>1);
435 right=left+window_size_x;
436 bottom=top+window_size_y;
438 clear_screen();
439 for (y=top;y<bottom;y++){
440 for (x=left;x<right;x++){
441 pointer=get_pointer(x,y,cursor_pos,0);
442 if (!pointer) pointer=dummy;
443 screen_a[(x-left)+SCREEN_X*(y-top)]=pointer[1];
444 screen[(x-left)+SCREEN_X*(y-top)]=*pointer;
447 filter_background();
448 /*screen[(cursor_x-left)+SCREEN_X*(cursor_y-top)]='+';
449 screen_a[(cursor_x-left)+SCREEN_X*(cursor_y-top)]=15;*/
451 print_bottom_line();
452 if (help)print_help_window();
453 blit_screen(0);
454 if (!help)
456 c_setcolor(15);
457 c_goto((cursor_x-left),(cursor_y-top));
458 c_refresh();
462 void animate(void)
464 int s;
465 unsigned long_long animate_speed=1000000/36;
467 anim=1;
468 while(1){
469 for (s=0;s<sequence_size;s++){
470 c_update_kbd();
471 if (c_pressed('h')){
472 anim=0;
473 return;
475 cursor_pos=sequence[s];
476 print_view();
477 sleep_until(get_time()+animate_speed);
483 void draw_colour(int colour){
484 unsigned char *ptr;
486 ptr=get_pointer(cursor_x,cursor_y,cursor_pos,1);
487 ptr[1]=colour;
488 last_color=colour;
491 void draw_char(int character){
492 unsigned char *ptr;
494 ptr=get_pointer(cursor_x,cursor_y,cursor_pos,1);
495 ptr[0]=character;
496 if (!ptr[1]) ptr[1]=7;
497 last_char=character;
500 void copy_pos(int dest, int src)
502 if (max(dest,src)>=n_pos)
503 add_pos(max(dest,src)+1-n_pos);
504 memcpy(pos+(right-left)*(bottom-top)*2*dest,pos+(right-left)*(bottom-top)*2*src,(right-left)*(bottom-top)*2);
507 void shift_right(int p)
509 int y;
510 unsigned char a1,a2;
511 unsigned char *ptr=pos+(right-left)*(bottom-top)*2*p;
513 if (right==left) return;
514 for (y=bottom-top;y;y--){
515 a1=ptr[(right-left)*2-1];
516 a2=ptr[(right-left)*2-2];
517 memmove(ptr+2,ptr,(right-left-1)*2);
518 ptr[0]=a2;
519 ptr[1]=a1;
520 ptr+=(right-left)*2;
524 void shift_left(int p)
526 int y;
527 unsigned char *ptr=pos+(right-left)*(bottom-top)*2*p,a1,a2;
529 if (right==left) return;
530 for (y=bottom-top;y;y--){
531 a1=ptr[1];
532 a2=ptr[0];
533 memmove(ptr,ptr+2,(right-left-1)*2);
534 ptr[(right-left)*2-1]=a1;
535 ptr[(right-left)*2-2]=a2;
536 ptr+=(right-left)*2;
540 void loop(void)
542 typedef unsigned long_long ttp;
543 int xdelta,ydelta;
544 int posdelta;
545 ttp last_left=0, last_right=0, last_up=0, last_down=0, repeat,
546 repeat_time=100000;
547 ttp last_plus=0, last_minus=0;
548 int l,r,u,d;
549 int oldhelp;
551 redraw:
552 print_view();
553 rescan:
554 oldhelp=help;
555 repeat=get_time()-repeat_time;
556 c_update_kbd();
557 xdelta=ydelta=posdelta=0;
558 l=!!c_pressed(K_LEFT);
559 r=!!c_pressed(K_RIGHT);
560 u=!!c_pressed(K_UP);
561 d=!!c_pressed(K_DOWN);
562 if (l^r){
563 if (l&&last_left<repeat){
564 xdelta--;
565 last_left=get_time();
567 if (r&&last_right<repeat){
568 xdelta++;
569 last_right=get_time();
572 if (u^d){
573 if (u&&last_up<repeat){
574 ydelta--;
575 last_up=get_time();
577 if (d&&last_down<repeat){
578 ydelta++;
579 last_down=get_time();
582 if (c_pressed('=')&&last_plus<repeat){
583 posdelta++;
584 last_plus=get_time();
586 if (c_pressed('-')&&last_minus<repeat){
587 posdelta--;
588 last_minus=get_time();
590 if (c_was_pressed(K_TAB)){
591 hold_mode^=1;
592 goto redraw;
594 if (c_was_pressed(K_ENTER)){
595 mode^=1;
596 hold_mode=0;
597 goto redraw;
599 if (c_was_pressed(K_F1))
600 help^=1;
601 if (mode){ /* draw */
602 int a;
604 for (a=0;a<((signed)sizeof(char_block))-1;a+=2){
605 if (c_pressed(char_block[a])){
607 (c_pressed(K_LEFT_SHIFT)||c_pressed(K_RIGHT_SHIFT))
608 draw_char(char_block[a+1]);
609 else
610 draw_char(char_block[a]);
611 goto redraw;
615 else
617 if (c_was_pressed('o'))
618 help^=1;
619 if (c_was_pressed('q')) return;
620 if (c_was_pressed('g')){animate();goto redraw;}
622 int a;
623 for (a=0;a<10;a++){
624 if (c_pressed('0'+a)){
625 draw_colour(a);
626 goto redraw;
631 int a;
632 for (a=0;a<6;a++){
633 if (c_pressed('a'+a)){
634 draw_colour(a+10);
635 goto redraw;
639 if (c_was_pressed('[')){
640 copy_pos(cursor_pos,(cursor_pos+n_pos-1)%n_pos);
641 goto redraw;
643 if (c_was_pressed(']')){
644 copy_pos(cursor_pos,(cursor_pos+1)%n_pos);
645 goto redraw;
647 if (c_was_pressed(',')){
648 shift_left(cursor_pos);
649 goto redraw;
651 if (c_was_pressed('.')){
652 shift_right(cursor_pos);
653 goto redraw;
657 if (!cursor_pos&&posdelta<0) posdelta=0;
658 cursor_x+=xdelta;
659 cursor_y+=ydelta;
660 cursor_pos+=posdelta;
661 if (hold_mode)
663 if (mode)
664 draw_char(last_char);
665 else
666 draw_colour(last_color);
667 goto redraw;
669 if (oldhelp^help)goto redraw;
670 if (xdelta||ydelta||posdelta) goto redraw;
671 goto rescan;
674 /* fatal signal */
675 void signal_handler(int signum)
678 shutdown_blit();
679 c_shutdown();
680 #ifdef HAVE_PSIGNAL
681 psignal(signum,"Exiting on signal");
682 #else
683 fprintf(stderr, "Exiting on signal: %d\n", signum);
684 #endif
685 check_memory_leaks();
686 EXIT(1);
691 int main(int argc, char **argv)
693 if (argc<2){
694 fprintf(stderr,"usage: %s foo.avi\n",argv[0]);
695 return -1;
698 signal(SIGINT,signal_handler);
699 signal(SIGTERM,signal_handler);
700 signal(SIGILL,signal_handler);
701 signal(SIGABRT,signal_handler);
702 signal(SIGFPE,signal_handler);
703 signal(SIGSEGV,signal_handler);
704 signal(SIGQUIT,signal_handler);
705 signal(SIGBUS,signal_handler);
707 c_get_size(&SCREEN_X,&SCREEN_Y);
708 init_blit();
709 c_init(SCREEN_X,SCREEN_Y);
710 c_get_size(&window_size_x,&window_size_y);
711 load_avi(argv[1]);
712 loop();
713 save_avi(argv[1]);
714 c_shutdown();
715 mem_free(sequence);
716 mem_free(pos);
717 shutdown_blit();
718 check_memory_leaks();
719 return 0;