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 typedef struct TimerDat {
58 	struct TimerDat *next;
59 	Animate *animate;
60 	u_int interval;
61 } TimerDat, *TimerDatList;
62 
63 TimerDat*
timer_new(void)64 timer_new(void)
65 {
66 	TimerDat *p;
67 	if ((p = malloc(sizeof(*p))) == NULL) {
68 		perror("timer_new");
69 		exit(1);
70 	}
71 	p->next  = NULL;
72 	p->animate = NULL;
73 	p->interval = 0;
74 	return p;
75 }
76 
77 void
timer_delete(TimerDat * p)78 timer_delete(TimerDat *p)
79 {
80 	if (p)
81 		free(p);
82 }
83 
84 void
timer_reentry(TimerDatList list,Animate * animate,TimerDat * new,int interval)85 timer_reentry(TimerDatList list, Animate *animate,
86 			  TimerDat *new, int interval)
87 {
88 	TimerDat *t = list->next;
89 
90 	if (t != NULL) {
91 		/* search entry point */
92 		while (t->next != NULL) {
93 			if (t->interval > interval)
94 				break;
95 			interval -= t->interval;
96 			t = t->next;
97 		}
98 		/* �ꥹ�Ȥ��ɲ� */
99 		new->animate  = animate;
100 		new->next     = t->next;
101 		new->interval = interval;
102 		t->next->interval -= interval;
103 		t->next = new;
104 	} else {
105 		new->animate  = animate;
106 		new->next     = NULL;
107 		new->interval = interval;
108 		list->next = new;
109 	}
110 }
111 
112 void
timer_entry(TimerDatList list,Animate * animate)113 timer_entry(TimerDatList list, Animate *animate)
114 {
115 	TimerDat *new = timer_new();
116 	timer_reentry(list, animate, new, 0);
117 }
118 
119 static void timer_go(TimerDatList list);
120 static volatile XtIntervalId id;
121 
122 static void
TimerHand(XtPointer cl,XtIntervalId * id)123 TimerHand(XtPointer cl, XtIntervalId *id)
124 {
125 	timer_go((TimerDatList)cl);
126 }
127 
128 static void
timer_go(TimerDatList list)129 timer_go(TimerDatList list)
130 {
131 	TimerDat *p = list->next;
132 	int interval;
133 
134 	if (list != NULL && (p = list->next) != NULL) {
135 		interval = p->animate->point->interval;
136 		list->next = p->next;
137 		if (animate_go(p->animate)) {
138 			timer_reentry(list, p->animate, p, interval);
139 		} else {
140 			timer_delete(p);
141 		}
142 
143 		animate_set_shape(p->animate);
144 		animate_expose(p->animate, 0, 0, p->animate->w, p->animate->h);
145 
146 
147 		if (list->next)
148 			id = XtAppAddTimeOut(app, list->next->interval, TimerHand, list);
149 	}
150 }
151 
152 int
main(int argc,char ** argv)153 main(int argc, char **argv)
154 {
155 	Widget top;
156 	TimerDatList tlist = timer_new();
157 	FILE *fp;
158 
159 	verbose = 0;
160 
161 	top = XtVaOpenApplication(&app, "AnimTest", options, XtNumber(options),
162 							  &argc, argv, NULL,
163 							  overrideShellWidgetClass, NULL);
164 
165 	if (argv[1]) {
166 
167 		wm_protocols[0] =
168 			XInternAtom(XtDisplay(top), "WM_DELETE_WINDOW", False);
169 		wm_protocols[1] =
170 			XInternAtom(XtDisplay(top), "WM_SAVEYOURSELF", False);
171 
172 		XtAppAddActions(app, actions, XtNumber(actions));
173 		XtOverrideTranslations(top, XtParseTranslationTable(trans_top));
174 		XtVaSetValues(top, XtNwidth,(Dimension)1,
175 					  XtNheight,(Dimension)1, NULL);
176 		XtSetMappedWhenManaged(top, False);
177 		XtRealizeWidget(top);
178 		XSetWMProtocols(XtDisplay(top), XtWindow(top), wm_protocols, 2);
179 
180 		anim = animate_new();
181 		if ((fp = fopen(argv[1], "r")) == NULL) {
182 			perror("fopen");
183 			exit(1);
184 		}
185 		if (anim_gif_read_stream(anim,fp) < 0) {
186 			perror("anim_gif_read_stream");
187 			exit(1);
188 		}
189 
190 		animate_attach_win(anim, XtDisplay(top), XtWindow(top));
191 		animate_realize(anim);
192 
193 		timer_entry(tlist,anim);
194 		timer_go(tlist);
195 
196 		XtVaSetValues(top, XtNwidth, (Dimension)anim->w,
197 					  XtNheight, (Dimension)anim->h, NULL);
198 		XtMapWidget(top);
199 
200 		XtAppMainLoop(app);
201 
202 	} else {
203 		fprintf(stderr, "usage: %s filename\n", argv[0]);
204 		exit(1);
205 	}
206 
207 	exit(0);
208 }
209 
210