# include "Ximage.h"

# define IgnoreMask (long) (~(StructureNotifyMask | SubstructureNotifyMask | ExposureMask | KeyPressMask | ButtonPressMask | PointerMotionMask))

int LastEvent (Display *display, int type, XEvent *event);

int cursor (Graphic *graphic, Layout *layout) {

  Display        *display;
  XEvent          event;
  KeySym          keysym;
  int             status;
  XComposeStatus  composestatus;
  char            string[10], line[40], *name;
  double          x, y;
  
  while (1) {
    
    status = CheckPipe (graphic, layout);
    if (status == 0) return (FALSE);
    if (status == 2) return (TRUE);
    if (status == 1) goto events;

  events:
    if (XEventsQueued (graphic[0].display, QueuedAfterFlush) < 1) {
      usleep (10000);
      continue;
    }

    display = graphic[0].display;

    /* only do the last entry for these events */
    /* this ignores the return status from these functions */
    if (LastEvent (display, ConfigureNotify, &event)) Reconfig (graphic, layout, &event);
    if (LastEvent (display, Expose,          &event)) Refresh (graphic, layout, 1);
    if (LastEvent (display, MappingNotify,   &event)) XRefreshKeyboardMapping ((XMappingEvent *) &event);
    if (LastEvent (display, MotionNotify,    &event)) UpdatePointer (graphic, layout, (XMotionEvent *) &event);
    if (LastEvent (display, ButtonPress,     &event)) InterpretPresses (graphic, layout, (XButtonEvent *) &event);
    if (LastEvent (display, KeyPress,        &event)) {
      status = XLookupString ((XKeyEvent *) &event, string, 9, &keysym, &composestatus);

      if (event.xkey.x < layout[0].picture.x) continue;
      if (event.xkey.x > layout[0].picture.x + layout[0].picture.dx) continue;
      if (event.xkey.y < layout[0].picture.y) continue;
      if (event.xkey.y > layout[0].picture.y + layout[0].picture.dy) continue;
	
      Screen_to_Image (&x, &y, (double)event.xkey.x, (double)event.xkey.y, layout);
      name = XKeysymToString (keysym);

      // skip the following keys: 
      if (!strcmp (name, "Shift_L")) continue;
      if (!strcmp (name, "Shift_R")) continue;
      if (!strcmp (name, "Control_L")) continue;
      if (!strcmp (name, "Control_R")) continue;
      if (!strcmp (name, "Alt_L")) continue;
      if (!strcmp (name, "Alt_R")) continue;
      if (!strcmp (name, "Super_L")) continue;
      if (!strcmp (name, "Super_R")) continue;
      if (!strcmp (name, "Caps_Lock")) continue;
      if (!strcmp (name, "Pause")) continue;
      if (!strcmp (name, "Continue")) continue;
      if (!strcmp (name, "Num_Lock")) continue;
      if (!strcmp (name, "Scroll_Lock")) continue;
      if (!strcmp (name, "Print")) continue;
      if (!strcmp (name, "(null)")) continue;

      snprintf (line, 40, "%12s %12.6f %12.6f ", name, x, y);
      write (layout[0].Ximage, line, 40);
    }

    /* remove those events we will ignore */
    while (XCheckMaskEvent (display, IgnoreMask, &event)) continue;

    /* events to remove which have no mask component */
    while (XCheckTypedEvent (display, MappingNotify, &event)) continue;
    while (XCheckTypedEvent (display, ClientMessage, &event)) continue;
    while (XCheckTypedEvent (display, SelectionClear, &event)) continue;
    while (XCheckTypedEvent (display, SelectionNotify, &event)) continue;
    while (XCheckTypedEvent (display, SelectionRequest, &event)) continue;
  }
  return (FALSE);
}
