1 /*
2  *	oneko  -  X11 $@G-(J
3  */
4 
5 #ifndef	lint
6 static char rcsid[] = "$Header: /home/sun/unix/kato/xsam/oneko/oneko.c,v 1.5 90/10/19 21:25:16 kato Exp $";
7 #endif
8 
9 #include "oneko.h"
10 #include "patchlevel.h"
11 /*
12  *	$@%0%m!<%P%kJQ?t(J
13  */
14 
15 char	*ClassName = "Oneko";		/* $@%3%^%s%IL>>N(J */
16 char	*ProgramName;			/* $@%3%^%s%IL>>N(J */
17 
18 Display	*theDisplay;			/* $@%G%#%9%W%l%$9=B$BN(J */
19 int	theScreen;			/* $@%9%/%j!<%sHV9f(J */
20 unsigned int	theDepth;		/* $@%G%W%9(J */
21 Window	theRoot;			/* $@%k!<%H%&%#%s%I%&$N#I#D(J */
22 Window	theWindow;			/* $@G-%&%#%s%I%&$N#I#D(J */
23 char    *WindowName = NULL;		/* $@G-%&%#%s%I%&$NL>A0(J */
24 Window	theTarget = None;		/* $@L\I8%&%#%s%I%&$N#I#D(J */
25 char    *TargetName = NULL;		/* $@L\I8%&%#%s%I%&$NL>A0(J */
26 Cursor	theCursor;			/* $@$M$:$_%+!<%=%k(J */
27 
28 unsigned int	WindowWidth;		/* $@%k!<%H%&%#%s%I%&$NI}(J */
29 unsigned int	WindowHeight;		/* $@%k!<%H%&%#%s%I%&$N9b$5(J */
30 
31 XColor	theForegroundColor;		/* $@?'(J ($@%U%)%"%0%i%&%s%I(J) */
32 XColor	theBackgroundColor;		/* $@?'(J ($@%P%C%/%0%i%&%s%I(J) */
33 
34 int Synchronous = False;
35 /* Types of animals */
36 #define BITMAPTYPES 6
37 typedef struct _AnimalDefaults {
38   char *name;
39   int speed, idle, bitmap_width, bitmap_height;
40   long time;
41   int off_x, off_y;
42   char *cursor,*mask;
43   int cursor_width,cursor_height,cursor_x_hot,cursor_y_hot;
44 } AnimalDefaultsData;
45 
46 AnimalDefaultsData AnimalDefaultsDataTable[] =
47 {
48   { "neko", 13, 6, 32, 32, 125000L, 0, 0, mouse_cursor_bits,mouse_cursor_mask_bits,
49       mouse_cursor_width,mouse_cursor_height, mouse_cursor_x_hot,mouse_cursor_y_hot },
50   { "tora", 16, 6, 32, 32, 125000L, 0, 0, mouse_cursor_bits,mouse_cursor_mask_bits,
51       mouse_cursor_width,mouse_cursor_height, mouse_cursor_x_hot,mouse_cursor_y_hot },
52   { "dog" , 10, 6, 32, 32, 125000L, 0, 0, bone_cursor_bits,bone_cursor_mask_bits,
53       bone_cursor_width,bone_cursor_height, bone_cursor_x_hot,bone_cursor_y_hot },
54   { "bsd_daemon" , 16, 6, 32, 32, 300000L, 22, 20, bsd_cursor_bits,bsd_cursor_mask_bits,
55       bsd_cursor_width,bsd_cursor_height, bsd_cursor_x_hot,bsd_cursor_y_hot },
56   { "sakura" , 13, 6, 32, 32, 125000L, 0, 0, card_cursor_bits,card_cursor_mask_bits,
57       card_cursor_width,card_cursor_height, card_cursor_x_hot,card_cursor_y_hot },
58   { "tomoyo" , 10, 6, 32, 32, 125000L, 32, 32, petal_cursor_bits,petal_cursor_mask_bits,
59       petal_cursor_width,petal_cursor_height, petal_cursor_x_hot,petal_cursor_y_hot },
60 };
61 
62 /*
63  *	$@$$$m$$$m$J=i4|@_Dj(J ($@%*%W%7%g%s!"%j%=!<%9$GJQ$($i$l$k$h(J)
64  */
65 
66 					/* Resource:	*/
67 char	*Foreground = NULL;		/*   foreground	*/
68 char	*Background = NULL;		/*   background	*/
69 long	IntervalTime = 0L;		/*   time	*/
70 double	NekoSpeed = (double)0;		/*   speed	*/
71 int	IdleSpace = 0;			/*   idle	*/
72 int	NekoMoyou = NOTDEFINED;		/*   tora	*/
73 int	NoShape = NOTDEFINED;		/*   noshape	*/
74 int	ReverseVideo = NOTDEFINED;	/*   reverse	*/
75 int	ToWindow = NOTDEFINED;		/*   towindow	*/
76 int	ToFocus = NOTDEFINED;		/*   tofocus	*/
77 int     XOffset=0,YOffset=0;            /* X and Y offsets for cat from mouse
78 					   pointer. */
79 /*
80  *	$@$$$m$$$m$J>uBVJQ?t(J
81  */
82 
83 Bool	DontMapped = True;
84 
85 int	NekoTickCount;		/* $@G-F0:n%+%&%s%?(J */
86 int	NekoStateCount;		/* $@G-F10l>uBV%+%&%s%?(J */
87 int	NekoState;		/* $@G-$N>uBV(J */
88 
89 int	MouseX;			/* $@%^%&%9#X:BI8(J */
90 int	MouseY;			/* $@%^%&%9#Y:BI8(J */
91 
92 int	PrevMouseX = 0;		/* $@D>A0$N%^%&%9#X:BI8(J */
93 int	PrevMouseY = 0;		/* $@D>A0$N%^%&%9#Y:BI8(J */
94 Window	PrevTarget = None;	/* $@D>A0$NL\I8%&%#%s%I%&$N#I#D(J */
95 
96 int	NekoX;			/* $@G-#X:BI8(J */
97 int	NekoY;			/* $@G-#Y:BI8(J */
98 
99 int	NekoMoveDx;		/* $@G-0\F05wN%#X(J */
100 int	NekoMoveDy;		/* $@G-0\F05wN%#Y(J */
101 
102 int	NekoLastX;		/* $@G-:G=*IA2h#X:BI8(J */
103 int	NekoLastY;		/* $@G-:G=*IA2h#Y:BI8(J */
104 GC	NekoLastGC;		/* $@G-:G=*IA2h(J GC */
105 /* Variables used to set how quickly the program will chose to raise itself. */
106 /* Look at Interval(), Handle Visiblility Notify Event */
107 #define DEFAULT_RAISE_WAIT 16  /* About 2 seconds with default interval */
108 int     RaiseWindowDelay=0;
109 /*
110  *	$@$=$NB>(J
111  */
112 
113 double	SinPiPer8Times3;	/* sin($@#3&P!?#8(J) */
114 double	SinPiPer8;		/* sin($@&P!?#8(J) */
115 
116 Pixmap	Mati2Xbm, Jare2Xbm, Kaki1Xbm, Kaki2Xbm, Mati3Xbm, Sleep1Xbm, Sleep2Xbm;
117 Pixmap	Mati2Msk, Jare2Msk, Kaki1Msk, Kaki2Msk, Mati3Msk, Sleep1Msk, Sleep2Msk;
118 
119 Pixmap	AwakeXbm, AwakeMsk;
120 
121 Pixmap	Up1Xbm, Up2Xbm, Down1Xbm, Down2Xbm, Left1Xbm, Left2Xbm;
122 Pixmap	Up1Msk, Up2Msk, Down1Msk, Down2Msk, Left1Msk, Left2Msk;
123 Pixmap	Right1Xbm, Right2Xbm, UpLeft1Xbm, UpLeft2Xbm, UpRight1Xbm;
124 Pixmap	Right1Msk, Right2Msk, UpLeft1Msk, UpLeft2Msk, UpRight1Msk;
125 Pixmap	UpRight2Xbm, DownLeft1Xbm, DownLeft2Xbm, DownRight1Xbm, DownRight2Xbm;
126 Pixmap	UpRight2Msk, DownLeft1Msk, DownLeft2Msk, DownRight1Msk, DownRight2Msk;
127 
128 Pixmap	UpTogi1Xbm, UpTogi2Xbm, DownTogi1Xbm, DownTogi2Xbm, LeftTogi1Xbm;
129 Pixmap	UpTogi1Msk, UpTogi2Msk, DownTogi1Msk, DownTogi2Msk, LeftTogi1Msk;
130 Pixmap	LeftTogi2Xbm, RightTogi1Xbm, RightTogi2Xbm;
131 Pixmap	LeftTogi2Msk, RightTogi1Msk, RightTogi2Msk;
132 
133 GC      Mati2GC;
134 
135 GC	Jare2GC, Kaki1GC, Kaki2GC, Mati3GC, Sleep1GC, Sleep2GC;
136 
137 GC	AwakeGC;
138 
139 GC	Up1GC, Up2GC, Down1GC, Down2GC, Left1GC, Left2GC, Right1GC, Right2GC;
140 GC	UpLeft1GC, UpLeft2GC, UpRight1GC, UpRight2GC, DownLeft1GC, DownLeft2GC;
141 GC	DownRight1GC, DownRight2GC;
142 
143 GC	UpTogi1GC, UpTogi2GC, DownTogi1GC, DownTogi2GC, LeftTogi1GC;
144 GC	LeftTogi2GC, RightTogi1GC, RightTogi2GC;
145 
146 
147 typedef struct {
148     GC		*GCCreatePtr;
149     Pixmap	*BitmapCreatePtr;
150     char	*PixelPattern[BITMAPTYPES];
151     Pixmap	*BitmapMasksPtr;
152     char	*MaskPattern[BITMAPTYPES];
153 } BitmapGCData;
154 
155 BitmapGCData	BitmapGCDataTable[] =
156 {
157     { &Mati2GC, &Mati2Xbm,  mati2_bits, mati2_tora_bits, mati2_dog_bits, mati2_bsd_bits, mati2_sakura_bits, mati2_tomoyo_bits,
158       &Mati2Msk, mati2_mask_bits, mati2_mask_bits, mati2_dog_mask_bits, mati2_bsd_mask_bits, mati2_sakura_mask_bits, mati2_tomoyo_mask_bits },
159     { &Jare2GC, &Jare2Xbm,  jare2_bits, jare2_tora_bits, jare2_dog_bits, jare2_bsd_bits, jare2_sakura_bits, jare2_tomoyo_bits,
160       &Jare2Msk, jare2_mask_bits, jare2_mask_bits, jare2_dog_mask_bits, jare2_bsd_mask_bits, jare2_sakura_mask_bits, jare2_tomoyo_mask_bits },
161     { &Kaki1GC, &Kaki1Xbm,  kaki1_bits, kaki1_tora_bits, kaki1_dog_bits, kaki1_bsd_bits, kaki1_sakura_bits, kaki1_tomoyo_bits,
162       &Kaki1Msk, kaki1_mask_bits, kaki1_mask_bits, kaki1_dog_mask_bits, kaki1_bsd_mask_bits, kaki1_sakura_mask_bits, kaki1_tomoyo_mask_bits },
163     { &Kaki2GC, &Kaki2Xbm,  kaki2_bits, kaki2_tora_bits, kaki2_dog_bits, kaki2_bsd_bits, kaki2_sakura_bits, kaki2_tomoyo_bits,
164       &Kaki2Msk, kaki2_mask_bits, kaki2_mask_bits, kaki2_dog_mask_bits, kaki2_bsd_mask_bits, kaki2_sakura_mask_bits, kaki2_tomoyo_mask_bits },
165     { &Mati3GC, &Mati3Xbm,  mati3_bits, mati3_tora_bits, mati3_dog_bits, mati3_bsd_bits, mati3_sakura_bits, mati3_tomoyo_bits,
166       &Mati3Msk, mati3_mask_bits, mati3_mask_bits, mati3_dog_mask_bits, mati3_bsd_mask_bits, mati3_sakura_mask_bits, mati3_tomoyo_mask_bits },
167     { &Sleep1GC, &Sleep1Xbm,  sleep1_bits, sleep1_tora_bits, sleep1_dog_bits, sleep1_bsd_bits, sleep1_sakura_bits, sleep1_tomoyo_bits,
168       &Sleep1Msk, sleep1_mask_bits, sleep1_mask_bits, sleep1_dog_mask_bits, sleep1_bsd_mask_bits, sleep1_sakura_mask_bits, sleep1_tomoyo_mask_bits },
169     { &Sleep2GC, &Sleep2Xbm,  sleep2_bits, sleep2_tora_bits, sleep2_dog_bits, sleep2_bsd_bits, sleep2_sakura_bits, sleep2_tomoyo_bits,
170       &Sleep2Msk, sleep2_mask_bits, sleep2_mask_bits, sleep2_dog_mask_bits, sleep2_bsd_mask_bits, sleep2_sakura_mask_bits, sleep2_tomoyo_mask_bits },
171     { &AwakeGC, &AwakeXbm,  awake_bits, awake_tora_bits, awake_dog_bits, awake_bsd_bits, awake_sakura_bits, awake_tomoyo_bits,
172       &AwakeMsk, awake_mask_bits, awake_mask_bits, awake_dog_mask_bits, awake_bsd_mask_bits, awake_sakura_mask_bits, awake_tomoyo_mask_bits },
173     { &Up1GC, &Up1Xbm,  up1_bits, up1_tora_bits, up1_dog_bits, up1_bsd_bits, up1_sakura_bits, up1_tomoyo_bits,
174       &Up1Msk, up1_mask_bits, up1_mask_bits, up1_dog_mask_bits, up1_bsd_mask_bits, up1_sakura_mask_bits, up1_tomoyo_mask_bits },
175     { &Up2GC, &Up2Xbm,  up2_bits, up2_tora_bits, up2_dog_bits, up2_bsd_bits, up2_sakura_bits, up2_tomoyo_bits,
176       &Up2Msk, up2_mask_bits, up2_mask_bits, up2_dog_mask_bits, up2_bsd_mask_bits, up2_sakura_mask_bits, up2_tomoyo_mask_bits },
177     { &Down1GC, &Down1Xbm,  down1_bits, down1_tora_bits, down1_dog_bits, down1_bsd_bits, down1_sakura_bits, down1_tomoyo_bits,
178       &Down1Msk, down1_mask_bits, down1_mask_bits, down1_dog_mask_bits, down1_bsd_mask_bits, down1_sakura_mask_bits, down1_tomoyo_mask_bits },
179     { &Down2GC, &Down2Xbm,  down2_bits, down2_tora_bits, down2_dog_bits, down2_bsd_bits, down2_sakura_bits, down2_tomoyo_bits,
180       &Down2Msk, down2_mask_bits, down2_mask_bits, down2_dog_mask_bits, down2_bsd_mask_bits, down2_sakura_mask_bits, down2_tomoyo_mask_bits },
181     { &Left1GC, &Left1Xbm,  left1_bits, left1_tora_bits, left1_dog_bits, left1_bsd_bits, left1_sakura_bits, left1_tomoyo_bits,
182       &Left1Msk, left1_mask_bits, left1_mask_bits, left1_dog_mask_bits, left1_bsd_mask_bits, left1_sakura_mask_bits, left1_tomoyo_mask_bits },
183     { &Left2GC, &Left2Xbm,  left2_bits, left2_tora_bits, left2_dog_bits, left2_bsd_bits, left2_sakura_bits, left2_tomoyo_bits,
184       &Left2Msk, left2_mask_bits, left2_mask_bits, left2_dog_mask_bits, left2_bsd_mask_bits, left2_sakura_mask_bits, left2_tomoyo_mask_bits },
185     { &Right1GC, &Right1Xbm,  right1_bits, right1_tora_bits, right1_dog_bits, right1_bsd_bits, right1_sakura_bits, right1_tomoyo_bits,
186       &Right1Msk, right1_mask_bits, right1_mask_bits,right1_dog_mask_bits, right1_bsd_mask_bits, right1_sakura_mask_bits, right1_tomoyo_mask_bits },
187     { &Right2GC, &Right2Xbm,  right2_bits, right2_tora_bits, right2_dog_bits, right2_bsd_bits, right2_sakura_bits, right2_tomoyo_bits,
188       &Right2Msk, right2_mask_bits, right2_mask_bits, right2_dog_mask_bits, right2_bsd_mask_bits, right2_sakura_mask_bits, right2_tomoyo_mask_bits },
189     { &UpLeft1GC, &UpLeft1Xbm,  upleft1_bits, upleft1_tora_bits, upleft1_dog_bits, upleft1_bsd_bits, upleft1_sakura_bits, upleft1_tomoyo_bits,
190       &UpLeft1Msk, upleft1_mask_bits, upleft1_mask_bits, upleft1_dog_mask_bits, upleft1_bsd_mask_bits, upleft1_sakura_mask_bits, upleft1_tomoyo_mask_bits },
191     { &UpLeft2GC, &UpLeft2Xbm,  upleft2_bits, upleft2_tora_bits, upleft2_dog_bits, upleft2_bsd_bits, upleft2_sakura_bits, upleft2_tomoyo_bits,
192       &UpLeft2Msk, upleft2_mask_bits, upleft2_mask_bits,upleft2_dog_mask_bits, upleft2_bsd_mask_bits, upleft2_sakura_mask_bits, upleft2_tomoyo_mask_bits },
193     { &UpRight1GC, &UpRight1Xbm,  upright1_bits, upright1_tora_bits, upright1_dog_bits, upright1_bsd_bits, upright1_sakura_bits, upright1_tomoyo_bits,
194       &UpRight1Msk, upright1_mask_bits, upright1_mask_bits,upright1_dog_mask_bits, upright1_bsd_mask_bits, upright1_sakura_mask_bits, upright1_tomoyo_mask_bits },
195     { &UpRight2GC, &UpRight2Xbm,  upright2_bits, upright2_tora_bits, upright2_dog_bits, upright2_bsd_bits, upright2_sakura_bits, upright2_tomoyo_bits,
196       &UpRight2Msk, upright2_mask_bits, upright2_mask_bits,upright2_dog_mask_bits, upright2_bsd_mask_bits, upright2_sakura_mask_bits, upright2_tomoyo_mask_bits },
197     { &DownLeft1GC, &DownLeft1Xbm,  dwleft1_bits, dwleft1_tora_bits, dwleft1_dog_bits, dwleft1_bsd_bits, dwleft1_sakura_bits, dwleft1_tomoyo_bits,
198       &DownLeft1Msk, dwleft1_mask_bits, dwleft1_mask_bits, dwleft1_dog_mask_bits, dwleft1_bsd_mask_bits, dwleft1_sakura_mask_bits, dwleft1_tomoyo_mask_bits },
199     { &DownLeft2GC, &DownLeft2Xbm,  dwleft2_bits, dwleft2_tora_bits, dwleft2_dog_bits, dwleft2_bsd_bits, dwleft2_sakura_bits, dwleft2_tomoyo_bits,
200       &DownLeft2Msk, dwleft2_mask_bits, dwleft2_mask_bits, dwleft2_dog_mask_bits, dwleft2_bsd_mask_bits, dwleft2_sakura_mask_bits, dwleft2_tomoyo_mask_bits },
201     { &DownRight1GC, &DownRight1Xbm,  dwright1_bits, dwright1_tora_bits, dwright1_dog_bits, dwright1_bsd_bits, dwright1_sakura_bits, dwright1_tomoyo_bits,
202       &DownRight1Msk, dwright1_mask_bits, dwright1_mask_bits, dwright1_dog_mask_bits, dwright1_bsd_mask_bits, dwright1_sakura_mask_bits, dwright1_tomoyo_mask_bits },
203     { &DownRight2GC, &DownRight2Xbm,  dwright2_bits, dwright2_tora_bits, dwright2_dog_bits, dwright2_bsd_bits, dwright2_sakura_bits, dwright2_tomoyo_bits,
204       &DownRight2Msk, dwright2_mask_bits, dwright2_mask_bits, dwright2_dog_mask_bits, dwright2_bsd_mask_bits, dwright2_sakura_mask_bits, dwright2_tomoyo_mask_bits },
205     { &UpTogi1GC, &UpTogi1Xbm,  utogi1_bits, utogi1_tora_bits, utogi1_dog_bits, utogi1_bsd_bits, utogi1_sakura_bits, utogi1_tomoyo_bits,
206       &UpTogi1Msk, utogi1_mask_bits, utogi1_mask_bits, utogi1_dog_mask_bits, utogi1_bsd_mask_bits, utogi1_sakura_mask_bits, utogi1_tomoyo_mask_bits },
207     { &UpTogi2GC, &UpTogi2Xbm,  utogi2_bits, utogi2_tora_bits, utogi2_dog_bits, utogi2_bsd_bits, utogi2_sakura_bits, utogi2_tomoyo_bits,
208       &UpTogi2Msk, utogi2_mask_bits, utogi2_mask_bits, utogi2_dog_mask_bits, utogi2_bsd_mask_bits, utogi2_sakura_mask_bits, utogi2_tomoyo_mask_bits },
209     { &DownTogi1GC, &DownTogi1Xbm,  dtogi1_bits, dtogi1_tora_bits, dtogi1_dog_bits, dtogi1_bsd_bits, dtogi1_sakura_bits, dtogi1_tomoyo_bits,
210       &DownTogi1Msk, dtogi1_mask_bits, dtogi1_mask_bits, dtogi1_dog_mask_bits, dtogi1_bsd_mask_bits, dtogi1_sakura_mask_bits, dtogi1_tomoyo_mask_bits },
211     { &DownTogi2GC, &DownTogi2Xbm,  dtogi2_bits, dtogi2_tora_bits, dtogi2_dog_bits, dtogi2_bsd_bits, dtogi2_sakura_bits, dtogi2_tomoyo_bits,
212       &DownTogi2Msk, dtogi2_mask_bits, dtogi2_mask_bits, dtogi2_dog_mask_bits, dtogi2_bsd_mask_bits, dtogi2_sakura_mask_bits, dtogi2_tomoyo_mask_bits },
213     { &LeftTogi1GC, &LeftTogi1Xbm,  ltogi1_bits, ltogi1_tora_bits, ltogi1_dog_bits, ltogi1_bsd_bits, ltogi1_sakura_bits, ltogi1_tomoyo_bits,
214       &LeftTogi1Msk, ltogi1_mask_bits, ltogi1_mask_bits,ltogi1_dog_mask_bits, ltogi1_bsd_mask_bits, ltogi1_sakura_mask_bits, ltogi1_tomoyo_mask_bits },
215     { &LeftTogi2GC, &LeftTogi2Xbm,  ltogi2_bits, ltogi2_tora_bits, ltogi2_dog_bits, ltogi2_bsd_bits, ltogi2_sakura_bits, ltogi2_tomoyo_bits,
216       &LeftTogi2Msk, ltogi2_mask_bits, ltogi2_mask_bits,ltogi2_dog_mask_bits, ltogi2_bsd_mask_bits, ltogi2_sakura_mask_bits, ltogi2_tomoyo_mask_bits },
217     { &RightTogi1GC, &RightTogi1Xbm,  rtogi1_bits, rtogi1_tora_bits, rtogi1_dog_bits, rtogi1_bsd_bits, rtogi1_sakura_bits, rtogi1_tomoyo_bits,
218       &RightTogi1Msk, rtogi1_mask_bits, rtogi1_mask_bits,rtogi1_dog_mask_bits, rtogi1_bsd_mask_bits, rtogi1_sakura_mask_bits, rtogi1_tomoyo_mask_bits },
219     { &RightTogi2GC, &RightTogi2Xbm,  rtogi2_bits, rtogi2_tora_bits, rtogi2_dog_bits, rtogi2_bsd_bits, rtogi2_sakura_bits, rtogi2_tomoyo_bits,
220       &RightTogi2Msk, rtogi2_mask_bits, rtogi2_mask_bits,rtogi2_dog_mask_bits, rtogi2_bsd_mask_bits, rtogi2_sakura_mask_bits, rtogi2_tomoyo_mask_bits },
221     { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
222 };
223 
224 typedef struct {
225     GC		*TickGCPtr;
226     Pixmap	*TickMaskPtr;
227 } Animation;
228 
229 Animation	AnimationPattern[][2] =
230 {
231   { { &Mati2GC, &Mati2Msk },
232     { &Mati2GC, &Mati2Msk } },		/* NekoState == NEKO_STOP */
233   { { &Jare2GC, &Jare2Msk },
234     { &Mati2GC, &Mati2Msk } },		/* NekoState == NEKO_JARE */
235   { { &Kaki1GC, &Kaki1Msk },
236     { &Kaki2GC, &Kaki2Msk } },		/* NekoState == NEKO_KAKI */
237   { { &Mati3GC, &Mati3Msk },
238     { &Mati3GC, &Mati3Msk } },		/* NekoState == NEKO_AKUBI */
239   { { &Sleep1GC, &Sleep1Msk },
240     { &Sleep2GC, &Sleep2Msk } },		/* NekoState == NEKO_SLEEP */
241   { { &AwakeGC, &AwakeMsk },
242     { &AwakeGC, &AwakeMsk } },		/* NekoState == NEKO_AWAKE */
243   { { &Up1GC, &Up1Msk },
244     { &Up2GC, &Up2Msk } },		/* NekoState == NEKO_U_MOVE */
245   { { &Down1GC, &Down1Msk },
246     { &Down2GC, &Down2Msk } },		/* NekoState == NEKO_D_MOVE */
247   { { &Left1GC, &Left1Msk },
248     { &Left2GC, &Left2Msk } },		/* NekoState == NEKO_L_MOVE */
249   { { &Right1GC, &Right1Msk },
250     { &Right2GC, &Right2Msk } },		/* NekoState == NEKO_R_MOVE */
251   { { &UpLeft1GC, &UpLeft1Msk },
252     { &UpLeft2GC, &UpLeft2Msk } },	/* NekoState == NEKO_UL_MOVE */
253   { { &UpRight1GC, &UpRight1Msk },
254     { &UpRight2GC, &UpRight2Msk } },	/* NekoState == NEKO_UR_MOVE */
255   { { &DownLeft1GC, &DownLeft1Msk },
256     { &DownLeft2GC, &DownLeft2Msk } },	/* NekoState == NEKO_DL_MOVE */
257   { { &DownRight1GC, &DownRight1Msk },
258     { &DownRight2GC, &DownRight2Msk } },	/* NekoState == NEKO_DR_MOVE */
259   { { &UpTogi1GC, &UpTogi1Msk },
260     { &UpTogi2GC, &UpTogi2Msk } },	/* NekoState == NEKO_U_TOGI */
261   { { &DownTogi1GC, &DownTogi1Msk },
262     { &DownTogi2GC, &DownTogi2Msk } },	/* NekoState == NEKO_D_TOGI */
263   { { &LeftTogi1GC, &LeftTogi1Msk },
264     { &LeftTogi2GC, &LeftTogi2Msk } },	/* NekoState == NEKO_L_TOGI */
265   { { &RightTogi1GC, &RightTogi1Msk },
266     { &RightTogi2GC, &RightTogi2Msk } },	/* NekoState == NEKO_R_TOGI */
267 };
268 
269 static void NullFunction();
270 
271 /*
272  *	$@%S%C%H%^%C%W%G!<%?!&(JGC $@=i4|2=(J
273  */
274 
275 void
InitBitmapAndGCs()276 InitBitmapAndGCs()
277 {
278     BitmapGCData	*BitmapGCDataTablePtr;
279     XGCValues		theGCValues;
280 
281     theGCValues.function = GXcopy;
282     theGCValues.foreground = theForegroundColor.pixel;
283     theGCValues.background = theBackgroundColor.pixel;
284     theGCValues.fill_style = FillTiled;
285     theGCValues.ts_x_origin = 0;
286     theGCValues.ts_y_origin = 0;
287 
288     for (BitmapGCDataTablePtr = BitmapGCDataTable;
289 	 BitmapGCDataTablePtr->GCCreatePtr != NULL;
290 	 BitmapGCDataTablePtr++) {
291 
292 	*(BitmapGCDataTablePtr->BitmapCreatePtr)
293 	    = XCreatePixmapFromBitmapData(theDisplay, theRoot,
294 		BitmapGCDataTablePtr->PixelPattern[NekoMoyou],
295 		BITMAP_WIDTH, BITMAP_HEIGHT,
296 		theForegroundColor.pixel,
297 		theBackgroundColor.pixel,
298 		DefaultDepth(theDisplay, theScreen));
299 
300 	theGCValues.tile = *(BitmapGCDataTablePtr->BitmapCreatePtr);
301 
302 	*(BitmapGCDataTablePtr->BitmapMasksPtr)
303 	    = XCreateBitmapFromData(theDisplay, theRoot,
304 		BitmapGCDataTablePtr->MaskPattern[NekoMoyou],
305 		BITMAP_WIDTH, BITMAP_HEIGHT);
306 
307 	*(BitmapGCDataTablePtr->GCCreatePtr)
308 	    = XCreateGC(theDisplay, theWindow,
309 		GCFunction | GCForeground | GCBackground | GCTile |
310 		GCTileStipXOrigin | GCTileStipYOrigin | GCFillStyle,
311 		&theGCValues);
312     }
313 }
314 
315 /*
316  *	$@%j%=!<%9!&%G!<%?%Y!<%9$+$iI,MW$J%j%=!<%9$r<h$j=P$9(J
317  */
318 
319 char	*
NekoGetDefault(resource)320 NekoGetDefault(resource)
321 char	*resource;
322 {
323 	char	*value;
324 
325 	if (value = XGetDefault(theDisplay, ProgramName, resource)) {
326 		return value;
327 	}
328 	if (value = XGetDefault(theDisplay, ClassName, resource)) {
329 		return value;
330 	}
331 	return NULL;
332 }
333 
334 /*
335  *	$@%j%=!<%9!&%G!<%?%Y!<%9$+$i%*%W%7%g%s$r@_Dj(J
336  */
337 
GetResources()338 GetResources()
339 {
340   char	*resource;
341   int		num;
342   int loop;
343   if (Foreground == NULL) {
344     if ((resource = NekoGetDefault("foreground")) != NULL) {
345       Foreground = resource;
346     }
347   }
348 
349   if (Background == NULL) {
350     if ((resource = NekoGetDefault("background")) != NULL) {
351       Background = resource;
352     }
353   }
354 
355   if (IntervalTime == 0) {
356     if ((resource = NekoGetDefault("time")) != NULL) {
357       if (num = atoi(resource)) {
358 	IntervalTime = num;
359       }
360     }
361   }
362 
363   if (NekoSpeed == (double)0) {
364     if ((resource = NekoGetDefault("speed")) != NULL) {
365       if (num = atoi(resource)) {
366 	NekoSpeed = (double)num;
367       }
368     }
369   }
370 
371   if (IdleSpace == 0) {
372     if ((resource = NekoGetDefault("idle")) != NULL) {
373       if (num = atoi(resource)) {
374 	IdleSpace = num;
375       }
376     }
377   }
378 
379   if (NekoMoyou == NOTDEFINED) {
380     for (loop=0;loop<BITMAPTYPES;loop++)
381       if ((resource = NekoGetDefault(AnimalDefaultsDataTable[loop].name)) != NULL) {
382 	if (IsTrue(resource))
383 	  NekoMoyou = loop;
384       }
385   }
386 
387   if (NoShape == NOTDEFINED) {
388     if ((resource = NekoGetDefault("noshape")) != NULL) {
389       NoShape = IsTrue(resource);
390     }
391   }
392 
393   if (ReverseVideo == NOTDEFINED) {
394     if ((resource = NekoGetDefault("reverse")) != NULL) {
395       ReverseVideo = IsTrue(resource);
396     }
397   }
398 
399   if (Foreground == NULL) {
400     Foreground = DEFAULT_FOREGROUND;
401   }
402   if (Background == NULL) {
403     Background = DEFAULT_BACKGROUND;
404   }
405   if (NekoMoyou == NOTDEFINED) {
406     NekoMoyou = 0;
407   }
408   if (IntervalTime == 0) {
409     IntervalTime = AnimalDefaultsDataTable[NekoMoyou].time;
410   }
411   if (NekoSpeed == (double)0) {
412     NekoSpeed = (double)(AnimalDefaultsDataTable[NekoMoyou].speed);
413   }
414   if (IdleSpace == 0) {
415     IdleSpace = AnimalDefaultsDataTable[NekoMoyou].idle;
416   }
417   XOffset = XOffset + AnimalDefaultsDataTable[NekoMoyou].off_x;
418   YOffset = YOffset + AnimalDefaultsDataTable[NekoMoyou].off_y;
419   if (NoShape == NOTDEFINED) {
420     NoShape = False;
421   }
422   if (ReverseVideo == NOTDEFINED) {
423     ReverseVideo = False;
424   }
425   if (ToWindow == NOTDEFINED) {
426     ToWindow = False;
427   }
428   if (ToFocus == NOTDEFINED) {
429     ToFocus = False;
430   }
431 }
432 
433 /*
434  *	$@$M$:$_7?%+!<%=%k$r:n$k(J
435  */
436 
MakeMouseCursor()437 MakeMouseCursor()
438 {
439     Pixmap			theCursorSource;
440     Pixmap			theCursorMask;
441 
442     theCursorSource
443 	= XCreateBitmapFromData(theDisplay, theRoot,
444 				AnimalDefaultsDataTable[NekoMoyou].cursor,
445 				AnimalDefaultsDataTable[NekoMoyou].cursor_width,
446 				AnimalDefaultsDataTable[NekoMoyou].cursor_height);
447 
448     theCursorMask
449 	= XCreateBitmapFromData(theDisplay, theRoot,
450 				AnimalDefaultsDataTable[NekoMoyou].mask,
451 				AnimalDefaultsDataTable[NekoMoyou].cursor_width,
452 				AnimalDefaultsDataTable[NekoMoyou].cursor_height);
453 
454     theCursor = XCreatePixmapCursor(theDisplay, theCursorSource, theCursorMask,
455 				    &theBackgroundColor, &theForegroundColor,
456 				    AnimalDefaultsDataTable[NekoMoyou].cursor_x_hot,
457 				    AnimalDefaultsDataTable[NekoMoyou].cursor_y_hot);
458     XFreePixmap(theDisplay,theCursorSource);
459     XFreePixmap(theDisplay,theCursorMask);
460 }
461 
462 /*
463  *	$@?'$r=i4|@_Dj$9$k(J
464  */
465 
SetupColors()466 SetupColors()
467 {
468     XColor	theExactColor;
469     Colormap	theColormap;
470 
471     theColormap = DefaultColormap(theDisplay, theScreen);
472 
473     if (theDepth == 1) {
474 	Foreground = "black";
475 	Background = "white";
476     }
477 
478     if (ReverseVideo == True) {
479 	char	*tmp;
480 
481 	tmp = Foreground;
482 	Foreground = Background;
483 	Background = tmp;
484     }
485 
486     if (!XAllocNamedColor(theDisplay, theColormap,
487 		Foreground, &theForegroundColor, &theExactColor)) {
488 	fprintf(stderr, "%s: Can't XAllocNamedColor(\"%s\").\n",
489 		ProgramName, Foreground);
490 	exit(1);
491     }
492 
493     if (!XAllocNamedColor(theDisplay, theColormap,
494 		Background, &theBackgroundColor, &theExactColor)) {
495 	fprintf(stderr, "%s: Can't XAllocNamedColor(\"%s\").\n",
496 		ProgramName, Background);
497 	exit(1);
498     }
499 }
500 
501 /*
502  * Routine to let user select a window using the mouse
503  *
504  * This routine originate in dsimple.c
505  */
506 
Select_Window(dpy)507 Window Select_Window(dpy)
508      Display *dpy;
509 {
510   int status;
511   Cursor cursor;
512   XEvent event;
513   Window target_win = None, root = theRoot;
514   int buttons = 0;
515 
516   /* Make the target cursor */
517   cursor = theCursor;
518 
519   /* Grab the pointer using target cursor, letting it room all over */
520   status = XGrabPointer(dpy, root, False,
521 			ButtonPressMask|ButtonReleaseMask, GrabModeSync,
522 			GrabModeAsync, root, cursor, CurrentTime);
523   if (status != GrabSuccess) {
524     fprintf(stderr, "%s: Can't grab the mouse.\n", ProgramName);
525     exit(1);
526   }
527 
528   /* Let the user select a window... */
529   while ((target_win == None) || (buttons != 0)) {
530     /* allow one more event */
531     XAllowEvents(dpy, SyncPointer, CurrentTime);
532     XWindowEvent(dpy, root, ButtonPressMask|ButtonReleaseMask, &event);
533     switch (event.type) {
534     case ButtonPress:
535       if (target_win == None) {
536 	target_win = event.xbutton.subwindow; /* window selected */
537 	if (target_win == None) target_win = root;
538       }
539       buttons++;
540       break;
541     case ButtonRelease:
542       if (buttons > 0) /* there may have been some down before we started */
543 	buttons--;
544        break;
545     }
546   }
547 
548   XUngrabPointer(dpy, CurrentTime);      /* Done with pointer */
549 
550   return(target_win);
551 }
552 
553 /*
554  * Window_With_Name: routine to locate a window with a given name on a display.
555  *                   If no window with the given name is found, 0 is returned.
556  *                   If more than one window has the given name, the first
557  *                   one found will be returned.  Only top and its subwindows
558  *                   are looked at.  Normally, top should be the RootWindow.
559  *
560  * This routine originate in dsimple.c
561  */
Window_With_Name(dpy,top,name)562 Window Window_With_Name(dpy, top, name)
563      Display *dpy;
564      Window top;
565      char *name;
566 {
567 	Window *children, dummy;
568 	unsigned int nchildren;
569 	int i;
570 	Window w=0;
571 	char *window_name;
572 
573 	if (XFetchName(dpy, top, &window_name) && !strcmp(window_name, name))
574 	  return(top);
575 
576 	if (!XQueryTree(dpy, top, &dummy, &dummy, &children, &nchildren))
577 	  return(0);
578 
579 	for (i=0; i<nchildren; i++) {
580 		w = Window_With_Name(dpy, children[i], name);
581 		if (w)
582 		  break;
583 	}
584 	if (children) XFree ((char *)children);
585 	return(w);
586 }
587 
588 /*
589  *	$@%9%/%j!<%s4D6-=i4|2=(J
590  */
591 
592 void
InitScreen(DisplayName)593 InitScreen(DisplayName)
594     char	*DisplayName;
595 {
596   XSetWindowAttributes	theWindowAttributes;
597   unsigned long		theWindowMask;
598   Window			theTempRoot;
599   int				WindowPointX;
600   int				WindowPointY;
601   unsigned int		BorderWidth;
602   int				event_base, error_base;
603 
604   if ((theDisplay = XOpenDisplay(DisplayName)) == NULL) {
605     fprintf(stderr, "%s: Can't open display", ProgramName);
606     if (DisplayName != NULL) {
607       fprintf(stderr, " %s.\n", DisplayName);
608     } else {
609       fprintf(stderr, ".\n");
610     }
611     exit(1);
612   }
613 
614   GetResources();
615 
616   if (Synchronous == True) {
617     fprintf(stderr,"Synchronizing.\n");
618     XSynchronize(theDisplay,True);
619   }
620 
621 #ifdef SHAPE
622   if (!NoShape && XShapeQueryExtension(theDisplay,
623 				       &event_base, &error_base) == False) {
624     fprintf(stderr, "Display not suported shape extension.\n");
625     NoShape = True;
626 				       }
627 #endif SHAPE
628 
629   theScreen = DefaultScreen(theDisplay);
630   theDepth = DefaultDepth(theDisplay, theScreen);
631 
632   theRoot = RootWindow(theDisplay, theScreen);
633 
634   XGetGeometry(theDisplay, theRoot, &theTempRoot,
635 	       &WindowPointX, &WindowPointY,
636 	       &WindowWidth, &WindowHeight,
637 	       &BorderWidth, &theDepth);
638 
639   SetupColors();
640   MakeMouseCursor();
641 
642   if (ToWindow && theTarget == None) {
643     if (TargetName != NULL) {
644       int i;
645 
646       for (i=0; i<5; i++) {
647 	theTarget = Window_With_Name(theDisplay, theRoot, TargetName);
648 	if (theTarget != None) break;
649       }
650       if (theTarget == None) {
651 	fprintf(stderr, "%s: No window with name '%s' exists.\n",
652 		ProgramName, TargetName);
653 	exit(1);
654       }
655     } else {
656       theTarget = Select_Window(theDisplay);
657       if (theTarget == theRoot) {
658 	theTarget = None;
659 	ToWindow = False;
660       }
661     }
662     if (theTarget != None) {
663       Window		QueryRoot, QueryParent, *QueryChildren;
664       unsigned int	nchild;
665 
666       for (;;) {
667 	if (XQueryTree(theDisplay, theTarget, &QueryRoot,
668 		       &QueryParent, &QueryChildren, &nchild)) {
669 	  XFree(QueryChildren);
670 	  if (QueryParent == QueryRoot) break;
671 	  theTarget = QueryParent;
672 	}
673 	else {
674 	  fprintf(stderr, "%s: Target Lost.\n",ProgramName);
675 	  exit(1);
676 	}
677       }
678     }
679   }
680 
681   theWindowAttributes.background_pixel = theBackgroundColor.pixel;
682   theWindowAttributes.cursor = theCursor;
683   theWindowAttributes.override_redirect = True;
684 
685   if (!ToWindow) XChangeWindowAttributes(theDisplay, theRoot, CWCursor,
686 					 &theWindowAttributes);
687 
688   theWindowMask = CWBackPixel		|
689     CWCursor		|
690       CWOverrideRedirect;
691 
692   theWindow = XCreateWindow(theDisplay, theRoot, 0, 0,
693 			    BITMAP_WIDTH, BITMAP_HEIGHT,
694 			    0, theDepth, InputOutput, CopyFromParent,
695 			    theWindowMask, &theWindowAttributes);
696 
697   if (WindowName == NULL) WindowName = ProgramName;
698   XStoreName(theDisplay, theWindow, WindowName);
699 
700   InitBitmapAndGCs();
701 
702   XSelectInput(theDisplay, theWindow,
703 	       ExposureMask|VisibilityChangeMask|KeyPressMask);
704 
705   XFlush(theDisplay);
706 }
707 
708 
709 /*
710  *	SIGINT $@%7%0%J%k=hM}(J
711  */
712 
713 void
RestoreCursor()714 RestoreCursor()
715 {
716   XSetWindowAttributes	theWindowAttributes;
717   BitmapGCData *BitmapGCDataTablePtr;
718 
719   theWindowAttributes.cursor = None;
720   XChangeWindowAttributes(theDisplay, theRoot, CWCursor,
721 			  &theWindowAttributes);
722   for (BitmapGCDataTablePtr = BitmapGCDataTable;
723        BitmapGCDataTablePtr->GCCreatePtr != NULL;
724        BitmapGCDataTablePtr++) {
725     XFreePixmap(theDisplay,*(BitmapGCDataTablePtr->BitmapCreatePtr));
726     XFreePixmap(theDisplay,*(BitmapGCDataTablePtr->BitmapMasksPtr));
727     XFreeGC(theDisplay,*(BitmapGCDataTablePtr->GCCreatePtr));
728        }
729   XFreeCursor(theDisplay,theCursor);
730   XCloseDisplay(theDisplay);
731   exit(0);
732 }
733 
734 
735 /*
736  *	$@%$%s%?!<%P%k(J
737  *
738  *	$@!!$3$N4X?t$r8F$V$H!"$"$k0lDj$N;~4VJV$C$F$3$J$/$J$k!#G-(J
739  *	$@$NF0:n%?%$%_%s%0D4@0$KMxMQ$9$k$3$H!#(J
740  */
741 
742 void
Interval()743 Interval()
744 {
745     pause();
746     if (RaiseWindowDelay>0)
747       RaiseWindowDelay--;
748 }
749 
750 
751 /*
752  *	$@%F%#%C%/%+%&%s%H=hM}(J
753  */
754 
755 void
TickCount()756 TickCount()
757 {
758     if (++NekoTickCount >= MAX_TICK) {
759 	NekoTickCount = 0;
760     }
761 
762     if (NekoTickCount % 2 == 0) {
763 	if (NekoStateCount < MAX_TICK) {
764 	    NekoStateCount++;
765 	}
766     }
767 }
768 
769 
770 /*
771  *	$@G->uBV@_Dj(J
772  */
773 
774 void
SetNekoState(SetValue)775 SetNekoState(SetValue)
776     int		SetValue;
777 {
778     NekoTickCount = 0;
779     NekoStateCount = 0;
780 
781     NekoState = SetValue;
782 }
783 
784 
785 /*
786  *	$@G-IA2h=hM}(J
787  */
788 
789 void
DrawNeko(x,y,DrawAnime)790 DrawNeko(x, y, DrawAnime)
791     int		x;
792     int		y;
793     Animation	DrawAnime;
794 {
795 /*@@@@@@*/
796     register GC		DrawGC = *(DrawAnime.TickGCPtr);
797     register Pixmap	DrawMask = *(DrawAnime.TickMaskPtr);
798 
799     if ((x != NekoLastX) || (y != NekoLastY)
800 		|| (DrawGC != NekoLastGC)) {
801       XWindowChanges	theChanges;
802 
803       theChanges.x = x;
804       theChanges.y = y;
805       XConfigureWindow(theDisplay, theWindow, CWX | CWY, &theChanges);
806 #ifdef SHAPE
807       if (NoShape == False) {
808 	XShapeCombineMask(theDisplay, theWindow, ShapeBounding,
809 			  0, 0, DrawMask, ShapeSet);
810 
811       }
812 #endif SHAPE
813       if (DontMapped) {
814 	XMapWindow(theDisplay, theWindow);
815 	DontMapped = 0;
816       }
817       XFillRectangle(theDisplay, theWindow, DrawGC,
818 		     0, 0, BITMAP_WIDTH, BITMAP_HEIGHT);
819     }
820 
821     XFlush(theDisplay);
822 
823     NekoLastX = x;
824     NekoLastY = y;
825 
826     NekoLastGC = DrawGC;
827 }
828 
829 
830 /*
831  *	$@G-:FIA2h=hM}(J
832  */
833 
834 void
RedrawNeko()835 RedrawNeko()
836 {
837   XFillRectangle(theDisplay, theWindow, NekoLastGC,
838 		 0, 0, BITMAP_WIDTH, BITMAP_HEIGHT);
839 
840   XFlush(theDisplay);
841 }
842 
843 
844 /*
845  *	$@G-0\F0J}K!7hDj(J
846  *
847  *      This sets the direction that the neko is moving.
848  *
849  */
850 
851 void
NekoDirection()852 NekoDirection()
853 {
854     int			NewState;
855     double		LargeX, LargeY;
856     double		Length;
857     double		SinTheta;
858 
859     if (NekoMoveDx == 0 && NekoMoveDy == 0) {
860 	NewState = NEKO_STOP;
861     } else {
862 	LargeX = (double)NekoMoveDx;
863 	LargeY = (double)(-NekoMoveDy);
864 	Length = sqrt(LargeX * LargeX + LargeY * LargeY);
865 	SinTheta = LargeY / Length;
866 
867 	if (NekoMoveDx > 0) {
868 	    if (SinTheta > SinPiPer8Times3) {
869 		NewState = NEKO_U_MOVE;
870 	    } else if ((SinTheta <= SinPiPer8Times3)
871 			&& (SinTheta > SinPiPer8)) {
872 		NewState = NEKO_UR_MOVE;
873 	    } else if ((SinTheta <= SinPiPer8)
874 			&& (SinTheta > -(SinPiPer8))) {
875 		NewState = NEKO_R_MOVE;
876 	    } else if ((SinTheta <= -(SinPiPer8))
877 			&& (SinTheta > -(SinPiPer8Times3))) {
878 		NewState = NEKO_DR_MOVE;
879 	    } else {
880 		NewState = NEKO_D_MOVE;
881 	    }
882 	} else {
883 	    if (SinTheta > SinPiPer8Times3) {
884 		NewState = NEKO_U_MOVE;
885 	    } else if ((SinTheta <= SinPiPer8Times3)
886 			&& (SinTheta > SinPiPer8)) {
887 		NewState = NEKO_UL_MOVE;
888 	    } else if ((SinTheta <= SinPiPer8)
889 			&& (SinTheta > -(SinPiPer8))) {
890 		NewState = NEKO_L_MOVE;
891 	    } else if ((SinTheta <= -(SinPiPer8))
892 			&& (SinTheta > -(SinPiPer8Times3))) {
893 		NewState = NEKO_DL_MOVE;
894 	    } else {
895 		NewState = NEKO_D_MOVE;
896 	    }
897 	}
898     }
899 
900     if (NekoState != NewState) {
901 	SetNekoState(NewState);
902     }
903 }
904 
905 
906 /*
907  *	$@G-JI$V$D$+$jH=Dj(J
908  */
909 
910 Bool
IsWindowOver()911 IsWindowOver()
912 {
913     Bool	ReturnValue = False;
914 
915     if (NekoY <= 0) {
916 	NekoY = 0;
917 	ReturnValue = True;
918     } else if (NekoY >= WindowHeight - BITMAP_HEIGHT) {
919 	NekoY = WindowHeight - BITMAP_HEIGHT;
920 	ReturnValue = True;
921     }
922     if (NekoX <= 0) {
923 	NekoX = 0;
924 	ReturnValue = True;
925     } else if (NekoX >= WindowWidth - BITMAP_WIDTH) {
926 	NekoX = WindowWidth - BITMAP_WIDTH;
927 	ReturnValue = True;
928     }
929 
930     return(ReturnValue);
931 }
932 
933 
934 /*
935  *	$@G-0\F0>u67H=Dj(J
936  */
937 
938 Bool
IsNekoDontMove()939 IsNekoDontMove()
940 {
941     if (NekoX == NekoLastX && NekoY == NekoLastY) {
942 	return(True);
943     } else {
944 	return(False);
945     }
946 }
947 
948 
949 /*
950  *	$@G-0\F03+;OH=Dj(J
951  */
952 
953 Bool
IsNekoMoveStart()954 IsNekoMoveStart()
955 {
956     if ((PrevMouseX >= MouseX - IdleSpace
957 	 && PrevMouseX <= MouseX + IdleSpace) &&
958 	 (PrevMouseY >= MouseY - IdleSpace
959 	 && PrevMouseY <= MouseY + IdleSpace) &&
960 	(PrevTarget == theTarget)) {
961 	return(False);
962     } else {
963 	return(True);
964     }
965 }
966 
967 
968 /*
969  *	$@G-0\F0(J dx, dy $@7W;;(J
970  */
971 
972 void
CalcDxDy()973 CalcDxDy()
974 {
975     Window		QueryRoot, QueryChild;
976     int			AbsoluteX, AbsoluteY;
977     int			RelativeX, RelativeY;
978     unsigned int	ModKeyMask;
979     double		LargeX, LargeY;
980     double		DoubleLength, Length;
981 
982     XQueryPointer(theDisplay, theWindow,
983 		   &QueryRoot, &QueryChild,
984 		   &AbsoluteX, &AbsoluteY,
985 		   &RelativeX, &RelativeY,
986 		   &ModKeyMask);
987 
988     PrevMouseX = MouseX;
989     PrevMouseY = MouseY;
990     PrevTarget = theTarget;
991 
992     MouseX = AbsoluteX+XOffset;
993     MouseY = AbsoluteY+YOffset;
994 
995     if (ToFocus) {
996       int		revert;
997 
998       XGetInputFocus(theDisplay, &theTarget, &revert);
999 
1000       if (theTarget != theRoot
1001 	  && theTarget != PointerRoot && theTarget != None) {
1002 	Window		QueryParent, *QueryChildren;
1003 	unsigned int	nchild;
1004 
1005 	for (;;) {
1006 	  if (XQueryTree(theDisplay, theTarget, &QueryRoot,
1007 			 &QueryParent, &QueryChildren, &nchild)) {
1008 	    XFree(QueryChildren);
1009 	    if (QueryParent == QueryRoot) break;
1010 	    theTarget = QueryParent;
1011 	  }
1012 	  else {
1013 	    theTarget = None;
1014 	    break;
1015 	  }
1016 	}
1017       }
1018       else {
1019 	theTarget = None;
1020       }
1021     }
1022 
1023     if ((ToWindow || ToFocus) && theTarget != None) {
1024       int			status;
1025       XWindowAttributes		theTargetAttributes;
1026 
1027       status =
1028 	XGetWindowAttributes(theDisplay, theTarget, &theTargetAttributes);
1029 
1030       if (ToWindow && status == 0) {
1031 	fprintf(stderr, "%s: '%s', Target Lost.\n",ProgramName, WindowName);
1032 	RestoreCursor();
1033       }
1034 
1035       if (theTargetAttributes.x+theTargetAttributes.width > 0
1036 	  && theTargetAttributes.x < (int)WindowWidth
1037 	  && theTargetAttributes.y+theTargetAttributes.height > 0
1038 	  && theTargetAttributes.y < (int)WindowHeight
1039 	  && theTargetAttributes.map_state == IsViewable) {
1040 	if (ToFocus) {
1041 	  if (MouseX < theTargetAttributes.x+BITMAP_WIDTH/2)
1042 	    LargeX = (double)(theTargetAttributes.x + XOffset - NekoX);
1043 	  else if (MouseX > theTargetAttributes.x+theTargetAttributes.width
1044 		   -BITMAP_WIDTH/2)
1045 	    LargeX = (double)(theTargetAttributes.x + theTargetAttributes.width
1046 			      + XOffset - NekoX - BITMAP_WIDTH);
1047 	  else
1048 	    LargeX = (double)(MouseX - NekoX - BITMAP_WIDTH / 2);
1049 
1050 	  LargeY = (double)(theTargetAttributes.y
1051 			    + YOffset - NekoY - BITMAP_HEIGHT);
1052 	}
1053 	else {
1054 	  MouseX = theTargetAttributes.x
1055 	    + theTargetAttributes.width / 2 + XOffset;
1056 	  MouseY = theTargetAttributes.y + YOffset;
1057 	  LargeX = (double)(MouseX - NekoX - BITMAP_WIDTH / 2);
1058 	  LargeY = (double)(MouseY - NekoY - BITMAP_HEIGHT);
1059 	}
1060       }
1061       else {
1062 	LargeX = (double)(MouseX - NekoX - BITMAP_WIDTH / 2);
1063 	LargeY = (double)(MouseY - NekoY - BITMAP_HEIGHT);
1064       }
1065     }
1066     else {
1067       LargeX = (double)(MouseX - NekoX - BITMAP_WIDTH / 2);
1068       LargeY = (double)(MouseY - NekoY - BITMAP_HEIGHT);
1069     }
1070 
1071     DoubleLength = LargeX * LargeX + LargeY * LargeY;
1072 
1073     if (DoubleLength != (double)0) {
1074 	Length = sqrt(DoubleLength);
1075 	if (Length <= NekoSpeed) {
1076 	    NekoMoveDx = (int)LargeX;
1077 	    NekoMoveDy = (int)LargeY;
1078 	} else {
1079 	    NekoMoveDx = (int)((NekoSpeed * LargeX) / Length);
1080 	    NekoMoveDy = (int)((NekoSpeed * LargeY) / Length);
1081 	}
1082     } else {
1083 	NekoMoveDx = NekoMoveDy = 0;
1084     }
1085 }
1086 
1087 
1088 /*
1089  *	$@F0:n2r@OG-IA2h=hM}(J
1090  */
1091 
1092 void
NekoThinkDraw()1093 NekoThinkDraw()
1094 {
1095     CalcDxDy();
1096 
1097     if (NekoState != NEKO_SLEEP) {
1098 	DrawNeko(NekoX, NekoY,
1099 		AnimationPattern[NekoState][NekoTickCount & 0x1]);
1100     } else {
1101 	DrawNeko(NekoX, NekoY,
1102 		AnimationPattern[NekoState][(NekoTickCount >> 2) & 0x1]);
1103     }
1104 
1105     TickCount();
1106 
1107     switch (NekoState) {
1108     case NEKO_STOP:
1109 	if (IsNekoMoveStart()) {
1110 	    SetNekoState(NEKO_AWAKE);
1111 	    break;
1112 	}
1113 	if (NekoStateCount < NEKO_STOP_TIME) {
1114 	    break;
1115 	}
1116 	if (NekoMoveDx < 0 && NekoX <= 0) {
1117 	    SetNekoState(NEKO_L_TOGI);
1118 	} else if (NekoMoveDx > 0 && NekoX >= WindowWidth - BITMAP_WIDTH) {
1119 	    SetNekoState(NEKO_R_TOGI);
1120 	} else if ((NekoMoveDy < 0 && NekoY <= 0)
1121 		   || (ToFocus && theTarget != None && NekoY > MouseY)){
1122 	    SetNekoState(NEKO_U_TOGI);
1123 	} else if ((NekoMoveDy > 0 && NekoY >= WindowHeight - BITMAP_HEIGHT)
1124 		   || (ToFocus && theTarget != None
1125 		       &&  NekoY < MouseY - BITMAP_HEIGHT)){
1126 	    SetNekoState(NEKO_D_TOGI);
1127 	} else {
1128 	    SetNekoState(NEKO_JARE);
1129 	}
1130 	break;
1131     case NEKO_JARE:
1132 	if (IsNekoMoveStart()) {
1133 	    SetNekoState(NEKO_AWAKE);
1134 	    break;
1135 	}
1136 	if (NekoStateCount < NEKO_JARE_TIME) {
1137 	    break;
1138 	}
1139 	SetNekoState(NEKO_KAKI);
1140 	break;
1141     case NEKO_KAKI:
1142 	if (IsNekoMoveStart()) {
1143 	    SetNekoState(NEKO_AWAKE);
1144 	    break;
1145 	}
1146 	if (NekoStateCount < NEKO_KAKI_TIME) {
1147 	    break;
1148 	}
1149 	SetNekoState(NEKO_AKUBI);
1150 	break;
1151     case NEKO_AKUBI:
1152 	if (IsNekoMoveStart()) {
1153 	    SetNekoState(NEKO_AWAKE);
1154 	    break;
1155 	}
1156 	if (NekoStateCount < NEKO_AKUBI_TIME) {
1157 	    break;
1158 	}
1159 	SetNekoState(NEKO_SLEEP);
1160 	break;
1161     case NEKO_SLEEP:
1162 	if (IsNekoMoveStart()) {
1163 	    SetNekoState(NEKO_AWAKE);
1164 	    break;
1165 	}
1166 	break;
1167     case NEKO_AWAKE:
1168 	if (NekoStateCount < NEKO_AWAKE_TIME) {
1169 	    break;
1170 	}
1171 	NekoDirection();	/* $@G-$,F0$/8~$-$r5a$a$k(J */
1172 	break;
1173     case NEKO_U_MOVE:
1174     case NEKO_D_MOVE:
1175     case NEKO_L_MOVE:
1176     case NEKO_R_MOVE:
1177     case NEKO_UL_MOVE:
1178     case NEKO_UR_MOVE:
1179     case NEKO_DL_MOVE:
1180     case NEKO_DR_MOVE:
1181 	NekoX += NekoMoveDx;
1182 	NekoY += NekoMoveDy;
1183 	NekoDirection();
1184 	if (IsWindowOver()) {
1185 	    if (IsNekoDontMove()) {
1186 		SetNekoState(NEKO_STOP);
1187 	    }
1188 	}
1189 	break;
1190     case NEKO_U_TOGI:
1191     case NEKO_D_TOGI:
1192     case NEKO_L_TOGI:
1193     case NEKO_R_TOGI:
1194 	if (IsNekoMoveStart()) {
1195 	    SetNekoState(NEKO_AWAKE);
1196 	    break;
1197 	}
1198 	if (NekoStateCount < NEKO_TOGI_TIME) {
1199 	    break;
1200 	}
1201 	SetNekoState(NEKO_KAKI);
1202 	break;
1203     default:
1204 	/* Internal Error */
1205 	SetNekoState(NEKO_STOP);
1206 	break;
1207     }
1208 
1209     Interval();
1210 }
1211 
1212 
1213 /*
1214  *	$@%-!<%$%Y%s%H=hM}(J
1215  */
1216 
1217 Bool
ProcessKeyPress(theKeyEvent)1218 ProcessKeyPress(theKeyEvent)
1219     XKeyEvent	*theKeyEvent;
1220 {
1221   int			Length;
1222   int			theKeyBufferMaxLen = AVAIL_KEYBUF;
1223   char		theKeyBuffer[AVAIL_KEYBUF + 1];
1224   KeySym		theKeySym;
1225   XComposeStatus	theComposeStatus;
1226   Bool		ReturnState;
1227 
1228   ReturnState = True;
1229 
1230   Length = XLookupString(theKeyEvent,
1231 			 theKeyBuffer, theKeyBufferMaxLen,
1232 			 &theKeySym, &theComposeStatus);
1233 
1234   if (Length > 0) {
1235     switch (theKeyBuffer[0]) {
1236     case 'q':
1237     case 'Q':
1238       if (theKeyEvent->state & Mod1Mask) { /* META (Alt) $@%-!<(J */
1239 	ReturnState = False;
1240       }
1241       break;
1242     default:
1243       break;
1244     }
1245   }
1246 
1247   return(ReturnState);
1248 }
1249 
1250 
1251 /*
1252  *	$@%$%Y%s%H=hM}(J
1253  */
1254 
1255 Bool
ProcessEvent()1256 ProcessEvent()
1257 {
1258     XEvent	theEvent;
1259     Bool	ContinueState = True;
1260 
1261     while (XPending(theDisplay)) {
1262         XNextEvent(theDisplay,&theEvent);
1263 	switch (theEvent.type) {
1264 	case Expose:
1265 	    if (theEvent.xexpose.count == 0) {
1266 		RedrawNeko();
1267 	    }
1268 	    break;
1269 	case KeyPress:
1270 	    ContinueState = ProcessKeyPress(&theEvent);
1271 	    if (!ContinueState) {
1272 		    return(ContinueState);
1273 	    }
1274 	    break;
1275 	case VisibilityNotify:
1276 	    if (RaiseWindowDelay==0) {
1277 	      XRaiseWindow(theDisplay,theWindow);
1278 	      RaiseWindowDelay=DEFAULT_RAISE_WAIT;
1279 	    }
1280 	default:
1281 	    /* Unknown Event */
1282 	    break;
1283 	}
1284     }
1285 
1286     return(ContinueState);
1287 }
1288 
1289 
1290 /*
1291  *	$@G-=hM}(J
1292  */
1293 
1294 void
ProcessNeko()1295 ProcessNeko()
1296 {
1297   struct itimerval	Value;
1298 
1299   /* $@G-$N=i4|2=(J */
1300 
1301   NekoX = (WindowWidth - BITMAP_WIDTH / 2) / 2;
1302   NekoY = (WindowHeight - BITMAP_HEIGHT / 2) / 2;
1303 
1304   NekoLastX = NekoX;
1305   NekoLastY = NekoY;
1306 
1307   SetNekoState(NEKO_STOP);
1308 
1309   /* $@%?%$%^!<@_Dj(J */
1310 
1311   timerclear(&Value.it_interval);
1312   timerclear(&Value.it_value);
1313 
1314   Value.it_interval.tv_usec = IntervalTime;
1315   Value.it_value.tv_usec = IntervalTime;
1316 
1317   setitimer(ITIMER_REAL, &Value, 0);
1318 
1319   /* $@%a%$%s=hM}(J */
1320 
1321   do {
1322     NekoThinkDraw();
1323   } while (ProcessEvent());
1324 }
1325 
1326 
1327 /*
1328  *	SIGALRM $@%7%0%J%k=hM}(J
1329  */
1330 
1331 static void
NullFunction()1332 NullFunction()
1333 {
1334   /* No Operation */
1335 #if defined(SYSV) || defined(SVR4)
1336   signal(SIGALRM, NullFunction);
1337 #endif /* SYSV || SVR4 */
1338 }
1339 
1340 /*
1341  *	$@%(%i!<=hM}(J
1342  */
1343 
1344 int
NekoErrorHandler(dpy,err)1345 NekoErrorHandler(dpy, err)
1346      Display		*dpy;
1347      XErrorEvent	*err;
1348 {
1349   if (err->error_code==BadWindow && (ToWindow || ToFocus)) {
1350   }
1351   else {
1352     char msg[80];
1353     XGetErrorText(dpy, err->error_code, msg, 80);
1354     fprintf(stderr, "%s: Error and exit.\n%s\n", ProgramName, msg);
1355     exit(1);
1356   }
1357 }
1358 
1359 
1360 /*
1361  *	Usage
1362  */
1363 
1364 char	*message[] = {
1365 "",
1366 "Options are:",
1367 "-display <display>	: Neko appears on specified display.",
1368 "-fg <color>		: Foreground color",
1369 "-bg <color>		: Background color",
1370 "-speed <dots>",
1371 "-time <microseconds>",
1372 "-idle <dots>",
1373 "-name <name>		: set window name of neko.",
1374 "-towindow	       	: Neko chases selected window.",
1375 "-toname <name>		: Neko chases specified window.",
1376 "-tofocus      		: Neko runs on top of focus window",
1377 "-rv			: Reverse video. (effects monochrome display only)",
1378 "-position <geometry>   : adjust position relative to mouse pointer.",
1379 "-debug                 : puts you in synchronous mode.",
1380 "-patchlevel            : print out your current patchlevel.",
1381 NULL };
1382 
1383 void
Usage()1384 Usage()
1385 {
1386   char	**mptr;
1387   int loop;
1388 
1389   mptr = message;
1390   fprintf(stderr, "Usage: %s [<options>]\n", ProgramName);
1391   while (*mptr) {
1392     fprintf(stderr,"%s\n", *mptr);
1393     mptr++;
1394   }
1395   for (loop=0;loop<BITMAPTYPES;loop++)
1396     fprintf(stderr,"-%s Use %s bitmaps\n",AnimalDefaultsDataTable[loop].name,AnimalDefaultsDataTable[loop].name);
1397 }
1398 
1399 
1400 /*
1401  *	$@%*%W%7%g%s$NM}2r(J
1402  */
1403 
1404 Bool
GetArguments(argc,argv,theDisplayName)1405 GetArguments(argc, argv, theDisplayName)
1406     int		argc;
1407     char	*argv[];
1408     char	*theDisplayName;
1409 {
1410   int		ArgCounter;
1411   int    result,foo,bar;
1412   extern int XOffset,YOffset;
1413   int loop,found=0;
1414 
1415   theDisplayName[0] = '\0';
1416 
1417   for (ArgCounter = 0; ArgCounter < argc; ArgCounter++) {
1418 
1419     if (strncmp(argv[ArgCounter], "-h", 2) == 0) {
1420       Usage();
1421       exit(0);
1422     }
1423     if (strcmp(argv[ArgCounter], "-display") == 0) {
1424       ArgCounter++;
1425       if (ArgCounter < argc) {
1426 	strcpy(theDisplayName, argv[ArgCounter]);
1427       } else {
1428 	fprintf(stderr, "%s: -display option error.\n", ProgramName);
1429 	exit(1);
1430       }
1431     }
1432     else if (strcmp(argv[ArgCounter], "-speed") == 0) {
1433       ArgCounter++;
1434       if (ArgCounter < argc) {
1435 	NekoSpeed = atof(argv[ArgCounter]);
1436       } else {
1437 	fprintf(stderr, "%s: -speed option error.\n", ProgramName);
1438 	exit(1);
1439       }
1440     }
1441     else if (strcmp(argv[ArgCounter], "-time") == 0) {
1442       ArgCounter++;
1443       if (ArgCounter < argc) {
1444 	IntervalTime = atol(argv[ArgCounter]);
1445       } else {
1446 	fprintf(stderr, "%s: -time option error.\n", ProgramName);
1447 	exit(1);
1448       }
1449     }
1450     else if (strcmp(argv[ArgCounter], "-idle") == 0) {
1451       ArgCounter++;
1452       if (ArgCounter < argc) {
1453 	IdleSpace = atol(argv[ArgCounter]);
1454       } else {
1455 	fprintf(stderr, "%s: -idle option error.\n", ProgramName);
1456 	exit(1);
1457       }
1458     }
1459     else if (strcmp(argv[ArgCounter], "-name") == 0) {
1460       ArgCounter++;
1461       if (ArgCounter < argc) {
1462 	WindowName = argv[ArgCounter];
1463       } else {
1464 	fprintf(stderr, "%s: -name option error.\n", ProgramName);
1465 	exit(1);
1466       }
1467     }
1468     else if (strcmp(argv[ArgCounter], "-towindow") == 0) {
1469       ToWindow = True;
1470       ToFocus = False;
1471     }
1472     else if (strcmp(argv[ArgCounter], "-toname") == 0) {
1473       ArgCounter++;
1474       if (ArgCounter < argc) {
1475 	TargetName = argv[ArgCounter];
1476 	ToWindow = True;
1477 	ToFocus = False;
1478       } else {
1479 	fprintf(stderr, "%s: -toname option error.\n", ProgramName);
1480 	exit(1);
1481       }
1482     }
1483     else if (strcmp(argv[ArgCounter], "-tofocus") == 0) {
1484       ToFocus = True;
1485       ToWindow = False;
1486     }
1487     else if ((strcmp(argv[ArgCounter], "-fg") == 0) ||
1488 	     (strcmp(argv[ArgCounter], "-foreground") == 0)) {
1489       ArgCounter++;
1490       Foreground = argv[ArgCounter];
1491 	     }
1492     else if ((strcmp(argv[ArgCounter], "-bg") == 0) ||
1493 	     (strcmp(argv[ArgCounter], "-background") == 0)) {
1494       ArgCounter++;
1495       Background = argv[ArgCounter];
1496 	     }
1497     else if (strcmp(argv[ArgCounter], "-rv") == 0) {
1498       ReverseVideo = True;
1499     }
1500     else if (strcmp(argv[ArgCounter], "-noshape") == 0) {
1501       NoShape = True;
1502     }
1503     else if (strcmp(argv[ArgCounter], "-position") == 0) {
1504       ArgCounter++;
1505       result=XParseGeometry(argv[ArgCounter],&XOffset,&YOffset,&foo,&bar);
1506     }
1507     else if (strcmp(argv[ArgCounter], "-debug") ==0) {
1508       Synchronous = True;
1509     }
1510     else if (strcmp(argv[ArgCounter], "-patchlevel") == 0) {
1511       fprintf(stderr,"Patchlevel :%s\n",PATCHLEVEL);
1512     }
1513     else {
1514       char *av = argv[ArgCounter] + 1;
1515       if (strcmp(av, "bsd") == 0)
1516 	av = "bsd_daemon";
1517       for (loop=0;loop<BITMAPTYPES;loop++) {
1518 	if (strcmp(av,AnimalDefaultsDataTable[loop].name)==0)
1519 	  {NekoMoyou = loop;found=1;}
1520       }
1521       if (!found) {
1522 	fprintf(stderr,
1523 		"%s: Unknown option \"%s\".\n", ProgramName,
1524 		argv[ArgCounter]);
1525 	Usage();
1526 	exit(1);
1527       }
1528     }
1529   }
1530 
1531   if (strlen(theDisplayName) < 1) {
1532     theDisplayName = NULL;
1533   }
1534 }
1535 
1536 
1537 /*
1538  *	$@%a%$%s4X?t(J
1539  */
1540 
1541 int
main(argc,argv)1542 main(argc, argv)
1543     int		argc;
1544     char	*argv[];
1545 {
1546   char	theDisplayName[MAXDISPLAYNAME];
1547 
1548   ProgramName = argv[0];
1549 
1550   argc--;
1551   argv++;
1552 
1553   GetArguments(argc, argv, theDisplayName);
1554 
1555   XSetErrorHandler(NekoErrorHandler);
1556 
1557   InitScreen(theDisplayName);
1558 
1559   signal(SIGALRM, NullFunction);
1560   signal(SIGINT, RestoreCursor);
1561   signal(SIGTERM, RestoreCursor);
1562   signal(SIGQUIT, RestoreCursor);
1563 
1564   SinPiPer8Times3 = sin(PI_PER8 * (double)3);
1565   SinPiPer8 = sin(PI_PER8);
1566 
1567   ProcessNeko();
1568 
1569   RestoreCursor();
1570 }
1571