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 */
25 #include <X11/XCB/xcb.h>
26 /*#include <X11/XCB/xcb_image.h>*/
27 #include <X11/XCB/xcb_aux.h> /* XCBAuxGetScreen */
28 #include <X11/XCB/xcb_icccm.h>
29 #include <X11/XCB/xcb_atom.h> /* STRING atom */
30 #include <X11/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 ( XCBEventMaskKeyPress | XCBEventMaskButtonPress | \
97 XCBEventMaskExposure | XCBEventMaskStructureNotify )
99 #define EVENT_MASK_ROOT ( XCBEventMaskKeyPress | XCBEventMaskExposure )
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;
145 XCBSCREEN *theScreen; /* instead of macro(theDisplay, int theScreen) */
146 unsigned long theBlackPixel;
147 unsigned long theWhitePixel;
150 XCBKeySymbols *theKeySyms;
151 XCBATOM 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 XCBGCONTEXT NekoLastGC;
184 double NekoSpeed = (double)NEKO_SPEED;
186 double SinPiPer8Times3;
209 XCBPIXMAP UpLeft1Xbm;
210 XCBPIXMAP UpLeft2Xbm;
211 XCBPIXMAP UpRight1Xbm;
212 XCBPIXMAP UpRight2Xbm;
213 XCBPIXMAP DownLeft1Xbm;
214 XCBPIXMAP DownLeft2Xbm;
215 XCBPIXMAP DownRight1Xbm;
216 XCBPIXMAP DownRight2Xbm;
218 XCBPIXMAP UpTogi1Xbm;
219 XCBPIXMAP UpTogi2Xbm;
220 XCBPIXMAP DownTogi1Xbm;
221 XCBPIXMAP DownTogi2Xbm;
222 XCBPIXMAP LeftTogi1Xbm;
223 XCBPIXMAP LeftTogi2Xbm;
224 XCBPIXMAP RightTogi1Xbm;
225 XCBPIXMAP RightTogi2Xbm;
234 XCBGCONTEXT Sleep1GC;
235 XCBGCONTEXT Sleep2GC;
245 XCBGCONTEXT Right1GC;
246 XCBGCONTEXT Right2GC;
247 XCBGCONTEXT UpLeft1GC;
248 XCBGCONTEXT UpLeft2GC;
249 XCBGCONTEXT UpRight1GC;
250 XCBGCONTEXT UpRight2GC;
251 XCBGCONTEXT DownLeft1GC;
252 XCBGCONTEXT DownLeft2GC;
253 XCBGCONTEXT DownRight1GC;
254 XCBGCONTEXT DownRight2GC;
256 XCBGCONTEXT UpTogi1GC;
257 XCBGCONTEXT UpTogi2GC;
258 XCBGCONTEXT DownTogi1GC;
259 XCBGCONTEXT DownTogi2GC;
260 XCBGCONTEXT LeftTogi1GC;
261 XCBGCONTEXT LeftTogi2GC;
262 XCBGCONTEXT RightTogi1GC;
263 XCBGCONTEXT RightTogi2GC;
266 XCBGCONTEXT *GCCreatePtr;
267 XCBPIXMAP *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 XCBGCONTEXT *TickEvenGCPtr;
318 XCBGCONTEXT *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 XCBPIXMAP CreatePixmapFromBitmapData( XCBConnection *c,
403 XCBWINDOW window, char *data, CARD16 w, CARD16 h,
404 CARD32 fg, CARD32 bg, CARD32 depth)
406 XCBDRAWABLE drawable;
407 XCBPIXMAP bitmap = XCBPIXMAPNew( c );
409 drawable.window = window;
410 XCBCreatePixmap( c, depth, bitmap, drawable, w, h );
412 XCBGCONTEXT gc = XCBGCONTEXTNew( c );
414 CARD32 mask = (depth==1 ? 0 : XCBGCForeground | XCBGCBackground);
415 CARD32 values[] = { fg, bg };
417 drawable.pixmap = bitmap;
418 XCBCreateGC( 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 = XCBGetSetup(c)->bitmap_format_scanline_pad;
428 long bpd = ROUNDUP(w, pad)>>3;
429 long bufLen = bpd * h;
431 if (XCBGetSetup(c)->bitmap_format_scanline_unit == 32 &&
432 XCBGetSetup(c)->bitmap_format_bit_order == XCBImageOrderMSBFirst &&
433 XCBGetSetup(c)->image_byte_order == XCBImageOrderMSBFirst)
435 SwapBits((unsigned char *)data, buf, bpl, bpl, bpd, h);
440 BYTE *src = (BYTE *)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 CARD8 format = (depth==1 ? XCBImageFormatXYPixmap : XCBImageFormatXYBitmap);
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 XCBPutImage( c, format, drawable, gc,
458 0, 1, /* left_pad, depth */
462 XCBGenericError *error = NULL;
463 XCBSync( c, &error );
465 printf("error code %d", (int)error->error_code);
472 /* later: XCBFreePixmap( c, bitmap ); */
476 XCBPIXMAP CreateBitmapFromData(XCBConnection *c, XCBWINDOW window,
477 char *data, CARD16 w, CARD16 h)
480 return CreatePixmapFromBitmapData(c, window, data, w, h, 0, 0, depth);
483 void InitBitmapAndGCs(void) {
484 BitmapGCData *BitmapGCDataTablePtr;
485 CARD32 theGCValues[5];
486 XCBDRAWABLE drawable; drawable.window = theWindow;
488 theGCValues[0] = XCBGXcopy;
490 theGCValues[1] = theBlackPixel;
491 theGCValues[2] = theWhitePixel;
493 theGCValues[3] = XCBFillStyleTiled;
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 theBlackPixel, theWhitePixel, theScreen->root_depth);
508 theGCValues[4] = BitmapGCDataTablePtr->BitmapCreatePtr->xid; /* tile */
510 *(BitmapGCDataTablePtr->GCCreatePtr) = XCBGCONTEXTNew( xc );
511 XCBCreateGC( xc, *(BitmapGCDataTablePtr->GCCreatePtr), drawable,
512 XCBGCFunction | XCBGCForeground | XCBGCBackground |
513 XCBGCFillStyle | XCBGCTile,
517 /* later: XCBFreePixmap( c, bitmap ); */
518 /* later: XCBFreeGC( c, gc ); */
522 GetAtom(XCBConnection *c, const char *atomName)
524 XCBATOM atom = { XCBNone };
525 XCBInternAtomRep *r = XCBInternAtomReply(c,
526 XCBInternAtom(c, 0, strlen(atomName), atomName), NULL);
535 InitScreen( char *DisplayName, char *theGeometry, char *theTitle, Bool iconicState )
537 XCBPIXMAP theCursorSource;
538 XCBPIXMAP theCursorMask;
539 unsigned int theDepth;
540 XCBCOLORMAP theColormap;
543 if ( ( xc = XCBConnect( 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 = XCBAuxGetScreen(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 XCBAllocNamedColorCookie bgCookie = XCBAllocNamedColor ( xc,
590 theColormap, strlen(bgColor), bgColor );
592 XCBAllocNamedColorCookie fgCookie = XCBAllocNamedColor ( xc,
593 theColormap, strlen(fgColor), fgColor );
595 XCBAllocNamedColorRep *bgRep = XCBAllocNamedColorReply( xc, bgCookie, 0 );
598 "%s: Can't allocate the background color %s.\n", ProgramName, bgColor );
601 theWhitePixel = bgRep->pixel;
603 XCBAllocNamedColorRep *fgRep = XCBAllocNamedColorReply( xc, fgCookie, 0 );
606 "%s: Can't allocate the foreground color %s.\n", ProgramName, fgColor );
609 theBlackPixel = fgRep->pixel;
611 theCursor = XCBCURSORNew( xc );
612 XCBCreateCursor ( xc, theCursor, theCursorSource, theCursorMask,
613 fgRep->visual_red, fgRep->visual_green, fgRep->visual_blue,
614 bgRep->visual_red, bgRep->visual_green, bgRep->visual_blue,
615 cursor_x_hot, cursor_y_hot );
621 CARD32 rootAttributes[] = { EVENT_MASK_ROOT, theCursor.xid };
622 theWindow = theScreen->root;
623 XCBChangeWindowAttributes(xc, theWindow,
624 XCBCWEventMask | XCBCWCursor, rootAttributes );
627 XCBPIXMAP theIconPixmap;
629 CARD32 theWindowAttributes[] = {
630 theWhitePixel, /* background */
631 theBlackPixel, /* border */
632 False, /* override_redirect */
636 unsigned long theWindowMask = XCBCWBackPixel | XCBCWBorderPixel |
637 XCBCWOverrideRedirect | XCBCWEventMask | XCBCWCursor;
639 theWindow = XCBWINDOWNew( xc );
644 WindowPointX, WindowPointY,
645 WindowWidth, WindowHeight,
647 XCBWindowClassInputOutput,
648 theScreen->root_visual, /* CopyFromParent */
649 theWindowMask, theWindowAttributes );
651 /* new: obey the window-delete protocol, look for XCBClientMessage */
652 deleteWindowAtom = GetAtom(xc, "WM_DELETE_WINDOW");
653 SetWMProtocols( xc, theWindow, 1, &deleteWindowAtom );
655 theIconPixmap = CreateBitmapFromData( xc, theWindow,
656 icon_bits, icon_width, icon_height );
658 theWMHints.icon_pixmap = theIconPixmap;
661 theWMHints.initial_state = IconicState;
663 theWMHints.initial_state = NormalState;
665 theWMHints.flags = IconPixmapHint | StateHint;
667 XSetWMHints( theDisplay, theWindow, &theWMHints );
669 /* Um... there is no function to send the hints...
671 WMHintsSetIconPixmap( &theHints, theIconPixmap );
674 WMHintsSetIconic( &theHints );
676 WMHintsSetNormal( &theHints );
682 /* why hide the structure? */
683 SizeHints *theSizeHints = AllocSizeHints();
685 /* need enum for second param (user specified) */
686 SizeHintsSetPosition(theSizeHints, 0, WindowPointX, WindowPointY);
687 SizeHintsSetSize(theSizeHints, 0, WindowWidth, WindowHeight);
689 SetWMNormalHints(xc, theWindow, theSizeHints);
691 FreeSizeHints(theSizeHints);
693 /* Um, why do I have to specify the encoding in this API? */
694 SetWMName( xc, theWindow, STRING, strlen(theTitle), theTitle );
695 SetWMIconName( xc, theWindow, STRING, strlen(theTitle), theTitle );
697 XCBMapWindow( xc, theWindow );
702 /* is this really necessary? */
703 XSetWindowBackground( theDisplay, theWindow, theWhitePixel );
704 XClearWindow( theDisplay, theWindow );
705 XFlush( theDisplay );
708 XGetGeometry( theDisplay, theWindow, &theRoot,
709 &WindowPointX, &WindowPointY, &WindowWidth, &WindowHeight,
710 &BorderWidth, &theDepth );
717 /* latency: ask for keysyms now, and receive them later */
718 theKeySyms = XCBKeySymbolsAlloc( xc );
720 /* later: XCBKeySymbolsFree( keysyms ); */
721 /* later: XCBRefreshKeyboardMapping ( keysyms, mappingEvent ); */
725 void Interval(void) {
730 void TickCount(void) {
731 if ( ++NekoTickCount >= MAX_TICK )
734 if ( NekoTickCount % 2 == 0 )
735 if ( NekoStateCount < MAX_TICK )
741 SetNekoState( int SetValue )
746 NekoState = SetValue;
749 switch ( NekoState ) {
759 NekoMoveDx = NekoMoveDy = 0;
768 /* Xlib does merging of requests, but the Flush and frequent DrawGC changes
769 defeat this mechanism */
772 DrawNeko( int x, int y, XCBGCONTEXT DrawGC )
774 XCBDRAWABLE drawable; drawable.window = theWindow;
775 XCBRECTANGLE rect = { NekoLastX, NekoLastY, BITMAP_WIDTH, BITMAP_HEIGHT };
777 if ( (x != NekoLastX || y != NekoLastY) && (EventState != DEBUG_LIST) )
779 XCBPolyFillRectangle( xc, drawable, SpaceGC, 1, &rect );
780 rect.x = x; rect.y = y;
784 CARD32 originMask = XCBGCTileStippleOriginX | XCBGCTileStippleOriginY;
785 CARD32 origin[2] = { x, y };
786 XCBChangeGC( xc, DrawGC, originMask, origin );
787 /* XSetTSOrigin( theDisplay, DrawGC, x, y ); */
789 XCBPolyFillRectangle( xc, drawable, DrawGC, 1, &rect );
800 void RedrawNeko(void) {
801 XCBDRAWABLE drawable; drawable.window = theWindow;
802 XCBRECTANGLE rect = { NekoLastX, NekoLastY, BITMAP_WIDTH, BITMAP_HEIGHT };
804 XCBPolyFillRectangle( xc, drawable, NekoLastGC, 1, &rect );
811 void NekoDirection(void) {
813 double LargeX, LargeY;
817 if ( NekoMoveDx == 0 && NekoMoveDy == 0 ) {
818 NewState = NEKO_STOP;
820 LargeX = (double)NekoMoveDx;
821 LargeY = (double)(-NekoMoveDy);
822 Length = sqrt( LargeX * LargeX + LargeY * LargeY );
823 SinTheta = LargeY / Length;
825 if ( NekoMoveDx > 0 ) {
826 if ( SinTheta > SinPiPer8Times3 ) {
827 NewState = NEKO_U_MOVE;
828 } else if ( ( SinTheta <= SinPiPer8Times3 )
829 && ( SinTheta > SinPiPer8 ) ) {
830 NewState = NEKO_UR_MOVE;
831 } else if ( ( SinTheta <= SinPiPer8 )
832 && ( SinTheta > -( SinPiPer8 ) ) ) {
833 NewState = NEKO_R_MOVE;
834 } else if ( ( SinTheta <= -( SinPiPer8 ) )
835 && ( SinTheta > -( SinPiPer8Times3 ) ) ) {
836 NewState = NEKO_DR_MOVE;
838 NewState = NEKO_D_MOVE;
841 if ( SinTheta > SinPiPer8Times3 ) {
842 NewState = NEKO_U_MOVE;
843 } else if ( ( SinTheta <= SinPiPer8Times3 )
844 && ( SinTheta > SinPiPer8 ) ) {
845 NewState = NEKO_UL_MOVE;
846 } else if ( ( SinTheta <= SinPiPer8 )
847 && ( SinTheta > -( SinPiPer8 ) ) ) {
848 NewState = NEKO_L_MOVE;
849 } else if ( ( SinTheta <= -( SinPiPer8 ) )
850 && ( SinTheta > -( SinPiPer8Times3 ) ) ) {
851 NewState = NEKO_DL_MOVE;
853 NewState = NEKO_D_MOVE;
858 if ( NekoState != NewState ) {
859 SetNekoState( NewState );
864 Bool IsWindowOver(void) {
865 Bool ReturnValue = False;
870 } else if ( NekoY >= WindowHeight - BITMAP_HEIGHT ) {
871 NekoY = WindowHeight - BITMAP_HEIGHT;
877 } else if ( NekoX >= WindowWidth - BITMAP_WIDTH ) {
878 NekoX = WindowWidth - BITMAP_WIDTH;
882 return( ReturnValue );
886 Bool IsNekoDontMove(void) {
887 return( NekoX == NekoLastX && NekoY == NekoLastY );
891 Bool IsNekoMoveStart(void) {
893 if ( (PrevMouseX >= MouseX - IDLE_SPACE
894 && PrevMouseX <= MouseX + IDLE_SPACE) &&
895 (PrevMouseY >= MouseY - IDLE_SPACE
896 && PrevMouseY <= MouseY + IDLE_SPACE) )
901 if ( NekoMoveDx == 0 && NekoMoveDy == 0 )
909 void CalcDxDy(void) {
910 int RelativeX, RelativeY;
911 double LargeX, LargeY;
912 double DoubleLength, Length;
914 /* TODO: replace query with pointer motion notification? */
916 XCBQueryPointerRep *reply = XCBQueryPointerReply( xc,
917 XCBQueryPointer( xc, theWindow ), NULL);
919 RelativeX = reply->win_x;
920 RelativeY = reply->win_y;
930 LargeX = (double)( MouseX - NekoX - BITMAP_WIDTH / 2 );
931 LargeY = (double)( MouseY - NekoY - BITMAP_HEIGHT );
933 DoubleLength = LargeX * LargeX + LargeY * LargeY;
935 if ( DoubleLength != (double)0 ) {
936 Length = sqrt( DoubleLength );
937 if ( Length <= NekoSpeed ) {
938 NekoMoveDx = (int)LargeX;
939 NekoMoveDy = (int)LargeY;
941 NekoMoveDx = (int)( ( NekoSpeed * LargeX ) / Length );
942 NekoMoveDy = (int)( ( NekoSpeed * LargeY ) / Length );
945 NekoMoveDx = NekoMoveDy = 0;
950 void NekoThinkDraw(void) {
955 if ( NekoState != NEKO_SLEEP ) {
956 DrawNeko( NekoX, NekoY,
957 NekoTickCount % 2 == 0 ?
958 *(AnimationPattern[ NekoState ].TickEvenGCPtr) :
959 *(AnimationPattern[ NekoState ].TickOddGCPtr) );
961 DrawNeko( NekoX, NekoY,
962 NekoTickCount % 8 <= 3 ?
963 *(AnimationPattern[ NekoState ].TickEvenGCPtr) :
964 *(AnimationPattern[ NekoState ].TickOddGCPtr) );
969 switch ( NekoState ) {
971 if ( IsNekoMoveStart() ) {
972 SetNekoState( NEKO_AWAKE );
975 if ( NekoStateCount < NEKO_STOP_TIME ) {
978 if ( NekoMoveDx < 0 && NekoX <= 0 ) {
979 SetNekoState( NEKO_L_TOGI );
980 } else if ( NekoMoveDx > 0 && NekoX >= WindowWidth - BITMAP_WIDTH ) {
981 SetNekoState( NEKO_R_TOGI );
982 } else if ( NekoMoveDy < 0 && NekoY <= 0 ) {
983 SetNekoState( NEKO_U_TOGI );
984 } else if ( NekoMoveDy > 0 && NekoY >= WindowHeight - BITMAP_HEIGHT ) {
985 SetNekoState( NEKO_D_TOGI );
987 SetNekoState( NEKO_JARE );
991 if ( IsNekoMoveStart() ) {
992 SetNekoState( NEKO_AWAKE );
995 if ( NekoStateCount < NEKO_JARE_TIME ) {
998 SetNekoState( NEKO_KAKI );
1001 if ( IsNekoMoveStart() ) {
1002 SetNekoState( NEKO_AWAKE );
1005 if ( NekoStateCount < NEKO_KAKI_TIME ) {
1008 SetNekoState( NEKO_AKUBI );
1011 if ( IsNekoMoveStart() ) {
1012 SetNekoState( NEKO_AWAKE );
1015 if ( NekoStateCount < NEKO_AKUBI_TIME ) {
1018 SetNekoState( NEKO_SLEEP );
1021 if ( IsNekoMoveStart() ) {
1022 SetNekoState( NEKO_AWAKE );
1027 if ( NekoStateCount < NEKO_AWAKE_TIME ) {
1040 NekoX += NekoMoveDx;
1041 NekoY += NekoMoveDy;
1043 if ( IsWindowOver() ) {
1044 if ( IsNekoDontMove() ) {
1045 SetNekoState( NEKO_STOP );
1053 if ( IsNekoMoveStart() ) {
1054 SetNekoState( NEKO_AWAKE );
1057 if ( NekoStateCount < NEKO_TOGI_TIME ) {
1060 SetNekoState( NEKO_KAKI );
1063 /* Internal Error */
1064 SetNekoState( NEKO_STOP );
1073 void DisplayCharacters() {
1077 for ( Index = 0, x = 0, y = 0;
1078 BitmapGCDataTable[ Index ].GCCreatePtr != NULL; Index++ ) {
1080 DrawNeko( x, y, *(BitmapGCDataTable[ Index ].GCCreatePtr) );
1081 XFlush( theDisplay );
1085 if ( x > WindowWidth - BITMAP_WIDTH ) {
1088 if ( y > WindowHeight - BITMAP_HEIGHT) {
1098 ProcessKeyPress( XCBKeyPressEvent *theKeyEvent )
1100 Bool ReturnState = True;
1102 /* quit on Meta-Q (Alt-Q) */
1103 XCBKEYSYM theKeySym;
1105 /* last param is "int col". What? add enumeration to xcb_keysyms.h */
1106 theKeySym = XCBKeyPressLookupKeysym( theKeySyms, theKeyEvent, 1 );
1108 /* KeySym XK_Q == 'Q' */
1109 if (theKeySym.id == 'Q' && (theKeyEvent->state & XCBModMask1))
1110 ReturnState = False;
1113 if ( EventState == DEBUG_MOVE ) {
1114 switch ( theKeySym ) {
1116 NekoMoveDx = -(int)( NekoSpeed / sqrt( (double)2 ) );
1117 NekoMoveDy = -NekoMoveDx;
1121 NekoMoveDy = (int)NekoSpeed;
1124 NekoMoveDx = (int)( NekoSpeed / sqrt( (double)2 ) );
1125 NekoMoveDy = NekoMoveDx;
1128 NekoMoveDx = -(int)NekoSpeed;
1136 NekoMoveDx = (int)NekoSpeed;
1140 NekoMoveDx = -(int)( NekoSpeed / sqrt( (double)2 ) );
1141 NekoMoveDy = NekoMoveDx;
1145 NekoMoveDy = -(int)NekoSpeed;
1148 NekoMoveDx = (int)( NekoSpeed / sqrt( (double)2 ) );
1149 NekoMoveDy = -NekoMoveDx;
1155 return( ReturnState );
1159 void NekoAdjust(void) {
1162 else if ( NekoX > WindowWidth - BITMAP_WIDTH )
1163 NekoX = WindowWidth - BITMAP_WIDTH;
1167 else if ( NekoY > WindowHeight - BITMAP_HEIGHT )
1168 NekoY = WindowHeight - BITMAP_HEIGHT;
1171 int IsDeleteMessage(XCBClientMessageEvent *msg)
1173 return msg->data.data32[0] == deleteWindowAtom.xid;
1176 Bool ProcessEvent(void) {
1177 XCBGenericEvent *theEvent;
1178 XCBConfigureNotifyEvent *theConfigureNotification;
1179 XCBExposeEvent *theExposure;
1180 XCBButtonPressEvent *theButtonPress;
1181 Bool ContinueState = True;
1184 switch ( EventState ) {
1186 while ( ContinueState &&
1187 NULL != (theEvent = XCBPollForEvent( xc, &error )) ) { /*while ( XCheckMaskEvent( theDisplay, EVENT_MASK, &theEvent ) ) {*/
1188 switch ( theEvent->response_type & 0x7f ) {
1189 case XCBConfigureNotify:
1190 theConfigureNotification = (XCBConfigureNotifyEvent *)theEvent;
1191 WindowWidth = theConfigureNotification->width;
1192 WindowHeight = theConfigureNotification->height;
1193 WindowPointX = theConfigureNotification->x;
1194 WindowPointY = theConfigureNotification->y;
1195 BorderWidth = theConfigureNotification->border_width;
1199 theExposure = (XCBExposeEvent *)theEvent;
1200 if ( theExposure->count == 0 )
1207 ContinueState = ProcessKeyPress( (XCBKeyPressEvent *)theEvent );
1209 case XCBButtonPress:
1210 theButtonPress = (XCBButtonPressEvent *)theEvent;
1211 ContinueState = ( theButtonPress->detail.id != 3 ); /* xbutton.button */
1213 /* new: handle ClientMessage */
1214 case XCBClientMessage:
1215 ContinueState = !IsDeleteMessage((XCBClientMessageEvent *)theEvent);
1219 /*printf("event type:%x\n", (int)theEvent->response_type);*/
1229 XNextEvent( theDisplay, &theEvent );
1230 switch ( theEvent.type ) {
1231 case ConfigureNotify:
1232 WindowWidth = theEvent.xconfigure.width;
1233 WindowHeight = theEvent.xconfigure.height;
1234 WindowPointX = theEvent.xconfigure.x;
1235 WindowPointY = theEvent.xconfigure.y;
1236 BorderWidth = theEvent.xconfigure.border_width;
1239 if ( theEvent.xexpose.count == 0 )
1240 DisplayCharacters();
1243 DisplayCharacters();
1246 ContinueState = ProcessKeyPress( &theEvent );
1249 if ( theEvent.xbutton.button == 3 )
1258 while ( XCheckMaskEvent( theDisplay, EVENT_MASK, &theEvent ) ) {
1259 switch ( theEvent.type ) {
1260 case ConfigureNotify:
1261 WindowWidth = theEvent.xconfigure.width;
1262 WindowHeight = theEvent.xconfigure.height;
1263 WindowPointX = theEvent.xconfigure.x;
1264 WindowPointY = theEvent.xconfigure.y;
1265 BorderWidth = theEvent.xconfigure.border_width;
1269 if ( theEvent.xexpose.count == 0 )
1276 ContinueState = ProcessKeyPress( &theEvent );
1277 if ( !ContinueState ) {
1278 return( ContinueState );
1282 if ( theEvent.xbutton.button == 3 )
1293 /* Internal Error */
1297 return( ContinueState );
1301 void ProcessNeko(void) {
1302 struct itimerval Value;
1304 EventState = NORMAL_STATE;
1306 NekoX = ( WindowWidth - BITMAP_WIDTH / 2 ) / 2;
1307 NekoY = ( WindowHeight - BITMAP_HEIGHT / 2 ) / 2;
1312 SetNekoState( NEKO_STOP );
1314 timerclear( &Value.it_interval );
1315 timerclear( &Value.it_value );
1317 Value.it_interval.tv_usec = IntervalTime;
1318 Value.it_value.tv_usec = IntervalTime;
1320 setitimer( ITIMER_REAL, &Value, 0 );
1324 } while ( ProcessEvent() );
1330 EventState = DEBUG_LIST;
1332 fprintf( stderr, "\n" );
1333 fprintf( stderr, "G-0lMw$rI=<($7$^$9!#(Quit !D Alt-Q)\n" );
1334 fprintf( stderr, "\n" );
1336 XSelectInput( theDisplay, theWindow, EVENT_MASK );
1338 while ( ProcessEvent() );
1342 void NekoMoveTest() {
1343 struct itimerval Value;
1345 EventState = DEBUG_MOVE;
1347 NekoX = ( WindowWidth - BITMAP_WIDTH / 2 ) / 2;
1348 NekoY = ( WindowHeight - BITMAP_HEIGHT / 2 ) / 2;
1353 SetNekoState( NEKO_STOP );
1355 timerclear( &Value.it_interval );
1356 timerclear( &Value.it_value );
1358 Value.it_interval.tv_usec = IntervalTime;
1359 Value.it_value.tv_usec = IntervalTime;
1361 setitimer( ITIMER_REAL, &Value, 0 );
1363 fprintf( stderr, "\n" );
1364 fprintf( stderr, "G-$N0\F0%F%9%H$r9T$$$^$9!#(Quit !D Alt-Q)\n" );
1365 fprintf( stderr, "\n" );
1366 fprintf( stderr, "\t%-!<%Q%C%I>e$N%F%s%-!<$GG-$r0\F0$5$;$F2<$5$$!#\n" );
1367 fprintf( stderr, "\t(M-8z$J%-!<$O#1!A#9$G$9!#)\n" );
1368 fprintf( stderr, "\n" );
1372 } while ( ProcessEvent() );
1376 void ProcessDebugMenu() {
1377 int UserSelectNo = 0;
1378 char UserAnswer[ BUFSIZ ];
1380 fprintf( stderr, "\n" );
1381 fprintf( stderr, "!Zxneko %G%P%C%0%a%K%e!<![\n" );
1383 while ( !( UserSelectNo >= 1 && UserSelectNo <= 2 ) ) {
1384 fprintf( stderr, "\n" );
1385 fprintf( stderr, "\t1)!!G-%-%c%i%/%?!<0lMwI=<(\n" );
1386 fprintf( stderr, "\t2)!!G-0\F0%F%9%H\n" );
1387 fprintf( stderr, "\n" );
1388 fprintf( stderr, "Select: " );
1390 fgets( UserAnswer, sizeof( UserAnswer ), stdin );
1392 UserSelectNo = atoi( UserAnswer );
1394 if ( !( UserSelectNo >= 1 && UserSelectNo <= 2 ) ) {
1395 fprintf( stderr, "\n" );
1396 fprintf( stderr, "@5$7$$HV9f$rA*Br$7$F2<$5$$!#\n" );
1400 switch ( UserSelectNo ) {
1408 /* Internal Error */
1412 fprintf( stderr, "%F%9%H=*N;!#\n" );
1413 fprintf( stderr, "\n" );
1418 void NullFunction(int ignored)
1420 /* signal( SIGALRM, NullFunction ); */
1426 "Usage: %s [-display <display>] [-geometry <geometry>] \\\n",
1428 fprintf( stderr, "\t[-bg <background>] [-fg <foreground>] \\\n" );
1429 fprintf( stderr, "\t[-title <title>] [-name <title>] [-iconic] \\\n" );
1430 fprintf( stderr, "\t[-speed <speed>] [-time <time>] [-root] [-help]\n" );
1435 GetArguments( int argc, char *argv[],
1436 char *theDisplayName, char *theGeometry, char **theTitle,
1437 double *NekoSpeed, long *IntervalTime )
1442 theDisplayName[ 0 ] = '\0';
1443 theGeometry[ 0 ] = '\0';
1445 iconicState = False;
1447 for ( ArgCounter = 0; ArgCounter < argc; ArgCounter++ ) {
1448 if ( strncmp( argv[ ArgCounter ], "-h", 2 ) == 0 ) {
1451 } else if ( strcmp( argv[ ArgCounter ], "-display" ) == 0 ) {
1453 if ( ArgCounter < argc ) {
1454 strcpy( theDisplayName, argv[ ArgCounter ] );
1456 fprintf( stderr, "%s: -display option error.\n", ProgramName );
1459 } else if ( strncmp( argv[ ArgCounter ], "-geom", 5 ) == 0 ) {
1461 if ( ArgCounter < argc ) {
1462 strcpy( theGeometry, argv[ ArgCounter ] );
1465 "%s: -geometry option error.\n", ProgramName );
1468 } else if ( ( strcmp( argv[ ArgCounter ], "-title" ) == 0 )
1469 || ( strcmp( argv[ ArgCounter ], "-name" ) == 0 ) ) {
1471 if ( ArgCounter < argc ) {
1472 *theTitle = argv[ ArgCounter ];
1474 fprintf( stderr, "%s: -title option error.\n", ProgramName );
1477 } else if ( strcmp( argv[ ArgCounter ], "-iconic" ) == 0 ) {
1479 } else if ( strcmp( argv[ ArgCounter ], "-speed" ) == 0 ) {
1481 if ( ArgCounter < argc ) {
1482 *NekoSpeed = atof( argv[ ArgCounter ] );
1484 fprintf( stderr, "%s: -speed option error.\n", ProgramName );
1487 } else if ( strcmp( argv[ ArgCounter ], "-fg" ) == 0 ) {
1489 if ( ArgCounter < argc ) {
1490 fgColor = argv[ArgCounter];
1492 fprintf( stderr, "%s: -fg option error.\n", ProgramName );
1495 } else if ( strcmp( argv[ ArgCounter ], "-bg" ) == 0 ) {
1497 if ( ArgCounter < argc ) {
1498 bgColor = argv[ArgCounter];
1500 fprintf( stderr, "%s: -bg option error.\n", ProgramName );
1503 } else if ( strcmp( argv[ ArgCounter ], "-time" ) == 0 ) {
1505 if ( ArgCounter < argc ) {
1506 *IntervalTime = atol( argv[ ArgCounter ] );
1508 fprintf( stderr, "%s: -time option error.\n", ProgramName );
1511 } else if ( strcmp( argv[ ArgCounter ], "-root" ) == 0 ) {
1515 "%s: Unknown option \"%s\".\n", ProgramName,
1516 argv[ ArgCounter ] );
1522 return( iconicState );
1525 void UndefineCursor( XCBConnection *c, XCBWINDOW w)
1527 CARD32 none[] = { XCBNone };
1528 XCBChangeWindowAttributes( c, w, XCBCWCursor, none );
1532 main( int argc, char *argv[] )
1535 char theDisplayName[ DIRNAMELEN ];
1536 char theGeometry[ DIRNAMELEN ];
1537 char *theTitle = "";
1539 ProgramName = argv[ 0 ];
1545 fgColor = bgColor = (char *) NULL;
1547 iconicState = GetArguments( argc, argv, theDisplayName, theGeometry,
1548 &theTitle, &NekoSpeed, &IntervalTime );
1550 if (theTitle[0] == 0) theTitle = ProgramName;
1551 InitScreen( theDisplayName, theGeometry, theTitle, iconicState );
1553 signal( SIGALRM, NullFunction );
1555 SinPiPer8Times3 = sin( PI_PER8 * (double)3 );
1556 SinPiPer8 = sin( PI_PER8 );
1564 UndefineCursor( xc, theWindow );
1565 XCBDisconnect( xc );