1 #include <stdio.h>
2 #include <stdlib.h>
3 
4 #include <sys/types.h>
5 #include <unistd.h>
6 
7 #include <X11/Xlib.h>
8 #include <X11/Xutil.h>
9 #include <X11/Intrinsic.h>
10 #include <X11/StringDefs.h>
11 #include <X11/Shell.h>
12 
13 #include "image.h"
14 #include "animate.h"
15 #include "namelist.h"
16 
17 Atom wm_protocols[2];
18 XtAppContext app;
19 
20 Animate *anim = NULL;
21 
22 void
QuitMsg(Widget w,XEvent * e,String * p,Cardinal * n)23 QuitMsg(Widget w, XEvent *e, String *p, Cardinal *n)
24 {
25 	if (e->xclient.data.l[0] == wm_protocols[0] ||
26 		e->xclient.data.l[0] == wm_protocols[1]) {
27 		exit(1);
28 /*		XtDestroyWidget(w); */
29 	}
30 }
31 
32 /* bad function */
33 void
expose(Widget w,XEvent * e,String * p,Cardinal * n)34 expose(Widget w, XEvent *e, String *p, Cardinal *n)
35 {
36 	XExposeEvent *ee = (XExposeEvent*)e;
37 	if (anim->dpy == ee->display && anim->win == ee->window)
38 		animate_expose(anim,ee->x, ee->y, ee->width, ee->height);
39 }
40 
41 /* command-line options */
42 static XrmOptionDescRec options[] = {};
43 
44 /* actions */
45 static XtActionsRec actions[] = {
46 	{"quitmsg", QuitMsg},
47 	{"expose", expose}
48 };
49 
50 /* translations */
51 String trans_top =
52 "<Message>WM_PROTOCOLS: quitmsg()\n"
53 "<Expose>: expose()\n";
54 
55 extern int verbose;
56 
57 void
set_animate(char * name)58 set_animate(char *name)
59 {
60 	FILE *fp;
61 	anim = animate_new();
62 	if ((fp = animate_fopen(name)) == NULL) {
63 		perror("animate_fopen");
64 		exit(1);
65 	}
66 	if (animate_parse(anim,fp)) {
67 		fprintf(stderr,"animate file load error.\n");
68 		exit(1);
69 	}
70 }
71 
72 typedef struct TimerDat {
73 	struct TimerDat *next;
74 	Animate *animate;
75 	u_int interval;
76 } TimerDat, *TimerDatList;
77 
78 TimerDat*
timer_new(void)79 timer_new(void)
80 {
81 	TimerDat *p;
82 	if ((p = malloc(sizeof(*p))) == NULL) {
83 		perror("timer_new");
84 		exit(1);
85 	}
86 	p->next  = NULL;
87 	p->animate = NULL;
88 	p->interval = 0;
89 	return p;
90 }
91 
92 void
timer_delete(TimerDat * p)93 timer_delete(TimerDat *p)
94 {
95 	if (p)
96 		free(p);
97 }
98 
99 void
timer_reentry(TimerDatList list,Animate * animate,TimerDat * new,int interval)100 timer_reentry(TimerDatList list, Animate *animate,
101 			  TimerDat *new, int interval)
102 {
103 	TimerDat *t = list->next;
104 
105 	if (t != NULL) {
106 		/* search entry point */
107 		while (t->next != NULL) {
108 			if (t->interval > interval)
109 				break;
110 			interval -= t->interval;
111 			t = t->next;
112 		}
113 		/* $B%j%9%H$KDI2C(B */
114 		new->animate  = animate;
115 		new->next     = t->next;
116 		new->interval = interval;
117 		t->next->interval -= interval;
118 		t->next = new;
119 	} else {
120 		new->animate  = animate;
121 		new->next     = NULL;
122 		new->interval = interval;
123 		list->next = new;
124 	}
125 }
126 
127 void
timer_entry(TimerDatList list,Animate * animate)128 timer_entry(TimerDatList list, Animate *animate)
129 {
130 	TimerDat *new = timer_new();
131 	timer_reentry(list, animate, new, 0);
132 }
133 
134 static void timer_go(TimerDatList list);
135 
136 static volatile XtIntervalId id;
137 
138 static void
TimerHand(XtPointer cl,XtIntervalId * id)139 TimerHand(XtPointer cl, XtIntervalId *id)
140 {
141 	timer_go((TimerDatList)cl);
142 }
143 
144 static void
timer_go(TimerDatList list)145 timer_go(TimerDatList list)
146 {
147 	TimerDat *p = list->next;
148 	int interval;
149 
150 	if (list != NULL && (p = list->next) != NULL) {
151 		interval = p->animate->point->interval;
152 		fprintf(stderr,"interval:[%d]\n",interval);
153 		list->next = p->next;
154 		if (animate_go(p->animate)) {
155 			timer_reentry(list, p->animate, p, interval);
156 		} else {
157 			timer_delete(p);
158 		}
159 
160 		if (list->next)
161 			id = XtAppAddTimeOut(app, list->next->interval, TimerHand, list);
162 	}
163 }
164 
165 int
main(int argc,char ** argv)166 main(int argc, char **argv)
167 {
168 	Widget top;
169 	TimerDatList tlist = timer_new();
170 	verbose = 1;
171 
172 	top = XtVaOpenApplication(&app, "AnimTest", options, XtNumber(options),
173 							  &argc, argv, NULL,
174 							  sessionShellWidgetClass, NULL);
175 
176 	if (argv[1]) {
177 
178 		wm_protocols[0] =
179 			XInternAtom(XtDisplay(top), "WM_DELETE_WINDOW", False);
180 		wm_protocols[1] =
181 			XInternAtom(XtDisplay(top), "WM_SAVEYOURSELF", False);
182 
183 		XtAppAddActions(app, actions, XtNumber(actions));
184 		XtOverrideTranslations(top, XtParseTranslationTable(trans_top));
185 		XtVaSetValues(top, XtNwidth,(Dimension)100,
186 					  XtNheight,(Dimension)100, NULL);
187 
188 		XtRealizeWidget(top);
189 		XSetWMProtocols(XtDisplay(top), XtWindow(top), wm_protocols, 2);
190 
191 		set_animate(argv[1]);
192 		animate_attach_win(anim, XtDisplay(top), XtWindow(top));
193 		animate_realize(anim);
194 		animate_init_all(anim);
195 
196 		fprintf(stderr,"timer\n");
197 
198 		timer_entry(tlist,anim);
199 		timer_go(tlist);
200 
201 		XtAppMainLoop(app);
202 	} else {
203 		fprintf(stderr, "usage: %s filename\n", argv[0]);
204 		exit(1);
205 	}
206 	exit(0);
207 }
208 
209