JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
update VERSION.
[st.git] / st.c
diff --git a/st.c b/st.c
index 4d04416..a6fb766 100644 (file)
--- a/st.c
+++ b/st.c
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <unistd.h>
-#include <X11/Xlib.h>
 #include <X11/Xatom.h>
-#include <X11/keysym.h>
+#include <X11/Xlib.h>
 #include <X11/Xutil.h>
+#include <X11/cursorfont.h>
+#include <X11/keysym.h>
 
 #if   defined(__linux)
  #include <pty.h>
@@ -31,7 +32,7 @@
 
 #define USAGE \
        "st-" VERSION ", (c) 2010 st engineers\n" \
-       "usage: st [-t title] [-c class] [-e cmd] [-v]\n"
+       "usage: st [-t title] [-c class] [-v] [-e cmd]\n"
 
 /* Arbitrary sizes */
 #define ESC_TITLE_SIZ 256
@@ -151,6 +152,7 @@ typedef struct {
        int ex, ey;
        struct {int x, y;}  b, e;
        char *clip;
+       Atom xtarget;
 } Selection;
 
 #include "config.h"
@@ -247,7 +249,7 @@ static CSIEscape escseq;
 static int cmdfd;
 static pid_t pid;
 static Selection sel;
-static char *opt_cmd   = NULL;
+static char **opt_cmd  = NULL;
 static char *opt_title = NULL;
 static char *opt_class = NULL;
 
@@ -369,6 +371,9 @@ selinit(void) {
        sel.mode = 0;
        sel.bx = -1;
        sel.clip = NULL;
+       sel.xtarget = XInternAtom(xw.dpy, "UTF8_STRING", 0);
+       if(sel.xtarget == None)
+               sel.xtarget = XA_STRING;
 }
 
 static inline int 
@@ -387,8 +392,8 @@ getbuttoninfo(XEvent *e, int *b, int *x, int *y) {
        if(b) 
                *b = e->xbutton.button;
 
-       *x = e->xbutton.x/xw.cw;
-       *y = e->xbutton.y/xw.ch;
+       *x = (e->xbutton.x - BORDER)/xw.cw;
+       *y = (e->xbutton.y - BORDER)/xw.ch;
        sel.b.x = sel.by < sel.ey ? sel.bx : sel.ex;
        sel.b.y = MIN(sel.by, sel.ey);
        sel.e.x = sel.by < sel.ey ? sel.ex : sel.bx;
@@ -398,8 +403,8 @@ getbuttoninfo(XEvent *e, int *b, int *x, int *y) {
 void
 bpress(XEvent *e) {
        sel.mode = 1;
-       sel.ex = sel.bx = e->xbutton.x/xw.cw;
-       sel.ey = sel.by = e->xbutton.y/xw.ch;
+       sel.ex = sel.bx = (e->xbutton.x - BORDER)/xw.cw;
+       sel.ey = sel.by = (e->xbutton.y - BORDER)/xw.ch;
 }
 
 void
@@ -419,8 +424,8 @@ selcopy(void) {
                                        memcpy(ptr, term.line[y][x].c, sl);
                                        ptr += sl;
                                }
-                       if(ls)
-                               *ptr = '\n', ptr++;
+                       if(ls && y < sel.e.y)
+                               *ptr++ = '\n';
                }
                *ptr = 0;
        }
@@ -452,7 +457,7 @@ selnotify(XEvent *e) {
 
 void
 selpaste() {
-       XConvertSelection(xw.dpy, XA_PRIMARY, XA_STRING, XA_PRIMARY, xw.win, CurrentTime);
+       XConvertSelection(xw.dpy, XA_PRIMARY, sel.xtarget, XA_PRIMARY, xw.win, CurrentTime);
 }
 
 void
@@ -473,12 +478,12 @@ selrequest(XEvent *e) {
        xa_targets = XInternAtom(xw.dpy, "TARGETS", 0);
        if(xsre->target == xa_targets) {
                /* respond with the supported type */
-               Atom string = XA_STRING;
+               Atom string = sel.xtarget;
                XChangeProperty(xsre->display, xsre->requestor, xsre->property,
                                XA_ATOM, 32, PropModeReplace,
                                (unsigned char *) &string, 1);
                xev.property = xsre->property;
-       } else if(xsre->target == XA_STRING) {
+       } else if(xsre->target == sel.xtarget) {
                XChangeProperty(xsre->display, xsre->requestor, xsre->property,
                                xsre->target, 8, PropModeReplace,
                                (unsigned char *) sel.clip, strlen(sel.clip));
@@ -545,13 +550,14 @@ die(const char *errstr, ...) {
 
 void
 execsh(void) {
-       char *args[] = {getenv("SHELL"), "-i", NULL};
-       if(opt_cmd)
-               args[0] = opt_cmd, args[1] = NULL;
-       else
-               DEFAULT(args[0], SHELL);
+       char **args;
+       char *envshell = getenv("SHELL");
+
+       DEFAULT(envshell, "sh");
        putenv("TERM="TNAME);
+       args = opt_cmd ? opt_cmd : (char*[]){envshell, "-i", NULL};
        execvp(args[0], args);
+       exit(EXIT_FAILURE);
 }
 
 void 
@@ -933,7 +939,7 @@ csihandle(void) {
        switch(escseq.mode) {
        default:
        unknown:
-               printf("erresc: unknown csi ");
+               fprintf(stderr, "erresc: unknown csi ");
                csidump();
                /* die(""); */
                break;
@@ -1205,7 +1211,7 @@ tputc(char *c) {
                                term.c.attr.mode &= ~ATTR_GFX;
                                break;
                        default:
-                               printf("esc unhandled charset: ESC ( %c\n", ascii);
+                               fprintf(stderr, "esc unhandled charset: ESC ( %c\n", ascii);
                        }
                        term.esc = 0;
                } else {
@@ -1502,6 +1508,7 @@ initfonts(char *fontstr, char *bfontstr)
 void
 xinit(void) {
        XSetWindowAttributes attrs;
+       Cursor cursor;
 
        if(!(xw.dpy = XOpenDisplay(NULL)))
                die("Can't open display\n");
@@ -1549,6 +1556,13 @@ xinit(void) {
        /* gc */
        dc.gc = XCreateGC(xw.dpy, xw.win, 0, NULL);
        
+       /* white cursor, black outline */
+       cursor = XCreateFontCursor(xw.dpy, XC_xterm);
+       XDefineCursor(xw.dpy, xw.win, cursor);
+       XRecolorCursor(xw.dpy, cursor, 
+               &(XColor){.red = 0xffff, .green = 0xffff, .blue = 0xffff},
+               &(XColor){.red = 0x0000, .green = 0x0000, .blue = 0x0000});
+
        XMapWindow(xw.dpy, xw.win);
        xhints();
        XStoreName(xw.dpy, xw.win, opt_title ? opt_title : "st");
@@ -1784,8 +1798,7 @@ kpress(XEvent *ev) {
                                if(meta && len == 1)
                                        ttywrite("\033", 1);
                                ttywrite(buf, len);
-                       } else /* 4. nothing to send */
-                               fprintf(stderr, "errkey: %d\n", (int)ksym);
+                       }
                        break;
                }
 }
@@ -1851,12 +1864,15 @@ main(int argc, char *argv[]) {
                        if(++i < argc) opt_class = argv[i];
                        break;
                case 'e':
-                       if(++i < argc) opt_cmd = argv[i];
+                       if(++i < argc) opt_cmd = &argv[i];
                        break;
                case 'v':
                default:
                        die(USAGE);
                }
+               /* -e eats every remaining arguments */
+               if(opt_cmd)
+                       break;
        }
        setlocale(LC_CTYPE, "");
        tnew(80, 24);