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 set_wm_protocols( xc, theWindow, 1, &deleteWindowAtom );
685 theIconPixmap = CreateBitmapFromData( xc, theWindow,
686 icon_bits, icon_width, icon_height );
688 wm_hints_t *theWMHints = alloc_wm_hints();
690 wm_hints_set_icon_pixmap( theWMHints, theIconPixmap );
693 wm_hints_set_iconic( theWMHints );
695 wm_hints_set_normal( theWMHints );
697 set_wm_hints( xc, theWindow, theWMHints);
701 /* why hide the structure? */
702 size_hints_t *theSizeHints = alloc_size_hints();
704 /* need enum for second param (user specified) */
705 size_hints_set_position(theSizeHints, 0, WindowPointX, WindowPointY);
706 size_hints_set_size(theSizeHints, 0, WindowWidth, WindowHeight);
708 set_wm_normal_hints(xc, theWindow, theSizeHints);
710 free_size_hints(theSizeHints);
712 set_wm_name( xc, theWindow, STRING, strlen(theTitle), theTitle );
713 set_wm_icon_name( xc, theWindow, STRING, strlen(theTitle), theTitle );
715 xcb_map_window( xc, theWindow );
723 /* latency: ask for keysyms now, and receive them later */
724 theKeySyms = xcb_key_symbols_alloc( xc );
726 /* later: xcb_key_symbols_free( keysyms ); */
727 /* later: xcb_refresh_keyboard_mapping ( keysyms, mappingEvent ); */
731 void Interval(void) {
736 void TickCount(void) {
737 if ( ++NekoTickCount >= MAX_TICK )
740 if ( NekoTickCount % 2 == 0 )
741 if ( NekoStateCount < MAX_TICK )
747 SetNekoState( int SetValue )
752 NekoState = SetValue;
755 switch ( NekoState ) {
765 NekoMoveDx = NekoMoveDy = 0;
774 /* Xlib does merging of requests, but the Flush and frequent DrawGC changes
775 defeat this mechanism */
778 DrawNeko( int x, int y, xcb_gcontext_t DrawGC )
780 xcb_rectangle_t rect = { NekoLastX, NekoLastY, BITMAP_WIDTH, BITMAP_HEIGHT };
782 if ( (x != NekoLastX || y != NekoLastY) && (EventState != DEBUG_LIST) )
784 xcb_poly_fill_rectangle( xc, theWindow, SpaceGC, 1, &rect );
785 rect.x = x; rect.y = y;
789 uint32_t originMask = XCB_GC_TILE_STIPPLE_ORIGIN_X | XCB_GC_TILE_STIPPLE_ORIGIN_Y;
790 uint32_t origin[2] = { x, y };
791 xcb_change_gc( xc, DrawGC, originMask, origin );
792 /* XSetTSOrigin( theDisplay, DrawGC, x, y ); */
794 xcb_poly_fill_rectangle( xc, theWindow, DrawGC, 1, &rect );
805 void RedrawNeko(void) {
806 xcb_rectangle_t rect = { NekoLastX, NekoLastY, BITMAP_WIDTH, BITMAP_HEIGHT };
808 xcb_poly_fill_rectangle( xc, theWindow, NekoLastGC, 1, &rect );
815 void NekoDirection(void) {
817 double LargeX, LargeY;
821 if ( NekoMoveDx == 0 && NekoMoveDy == 0 ) {
822 NewState = NEKO_STOP;
824 LargeX = (double)NekoMoveDx;
825 LargeY = (double)(-NekoMoveDy);
826 Length = sqrt( LargeX * LargeX + LargeY * LargeY );
827 SinTheta = LargeY / Length;
829 if ( NekoMoveDx > 0 ) {
830 if ( SinTheta > SinPiPer8Times3 ) {
831 NewState = NEKO_U_MOVE;
832 } else if ( ( SinTheta <= SinPiPer8Times3 )
833 && ( SinTheta > SinPiPer8 ) ) {
834 NewState = NEKO_UR_MOVE;
835 } else if ( ( SinTheta <= SinPiPer8 )
836 && ( SinTheta > -( SinPiPer8 ) ) ) {
837 NewState = NEKO_R_MOVE;
838 } else if ( ( SinTheta <= -( SinPiPer8 ) )
839 && ( SinTheta > -( SinPiPer8Times3 ) ) ) {
840 NewState = NEKO_DR_MOVE;
842 NewState = NEKO_D_MOVE;
845 if ( SinTheta > SinPiPer8Times3 ) {
846 NewState = NEKO_U_MOVE;
847 } else if ( ( SinTheta <= SinPiPer8Times3 )
848 && ( SinTheta > SinPiPer8 ) ) {
849 NewState = NEKO_UL_MOVE;
850 } else if ( ( SinTheta <= SinPiPer8 )
851 && ( SinTheta > -( SinPiPer8 ) ) ) {
852 NewState = NEKO_L_MOVE;
853 } else if ( ( SinTheta <= -( SinPiPer8 ) )
854 && ( SinTheta > -( SinPiPer8Times3 ) ) ) {
855 NewState = NEKO_DL_MOVE;
857 NewState = NEKO_D_MOVE;
862 if ( NekoState != NewState ) {
863 SetNekoState( NewState );
868 Bool IsWindowOver(void) {
869 Bool ReturnValue = False;
874 } else if ( NekoY >= WindowHeight - BITMAP_HEIGHT ) {
875 NekoY = WindowHeight - BITMAP_HEIGHT;
881 } else if ( NekoX >= WindowWidth - BITMAP_WIDTH ) {
882 NekoX = WindowWidth - BITMAP_WIDTH;
886 return( ReturnValue );
890 Bool IsNekoDontMove(void) {
891 return( NekoX == NekoLastX && NekoY == NekoLastY );
895 Bool IsNekoMoveStart(void) {
897 if ( (PrevMouseX >= MouseX - IDLE_SPACE
898 && PrevMouseX <= MouseX + IDLE_SPACE) &&
899 (PrevMouseY >= MouseY - IDLE_SPACE
900 && PrevMouseY <= MouseY + IDLE_SPACE) )
905 if ( NekoMoveDx == 0 && NekoMoveDy == 0 )
913 void CalcDxDy(void) {
914 int RelativeX, RelativeY;
915 double LargeX, LargeY;
916 double DoubleLength, Length;
918 /* TODO: replace query with pointer motion notification? */
920 xcb_query_pointer_reply_t *reply = xcb_query_pointer_reply( xc,
921 xcb_query_pointer( xc, theWindow ), NULL);
923 RelativeX = reply->win_x;
924 RelativeY = reply->win_y;
934 LargeX = (double)( MouseX - NekoX - BITMAP_WIDTH / 2 );
935 LargeY = (double)( MouseY - NekoY - BITMAP_HEIGHT );
937 DoubleLength = LargeX * LargeX + LargeY * LargeY;
939 if ( DoubleLength != (double)0 ) {
940 Length = sqrt( DoubleLength );
941 if ( Length <= NekoSpeed ) {
942 NekoMoveDx = (int)LargeX;
943 NekoMoveDy = (int)LargeY;
945 NekoMoveDx = (int)( ( NekoSpeed * LargeX ) / Length );
946 NekoMoveDy = (int)( ( NekoSpeed * LargeY ) / Length );
949 NekoMoveDx = NekoMoveDy = 0;
954 void NekoThinkDraw(void) {
959 if ( NekoState != NEKO_SLEEP ) {
960 DrawNeko( NekoX, NekoY,
961 NekoTickCount % 2 == 0 ?
962 *(AnimationPattern[ NekoState ].TickEvenGCPtr) :
963 *(AnimationPattern[ NekoState ].TickOddGCPtr) );
965 DrawNeko( NekoX, NekoY,
966 NekoTickCount % 8 <= 3 ?
967 *(AnimationPattern[ NekoState ].TickEvenGCPtr) :
968 *(AnimationPattern[ NekoState ].TickOddGCPtr) );
973 switch ( NekoState ) {
975 if ( IsNekoMoveStart() ) {
976 SetNekoState( NEKO_AWAKE );
979 if ( NekoStateCount < NEKO_STOP_TIME ) {
982 if ( NekoMoveDx < 0 && NekoX <= 0 ) {
983 SetNekoState( NEKO_L_TOGI );
984 } else if ( NekoMoveDx > 0 && NekoX >= WindowWidth - BITMAP_WIDTH ) {
985 SetNekoState( NEKO_R_TOGI );
986 } else if ( NekoMoveDy < 0 && NekoY <= 0 ) {
987 SetNekoState( NEKO_U_TOGI );
988 } else if ( NekoMoveDy > 0 && NekoY >= WindowHeight - BITMAP_HEIGHT ) {
989 SetNekoState( NEKO_D_TOGI );
991 SetNekoState( NEKO_JARE );
995 if ( IsNekoMoveStart() ) {
996 SetNekoState( NEKO_AWAKE );
999 if ( NekoStateCount < NEKO_JARE_TIME ) {
1002 SetNekoState( NEKO_KAKI );
1005 if ( IsNekoMoveStart() ) {
1006 SetNekoState( NEKO_AWAKE );
1009 if ( NekoStateCount < NEKO_KAKI_TIME ) {
1012 SetNekoState( NEKO_AKUBI );
1015 if ( IsNekoMoveStart() ) {
1016 SetNekoState( NEKO_AWAKE );
1019 if ( NekoStateCount < NEKO_AKUBI_TIME ) {
1022 SetNekoState( NEKO_SLEEP );
1025 if ( IsNekoMoveStart() ) {
1026 SetNekoState( NEKO_AWAKE );
1031 if ( NekoStateCount < NEKO_AWAKE_TIME ) {
1044 NekoX += NekoMoveDx;
1045 NekoY += NekoMoveDy;
1047 if ( IsWindowOver() ) {
1048 if ( IsNekoDontMove() ) {
1049 SetNekoState( NEKO_STOP );
1057 if ( IsNekoMoveStart() ) {
1058 SetNekoState( NEKO_AWAKE );
1061 if ( NekoStateCount < NEKO_TOGI_TIME ) {
1064 SetNekoState( NEKO_KAKI );
1067 /* Internal Error */
1068 SetNekoState( NEKO_STOP );
1077 void DisplayCharacters() {
1081 for ( Index = 0, x = 0, y = 0;
1082 BitmapGCDataTable[ Index ].GCCreatePtr != NULL; Index++ ) {
1084 DrawNeko( x, y, *(BitmapGCDataTable[ Index ].GCCreatePtr) );
1085 XFlush( theDisplay );
1089 if ( x > WindowWidth - BITMAP_WIDTH ) {
1092 if ( y > WindowHeight - BITMAP_HEIGHT) {
1102 ProcessKeyPress( xcb_key_press_event_t *theKeyEvent )
1104 Bool ReturnState = True;
1106 /* quit on Meta-Q (Alt-Q) */
1107 xcb_keysym_t theKeySym;
1109 /* last param is "int col". What? add enumeration to xcb_keysyms.h */
1110 theKeySym = xcb_key_press_lookup_keysym( theKeySyms, theKeyEvent, 1 );
1112 /* KeySym XK_Q == 'Q' */
1113 if (theKeySym == 'Q' && (theKeyEvent->state & XCB_MOD_MASK_1))
1114 ReturnState = False;
1117 if ( EventState == DEBUG_MOVE ) {
1118 switch ( theKeySym ) {
1120 NekoMoveDx = -(int)( NekoSpeed / sqrt( (double)2 ) );
1121 NekoMoveDy = -NekoMoveDx;
1125 NekoMoveDy = (int)NekoSpeed;
1128 NekoMoveDx = (int)( NekoSpeed / sqrt( (double)2 ) );
1129 NekoMoveDy = NekoMoveDx;
1132 NekoMoveDx = -(int)NekoSpeed;
1140 NekoMoveDx = (int)NekoSpeed;
1144 NekoMoveDx = -(int)( NekoSpeed / sqrt( (double)2 ) );
1145 NekoMoveDy = NekoMoveDx;
1149 NekoMoveDy = -(int)NekoSpeed;
1152 NekoMoveDx = (int)( NekoSpeed / sqrt( (double)2 ) );
1153 NekoMoveDy = -NekoMoveDx;
1159 return( ReturnState );
1163 void NekoAdjust(void) {
1166 else if ( NekoX > WindowWidth - BITMAP_WIDTH )
1167 NekoX = WindowWidth - BITMAP_WIDTH;
1171 else if ( NekoY > WindowHeight - BITMAP_HEIGHT )
1172 NekoY = WindowHeight - BITMAP_HEIGHT;
1175 int IsDeleteMessage(xcb_client_message_event_t *msg)
1177 return msg->data.data32[0] == deleteWindowAtom;
1180 Bool ProcessEvent(void) {
1181 xcb_generic_event_t *theEvent;
1182 xcb_configure_notify_event_t *theConfigureNotification;
1183 xcb_expose_event_t *theExposure;
1184 xcb_button_press_event_t *theButtonPress;
1185 Bool ContinueState = True;
1187 switch ( EventState ) {
1189 while ( ContinueState &&
1190 NULL != (theEvent = xcb_poll_for_event( xc )) ) { /*while ( XCheckMaskEvent( theDisplay, EVENT_MASK, &theEvent ) ) {*/
1191 switch ( theEvent->response_type & 0x7f ) {
1192 case XCB_CONFIGURE_NOTIFY:
1193 theConfigureNotification = (xcb_configure_notify_event_t *)theEvent;
1194 WindowWidth = theConfigureNotification->width;
1195 WindowHeight = theConfigureNotification->height;
1196 WindowPointX = theConfigureNotification->x;
1197 WindowPointY = theConfigureNotification->y;
1198 BorderWidth = theConfigureNotification->border_width;
1202 theExposure = (xcb_expose_event_t *)theEvent;
1203 if ( theExposure->count == 0 )
1206 case XCB_MAP_NOTIFY:
1210 ContinueState = ProcessKeyPress( (xcb_key_press_event_t *)theEvent );
1212 case XCB_BUTTON_PRESS:
1213 theButtonPress = (xcb_button_press_event_t *)theEvent;
1214 ContinueState = ( theButtonPress->detail != 3 ); /* xbutton.button */
1216 /* new: handle ClientMessage */
1217 case XCB_CLIENT_MESSAGE:
1218 ContinueState = !IsDeleteMessage((xcb_client_message_event_t *)theEvent);
1222 /*printf("event type:%x\n", (int)theEvent->response_type);*/
1230 XNextEvent( theDisplay, &theEvent );
1231 switch ( theEvent.type ) {
1232 case ConfigureNotify:
1233 WindowWidth = theEvent.xconfigure.width;
1234 WindowHeight = theEvent.xconfigure.height;
1235 WindowPointX = theEvent.xconfigure.x;
1236 WindowPointY = theEvent.xconfigure.y;
1237 BorderWidth = theEvent.xconfigure.border_width;
1240 if ( theEvent.xexpose.count == 0 )
1241 DisplayCharacters();
1244 DisplayCharacters();
1247 ContinueState = ProcessKeyPress( &theEvent );
1250 if ( theEvent.xbutton.button == 3 )
1259 while ( XCheckMaskEvent( theDisplay, EVENT_MASK, &theEvent ) ) {
1260 switch ( theEvent.type ) {
1261 case ConfigureNotify:
1262 WindowWidth = theEvent.xconfigure.width;
1263 WindowHeight = theEvent.xconfigure.height;
1264 WindowPointX = theEvent.xconfigure.x;
1265 WindowPointY = theEvent.xconfigure.y;
1266 BorderWidth = theEvent.xconfigure.border_width;
1270 if ( theEvent.xexpose.count == 0 )
1277 ContinueState = ProcessKeyPress( &theEvent );
1278 if ( !ContinueState ) {
1279 return( ContinueState );
1283 if ( theEvent.xbutton.button == 3 )
1294 /* Internal Error */
1298 return( ContinueState );
1302 void ProcessNeko(void) {
1303 struct itimerval Value;
1305 EventState = NORMAL_STATE;
1307 NekoX = ( WindowWidth - BITMAP_WIDTH / 2 ) / 2;
1308 NekoY = ( WindowHeight - BITMAP_HEIGHT / 2 ) / 2;
1313 SetNekoState( NEKO_STOP );
1315 timerclear( &Value.it_interval );
1316 timerclear( &Value.it_value );
1318 Value.it_interval.tv_usec = IntervalTime;
1319 Value.it_value.tv_usec = IntervalTime;
1321 setitimer( ITIMER_REAL, &Value, 0 );
1325 } while ( ProcessEvent() );
1331 EventState = DEBUG_LIST;
1333 fprintf( stderr, "\n" );
1334 fprintf( stderr, "G-0lMw$rI=<($7$^$9!#(Quit !D Alt-Q)\n" );
1335 fprintf( stderr, "\n" );
1337 XSelectInput( theDisplay, theWindow, EVENT_MASK );
1339 while ( ProcessEvent() );
1343 void NekoMoveTest() {
1344 struct itimerval Value;
1346 EventState = DEBUG_MOVE;
1348 NekoX = ( WindowWidth - BITMAP_WIDTH / 2 ) / 2;
1349 NekoY = ( WindowHeight - BITMAP_HEIGHT / 2 ) / 2;
1354 SetNekoState( NEKO_STOP );
1356 timerclear( &Value.it_interval );
1357 timerclear( &Value.it_value );
1359 Value.it_interval.tv_usec = IntervalTime;
1360 Value.it_value.tv_usec = IntervalTime;
1362 setitimer( ITIMER_REAL, &Value, 0 );
1364 fprintf( stderr, "\n" );
1365 fprintf( stderr, "G-$N0\F0%F%9%H$r9T$$$^$9!#(Quit !D Alt-Q)\n" );
1366 fprintf( stderr, "\n" );
1367 fprintf( stderr, "\t%-!<%Q%C%I>e$N%F%s%-!<$GG-$r0\F0$5$;$F2<$5$$!#\n" );
1368 fprintf( stderr, "\t(M-8z$J%-!<$O#1!A#9$G$9!#)\n" );
1369 fprintf( stderr, "\n" );
1373 } while ( ProcessEvent() );
1377 void ProcessDebugMenu() {
1378 int UserSelectNo = 0;
1379 char UserAnswer[ BUFSIZ ];
1381 fprintf( stderr, "\n" );
1382 fprintf( stderr, "!Zxneko %G%P%C%0%a%K%e!<![\n" );
1384 while ( !( UserSelectNo >= 1 && UserSelectNo <= 2 ) ) {
1385 fprintf( stderr, "\n" );
1386 fprintf( stderr, "\t1)!!G-%-%c%i%/%?!<0lMwI=<(\n" );
1387 fprintf( stderr, "\t2)!!G-0\F0%F%9%H\n" );
1388 fprintf( stderr, "\n" );
1389 fprintf( stderr, "Select: " );
1391 fgets( UserAnswer, sizeof( UserAnswer ), stdin );
1393 UserSelectNo = atoi( UserAnswer );
1395 if ( !( UserSelectNo >= 1 && UserSelectNo <= 2 ) ) {
1396 fprintf( stderr, "\n" );
1397 fprintf( stderr, "@5$7$$HV9f$rA*Br$7$F2<$5$$!#\n" );
1401 switch ( UserSelectNo ) {
1409 /* Internal Error */
1413 fprintf( stderr, "%F%9%H=*N;!#\n" );
1414 fprintf( stderr, "\n" );
1419 void NullFunction(int ignored)
1421 /* signal( SIGALRM, NullFunction ); */
1427 "Usage: %s [-display <display>] [-geometry <geometry>] \\\n",
1429 fprintf( stderr, "\t[-bg <background>] [-fg <foreground>] \\\n" );
1430 fprintf( stderr, "\t[-title <title>] [-name <title>] [-iconic] \\\n" );
1431 fprintf( stderr, "\t[-speed <speed>] [-time <time>] [-root] [-help]\n" );
1436 GetArguments( int argc, char *argv[],
1437 char *theDisplayName, char *theGeometry, char **theTitle,
1438 double *NekoSpeed, long *IntervalTime )
1443 theDisplayName[ 0 ] = '\0';
1444 theGeometry[ 0 ] = '\0';
1446 iconicState = False;
1448 for ( ArgCounter = 0; ArgCounter < argc; ArgCounter++ ) {
1449 if ( strncmp( argv[ ArgCounter ], "-h", 2 ) == 0 ) {
1452 } else if ( strcmp( argv[ ArgCounter ], "-display" ) == 0 ) {
1454 if ( ArgCounter < argc ) {
1455 strcpy( theDisplayName, argv[ ArgCounter ] );
1457 fprintf( stderr, "%s: -display option error.\n", ProgramName );
1460 } else if ( strncmp( argv[ ArgCounter ], "-geom", 5 ) == 0 ) {
1462 if ( ArgCounter < argc ) {
1463 strcpy( theGeometry, argv[ ArgCounter ] );
1466 "%s: -geometry option error.\n", ProgramName );
1469 } else if ( ( strcmp( argv[ ArgCounter ], "-title" ) == 0 )
1470 || ( strcmp( argv[ ArgCounter ], "-name" ) == 0 ) ) {
1472 if ( ArgCounter < argc ) {
1473 *theTitle = argv[ ArgCounter ];
1475 fprintf( stderr, "%s: -title option error.\n", ProgramName );
1478 } else if ( strcmp( argv[ ArgCounter ], "-iconic" ) == 0 ) {
1480 } else if ( strcmp( argv[ ArgCounter ], "-speed" ) == 0 ) {
1482 if ( ArgCounter < argc ) {
1483 *NekoSpeed = atof( argv[ ArgCounter ] );
1485 fprintf( stderr, "%s: -speed option error.\n", ProgramName );
1488 } else if ( strcmp( argv[ ArgCounter ], "-fg" ) == 0 ) {
1490 if ( ArgCounter < argc ) {
1491 fgColor = argv[ArgCounter];
1493 fprintf( stderr, "%s: -fg option error.\n", ProgramName );
1496 } else if ( strcmp( argv[ ArgCounter ], "-bg" ) == 0 ) {
1498 if ( ArgCounter < argc ) {
1499 bgColor = argv[ArgCounter];
1501 fprintf( stderr, "%s: -bg option error.\n", ProgramName );
1504 } else if ( strcmp( argv[ ArgCounter ], "-time" ) == 0 ) {
1506 if ( ArgCounter < argc ) {
1507 *IntervalTime = atol( argv[ ArgCounter ] );
1509 fprintf( stderr, "%s: -time option error.\n", ProgramName );
1512 } else if ( strcmp( argv[ ArgCounter ], "-root" ) == 0 ) {
1516 "%s: Unknown option \"%s\".\n", ProgramName,
1517 argv[ ArgCounter ] );
1523 return( iconicState );
1526 void UndefineCursor( xcb_connection_t *c, xcb_window_t w)
1528 uint32_t none[] = { XCB_NONE };
1529 xcb_change_window_attributes( c, w, XCB_CW_CURSOR, none );
1533 main( int argc, char *argv[] )
1536 char theDisplayName[ DIRNAMELEN ];
1537 char theGeometry[ DIRNAMELEN ];
1538 char *theTitle = "";
1540 ProgramName = argv[ 0 ];
1546 fgColor = bgColor = (char *) NULL;
1548 iconicState = GetArguments( argc, argv, theDisplayName, theGeometry,
1549 &theTitle, &NekoSpeed, &IntervalTime );
1551 if (theTitle[0] == 0) theTitle = ProgramName;
1552 InitScreen( theDisplayName, theGeometry, theTitle, iconicState );
1554 signal( SIGALRM, NullFunction );
1556 SinPiPer8Times3 = sin( PI_PER8 * (double)3 );
1557 SinPiPer8 = sin( PI_PER8 );
1565 UndefineCursor( xc, theWindow );
1566 xcb_disconnect( xc );