--- /dev/null
+#include <stdio.h>
+#include <X11/Xutil.h>
+#include "winsys.h"
+
+Display *dpy;
+Window win;
+int quit;
+
+static Window root_win;
+static int xscr;
+static Atom xa_wm_proto, xa_wm_del_win;
+static int reshape_pending;
+
+static int win_width, win_height, win_mapped;
+
+static void handle_event(XEvent *ev);
+static int translate_keysym(KeySym sym);
+
+int create_window(const char *title, int xsz, int ysz)
+{
+ XVisualInfo vinf;
+ XTextProperty txprop;
+ XSetWindowAttributes xattr;
+
+ if(!dpy) {
+ if(!(dpy = XOpenDisplay(0))) {
+ fprintf(stderr, "failed to connect to the X server\n");
+ return -1;
+ }
+ xscr = DefaultScreen(dpy);
+ root_win = RootWindow(dpy, xscr);
+ xa_wm_proto = XInternAtom(dpy, "WM_PROTOCOLS", False);
+ xa_wm_del_win = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
+ }
+
+ if(!XMatchVisualInfo(dpy, xscr, 24, TrueColor, &vinf)) {
+ fprintf(stderr, "no suitable visual found\n");
+ return -1;
+ }
+
+ xattr.background_pixel = BlackPixel(dpy, xscr);
+ xattr.colormap = XCreateColormap(dpy, root_win, vinf.visual, AllocNone);
+
+ if(!(win = XCreateWindow(dpy, root_win, 0, 0, xsz, ysz, 0, 24, InputOutput,
+ vinf.visual, CWBackPixel | CWColormap, &xattr))) {
+ fprintf(stderr, "failed to create window\n");
+ return -1;
+ }
+
+ XSelectInput(dpy, win, KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
+ ButtonMotionMask | ExposureMask | StructureNotifyMask);
+
+ XSetWMProtocols(dpy, win, &xa_wm_del_win, 1);
+
+ if(XStringListToTextProperty((char**)&title, 1, &txprop)) {
+ XSetWMName(dpy, win, &txprop);
+ XSetWMIconName(dpy, win, &txprop);
+ XFree(txprop.value);
+ }
+
+ XMapWindow(dpy, win);
+
+ reshape_pending = 1;
+ return 0;
+}
+
+void destroy_window(void)
+{
+ XDestroyWindow(dpy, win);
+}
+
+void handle_events(void)
+{
+ XEvent ev;
+
+ while(XPending(dpy)) {
+ XNextEvent(dpy, &ev);
+ handle_event(&ev);
+ if(quit) return;
+ }
+
+ if(reshape_pending) {
+ reshape_pending = 0;
+ reshape(win_width, win_height);
+ }
+}
+
+static void handle_event(XEvent *ev)
+{
+ KeySym sym;
+ int key;
+
+ switch(ev->type) {
+ case MapNotify:
+ win_mapped = 1;
+ break;
+ case UnmapNotify:
+ win_mapped = 0;
+ break;
+
+ case ConfigureNotify:
+ if(ev->xconfigure.width != win_width || ev->xconfigure.height != win_height) {
+ win_width = ev->xconfigure.width;
+ win_height = ev->xconfigure.height;
+ reshape_pending = 1;
+ }
+ break;
+
+ case KeyPress:
+ case KeyRelease:
+ if((sym = XLookupKeysym(&ev->xkey, 0)) && (key = translate_keysym(sym))) {
+ if(ev->type == KeyPress) {
+ keypress(key);
+ } else {
+ keyrelease(key);
+ }
+ }
+ break;
+
+ case ButtonPress:
+ case ButtonRelease:
+ mousebutton(ev->xbutton.button - Button1, ev->type == ButtonPress, ev->xbutton.x, ev->xbutton.y);
+ break;
+
+ case MotionNotify:
+ mousemotion(ev->xmotion.x, ev->xmotion.y);
+ break;
+
+ case ClientMessage:
+ if(ev->xclient.message_type == xa_wm_proto) {
+ if(ev->xclient.data.l[0] == xa_wm_del_win) {
+ quit = 1;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+void swap_buffers(void)
+{
+}
+
+static int translate_keysym(KeySym sym)
+{
+ if(sym < 128) return sym;
+
+ switch(sym) {
+ case XK_Escape: return 27;
+ case XK_Tab: return '\t';
+ case XK_Return: return '\n';
+ case XK_BackSpace: return '\b';
+ case XK_Delete: return 127;
+ /*case XK_Home: return KEY_HOME;
+ case XK_End: return KEY_END;
+ case XK_Page_Up: return KEY_PGUP;
+ case XK_Page_Down: return KEY_PGDOWN;*/
+ default:
+ break;
+ }
+
+ return 0;
+}