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