#include "xlib.h" #include "scheme48.h" #define ECAST(name, type) type* name = (type*)e #define sidx 4 #define SET(i, v) S48_VECTOR_SET(r, i, v) #define SETSIZE(i) r = s48_make_vector(sidx+i, S48_FALSE) s48_value scx_enter_event(XEvent* e) { s48_value r = S48_FALSE; s48_value temp = S48_FALSE; int i; S48_DECLARE_GC_PROTECT(2); S48_GC_PROTECT_2(r, temp); switch (e->type) { case KeyPress : case KeyRelease : case ButtonPress : case ButtonRelease : case MotionNotify : { ECAST(q, XKeyEvent); SETSIZE(10); // all equal in the beginning SET(sidx+0, SCX_ENTER_WINDOW(q->root)); SET(sidx+1, SCX_ENTER_WINDOW(q->subwindow)); SET(sidx+2, SCX_ENTER_TIME(q->time)); SET(sidx+3, s48_enter_integer(q->x)); SET(sidx+4, s48_enter_integer(q->y)); SET(sidx+5, s48_enter_integer(q->x_root)); SET(sidx+6, s48_enter_integer(q->y_root)); SET(sidx+7, Bits_To_Symbols(q->state, State_Syms)); // now they are different switch (e->type) { case KeyPress : case KeyRelease : { SET(sidx+8, s48_enter_integer(q->keycode)); SET(sidx+9, S48_ENTER_BOOLEAN(q->same_screen)); } break; case ButtonPress : case ButtonRelease : { ECAST(q, XButtonEvent); SET(sidx+8, Bit_To_Symbol(q->button, Button_Syms)); SET(sidx+9, S48_ENTER_BOOLEAN(q->same_screen)); } break; case MotionNotify : { ECAST(q, XMotionEvent); SET(sidx+8, S48_ENTER_BOOLEAN(q->is_hint)); SET(sidx+9, S48_ENTER_BOOLEAN(q->same_screen)); } break; } } break; case EnterNotify : case LeaveNotify : { ECAST(q, XCrossingEvent); SETSIZE(12); SET(sidx+0, SCX_ENTER_WINDOW(q->root)); SET(sidx+1, SCX_ENTER_WINDOW(q->subwindow)); SET(sidx+2, SCX_ENTER_TIME(q->time)); SET(sidx+3, s48_enter_integer(q->x)); SET(sidx+4, s48_enter_integer(q->y)); SET(sidx+5, s48_enter_integer(q->x_root)); SET(sidx+6, s48_enter_integer(q->y_root)); SET(sidx+7, Bit_To_Symbol(q->mode, Cross_Mode_Syms)); SET(sidx+8, Bit_To_Symbol(q->detail, Cross_Detail_Syms)); SET(sidx+9, S48_ENTER_BOOLEAN(q->same_screen)); SET(sidx+10, S48_ENTER_BOOLEAN(q->focus)); // Elk does this; but why not State_Syms?? SET(sidx+11, Bit_To_Symbol(q->state, Button_Syms)); } break; case FocusIn : case FocusOut : { ECAST(q, XFocusChangeEvent); SETSIZE(2); SET(sidx+0, Bit_To_Symbol(q->mode, Cross_Mode_Syms)); SET(sidx+1, Bit_To_Symbol(q->detail, Focus_Detail_Syms)); } break; case KeymapNotify : { ECAST(q, XKeymapEvent); SETSIZE(1); temp = s48_make_string(32, (char)0); for (i=0; i < 32; i++) S48_STRING_SET(temp, i, q->key_vector[i]); SET(sidx+0, temp); } break; case Expose : { ECAST(q, XExposeEvent); SETSIZE(5); SET(sidx+0, s48_enter_integer(q->x)); SET(sidx+1, s48_enter_integer(q->y)); SET(sidx+2, s48_enter_integer(q->width)); SET(sidx+3, s48_enter_integer(q->height)); SET(sidx+4, s48_enter_integer(q->count)); } break; case GraphicsExpose : { ECAST(q, XGraphicsExposeEvent); SETSIZE(7); // the ->window member is only a drawable here! ?? SET(sidx+0, s48_enter_integer(q->x)); SET(sidx+1, s48_enter_integer(q->y)); SET(sidx+2, s48_enter_integer(q->width)); SET(sidx+3, s48_enter_integer(q->height)); SET(sidx+4, s48_enter_integer(q->count)); SET(sidx+5, s48_enter_integer(q->major_code)); SET(sidx+6, s48_enter_integer(q->minor_code)); } break; case NoExpose : { ECAST(q, XNoExposeEvent); SETSIZE(2); SET(sidx+0, s48_enter_integer(q->major_code)); SET(sidx+1, s48_enter_integer(q->minor_code)); } break; case VisibilityNotify : { ECAST(q, XVisibilityEvent); SETSIZE(1); SET(sidx+0, Bit_To_Symbol(q->state, Visibility_Syms)); } break; case CreateNotify : { ECAST(q, XCreateWindowEvent); SETSIZE(7); SET(sidx+0, SCX_ENTER_WINDOW(q->window)); SET(sidx+1, s48_enter_integer(q->x)); SET(sidx+2, s48_enter_integer(q->y)); SET(sidx+3, s48_enter_integer(q->width)); SET(sidx+4, s48_enter_integer(q->height)); SET(sidx+5, s48_enter_integer(q->border_width)); SET(sidx+6, S48_ENTER_BOOLEAN(q->override_redirect)); } break; case DestroyNotify : { ECAST(q, XDestroyWindowEvent); SETSIZE(1); SET(sidx+0, SCX_ENTER_WINDOW(q->window)); } break; case UnmapNotify : { ECAST(q, XUnmapEvent); SETSIZE(2); SET(sidx+0, SCX_ENTER_WINDOW(q->window)); SET(sidx+1, S48_ENTER_BOOLEAN(q->from_configure)); } break; case MapNotify : { ECAST(q, XMapEvent); SETSIZE(2); SET(sidx+0, SCX_ENTER_WINDOW(q->window)); SET(sidx+1, S48_ENTER_BOOLEAN(q->override_redirect)); } break; case MapRequest : { ECAST(q, XMapRequestEvent); SETSIZE(1); SET(sidx+0, SCX_ENTER_WINDOW(q->window)); } break; case ReparentNotify : { ECAST(q, XReparentEvent); SETSIZE(5); SET(sidx+0, SCX_ENTER_WINDOW(q->window)); SET(sidx+1, SCX_ENTER_WINDOW(q->parent)); SET(sidx+2, s48_enter_integer(q->x)); SET(sidx+3, s48_enter_integer(q->y)); SET(sidx+4, S48_ENTER_BOOLEAN(q->override_redirect)); } break; case ConfigureNotify : { ECAST(q, XConfigureEvent); SETSIZE(8); SET(sidx+0, SCX_ENTER_WINDOW(q->window)); SET(sidx+1, s48_enter_integer(q->x)); SET(sidx+2, s48_enter_integer(q->y)); SET(sidx+3, s48_enter_integer(q->width)); SET(sidx+4, s48_enter_integer(q->height)); SET(sidx+5, s48_enter_integer(q->border_width)); SET(sidx+6, SCX_ENTER_WINDOW(q->above)); SET(sidx+7, S48_ENTER_BOOLEAN(q->override_redirect)); } break; case ConfigureRequest : { ECAST(q, XConfigureRequestEvent); SETSIZE(9); SET(sidx+0, SCX_ENTER_WINDOW(q->window)); SET(sidx+1, s48_enter_integer(q->x)); SET(sidx+2, s48_enter_integer(q->y)); SET(sidx+3, s48_enter_integer(q->width)); SET(sidx+4, s48_enter_integer(q->height)); SET(sidx+5, s48_enter_integer(q->border_width)); SET(sidx+6, SCX_ENTER_WINDOW(q->above)); SET(sidx+7, Bit_To_Symbol(q->detail, Stack_Mode_Syms)); SET(sidx+8, s48_enter_integer(q->value_mask)); } break; case GravityNotify : { ECAST(q, XGravityEvent); SETSIZE(3); SET(sidx+0, SCX_ENTER_WINDOW(q->window)); SET(sidx+1, s48_enter_integer(q->x)); SET(sidx+2, s48_enter_integer(q->y)); } break; case ResizeRequest : { ECAST(q, XResizeRequestEvent); SETSIZE(2); SET(sidx+0, s48_enter_integer(q->width)); SET(sidx+1, s48_enter_integer(q->height)); } break; case CirculateRequest : { ECAST(q, XCirculateEvent); SETSIZE(2); SET(sidx+0, SCX_ENTER_WINDOW(q->window)); SET(sidx+1, Bit_To_Symbol(q->place, Place_Syms)); } break; case PropertyNotify : { ECAST(q, XPropertyEvent); SETSIZE(3); SET(sidx+0, SCX_ENTER_ATOM(q->atom)); SET(sidx+1, SCX_ENTER_TIME(q->time)); SET(sidx+2, Bit_To_Symbol(q->state, Prop_Syms)); } break; case SelectionClear : { ECAST(q, XSelectionClearEvent); SETSIZE(2); SET(sidx+0, SCX_ENTER_ATOM(q->selection)); SET(sidx+1, SCX_ENTER_TIME(q->time)); } break; case SelectionRequest : { ECAST(q, XSelectionRequestEvent); SETSIZE(5); SET(sidx+0, SCX_ENTER_WINDOW(q->requestor)); SET(sidx+1, SCX_ENTER_ATOM(q->selection)); SET(sidx+2, SCX_ENTER_ATOM(q->target)); SET(sidx+3, SCX_ENTER_ATOM(q->property)); SET(sidx+4, SCX_ENTER_TIME(q->time)); } break; case SelectionNotify : { ECAST(q, XSelectionEvent); SETSIZE(4); SET(sidx+0, SCX_ENTER_ATOM(q->selection)); SET(sidx+1, SCX_ENTER_ATOM(q->target)); SET(sidx+2, SCX_ENTER_ATOM(q->property)); SET(sidx+3, SCX_ENTER_TIME(q->time)); } break; case ColormapNotify : { ECAST(q, XColormapEvent); SETSIZE(3); SET(sidx+0, SCX_ENTER_COLORMAP(q->colormap)); SET(sidx+1, S48_ENTER_BOOLEAN(q->new)); SET(sidx+2, q->state == ColormapInstalled ? S48_TRUE : S48_FALSE); } break; case ClientMessage : { ECAST(q, XClientMessageEvent); SETSIZE(2); SET(sidx+0, SCX_ENTER_ATOM(q->message_type)); switch (q->format) { case 8 : { temp = s48_make_string(20, (char)0); for (i=0; i < 20; i++) S48_STRING_SET(temp, i, q->data.b[i]); } break; case 16 : { temp = s48_make_vector(10, S48_FALSE); for (i=0; i < 10; i++) S48_VECTOR_SET(temp, i, s48_enter_integer(q->data.s[i])); } break; case 32 : { temp = s48_make_vector(5, S48_FALSE); for (i=0; i < 5; i++) S48_VECTOR_SET(temp, i, s48_enter_integer(q->data.l[i])); } break; default : temp = s48_enter_integer(q->format); //?? } SET(sidx+1, temp); } case MappingNotify : { ECAST(q, XMappingEvent); SETSIZE(3); SET(sidx+0, Bit_To_Symbol(q->request, Mapping_Syms)); SET(sidx+1, s48_enter_integer(q->first_keycode)); SET(sidx+2, s48_enter_integer(q->count)); } break; } // switch end // XAnyEvent entries { ECAST(q, XAnyEvent); SET(0, s48_enter_integer(q->serial)); SET(1, S48_ENTER_BOOLEAN(q->send_event)); SET(2, SCX_ENTER_DISPLAY(q->display)); SET(3, SCX_ENTER_WINDOW(q->window)); } // more?? // And the Event-Name r = s48_cons( Bit_To_Symbol(e->type, Event_Syms), r ); S48_GC_UNPROTECT(); return r; } s48_value scx_Next_Event(s48_value Xdisplay) { XEvent e; XNextEvent(SCX_EXTRACT_DISPLAY(Xdisplay), &e); return scx_enter_event(&e); } s48_value scx_Peek_Event(s48_value Xdisplay) { XEvent e; XPeekEvent(SCX_EXTRACT_DISPLAY(Xdisplay), &e); return scx_enter_event(&e); } s48_value scx_Events_Pending(s48_value Xdisplay) { return s48_enter_integer(XPending(SCX_EXTRACT_DISPLAY(Xdisplay))); } s48_value scx_Get_Motion_Events(s48_value Xdisplay, s48_value Xwindow, s48_value from, s48_value to) { int n,i; XTimeCoord *p = XGetMotionEvents(SCX_EXTRACT_DISPLAY(Xdisplay), SCX_EXTRACT_WINDOW(Xwindow), SCX_EXTRACT_TIME(from), SCX_EXTRACT_TIME(to), &n); s48_value v = s48_make_vector(n, S48_FALSE); s48_value l = S48_NULL; S48_DECLARE_GC_PROTECT(2); S48_GC_PROTECT_2(v,l); for (i = 0; i < n; i++) { l = s48_cons(SCX_ENTER_TIME(p[i].time), s48_cons(s48_enter_integer(p[i].x), s48_cons(s48_enter_integer(p[i].y), S48_NULL))); S48_VECTOR_SET(v, i, l); } S48_GC_UNPROTECT(); XFree((char*)p); return v; } s48_value scx_add_pending_channel (channel){ int socket_fd; S48_CHECK_CHANNEL(channel); socket_fd = S48_UNSAFE_EXTRACT_FIXNUM(S48_UNSAFE_CHANNEL_OS_INDEX(channel)); if (! s48_add_pending_fd(socket_fd, 1)) // 1 for: yes, is input s48_raise_out_of_memory_error(); return S48_UNSPECIFIC; } void scx_init_event(void) { S48_EXPORT_FUNCTION(scx_Next_Event); S48_EXPORT_FUNCTION(scx_Peek_Event); S48_EXPORT_FUNCTION(scx_Events_Pending); S48_EXPORT_FUNCTION(scx_Get_Motion_Events); S48_EXPORT_FUNCTION(scx_add_pending_channel); }