1 /* CAVE (Character Animation Viewer for Everyone)
2 Copyright (C) 2001-2002 Ben Kibbey <bjk@luxsci.net>
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include <sys/types.h>
35 void changecolor(WINDOW
*win
, int which
)
37 if (has_colors() != TRUE
)
41 if (++foreg
> (COLORS
- 1))
42 foreg
= (backg
== 0) ? 1 : 0;
45 if (++backg
> (COLORS
- 1))
46 backg
= (foreg
== 0) ? 1 : 0;
50 changecolor(win
, which
);
52 init_pair(1, foreg
, backg
);
53 wbkgdset(win
, COLOR_PAIR(1));
58 void *Malloc(size_t size
)
62 if ((ptr
= malloc(size
)) == NULL
) {
71 void *Calloc(size_t num
, size_t size
)
75 if ((ptr
= calloc(num
, size
)) == NULL
) {
84 static void freeup(SCENE
* scene
)
91 while (node
->frameid
!= 0)
94 for (node
= node
; node
->frameid
< frames
; node
= next
) {
97 for (fnode
= node
->frame
; fnode
; fnode
= fnext
) {
110 char *sepfile(char *filename
)
113 static char tmp
[FILENAME_MAX
];
116 if ((str
= strrchr(filename
, '/')) == NULL
)
119 for (i
= 1; i
< strlen(str
); i
++)
127 void updatestatus(FILES
* file
, SCENE
* scene
, int row
, int dir
, int mark
,
128 int horizontal_offset
)
130 unsigned min
, tmin
, tsec
, sec
, i
= 0;
134 i
= delaylen
* 1000000 / fps
;
136 tmin
= (regexdelay
) ? (i
/ 1000000) / 60 : (frames
/ fps
) / 60;
137 tsec
= (regexdelay
) ? (i
/ 1000000) % 60 : (frames
/ fps
) % 60;
138 min
= (regexdelay
) ? (scene
->timepos
* 1000000) / fps
/ 1000000 / 60 :
139 (scene
->frameid
/ fps
) / 60;
140 sec
= (regexdelay
) ? (scene
->timepos
* 1000000) / fps
/ 1000000 % 60 :
141 (scene
->frameid
/ fps
) % 60;
143 /* wmove(statusw, 0, 0);
144 wclrtoeol(statusw); */
146 tmp
= sepfile(file
->filename
);
148 mvwprintw(statusw
, 0, 0, "%i/%i: %-16s frame: %li/%li-%-2i "
149 "%.2i:%.2i/%.2i:%.2i %i/%ix%i/%i", file
->fileid
, total
,
150 tmp
, scene
->frameid
, frames
, fps
, min
, sec
, tmin
, tsec
,
151 row
, maxy
, (maxx
> COLS
) ? COLS
+ horizontal_offset
: maxx
, maxx
);
152 mvwprintw(statusw
, 0, COLS
- (strlen(LOOP
) + strlen(STEP
) + 2),
153 "%s [%c%c%c]", (stepping
) ? STEP
: PLAY
,
154 (dir
) ? 'R' : ' ', mark
, (loops
) ? 'O' : ' ');
162 static void usage(const char *me
)
164 fprintf(stderr
, "Usage: %s [-hvsSqd] [-f <fps>] [-c <cue>] [-r <regex>] "
165 "[-t <secs>] file ...\n", me
);
166 fprintf(stderr
, " -f\tInitial frames-per-second (%i).\n", DEF_FPS
);
167 fprintf(stderr
, " -c\tNumber of frames to jump when cueing (%i).\n",
169 fprintf(stderr
, " -r\tAlternate frame deliminator expression ('%s').\n",
171 fprintf(stderr
, " -d\tThe specified frame deliminator is a frame delay "
173 fprintf(stderr
, " -s\tGo directly into screensaver mode.\n");
174 fprintf(stderr
, " -S\tGo directly into screensaver mode with file "
176 fprintf(stderr
, " -q\tQuit after keypress in screensaver.\n");
177 fprintf(stderr
, " -t\tScreensaver timeout (%i). Zero disables.\n",
179 fprintf(stderr
, " -v\tVersion info.\n");
180 fprintf(stderr
, " -h\tThis help text.\n");
185 static void fullscreen(WINDOW
* win
)
187 static int x
, y
, posx
, posy
;
189 if (panel_hidden(statusp
) && !ssmode
) {
192 mvwin(win
, posy
, posx
);
198 getbegyx(win
, posy
, posx
);
199 wresize(win
, LINES
, (maxx
> COLS
) ? COLS
: maxx
);
200 mvwin(win
, CALCPOSY(maxy
), CALCPOSX(maxx
));
210 static void sstimer(struct itimerval ssitv
, unsigned to
)
213 ssitv
.it_interval
.tv_sec
= 0;
214 ssitv
.it_interval
.tv_usec
= 0;
215 ssitv
.it_value
.tv_sec
= to
;
216 ssitv
.it_value
.tv_usec
= 0;
217 setitimer(ITIMER_REAL
, &ssitv
, 0);
223 static int loop(FILES
* file
, SCENE
* scene
)
226 int err
= 0, scrollpos
= 0, dir
= 0, z
, horizontal_offset
= 0;
227 unsigned long marks
= 0, marke
= 0;
228 SCENE
*snode
= scene
, *s_marks
= NULL
, *s_marke
= NULL
, s_olds
, s_olde
;
229 struct itimerval ssitv
;
231 z
= (maxx
> COLS
) ? COLS
: maxx
;
233 animw
= newwin((maxy
> LINES
- 1) ? LINES
- 1 : maxy
, z
,
234 (maxy
> LINES
- 1) ? CALCPOSY(maxy
) : CALCPOSY(maxy
) - 1,
237 nodelay(animw
, TRUE
);
239 leaveok(animw
, TRUE
);
247 sstimer(ssitv
, sstimeout
);
251 int c
, framejump
= 0, n
= 0;
258 if (snode
->frameid
== 0) {
259 if (ssmode
&& total
> 1) {
261 len
= delaylen
* 1000000 / fps
/ 1000000 % 60;
263 len
= (frames
/ fps
) % 60;
265 if (sstimeout
&& len
< sstimeout
&& !ssalarm
)
282 if (((snode
->frameid
== 1 || snode
->frameid
== frames
) ||
283 ((marks
&& marke
) && snode
->frameid
== marke
)) && !loops
)
287 nodelay(animw
, FALSE
);
289 nodelay(animw
, TRUE
);
292 getmaxyx(animw
, row
, col
);
294 fnode
= snode
->frame
;
296 while (fnode
->next
!= NULL
) {
299 if (scrollpos
> i
++) {
304 for (h
= horizontal_offset
; fnode
->line
[h
]; h
++)
305 mvwaddch(animw
, y
, q
++, fnode
->line
[h
]);
312 i
= maxy
- snode
->rows
;
315 mvwaddch(animw
, y
++, 0, ' ');
319 else if (marks
&& !marke
)
325 updatestatus(file
, snode
, row
+ scrollpos
, dir
, i
, horizontal_offset
);
327 i
= maxy
- snode
->rows
;
331 if (ssmode
&& !stepping
&& ssquit
) {
339 changecolor(animw
, 1);
342 changecolor(animw
, 0);
345 message(VINFO
, ANYKEY
, "\n%s\n\n%s\nTerminal %s supports %d "
346 "colors.", COPYRIGHT
, curses_version(),
347 getenv("TERM"), COLORS
);
357 marks
= snode
->frameid
;
362 if (!marks
|| snode
->frameid
== marks
) {
368 marke
= snode
->frameid
;
373 s_marks
->prev
= s_marke
;
374 s_marke
->next
= s_marks
;
378 s_marke
->prev
= s_marks
;
379 s_marks
->next
= s_marke
;
400 message(INFO
, ANYKEY
, "delay: %li, pos: %li, id: %li, rows: "
401 "%i", snode
->delay
, snode
->timepos
, snode
->frameid
,
408 scrollpos
= snode
->rows
- row
+ i
;
409 /* wscrl(animw, scrollpos); */
416 /* wscrl(animw, -1); */
419 if ((snode
->rows
- scrollpos
) + i
- 1 < row
)
423 /* wscrl(animw, 1); */
429 if (file
->fileid
+ 1 > total
)
435 if (file
->fileid
- 1 < 1)
441 if (snode
->frameid
== 0)
444 if ((n
= getint(GOTO
, -1)) == -1 || n
> frames
)
447 while (snode
->frameid
!= n
)
454 if (fps
+ 1 > MAXFPS
)
465 if (horizontal_offset
- 1 < 0)
471 if (horizontal_offset
+ COLS
+ 1 > maxx
)
478 if (snode
->frameid
== 0)
482 n
= snode
->frameid
- cue
;
487 while (snode
->frameid
!= n
)
499 n
= snode
->frameid
+ cue
;
508 while (snode
->frameid
!= n
)
518 if ((n
= getint(CHGSSTIMEOUT
, -1)) == -1)
528 if (err
== ERR_SHUFFLE
)
535 sstimer(ssitv
, sstimeout
);
560 err
= ERR_RELOADFILE
;
566 if (snode
->frameid
== 0)
574 if (marks
&& marke
) {
575 while (snode
->frameid
!= marks
)
580 updatestatus(file
, snode
, row
+ scrollpos
, dir
, i
,
598 if (!stepping
&& !framejump
) {
601 tv
.tv_usec
= 999999 / fps
;
604 i
= (snode
->delay
* 999999) / fps
;
606 tv
.tv_sec
= i
/ 999999;
607 tv
.tv_usec
= i
% 999999;
610 select(0, 0, 0, 0, &tv
);
612 if (marks
> marke
&& dir
)
614 else if (dir
|| marks
> marke
)
625 void sighandler(int sig
)
639 static int isinteger(char *str
)
643 for (i
= 0; i
< strlen(str
); i
++) {
644 if (isdigit(str
[i
]) == 0)
651 static long randfile(unsigned n
)
656 int main(int argc
, char *argv
[])
660 FILES
*files
, *fnode
, *fprev
;
668 sstimeout
= DEF_TIMEOUT
;
672 signal(SIGALRM
, sighandler
);
674 while ((opt
= getopt(argc
, argv
, "hvf:Sqt:sdc:r:")) != -1) {
680 if ((sstimeout
= isinteger(optarg
)) == -1 || sstimeout
< 1)
690 if ((fps
= isinteger(optarg
)) == -1 || fps
< 1)
694 if ((cue
= isinteger(optarg
)) == -1 || cue
< 1)
704 fprintf(stdout
, "%s\n%s\n", PACKAGE_STRING
, COPYRIGHT
);
722 if ((err
= regcomp(®ex
, regexp
, REG_EXTENDED
| REG_NOSUB
)) != 0) {
723 regerror(err
, ®ex
, tmp
, sizeof(tmp
));
724 fprintf(stderr
, "regcomp(): %s\n", tmp
);
730 if (start_color() == OK
&& has_colors() == TRUE
)
731 use_default_colors();
738 statusw
= newwin(1, COLS
, LINES
- 1, 0);
739 statusp
= new_panel(statusw
);
741 wbkgd(statusw
, ' ' | A_REVERSE
);
742 files
= Malloc(sizeof(FILES
));
747 while (optind
< argc
) {
750 if (stat(argv
[optind
], &mystat
) != 0) {
751 message(ERROR
, ANYKEY
, "%s: %s", argv
[optind
], strerror(errno
));
756 if (!S_ISREG(mystat
.st_mode
)) {
757 message(ERROR
, ANYKEY
, NOTAFILE
, argv
[optind
]);
762 fnode
->filename
= strdup(argv
[optind
]);
763 fnode
->fileid
= ++total
;
765 fnode
->next
= Calloc(1, sizeof(FILES
));
781 if (total
< 2 && ssmode
)
784 while (i
!= ERR_QUIT
) {
790 if ((scene
= readfile(fnode
->filename
)) == NULL
) {
791 if (fnode
->fileid
== total
)
798 i
= loop(fnode
, scene
);
803 for (fnode
= files
; fnode
; fnode
= fprev
) {
805 free(fnode
->filename
);
811 if (fnode
->next
->next
== NULL
) {
823 if ((n
= randfile(total
)) != lastfileid
)
829 while (fnode
->next
->next
!= NULL
) {
830 if (fnode
->fileid
== n
)