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