1 /*--------------------------------------------------------------
11 * Added Color, RootWindow Capability and Quit Ability:
12 * Dan Checkoway, 7-12-94
14 * Converted to use ANSI C and XCB by:
17 *--------------------------------------------------------------*/
21 #include <X11/Xutil.h>
22 #include <X11/keysym.h>
24 #define X_H /* make sure we aren't using symbols from X.h */
26 /*#include <X11/XCB/xcb_image.h>*/
27 #include <xcb/xcb_aux.h> /* xcb_aux_get_screen_t */
28 #include <xcb/xcb_icccm.h>
29 #include <xcb/xcb_atom.h> /* STRING atom */
30 #include <xcb/xcb_keysyms.h>
32 typedef enum { False, True } Bool;
40 #include <unistd.h> /* pause() */
45 #include "bitmaps/icon.xbm"
46 #include "bitmaps/cursor.xbm"
47 #include "bitmaps/cursor_mask.xbm"
49 #include "bitmaps/space.xbm"
51 #include "bitmaps/mati2.xbm"
52 #include "bitmaps/jare2.xbm"
53 #include "bitmaps/kaki1.xbm"
54 #include "bitmaps/kaki2.xbm"
55 #include "bitmaps/mati3.xbm"
56 #include "bitmaps/sleep1.xbm"
57 #include "bitmaps/sleep2.xbm"
59 #include "bitmaps/awake.xbm"
61 #include "bitmaps/up1.xbm"
62 #include "bitmaps/up2.xbm"
63 #include "bitmaps/down1.xbm"
64 #include "bitmaps/down2.xbm"
65 #include "bitmaps/left1.xbm"
66 #include "bitmaps/left2.xbm"
67 #include "bitmaps/right1.xbm"
68 #include "bitmaps/right2.xbm"
69 #include "bitmaps/upright1.xbm"
70 #include "bitmaps/upright2.xbm"
71 #include "bitmaps/upleft1.xbm"
72 #include "bitmaps/upleft2.xbm"
73 #include "bitmaps/dwleft1.xbm"
74 #include "bitmaps/dwleft2.xbm"
75 #include "bitmaps/dwright1.xbm"
76 #include "bitmaps/dwright2.xbm"
78 #include "bitmaps/utogi1.xbm"
79 #include "bitmaps/utogi2.xbm"
80 #include "bitmaps/dtogi1.xbm"
81 #include "bitmaps/dtogi2.xbm"
82 #include "bitmaps/ltogi1.xbm"
83 #include "bitmaps/ltogi2.xbm"
84 #include "bitmaps/rtogi1.xbm"
85 #include "bitmaps/rtogi2.xbm"
87 #define BITMAP_WIDTH 32
88 #define BITMAP_HEIGHT 32
89 #define WINDOW_WIDTH 320
90 #define WINDOW_HEIGHT 256
91 #define DEFAULT_BORDER 2
92 #define DEFAULT_WIN_X 1
93 #define DEFAULT_WIN_Y 1
94 #define AVAIL_KEYBUF 255
96 #define EVENT_MASK ( XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_BUTTON_PRESS | \
97 XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_STRUCTURE_NOTIFY )
99 #define EVENT_MASK_ROOT ( XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_EXPOSURE )
101 #define MAX_TICK 9999 /* Odd Only! */
102 #define INTERVAL 125000L
103 #define NEKO_SPEED 16
105 #define NORMAL_STATE 1
115 #define NEKO_U_MOVE 6
116 #define NEKO_D_MOVE 7
117 #define NEKO_L_MOVE 8
118 #define NEKO_R_MOVE 9
119 #define NEKO_UL_MOVE 10
120 #define NEKO_UR_MOVE 11
121 #define NEKO_DL_MOVE 12
122 #define NEKO_DR_MOVE 13
123 #define NEKO_U_TOGI 14
124 #define NEKO_D_TOGI 15
125 #define NEKO_L_TOGI 16
126 #define NEKO_R_TOGI 17
128 #define NEKO_STOP_TIME 4
129 #define NEKO_JARE_TIME 10
130 #define NEKO_KAKI_TIME 4
131 #define NEKO_AKUBI_TIME 3
132 #define NEKO_AWAKE_TIME 3
133 #define NEKO_TOGI_TIME 10
135 #define PI_PER8 ((double)3.1415926535/(double)8)
137 #define DIRNAMELEN 255
140 char *fgColor, *bgColor;
142 static char *ProgramName;
144 xcb_connection_t *xc;
145 xcb_screen_t *theScreen; /* instead of macro(theDisplay, int theScreen) */
146 unsigned long theFgPixel;
147 unsigned long theBgPixel;
148 xcb_window_t theWindow;
149 xcb_cursor_t theCursor;
150 xcb_key_symbols_t *theKeySyms;
151 xcb_atom_t deleteWindowAtom;
153 static unsigned int WindowWidth;
154 static unsigned int WindowHeight;
155 static int WindowPointX;
156 static int WindowPointY;
158 static unsigned int BorderWidth = DEFAULT_BORDER;
160 long IntervalTime = INTERVAL;
182 xcb_gcontext_t NekoLastGC;
184 double NekoSpeed = (double)NEKO_SPEED;
186 double SinPiPer8Times3;
189 xcb_pixmap_t SpaceXbm;
191 xcb_pixmap_t Mati2Xbm;
192 xcb_pixmap_t Jare2Xbm;
193 xcb_pixmap_t Kaki1Xbm;
194 xcb_pixmap_t Kaki2Xbm;
195 xcb_pixmap_t Mati3Xbm;
196 xcb_pixmap_t Sleep1Xbm;
197 xcb_pixmap_t Sleep2Xbm;
199 xcb_pixmap_t AwakeXbm;
203 xcb_pixmap_t Down1Xbm;
204 xcb_pixmap_t Down2Xbm;
205 xcb_pixmap_t Left1Xbm;
206 xcb_pixmap_t Left2Xbm;
207 xcb_pixmap_t Right1Xbm;
208 xcb_pixmap_t Right2Xbm;
209 xcb_pixmap_t UpLeft1Xbm;
210 xcb_pixmap_t UpLeft2Xbm;
211 xcb_pixmap_t UpRight1Xbm;
212 xcb_pixmap_t UpRight2Xbm;
213 xcb_pixmap_t DownLeft1Xbm;
214 xcb_pixmap_t DownLeft2Xbm;
215 xcb_pixmap_t DownRight1Xbm;
216 xcb_pixmap_t DownRight2Xbm;
218 xcb_pixmap_t UpTogi1Xbm;
219 xcb_pixmap_t UpTogi2Xbm;
220 xcb_pixmap_t DownTogi1Xbm;
221 xcb_pixmap_t DownTogi2Xbm;
222 xcb_pixmap_t LeftTogi1Xbm;
223 xcb_pixmap_t LeftTogi2Xbm;
224 xcb_pixmap_t RightTogi1Xbm;
225 xcb_pixmap_t RightTogi2Xbm;
227 xcb_gcontext_t SpaceGC;
229 xcb_gcontext_t Mati2GC;
230 xcb_gcontext_t Jare2GC;
231 xcb_gcontext_t Kaki1GC;
232 xcb_gcontext_t Kaki2GC;
233 xcb_gcontext_t Mati3GC;
234 xcb_gcontext_t Sleep1GC;
235 xcb_gcontext_t Sleep2GC;
237 xcb_gcontext_t AwakeGC;
239 xcb_gcontext_t Up1GC;
240 xcb_gcontext_t Up2GC;
241 xcb_gcontext_t Down1GC;
242 xcb_gcontext_t Down2GC;
243 xcb_gcontext_t Left1GC;
244 xcb_gcontext_t Left2GC;
245 xcb_gcontext_t Right1GC;
246 xcb_gcontext_t Right2GC;
247 xcb_gcontext_t UpLeft1GC;
248 xcb_gcontext_t UpLeft2GC;
249 xcb_gcontext_t UpRight1GC;
250 xcb_gcontext_t UpRight2GC;
251 xcb_gcontext_t DownLeft1GC;
252 xcb_gcontext_t DownLeft2GC;
253 xcb_gcontext_t DownRight1GC;
254 xcb_gcontext_t DownRight2GC;
256 xcb_gcontext_t UpTogi1GC;
257 xcb_gcontext_t UpTogi2GC;
258 xcb_gcontext_t DownTogi1GC;
259 xcb_gcontext_t DownTogi2GC;
260 xcb_gcontext_t LeftTogi1GC;
261 xcb_gcontext_t LeftTogi2GC;
262 xcb_gcontext_t RightTogi1GC;
263 xcb_gcontext_t RightTogi2GC;
266 xcb_gcontext_t *GCCreatePtr;
267 xcb_pixmap_t *BitmapCreatePtr;
269 unsigned int PixelWidth;
270 unsigned int PixelHeight;
273 BitmapGCData BitmapGCDataTable[] = {
274 { &SpaceGC, &SpaceXbm, space_bits, space_width, space_height },
275 { &Mati2GC, &Mati2Xbm, mati2_bits, mati2_width, mati2_height },
276 { &Jare2GC, &Jare2Xbm, jare2_bits, jare2_width, jare2_height },
277 { &Kaki1GC, &Kaki1Xbm, kaki1_bits, kaki1_width, kaki1_height },
278 { &Kaki2GC, &Kaki2Xbm, kaki2_bits, kaki2_width, kaki2_height },
279 { &Mati3GC, &Mati3Xbm, mati3_bits, mati3_width, mati3_height },
280 { &Sleep1GC, &Sleep1Xbm, sleep1_bits, sleep1_width, sleep1_height },
281 { &Sleep2GC, &Sleep2Xbm, sleep2_bits, sleep2_width, sleep2_height },
282 { &AwakeGC, &AwakeXbm, awake_bits, awake_width, awake_height },
283 { &Up1GC, &Up1Xbm, up1_bits, up1_width, up1_height },
284 { &Up2GC, &Up2Xbm, up2_bits, up2_width, up2_height },
285 { &Down1GC, &Down1Xbm, down1_bits, down1_width, down1_height },
286 { &Down2GC, &Down2Xbm, down2_bits, down2_width, down2_height },
287 { &Left1GC, &Left1Xbm, left1_bits, left1_width, left1_height },
288 { &Left2GC, &Left2Xbm, left2_bits, left2_width, left2_height },
289 { &Right1GC, &Right1Xbm, right1_bits, right1_width, right1_height },
290 { &Right2GC, &Right2Xbm, right2_bits, right2_width, right2_height },
291 { &UpLeft1GC, &UpLeft1Xbm, upleft1_bits, upleft1_width, upleft1_height },
292 { &UpLeft2GC, &UpLeft2Xbm, upleft2_bits, upleft2_width, upleft2_height },
294 &UpRight1Xbm, upright1_bits, upright1_width, upright1_height },
296 &UpRight2Xbm, upright2_bits, upright2_width, upright2_height },
297 { &DownLeft1GC, &DownLeft1Xbm, dwleft1_bits, dwleft1_width, dwleft1_height },
298 { &DownLeft2GC, &DownLeft2Xbm, dwleft2_bits, dwleft2_width, dwleft2_height },
300 &DownRight1Xbm, dwright1_bits, dwright1_width, dwright1_height },
302 &DownRight2Xbm, dwright2_bits, dwright2_width, dwright2_height },
303 { &UpTogi1GC, &UpTogi1Xbm, utogi1_bits, utogi1_width, utogi1_height },
304 { &UpTogi2GC, &UpTogi2Xbm, utogi2_bits, utogi2_width, utogi2_height },
305 { &DownTogi1GC, &DownTogi1Xbm, dtogi1_bits, dtogi1_width, dtogi1_height },
306 { &DownTogi2GC, &DownTogi2Xbm, dtogi2_bits, dtogi2_width, dtogi2_height },
307 { &LeftTogi1GC, &LeftTogi1Xbm, ltogi1_bits, ltogi1_width, ltogi1_height },
308 { &LeftTogi2GC, &LeftTogi2Xbm, ltogi2_bits, ltogi2_width, ltogi2_height },
310 &RightTogi1Xbm, rtogi1_bits, rtogi1_width, rtogi1_height },
312 &RightTogi2Xbm, rtogi2_bits, rtogi2_width, rtogi2_height },
313 { NULL, NULL, NULL, 0, 0 }
317 xcb_gcontext_t *TickEvenGCPtr;
318 xcb_gcontext_t *TickOddGCPtr;
321 Animation AnimationPattern[] = {
322 { &Mati2GC, &Mati2GC }, /* NekoState == NEKO_STOP */
323 { &Jare2GC, &Mati2GC }, /* NekoState == NEKO_JARE */
324 { &Kaki1GC, &Kaki2GC }, /* NekoState == NEKO_KAKI */
325 { &Mati3GC, &Mati3GC }, /* NekoState == NEKO_AKUBI */
326 { &Sleep1GC, &Sleep2GC }, /* NekoState == NEKO_SLEEP */
327 { &AwakeGC, &AwakeGC }, /* NekoState == NEKO_AWAKE */
328 { &Up1GC, &Up2GC } , /* NekoState == NEKO_U_MOVE */
329 { &Down1GC, &Down2GC }, /* NekoState == NEKO_D_MOVE */
330 { &Left1GC, &Left2GC }, /* NekoState == NEKO_L_MOVE */
331 { &Right1GC, &Right2GC }, /* NekoState == NEKO_R_MOVE */
332 { &UpLeft1GC, &UpLeft2GC }, /* NekoState == NEKO_UL_MOVE */
333 { &UpRight1GC, &UpRight2GC }, /* NekoState == NEKO_UR_MOVE */
334 { &DownLeft1GC, &DownLeft2GC }, /* NekoState == NEKO_DL_MOVE */
335 { &DownRight1GC, &DownRight2GC }, /* NekoState == NEKO_DR_MOVE */
336 { &UpTogi1GC, &UpTogi2GC }, /* NekoState == NEKO_U_TOGI */
337 { &DownTogi1GC, &DownTogi2GC }, /* NekoState == NEKO_D_TOGI */
338 { &LeftTogi1GC, &LeftTogi2GC }, /* NekoState == NEKO_L_TOGI */
339 { &RightTogi1GC, &RightTogi2GC }, /* NekoState == NEKO_R_TOGI */
343 /* PutImage.c: format/unit/order conversion should move out to a library */
344 static unsigned char const _reverse_byte[0x100] = {
345 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
346 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
347 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
348 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
349 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
350 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
351 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
352 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
353 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
354 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
355 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
356 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
357 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
358 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
359 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
360 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
361 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
362 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
363 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
364 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
365 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
366 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
367 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
368 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
369 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
370 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
371 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
372 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
373 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
374 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
375 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
376 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
379 /* convert 1Ll <--> 4Mm */
382 register unsigned char *src,
383 register unsigned char *dest,
384 long srclen, long srcinc, long destinc,
388 register const unsigned char *rev = _reverse_byte;
392 for (h = height; --h >= 0; src += srcinc, dest += destinc)
393 for (n = srclen; --n >= 0; )
394 *dest++ = rev[*src++];
397 /* assumes pad is a power of 2 */
398 #define ROUNDUP(nbytes, pad) (((nbytes) + ((pad) - 1)) & ~(long)((pad) - 1))
400 /* CrPFBData.c and CrBFData.c (very similar) */
401 /* if depth==1, behaves like CreateBitmapFromData */
402 xcb_pixmap_t CreatePixmapFromBitmapData( xcb_connection_t *c,
403 xcb_window_t window, char *data, uint16_t w, uint16_t h,
404 uint32_t fg, uint32_t bg, uint32_t depth)
406 xcb_drawable_t drawable;
407 xcb_pixmap_t bitmap = xcb_pixmap_new( c );
409 drawable.window = window;
410 xcb_create_pixmap( c, depth, bitmap, drawable, w, h );
412 xcb_gcontext_t gc = xcb_gcontext_new( c );
414 uint32_t mask = (depth==1 ? 0 : XCB_GC_FOREGROUND | XCB_GC_BACKGROUND);
415 uint32_t values[] = { fg, bg };
417 drawable.pixmap = bitmap;
418 xcb_create_gc( c, gc, drawable, mask, values );
420 /* XImage attributes: bpp=1, xoffset=0,
421 byte_order=bit_order=LSB, unit=8, pad=8, bpl=(w+7/8) */
423 /* must swap and pad the data if bit/byte_order isn't LSB (Mac) */
425 /* Mac X Server: byte_order=bit_order=MSB, unit=32, padding=32 */
427 long pad = xcb_get_setup(c)->bitmap_format_scanline_pad;
428 long bpd = ROUNDUP(w, pad)>>3;
429 long bufLen = bpd * h;
431 if (xcb_get_setup(c)->bitmap_format_scanline_unit == 32 &&
432 xcb_get_setup(c)->bitmap_format_bit_order == XCB_IMAGE_ORDER_MSB_FIRST &&
433 xcb_get_setup(c)->image_byte_order == XCB_IMAGE_ORDER_MSB_FIRST)
435 SwapBits((unsigned char *)data, buf, bpl, bpl, bpd, h);
440 uint8_t *src = (uint8_t *)data, *dest = buf;
441 for (i=0; i<h; i++, dest += bpd, src += bpl)
442 memcpy(dest, src, bpl);
445 memcpy(buf, data, bufLen);
447 /* note: CBfD uses XYPixmap, but CPfBD uses XYBitmap
448 there shouldn't be a difference when depth==1,
449 but the neko images are corrupt if using XYPixmap */
450 uint8_t format = (depth==1 ? XCB_IMAGE_FORMAT_XY_PIXMAP : XCB_IMAGE_FORMAT_XY_BITMAP);
452 /* PutImage.c: left_pad = (image->xoffset + req->xoffset) & (dpy->bitmap_unit-1)
453 screen->bitmap_format_scanline_unit
454 left_pad = (0 + 0) & (32 - 1) = 0 */
456 xcb_put_image( c, format, drawable, gc,
458 0, 1, /* left_pad, depth */
462 xcb_generic_error_t *error = NULL;
463 xcb_sync( c, &error );
465 printf("error code %d", (int)error->error_code);
470 xcb_free_gc( c, gc );
472 /* later: xcb_free_pixmap( c, bitmap ); */
476 xcb_pixmap_t CreateBitmapFromData(xcb_connection_t *c, xcb_window_t window,
477 char *data, uint16_t w, uint16_t h)
480 return CreatePixmapFromBitmapData(c, window, data, w, h, 0, 0, depth);
483 void InitBitmapAndGCs(void) {
484 BitmapGCData *BitmapGCDataTablePtr;
485 uint32_t theGCValues[5];
486 xcb_drawable_t drawable; drawable.window = theWindow;
488 theGCValues[0] = XCB_GX_COPY;
490 theGCValues[1] = theFgPixel;
491 theGCValues[2] = theBgPixel;
493 theGCValues[3] = XCB_FILL_STYLE_TILED;
495 /* TODO: latency: make all the bitmaps, then all the contexts? */
497 for ( BitmapGCDataTablePtr = BitmapGCDataTable;
498 BitmapGCDataTablePtr->GCCreatePtr != NULL;
499 BitmapGCDataTablePtr++ ) {
501 *(BitmapGCDataTablePtr->BitmapCreatePtr)
502 = CreatePixmapFromBitmapData( xc, theScreen->root,
503 BitmapGCDataTablePtr->PixelPattern,
504 BitmapGCDataTablePtr->PixelWidth,
505 BitmapGCDataTablePtr->PixelHeight,
506 theFgPixel, theBgPixel, theScreen->root_depth);
508 theGCValues[4] = BitmapGCDataTablePtr->BitmapCreatePtr->xid; /* tile */
510 *(BitmapGCDataTablePtr->GCCreatePtr) = xcb_gcontext_new( xc );
511 xcb_create_gc( xc, *(BitmapGCDataTablePtr->GCCreatePtr), drawable,
512 XCB_GC_FUNCTION | XCB_GC_FOREGROUND | XCB_GC_BACKGROUND |
513 XCB_GC_FILL_STYLE | XCB_GC_TILE,
517 /* later: xcb_free_pixmap( c, bitmap ); */
518 /* later: xcb_free_gc( c, gc ); */
522 GetAtom(xcb_connection_t *c, const char *atomName)
524 xcb_atom_t atom = { XCB_NONE };
525 xcb_intern_atom_reply_t *r = xcb_intern_atom_reply(c,
526 xcb_intern_atom(c, 0, strlen(atomName), atomName), NULL);
535 InitScreen( char *DisplayName, char *theGeometry, char *theTitle, Bool iconicState )
537 xcb_pixmap_t theCursorSource;
538 xcb_pixmap_t theCursorMask;
539 unsigned int theDepth;
540 xcb_colormap_t theColormap;
543 if ( ( xc = xcb_connect( DisplayName, &screen ) ) == NULL ) {
544 fprintf( stderr, "%s: Can't open connection", ProgramName );
545 if ( DisplayName != NULL )
546 fprintf( stderr, " %s.\n", DisplayName );
548 fprintf( stderr, ".\n" );
552 theScreen = xcb_aux_get_screen(xc, screen);
553 if (theScreen == NULL) {
554 fprintf( stderr, "%s: Can't get default screen", ProgramName );
558 theDepth = theScreen->root_depth; /* DefaultDepth */
559 theColormap = theScreen->default_colormap;
561 WindowPointX = DEFAULT_WIN_X;
562 WindowPointY = DEFAULT_WIN_Y;
563 WindowWidth = WINDOW_WIDTH;
564 WindowHeight = WINDOW_HEIGHT;
568 GeometryStatus = XParseGeometry( theGeometry,
569 &WindowPointX, &WindowPointY,
570 &WindowWidth, &WindowHeight );
573 theCursorSource = CreateBitmapFromData( xc,
579 theCursorMask = CreateBitmapFromData( xc,
583 cursor_mask_height );
586 if ( bgColor == NULL) bgColor = "white";
587 if ( fgColor == NULL) fgColor = "black";
589 xcb_alloc_named_color_cookie_t bgCookie = xcb_alloc_named_color ( xc,
590 theColormap, strlen(bgColor), bgColor );
592 xcb_alloc_named_color_cookie_t fgCookie = xcb_alloc_named_color ( xc,
593 theColormap, strlen(fgColor), fgColor );
595 /* mouse cursor is always black and white */
596 xcb_alloc_named_color_cookie_t blackCookie = xcb_alloc_named_color ( xc,
597 theColormap, strlen("black"), "black" );
598 xcb_alloc_named_color_cookie_t whiteCookie = xcb_alloc_named_color ( xc,
599 theColormap, strlen("white"), "white" );
601 xcb_alloc_named_color_reply_t *bgRep = xcb_alloc_named_color_reply( xc, bgCookie, 0 );
604 "%s: Can't allocate the background color %s.\n", ProgramName, bgColor );
607 theBgPixel = bgRep->pixel;
609 xcb_alloc_named_color_reply_t *fgRep = xcb_alloc_named_color_reply( xc, fgCookie, 0 );
612 "%s: Can't allocate the foreground color %s.\n", ProgramName, fgColor );
615 theFgPixel = fgRep->pixel;
617 xcb_alloc_named_color_reply_t *blackRep = xcb_alloc_named_color_reply( xc, blackCookie, 0 );
620 "%s: Can't allocate the black color.\n", ProgramName );
623 xcb_alloc_named_color_reply_t *whiteRep = xcb_alloc_named_color_reply( xc, whiteCookie, 0 );
626 "%s: Can't allocate the white color.\n", ProgramName );
630 theCursor = xcb_cursor_new( xc );
631 xcb_create_cursor ( xc, theCursor, theCursorSource, theCursorMask,
632 blackRep->visual_red, blackRep->visual_green, blackRep->visual_blue,
633 whiteRep->visual_red, whiteRep->visual_green, whiteRep->visual_blue,
634 cursor_x_hot, cursor_y_hot );
642 uint32_t rootAttributes[] = { theBgPixel, EVENT_MASK_ROOT, theCursor.xid };
643 theWindow = theScreen->root;
644 xcb_change_window_attributes(xc, theWindow,
645 XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK | XCB_CW_CURSOR, rootAttributes );
647 /* XClearWindow: clear area with all dimensions 0 */
648 xcb_clear_area( xc, False, theWindow, 0, 0, 0, 0 );
650 xcb_drawable_t d = { theWindow };
651 xcb_get_geometry_reply_t *geometry = xcb_get_geometry_reply( xc,
652 xcb_get_geometry( xc, d ), NULL);
654 /* only width & height are used by the program */
655 WindowWidth = geometry->width;
656 WindowHeight = geometry->height;
660 /* TODO: grab key Alt-Q to quit gracefully? */
663 xcb_pixmap_t theIconPixmap;
665 uint32_t theWindowAttributes[] = {
666 theBgPixel, /* background */
667 theFgPixel, /* border */
668 False, /* override_redirect */
672 unsigned long theWindowMask = XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL |
673 XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK | XCB_CW_CURSOR;
675 theWindow = xcb_window_new( xc );
676 xcb_create_window( xc,
680 WindowPointX, WindowPointY,
681 WindowWidth, WindowHeight,
683 XCB_WINDOW_CLASS_INPUT_OUTPUT,
684 theScreen->root_visual, /* CopyFromParent */
685 theWindowMask, theWindowAttributes );
687 /* new: obey the window-delete protocol, look for XCB_CLIENT_MESSAGE */
688 deleteWindowAtom = GetAtom(xc, "WM_DELETE_WINDOW");
689 SetWMProtocols( xc, theWindow, 1, &deleteWindowAtom );
691 theIconPixmap = CreateBitmapFromData( xc, theWindow,
692 icon_bits, icon_width, icon_height );
694 WMHints *theWMHints = AllocWMHints();
696 WMHintsSetIconPixmap( theWMHints, theIconPixmap );
699 WMHintsSetIconic( theWMHints );
701 WMHintsSetNormal( theWMHints );
703 SetWMHints( xc, theWindow, theWMHints);
707 /* why hide the structure? */
708 SizeHints *theSizeHints = AllocSizeHints();
710 /* need enum for second param (user specified) */
711 SizeHintsSetPosition(theSizeHints, 0, WindowPointX, WindowPointY);
712 SizeHintsSetSize(theSizeHints, 0, WindowWidth, WindowHeight);
714 SetWMNormalHints(xc, theWindow, theSizeHints);
716 FreeSizeHints(theSizeHints);
718 /* Um, why do I have to specify the encoding in this API? */
719 SetWMName( xc, theWindow, STRING, strlen(theTitle), theTitle );
720 SetWMIconName( xc, theWindow, STRING, strlen(theTitle), theTitle );
722 xcb_map_window( xc, theWindow );
730 /* latency: ask for keysyms now, and receive them later */
731 theKeySyms = xcb_key_symbols_alloc( xc );
733 /* later: xcb_key_symbols_free( keysyms ); */
734 /* later: xcb_refresh_keyboard_mapping ( keysyms, mappingEvent ); */
738 void Interval(void) {
743 void TickCount(void) {
744 if ( ++NekoTickCount >= MAX_TICK )
747 if ( NekoTickCount % 2 == 0 )
748 if ( NekoStateCount < MAX_TICK )
754 SetNekoState( int SetValue )
759 NekoState = SetValue;
762 switch ( NekoState ) {
772 NekoMoveDx = NekoMoveDy = 0;
781 /* Xlib does merging of requests, but the Flush and frequent DrawGC changes
782 defeat this mechanism */
785 DrawNeko( int x, int y, xcb_gcontext_t DrawGC )
787 xcb_drawable_t drawable; drawable.window = theWindow;
788 xcb_rectangle_t rect = { NekoLastX, NekoLastY, BITMAP_WIDTH, BITMAP_HEIGHT };
790 if ( (x != NekoLastX || y != NekoLastY) && (EventState != DEBUG_LIST) )
792 xcb_poly_fill_rectangle( xc, drawable, SpaceGC, 1, &rect );
793 rect.x = x; rect.y = y;
797 uint32_t originMask = XCB_GC_TILE_STIPPLE_ORIGIN_X | XCB_GC_TILE_STIPPLE_ORIGIN_Y;
798 uint32_t origin[2] = { x, y };
799 xcb_change_gc( xc, DrawGC, originMask, origin );
800 /* XSetTSOrigin( theDisplay, DrawGC, x, y ); */
802 xcb_poly_fill_rectangle( xc, drawable, DrawGC, 1, &rect );
813 void RedrawNeko(void) {
814 xcb_drawable_t drawable; drawable.window = theWindow;
815 xcb_rectangle_t rect = { NekoLastX, NekoLastY, BITMAP_WIDTH, BITMAP_HEIGHT };
817 xcb_poly_fill_rectangle( xc, drawable, NekoLastGC, 1, &rect );
824 void NekoDirection(void) {
826 double LargeX, LargeY;
830 if ( NekoMoveDx == 0 && NekoMoveDy == 0 ) {
831 NewState = NEKO_STOP;
833 LargeX = (double)NekoMoveDx;
834 LargeY = (double)(-NekoMoveDy);
835 Length = sqrt( LargeX * LargeX + LargeY * LargeY );
836 SinTheta = LargeY / Length;
838 if ( NekoMoveDx > 0 ) {
839 if ( SinTheta > SinPiPer8Times3 ) {
840 NewState = NEKO_U_MOVE;
841 } else if ( ( SinTheta <= SinPiPer8Times3 )
842 && ( SinTheta > SinPiPer8 ) ) {
843 NewState = NEKO_UR_MOVE;
844 } else if ( ( SinTheta <= SinPiPer8 )
845 && ( SinTheta > -( SinPiPer8 ) ) ) {
846 NewState = NEKO_R_MOVE;
847 } else if ( ( SinTheta <= -( SinPiPer8 ) )
848 && ( SinTheta > -( SinPiPer8Times3 ) ) ) {
849 NewState = NEKO_DR_MOVE;
851 NewState = NEKO_D_MOVE;
854 if ( SinTheta > SinPiPer8Times3 ) {
855 NewState = NEKO_U_MOVE;
856 } else if ( ( SinTheta <= SinPiPer8Times3 )
857 && ( SinTheta > SinPiPer8 ) ) {
858 NewState = NEKO_UL_MOVE;
859 } else if ( ( SinTheta <= SinPiPer8 )
860 && ( SinTheta > -( SinPiPer8 ) ) ) {
861 NewState = NEKO_L_MOVE;
862 } else if ( ( SinTheta <= -( SinPiPer8 ) )
863 && ( SinTheta > -( SinPiPer8Times3 ) ) ) {
864 NewState = NEKO_DL_MOVE;
866 NewState = NEKO_D_MOVE;
871 if ( NekoState != NewState ) {
872 SetNekoState( NewState );
877 Bool IsWindowOver(void) {
878 Bool ReturnValue = False;
883 } else if ( NekoY >= WindowHeight - BITMAP_HEIGHT ) {
884 NekoY = WindowHeight - BITMAP_HEIGHT;
890 } else if ( NekoX >= WindowWidth - BITMAP_WIDTH ) {
891 NekoX = WindowWidth - BITMAP_WIDTH;
895 return( ReturnValue );
899 Bool IsNekoDontMove(void) {
900 return( NekoX == NekoLastX && NekoY == NekoLastY );
904 Bool IsNekoMoveStart(void) {
906 if ( (PrevMouseX >= MouseX - IDLE_SPACE
907 && PrevMouseX <= MouseX + IDLE_SPACE) &&
908 (PrevMouseY >= MouseY - IDLE_SPACE
909 && PrevMouseY <= MouseY + IDLE_SPACE) )
914 if ( NekoMoveDx == 0 && NekoMoveDy == 0 )
922 void CalcDxDy(void) {
923 int RelativeX, RelativeY;
924 double LargeX, LargeY;
925 double DoubleLength, Length;
927 /* TODO: replace query with pointer motion notification? */
929 xcb_query_pointer_reply_t *reply = xcb_query_pointer_reply( xc,
930 xcb_query_pointer( xc, theWindow ), NULL);
932 RelativeX = reply->win_x;
933 RelativeY = reply->win_y;
943 LargeX = (double)( MouseX - NekoX - BITMAP_WIDTH / 2 );
944 LargeY = (double)( MouseY - NekoY - BITMAP_HEIGHT );
946 DoubleLength = LargeX * LargeX + LargeY * LargeY;
948 if ( DoubleLength != (double)0 ) {
949 Length = sqrt( DoubleLength );
950 if ( Length <= NekoSpeed ) {
951 NekoMoveDx = (int)LargeX;
952 NekoMoveDy = (int)LargeY;
954 NekoMoveDx = (int)( ( NekoSpeed * LargeX ) / Length );
955 NekoMoveDy = (int)( ( NekoSpeed * LargeY ) / Length );
958 NekoMoveDx = NekoMoveDy = 0;
963 void NekoThinkDraw(void) {
968 if ( NekoState != NEKO_SLEEP ) {
969 DrawNeko( NekoX, NekoY,
970 NekoTickCount % 2 == 0 ?
971 *(AnimationPattern[ NekoState ].TickEvenGCPtr) :
972 *(AnimationPattern[ NekoState ].TickOddGCPtr) );
974 DrawNeko( NekoX, NekoY,
975 NekoTickCount % 8 <= 3 ?
976 *(AnimationPattern[ NekoState ].TickEvenGCPtr) :
977 *(AnimationPattern[ NekoState ].TickOddGCPtr) );
982 switch ( NekoState ) {
984 if ( IsNekoMoveStart() ) {
985 SetNekoState( NEKO_AWAKE );
988 if ( NekoStateCount < NEKO_STOP_TIME ) {
991 if ( NekoMoveDx < 0 && NekoX <= 0 ) {
992 SetNekoState( NEKO_L_TOGI );
993 } else if ( NekoMoveDx > 0 && NekoX >= WindowWidth - BITMAP_WIDTH ) {
994 SetNekoState( NEKO_R_TOGI );
995 } else if ( NekoMoveDy < 0 && NekoY <= 0 ) {
996 SetNekoState( NEKO_U_TOGI );
997 } else if ( NekoMoveDy > 0 && NekoY >= WindowHeight - BITMAP_HEIGHT ) {
998 SetNekoState( NEKO_D_TOGI );
1000 SetNekoState( NEKO_JARE );
1004 if ( IsNekoMoveStart() ) {
1005 SetNekoState( NEKO_AWAKE );
1008 if ( NekoStateCount < NEKO_JARE_TIME ) {
1011 SetNekoState( NEKO_KAKI );
1014 if ( IsNekoMoveStart() ) {
1015 SetNekoState( NEKO_AWAKE );
1018 if ( NekoStateCount < NEKO_KAKI_TIME ) {
1021 SetNekoState( NEKO_AKUBI );
1024 if ( IsNekoMoveStart() ) {
1025 SetNekoState( NEKO_AWAKE );
1028 if ( NekoStateCount < NEKO_AKUBI_TIME ) {
1031 SetNekoState( NEKO_SLEEP );
1034 if ( IsNekoMoveStart() ) {
1035 SetNekoState( NEKO_AWAKE );
1040 if ( NekoStateCount < NEKO_AWAKE_TIME ) {
1053 NekoX += NekoMoveDx;
1054 NekoY += NekoMoveDy;
1056 if ( IsWindowOver() ) {
1057 if ( IsNekoDontMove() ) {
1058 SetNekoState( NEKO_STOP );
1066 if ( IsNekoMoveStart() ) {
1067 SetNekoState( NEKO_AWAKE );
1070 if ( NekoStateCount < NEKO_TOGI_TIME ) {
1073 SetNekoState( NEKO_KAKI );
1076 /* Internal Error */
1077 SetNekoState( NEKO_STOP );
1086 void DisplayCharacters() {
1090 for ( Index = 0, x = 0, y = 0;
1091 BitmapGCDataTable[ Index ].GCCreatePtr != NULL; Index++ ) {
1093 DrawNeko( x, y, *(BitmapGCDataTable[ Index ].GCCreatePtr) );
1094 XFlush( theDisplay );
1098 if ( x > WindowWidth - BITMAP_WIDTH ) {
1101 if ( y > WindowHeight - BITMAP_HEIGHT) {
1111 ProcessKeyPress( xcb_key_press_event_t *theKeyEvent )
1113 Bool ReturnState = True;
1115 /* quit on Meta-Q (Alt-Q) */
1116 xcb_keysym_t theKeySym;
1118 /* last param is "int col". What? add enumeration to xcb_keysyms.h */
1119 theKeySym = xcb_key_press_lookup_keysym( theKeySyms, theKeyEvent, 1 );
1121 /* KeySym XK_Q == 'Q' */
1122 if (theKeySym.id == 'Q' && (theKeyEvent->state & XCB_MOD_MASK_1))
1123 ReturnState = False;
1126 if ( EventState == DEBUG_MOVE ) {
1127 switch ( theKeySym ) {
1129 NekoMoveDx = -(int)( NekoSpeed / sqrt( (double)2 ) );
1130 NekoMoveDy = -NekoMoveDx;
1134 NekoMoveDy = (int)NekoSpeed;
1137 NekoMoveDx = (int)( NekoSpeed / sqrt( (double)2 ) );
1138 NekoMoveDy = NekoMoveDx;
1141 NekoMoveDx = -(int)NekoSpeed;
1149 NekoMoveDx = (int)NekoSpeed;
1153 NekoMoveDx = -(int)( NekoSpeed / sqrt( (double)2 ) );
1154 NekoMoveDy = NekoMoveDx;
1158 NekoMoveDy = -(int)NekoSpeed;
1161 NekoMoveDx = (int)( NekoSpeed / sqrt( (double)2 ) );
1162 NekoMoveDy = -NekoMoveDx;
1168 return( ReturnState );
1172 void NekoAdjust(void) {
1175 else if ( NekoX > WindowWidth - BITMAP_WIDTH )
1176 NekoX = WindowWidth - BITMAP_WIDTH;
1180 else if ( NekoY > WindowHeight - BITMAP_HEIGHT )
1181 NekoY = WindowHeight - BITMAP_HEIGHT;
1184 int IsDeleteMessage(xcb_client_message_event_t *msg)
1186 return msg->data.data32[0] == deleteWindowAtom.xid;
1189 Bool ProcessEvent(void) {
1190 xcb_generic_event_t *theEvent;
1191 xcb_configure_notify_event_t *theConfigureNotification;
1192 xcb_expose_event_t *theExposure;
1193 xcb_button_press_event_t *theButtonPress;
1194 Bool ContinueState = True;
1197 switch ( EventState ) {
1199 while ( ContinueState &&
1200 NULL != (theEvent = xcb_poll_for_event( xc, &error )) ) { /*while ( XCheckMaskEvent( theDisplay, EVENT_MASK, &theEvent ) ) {*/
1201 switch ( theEvent->response_type & 0x7f ) {
1202 case XCB_CONFIGURE_NOTIFY:
1203 theConfigureNotification = (xcb_configure_notify_event_t *)theEvent;
1204 WindowWidth = theConfigureNotification->width;
1205 WindowHeight = theConfigureNotification->height;
1206 WindowPointX = theConfigureNotification->x;
1207 WindowPointY = theConfigureNotification->y;
1208 BorderWidth = theConfigureNotification->border_width;
1212 theExposure = (xcb_expose_event_t *)theEvent;
1213 if ( theExposure->count == 0 )
1216 case XCB_MAP_NOTIFY:
1220 ContinueState = ProcessKeyPress( (xcb_key_press_event_t *)theEvent );
1222 case XCB_BUTTON_PRESS:
1223 theButtonPress = (xcb_button_press_event_t *)theEvent;
1224 ContinueState = ( theButtonPress->detail.id != 3 ); /* xbutton.button */
1226 /* new: handle ClientMessage */
1227 case XCB_CLIENT_MESSAGE:
1228 ContinueState = !IsDeleteMessage((xcb_client_message_event_t *)theEvent);
1232 /*printf("event type:%x\n", (int)theEvent->response_type);*/
1242 XNextEvent( theDisplay, &theEvent );
1243 switch ( theEvent.type ) {
1244 case ConfigureNotify:
1245 WindowWidth = theEvent.xconfigure.width;
1246 WindowHeight = theEvent.xconfigure.height;
1247 WindowPointX = theEvent.xconfigure.x;
1248 WindowPointY = theEvent.xconfigure.y;
1249 BorderWidth = theEvent.xconfigure.border_width;
1252 if ( theEvent.xexpose.count == 0 )
1253 DisplayCharacters();
1256 DisplayCharacters();
1259 ContinueState = ProcessKeyPress( &theEvent );
1262 if ( theEvent.xbutton.button == 3 )
1271 while ( XCheckMaskEvent( theDisplay, EVENT_MASK, &theEvent ) ) {
1272 switch ( theEvent.type ) {
1273 case ConfigureNotify:
1274 WindowWidth = theEvent.xconfigure.width;
1275 WindowHeight = theEvent.xconfigure.height;
1276 WindowPointX = theEvent.xconfigure.x;
1277 WindowPointY = theEvent.xconfigure.y;
1278 BorderWidth = theEvent.xconfigure.border_width;
1282 if ( theEvent.xexpose.count == 0 )
1289 ContinueState = ProcessKeyPress( &theEvent );
1290 if ( !ContinueState ) {
1291 return( ContinueState );
1295 if ( theEvent.xbutton.button == 3 )
1306 /* Internal Error */
1310 return( ContinueState );
1314 void ProcessNeko(void) {
1315 struct itimerval Value;
1317 EventState = NORMAL_STATE;
1319 NekoX = ( WindowWidth - BITMAP_WIDTH / 2 ) / 2;
1320 NekoY = ( WindowHeight - BITMAP_HEIGHT / 2 ) / 2;
1325 SetNekoState( NEKO_STOP );
1327 timerclear( &Value.it_interval );
1328 timerclear( &Value.it_value );
1330 Value.it_interval.tv_usec = IntervalTime;
1331 Value.it_value.tv_usec = IntervalTime;
1333 setitimer( ITIMER_REAL, &Value, 0 );
1337 } while ( ProcessEvent() );
1343 EventState = DEBUG_LIST;
1345 fprintf( stderr, "\n" );
1346 fprintf( stderr, "G-0lMw$rI=<($7$^$9!#(Quit !D Alt-Q)\n" );
1347 fprintf( stderr, "\n" );
1349 XSelectInput( theDisplay, theWindow, EVENT_MASK );
1351 while ( ProcessEvent() );
1355 void NekoMoveTest() {
1356 struct itimerval Value;
1358 EventState = DEBUG_MOVE;
1360 NekoX = ( WindowWidth - BITMAP_WIDTH / 2 ) / 2;
1361 NekoY = ( WindowHeight - BITMAP_HEIGHT / 2 ) / 2;
1366 SetNekoState( NEKO_STOP );
1368 timerclear( &Value.it_interval );
1369 timerclear( &Value.it_value );
1371 Value.it_interval.tv_usec = IntervalTime;
1372 Value.it_value.tv_usec = IntervalTime;
1374 setitimer( ITIMER_REAL, &Value, 0 );
1376 fprintf( stderr, "\n" );
1377 fprintf( stderr, "G-$N0\F0%F%9%H$r9T$$$^$9!#(Quit !D Alt-Q)\n" );
1378 fprintf( stderr, "\n" );
1379 fprintf( stderr, "\t%-!<%Q%C%I>e$N%F%s%-!<$GG-$r0\F0$5$;$F2<$5$$!#\n" );
1380 fprintf( stderr, "\t(M-8z$J%-!<$O#1!A#9$G$9!#)\n" );
1381 fprintf( stderr, "\n" );
1385 } while ( ProcessEvent() );
1389 void ProcessDebugMenu() {
1390 int UserSelectNo = 0;
1391 char UserAnswer[ BUFSIZ ];
1393 fprintf( stderr, "\n" );
1394 fprintf( stderr, "!Zxneko %G%P%C%0%a%K%e!<![\n" );
1396 while ( !( UserSelectNo >= 1 && UserSelectNo <= 2 ) ) {
1397 fprintf( stderr, "\n" );
1398 fprintf( stderr, "\t1)!!G-%-%c%i%/%?!<0lMwI=<(\n" );
1399 fprintf( stderr, "\t2)!!G-0\F0%F%9%H\n" );
1400 fprintf( stderr, "\n" );
1401 fprintf( stderr, "Select: " );
1403 fgets( UserAnswer, sizeof( UserAnswer ), stdin );
1405 UserSelectNo = atoi( UserAnswer );
1407 if ( !( UserSelectNo >= 1 && UserSelectNo <= 2 ) ) {
1408 fprintf( stderr, "\n" );
1409 fprintf( stderr, "@5$7$$HV9f$rA*Br$7$F2<$5$$!#\n" );
1413 switch ( UserSelectNo ) {
1421 /* Internal Error */
1425 fprintf( stderr, "%F%9%H=*N;!#\n" );
1426 fprintf( stderr, "\n" );
1431 void NullFunction(int ignored)
1433 /* signal( SIGALRM, NullFunction ); */
1439 "Usage: %s [-display <display>] [-geometry <geometry>] \\\n",
1441 fprintf( stderr, "\t[-bg <background>] [-fg <foreground>] \\\n" );
1442 fprintf( stderr, "\t[-title <title>] [-name <title>] [-iconic] \\\n" );
1443 fprintf( stderr, "\t[-speed <speed>] [-time <time>] [-root] [-help]\n" );
1448 GetArguments( int argc, char *argv[],
1449 char *theDisplayName, char *theGeometry, char **theTitle,
1450 double *NekoSpeed, long *IntervalTime )
1455 theDisplayName[ 0 ] = '\0';
1456 theGeometry[ 0 ] = '\0';
1458 iconicState = False;
1460 for ( ArgCounter = 0; ArgCounter < argc; ArgCounter++ ) {
1461 if ( strncmp( argv[ ArgCounter ], "-h", 2 ) == 0 ) {
1464 } else if ( strcmp( argv[ ArgCounter ], "-display" ) == 0 ) {
1466 if ( ArgCounter < argc ) {
1467 strcpy( theDisplayName, argv[ ArgCounter ] );
1469 fprintf( stderr, "%s: -display option error.\n", ProgramName );
1472 } else if ( strncmp( argv[ ArgCounter ], "-geom", 5 ) == 0 ) {
1474 if ( ArgCounter < argc ) {
1475 strcpy( theGeometry, argv[ ArgCounter ] );
1478 "%s: -geometry option error.\n", ProgramName );
1481 } else if ( ( strcmp( argv[ ArgCounter ], "-title" ) == 0 )
1482 || ( strcmp( argv[ ArgCounter ], "-name" ) == 0 ) ) {
1484 if ( ArgCounter < argc ) {
1485 *theTitle = argv[ ArgCounter ];
1487 fprintf( stderr, "%s: -title option error.\n", ProgramName );
1490 } else if ( strcmp( argv[ ArgCounter ], "-iconic" ) == 0 ) {
1492 } else if ( strcmp( argv[ ArgCounter ], "-speed" ) == 0 ) {
1494 if ( ArgCounter < argc ) {
1495 *NekoSpeed = atof( argv[ ArgCounter ] );
1497 fprintf( stderr, "%s: -speed option error.\n", ProgramName );
1500 } else if ( strcmp( argv[ ArgCounter ], "-fg" ) == 0 ) {
1502 if ( ArgCounter < argc ) {
1503 fgColor = argv[ArgCounter];
1505 fprintf( stderr, "%s: -fg option error.\n", ProgramName );
1508 } else if ( strcmp( argv[ ArgCounter ], "-bg" ) == 0 ) {
1510 if ( ArgCounter < argc ) {
1511 bgColor = argv[ArgCounter];
1513 fprintf( stderr, "%s: -bg option error.\n", ProgramName );
1516 } else if ( strcmp( argv[ ArgCounter ], "-time" ) == 0 ) {
1518 if ( ArgCounter < argc ) {
1519 *IntervalTime = atol( argv[ ArgCounter ] );
1521 fprintf( stderr, "%s: -time option error.\n", ProgramName );
1524 } else if ( strcmp( argv[ ArgCounter ], "-root" ) == 0 ) {
1528 "%s: Unknown option \"%s\".\n", ProgramName,
1529 argv[ ArgCounter ] );
1535 return( iconicState );
1538 void UndefineCursor( xcb_connection_t *c, xcb_window_t w)
1540 uint32_t none[] = { XCB_NONE };
1541 xcb_change_window_attributes( c, w, XCB_CW_CURSOR, none );
1545 main( int argc, char *argv[] )
1548 char theDisplayName[ DIRNAMELEN ];
1549 char theGeometry[ DIRNAMELEN ];
1550 char *theTitle = "";
1552 ProgramName = argv[ 0 ];
1558 fgColor = bgColor = (char *) NULL;
1560 iconicState = GetArguments( argc, argv, theDisplayName, theGeometry,
1561 &theTitle, &NekoSpeed, &IntervalTime );
1563 if (theTitle[0] == 0) theTitle = ProgramName;
1564 InitScreen( theDisplayName, theGeometry, theTitle, iconicState );
1566 signal( SIGALRM, NullFunction );
1568 SinPiPer8Times3 = sin( PI_PER8 * (double)3 );
1569 SinPiPer8 = sin( PI_PER8 );
1577 UndefineCursor( xc, theWindow );
1578 xcb_disconnect( xc );