diff -uNr gpm-1.20.1_orig/src/gpm.c gpm-1.20.1/src/gpm.c
--- gpm-1.20.1_orig/src/gpm.c	2004-02-24 00:57:40.000000000 +0200
+++ gpm-1.20.1/src/gpm.c	2004-02-24 01:09:03.428662464 +0200
@@ -21,6 +21,11 @@
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  ********/
 
+/*
+ * Xwindow Copy&Paste patch
+ * (c) 2004 Alex Efros <powerman@powerman.name>
+ */
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>        /* strerror(); ?!?  */
@@ -39,12 +44,17 @@
 
 #include <linux/vt.h>      /* VT_GETSTATE */
 #include <linux/serial.h>  /* for serial console check */
-#include <sys/kd.h>        /* KDGETMODE */
+#include <sys/kd.h>        /* KDGETMODE */ /* XCaP: E_TABSZ GIO_SCRNMAP */
 #include <termios.h>       /* winsize */
 
 #include "headers/gpmInt.h"
 #include "headers/message.h"
 
+/* XCaP start */
+#include <ctype.h>             /* isspace()    */
+#include "headers/xcap.h"
+/* XCaP end */
+
 /* who the f*** runs gpm without glibc? doesn't have dietlibc __socklent_t? */
 #if !defined(__GLIBC__)
    typedef unsigned int __socklen_t;
@@ -198,6 +208,20 @@
 }
 
 /*-------------------------------------------------------------------*/
+
+/* XCaP start */
+/* inword() from /usr/src/linux-2.4.19/drivers/char/selection.c */
+static inline int inword(const unsigned char c) {
+    return ( inwordLut[c>>5] >> (c & 0x1F) ) & 1;
+}
+/* atedge() from /usr/src/linux-2.4.19/drivers/char/selection.c */
+static inline int atedge(const int p, int size_row)
+{
+    /* p+2 changed to p+1 because kernel operate with screen address */
+    return (!(p % size_row) || !((p + 1) % size_row));
+}
+/* XCaP end */
+
 static inline void selection_copy(int x1, int y1, int x2, int y2, int mode)
 {
 /*
@@ -208,6 +232,106 @@
    unsigned short *arg = (unsigned short *)buf + 1;
    int fd;
 
+    /* XCaP start */
+    int i, j;		    /* loop variables */
+    FILE *co_fptr;	    /* file with current console image */
+    char scr[SCR_SIZE];	    /* current console image */
+    int scr_lth;	    /* current console image size */
+    char scrmap[E_TABSZ];   /* current screen map for inverse translation */
+    int p1, p2;		    /* cursor top/left and bottom/right position */
+    int n1, n2;		    /* selection top/left and bottom/right position */
+    int tmp;		    /* temp integer */
+    char *bp, *obp;	    /* temp pointers to fill sel_buffer */
+
+    /* read data from the console */
+    if( ((co_fptr=fopen("/dev/vcs0","r"))==NULL) && /* usual /dev/ */
+	((co_fptr=fopen("/dev/vcc/0","r"))==NULL) ) /* devfs /dev/ */
+	    gpm_report(GPM_PR_OOPS, "open /dev/vcs0 or /dev/vcc/0");
+    scr_lth = fread(&scr, sizeof(char), SCR_SIZE-1, co_fptr);
+    fclose(co_fptr);
+    scr[scr_lth] = 0;
+    /* unmap font translation */
+    /* ... is it possible to use kernel's inverse_translate() here? */
+    if ((fd=open_console(O_RDONLY))<0)
+	gpm_report(GPM_PR_OOPS,GPM_MESS_OPEN_CON);
+    if (ioctl(fd,GIO_SCRNMAP,&scrmap))
+	gpm_report(GPM_PR_OOPS,"GIO_SCRNMAP");
+    close(fd);
+    for (j=0; j<scr_lth; j++) {
+	for (i=0; i<E_TABSZ; i++)
+	    if ((unsigned char) scrmap[i] == (unsigned char) scr[j])
+		break;
+	scr[j] = (char) i;
+    }
+    /* calc start-position and how many bytes to copy */
+    if (y1>y2) { tmp=y1; y1=y2; y2=tmp; tmp=x1; x1=x2; x2=tmp; }
+    if (y1==y2 && x1>x2) { tmp=x1; x1=x2; x2=tmp; }
+    p1 = (y1-1)*win.ws_col+x1-1;
+    p2 = (y2-1)*win.ws_col+x2-1;
+    n1 = 0;
+    n2 = 0;
+    /* selection logic from /usr/src/linux-2.4.19/drivers/char/selection.c */
+    if (mode==0) { /* character-by-character selection */
+	n1=p1;
+	n2=p2;
+    }
+    if (mode==1) { /* word-by-word selection */
+	tmp = isspace(scr[p1]);
+	for (n1 = p1; ; p1--) {
+	    if ((tmp && !isspace(scr[p1])) || (!tmp && !inword(scr[p1])))
+		break;
+	    n1 = p1;
+	    if (!(p1 % win.ws_col))
+		break;
+	}
+	tmp = isspace(scr[p2]);
+	for (n2 = p2; ; p2++) {
+	    if ((tmp && !isspace(scr[p2])) || (!tmp && !inword(scr[p2])))
+		break;
+	    n2 = p2;
+	    if (!((p2+1) % win.ws_col))
+		break;
+	}
+    }
+    if (mode==2) { /* line-by-line selection */
+	n1 = p1 - p1 % win.ws_col;
+	n2 = p2 + win.ws_col - p2 % win.ws_col - 1;
+    }
+    /* select to end of line if on trailing space */
+    if (n2 > n1 && !atedge(n2, win.ws_col) && isspace(scr[n2])) {
+	for (p2 = n2+1; ; p2++)
+	    if (!isspace(scr[p2]) || atedge(p2, win.ws_col))
+		break;
+	if (isspace(scr[p2]))
+	    n2 = p2;
+    }
+    /* save selection to sel_buffer */
+    if (mode<3) {
+	/* is the buffer big enough? */
+	if(((n2-n1+1)>=sel_buffer_lth) && ((n2-n1+1)>=SCR_SIZE)) {
+	    free(sel_buffer);
+	    sel_buffer=malloc((n2-n1+1)+1);
+	}
+	/* save selection, replacÅ trailing spaces to \n in each line */
+	bp = sel_buffer;
+	obp= sel_buffer;
+	for (i = n1; i <= n2; i++ ) {
+	    *bp = scr[i];
+	    if (!isspace(*bp++))
+		obp = bp;
+	    if (! ((i+1) % win.ws_col)) {
+		if (obp != bp) {
+		    bp = obp;
+		    *bp++ = '\n';
+		}
+		obp = bp;
+	    }
+	}
+	sel_buffer_lth = bp - sel_buffer;
+	*(sel_buffer+sel_buffer_lth) = 0;
+    }
+    /* XCaP end */
+
    buf[sizeof(short)-1] = 2;  /* set selection */
 
    arg[0]=(unsigned short)x1;
@@ -239,6 +363,12 @@
    char c=3;
    int fd;
 
+    /* XCaP start */
+    int i;
+    struct stat X0;
+    FILE *xcb;
+    /* XCaP start */
+    
    if (!opt_aged && (0 != opt_age_limit) &&
       (last_selection_time + opt_age_limit < time(0))) {
       opt_aged = 1;
@@ -249,20 +379,72 @@
       return;
    } 
 
+    /* XCaP start */
+    /* check Xwindow: if Xwindow not active - xcb freeze for 6 sec :( */
+    if (stat("/tmp/.X11-unix/X0", &X0) != -1) {
+	if (!(xcb=popen("/usr/bin/xcb -d :0 -p 0", "r")))
+	    gpm_report(GPM_PR_OOPS,"open pipe");
+	/* read Xwindow clipboard into current selection */
+	if ((i = fread(sel_buffer, sizeof(char), SCR_SIZE-1, xcb)) > 0)
+	    *(sel_buffer+(sel_buffer_lth=i)) = 0;
+	if (!WIFEXITED(pclose(xcb)))
+	    gpm_report(GPM_PR_OOPS,"close pipe");
+    }
+    fd=open_console(O_WRONLY);
+    for(i=0; i<sel_buffer_lth; i++)
+	if (ioctl(fd,TIOCSTI,&sel_buffer[i]) < 0)
+	    gpm_report(GPM_PR_OOPS,"TIOCSTI");
+    close(fd);
+    return;		/* never paste from kernel buffer */
+    /* XCaP end */
+
+/* XCaP replaced this:
+
    fd=open_console(O_WRONLY);
    if(ioctl(fd, TIOCLINUX, &c) < 0)
       gpm_report(GPM_PR_OOPS,GPM_MESS_IOCTL_TIOCLINUX);
    close(fd);
+
+ */
+ 
 }
 
 /*-------------------------------------------------------------------*/
 static  inline int do_selection(Gpm_Event *event)  /* returns 0, always */
 {
    static int x1=1, y1=1, x2, y2;
+   
+    /* XCaP start */
+    struct stat X0;
+    FILE *xcb;
+    /* XCaP end */
+    
 #define UNPOINTER() 0
 
    x2=event->x; y2=event->y;
    switch(GPM_BARE_EVENTS(event->type)) {
+       
+    /* XCaP start */
+    case GPM_UP:
+	if(event->buttons==GPM_B_LEFT) {
+	    /* check Xwindow: if Xwindow not active - xcb freeze for 6 sec :( */
+	    if (stat("/tmp/.X11-unix/X0", &X0) != -1) {
+		if (!(xcb=popen("/usr/bin/xcb -d :0 -s 0", "w")))
+		    gpm_report(GPM_PR_OOPS,"open pipe");
+		/* send currect selection to Xwindow clipboard */
+		fwrite(sel_buffer, sizeof(char), sel_buffer_lth, xcb);
+		if (!WIFEXITED(pclose(xcb)))
+		    gpm_report(GPM_PR_OOPS,"close pipe");
+	    }
+	    /*resize sel_buffer back to "normal" size*/
+	    if(sel_buffer_lth>SCR_SIZE) {
+		free(sel_buffer);
+		sel_buffer=malloc(SCR_SIZE);
+		sel_buffer_lth=SCR_SIZE;
+	    }
+	}
+    /* XCaP end */
+
       case GPM_MOVE:
          if (x2<1) x2++; else if (x2>maxx) x2--;
          if (y2<1) y2++; else if (y2>maxy) y2--;
@@ -966,6 +1148,11 @@
       maxfd=max(fd, maxfd);
    }
 
+    /* XCaP start */
+    sel_buffer=malloc(SCR_SIZE);
+    sel_buffer_lth=SCR_SIZE;
+    /* XCaP end */
+
 /*....................................... catch interesting signals */
 
    signal(SIGTERM, gpm_killed);
diff -uNr gpm-1.20.1_orig/src/gpn.c gpm-1.20.1/src/gpn.c
--- gpm-1.20.1_orig/src/gpn.c	2002-12-25 00:57:16.000000000 +0200
+++ gpm-1.20.1/src/gpn.c	2004-02-24 01:11:21.111731456 +0200
@@ -24,6 +24,11 @@
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  ********/
 
+/*
+ * Xwindow Copy&Paste patch
+ * (c) 2004 Alex Efros <powerman@powerman.name>
+ */
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>        /* strerror(); ?!? memcpy() */
@@ -56,6 +61,8 @@
 #include "headers/gpmInt.h"
 #include "headers/gpm.h"
 
+#include "headers/xcap.h"
+
 extern int errno;
 
 /*===================================================================*/
@@ -102,7 +109,7 @@
    };
 
 
-#define inwordLut (long_array+1)
+//#define inwordLut (long_array+1)
 
    for (i=0; charset[i]; ) {
       i += getsym(charset+i, &this);
@@ -111,9 +118,16 @@
       else
          next = this;
       for (c = this; c <= next; c++)
-         inwordLut[c>>5] |= 1 << (c&0x1F);
+         //inwordLut[c>>5] |= 1 << (c&0x1F);
+	 (long_array+1)[c>>5] |= 1 << (c&0x1F);
    }
-  
+
+    /* XCaP */
+    /* used in mode=1 (word-by-word selection) */
+    for (i=0; i<8; i++) 
+	inwordLut[i] = long_array[i+1];
+    /* XCaP */
+   
    if ((fd=open(option.consolename, O_WRONLY)) < 0) {
       /* try /dev/console, if /dev/tty0 failed -- is that really senseful ??? */
       free(option.consolename); /* allocated by main */
diff -uNr gpm-1.20.1_orig/src/headers/xcap.h gpm-1.20.1/src/headers/xcap.h
--- gpm-1.20.1_orig/src/headers/xcap.h	1970-01-01 03:00:00.000000000 +0300
+++ gpm-1.20.1/src/headers/xcap.h	2004-02-24 01:14:12.952607672 +0200
@@ -0,0 +1,13 @@
+/*
+ * Xwindow Copy&Paste patch
+ * (c) 2004 Alex Efros <powerman@powerman.name>
+ */
+
+#define SCR_SIZE 10240	/* current console image, for 80x25 needed only 2000 */
+
+#include <asm/types.h>	/* __u32 */
+__u32 inwordLut[8];	/* used in gpn.c and gpm.c */
+
+char *sel_buffer;	/* buffer with current selection */
+int sel_buffer_lth;	/* size of buffer with current selection */
+
