xref: /original-bsd/games/xneko/xneko.c (revision 403c148d)
1 /*-
2  * Copyright (c) 1991 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 char copyright[] =
10 "@(#) Copyright (c) 1991 The Regents of the University of California.\n\
11  All rights reserved.\n";
12 #endif /* not lint */
13 
14 #ifndef lint
15 static char sccsid[] = "@(#)xneko.c	5.2 (Berkeley) 05/22/91";
16 #endif /* not lint */
17 
18 /*--------------------------------------------------------------
19  *
20  *	xneko  -  X11 G-
21  *
22  *			Original Writer: Masayuki Koba
23  *			Programmed by Masayuki Koba, 1990
24  *
25  *--------------------------------------------------------------
26  *
27  *!!Introduction:
28  *
29  *!!!!K\@(#)xneko.c	5.2m%0%i%`$O Macintosh $N05/22/919%/%"%/%;%5%j!< "neko" $N
30  *!!F0:n$r X11 $G%^%M$?$b$N$G$9!#
31  *
32  *!!!!Macintosh "neko" $N=(0o$J05/22/916%$%s$K7I0U$rI=$7$D$D!"$3$N
33  *!!@(#)xneko.c	5.2m%0%i%`$r3'$5$s$KJ{$2$^$9!#
34  *
35  *--------------------------------------------------------------
36  *
37  *!!Special Thanks to
38  *
39  *	toshi-w	!D!!Macintosh neko $N>R2p<T
40  *	shio-m	!D!!!VX11 $N neko $,M_$7$$!*!W$H%?%@$r$3$M$??M
41  *	disco	!D!!X11 s.xneko.c/%K%+%k!&%"5.2P%$%6!<
42  *
43  *	HOMY	!D!!/usr/home/csrg/sccs/games/xneko/SCCS/s.xneko.c0;XE&<T
44  *	BNS	!D!!J#?t@(#)xneko.c	5.2l!<%sBP1~C%ADs6!<T
45  *
46  *		"xneko"  Presented by Masayuki Koba (masa-k).
47  *
48  *--------------------------------------------------------------
49  *
50  *!!Manifest:
51  *
52  *!!!!K\@(#)xneko.c	5.2m%0%i%`$O Public Domain Software $G$9!#E>:\!&2~NI$O
53  *!!<+M3$K9T$C$F2<$5$$!#
54  *
55  *!!!!$J$*!"86:n<T$O!"K\@(#)xneko.c	5.2m%0%i%`$r;HMQ$9$k$3$H$K$h$C$F@8$8$?
56  *!!>c32$dITMx1W$K$D$$$F$$$C$5$$@UG$$r;}$A$^$;$s!#
57  *
58  *--------------------------------------------------------------
59  *
60  *!!Bugs:
61  *
62  *!!!!!J#1!KX11 $N .Xdefaults $N@_Dj$r$^$k$C$-$jL5;k$7$F$$$^$9!#
63  *
64  *!!!!!J#2!KG-$NF0:n$,;~4V$HF14|$7$F$$$k$?$a!"%^%&%9$N0\F0>pJs
65  *!!!!!!!!$r%]!<%j%s%0$7$F$$$^$9!#=>$C$F!"%^%&%9$,A4$/F0:n$7$F
66  *!!!!!!!!$$$J$$;~$OL5BL$J%^%&%9:BI8FI$_<h$j$r9T$C$F$7$^$$$^$9!#
67  *
68  *!!!!!J#3!K%&%#%s5.2&$,%"%$%3%s2=$5$l$F$b!"$7$i$s$W$j$GIA2h$7
69  *!!!!!!!!$D$E$1$^$9!#$3$NItJ,$O!"8=:_$N%&%#%s5.2&$N>uBV$r@(#) xneko.c 5.2@(#)'
70  *!!!!!!!!70/$7$F!"%"%$%3%s2=$5$l$F$$$k;~$O40A4$K%$s%HBT$A
71  *!!!!!!!!$K$J$k$h$&$K=q$-JQ$($J$1$l$P$J$j$^$;$s!# ($=$s$J$3$H!"
72  *!!!!!!!!$G$-$k$N$+$J$!!#X10 $G$O$G$-$^$7$?$,!#)
73  *
74  *!!!!!J#4!K%j%5%$%:8e$N%&%#%s5.2&$,6KC<$K>.$5$/$J$C$?;~$NF0:n
75  *!!!!!!!!$OJ]>Z$G$-$^$;$s!#
76  *
77  *!!!!!J#5!KK\Mh$J$i$P3NJ]$7$?%&%#%s5.2&$d Pixmap $O@(#)xneko.c	5.2m%0%i%`
78  *!!!!!!!!=*N;;~$K2rJ|$9$kI,MW$,$"$j$^$9$,!"K\@(#)xneko.c	5.2m%0%i%`$O$=$N
79  *!!!!!!!!$X$s$r%5%\$C$F$*$j!"Hs>o$K$*9T57$,0-$/$J$C$F$$$^$9!#
80  *!!!!!!!!IaDL$O exit() ;~$K%7%9s.xneko.c`$,M>J,$J%j%=!<%9$r2rJ|$7$F
81  *!!!!!!!!$/$l$^$9$,!"#O#S$K/usr/home/csrg/sccs/games/xneko/SCCS/s.xneko.c0$,$"$k>l9g$O xneko $r2?EY$b5/
82  *!!!!!!!!F0$9$k$H!"$=$N$&$A%9%o82WNN0h$,ITB-$7$F$7$^$&$3$H$K
83  *!!!!!!!!$J$k$+$b$7$l$^$;$s!#
84  *
85  *!!!!!J#6!K;~4V$KF14|$7$FI,$:IA2h=hM}$r<B9T$9$k$?$a!"0BDj>uBV
86  *!!!!!!!!$G$b Idle 90 !A 95% $H$J$j!"%7%9s.xneko.c`#C#P#U$r 5 !A 10%
87  *!!!!!!!!Dx>CHq$7$^$9!#!Jxtachos $GD4$Y$^$7$?!#!K
88  *
89  *--------------------------------------------------------------
90  *
91  *!!System (Machine):
92  *
93  *!!!!K\@(#)xneko.c	5.2m%0%i%`$NF0:n$r3NG'$7$?%7%9s.xneko.c`9=@.$O0J2<$NDL$j!#
94  *
95  *	!&NWS-1750!"NWS-1720 (NEWS)!"NWP-512D
96  *	!!NEWS-OS 3.2a (UNIX 4.3BSD)!"X11 Release 2
97  *
98  *	!&NWS-1750!"NWS-1720 (NEWS)!"NWP-512D
99  *	!!NEWS-OS 3.3 (UNIX 4.3BSD)!"X11 Release 3
100  *
101  *	!&Sun 3!"X11 Release 4
102  *
103  *	!&LUNA!"X11 Release 3
104  *
105  *	!&DECstation 3100!"ULTRIX!"X11
106  *
107  *--------------------------------------------------------------*/
108 
109 
110 #include <X11/Xlib.h>
111 #include <X11/Xutil.h>
112 #include <X11/keysym.h>
113 
114 #include <stdio.h>
115 
116 #include <signal.h>
117 #include <math.h>
118 #include <sys/time.h>
119 
120 
121 #ifndef	lint
122 static char
123 	rcsid[] = "$Header: /afs/athena.mit.edu/user/j/jik/sipbsrc/src/xneko/RCS/xneko.c,v 1.2 90/09/01 23:40:01 jik Exp $";
124 static char	WriterMessage[] = "xneko: Programmed by Masayuki Koba, 1990";
125 #endif
126 
127 
128 /*
129  *	X11 G- 0C10/14/12^129W13:03:18!%$%k0lMw!'
130  *
131  *		"icon.xbm"		!D!!%"%$%3%s
132  *		"cursor.xbm"		!D!!%+!<%=%k
133  *		"cursor_mask.xbm"	!D!!%+!<%=%k!J%^%9%/!K
134  *
135  *		"space.xbm"		!D!!%9%Z!<%9
136  *
137  *		"mati2.xbm"		!D!!BT$A#2
138  *		"jare2.xbm"		!D!!$8$c$l#2
139  *		"kaki1.xbm"		!D!!A_$-#1
140  *		"kaki2.xbm"		!D!!A_$-#2
141  *		"mati3.xbm"		!D!!BT$A#3!J$"$/$S!K
142  *		"sleep1.xbm"		!D!!?2$k#1
143  *		"sleep2.xbm"		!D!!?2$k#2
144  *
145  *		"awake.xbm"		!D!!L\3P$a
146  *
147  *		"up1.xbm"		!D!!>e#1
148  *		"up2.xbm"		!D!!>e#2
149  *		"down1.xbm"		!D!!2<#1
150  *		"down2.xbm"		!D!!2<#2
151  *		"left1.xbm"		!D!!:8#1
152  *		"left2.xbm"		!D!!:8#2
153  *		"right1.xbm"		!D!!1&#1
154  *		"right2.xbm"		!D!!1&#2
155  *		"upleft1.xbm"		!D!!:8>e#1
156  *		"upleft2.xbm"		!D!!:8>e#2
157  *		"upright1.xbm"		!D!!1&>e#1
158  *		"upright2.xbm"		!D!!1&>e#2
159  *		"dwleft1.xbm"		!D!!:82<#1
160  *		"dwleft2.xbm"		!D!!:82<#2
161  *		"dwright1.xbm"		!D!!1&2<#1
162  *		"dwright2.xbm"		!D!!1&2<#2
163  *
164  *		"utogi1.xbm"		!D!!>eKa$.#1
165  *		"utogi2.xbm"		!D!!>eKa$.#2
166  *		"dtogi1.xbm"		!D!!2<Ka$.#1
167  *		"dtogi2.xbm"		!D!!2<Ka$.#2
168  *		"ltogi1.xbm"		!D!!:8Ka$.#1
169  *		"ltogi2.xbm"		!D!!:8Ka$.#2
170  *		"rtogi1.xbm"		!D!!1&Ka$.#1
171  *		"rtogi2.xbm"		!D!!1&Ka$.#2
172  *
173  *	!!$3$l$i$N13:03:18!%$%k$O bitmap %3%^%s%I$GJT=82DG=$G$9!#
174  *
175  *		(bitmap size "* 32x32 ... Macintosh ICON resource size.)
176  *
177  */
178 
179 
180 #include "bitmaps/icon.xbm"
181 #include "bitmaps/cursor.xbm"
182 #include "bitmaps/cursor_mask.xbm"
183 
184 #include "bitmaps/space.xbm"
185 
186 #include "bitmaps/mati2.xbm"
187 #include "bitmaps/jare2.xbm"
188 #include "bitmaps/kaki1.xbm"
189 #include "bitmaps/kaki2.xbm"
190 #include "bitmaps/mati3.xbm"
191 #include "bitmaps/sleep1.xbm"
192 #include "bitmaps/sleep2.xbm"
193 
194 #include "bitmaps/awake.xbm"
195 
196 #include "bitmaps/up1.xbm"
197 #include "bitmaps/up2.xbm"
198 #include "bitmaps/down1.xbm"
199 #include "bitmaps/down2.xbm"
200 #include "bitmaps/left1.xbm"
201 #include "bitmaps/left2.xbm"
202 #include "bitmaps/right1.xbm"
203 #include "bitmaps/right2.xbm"
204 #include "bitmaps/upright1.xbm"
205 #include "bitmaps/upright2.xbm"
206 #include "bitmaps/upleft1.xbm"
207 #include "bitmaps/upleft2.xbm"
208 #include "bitmaps/dwleft1.xbm"
209 #include "bitmaps/dwleft2.xbm"
210 #include "bitmaps/dwright1.xbm"
211 #include "bitmaps/dwright2.xbm"
212 
213 #include "bitmaps/utogi1.xbm"
214 #include "bitmaps/utogi2.xbm"
215 #include "bitmaps/dtogi1.xbm"
216 #include "bitmaps/dtogi2.xbm"
217 #include "bitmaps/ltogi1.xbm"
218 #include "bitmaps/ltogi2.xbm"
219 #include "bitmaps/rtogi1.xbm"
220 #include "bitmaps/rtogi2.xbm"
221 
222 
223 /*
224  *	Dj?tDj5A
225  */
226 
227 #define	BITMAP_WIDTH		32	/* #1%-%c%i%/%?$NI} (16:56:31/%;%k) */
228 #define	BITMAP_HEIGHT		32	/* #1%-%c%i%/%?$N9b$5 (16:56:31/%;%k) */
229 
230 #define	WINDOW_WIDTH		320	/* %&%#%s5.2&$NI} (16:56:31/%;%k) */
231 #define	WINDOW_HEIGHT		256	/* %&%#%s5.2&$N9b$5 (16:56:31/%;%k) */
232 
233 #define	DEFAULT_BORDER		2	/* %\!<%@!<%5%$%: */
234 
235 #define	DEFAULT_WIN_X		1	/* %&%#%s5.2&@8@.#X:BI8 */
236 #define	DEFAULT_WIN_Y		1	/* %&%#%s5.2&@8@.#Y:BI8 */
237 
238 #define	AVAIL_KEYBUF		255
239 
240 #define	EVENT_MASK1		( KeyPressMask | StructureNotifyMask )
241 
242 #define	EVENT_MASK2		( KeyPressMask | \
243 				  ExposureMask | \
244 				  StructureNotifyMask )
245 
246 #define	MAX_TICK		9999		/* Odd Only! */
247 
248 #define	INTERVAL		125000L		/* %$%s%?!</usr/home/csrg/sccs/games/xneko/SCCS/s.xneko.ck%?%$%` */
249 
250 #define	NEKO_SPEED		16
251 
252 #define	IDLE_SPACE		6
253 
254 #define	NORMAL_STATE		1
255 #define	DEBUG_LIST		2
256 #define	DEBUG_MOVE		3
257 
258 /* G-$N>uBVDj?t */
259 
260 #define	NEKO_STOP		0	/* N)$A;_$^$C$? */
261 #define	NEKO_JARE		1	/* 4i$r@v$C$F$$$k */
262 #define	NEKO_KAKI		2	/* F,$rA_$$$F$$$k */
263 #define	NEKO_AKUBI		3	/* $"$/$S$r$7$F$$$k */
264 #define	NEKO_SLEEP		4	/* ?2$F$7$^$C$? */
265 #define	NEKO_AWAKE		5	/* L\$,3P$a$? */
266 #define	NEKO_U_MOVE		6	/* >e$K0\F0Cf */
267 #define	NEKO_D_MOVE		7	/* 2<$K0\F0Cf */
268 #define	NEKO_L_MOVE		8	/* :8$K0\F0Cf */
269 #define	NEKO_R_MOVE		9	/* 1&$K0\F0Cf */
270 #define	NEKO_UL_MOVE		10	/* :8>e$K0\F0Cf */
271 #define	NEKO_UR_MOVE		11	/* 1&>e$K0\F0Cf */
272 #define	NEKO_DL_MOVE		12	/* :82<$K0\F0Cf */
273 #define	NEKO_DR_MOVE		13	/* 1&2<$K0\F0Cf */
274 #define	NEKO_U_TOGI		14	/* >e$NJI$r0z$CA_$$$F$$$k */
275 #define	NEKO_D_TOGI		15	/* 2<$NJI$r0z$CA_$$$F$$$k */
276 #define	NEKO_L_TOGI		16	/* :8$NJI$r0z$CA_$$$F$$$k */
277 #define	NEKO_R_TOGI		17	/* 1&$NJI$r0z$CA_$$$F$$$k */
278 
279 /* G-$N%"%K%a!<%7%g%s7+$jJV$72s?t */
280 
281 #define	NEKO_STOP_TIME		4
282 #define	NEKO_JARE_TIME		10
283 #define	NEKO_KAKI_TIME		4
284 #define	NEKO_AKUBI_TIME		3
285 #define	NEKO_AWAKE_TIME		3
286 #define	NEKO_TOGI_TIME		10
287 
288 #define	PI_PER8			((double)3.1415926535/(double)8)
289 
290 #define	DIRNAMELEN		255
291 
292 
293 /*
294  *	%0%m!</usr/home/csrg/sccs/games/xneko/SCCS/s.xneko.ckJQ?t
295  */
296 
297 static char		*ProgramName;		/* %3%^%s%IL>>N */
298 
299 Display			*theDisplay;
300 int			theScreen;
301 unsigned int		theDepth;
302 unsigned long		theBlackPixel;
303 unsigned long		theWhitePixel;
304 Window			theWindow;
305 Cursor			theCursor;
306 
307 static unsigned int	WindowWidth;
308 static unsigned int	WindowHeight;
309 
310 static int		WindowPointX;
311 static int		WindowPointY;
312 
313 static unsigned int	BorderWidth = DEFAULT_BORDER;
314 
315 long			IntervalTime = INTERVAL;
316 
317 int			EventState;		/* %$s%H=hM}MQ >uBVJQ?t */
318 
319 int			NekoTickCount;		/* G-F0:n%+%&%s%? */
320 int			NekoStateCount;		/* G-F10l>uBV%+%&%s%? */
321 int			NekoState;		/* G-$N>uBV */
322 
323 int			MouseX;			/* %^%&%9#X:BI8 */
324 int			MouseY;			/* %^%&%9#Y:BI8 */
325 
326 int			PrevMouseX = 0;		/* D>A0$N%^%&%9#X:BI8 */
327 int			PrevMouseY = 0;		/* D>A0$N%^%&%9#Y:BI8 */
328 
329 int			NekoX;			/* G-#X:BI8 */
330 int			NekoY;			/* G-#Y:BI8 */
331 
332 int			NekoMoveDx;		/* G-0\F05wN%#X */
333 int			NekoMoveDy;		/* G-0\F05wN%#Y */
334 
335 int			NekoLastX;		/* G-:G=*IA2h#X:BI8 */
336 int			NekoLastY;		/* G-:G=*IA2h#Y:BI8 */
337 GC			NekoLastGC;		/* G-:G=*IA2h GC */
338 
339 double			NekoSpeed = (double)NEKO_SPEED;
340 
341 double			SinPiPer8Times3;	/* sin( #3&P!?#8 ) */
342 double			SinPiPer8;		/* sin( &P!?#8 ) */
343 
344 Pixmap			SpaceXbm;
345 
346 Pixmap			Mati2Xbm;
347 Pixmap			Jare2Xbm;
348 Pixmap			Kaki1Xbm;
349 Pixmap			Kaki2Xbm;
350 Pixmap			Mati3Xbm;
351 Pixmap			Sleep1Xbm;
352 Pixmap			Sleep2Xbm;
353 
354 Pixmap			AwakeXbm;
355 
356 Pixmap			Up1Xbm;
357 Pixmap			Up2Xbm;
358 Pixmap			Down1Xbm;
359 Pixmap			Down2Xbm;
360 Pixmap			Left1Xbm;
361 Pixmap			Left2Xbm;
362 Pixmap			Right1Xbm;
363 Pixmap			Right2Xbm;
364 Pixmap			UpLeft1Xbm;
365 Pixmap			UpLeft2Xbm;
366 Pixmap			UpRight1Xbm;
367 Pixmap			UpRight2Xbm;
368 Pixmap			DownLeft1Xbm;
369 Pixmap			DownLeft2Xbm;
370 Pixmap			DownRight1Xbm;
371 Pixmap			DownRight2Xbm;
372 
373 Pixmap			UpTogi1Xbm;
374 Pixmap			UpTogi2Xbm;
375 Pixmap			DownTogi1Xbm;
376 Pixmap			DownTogi2Xbm;
377 Pixmap			LeftTogi1Xbm;
378 Pixmap			LeftTogi2Xbm;
379 Pixmap			RightTogi1Xbm;
380 Pixmap			RightTogi2Xbm;
381 
382 GC			SpaceGC;
383 
384 GC			Mati2GC;
385 GC			Jare2GC;
386 GC			Kaki1GC;
387 GC			Kaki2GC;
388 GC			Mati3GC;
389 GC			Sleep1GC;
390 GC			Sleep2GC;
391 
392 GC			AwakeGC;
393 
394 GC			Up1GC;
395 GC			Up2GC;
396 GC			Down1GC;
397 GC			Down2GC;
398 GC			Left1GC;
399 GC			Left2GC;
400 GC			Right1GC;
401 GC			Right2GC;
402 GC			UpLeft1GC;
403 GC			UpLeft2GC;
404 GC			UpRight1GC;
405 GC			UpRight2GC;
406 GC			DownLeft1GC;
407 GC			DownLeft2GC;
408 GC			DownRight1GC;
409 GC			DownRight2GC;
410 
411 GC			UpTogi1GC;
412 GC			UpTogi2GC;
413 GC			DownTogi1GC;
414 GC			DownTogi2GC;
415 GC			LeftTogi1GC;
416 GC			LeftTogi2GC;
417 GC			RightTogi1GC;
418 GC			RightTogi2GC;
419 
420 typedef struct {
421     GC			*GCCreatePtr;
422     Pixmap		*BitmapCreatePtr;
423     char		*PixelPattern;
424     unsigned int	PixelWidth;
425     unsigned int	PixelHeight;
426 } BitmapGCData;
427 
428 BitmapGCData	BitmapGCDataTable[] =
429 {
430     { &SpaceGC, &SpaceXbm, space_bits, space_width, space_height },
431     { &Mati2GC, &Mati2Xbm, mati2_bits, mati2_width, mati2_height },
432     { &Jare2GC, &Jare2Xbm, jare2_bits, jare2_width, jare2_height },
433     { &Kaki1GC, &Kaki1Xbm, kaki1_bits, kaki1_width, kaki1_height },
434     { &Kaki2GC, &Kaki2Xbm, kaki2_bits, kaki2_width, kaki2_height },
435     { &Mati3GC, &Mati3Xbm, mati3_bits, mati3_width, mati3_height },
436     { &Sleep1GC, &Sleep1Xbm, sleep1_bits, sleep1_width, sleep1_height },
437     { &Sleep2GC, &Sleep2Xbm, sleep2_bits, sleep2_width, sleep2_height },
438     { &AwakeGC, &AwakeXbm, awake_bits, awake_width, awake_height },
439     { &Up1GC, &Up1Xbm, up1_bits, up1_width, up1_height },
440     { &Up2GC, &Up2Xbm, up2_bits, up2_width, up2_height },
441     { &Down1GC, &Down1Xbm, down1_bits, down1_width, down1_height },
442     { &Down2GC, &Down2Xbm, down2_bits, down2_width, down2_height },
443     { &Left1GC, &Left1Xbm, left1_bits, left1_width, left1_height },
444     { &Left2GC, &Left2Xbm, left2_bits, left2_width, left2_height },
445     { &Right1GC, &Right1Xbm, right1_bits, right1_width, right1_height },
446     { &Right2GC, &Right2Xbm, right2_bits, right2_width, right2_height },
447     { &UpLeft1GC, &UpLeft1Xbm, upleft1_bits, upleft1_width, upleft1_height },
448     { &UpLeft2GC, &UpLeft2Xbm, upleft2_bits, upleft2_width, upleft2_height },
449     { &UpRight1GC,
450       &UpRight1Xbm, upright1_bits, upright1_width, upright1_height },
451     { &UpRight2GC,
452       &UpRight2Xbm, upright2_bits, upright2_width, upright2_height },
453     { &DownLeft1GC,
454       &DownLeft1Xbm, dwleft1_bits, dwleft1_width, dwleft1_height },
455     { &DownLeft2GC,
456       &DownLeft2Xbm, dwleft2_bits, dwleft2_width, dwleft2_height },
457     { &DownRight1GC,
458       &DownRight1Xbm, dwright1_bits, dwright1_width, dwright1_height },
459     { &DownRight2GC,
460       &DownRight2Xbm, dwright2_bits, dwright2_width, dwright2_height },
461     { &UpTogi1GC, &UpTogi1Xbm, utogi1_bits, utogi1_width, utogi1_height },
462     { &UpTogi2GC, &UpTogi2Xbm, utogi2_bits, utogi2_width, utogi2_height },
463     { &DownTogi1GC, &DownTogi1Xbm, dtogi1_bits, dtogi1_width, dtogi1_height },
464     { &DownTogi2GC, &DownTogi2Xbm, dtogi2_bits, dtogi2_width, dtogi2_height },
465     { &LeftTogi1GC, &LeftTogi1Xbm, ltogi1_bits, ltogi1_width, ltogi1_height },
466     { &LeftTogi2GC, &LeftTogi2Xbm, ltogi2_bits, ltogi2_width, ltogi2_height },
467     { &RightTogi1GC,
468       &RightTogi1Xbm, rtogi1_bits, rtogi1_width, rtogi1_height },
469     { &RightTogi2GC,
470       &RightTogi2Xbm, rtogi2_bits, rtogi2_width, rtogi2_height },
471     { NULL, NULL, NULL, NULL, NULL }
472 };
473 
474 typedef struct {
475     GC		*TickEvenGCPtr;
476     GC		*TickOddGCPtr;
477 } Animation;
478 
479 Animation	AnimationPattern[] =
480 {
481     { &Mati2GC, &Mati2GC },		/* NekoState == NEKO_STOP */
482     { &Jare2GC, &Mati2GC },		/* NekoState == NEKO_JARE */
483     { &Kaki1GC, &Kaki2GC },		/* NekoState == NEKO_KAKI */
484     { &Mati3GC, &Mati3GC },		/* NekoState == NEKO_AKUBI */
485     { &Sleep1GC, &Sleep2GC },		/* NekoState == NEKO_SLEEP */
486     { &AwakeGC, &AwakeGC },		/* NekoState == NEKO_AWAKE */
487     { &Up1GC, &Up2GC }	,		/* NekoState == NEKO_U_MOVE */
488     { &Down1GC, &Down2GC },		/* NekoState == NEKO_D_MOVE */
489     { &Left1GC, &Left2GC },		/* NekoState == NEKO_L_MOVE */
490     { &Right1GC, &Right2GC },		/* NekoState == NEKO_R_MOVE */
491     { &UpLeft1GC, &UpLeft2GC },		/* NekoState == NEKO_UL_MOVE */
492     { &UpRight1GC, &UpRight2GC },	/* NekoState == NEKO_UR_MOVE */
493     { &DownLeft1GC, &DownLeft2GC },	/* NekoState == NEKO_DL_MOVE */
494     { &DownRight1GC, &DownRight2GC },	/* NekoState == NEKO_DR_MOVE */
495     { &UpTogi1GC, &UpTogi2GC },		/* NekoState == NEKO_U_TOGI */
496     { &DownTogi1GC, &DownTogi2GC },	/* NekoState == NEKO_D_TOGI */
497     { &LeftTogi1GC, &LeftTogi2GC },	/* NekoState == NEKO_L_TOGI */
498     { &RightTogi1GC, &RightTogi2GC },	/* NekoState == NEKO_R_TOGI */
499 };
500 
501 
502 /*--------------------------------------------------------------
503  *
504  *	0C10/14/12^504W%G!<%?!&GC =i4|2=
505  *
506  *--------------------------------------------------------------*/
507 
508 void
509 InitBitmapAndGCs()
510 {
511     BitmapGCData	*BitmapGCDataTablePtr;
512     XGCValues		theGCValues;
513 
514     theGCValues.function = GXcopy;
515     theGCValues.foreground = BlackPixel( theDisplay, theScreen );
516     theGCValues.background = WhitePixel( theDisplay, theScreen );
517     theGCValues.fill_style = FillTiled;
518 
519     for ( BitmapGCDataTablePtr = BitmapGCDataTable;
520 	  BitmapGCDataTablePtr->GCCreatePtr != NULL;
521 	  BitmapGCDataTablePtr++ ) {
522 
523 	*(BitmapGCDataTablePtr->BitmapCreatePtr)
524 	    = XCreatePixmapFromBitmapData(
525 		  theDisplay,
526 		  RootWindow( theDisplay, theScreen ),
527 		  BitmapGCDataTablePtr->PixelPattern,
528 		  BitmapGCDataTablePtr->PixelWidth,
529 		  BitmapGCDataTablePtr->PixelHeight,
530 		  BlackPixel( theDisplay, theScreen ),
531 		  WhitePixel( theDisplay, theScreen ),
532 		  DefaultDepth( theDisplay, theScreen ) );
533 
534 	theGCValues.tile = *(BitmapGCDataTablePtr->BitmapCreatePtr);
535 
536 	*(BitmapGCDataTablePtr->GCCreatePtr)
537 	    = XCreateGC( theDisplay, theWindow,
538 			 GCFunction | GCForeground | GCBackground |
539 			 GCTile | GCFillStyle,
540 			 &theGCValues );
541     }
542 
543     XFlush( theDisplay );
544 }
545 
546 
547 /*--------------------------------------------------------------
548  *
549  *	%9%/%j!<%s4D6-=i4|2=
550  *
551  *--------------------------------------------------------------*/
552 
553 void
554 InitScreen( DisplayName, theGeometry, TitleName, iconicState )
555     char	*DisplayName;
556     char	*theGeometry;
557     char	*TitleName;
558     Bool	iconicState;
559 {
560     int				GeometryStatus;
561     XSetWindowAttributes	theWindowAttributes;
562     XSizeHints			theSizeHints;
563     unsigned long		theWindowMask;
564     Pixmap			theIconPixmap;
565     Pixmap			theCursorSource;
566     Pixmap			theCursorMask;
567     XWMHints			theWMHints;
568     Window			theRoot;
569     Colormap			theColormap;
570     XColor			theWhiteColor, theBlackColor, theExactColor;
571 
572     if ( ( theDisplay = XOpenDisplay( DisplayName ) ) == NULL ) {
573 	fprintf( stderr, "%s: Can't open display", ProgramName );
574 	if ( DisplayName != NULL ) {
575 	    fprintf( stderr, " %s.\n", DisplayName );
576 	} else {
577 	    fprintf( stderr, ".\n" );
578 	}
579 	exit( 1 );
580     }
581 
582     theScreen = DefaultScreen( theDisplay );
583     theDepth = DefaultDepth( theDisplay, theScreen );
584 
585     theBlackPixel = BlackPixel( theDisplay, theScreen );
586     theWhitePixel = WhitePixel( theDisplay, theScreen );
587 
588     GeometryStatus = XParseGeometry( theGeometry,
589 				     &WindowPointX, &WindowPointY,
590 				     &WindowWidth, &WindowHeight );
591 
592     if ( !( GeometryStatus & XValue ) ) {
593 	WindowPointX = DEFAULT_WIN_X;
594     }
595     if ( !( GeometryStatus & YValue ) ) {
596 	WindowPointY = DEFAULT_WIN_Y;
597     }
598     if ( !( GeometryStatus & WidthValue ) ) {
599 	WindowWidth = WINDOW_WIDTH;
600     }
601     if ( !( GeometryStatus & HeightValue ) ) {
602 	WindowHeight = WINDOW_HEIGHT;
603     }
604 
605     theCursorSource
606 	= XCreateBitmapFromData( theDisplay,
607 				 RootWindow( theDisplay, theScreen ),
608 				 cursor_bits,
609 				 cursor_width,
610 				 cursor_height );
611 
612     theCursorMask
613 	= XCreateBitmapFromData( theDisplay,
614 				 RootWindow( theDisplay, theScreen ),
615 				 cursor_mask_bits,
616 				 cursor_mask_width,
617 				 cursor_mask_height );
618 
619     theColormap = DefaultColormap( theDisplay, theScreen );
620 
621     if ( !XAllocNamedColor( theDisplay, theColormap,
622 			    "white", &theWhiteColor, &theExactColor ) ) {
623 	fprintf( stderr,
624 		 "%s: Can't XAllocNamedColor( \"white\" ).\n", ProgramName );
625 	exit( 1 );
626     }
627 
628     if ( !XAllocNamedColor( theDisplay, theColormap,
629 			    "black", &theBlackColor, &theExactColor ) ) {
630 	fprintf( stderr,
631 		 "%s: Can't XAllocNamedColor( \"black\" ).\n", ProgramName );
632 	exit( 1 );
633     }
634 
635     theCursor = XCreatePixmapCursor( theDisplay,
636 				     theCursorSource, theCursorMask,
637 				     &theBlackColor, &theWhiteColor,
638 				     cursor_x_hot, cursor_y_hot );
639 
640     theWindowAttributes.border_pixel = theBlackPixel;
641     theWindowAttributes.background_pixel = theWhitePixel;
642     theWindowAttributes.cursor = theCursor;
643     theWindowAttributes.override_redirect = False;
644 
645     theWindowMask = CWBackPixel		|
646 		    CWBorderPixel	|
647 		    CWCursor		|
648 		    CWOverrideRedirect;
649 
650     theWindow = XCreateWindow( theDisplay,
651 			       RootWindow( theDisplay, theScreen ),
652 			       WindowPointX, WindowPointY,
653 			       WindowWidth, WindowHeight,
654 			       BorderWidth,
655 			       theDepth,
656 			       InputOutput,
657 			       CopyFromParent,
658 			       theWindowMask,
659 			       &theWindowAttributes );
660 
661     theIconPixmap = XCreateBitmapFromData( theDisplay, theWindow,
662 					   icon_bits,
663 					   icon_width,
664 					   icon_height );
665 
666     theWMHints.icon_pixmap = theIconPixmap;
667     if ( iconicState ) {
668 	theWMHints.initial_state = IconicState;
669     } else {
670 	theWMHints.initial_state = NormalState;
671     }
672     theWMHints.flags = IconPixmapHint | StateHint;
673 
674     XSetWMHints( theDisplay, theWindow, &theWMHints );
675 
676     theSizeHints.flags = PPosition | PSize;
677     theSizeHints.x = WindowPointX;
678     theSizeHints.y = WindowPointY;
679     theSizeHints.width = WindowWidth;
680     theSizeHints.height = WindowHeight;
681 
682     XSetNormalHints( theDisplay, theWindow, &theSizeHints );
683 
684     if ( strlen( TitleName ) >= 1 ) {
685 	XStoreName( theDisplay, theWindow, TitleName );
686 	XSetIconName( theDisplay, theWindow, TitleName );
687     } else {
688 	XStoreName( theDisplay, theWindow, ProgramName );
689 	XSetIconName( theDisplay, theWindow, ProgramName );
690     }
691 
692     XMapWindow( theDisplay, theWindow );
693 
694     XFlush( theDisplay );
695 
696     XGetGeometry( theDisplay, theWindow,
697 		  &theRoot,
698 		  &WindowPointX, &WindowPointY,
699 		  &WindowWidth, &WindowHeight,
700 		  &BorderWidth, &theDepth );
701 
702     InitBitmapAndGCs();
703 
704     XSelectInput( theDisplay, theWindow, EVENT_MASK1 );
705 
706     XFlush( theDisplay );
707 }
708 
709 
710 /*--------------------------------------------------------------
711  *
712  *	%$%s%?!</usr/home/csrg/sccs/games/xneko/SCCS/s.xneko.ck
713  *
714  *	!!$3$N4X?t$r8F$V$H!"$"$k0lDj$N;~4VJV$C$F$3$J$/$J$k!#G-
715  *	$NF0:n%?%$%_%s%0D4@0$KMxMQ$9$k$3$H!#
716  *
717  *--------------------------------------------------------------*/
718 
719 void
720 Interval()
721 {
722     pause();
723 }
724 
725 
726 /*--------------------------------------------------------------
727  *
728  *	s.xneko.c#728/%+%&%s%H=hM}
729  *
730  *--------------------------------------------------------------*/
731 
732 void
733 TickCount()
734 {
735     if ( ++NekoTickCount >= MAX_TICK ) {
736 	NekoTickCount = 0;
737     }
738 
739     if ( NekoTickCount % 2 == 0 ) {
740 	if ( NekoStateCount < MAX_TICK ) {
741 	    NekoStateCount++;
742 	}
743     }
744 }
745 
746 
747 /*--------------------------------------------------------------
748  *
749  *	G->uBV@_Dj
750  *
751  *--------------------------------------------------------------*/
752 
753 void
754 SetNekoState( SetValue )
755     int		SetValue;
756 {
757     NekoTickCount = 0;
758     NekoStateCount = 0;
759 
760     NekoState = SetValue;
761 
762 #ifdef	DEBUG
763     switch ( NekoState ) {
764     case NEKO_STOP:
765     case NEKO_JARE:
766     case NEKO_KAKI:
767     case NEKO_AKUBI:
768     case NEKO_SLEEP:
769     case NEKO_U_TOGI:
770     case NEKO_D_TOGI:
771     case NEKO_L_TOGI:
772     case NEKO_R_TOGI:
773 	NekoMoveDx = NekoMoveDy = 0;
774 	break;
775     default:
776 	break;
777     }
778 #endif
779 }
780 
781 
782 /*--------------------------------------------------------------
783  *
784  *	G-IA2h=hM}
785  *
786  *--------------------------------------------------------------*/
787 
788 void
789 DrawNeko( x, y, DrawGC )
790     int		x;
791     int		y;
792     GC		DrawGC;
793 {
794     if ( ( x != NekoLastX || y != NekoLastY )
795 	 && ( EventState != DEBUG_LIST ) ) {
796 	XFillRectangle( theDisplay, theWindow, SpaceGC,
797 			NekoLastX, NekoLastY,
798 			BITMAP_WIDTH, BITMAP_HEIGHT );
799     }
800 
801     XSetTSOrigin( theDisplay, DrawGC, x, y );
802 
803     XFillRectangle( theDisplay, theWindow, DrawGC,
804 		    x, y, BITMAP_WIDTH, BITMAP_HEIGHT );
805 
806     XFlush( theDisplay );
807 
808     NekoLastX = x;
809     NekoLastY = y;
810 
811     NekoLastGC = DrawGC;
812 }
813 
814 
815 /*--------------------------------------------------------------
816  *
817  *	G-:FIA2h=hM}
818  *
819  *--------------------------------------------------------------*/
820 
821 void
822 RedrawNeko()
823 {
824     XFillRectangle( theDisplay, theWindow, NekoLastGC,
825 		    NekoLastX, NekoLastY,
826 		    BITMAP_WIDTH, BITMAP_HEIGHT );
827 
828     XFlush( theDisplay );
829 }
830 
831 
832 /*--------------------------------------------------------------
833  *
834  *	G-0\F0J}K!7hDj
835  *
836  *--------------------------------------------------------------*/
837 
838 void
839 NekoDirection()
840 {
841     int			NewState;
842     double		LargeX, LargeY;
843     double		Length;
844     double		SinTheta;
845 
846     if ( NekoMoveDx == 0 && NekoMoveDy == 0 ) {
847 	NewState = NEKO_STOP;
848     } else {
849 	LargeX = (double)NekoMoveDx;
850 	LargeY = (double)(-NekoMoveDy);
851 	Length = sqrt( LargeX * LargeX + LargeY * LargeY );
852 	SinTheta = LargeY / Length;
853 
854 	if ( NekoMoveDx > 0 ) {
855 	    if ( SinTheta > SinPiPer8Times3 ) {
856 		NewState = NEKO_U_MOVE;
857 	    } else if ( ( SinTheta <= SinPiPer8Times3 )
858 			&& ( SinTheta > SinPiPer8 ) ) {
859 		NewState = NEKO_UR_MOVE;
860 	    } else if ( ( SinTheta <= SinPiPer8 )
861 			&& ( SinTheta > -( SinPiPer8 ) ) ) {
862 		NewState = NEKO_R_MOVE;
863 	    } else if ( ( SinTheta <= -( SinPiPer8 ) )
864 			&& ( SinTheta > -( SinPiPer8Times3 ) ) ) {
865 		NewState = NEKO_DR_MOVE;
866 	    } else {
867 		NewState = NEKO_D_MOVE;
868 	    }
869 	} else {
870 	    if ( SinTheta > SinPiPer8Times3 ) {
871 		NewState = NEKO_U_MOVE;
872 	    } else if ( ( SinTheta <= SinPiPer8Times3 )
873 			&& ( SinTheta > SinPiPer8 ) ) {
874 		NewState = NEKO_UL_MOVE;
875 	    } else if ( ( SinTheta <= SinPiPer8 )
876 			&& ( SinTheta > -( SinPiPer8 ) ) ) {
877 		NewState = NEKO_L_MOVE;
878 	    } else if ( ( SinTheta <= -( SinPiPer8 ) )
879 			&& ( SinTheta > -( SinPiPer8Times3 ) ) ) {
880 		NewState = NEKO_DL_MOVE;
881 	    } else {
882 		NewState = NEKO_D_MOVE;
883 	    }
884 	}
885     }
886 
887     if ( NekoState != NewState ) {
888 	SetNekoState( NewState );
889     }
890 }
891 
892 
893 /*--------------------------------------------------------------
894  *
895  *	G-JI$V$D$+$jH=Dj
896  *
897  *--------------------------------------------------------------*/
898 
899 Bool
900 IsWindowOver()
901 {
902     Bool	ReturnValue = False;
903 
904     if ( NekoY <= 0 ) {
905 	NekoY = 0;
906 	ReturnValue = True;
907     } else if ( NekoY >= WindowHeight - BITMAP_HEIGHT ) {
908 	NekoY = WindowHeight - BITMAP_HEIGHT;
909 	ReturnValue = True;
910     }
911     if ( NekoX <= 0 ) {
912 	NekoX = 0;
913 	ReturnValue = True;
914     } else if ( NekoX >= WindowWidth - BITMAP_WIDTH ) {
915 	NekoX = WindowWidth - BITMAP_WIDTH;
916 	ReturnValue = True;
917     }
918 
919     return( ReturnValue );
920 }
921 
922 
923 /*--------------------------------------------------------------
924  *
925  *	G-0\F0>u67H=Dj
926  *
927  *--------------------------------------------------------------*/
928 
929 Bool
930 IsNekoDontMove()
931 {
932     if ( NekoX == NekoLastX && NekoY == NekoLastY ) {
933 	return( True );
934     } else {
935 	return( False );
936     }
937 }
938 
939 
940 /*--------------------------------------------------------------
941  *
942  *	G-0\F03+;OH=Dj
943  *
944  *--------------------------------------------------------------*/
945 
946 Bool
947 IsNekoMoveStart()
948 {
949 #ifndef	DEBUG
950     if ( ( PrevMouseX >= MouseX - IDLE_SPACE
951 	 && PrevMouseX <= MouseX + IDLE_SPACE ) &&
952 	 ( PrevMouseY >= MouseY - IDLE_SPACE
953 	 && PrevMouseY <= MouseY + IDLE_SPACE ) ) {
954 	return( False );
955     } else {
956 	return( True );
957     }
958 #else
959     if ( NekoMoveDx == 0 && NekoMoveDy == 0 ) {
960 	return( False );
961     } else {
962 	return( True );
963     }
964 #endif
965 }
966 
967 
968 /*--------------------------------------------------------------
969  *
970  *	G-0\F0 dx, dy 7W;;
971  *
972  *--------------------------------------------------------------*/
973 
974 void
975 CalcDxDy()
976 {
977     Window		QueryRoot, QueryChild;
978     int			AbsoluteX, AbsoluteY;
979     int			RelativeX, RelativeY;
980     unsigned int	ModKeyMask;
981     double		LargeX, LargeY;
982     double		DoubleLength, Length;
983 
984     XQueryPointer( theDisplay, theWindow,
985 		   &QueryRoot, &QueryChild,
986 		   &AbsoluteX, &AbsoluteY,
987 		   &RelativeX, &RelativeY,
988 		   &ModKeyMask );
989 
990     PrevMouseX = MouseX;
991     PrevMouseY = MouseY;
992 
993     MouseX = RelativeX;
994     MouseY = RelativeY;
995 
996     LargeX = (double)( MouseX - NekoX - BITMAP_WIDTH / 2 );
997     LargeY = (double)( MouseY - NekoY - BITMAP_HEIGHT );
998 
999     DoubleLength = LargeX * LargeX + LargeY * LargeY;
1000 
1001     if ( DoubleLength != (double)0 ) {
1002 	Length = sqrt( DoubleLength );
1003 	if ( Length <= NekoSpeed ) {
1004 	    NekoMoveDx = (int)LargeX;
1005 	    NekoMoveDy = (int)LargeY;
1006 	} else {
1007 	    NekoMoveDx = (int)( ( NekoSpeed * LargeX ) / Length );
1008 	    NekoMoveDy = (int)( ( NekoSpeed * LargeY ) / Length );
1009 	}
1010     } else {
1011 	NekoMoveDx = NekoMoveDy = 0;
1012     }
1013 }
1014 
1015 
1016 /*--------------------------------------------------------------
1017  *
1018  *	F0:n2r@OG-IA2h=hM}
1019  *
1020  *--------------------------------------------------------------*/
1021 
1022 void
1023 NekoThinkDraw()
1024 {
1025 #ifndef	DEBUG
1026     CalcDxDy();
1027 #endif
1028 
1029     if ( NekoState != NEKO_SLEEP ) {
1030 	DrawNeko( NekoX, NekoY,
1031 		  NekoTickCount % 2 == 0 ?
1032 		  *(AnimationPattern[ NekoState ].TickEvenGCPtr) :
1033 		  *(AnimationPattern[ NekoState ].TickOddGCPtr) );
1034     } else {
1035 	DrawNeko( NekoX, NekoY,
1036 		  NekoTickCount % 8 <= 3 ?
1037 		  *(AnimationPattern[ NekoState ].TickEvenGCPtr) :
1038 		  *(AnimationPattern[ NekoState ].TickOddGCPtr) );
1039     }
1040 
1041     TickCount();
1042 
1043     switch ( NekoState ) {
1044     case NEKO_STOP:
1045 	if ( IsNekoMoveStart() ) {
1046 	    SetNekoState( NEKO_AWAKE );
1047 	    break;
1048 	}
1049 	if ( NekoStateCount < NEKO_STOP_TIME ) {
1050 	    break;
1051 	}
1052 	if ( NekoMoveDx < 0 && NekoX <= 0 ) {
1053 	    SetNekoState( NEKO_L_TOGI );
1054 	} else if ( NekoMoveDx > 0 && NekoX >= WindowWidth - BITMAP_WIDTH ) {
1055 	    SetNekoState( NEKO_R_TOGI );
1056 	} else if ( NekoMoveDy < 0 && NekoY <= 0 ) {
1057 	    SetNekoState( NEKO_U_TOGI );
1058 	} else if ( NekoMoveDy > 0 && NekoY >= WindowHeight - BITMAP_HEIGHT ) {
1059 	    SetNekoState( NEKO_D_TOGI );
1060 	} else {
1061 	    SetNekoState( NEKO_JARE );
1062 	}
1063 	break;
1064     case NEKO_JARE:
1065 	if ( IsNekoMoveStart() ) {
1066 	    SetNekoState( NEKO_AWAKE );
1067 	    break;
1068 	}
1069 	if ( NekoStateCount < NEKO_JARE_TIME ) {
1070 	    break;
1071 	}
1072 	SetNekoState( NEKO_KAKI );
1073 	break;
1074     case NEKO_KAKI:
1075 	if ( IsNekoMoveStart() ) {
1076 	    SetNekoState( NEKO_AWAKE );
1077 	    break;
1078 	}
1079 	if ( NekoStateCount < NEKO_KAKI_TIME ) {
1080 	    break;
1081 	}
1082 	SetNekoState( NEKO_AKUBI );
1083 	break;
1084     case NEKO_AKUBI:
1085 	if ( IsNekoMoveStart() ) {
1086 	    SetNekoState( NEKO_AWAKE );
1087 	    break;
1088 	}
1089 	if ( NekoStateCount < NEKO_AKUBI_TIME ) {
1090 	    break;
1091 	}
1092 	SetNekoState( NEKO_SLEEP );
1093 	break;
1094     case NEKO_SLEEP:
1095 	if ( IsNekoMoveStart() ) {
1096 	    SetNekoState( NEKO_AWAKE );
1097 	    break;
1098 	}
1099 	break;
1100     case NEKO_AWAKE:
1101 	if ( NekoStateCount < NEKO_AWAKE_TIME ) {
1102 	    break;
1103 	}
1104 	NekoDirection();	/* G-$,F0$/8~$-$r5a$a$k */
1105 	break;
1106     case NEKO_U_MOVE:
1107     case NEKO_D_MOVE:
1108     case NEKO_L_MOVE:
1109     case NEKO_R_MOVE:
1110     case NEKO_UL_MOVE:
1111     case NEKO_UR_MOVE:
1112     case NEKO_DL_MOVE:
1113     case NEKO_DR_MOVE:
1114 	NekoX += NekoMoveDx;
1115 	NekoY += NekoMoveDy;
1116 	NekoDirection();
1117 	if ( IsWindowOver() ) {
1118 	    if ( IsNekoDontMove() ) {
1119 		SetNekoState( NEKO_STOP );
1120 	    }
1121 	}
1122 	break;
1123     case NEKO_U_TOGI:
1124     case NEKO_D_TOGI:
1125     case NEKO_L_TOGI:
1126     case NEKO_R_TOGI:
1127 	if ( IsNekoMoveStart() ) {
1128 	    SetNekoState( NEKO_AWAKE );
1129 	    break;
1130 	}
1131 	if ( NekoStateCount < NEKO_TOGI_TIME ) {
1132 	    break;
1133 	}
1134 	SetNekoState( NEKO_KAKI );
1135 	break;
1136     default:
1137 	/* Internal Error */
1138 	SetNekoState( NEKO_STOP );
1139 	break;
1140     }
1141 
1142     Interval();
1143 }
1144 
1145 
1146 #ifdef	DEBUG
1147 
1148 /*--------------------------------------------------------------
1149  *
1150  *	%-%c%i%/%?!<0lMwI=<(!J05/22/91P11500MQ!K
1151  *
1152  *--------------------------------------------------------------*/
1153 
1154 void
1155 DisplayCharacters()
1156 {
1157     int		Index;
1158     int		x, y;
1159 
1160     for ( Index = 0, x = 0, y = 0;
1161 	  BitmapGCDataTable[ Index ].GCCreatePtr != NULL; Index++ ) {
1162 
1163 	DrawNeko( x, y, *(BitmapGCDataTable[ Index ].GCCreatePtr) );
1164 	XFlush( theDisplay );
1165 
1166 	x += BITMAP_WIDTH;
1167 
1168 	if ( x > WindowWidth - BITMAP_WIDTH ) {
1169 	    x = 0;
1170 	    y += BITMAP_HEIGHT;
1171 	    if ( y > WindowHeight - BITMAP_HEIGHT) {
1172 		break;
1173 	    }
1174 	}
1175     }
1176 }
1177 
1178 #endif	/* DEBUG */
1179 
1180 
1181 /*--------------------------------------------------------------
1182  *
1183  *	%-!<%$s%H=hM}
1184  *
1185  *--------------------------------------------------------------*/
1186 
1187 Bool
1188 ProcessKeyPress( theKeyEvent )
1189     XKeyEvent	*theKeyEvent;
1190 {
1191     int			Length;
1192     int			theKeyBufferMaxLen = AVAIL_KEYBUF;
1193     char		theKeyBuffer[ AVAIL_KEYBUF + 1 ];
1194     KeySym		theKeySym;
1195     XComposeStatus	theComposeStatus;
1196     Bool		ReturnState;
1197 
1198     ReturnState = True;
1199 
1200     Length = XLookupString( theKeyEvent,
1201 			    theKeyBuffer, theKeyBufferMaxLen,
1202 			    &theKeySym, &theComposeStatus );
1203 
1204     if ( Length > 0 ) {
1205 	switch ( theKeyBuffer[ 0 ] ) {
1206 	case 'q':
1207 	case 'Q':
1208 	    if ( theKeyEvent->state & Mod1Mask ) {	/* META (Alt) %-!< */
1209 		ReturnState = False;
1210 	    }
1211 	    break;
1212 	default:
1213 	    break;
1214 	}
1215     }
1216 
1217 #ifdef	DEBUG
1218     if ( EventState == DEBUG_MOVE ) {
1219 	switch ( theKeySym ) {
1220 	case XK_KP_1:
1221 	    NekoMoveDx = -(int)( NekoSpeed / sqrt( (double)2 ) );
1222 	    NekoMoveDy = -NekoMoveDx;
1223 	    break;
1224 	case XK_KP_2:
1225 	    NekoMoveDx = 0;
1226 	    NekoMoveDy = (int)NekoSpeed;
1227 	    break;
1228 	case XK_KP_3:
1229 	    NekoMoveDx = (int)( NekoSpeed / sqrt( (double)2 ) );
1230 	    NekoMoveDy = NekoMoveDx;
1231 	    break;
1232 	case XK_KP_4:
1233 	    NekoMoveDx = -(int)NekoSpeed;
1234 	    NekoMoveDy = 0;
1235 	    break;
1236 	case XK_KP_5:
1237 	    NekoMoveDx = 0;
1238 	    NekoMoveDy = 0;
1239 	    break;
1240 	case XK_KP_6:
1241 	    NekoMoveDx = (int)NekoSpeed;
1242 	    NekoMoveDy = 0;
1243 	    break;
1244 	case XK_KP_7:
1245 	    NekoMoveDx = -(int)( NekoSpeed / sqrt( (double)2 ) );
1246 	    NekoMoveDy = NekoMoveDx;
1247 	    break;
1248 	case XK_KP_8:
1249 	    NekoMoveDx = 0;
1250 	    NekoMoveDy = -(int)NekoSpeed;
1251 	    break;
1252 	case XK_KP_9:
1253 	    NekoMoveDx = (int)( NekoSpeed / sqrt( (double)2 ) );
1254 	    NekoMoveDy = -NekoMoveDx;
1255 	    break;
1256 	}
1257     }
1258 #endif
1259 
1260     return( ReturnState );
1261 }
1262 
1263 
1264 /*--------------------------------------------------------------
1265  *
1266  *	G-0LCVD4@0
1267  *
1268  *--------------------------------------------------------------*/
1269 
1270 void
1271 NekoAdjust()
1272 {
1273     if ( NekoX < 0 ) {
1274 	NekoX = 0;
1275     } else if ( NekoX > WindowWidth - BITMAP_WIDTH ) {
1276 	NekoX = WindowWidth - BITMAP_WIDTH;
1277     }
1278 
1279     if ( NekoY < 0 ) {
1280 	NekoY = 0;
1281     } else if ( NekoY > WindowHeight - BITMAP_HEIGHT ) {
1282 	NekoY = WindowHeight - BITMAP_HEIGHT;
1283     }
1284 }
1285 
1286 
1287 /*--------------------------------------------------------------
1288  *
1289  *	%$s%H=hM}
1290  *
1291  *--------------------------------------------------------------*/
1292 
1293 Bool
1294 ProcessEvent()
1295 {
1296     XEvent	theEvent;
1297     Bool	ContinueState = True;
1298 
1299     switch ( EventState ) {
1300     case NORMAL_STATE:
1301 	while ( XCheckMaskEvent( theDisplay, EVENT_MASK1, &theEvent ) ) {
1302 	    switch ( theEvent.type ) {
1303 	    case ConfigureNotify:
1304 		WindowWidth = theEvent.xconfigure.width;
1305 		WindowHeight = theEvent.xconfigure.height;
1306 		WindowPointX = theEvent.xconfigure.x;
1307 		WindowPointY = theEvent.xconfigure.y;
1308 		BorderWidth = theEvent.xconfigure.border_width;
1309 		NekoAdjust();
1310 		break;
1311 	    case Expose:
1312 		if ( theEvent.xexpose.count == 0 ) {
1313 		    RedrawNeko();
1314 		}
1315 		break;
1316 	    case MapNotify:
1317 		RedrawNeko();
1318 		break;
1319 	    case KeyPress:
1320 		ContinueState = ProcessKeyPress( &theEvent.xkey );
1321 		if ( !ContinueState ) {
1322 		    return( ContinueState );
1323 		}
1324 		break;
1325 	    default:
1326 		/* Unknown Event */
1327 		break;
1328 	    }
1329 	}
1330 	break;
1331 #ifdef	DEBUG
1332     case DEBUG_LIST:
1333 	XNextEvent( theDisplay, &theEvent );
1334 	switch ( theEvent.type ) {
1335 	case ConfigureNotify:
1336 	    WindowWidth = theEvent.xconfigure.width;
1337 	    WindowHeight = theEvent.xconfigure.height;
1338 	    WindowPointX = theEvent.xconfigure.x;
1339 	    WindowPointY = theEvent.xconfigure.y;
1340 	    BorderWidth = theEvent.xconfigure.border_width;
1341 	    break;
1342 	case Expose:
1343 	    if ( theEvent.xexpose.count == 0 ) {
1344 		DisplayCharacters();
1345 	    }
1346 	    break;
1347 	case MapNotify:
1348 	    DisplayCharacters();
1349 	    break;
1350 	case KeyPress:
1351 	    ContinueState = ProcessKeyPress( &theEvent );
1352 	    break;
1353 	default:
1354 	    /* Unknown Event */
1355 	    break;
1356 	}
1357 	break;
1358     case DEBUG_MOVE:
1359 	while ( XCheckMaskEvent( theDisplay, EVENT_MASK1, &theEvent ) ) {
1360 	    switch ( theEvent.type ) {
1361 	    case ConfigureNotify:
1362 		WindowWidth = theEvent.xconfigure.width;
1363 		WindowHeight = theEvent.xconfigure.height;
1364 		WindowPointX = theEvent.xconfigure.x;
1365 		WindowPointY = theEvent.xconfigure.y;
1366 		BorderWidth = theEvent.xconfigure.border_width;
1367 		NekoAdjust();
1368 		break;
1369 	    case Expose:
1370 		if ( theEvent.xexpose.count == 0 ) {
1371 		    RedrawNeko();
1372 		}
1373 		break;
1374 	    case MapNotify:
1375 		RedrawNeko();
1376 		break;
1377 	    case KeyPress:
1378 		ContinueState = ProcessKeyPress( &theEvent );
1379 		if ( !ContinueState ) {
1380 		    return( ContinueState );
1381 		}
1382 		break;
1383 	    default:
1384 		/* Unknown Event */
1385 		break;
1386 	    }
1387 	}
1388 	break;
1389 #endif
1390     default:
1391 	/* Internal Error */
1392 	break;
1393     }
1394 
1395     return( ContinueState );
1396 }
1397 
1398 
1399 /*--------------------------------------------------------------
1400  *
1401  *	G-=hM}
1402  *
1403  *--------------------------------------------------------------*/
1404 
1405 void
1406 ProcessNeko()
1407 {
1408     struct itimerval	Value;
1409 
1410     /* 4D6-$N=i4|2= */
1411 
1412     EventState = NORMAL_STATE;
1413 
1414     /* G-$N=i4|2= */
1415 
1416     NekoX = ( WindowWidth - BITMAP_WIDTH / 2 ) / 2;
1417     NekoY = ( WindowHeight - BITMAP_HEIGHT / 2 ) / 2;
1418 
1419     NekoLastX = NekoX;
1420     NekoLastY = NekoY;
1421 
1422     SetNekoState( NEKO_STOP );
1423 
1424     /* %?%$%^!<@_Dj */
1425 
1426     timerclear( &Value.it_interval );
1427     timerclear( &Value.it_value );
1428 
1429     Value.it_interval.tv_usec = IntervalTime;
1430     Value.it_value.tv_usec = IntervalTime;
1431 
1432     setitimer( ITIMER_REAL, &Value, 0 );
1433 
1434     /* %a%$%s=hM} */
1435 
1436     do {
1437 	NekoThinkDraw();
1438     } while ( ProcessEvent() );
1439 }
1440 
1441 
1442 #ifdef	DEBUG
1443 
1444 /*--------------------------------------------------------------
1445  *
1446  *	G-0lMw!J05/22/91P14460MQ!K
1447  *
1448  *--------------------------------------------------------------*/
1449 
1450 void
1451 NekoList()
1452 {
1453     EventState = DEBUG_LIST;
1454 
1455     fprintf( stderr, "\n" );
1456     fprintf( stderr, "G-0lMw$rI=<($7$^$9!#(Quit !D Alt-Q)\n" );
1457     fprintf( stderr, "\n" );
1458 
1459     XSelectInput( theDisplay, theWindow, EVENT_MASK2 );
1460 
1461     while ( ProcessEvent() );
1462 }
1463 
1464 
1465 /*--------------------------------------------------------------
1466  *
1467  *	G-0\F0s.xneko.c9%H!J05/22/91P14670MQ!K
1468  *
1469  *--------------------------------------------------------------*/
1470 
1471 void
1472 NekoMoveTest()
1473 {
1474     struct itimerval	Value;
1475 
1476     /* 4D6-$N=i4|2= */
1477 
1478     EventState = DEBUG_MOVE;
1479 
1480     /* G-$N=i4|2= */
1481 
1482     NekoX = ( WindowWidth - BITMAP_WIDTH / 2 ) / 2;
1483     NekoY = ( WindowHeight - BITMAP_HEIGHT / 2 ) / 2;
1484 
1485     NekoLastX = NekoX;
1486     NekoLastY = NekoY;
1487 
1488     SetNekoState( NEKO_STOP );
1489 
1490     /* %?%$%^!<@_Dj */
1491 
1492     timerclear( &Value.it_interval );
1493     timerclear( &Value.it_value );
1494 
1495     Value.it_interval.tv_usec = IntervalTime;
1496     Value.it_value.tv_usec = IntervalTime;
1497 
1498     setitimer( ITIMER_REAL, &Value, 0 );
1499 
1500     /* %a%$%s=hM} */
1501 
1502     fprintf( stderr, "\n" );
1503     fprintf( stderr, "G-$N0\F0s.xneko.c9%H$r9T$$$^$9!#(Quit !D Alt-Q)\n" );
1504     fprintf( stderr, "\n" );
1505     fprintf( stderr, "\t%-!<C%I>e$Ns.xneko.cs%-!<$GG-$r0\F0$5$;$F2<$5$$!#\n" );
1506     fprintf( stderr, "\t(M-8z$J%-!<$O#1!A#9$G$9!#)\n" );
1507     fprintf( stderr, "\n" );
1508 
1509     do {
1510 	NekoThinkDraw();
1511     } while ( ProcessEvent() );
1512 }
1513 
1514 
1515 /*--------------------------------------------------------------
1516  *
1517  *	%a%K%e!<=hM}!J05/22/91P15170MQ!K
1518  *
1519  *--------------------------------------------------------------*/
1520 
1521 void
1522 ProcessDebugMenu()
1523 {
1524     int		UserSelectNo = 0;
1525     char	UserAnswer[ BUFSIZ ];
1526 
1527     fprintf( stderr, "\n" );
1528     fprintf( stderr, "!Zxneko 05/22/91P15280%a%K%e!<![\n" );
1529 
1530     while ( !( UserSelectNo >= 1 && UserSelectNo <= 2 ) ) {
1531 	fprintf( stderr, "\n" );
1532 	fprintf( stderr, "\t1)!!G-%-%c%i%/%?!<0lMwI=<(\n" );
1533 	fprintf( stderr, "\t2)!!G-0\F0s.xneko.c9%H\n" );
1534 	fprintf( stderr, "\n" );
1535 	fprintf( stderr, "Select: " );
1536 
1537 	fgets( UserAnswer, sizeof( UserAnswer ), stdin );
1538 
1539 	UserSelectNo = atoi( UserAnswer );
1540 
1541 	if ( !( UserSelectNo >= 1 && UserSelectNo <= 2 ) ) {
1542 	    fprintf( stderr, "\n" );
1543 	    fprintf( stderr, "@5$7$$HV9f$rA*Br$7$F2<$5$$!#\n" );
1544 	}
1545     }
1546 
1547     switch ( UserSelectNo ) {
1548     case 1:
1549 	/* G-%-%c%i%/%?!<0lMwI=<( */
1550 	NekoList();
1551 	break;
1552     case 2:
1553 	/* G-0\F0s.xneko.c9%H */
1554 	NekoMoveTest();
1555 	break;
1556     default:
1557 	/* Internal Error */
1558 	break;
1559     }
1560 
1561     fprintf( stderr, "s.xneko.c9%H=*N;!#\n" );
1562     fprintf( stderr, "\n" );
1563 }
1564 
1565 #endif	/* DEBUG */
1566 
1567 
1568 /*--------------------------------------------------------------
1569  *
1570  *	SIGALRM %7%0%J%k=hM}
1571  *
1572  *--------------------------------------------------------------*/
1573 
1574 void
1575 NullFunction()
1576 {
1577     /* No Operation */
1578 }
1579 
1580 
1581 /*--------------------------------------------------------------
1582  *
1583  *	Usage
1584  *
1585  *--------------------------------------------------------------*/
1586 
1587 void
1588 Usage()
1589 {
1590     fprintf( stderr,
1591 	     "Usage: %s [-display <display>] [-geometry <geometry>] \\\n",
1592 	     ProgramName );
1593     fprintf( stderr, "  [-title <title>] [-name <title>] [-iconic] \\\n" );
1594     fprintf( stderr, "  [-speed <speed>] [-time <time>] [-help]\n" );
1595 }
1596 
1597 
1598 /*--------------------------------------------------------------
1599  *
1600  *	#Xi%a!<%?I>2A
1601  *
1602  *--------------------------------------------------------------*/
1603 
1604 Bool
1605 GetArguments( argc, argv, theDisplayName, theGeometry, theTitle,
1606 	      NekoSpeed, IntervalTime )
1607     int		argc;
1608     char	*argv[];
1609     char	*theDisplayName;
1610     char	*theGeometry;
1611     char	*theTitle;
1612     double	*NekoSpeed;
1613     long	*IntervalTime;
1614 {
1615     int		ArgCounter;
1616     Bool	iconicState;
1617 
1618     theDisplayName[ 0 ] = '\0';
1619     theGeometry[ 0 ] = '\0';
1620     theTitle[ 0 ] = '\0';
1621 
1622     iconicState = False;
1623 
1624     for ( ArgCounter = 0; ArgCounter < argc; ArgCounter++ ) {
1625 
1626 	if ( strncmp( argv[ ArgCounter ], "-h", 2 ) == 0 ) {
1627 	    Usage();
1628 	    exit( 0 );
1629 	} else if ( strcmp( argv[ ArgCounter ], "-display" ) == 0 ) {
1630 	    ArgCounter++;
1631 	    if ( ArgCounter < argc ) {
1632 		strcpy( theDisplayName, argv[ ArgCounter ] );
1633 	    } else {
1634 		fprintf( stderr, "%s: -display option error.\n", ProgramName );
1635 		exit( 1 );
1636 	    }
1637 	} else if ( strncmp( argv[ ArgCounter ], "-geom", 5 ) == 0 ) {
1638 	    ArgCounter++;
1639 	    if ( ArgCounter < argc ) {
1640 		strcpy( theGeometry, argv[ ArgCounter ] );
1641 	    } else {
1642 		fprintf( stderr,
1643 			 "%s: -geometry option error.\n", ProgramName );
1644 		exit( 1 );
1645 	    }
1646 	} else if ( ( strcmp( argv[ ArgCounter ], "-title" ) == 0 )
1647 	     || ( strcmp( argv[ ArgCounter ], "-name" ) == 0 ) ) {
1648 	    ArgCounter++;
1649 	    if ( ArgCounter < argc ) {
1650 		strcpy( theTitle, argv[ ArgCounter ] );
1651 	    } else {
1652 		fprintf( stderr, "%s: -title option error.\n", ProgramName );
1653 		exit( 1 );
1654 	    }
1655 	} else if ( strcmp( argv[ ArgCounter ], "-iconic" ) == 0 ) {
1656 	    iconicState = True;
1657 	} else if ( strcmp( argv[ ArgCounter ], "-speed" ) == 0 ) {
1658 	    ArgCounter++;
1659 	    if ( ArgCounter < argc ) {
1660 		*NekoSpeed = atof( argv[ ArgCounter ] );
1661 	    } else {
1662 		fprintf( stderr, "%s: -speed option error.\n", ProgramName );
1663 		exit( 1 );
1664 	    }
1665 	} else if ( strcmp( argv[ ArgCounter ], "-time" ) == 0 ) {
1666 	    ArgCounter++;
1667 	    if ( ArgCounter < argc ) {
1668 		*IntervalTime = atol( argv[ ArgCounter ] );
1669 	    } else {
1670 		fprintf( stderr, "%s: -time option error.\n", ProgramName );
1671 		exit( 1 );
1672 	    }
1673 	} else {
1674 	    fprintf( stderr,
1675 		     "%s: Unknown option \"%s\".\n", ProgramName,
1676 						     argv[ ArgCounter ] );
1677 	    Usage();
1678 	    exit( 1 );
1679 	}
1680     }
1681 
1682     if ( strlen( theDisplayName ) < 1 ) {
1683 	theDisplayName = NULL;
1684     }
1685 
1686     if ( strlen( theGeometry ) < 1 ) {
1687 	theGeometry = NULL;
1688     }
1689 
1690     return( iconicState );
1691 }
1692 
1693 
1694 /*--------------------------------------------------------------
1695  *
1696  *	%a%$%s4X?t
1697  *
1698  *--------------------------------------------------------------*/
1699 
1700 int
1701 main( argc, argv )
1702     int		argc;
1703     char	*argv[];
1704 {
1705     Bool	iconicState;
1706     char	theDisplayName[ DIRNAMELEN ];
1707     char	theGeometry[ DIRNAMELEN ];
1708     char	theTitle[ DIRNAMELEN ];
1709 
1710     ProgramName = argv[ 0 ];
1711 
1712     argc--;
1713     argv++;
1714 
1715     iconicState = GetArguments( argc, argv,
1716 				theDisplayName,
1717 				theGeometry,
1718 				theTitle,
1719 				&NekoSpeed,
1720 				&IntervalTime );
1721 
1722     InitScreen( theDisplayName, theGeometry, theTitle, iconicState );
1723 
1724     signal( SIGALRM, NullFunction );
1725 
1726     SinPiPer8Times3 = sin( PI_PER8 * (double)3 );
1727     SinPiPer8 = sin( PI_PER8 );
1728 
1729 #ifndef	DEBUG
1730     ProcessNeko();
1731 #else
1732     ProcessDebugMenu();
1733 #endif
1734 
1735     exit( 0 );
1736 }
1737