hlfw.ca

x9dev

Download patch

ref: 28d50d30db674c231702b8a83a37591a4e7b0e40
parent: b33d1d50e317c87e58d179caaa3e158d6d234add
author: halfwit <michaelmisch1985@gmail.com>
date: Sat Oct 3 17:42:44 PDT 2020

Stashing some things and getting ready to use c9

--- /dev/null
+++ b/draw.c
@@ -1,0 +1,512 @@
+/*
+ * Copyright (c) 2020 Michael Misch <michaelmisch1985@gmail.com> 
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+
+#include <X11/X.h>
+#include "mi.h"
+#define NEED_EVENTS
+#include <X11/Xproto.h>
+#include <X11/Xos.h>
+#include <X11/Xpoll.h>
+#define XK_TECHNICA
+#define XK_PUBLISHING
+#include <X11/keysym.h>
+#include <X11/keysymdef.h>
+#include "scrnintstr.h"
+#include "servermd.h"
+#define PSZ 8
+#include "fb.h"
+#include "colormapst.h"
+#include "gcstruct.h"
+#include "input.h"
+#include "mipointer.h"
+#include "micmap.h"
+#include "dix.h"
+#include "miline.h"
+#include "shadow.h"
+#include "xkbsrv.h"
+#include "xserver-properties.h"
+#include "exevents.h"
+#include "extinit.h"
+#include "keymap.h"
+#include "x9dev.h"
+
+x9devInfo x9di;
+
+static DeviceIntPtr x9devMouse;
+static DeviceIntPtr x9devKeybd;
+static int  oldx, oldy, oldbut;
+
+static CARD8 modmap[MAP_LENGTH];
+
+static PixmapFormatRec formats[] = {
+    { 1,    1,  BITMAP_SCANLINE_PAD },
+    { 8,    8,  BITMAP_SCANLINE_PAD },
+    { 16,   16,     BITMAP_SCANLINE_PAD },
+    { 24,   24,     BITMAP_SCANLINE_PAD },
+    { 32,   32,     BITMAP_SCANLINE_PAD }
+};
+
+#define NUMFORMATS (sizeof(formats)/sizeof((formats)[0]))
+#define x9devSaveScreen (void *) NoopDDA
+#define x9devConstrainCursor    (void *) NoopDDA
+#define x9devDisplayCursor  (void *) NoopDDA
+#define x9devRealizeCursor  (void *) NoopDDA
+#define x9devUnrealizeCursor    (void *) NoopDDA
+#define x9devRecolorCursor  (void *) NoopDDA
+#define x9devSetCursorPosition  (void *) NoopDDA
+#define e    ev.u.u
+#define ek    ev.u.keyButtonPointer
+
+static void
+x9devSendKeybdEvent(int k, int t)
+{
+    xEvent ev;
+
+    memset(&ev, 0, sizeof(xEvent));
+    e.type = t;
+    e.detail = k + MIN_KEYCODE;
+    ek.time = GetTimeInMillis();
+    mieqEnqueue(x9devKeybd, (InternalEvent *)&ev);
+}
+
+static void
+x9devSendMouseEvent(int x, int y, int b, int t)
+{
+    xEvent ev;
+
+    memset(&ev, 0, sizeof(xEvent));
+    e.type = t;
+    e.detail = b;
+    ek.rootX = x;
+    ek.rootY = y;
+    ek.time = GetTimeInMillis();
+    mieqEnqueue(x9devMouse, (InternalEvent *)&ev);
+}
+#undef ek
+#undef e
+
+static void
+x9devRefreshScreen(int x1, int y1, int x2, int y2)
+{
+    /* 
+    Rectangle r;
+    uchar *p;
+    int n;
+
+    p = (uchar *)x9di.fb+(y1*x9di.width+x1)*(x9di.depth/8);
+    r = rectaddpt(Rect(x1, y1, x2, y2), screen->r.min);
+    if (Dx(r) == x9di.width) {
+        if (loadimage(screen, r, p, x9di.bpl * Dy(r)) < 0)
+            FatalError("can't load image");
+        goto End;
+    }
+    n = Dx(r)*(x9di.depth/8);
+    y2 += screen->r.min.y;
+       while(r.min.y < y2) {
+        r.max.y = r.min.y+1;
+        if (loadimage(screen, r, p, n) < 0)
+            FatalError("can't load image");
+        p += x9di.bpl;
+        r.min.y++;
+    }
+
+End:
+    flushimage(display, 1);
+    */
+}
+
+static void
+x9devResize(void)
+{
+    /*
+    if (getwindow(display, Refnone) < 0)
+        FatalError("can't reattach to window");
+
+    draw(screen, screen->r, display->white, nil, ZP);
+    x9devRefreshScreen(0, 0, x9di.width, x9di.height);
+    */
+}
+
+static int
+x9devMouseRead(int *x, int *y, int *b)
+{
+    char    buf[1+4*12];
+    int n;
+
+    if ((n = c9read(x9di.mouseFd, buf, sizeof buf)) <= 0)
+        return 0;
+
+    if (n != 1 + 4 * 12)
+        FatalError("Bad mouse event");
+
+    if (buf[0] == 'r') {
+        x9devResize();
+        return 0;
+    }
+    *x = atoi(buf + 1 + 0 * 12) - screen->r.min.x;
+    *y = atoi(buf + 1 + 1 * 12) - screen->r.min.y;
+    *b = atoi(buf + 1 + 2 * 12);
+
+    return 1;
+}
+
+static wchar_t
+x9devKeybdRead(void)
+{
+    static char s[3];
+    static int  n = 0;
+    wchar_t rune;
+
+    if (c9read(x9di.keybdFd, s + n, 1) != 1)
+        return 0;
+
+    rune = s[0];
+    if (n > 0 || (rune & 0x80) != 0x00) {
+        if (mbtowc(&rune, s, n + 1) == -1) {
+            /* incomplete rune; wait until next char */
+            if (++n == 3)
+                n = 0;
+            return 0;
+        }
+        n = 0;
+    }
+    if (rune == Kdown)
+        rune = 0x99;
+    else if (rune & KF)
+        rune = (rune&~KF) + 0x80;
+
+    return rune;
+}
+
+static void
+x9devInfoInit(void)
+{
+/*
+    char    buf[256];
+
+    if(initdraw(NULL, 0, "x9dev") < 0)
+        FatalError("can't open display");
+
+    x9di.depth = screen->depth;
+    x9di.width = Dx(screen->r);
+    x9di.width -= x9di.width&(screen->depth/8);
+    x9di.dpi = 100;
+    x9di.bpl = bytesperline(Rect(0, 0, x9di.width, x9di.height), x9di.depth);
+    x9di.fb = malloc(x9di.bpl * x9di.height);
+    if (x9di.fb == nil)
+        FatalError("couldn't allocate framebuffer");
+
+    snprint(buf, sizeof buf, "%s/mouse", display->devdir);
+    x9di.mouseFd = c9open(buf, O_RDWR | O_NONBLOCK);
+    if(x9di.mouseFd < 0)
+        FatalError("can't open mouse");
+
+    snprint(buf, sizeof buf, "%s/cons", display->devdir);
+    x9di.keybdFd = c9open(buf, O_RDONLY | O_NONBLOCK);
+    if(x9di.keybdFd < 0)
+        FatalError("can't open keyboard");
+
+    snprint(buf, sizeof buf, "%s/consctl", display->devdir);
+    x9di.consctlFd = c9open(buf, O_WRONLY);
+    if(x9di.consctlFd < 0)
+        FatalError("can't open consctl");
+    if(c9write(x9di.consctlFd, "rawon", 5) != 5)
+        FatalError("can't set rawon");
+*/
+}
+
+static int  
+x9devKeybdHandle(void)
+{
+    unsigned char   k, m;
+    int c;
+
+    c = x9devKeybdRead();
+    if (c == 0 || c > sizeof(rune2keycode))
+        return 0;
+
+    k = rune2keycode[c].key;
+    if (k == 0)
+        return 0;
+
+    m = rune2keycode[c].mod;
+    if (m) 
+        x9devSendKeybdEvent(m, KeyPress);
+
+    x9devSendKeybdEvent(k, KeyPress);
+    x9devSendKeybdEvent(k, KeyRelease);
+    if (m) 
+        x9devSendKeybdEvent(m, KeyRelease);
+
+    return 1;
+}
+
+
+static int  
+x9devMouseHandle(void)
+{
+    int x, y, b, but, t;
+
+    if (!x9devMouseRead(&x, &y, &but))
+        return 0;
+
+    t = b = 0;
+    if (x != oldx || y != oldy) {
+        t = MotionNotify;
+        oldx = x, oldy = y;
+    }
+    if (but != oldbut) {
+        b = oldbut ^ but;
+        t = ButtonPress;
+        if (oldbut & b)
+            t = ButtonRelease;
+        if (b == 4)
+            b = 3;
+        if (but & (8 | 16)) {
+            if (b & 8)
+                b = 4;
+            else
+                b = 5;
+            x9devSendMouseEvent(x, y, b, ButtonPress);
+            x9devSendMouseEvent(x, y, b, ButtonRelease);
+            return 1;
+        }
+    }
+    x9devSendMouseEvent(x, y, b, t);
+    oldbut = but;
+
+    return 1;
+}
+
+
+static void
+x9devWakeupHandler(ScreenPtr scr, int result)
+{
+
+    if (result <= 0)
+        return;
+
+    while (x9devMouseHandle())
+        ;
+    while (x9devKeybdHandle())
+        ;
+}
+
+
+static void
+x9devInitModmap(void)
+{
+    KeySym * ks;
+    int i;
+
+    for (i = 0; i < MAP_LENGTH; i++)
+        modmap[i] = NoSymbol;
+
+    for (i = MIN_KEYCODE, ks = map; i < (MIN_KEYCODE + NUM_KEYCODES); i++, ks += MAP_WIDTH)
+        switch (*ks) {
+        case XK_Shift_L:
+        case XK_Shift_R:
+            modmap[i] = ShiftMask;
+            break;
+        case XK_Control_L:
+        case XK_Control_R:
+            modmap[i] = ControlMask;
+            break;
+        case XK_Alt_L:
+        case XK_Alt_R:
+            modmap[i] = Mod1Mask;
+            break;
+        }
+}
+
+static int  
+x9devKeybdProc(DeviceIntPtr pDev, int what)
+{
+
+    switch (what) {
+    case DEVICE_INIT:
+        x9devInitModmap();
+        if (!InitKeyboardDeviceStruct(pDev, NULL, 
+            (BellProcPtr)NoopDDA, (KbdCtrlProcPtr)NoopDDA))
+            FatalError("can't init keyboard");
+	pDev->inited = TRUE;
+        break;
+    case DEVICE_ON:
+        pDev->enabled = TRUE;
+        break;
+    case DEVICE_CLOSE:
+	break;
+    case DEVICE_OFF:
+        pDev->enabled = FALSE;
+        break;
+    }
+    return Success;
+}
+
+static int  
+x9devMouseProc(DeviceIntPtr pDevice, int what)
+{
+    static unsigned char    map[] = {0, 1, 2, 3, 4, 5};
+    DevicePtr pDev = (DevicePtr)pDevice;
+    Atom btn_labels[3] = {0};
+    Atom axes_labels[2] = {0};
+
+    switch (what) {
+    case DEVICE_INIT:
+        btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT);
+        btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE);
+        btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT);
+
+        axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X);
+        axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y);
+        InitPointerDeviceStruct(pDev, map, 3, btn_labels,
+            (PtrCtrlProcPtr)NoopDDA, GetMotionHistorySize(), 2, axes_labels);
+        break;
+
+    case DEVICE_ON:
+        pDev->on = TRUE;
+        break;
+
+    case DEVICE_CLOSE:
+    case DEVICE_OFF:
+        pDev->on = FALSE;
+        break;
+    }
+    return Success;
+}
+
+
+static void
+x9devCursorLimits(DeviceIntPtr dptr, ScreenPtr spr, CursorPtr cpr, BoxPtr hot, BoxPtr topleft)
+{
+    *topleft = *hot;
+}
+
+static void
+x9devShadowUpdate(ScreenPtr pScreen, shadowBufPtr pBuf)
+{
+    BoxPtr pbox;
+
+    pbox = REGION_EXTENTS(pScreen, &pBuf->pDamage);
+    x9devRefreshScreen(pbox->x1, pbox->y1, pbox->x2, pbox->y2);
+}
+
+
+/* callback dance... */
+static CreateScreenResourcesProcPtr x9devCreateResourcesPtr;
+
+static Bool
+x9devCreateResources(ScreenPtr pScreen)
+{
+    Bool ret = 0;
+
+    pScreen->CreateScreenResources = x9devCreateResourcesPtr;
+    if (pScreen->CreateScreenResources)
+        ret = pScreen->CreateScreenResources(pScreen);
+
+    x9devCreateResourcesPtr = pScreen->CreateScreenResources;
+    pScreen->CreateScreenResources = x9devCreateResourcesPtr;
+    if (ret == FALSE)
+        return FALSE;
+
+    shadowRemove(pScreen, pScreen->GetScreenPixmap(pScreen));
+    if (!shadowAdd(pScreen, pScreen->GetScreenPixmap(pScreen), x9devShadowUpdate, NULL, SHADOW_ROTATE_0, 0))
+        return FALSE;
+
+    return ret;
+}
+
+static Bool
+x9devScreenInit(ScreenPtr pScreen, int argc, char *argv[])
+{
+    int v, i;
+    unsigned long   r, g, b;
+    static int  first = 1;
+
+    if (first) {
+        x9devInfoInit();
+        first = 0;
+    }
+
+    for (i = 0; i < NUMFORMATS; i++)
+        fbSetVisualTypes(formats[i].depth, 0, 8);
+
+    switch (x9di.depth) {
+    case 16:
+        r = 0xF800, g = 0x07E0, b = 0x001F;
+        v = 1 << TrueColor;
+        break;
+    case 24:
+    case 32:
+        r = 0xFF0000, g = 0x00FF00, b = 0x0000FF;
+        v = 1 << TrueColor;
+        break;
+    default:
+        r = g = b = 0;
+        v = 1 << PseudoColor;
+    }
+    if (!fbSetVisualTypesAndMasks(x9di.depth, v, 8, r, g, b))
+        return FALSE;
+
+    if (monitorResolution)
+        x9di.dpi = monitorResolution;
+    if (!fbScreenInit(pScreen, x9di.fb, x9di.width, x9di.height,
+        x9di.dpi, x9di.dpi, x9di.width, x9di.depth))
+        return FALSE;
+
+    pScreen->mmWidth = x9di.width * 25.4 / x9di.dpi;
+    pScreen->mmHeight = x9di.height * 25.4 / x9di.dpi;
+
+    /* cursor */
+    pScreen->ConstrainCursor = x9devConstrainCursor;
+    pScreen->CursorLimits = x9devCursorLimits;
+    pScreen->DisplayCursor = x9devDisplayCursor;
+    pScreen->RealizeCursor = x9devRealizeCursor;
+    pScreen->UnrealizeCursor = x9devUnrealizeCursor;
+    pScreen->RecolorCursor = x9devRecolorCursor;
+    pScreen->SetCursorPosition = x9devSetCursorPosition;
+
+    pScreen->SaveScreen = x9devSaveScreen;
+    pScreen->WakeupHandler = x9devWakeupHandler;
+
+#ifdef RENDER
+    if (!fbPictureInit(pScreen, 0, 0))
+        return FALSE;
+#endif
+
+   if (!shadowSetup(pScreen))
+        return FALSE;
+
+    x9devCreateResourcesPtr = pScreen->CreateScreenResources;
+    pScreen->CreateScreenResources = x9devCreateResources;
+
+    if (!fbCreateDefColormap(pScreen))
+        return FALSE;
+
+    return TRUE;
+}
--- /dev/null
+++ b/io.c
@@ -1,0 +1,406 @@
+#define _DEFAULT_SOURCE
+#define _FILE_OFFSET_BITS 64
+#include <errno.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/select.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <termios.h>
+#include <unistd.h>
+#include "c9/c9.h"
+
+enum {
+	Msize = 8192,
+
+	Rootfid = 0,
+	Indexfid,
+	Chatfid,
+
+	Error = 1<<0,
+	Joined = 1<<1,
+	Disconnected = 1<<2,
+};
+
+typedef struct C9aux C9aux;
+typedef struct REntry REntry;
+
+struct C9aux {
+	C9ctx;
+	int f;
+	int flags;
+	uint8_t rdbuf[Msize];
+	uint8_t wrbuf[Msize];
+	uint32_t wroff;
+};
+
+static const char *nick;
+static int printjoin;
+static uint64_t chatoff, skipuntil;
+
+static uint8_t *
+ctxread(C9ctx *ctx, uint32_t size, int *err)
+{
+	uint32_t n;
+	int r;
+	C9aux *a;
+
+	a = ctx->aux;
+	*err = 0;
+	for (n = 0; n < size; n += r) {
+		if ((r = read(a->f, a->rdbuf+n, size-n)) <= 0) {
+			if (errno == EINTR)
+				continue;
+			a->flags |= Disconnected;
+			close(a->f);
+			return NULL;
+		}
+	}
+
+	return a->rdbuf;
+}
+
+static int
+wrsend(C9aux *a)
+{
+	uint32_t n;
+	int w;
+
+	for (n = 0; n < a->wroff; n += w) {
+		if ((w = write(a->f, a->wrbuf+n, a->wroff-n)) <= 0) {
+			if (errno == EINTR)
+				continue;
+			if (errno != EPIPE) /* remote end closed */
+				perror("write");
+			return -1;
+		}
+	}
+	a->wroff = 0;
+
+	return 0;
+}
+
+static uint8_t *
+ctxbegin(C9ctx *ctx, uint32_t size)
+{
+	uint8_t *b;
+	C9aux *a;
+
+	a = ctx->aux;
+	if (a->wroff + size > sizeof(a->wrbuf)) {
+		if (wrsend(a) != 0 || a->wroff + size > sizeof(a->wrbuf))
+			return NULL;
+	}
+	b = a->wrbuf + a->wroff;
+	a->wroff += size;
+
+	return b;
+}
+
+static int
+ctxend(C9ctx *ctx)
+{
+	(void)ctx;
+	return 0;
+}
+
+static int
+dial(char *s)
+{
+	struct addrinfo *r, *a, hint = {.ai_flags = AI_ADDRCONFIG, .ai_family = AF_UNSPEC, 0};
+	char host[64], *port;
+	int e, f;
+
+	if (strncmp(s, "udp!", 4) == 0) {
+		hint.ai_socktype = SOCK_DGRAM;
+		hint.ai_protocol = IPPROTO_UDP;
+	} else if (strncmp(s, "tcp!", 4) == 0) {
+		hint.ai_socktype = SOCK_STREAM;
+		hint.ai_protocol = IPPROTO_TCP;
+	} else {
+		fprintf(stderr, "invalid dial string: %s\n", s);
+		return -1;
+	}
+	if ((port = strchr(s+4, '!')) == NULL) {
+		fprintf(stderr, "invalid dial string: %s\n", s);
+		return -1;
+	}
+	if (snprintf(host, sizeof(host), "%.*s", (int)(port-s-4), s+4) >= (int)sizeof(host)) {
+		fprintf(stderr, "host name too large: %s\n", s);
+		return -1;
+	}
+	port++;
+	if ((e = getaddrinfo(host, port, &hint, &r)) != 0)
+		return -1;
+	f = -1;
+	for (a = r; a != NULL; a = a->ai_next) {
+		if ((f = socket(a->ai_family, a->ai_socktype, a->ai_protocol)) < 0)
+			continue;
+		if (connect(f, a->ai_addr, a->ai_addrlen) != 0) {
+			close(f);
+			f = -1;
+			continue;
+		}
+	}
+	freeaddrinfo(r);
+
+	return f;
+}
+
+static void
+output(uint8_t *d, int sz)
+{
+	int i, j;
+
+	for (i = j = 0; i < sz; i++) {
+		d[j] = d[i];
+		if (d[j] > 31 || d[j] == '\t' || d[j] == '\n')
+			j++;
+	}
+	write(1, d, j);
+}
+
+static void
+ctxchatR(C9ctx *ctx, C9r *r)
+{
+	C9aux *a;
+	C9tag tag;
+	const char *path[2];
+	char buf[64];
+
+	a = ctx->aux;
+	switch (r->type) {
+	case Rversion:
+		c9attach(ctx, &tag, Rootfid, C9nofid, "none", NULL);
+		path[0] = "chat";
+		path[1] = NULL;
+		c9walk(ctx, &tag, Rootfid, Chatfid, path);
+		c9open(ctx, &tag, Chatfid, C9rdwr);
+		break;
+
+	case Rread:
+		if (chatoff >= skipuntil)
+			output(r->read.data, r->read.size);
+		chatoff += r->read.size;
+		/* fallthrough */
+	case Ropen:
+		if ((a->flags & Joined) == 0 && printjoin) {
+			c9write(ctx, &tag, Chatfid, 0, buf, snprintf(buf, sizeof(buf), "JOIN %s to chat\n", nick));
+			a->flags |= Joined;
+		}
+		c9read(ctx, &tag, Chatfid, chatoff, chatoff < skipuntil ? skipuntil-chatoff : Msize);
+		break;
+
+	case Rerror:
+		fprintf(stderr, "chat error: %s\n", r->error);
+		a->flags |= Error;
+		break;
+
+	default:
+		break;
+	}
+}
+
+static void
+ctxregistryR(C9ctx *ctx, C9r *r)
+{
+	char *s, *b;
+	C9aux *a;
+	C9tag tag;
+	const char *path[2];
+
+	a = ctx->aux;
+	switch (r->type) {
+	case Rversion:
+		c9attach(ctx, &tag, Rootfid, C9nofid, "none", NULL);
+		path[0] = "index";
+		path[1] = NULL;
+		c9walk(ctx, &tag, Rootfid, Indexfid, path);
+		c9open(ctx, &tag, Indexfid, C9read);
+		break;
+
+	case Ropen:
+		c9read(ctx, &tag, Indexfid, 0, Msize);
+		break;
+
+	case Rread:
+		r->read.data[r->read.size] = 0;
+		for (s = (char*)r->read.data;;) {
+			if ((s = strstr(s, "gridchat")) == NULL)
+				break;
+			for (b = s; b != (char*)r->read.data && *b != '\n'; b--);
+			if (*b == '\n')
+				b++;
+			if ((s = strchr(s, '\n')) == NULL)
+				s = (char*)&r->read.data[r->read.size];
+			*s = 0;
+			if (strstr(b, "tlssrv") == NULL && (s = strchr(b, ' ')) != NULL) {
+				*s = 0;
+				close(a->f);
+				if ((a->f = dial(b)) < 0)
+					exit(1);
+				a->flags = 0;
+				a->r = ctxchatR;
+				a->wroff = 0;
+				c9version(ctx, &tag, Msize);
+				if (wrsend(a) != 0)
+					exit(1);
+				return;
+			}
+		}
+		fprintf(stderr, "chat hasn't been found in the registry\n");
+		exit(1);
+		break;
+
+	case Rerror:
+		fprintf(stderr, "registry error: %s\n", r->error);
+		a->flags |= Error;
+		break;
+
+	default:
+		break;
+	}
+}
+
+__attribute__ ((format (printf, 1, 2)))
+static void
+ctxerror(const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	vfprintf(stderr, fmt, ap);
+	fprintf(stderr, "\n");
+	va_end(ap);
+}
+
+static C9aux *
+srv(char *s)
+{
+	C9aux *c;
+	int f;
+
+	if ((f = dial(s)) < 0)
+		return NULL;
+	c = calloc(1, sizeof(*c));
+	c->f = f;
+	c->read = ctxread;
+	c->begin = ctxbegin;
+	c->end = ctxend;
+	c->error = ctxerror;
+	c->aux = c;
+
+	return c;
+}
+
+static C9aux *
+registry(void)
+{
+	C9aux *a;
+	C9tag tag;
+	int i;
+
+	for (i = 0; i < 10; i++) {
+		if ((a = srv("tcp!registry.9gridchan.org!6675")) != NULL)
+			break;
+		sleep(5);
+	}
+	if (a == NULL)
+		return NULL;
+
+	a->r = ctxregistryR;
+	c9version((C9ctx*)a, &tag, Msize);
+	wrsend(a);
+	while (c9proc((C9ctx*)a) == 0 && a->r == ctxregistryR)
+		wrsend(a);
+
+	return a;
+}
+
+static int
+chatrw(C9aux *a)
+{
+	struct timeval t;
+	fd_set r, e;
+	int n, sz;
+	C9tag tag;
+	C9ctx *ctx;
+	char *s;
+
+	FD_ZERO(&r);
+	FD_SET(a->f, &r);
+	FD_SET(0, &r);
+	FD_ZERO(&e);
+	FD_SET(a->f, &e);
+	FD_SET(0, &e);
+	memset(&t, 0, sizeof(t));
+	t.tv_sec = 10;
+	for (;;) {
+		errno = 0;
+		if ((n = select(a->f + 1, &r, NULL, &e, &t)) < 0 || FD_ISSET(a->f, &e) || FD_ISSET(0, &e)) {
+			if (errno == EINTR)
+				continue;
+			return -1;
+		}
+		break;
+	}
+
+	ctx = (C9ctx*)a;
+	if (FD_ISSET(a->f, &r)) {
+		c9proc(ctx);
+	} else if (FD_ISSET(0, &r)) {
+		s = (char*)a->rdbuf;
+		sz = sprintf(s, "%s → ", nick);
+		for (;;) {
+			if ((n = read(0, s+sz, sizeof(a->rdbuf)-sz)) > 0)
+				sz += n;
+			else
+				exit(0);
+			if (s[sz-1] != '\n'){
+				s[sz-1] = '\n';
+			}else{
+				c9write(ctx, &tag, Chatfid, 0, s, sz);
+				break;
+			}
+		}
+	} else {
+		const char *path[] = {NULL};
+		c9walk(ctx, &tag, Rootfid, Rootfid, path);
+	}
+
+	return 0;
+}
+
+int
+main(int argc, char **argv)
+{
+	struct termios t;
+	C9aux *a;
+	int c, noecho;
+
+	if (noecho && tcgetattr(0, &t) == 0) {
+		t.c_lflag &= ~ECHO;
+		tcsetattr(STDIN_FILENO, TCSANOW, &t);
+	}
+
+	for (;;) {
+		if ((a = registry()) == NULL)
+			return 1;
+		while (chatrw(a) == 0 && wrsend(a) == 0);
+		if (a->flags & (Disconnected|Error)) {
+			a->flags &= ~(Disconnected|Error);
+			skipuntil = chatoff;
+			chatoff = 0;
+			free(a);
+		} else {
+			printf("exiting\n");
+			exit(1);
+		}
+	}
+
+	return 0;
+}
--- a/x9dev.c
+++ b/x9dev.c
@@ -24,66 +24,52 @@
 #ifdef HAVE_DIX_CONFIG_H
 #include <dix-config.h>
 #endif
+#include "glx_extinit.h"
 
-#include <X11/X.h>
-#include "mi.h"
-#define NEED_EVENTS
-#include <X11/Xproto.h>
-#include <X11/Xos.h>
-#include <X11/Xpoll.h>
-#define XK_TECHNICA
-#define XK_PUBLISHING
-#include <X11/keysym.h>
-#include <X11/keysymdef.h>
-#include "scrnintstr.h"
-#include "servermd.h"
-#define PSZ 8
-#include "fb.h"
-#include "colormapst.h"
-#include "gcstruct.h"
-#include "input.h"
-#include "mipointer.h"
-#include "micmap.h"
-#include "dix.h"
-#include "miline.h"
-#include "shadow.h"
-#include "xkbsrv.h"
-#include "xserver-properties.h"
-#include "exevents.h"
-#include "extinit.h"
-#include "keymap.h"
-#include "x9dev.h"
+void
+InitOutput(ScreenInfo *si, int argc, char *argv[])
+{
+    int i;
 
-x9devInfo x9di;
+    si->imageByteOrder = IMAGE_BYTE_ORDER;
+    si->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT;
+    si->bitmapScanlinePad = BITMAP_SCANLINE_PAD;
+    si->bitmapBitOrder = BITMAP_BIT_ORDER;
+    si->numPixmapFormats = NUMFORMATS;
+    for (i = 0; i < NUMFORMATS; i++)
+        si->formats[i] = formats[i];
+    if (AddScreen(x9devScreenInit, argc, argv) < 0)
+        FatalError("InitOutput: can't addscreen");
+}
 
-static DeviceIntPtr x9devMouse;
-static DeviceIntPtr x9devKeybd;
-static int  oldx, oldy, oldbut;
+void
+InitInput(int argc, char *argv[])
+{
+    Atom xiclass;
+    
+    x9devMouse = AddInputDevice(serverClient, x9devMouseProc, TRUE);
+    x9devKeybd = AddInputDevice(serverClient, x9devKeybdProc, TRUE);
+    xiclass = MakeAtom(XI_MOUSE, sizeof(XI_MOUSE) - 1, TRUE);
+    AssignTypeAndName(x9devMouse, xiclass, "x9dev mouse");
+    xiclass = MakeAtom(XI_KEYBOARD, sizeof(XI_KEYBOARD) - 1, TRUE);
+    AssignTypeAndName(x9devKeybd, xiclass, "x9dev keyboard");
 
-static CARD8 modmap[MAP_LENGTH];
+    mieqInit();
+}
 
-static PixmapFormatRec formats[] = {
-    { 1,    1,  BITMAP_SCANLINE_PAD },
-    { 8,    8,  BITMAP_SCANLINE_PAD },
-    { 16,   16,     BITMAP_SCANLINE_PAD },
-    { 24,   24,     BITMAP_SCANLINE_PAD },
-    { 32,   32,     BITMAP_SCANLINE_PAD }
-};
-#define NUMFORMATS (sizeof(formats)/sizeof((formats)[0]))
-
-#define x9devSaveScreen (void *) NoopDDA
-#define x9devConstrainCursor    (void *) NoopDDA
-#define x9devDisplayCursor  (void *) NoopDDA
-#define x9devRealizeCursor  (void *) NoopDDA
-#define x9devUnrealizeCursor    (void *) NoopDDA
-#define x9devRecolorCursor  (void *) NoopDDA
-#define x9devSetCursorPosition  (void *) NoopDDA
-
 void
-OsVendorInit(void)
+ddxUseMsg(void)
 {
+    ErrorF("\nx9srv Option Usage:\n");
+    ErrorF("-D enable debug\n");
 }
 
+int
+ddxProcessArgument(int argc, char **argv, int i)
+{
+    // Passed in arg[i], act on it
+}
+
 void
 ddxGiveUp(enum ExitCode error)
 {
@@ -96,7 +82,6 @@
     ;
 }
 
-
 /* we may need to do some weird stuff here in the future */
 #if defined(DDXBEFORERESET)
 void
@@ -107,23 +92,16 @@
 
 
 void
-ddxUseMsg(void)
+DDXRingBell(int volume, int pitch, int duration)
 {
 }
 
 void
-DDXRingBell(int volume, int pitch, int duration)
+OsVendorInit(void)
 {
-}
 
-
-int
-ddxProcessArgument(int argc, char *argv[], int i)
-{
-    return 0;
 }
 
-
 Bool
 LegalModifier(unsigned int k, DeviceIntPtr pDev)
 {
@@ -134,470 +112,4 @@
 ProcessInputEvents(void)
 {
     mieqProcessInputEvents();
-}
-
-
-#define e    ev.u.u
-#define ek    ev.u.keyButtonPointer
-static void
-x9devSendKeybdEvent(int k, int t)
-{
-    xEvent ev;
-
-    memset(&ev, 0, sizeof(xEvent));
-    e.type = t;
-    e.detail = k + MIN_KEYCODE;
-    ek.time = GetTimeInMillis();
-    mieqEnqueue(x9devKeybd, (InternalEvent *)&ev);
-}
-
-static void
-x9devSendMouseEvent(int x, int y, int b, int t)
-{
-    xEvent ev;
-
-    memset(&ev, 0, sizeof(xEvent));
-    e.type = t;
-    e.detail = b;
-    ek.rootX = x;
-    ek.rootY = y;
-    ek.time = GetTimeInMillis();
-    mieqEnqueue(x9devMouse, (InternalEvent *)&ev);
-}
-#undef ek
-#undef e
-
-static void
-x9devRefreshScreen(int x1, int y1, int x2, int y2)
-{
-    /* 
-    Rectangle r;
-    uchar *p;
-    int n;
-
-    p = (uchar *)x9di.fb+(y1*x9di.width+x1)*(x9di.depth/8);
-    r = rectaddpt(Rect(x1, y1, x2, y2), screen->r.min);
-    if (Dx(r) == x9di.width) {
-        if (loadimage(screen, r, p, x9di.bpl * Dy(r)) < 0)
-            FatalError("can't load image");
-        goto End;
-    }
-    n = Dx(r)*(x9di.depth/8);
-    y2 += screen->r.min.y;
-       while(r.min.y < y2) {
-        r.max.y = r.min.y+1;
-        if (loadimage(screen, r, p, n) < 0)
-            FatalError("can't load image");
-        p += x9di.bpl;
-        r.min.y++;
-    }
-
-End:
-    flushimage(display, 1);
-    */
-}
-
-static void
-x9devResize(void)
-{
-    /*
-    if (getwindow(display, Refnone) < 0)
-        FatalError("can't reattach to window");
-
-    draw(screen, screen->r, display->white, nil, ZP);
-    x9devRefreshScreen(0, 0, x9di.width, x9di.height);
-    */
-}
-
-static int
-x9devMouseRead(int *x, int *y, int *b)
-{
-    char    buf[1+4*12];
-    int n;
-
-    if ((n = read(x9di.mouseFd, buf, sizeof buf)) <= 0)
-        return 0;
-
-    if (n != 1 + 4 * 12)
-        FatalError("Bad mouse event");
-
-    if (buf[0] == 'r') {
-        x9devResize();
-        return 0;
-    }
-    *x = atoi(buf + 1 + 0 * 12) - screen->r.min.x;
-    *y = atoi(buf + 1 + 1 * 12) - screen->r.min.y;
-    *b = atoi(buf + 1 + 2 * 12);
-
-    return 1;
-}
-
-static wchar_t
-x9devKeybdRead(void)
-{
-    static char s[3];
-    static int  n = 0;
-    wchar_t rune;
-
-    if (read(x9di.keybdFd, s + n, 1) != 1)
-        return 0;
-
-    rune = s[0];
-    if (n > 0 || (rune & 0x80) != 0x00) {
-        if (mbtowc(&rune, s, n + 1) == -1) {
-            /* incomplete rune; wait until next char */
-            if (++n == 3)
-                n = 0;
-            return 0;
-        }
-        n = 0;
-    }
-    if (rune == Kdown)
-        rune = 0x99;
-    else if (rune & KF)
-        rune = (rune&~KF) + 0x80;
-
-    return rune;
-}
-
-static void
-x9devInfoInit(void)
-{
-/*
-    char    buf[256];
-
-    if(initdraw(NULL, 0, "x9dev") < 0)
-        FatalError("can't open display");
-
-    x9di.depth = screen->depth;
-    x9di.width = Dx(screen->r);
-    x9di.width -= x9di.width&(screen->depth/8);
-    x9di.dpi = 100;
-    x9di.bpl = bytesperline(Rect(0, 0, x9di.width, x9di.height), x9di.depth);
-    x9di.fb = malloc(x9di.bpl * x9di.height);
-    if (x9di.fb == nil)
-        FatalError("couldn't allocate framebuffer");
-
-    snprint(buf, sizeof buf, "%s/mouse", display->devdir);
-    x9di.mouseFd = open(buf, O_RDWR | O_NONBLOCK);
-    if(x9di.mouseFd < 0)
-        FatalError("can't open mouse");
-
-    snprint(buf, sizeof buf, "%s/cons", display->devdir);
-    x9di.keybdFd = open(buf, O_RDONLY | O_NONBLOCK);
-    if(x9di.keybdFd < 0)
-        FatalError("can't open keyboard");
-
-    snprint(buf, sizeof buf, "%s/consctl", display->devdir);
-    x9di.consctlFd = open(buf, O_WRONLY);
-    if(x9di.consctlFd < 0)
-        FatalError("can't open consctl");
-    if(write(x9di.consctlFd, "rawon", 5) != 5)
-        FatalError("can't set rawon");
-*/
-}
-
-static int  
-x9devKeybdHandle(void)
-{
-    unsigned char   k, m;
-    int c;
-
-    c = x9devKeybdRead();
-    if (c == 0 || c > sizeof(rune2keycode))
-        return 0;
-
-    k = rune2keycode[c].key;
-    if (k == 0)
-        return 0;
-
-    m = rune2keycode[c].mod;
-    if (m) 
-        x9devSendKeybdEvent(m, KeyPress);
-
-    x9devSendKeybdEvent(k, KeyPress);
-    x9devSendKeybdEvent(k, KeyRelease);
-    if (m) 
-        x9devSendKeybdEvent(m, KeyRelease);
-
-    return 1;
-}
-
-
-static int  
-x9devMouseHandle(void)
-{
-    int x, y, b, but, t;
-
-    if (!x9devMouseRead(&x, &y, &but))
-        return 0;
-
-    t = b = 0;
-    if (x != oldx || y != oldy) {
-        t = MotionNotify;
-        oldx = x, oldy = y;
-    }
-    if (but != oldbut) {
-        b = oldbut ^ but;
-        t = ButtonPress;
-        if (oldbut & b)
-            t = ButtonRelease;
-        if (b == 4)
-            b = 3;
-        if (but & (8 | 16)) {
-            if (b & 8)
-                b = 4;
-            else
-                b = 5;
-            x9devSendMouseEvent(x, y, b, ButtonPress);
-            x9devSendMouseEvent(x, y, b, ButtonRelease);
-            return 1;
-        }
-    }
-    x9devSendMouseEvent(x, y, b, t);
-    oldbut = but;
-
-    return 1;
-}
-
-
-static void
-x9devWakeupHandler(ScreenPtr scr, int result)
-{
-
-    if (result <= 0)
-        return;
-
-    while (x9devMouseHandle())
-        ;
-    while (x9devKeybdHandle())
-        ;
-}
-
-
-static void
-x9devInitModmap(void)
-{
-    KeySym * ks;
-    int i;
-
-    for (i = 0; i < MAP_LENGTH; i++)
-        modmap[i] = NoSymbol;
-
-    for (i = MIN_KEYCODE, ks = map; i < (MIN_KEYCODE + NUM_KEYCODES); i++, ks += MAP_WIDTH)
-        switch (*ks) {
-        case XK_Shift_L:
-        case XK_Shift_R:
-            modmap[i] = ShiftMask;
-            break;
-        case XK_Control_L:
-        case XK_Control_R:
-            modmap[i] = ControlMask;
-            break;
-        case XK_Alt_L:
-        case XK_Alt_R:
-            modmap[i] = Mod1Mask;
-            break;
-        }
-}
-
-static int  
-x9devKeybdProc(DeviceIntPtr pDev, int what)
-{
-
-    switch (what) {
-    case DEVICE_INIT:
-        x9devInitModmap();
-        if (!InitKeyboardDeviceStruct(pDev, NULL, 
-            (BellProcPtr)NoopDDA, (KbdCtrlProcPtr)NoopDDA))
-            FatalError("can't init keyboard");
-	pDev->inited = TRUE;
-        break;
-    case DEVICE_ON:
-        pDev->enabled = TRUE;
-        break;
-    case DEVICE_CLOSE:
-	break;
-    case DEVICE_OFF:
-        pDev->enabled = FALSE;
-        break;
-    }
-    return Success;
-}
-
-static int  
-x9devMouseProc(DeviceIntPtr pDevice, int what)
-{
-    static unsigned char    map[] = {0, 1, 2, 3, 4, 5};
-    DevicePtr pDev = (DevicePtr)pDevice;
-    Atom btn_labels[3] = {0};
-    Atom axes_labels[2] = {0};
-
-
-    switch (what) {
-    case DEVICE_INIT:
-        btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT);
-        btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE);
-        btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT);
-
-        axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X);
-        axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y);
-        InitPointerDeviceStruct(pDev, map, 3, btn_labels,
-            (PtrCtrlProcPtr)NoopDDA, GetMotionHistorySize(), 2, axes_labels);
-        break;
-
-    case DEVICE_ON:
-        pDev->on = TRUE;
-        break;
-
-    case DEVICE_CLOSE:
-    case DEVICE_OFF:
-        pDev->on = FALSE;
-        break;
-    }
-    return Success;
-}
-
-
-void
-InitInput(int argc, char *argv[])
-{
-    Atom xiclass;
-    
-    x9devMouse = AddInputDevice(serverClient, x9devMouseProc, TRUE);
-    x9devKeybd = AddInputDevice(serverClient, x9devKeybdProc, TRUE);
-    xiclass = MakeAtom(XI_MOUSE, sizeof(XI_MOUSE) - 1, TRUE);
-    AssignTypeAndName(x9devMouse, xiclass, "x9dev mouse");
-    xiclass = MakeAtom(XI_KEYBOARD, sizeof(XI_KEYBOARD) - 1, TRUE);
-    AssignTypeAndName(x9devKeybd, xiclass, "x9dev keyboard");
-
-    mieqInit();
-}
-
-static void
-x9devCursorLimits(DeviceIntPtr dptr, ScreenPtr spr, CursorPtr cpr, BoxPtr hot, BoxPtr topleft)
-{
-    *topleft = *hot;
-}
-
-static void
-x9devShadowUpdate(ScreenPtr pScreen, shadowBufPtr pBuf)
-{
-    BoxPtr pbox;
-
-    pbox = REGION_EXTENTS(pScreen, &pBuf->pDamage);
-    x9devRefreshScreen(pbox->x1, pbox->y1, pbox->x2, pbox->y2);
-}
-
-
-/* callback dance... */
-static CreateScreenResourcesProcPtr x9devCreateResourcesPtr;
-
-static Bool
-x9devCreateResources(ScreenPtr pScreen)
-{
-    Bool ret = 0;
-
-    pScreen->CreateScreenResources = x9devCreateResourcesPtr;
-    if (pScreen->CreateScreenResources)
-        ret = pScreen->CreateScreenResources(pScreen);
-
-    x9devCreateResourcesPtr = pScreen->CreateScreenResources;
-    pScreen->CreateScreenResources = x9devCreateResourcesPtr;
-    if (ret == FALSE)
-        return FALSE;
-
-    shadowRemove(pScreen, pScreen->GetScreenPixmap(pScreen));
-    if (!shadowAdd(pScreen, pScreen->GetScreenPixmap(pScreen), x9devShadowUpdate, NULL, SHADOW_ROTATE_0, 0))
-        return FALSE;
-
-    return ret;
-}
-
-static Bool
-x9devScreenInit(ScreenPtr pScreen, int argc, char *argv[])
-{
-    int v, i;
-    unsigned long   r, g, b;
-    static int  first = 1;
-
-    if (first) {
-        x9devInfoInit();
-        first = 0;
-    }
-
-    for (i = 0; i < NUMFORMATS; i++)
-        fbSetVisualTypes(formats[i].depth, 0, 8);
-
-    switch (x9di.depth) {
-    case 16:
-        r = 0xF800, g = 0x07E0, b = 0x001F;
-        v = 1 << TrueColor;
-        break;
-    case 24:
-    case 32:
-        r = 0xFF0000, g = 0x00FF00, b = 0x0000FF;
-        v = 1 << TrueColor;
-        break;
-    default:
-        r = g = b = 0;
-        v = 1 << PseudoColor;
-    }
-    if (!fbSetVisualTypesAndMasks(x9di.depth, v, 8, r, g, b))
-        return FALSE;
-
-    if (monitorResolution)
-        x9di.dpi = monitorResolution;
-    if (!fbScreenInit(pScreen, x9di.fb, x9di.width, x9di.height,
-        x9di.dpi, x9di.dpi, x9di.width, x9di.depth))
-        return FALSE;
-
-    pScreen->mmWidth = x9di.width * 25.4 / x9di.dpi;
-    pScreen->mmHeight = x9di.height * 25.4 / x9di.dpi;
-
-    /* cursor */
-    pScreen->ConstrainCursor = x9devConstrainCursor;
-    pScreen->CursorLimits = x9devCursorLimits;
-    pScreen->DisplayCursor = x9devDisplayCursor;
-    pScreen->RealizeCursor = x9devRealizeCursor;
-    pScreen->UnrealizeCursor = x9devUnrealizeCursor;
-    pScreen->RecolorCursor = x9devRecolorCursor;
-    pScreen->SetCursorPosition = x9devSetCursorPosition;
-
-    pScreen->SaveScreen = x9devSaveScreen;
-    pScreen->WakeupHandler = x9devWakeupHandler;
-
-#ifdef RENDER
-    if (!fbPictureInit(pScreen, 0, 0))
-        return FALSE;
-#endif
-
-   if (!shadowSetup(pScreen))
-        return FALSE;
-
-    x9devCreateResourcesPtr = pScreen->CreateScreenResources;
-    pScreen->CreateScreenResources = x9devCreateResources;
-
-    if (!fbCreateDefColormap(pScreen))
-        return FALSE;
-
-    return TRUE;
-}
-
-
-void
-InitOutput(ScreenInfo *si, int argc, char *argv[])
-{
-    int i;
-
-    si->imageByteOrder = IMAGE_BYTE_ORDER;
-    si->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT;
-    si->bitmapScanlinePad = BITMAP_SCANLINE_PAD;
-    si->bitmapBitOrder = BITMAP_BIT_ORDER;
-    si->numPixmapFormats = NUMFORMATS;
-    for (i = 0; i < NUMFORMATS; i++)
-        si->formats[i] = formats[i];
-    if (AddScreen(x9devScreenInit, argc, argv) < 0)
-        FatalError("InitOutput: can't addscreen");
-}
-
+}
\ No newline at end of file
--- a/x9dev.h
+++ b/x9dev.h
@@ -21,20 +21,27 @@
  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 
+#ifndef _X9DEV_H_
+#define _X9DEV_H_
+#include <stdio.h>
+#include <unistd.h>
+
 typedef struct x9devInfo x9devInfo;
 
 struct x9devInfo
 {
     char    *fb;
-    int depth;
-    int width;
-    int height;
-    int dpi;
-    int bpl;
-    int mouseFd;
-    int keybdFd;
-    int consctlFd;
+    int     depth;
+    int     width;
+    int     height;
+    int     dpi;
+    int     bpl;
+    int     mouseFd;
+    int     keybdFd;
+    int     consctlFd;
 };
 
-#define KF	0xF000
-#define Kdown	0x80
+#define KF      0xF000
+#define Kdown   0x80
+
+#endif