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>
25 /*#include <xcb/xcb_image.h>*/
26 #include <xcb/xcb_aux.h> /* xcb_aux_get_screen_t */
27 #include <xcb/xcb_icccm.h>
28 #include <xcb/xcb_atom.h> /* STRING atom */
29 #include <xcb/xcb_keysyms.h>
31 typedef enum { False, True } Bool;
39 #include <unistd.h> /* pause() */
44 #include "bitmaps/icon.xbm"
45 #include "bitmaps/cursor.xbm"
46 #include "bitmaps/cursor_mask.xbm"
48 #include "bitmaps/space.xbm"
50 #include "bitmaps/mati2.xbm"
51 #include "bitmaps/jare2.xbm"
52 #include "bitmaps/kaki1.xbm"
53 #include "bitmaps/kaki2.xbm"
54 #include "bitmaps/mati3.xbm"
55 #include "bitmaps/sleep1.xbm"
56 #include "bitmaps/sleep2.xbm"
58 #include "bitmaps/awake.xbm"
60 #include "bitmaps/up1.xbm"
61 #include "bitmaps/up2.xbm"
62 #include "bitmaps/down1.xbm"
63 #include "bitmaps/down2.xbm"
64 #include "bitmaps/left1.xbm"
65 #include "bitmaps/left2.xbm"
66 #include "bitmaps/right1.xbm"
67 #include "bitmaps/right2.xbm"
68 #include "bitmaps/upright1.xbm"
69 #include "bitmaps/upright2.xbm"
70 #include "bitmaps/upleft1.xbm"
71 #include "bitmaps/upleft2.xbm"
72 #include "bitmaps/dwleft1.xbm"
73 #include "bitmaps/dwleft2.xbm"
74 #include "bitmaps/dwright1.xbm"
75 #include "bitmaps/dwright2.xbm"
77 #include "bitmaps/utogi1.xbm"
78 #include "bitmaps/utogi2.xbm"
79 #include "bitmaps/dtogi1.xbm"
80 #include "bitmaps/dtogi2.xbm"
81 #include "bitmaps/ltogi1.xbm"
82 #include "bitmaps/ltogi2.xbm"
83 #include "bitmaps/rtogi1.xbm"
84 #include "bitmaps/rtogi2.xbm"
86 #define BITMAP_WIDTH 32
87 #define BITMAP_HEIGHT 32
88 #define WINDOW_WIDTH 320
89 #define WINDOW_HEIGHT 256
90 #define DEFAULT_BORDER 2
91 #define DEFAULT_WIN_X 1
92 #define DEFAULT_WIN_Y 1
93 #define AVAIL_KEYBUF 255
95 #define EVENT_MASK ( XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_BUTTON_PRESS | \
96 XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_STRUCTURE_NOTIFY )
98 #define EVENT_MASK_ROOT ( XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_EXPOSURE )
100 #define MAX_TICK 9999 /* Odd Only! */
101 #define INTERVAL 125000L
102 #define NEKO_SPEED 16
104 #define NORMAL_STATE 1
114 #define NEKO_U_MOVE 6
115 #define NEKO_D_MOVE 7
116 #define NEKO_L_MOVE 8
117 #define NEKO_R_MOVE 9
118 #define NEKO_UL_MOVE 10
119 #define NEKO_UR_MOVE 11
120 #define NEKO_DL_MOVE 12
121 #define NEKO_DR_MOVE 13
122 #define NEKO_U_TOGI 14
123 #define NEKO_D_TOGI 15
124 #define NEKO_L_TOGI 16
125 #define NEKO_R_TOGI 17
127 #define NEKO_STOP_TIME 4
128 #define NEKO_JARE_TIME 10
129 #define NEKO_KAKI_TIME 4
130 #define NEKO_AKUBI_TIME 3
131 #define NEKO_AWAKE_TIME 3
132 #define NEKO_TOGI_TIME 10
134 #define PI_PER8 ((double)3.1415926535/(double)8)
136 #define DIRNAMELEN 255
139 char *fgColor, *bgColor;
141 static char *ProgramName;
143 xcb_connection_t *xc;
144 xcb_screen_t *theScreen; /* instead of macro(theDisplay, int theScreen) */
145 unsigned long theFgPixel;
146 unsigned long theBgPixel;
147 xcb_window_t theWindow;
148 xcb_cursor_t theCursor;
149 xcb_key_symbols_t *theKeySyms;
150 xcb_atom_t deleteWindowAtom;
152 static unsigned int WindowWidth;
153 static unsigned int WindowHeight;
154 static int WindowPointX;
155 static int WindowPointY;
157 static unsigned int BorderWidth = DEFAULT_BORDER;
159 long IntervalTime = INTERVAL;
181 xcb_gcontext_t NekoLastGC;
183 double NekoSpeed = (double)NEKO_SPEED;
185 double SinPiPer8Times3;
188 xcb_pixmap_t SpaceXbm;
190 xcb_pixmap_t Mati2Xbm;
191 xcb_pixmap_t Jare2Xbm;
192 xcb_pixmap_t Kaki1Xbm;
193 xcb_pixmap_t Kaki2Xbm;
194 xcb_pixmap_t Mati3Xbm;
195 xcb_pixmap_t Sleep1Xbm;
196 xcb_pixmap_t Sleep2Xbm;
198 xcb_pixmap_t AwakeXbm;
202 xcb_pixmap_t Down1Xbm;
203 xcb_pixmap_t Down2Xbm;
204 xcb_pixmap_t Left1Xbm;
205 xcb_pixmap_t Left2Xbm;
206 xcb_pixmap_t Right1Xbm;
207 xcb_pixmap_t Right2Xbm;
208 xcb_pixmap_t UpLeft1Xbm;
209 xcb_pixmap_t UpLeft2Xbm;
210 xcb_pixmap_t UpRight1Xbm;
211 xcb_pixmap_t UpRight2Xbm;
212 xcb_pixmap_t DownLeft1Xbm;
213 xcb_pixmap_t DownLeft2Xbm;
214 xcb_pixmap_t DownRight1Xbm;
215 xcb_pixmap_t DownRight2Xbm;
217 xcb_pixmap_t UpTogi1Xbm;
218 xcb_pixmap_t UpTogi2Xbm;
219 xcb_pixmap_t DownTogi1Xbm;
220 xcb_pixmap_t DownTogi2Xbm;
221 xcb_pixmap_t LeftTogi1Xbm;
222 xcb_pixmap_t LeftTogi2Xbm;
223 xcb_pixmap_t RightTogi1Xbm;
224 xcb_pixmap_t RightTogi2Xbm;
226 xcb_gcontext_t SpaceGC;
228 xcb_gcontext_t Mati2GC;
229 xcb_gcontext_t Jare2GC;
230 xcb_gcontext_t Kaki1GC;
231 xcb_gcontext_t Kaki2GC;
232 xcb_gcontext_t Mati3GC;
233 xcb_gcontext_t Sleep1GC;
234 xcb_gcontext_t Sleep2GC;
236 xcb_gcontext_t AwakeGC;
238 xcb_gcontext_t Up1GC;
239 xcb_gcontext_t Up2GC;
240 xcb_gcontext_t Down1GC;
241 xcb_gcontext_t Down2GC;
242 xcb_gcontext_t Left1GC;
243 xcb_gcontext_t Left2GC;
244 xcb_gcontext_t Right1GC;
245 xcb_gcontext_t Right2GC;
246 xcb_gcontext_t UpLeft1GC;
247 xcb_gcontext_t UpLeft2GC;
248 xcb_gcontext_t UpRight1GC;
249 xcb_gcontext_t UpRight2GC;
250 xcb_gcontext_t DownLeft1GC;
251 xcb_gcontext_t DownLeft2GC;
252 xcb_gcontext_t DownRight1GC;
253 xcb_gcontext_t DownRight2GC;
255 xcb_gcontext_t UpTogi1GC;
256 xcb_gcontext_t UpTogi2GC;
257 xcb_gcontext_t DownTogi1GC;
258 xcb_gcontext_t DownTogi2GC;
259 xcb_gcontext_t LeftTogi1GC;
260 xcb_gcontext_t LeftTogi2GC;
261 xcb_gcontext_t RightTogi1GC;
262 xcb_gcontext_t RightTogi2GC;
265 xcb_gcontext_t *GCCreatePtr;
266 xcb_pixmap_t *BitmapCreatePtr;
268 unsigned int PixelWidth;
269 unsigned int PixelHeight;
272 BitmapGCData BitmapGCDataTable[] = {
273 { &SpaceGC, &SpaceXbm, space_bits, space_width, space_height },
274 { &Mati2GC, &Mati2Xbm, mati2_bits, mati2_width, mati2_height },
275 { &Jare2GC, &Jare2Xbm, jare2_bits, jare2_width, jare2_height },
276 { &Kaki1GC, &Kaki1Xbm, kaki1_bits, kaki1_width, kaki1_height },
277 { &Kaki2GC, &Kaki2Xbm, kaki2_bits, kaki2_width, kaki2_height },
278 { &Mati3GC, &Mati3Xbm, mati3_bits, mati3_width, mati3_height },
279 { &Sleep1GC, &Sleep1Xbm, sleep1_bits, sleep1_width, sleep1_height },
280 { &Sleep2GC, &Sleep2Xbm, sleep2_bits, sleep2_width, sleep2_height },
281 { &AwakeGC, &AwakeXbm, awake_bits, awake_width, awake_height },
282 { &Up1GC, &Up1Xbm, up1_bits, up1_width, up1_height },
283 { &Up2GC, &Up2Xbm, up2_bits, up2_width, up2_height },
284 { &Down1GC, &Down1Xbm, down1_bits, down1_width, down1_height },
285 { &Down2GC, &Down2Xbm, down2_bits, down2_width, down2_height },
286 { &Left1GC, &Left1Xbm, left1_bits, left1_width, left1_height },
287 { &Left2GC, &Left2Xbm, left2_bits, left2_width, left2_height },
288 { &Right1GC, &Right1Xbm, right1_bits, right1_width, right1_height },
289 { &Right2GC, &Right2Xbm, right2_bits, right2_width, right2_height },
290 { &UpLeft1GC, &UpLeft1Xbm, upleft1_bits, upleft1_width, upleft1_height },
291 { &UpLeft2GC, &UpLeft2Xbm, upleft2_bits, upleft2_width, upleft2_height },
293 &UpRight1Xbm, upright1_bits, upright1_width, upright1_height },
295 &UpRight2Xbm, upright2_bits, upright2_width, upright2_height },
296 { &DownLeft1GC, &DownLeft1Xbm, dwleft1_bits, dwleft1_width, dwleft1_height },
297 { &DownLeft2GC, &DownLeft2Xbm, dwleft2_bits, dwleft2_width, dwleft2_height },
299 &DownRight1Xbm, dwright1_bits, dwright1_width, dwright1_height },
301 &DownRight2Xbm, dwright2_bits, dwright2_width, dwright2_height },
302 { &UpTogi1GC, &UpTogi1Xbm, utogi1_bits, utogi1_width, utogi1_height },
303 { &UpTogi2GC, &UpTogi2Xbm, utogi2_bits, utogi2_width, utogi2_height },
304 { &DownTogi1GC, &DownTogi1Xbm, dtogi1_bits, dtogi1_width, dtogi1_height },
305 { &DownTogi2GC, &DownTogi2Xbm, dtogi2_bits, dtogi2_width, dtogi2_height },
306 { &LeftTogi1GC, &LeftTogi1Xbm, ltogi1_bits, ltogi1_width, ltogi1_height },
307 { &LeftTogi2GC, &LeftTogi2Xbm, ltogi2_bits, ltogi2_width, ltogi2_height },
309 &RightTogi1Xbm, rtogi1_bits, rtogi1_width, rtogi1_height },
311 &RightTogi2Xbm, rtogi2_bits, rtogi2_width, rtogi2_height },
312 { NULL, NULL, NULL, 0, 0 }
316 xcb_gcontext_t *TickEvenGCPtr;
317 xcb_gcontext_t *TickOddGCPtr;
320 Animation AnimationPattern[] = {
321 { &Mati2GC, &Mati2GC }, /* NekoState == NEKO_STOP */
322 { &Jare2GC, &Mati2GC }, /* NekoState == NEKO_JARE */
323 { &Kaki1GC, &Kaki2GC }, /* NekoState == NEKO_KAKI */
324 { &Mati3GC, &Mati3GC }, /* NekoState == NEKO_AKUBI */
325 { &Sleep1GC, &Sleep2GC }, /* NekoState == NEKO_SLEEP */
326 { &AwakeGC, &AwakeGC }, /* NekoState == NEKO_AWAKE */
327 { &Up1GC, &Up2GC } , /* NekoState == NEKO_U_MOVE */
328 { &Down1GC, &Down2GC }, /* NekoState == NEKO_D_MOVE */
329 { &Left1GC, &Left2GC }, /* NekoState == NEKO_L_MOVE */
330 { &Right1GC, &Right2GC }, /* NekoState == NEKO_R_MOVE */
331 { &UpLeft1GC, &UpLeft2GC }, /* NekoState == NEKO_UL_MOVE */
332 { &UpRight1GC, &UpRight2GC }, /* NekoState == NEKO_UR_MOVE */
333 { &DownLeft1GC, &DownLeft2GC }, /* NekoState == NEKO_DL_MOVE */
334 { &DownRight1GC, &DownRight2GC }, /* NekoState == NEKO_DR_MOVE */
335 { &UpTogi1GC, &UpTogi2GC }, /* NekoState == NEKO_U_TOGI */
336 { &DownTogi1GC, &DownTogi2GC }, /* NekoState == NEKO_D_TOGI */
337 { &LeftTogi1GC, &LeftTogi2GC }, /* NekoState == NEKO_L_TOGI */
338 { &RightTogi1GC, &RightTogi2GC }, /* NekoState == NEKO_R_TOGI */
342 /* PutImage.c: format/unit/order conversion should move out to a library */
343 static unsigned char const _reverse_byte[0x100] = {
344 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
345 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
346 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
347 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
348 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
349 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
350 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
351 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
352 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
353 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
354 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
355 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
356 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
357 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
358 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
359 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
360 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
361 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
362 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
363 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
364 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
365 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
366 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
367 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
368 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
369 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
370 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
371 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
372 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
373 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
374 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
375 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
378 /* convert 1Ll <--> 4Mm */
381 register unsigned char *src,
382 register unsigned char *dest,
383 long srclen, long srcinc, long destinc,
387 register const unsigned char *rev = _reverse_byte;
391 for (h = height; --h >= 0; src += srcinc, dest += destinc)
392 for (n = srclen; --n >= 0; )
393 *dest++ = rev[*src++];
396 /* assumes pad is a power of 2 */
397 #define ROUNDUP(nbytes, pad) (((nbytes) + ((pad) - 1)) & ~(long)((pad) - 1))
399 /* CrPFBData.c and CrBFData.c (very similar) */
400 /* if depth==1, behaves like CreateBitmapFromData */
401 xcb_pixmap_t CreatePixmapFromBitmapData( xcb_connection_t *c,
402 xcb_window_t window, char *data, uint16_t w, uint16_t h,
403 uint32_t fg, uint32_t bg, uint32_t depth)
405 xcb_pixmap_t bitmap = xcb_generate_id( c );
407 xcb_create_pixmap( c, depth, bitmap, window, w, h );
409 xcb_gcontext_t gc = xcb_generate_id( c );
411 uint32_t mask = (depth==1 ? 0 : XCB_GC_FOREGROUND | XCB_GC_BACKGROUND);
412 uint32_t values[] = { fg, bg };
414 xcb_create_gc( c, gc, bitmap, mask, values );
416 /* XImage attributes: bpp=1, xoffset=0,
417 byte_order=bit_order=LSB, unit=8, pad=8, bpl=(w+7/8) */
419 /* must swap and pad the data if bit/byte_order isn't LSB (Mac) */
421 /* Mac X Server: byte_order=bit_order=MSB, unit=32, padding=32 */
423 long pad = xcb_get_setup(c)->bitmap_format_scanline_pad;
424 long bpd = ROUNDUP(w, pad)>>3;
425 long bufLen = bpd * h;
427 if (xcb_get_setup(c)->bitmap_format_scanline_unit == 32 &&
428 xcb_get_setup(c)->bitmap_format_bit_order == XCB_IMAGE_ORDER_MSB_FIRST &&
429 xcb_get_setup(c)->image_byte_order == XCB_IMAGE_ORDER_MSB_FIRST)
431 SwapBits((unsigned char *)data, buf, bpl, bpl, bpd, h);
436 uint8_t *src = (uint8_t *)data, *dest = buf;
437 for (i=0; i<h; i++, dest += bpd, src += bpl)
438 memcpy(dest, src, bpl);
441 memcpy(buf, data, bufLen);
443 /* note: CBfD uses XYPixmap, but CPfBD uses XYBitmap
444 there shouldn't be a difference when depth==1,
445 but the neko images are corrupt if using XYPixmap */
446 uint8_t format = (depth==1 ? XCB_IMAGE_FORMAT_XY_PIXMAP : XCB_IMAGE_FORMAT_XY_BITMAP);
448 /* PutImage.c: left_pad = (image->xoffset + req->xoffset) & (dpy->bitmap_unit-1)
449 screen->bitmap_format_scanline_unit
450 left_pad = (0 + 0) & (32 - 1) = 0 */
452 xcb_put_image( c, format, bitmap, gc,
454 0, 1, /* left_pad, depth */
458 xcb_generic_error_t *error = NULL;
459 xcb_sync( c, &error );
461 printf("error code %d", (int)error->error_code);
466 xcb_free_gc( c, gc );
468 /* later: xcb_free_pixmap( c, bitmap ); */
472 xcb_pixmap_t CreateBitmapFromData(xcb_connection_t *c, xcb_window_t window,
473 char *data, uint16_t w, uint16_t h)
476 return CreatePixmapFromBitmapData(c, window, data, w, h, 0, 0, depth);
479 void InitBitmapAndGCs(void) {
480 BitmapGCData *BitmapGCDataTablePtr;
481 uint32_t theGCValues[5];
483 theGCValues[0] = XCB_GX_COPY;
485 theGCValues[1] = theFgPixel;
486 theGCValues[2] = theBgPixel;
488 theGCValues[3] = XCB_FILL_STYLE_TILED;
490 /* TODO: latency: make all the bitmaps, then all the contexts? */
492 for ( BitmapGCDataTablePtr = BitmapGCDataTable;
493 BitmapGCDataTablePtr->GCCreatePtr != NULL;
494 BitmapGCDataTablePtr++ ) {
496 *(BitmapGCDataTablePtr->BitmapCreatePtr)
497 = CreatePixmapFromBitmapData( xc, theScreen->root,
498 BitmapGCDataTablePtr->PixelPattern,
499 BitmapGCDataTablePtr->PixelWidth,
500 BitmapGCDataTablePtr->PixelHeight,
501 theFgPixel, theBgPixel, theScreen->root_depth);
503 theGCValues[4] = *(BitmapGCDataTablePtr->BitmapCreatePtr); /* tile */
505 *(BitmapGCDataTablePtr->GCCreatePtr) = xcb_generate_id( xc );
506 xcb_create_gc( xc, *(BitmapGCDataTablePtr->GCCreatePtr), theWindow,
507 XCB_GC_FUNCTION | XCB_GC_FOREGROUND | XCB_GC_BACKGROUND |
508 XCB_GC_FILL_STYLE | XCB_GC_TILE,
512 /* later: xcb_free_pixmap( c, bitmap ); */
513 /* later: xcb_free_gc( c, gc ); */
517 GetAtom(xcb_connection_t *c, const char *atomName)
519 xcb_atom_t atom = { XCB_NONE };
520 xcb_intern_atom_reply_t *r = xcb_intern_atom_reply(c,
521 xcb_intern_atom(c, 0, strlen(atomName), atomName), NULL);
530 InitScreen( char *DisplayName, char *theGeometry, char *theTitle, Bool iconicState )
532 xcb_pixmap_t theCursorSource;
533 xcb_pixmap_t theCursorMask;
534 unsigned int theDepth;
535 xcb_colormap_t theColormap;
538 if ( ( xc = xcb_connect( DisplayName, &screen ) ) == NULL ) {
539 fprintf( stderr, "%s: Can't open connection", ProgramName );
540 if ( DisplayName != NULL )
541 fprintf( stderr, " %s.\n", DisplayName );
543 fprintf( stderr, ".\n" );
547 theScreen = xcb_aux_get_screen(xc, screen);
548 if (theScreen == NULL) {
549 fprintf( stderr, "%s: Can't get default screen", ProgramName );
553 theDepth = theScreen->root_depth; /* DefaultDepth */
554 theColormap = theScreen->default_colormap;
556 WindowPointX = DEFAULT_WIN_X;
557 WindowPointY = DEFAULT_WIN_Y;
558 WindowWidth = WINDOW_WIDTH;
559 WindowHeight = WINDOW_HEIGHT;
563 GeometryStatus = XParseGeometry( theGeometry,
564 &WindowPointX, &WindowPointY,
565 &WindowWidth, &WindowHeight );
568 theCursorSource = CreateBitmapFromData( xc,
574 theCursorMask = CreateBitmapFromData( xc,
578 cursor_mask_height );
581 if ( bgColor == NULL) bgColor = "white";
582 if ( fgColor == NULL) fgColor = "black";
584 xcb_alloc_named_color_cookie_t bgCookie = xcb_alloc_named_color ( xc,
585 theColormap, strlen(bgColor), bgColor );
587 xcb_alloc_named_color_cookie_t fgCookie = xcb_alloc_named_color ( xc,
588 theColormap, strlen(fgColor), fgColor );
590 /* mouse cursor is always black and white */
591 xcb_alloc_named_color_cookie_t blackCookie = xcb_alloc_named_color ( xc,
592 theColormap, strlen("black"), "black" );
593 xcb_alloc_named_color_cookie_t whiteCookie = xcb_alloc_named_color ( xc,
594 theColormap, strlen("white"), "white" );
596 xcb_alloc_named_color_reply_t *bgRep = xcb_alloc_named_color_reply( xc, bgCookie, 0 );
599 "%s: Can't allocate the background color %s.\n", ProgramName, bgColor );
602 theBgPixel = bgRep->pixel;
604 xcb_alloc_named_color_reply_t *fgRep = xcb_alloc_named_color_reply( xc, fgCookie, 0 );
607 "%s: Can't allocate the foreground color %s.\n", ProgramName, fgColor );
610 theFgPixel = fgRep->pixel;
612 xcb_alloc_named_color_reply_t *blackRep = xcb_alloc_named_color_reply( xc, blackCookie, 0 );
615 "%s: Can't allocate the black color.\n", ProgramName );
618 xcb_alloc_named_color_reply_t *whiteRep = xcb_alloc_named_color_reply( xc, whiteCookie, 0 );
621 "%s: Can't allocate the white color.\n", ProgramName );
625 theCursor = xcb_generate_id( xc );
626 xcb_create_cursor ( xc, theCursor, theCursorSource, theCursorMask,
627 blackRep->visual_red, blackRep->visual_green, blackRep->visual_blue,
628 whiteRep->visual_red, whiteRep->visual_green, whiteRep->visual_blue,
629 cursor_x_hot, cursor_y_hot );
637 uint32_t rootAttributes[] = { theBgPixel, EVENT_MASK_ROOT, theCursor };
638 theWindow = theScreen->root;
639 xcb_change_window_attributes(xc, theWindow,
640 XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK | XCB_CW_CURSOR, rootAttributes );
642 /* XClearWindow: clear area with all dimensions 0 */
643 xcb_clear_area( xc, False, theWindow, 0, 0, 0, 0 );
645 xcb_get_geometry_reply_t *geometry = xcb_get_geometry_reply( xc,
646 xcb_get_geometry( xc, theWindow ), NULL);
648 /* only width & height are used by the program */
649 WindowWidth = geometry->width;
650 WindowHeight = geometry->height;
654 /* TODO: grab key Alt-Q to quit gracefully? */
657 xcb_pixmap_t theIconPixmap;
659 uint32_t theWindowAttributes[] = {
660 theBgPixel, /* background */
661 theFgPixel, /* border */
662 False, /* override_redirect */
666 unsigned long theWindowMask = XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL |
667 XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK | XCB_CW_CURSOR;
669 theWindow = xcb_generate_id( xc );
670 xcb_create_window( xc,
674 WindowPointX, WindowPointY,
675 WindowWidth, WindowHeight,
677 XCB_WINDOW_CLASS_INPUT_OUTPUT,
678 theScreen->root_visual, /* CopyFromParent */
679 theWindowMask, theWindowAttributes );
681 /* new: obey the window-delete protocol, look for XCB_CLIENT_MESSAGE */
682 deleteWindowAtom = GetAtom(xc, "WM_DELETE_WINDOW");
683 SetWMProtocols( xc, theWindow, 1, &deleteWindowAtom );
685 theIconPixmap = CreateBitmapFromData( xc, theWindow,
686 icon_bits, icon_width, icon_height );
688 WMHints *theWMHints = AllocWMHints();
690 WMHintsSetIconPixmap( theWMHints, theIconPixmap );
693 WMHintsSetIconic( theWMHints );
695 WMHintsSetNormal( theWMHints );
697 SetWMHints( xc, theWindow, theWMHints);
701 /* why hide the structure? */
702 SizeHints *theSizeHints = AllocSizeHints();
704 /* need enum for second param (user specified) */
705 SizeHintsSetPosition(theSizeHints, 0, WindowPointX, WindowPointY);
706 SizeHintsSetSize(theSizeHints, 0, WindowWidth, WindowHeight);
708 SetWMNormalHints(xc, theWindow, theSizeHints);
710 FreeSizeHints(theSizeHints);
712 /* Um, why do I have to specify the encoding in this API? */
713 SetWMName( xc, theWindow, STRING, strlen(theTitle), theTitle );
714 SetWMIconName( xc, theWindow, STRING, strlen(theTitle), theTitle );
716 xcb_map_window( xc, theWindow );
724 /* latency: ask for keysyms now, and receive them later */
725 theKeySyms = xcb_key_symbols_alloc( xc );
727 /* later: xcb_key_symbols_free( keysyms ); */
728 /* later: xcb_refresh_keyboard_mapping ( keysyms, mappingEvent ); */
732 void Interval(void) {
737 void TickCount(void) {
738 if ( ++NekoTickCount >= MAX_TICK )
741 if ( NekoTickCount % 2 == 0 )
742 if ( NekoStateCount < MAX_TICK )
748 SetNekoState( int SetValue )
753 NekoState = SetValue;
756 switch ( NekoState ) {
766 NekoMoveDx = NekoMoveDy = 0;
775 /* Xlib does merging of requests, but the Flush and frequent DrawGC changes
776 defeat this mechanism */
779 DrawNeko( int x, int y, xcb_gcontext_t DrawGC )
781 xcb_rectangle_t rect = { NekoLastX, NekoLastY, BITMAP_WIDTH, BITMAP_HEIGHT };
783 if ( (x != NekoLastX || y != NekoLastY) && (EventState != DEBUG_LIST) )
785 xcb_poly_fill_rectangle( xc, theWindow, SpaceGC, 1, &rect );
786 rect.x = x; rect.y = y;
790 uint32_t originMask = XCB_GC_TILE_STIPPLE_ORIGIN_X | XCB_GC_TILE_STIPPLE_ORIGIN_Y;
791 uint32_t origin[2] = { x, y };
792 xcb_change_gc( xc, DrawGC, originMask, origin );
793 /* XSetTSOrigin( theDisplay, DrawGC, x, y ); */
795 xcb_poly_fill_rectangle( xc, theWindow, DrawGC, 1, &rect );
806 void RedrawNeko(void) {
807 xcb_rectangle_t rect = { NekoLastX, NekoLastY, BITMAP_WIDTH, BITMAP_HEIGHT };
809 xcb_poly_fill_rectangle( xc, theWindow, NekoLastGC, 1, &rect );
816 void NekoDirection(void) {
818 double LargeX, LargeY;
822 if ( NekoMoveDx == 0 && NekoMoveDy == 0 ) {
823 NewState = NEKO_STOP;
825 LargeX = (double)NekoMoveDx;
826 LargeY = (double)(-NekoMoveDy);
827 Length = sqrt( LargeX * LargeX + LargeY * LargeY );
828 SinTheta = LargeY / Length;
830 if ( NekoMoveDx > 0 ) {
831 if ( SinTheta > SinPiPer8Times3 ) {
832 NewState = NEKO_U_MOVE;
833 } else if ( ( SinTheta <= SinPiPer8Times3 )
834 && ( SinTheta > SinPiPer8 ) ) {
835 NewState = NEKO_UR_MOVE;
836 } else if ( ( SinTheta <= SinPiPer8 )
837 && ( SinTheta > -( SinPiPer8 ) ) ) {
838 NewState = NEKO_R_MOVE;
839 } else if ( ( SinTheta <= -( SinPiPer8 ) )
840 && ( SinTheta > -( SinPiPer8Times3 ) ) ) {
841 NewState = NEKO_DR_MOVE;
843 NewState = NEKO_D_MOVE;
846 if ( SinTheta > SinPiPer8Times3 ) {
847 NewState = NEKO_U_MOVE;
848 } else if ( ( SinTheta <= SinPiPer8Times3 )
849 && ( SinTheta > SinPiPer8 ) ) {
850 NewState = NEKO_UL_MOVE;
851 } else if ( ( SinTheta <= SinPiPer8 )
852 && ( SinTheta > -( SinPiPer8 ) ) ) {
853 NewState = NEKO_L_MOVE;
854 } else if ( ( SinTheta <= -( SinPiPer8 ) )
855 && ( SinTheta > -( SinPiPer8Times3 ) ) ) {
856 NewState = NEKO_DL_MOVE;
858 NewState = NEKO_D_MOVE;
863 if ( NekoState != NewState ) {
864 SetNekoState( NewState );
869 Bool IsWindowOver(void) {
870 Bool ReturnValue = False;
875 } else if ( NekoY >= WindowHeight - BITMAP_HEIGHT ) {
876 NekoY = WindowHeight - BITMAP_HEIGHT;
882 } else if ( NekoX >= WindowWidth - BITMAP_WIDTH ) {
883 NekoX = WindowWidth - BITMAP_WIDTH;
887 return( ReturnValue );
891 Bool IsNekoDontMove(void) {
892 return( NekoX == NekoLastX && NekoY == NekoLastY );
896 Bool IsNekoMoveStart(void) {
898 if ( (PrevMouseX >= MouseX - IDLE_SPACE
899 && PrevMouseX <= MouseX + IDLE_SPACE) &&
900 (PrevMouseY >= MouseY - IDLE_SPACE
901 && PrevMouseY <= MouseY + IDLE_SPACE) )
906 if ( NekoMoveDx == 0 && NekoMoveDy == 0 )
914 void CalcDxDy(void) {
915 int RelativeX, RelativeY;
916 double LargeX, LargeY;
917 double DoubleLength, Length;
919 /* TODO: replace query with pointer motion notification? */
921 xcb_query_pointer_reply_t *reply = xcb_query_pointer_reply( xc,
922 xcb_query_pointer( xc, theWindow ), NULL);
924 RelativeX = reply->win_x;
925 RelativeY = reply->win_y;
935 LargeX = (double)( MouseX - NekoX - BITMAP_WIDTH / 2 );
936 LargeY = (double)( MouseY - NekoY - BITMAP_HEIGHT );
938 DoubleLength = LargeX * LargeX + LargeY * LargeY;
940 if ( DoubleLength != (double)0 ) {
941 Length = sqrt( DoubleLength );
942 if ( Length <= NekoSpeed ) {
943 NekoMoveDx = (int)LargeX;
944 NekoMoveDy = (int)LargeY;
946 NekoMoveDx = (int)( ( NekoSpeed * LargeX ) / Length );
947 NekoMoveDy = (int)( ( NekoSpeed * LargeY ) / Length );
950 NekoMoveDx = NekoMoveDy = 0;
955 void NekoThinkDraw(void) {
960 if ( NekoState != NEKO_SLEEP ) {
961 DrawNeko( NekoX, NekoY,
962 NekoTickCount % 2 == 0 ?
963 *(AnimationPattern[ NekoState ].TickEvenGCPtr) :
964 *(AnimationPattern[ NekoState ].TickOddGCPtr) );
966 DrawNeko( NekoX, NekoY,
967 NekoTickCount % 8 <= 3 ?
968 *(AnimationPattern[ NekoState ].TickEvenGCPtr) :
969 *(AnimationPattern[ NekoState ].TickOddGCPtr) );
974 switch ( NekoState ) {
976 if ( IsNekoMoveStart() ) {
977 SetNekoState( NEKO_AWAKE );
980 if ( NekoStateCount < NEKO_STOP_TIME ) {
983 if ( NekoMoveDx < 0 && NekoX <= 0 ) {
984 SetNekoState( NEKO_L_TOGI );
985 } else if ( NekoMoveDx > 0 && NekoX >= WindowWidth - BITMAP_WIDTH ) {
986 SetNekoState( NEKO_R_TOGI );
987 } else if ( NekoMoveDy < 0 && NekoY <= 0 ) {
988 SetNekoState( NEKO_U_TOGI );
989 } else if ( NekoMoveDy > 0 && NekoY >= WindowHeight - BITMAP_HEIGHT ) {
990 SetNekoState( NEKO_D_TOGI );
992 SetNekoState( NEKO_JARE );
996 if ( IsNekoMoveStart() ) {
997 SetNekoState( NEKO_AWAKE );
1000 if ( NekoStateCount < NEKO_JARE_TIME ) {
1003 SetNekoState( NEKO_KAKI );
1006 if ( IsNekoMoveStart() ) {
1007 SetNekoState( NEKO_AWAKE );
1010 if ( NekoStateCount < NEKO_KAKI_TIME ) {
1013 SetNekoState( NEKO_AKUBI );
1016 if ( IsNekoMoveStart() ) {
1017 SetNekoState( NEKO_AWAKE );
1020 if ( NekoStateCount < NEKO_AKUBI_TIME ) {
1023 SetNekoState( NEKO_SLEEP );
1026 if ( IsNekoMoveStart() ) {
1027 SetNekoState( NEKO_AWAKE );
1032 if ( NekoStateCount < NEKO_AWAKE_TIME ) {
1045 NekoX += NekoMoveDx;
1046 NekoY += NekoMoveDy;
1048 if ( IsWindowOver() ) {
1049 if ( IsNekoDontMove() ) {
1050 SetNekoState( NEKO_STOP );
1058 if ( IsNekoMoveStart() ) {
1059 SetNekoState( NEKO_AWAKE );
1062 if ( NekoStateCount < NEKO_TOGI_TIME ) {
1065 SetNekoState( NEKO_KAKI );
1068 /* Internal Error */
1069 SetNekoState( NEKO_STOP );
1078 void DisplayCharacters() {
1082 for ( Index = 0, x = 0, y = 0;
1083 BitmapGCDataTable[ Index ].GCCreatePtr != NULL; Index++ ) {
1085 DrawNeko( x, y, *(BitmapGCDataTable[ Index ].GCCreatePtr) );
1086 XFlush( theDisplay );
1090 if ( x > WindowWidth - BITMAP_WIDTH ) {
1093 if ( y > WindowHeight - BITMAP_HEIGHT) {
1103 ProcessKeyPress( xcb_key_press_event_t *theKeyEvent )
1105 Bool ReturnState = True;
1107 /* quit on Meta-Q (Alt-Q) */
1108 xcb_keysym_t theKeySym;
1110 /* last param is "int col". What? add enumeration to xcb_keysyms.h */
1111 theKeySym = xcb_key_press_lookup_keysym( theKeySyms, theKeyEvent, 1 );
1113 /* KeySym XK_Q == 'Q' */
1114 if (theKeySym == 'Q' && (theKeyEvent->state & XCB_MOD_MASK_1))
1115 ReturnState = False;
1118 if ( EventState == DEBUG_MOVE ) {
1119 switch ( theKeySym ) {
1121 NekoMoveDx = -(int)( NekoSpeed / sqrt( (double)2 ) );
1122 NekoMoveDy = -NekoMoveDx;
1126 NekoMoveDy = (int)NekoSpeed;
1129 NekoMoveDx = (int)( NekoSpeed / sqrt( (double)2 ) );
1130 NekoMoveDy = NekoMoveDx;
1133 NekoMoveDx = -(int)NekoSpeed;
1141 NekoMoveDx = (int)NekoSpeed;
1145 NekoMoveDx = -(int)( NekoSpeed / sqrt( (double)2 ) );
1146 NekoMoveDy = NekoMoveDx;
1150 NekoMoveDy = -(int)NekoSpeed;
1153 NekoMoveDx = (int)( NekoSpeed / sqrt( (double)2 ) );
1154 NekoMoveDy = -NekoMoveDx;
1160 return( ReturnState );
1164 void NekoAdjust(void) {
1167 else if ( NekoX > WindowWidth - BITMAP_WIDTH )
1168 NekoX = WindowWidth - BITMAP_WIDTH;
1172 else if ( NekoY > WindowHeight - BITMAP_HEIGHT )
1173 NekoY = WindowHeight - BITMAP_HEIGHT;
1176 int IsDeleteMessage(xcb_client_message_event_t *msg)
1178 return msg->data.data32[0] == deleteWindowAtom;
1181 Bool ProcessEvent(void) {
1182 xcb_generic_event_t *theEvent;
1183 xcb_configure_notify_event_t *theConfigureNotification;
1184 xcb_expose_event_t *theExposure;
1185 xcb_button_press_event_t *theButtonPress;
1186 Bool ContinueState = True;
1188 switch ( EventState ) {
1190 while ( ContinueState &&
1191 NULL != (theEvent = xcb_poll_for_event( xc )) ) { /*while ( XCheckMaskEvent( theDisplay, EVENT_MASK, &theEvent ) ) {*/
1192 switch ( theEvent->response_type & 0x7f ) {
1193 case XCB_CONFIGURE_NOTIFY:
1194 theConfigureNotification = (xcb_configure_notify_event_t *)theEvent;
1195 WindowWidth = theConfigureNotification->width;
1196 WindowHeight = theConfigureNotification->height;
1197 WindowPointX = theConfigureNotification->x;
1198 WindowPointY = theConfigureNotification->y;
1199 BorderWidth = theConfigureNotification->border_width;
1203 theExposure = (xcb_expose_event_t *)theEvent;
1204 if ( theExposure->count == 0 )
1207 case XCB_MAP_NOTIFY:
1211 ContinueState = ProcessKeyPress( (xcb_key_press_event_t *)theEvent );
1213 case XCB_BUTTON_PRESS:
1214 theButtonPress = (xcb_button_press_event_t *)theEvent;
1215 ContinueState = ( theButtonPress->detail != 3 ); /* xbutton.button */
1217 /* new: handle ClientMessage */
1218 case XCB_CLIENT_MESSAGE:
1219 ContinueState = !IsDeleteMessage((xcb_client_message_event_t *)theEvent);
1223 /*printf("event type:%x\n", (int)theEvent->response_type);*/
1231 XNextEvent( theDisplay, &theEvent );
1232 switch ( theEvent.type ) {
1233 case ConfigureNotify:
1234 WindowWidth = theEvent.xconfigure.width;
1235 WindowHeight = theEvent.xconfigure.height;
1236 WindowPointX = theEvent.xconfigure.x;
1237 WindowPointY = theEvent.xconfigure.y;
1238 BorderWidth = theEvent.xconfigure.border_width;
1241 if ( theEvent.xexpose.count == 0 )
1242 DisplayCharacters();
1245 DisplayCharacters();
1248 ContinueState = ProcessKeyPress( &theEvent );
1251 if ( theEvent.xbutton.button == 3 )
1260 while ( XCheckMaskEvent( theDisplay, EVENT_MASK, &theEvent ) ) {
1261 switch ( theEvent.type ) {
1262 case ConfigureNotify:
1263 WindowWidth = theEvent.xconfigure.width;
1264 WindowHeight = theEvent.xconfigure.height;
1265 WindowPointX = theEvent.xconfigure.x;
1266 WindowPointY = theEvent.xconfigure.y;
1267 BorderWidth = theEvent.xconfigure.border_width;
1271 if ( theEvent.xexpose.count == 0 )
1278 ContinueState = ProcessKeyPress( &theEvent );
1279 if ( !ContinueState ) {
1280 return( ContinueState );
1284 if ( theEvent.xbutton.button == 3 )
1295 /* Internal Error */
1299 return( ContinueState );
1303 void ProcessNeko(void) {
1304 struct itimerval Value;
1306 EventState = NORMAL_STATE;
1308 NekoX = ( WindowWidth - BITMAP_WIDTH / 2 ) / 2;
1309 NekoY = ( WindowHeight - BITMAP_HEIGHT / 2 ) / 2;
1314 SetNekoState( NEKO_STOP );
1316 timerclear( &Value.it_interval );
1317 timerclear( &Value.it_value );
1319 Value.it_interval.tv_usec = IntervalTime;
1320 Value.it_value.tv_usec = IntervalTime;
1322 setitimer( ITIMER_REAL, &Value, 0 );
1326 } while ( ProcessEvent() );
1332 EventState = DEBUG_LIST;
1334 fprintf( stderr, "\n" );
1335 fprintf( stderr, "G-0lMw$rI=<($7$^$9!#(Quit !D Alt-Q)\n" );
1336 fprintf( stderr, "\n" );
1338 XSelectInput( theDisplay, theWindow, EVENT_MASK );
1340 while ( ProcessEvent() );
1344 void NekoMoveTest() {
1345 struct itimerval Value;
1347 EventState = DEBUG_MOVE;
1349 NekoX = ( WindowWidth - BITMAP_WIDTH / 2 ) / 2;
1350 NekoY = ( WindowHeight - BITMAP_HEIGHT / 2 ) / 2;
1355 SetNekoState( NEKO_STOP );
1357 timerclear( &Value.it_interval );
1358 timerclear( &Value.it_value );
1360 Value.it_interval.tv_usec = IntervalTime;
1361 Value.it_value.tv_usec = IntervalTime;
1363 setitimer( ITIMER_REAL, &Value, 0 );
1365 fprintf( stderr, "\n" );
1366 fprintf( stderr, "G-$N0\F0%F%9%H$r9T$$$^$9!#(Quit !D Alt-Q)\n" );
1367 fprintf( stderr, "\n" );
1368 fprintf( stderr, "\t%-!<%Q%C%I>e$N%F%s%-!<$GG-$r0\F0$5$;$F2<$5$$!#\n" );
1369 fprintf( stderr, "\t(M-8z$J%-!<$O#1!A#9$G$9!#)\n" );
1370 fprintf( stderr, "\n" );
1374 } while ( ProcessEvent() );
1378 void ProcessDebugMenu() {
1379 int UserSelectNo = 0;
1380 char UserAnswer[ BUFSIZ ];
1382 fprintf( stderr, "\n" );
1383 fprintf( stderr, "!Zxneko %G%P%C%0%a%K%e!<![\n" );
1385 while ( !( UserSelectNo >= 1 && UserSelectNo <= 2 ) ) {
1386 fprintf( stderr, "\n" );
1387 fprintf( stderr, "\t1)!!G-%-%c%i%/%?!<0lMwI=<(\n" );
1388 fprintf( stderr, "\t2)!!G-0\F0%F%9%H\n" );
1389 fprintf( stderr, "\n" );
1390 fprintf( stderr, "Select: " );
1392 fgets( UserAnswer, sizeof( UserAnswer ), stdin );
1394 UserSelectNo = atoi( UserAnswer );
1396 if ( !( UserSelectNo >= 1 && UserSelectNo <= 2 ) ) {
1397 fprintf( stderr, "\n" );
1398 fprintf( stderr, "@5$7$$HV9f$rA*Br$7$F2<$5$$!#\n" );
1402 switch ( UserSelectNo ) {
1410 /* Internal Error */
1414 fprintf( stderr, "%F%9%H=*N;!#\n" );
1415 fprintf( stderr, "\n" );
1420 void NullFunction(int ignored)
1422 /* signal( SIGALRM, NullFunction ); */
1428 "Usage: %s [-display <display>] [-geometry <geometry>] \\\n",
1430 fprintf( stderr, "\t[-bg <background>] [-fg <foreground>] \\\n" );
1431 fprintf( stderr, "\t[-title <title>] [-name <title>] [-iconic] \\\n" );
1432 fprintf( stderr, "\t[-speed <speed>] [-time <time>] [-root] [-help]\n" );
1437 GetArguments( int argc, char *argv[],
1438 char *theDisplayName, char *theGeometry, char **theTitle,
1439 double *NekoSpeed, long *IntervalTime )
1444 theDisplayName[ 0 ] = '\0';
1445 theGeometry[ 0 ] = '\0';
1447 iconicState = False;
1449 for ( ArgCounter = 0; ArgCounter < argc; ArgCounter++ ) {
1450 if ( strncmp( argv[ ArgCounter ], "-h", 2 ) == 0 ) {
1453 } else if ( strcmp( argv[ ArgCounter ], "-display" ) == 0 ) {
1455 if ( ArgCounter < argc ) {
1456 strcpy( theDisplayName, argv[ ArgCounter ] );
1458 fprintf( stderr, "%s: -display option error.\n", ProgramName );
1461 } else if ( strncmp( argv[ ArgCounter ], "-geom", 5 ) == 0 ) {
1463 if ( ArgCounter < argc ) {
1464 strcpy( theGeometry, argv[ ArgCounter ] );
1467 "%s: -geometry option error.\n", ProgramName );
1470 } else if ( ( strcmp( argv[ ArgCounter ], "-title" ) == 0 )
1471 || ( strcmp( argv[ ArgCounter ], "-name" ) == 0 ) ) {
1473 if ( ArgCounter < argc ) {
1474 *theTitle = argv[ ArgCounter ];
1476 fprintf( stderr, "%s: -title option error.\n", ProgramName );
1479 } else if ( strcmp( argv[ ArgCounter ], "-iconic" ) == 0 ) {
1481 } else if ( strcmp( argv[ ArgCounter ], "-speed" ) == 0 ) {
1483 if ( ArgCounter < argc ) {
1484 *NekoSpeed = atof( argv[ ArgCounter ] );
1486 fprintf( stderr, "%s: -speed option error.\n", ProgramName );
1489 } else if ( strcmp( argv[ ArgCounter ], "-fg" ) == 0 ) {
1491 if ( ArgCounter < argc ) {
1492 fgColor = argv[ArgCounter];
1494 fprintf( stderr, "%s: -fg option error.\n", ProgramName );
1497 } else if ( strcmp( argv[ ArgCounter ], "-bg" ) == 0 ) {
1499 if ( ArgCounter < argc ) {
1500 bgColor = argv[ArgCounter];
1502 fprintf( stderr, "%s: -bg option error.\n", ProgramName );
1505 } else if ( strcmp( argv[ ArgCounter ], "-time" ) == 0 ) {
1507 if ( ArgCounter < argc ) {
1508 *IntervalTime = atol( argv[ ArgCounter ] );
1510 fprintf( stderr, "%s: -time option error.\n", ProgramName );
1513 } else if ( strcmp( argv[ ArgCounter ], "-root" ) == 0 ) {
1517 "%s: Unknown option \"%s\".\n", ProgramName,
1518 argv[ ArgCounter ] );
1524 return( iconicState );
1527 void UndefineCursor( xcb_connection_t *c, xcb_window_t w)
1529 uint32_t none[] = { XCB_NONE };
1530 xcb_change_window_attributes( c, w, XCB_CW_CURSOR, none );
1534 main( int argc, char *argv[] )
1537 char theDisplayName[ DIRNAMELEN ];
1538 char theGeometry[ DIRNAMELEN ];
1539 char *theTitle = "";
1541 ProgramName = argv[ 0 ];
1547 fgColor = bgColor = (char *) NULL;
1549 iconicState = GetArguments( argc, argv, theDisplayName, theGeometry,
1550 &theTitle, &NekoSpeed, &IntervalTime );
1552 if (theTitle[0] == 0) theTitle = ProgramName;
1553 InitScreen( theDisplayName, theGeometry, theTitle, iconicState );
1555 signal( SIGALRM, NullFunction );
1557 SinPiPer8Times3 = sin( PI_PER8 * (double)3 );
1558 SinPiPer8 = sin( PI_PER8 );
1566 UndefineCursor( xc, theWindow );
1567 xcb_disconnect( xc );