]> git.armaanb.net Git - st.git/blobdiff - st.c
Uses a &[] pointer loop instead of + pointer loop
[st.git] / st.c
diff --git a/st.c b/st.c
index f87412761b88210cd9423c8dd08dfe4ea4922447..5e92db20ac6d9131e206f25d32a73eef27cf2049 100644 (file)
--- a/st.c
+++ b/st.c
@@ -1,4 +1,4 @@
-/* See LICENSE for licence details. */
+/* See LICENSE for license details. */
 #include <ctype.h>
 #include <errno.h>
 #include <fcntl.h>
@@ -158,8 +158,7 @@ enum escape_state {
 
 enum window_state {
        WIN_VISIBLE = 1,
-       WIN_REDRAW  = 2,
-       WIN_FOCUSED = 4
+       WIN_FOCUSED = 2
 };
 
 enum selection_type {
@@ -352,6 +351,7 @@ static void draw(void);
 static void redraw(void);
 static void drawregion(int, int, int, int);
 static void execsh(void);
+static void stty(void);
 static void sigchld(int);
 static void run(void);
 
@@ -423,7 +423,7 @@ static void xsettitle(char *);
 static void xresettitle(void);
 static void xsetpointermotion(int);
 static void xseturgency(int);
-static void xsetsel(char *);
+static void xsetsel(char *, Time);
 static void xtermclear(int, int, int, int);
 static void xunloadfont(Font *);
 static void xunloadfonts(void);
@@ -449,7 +449,7 @@ static void selinit(void);
 static void selnormalize(void);
 static inline bool selected(int, int);
 static char *getsel(void);
-static void selcopy(void);
+static void selcopy(Time);
 static void selscroll(int, int);
 static void selsnap(int, int *, int *, int);
 static int x2col(int);
@@ -508,6 +508,7 @@ static char *opt_title = NULL;
 static char *opt_embed = NULL;
 static char *opt_class = NULL;
 static char *opt_font = NULL;
+static char *opt_line = NULL;
 static int oldbutton = 3; /* button event on startup: 3 = release */
 
 static char *usedfont = NULL;
@@ -671,7 +672,8 @@ y2row(int y) {
        return LIMIT(y, 0, term.row-1);
 }
 
-int tlinelen(int y) {
+int
+tlinelen(int y) {
        int i = term.col;
 
        if(term.line[y][i - 1].mode & ATTR_WRAP)
@@ -944,7 +946,7 @@ getsel(void) {
        ptr = str = xmalloc(bufsize);
 
        /* append every set & selected glyph to the selection */
-       for(y = sel.nb.y; y < sel.ne.y + 1; y++) {
+       for(y = sel.nb.y; y <= sel.ne.y; y++) {
                linelen = tlinelen(y);
 
                if(sel.type == SEL_RECTANGULAR) {
@@ -984,8 +986,8 @@ getsel(void) {
 }
 
 void
-selcopy(void) {
-       xsetsel(getsel());
+selcopy(Time t) {
+       xsetsel(getsel(), t);
 }
 
 void
@@ -997,7 +999,7 @@ selnotify(XEvent *e) {
        XSelectionEvent *xsev;
 
        ofs = 0;
-       xsev = (XSelectionEvent *)e;
+       xsev = &e->xselection;
        if (xsev->property == None)
            return;
        do {
@@ -1083,6 +1085,9 @@ selrequest(XEvent *e) {
        xev.selection = xsre->selection;
        xev.target = xsre->target;
        xev.time = xsre->time;
+        if (xsre->property == None)
+            xsre->property = xsre->target;
+
        /* reject */
        xev.property = None;
 
@@ -1125,11 +1130,13 @@ selrequest(XEvent *e) {
 }
 
 void
-xsetsel(char *str) {
+xsetsel(char *str, Time t) {
        free(sel.primary);
        sel.primary = str;
 
-       XSetSelectionOwner(xw.dpy, XA_PRIMARY, xw.win, CurrentTime);
+       XSetSelectionOwner(xw.dpy, XA_PRIMARY, xw.win, t);
+        if (XGetSelectionOwner(xw.dpy, XA_PRIMARY) != xw.win)
+            selclear(0);
 }
 
 void
@@ -1146,7 +1153,7 @@ brelease(XEvent *e) {
                        selclear(NULL);
                } else {
                        getbuttoninfo(e);
-                       selcopy();
+                       selcopy(e->xbutton.time);
                }
                sel.mode = 0;
                tsetdirt(sel.nb.y, sel.ne.y);
@@ -1248,11 +1255,55 @@ sigchld(int a) {
        exit(EXIT_SUCCESS);
 }
 
+
+void
+stty(void)
+{
+       char cmd[_POSIX_ARG_MAX], **p, *q, *s;
+       size_t n, siz;
+
+       if((n = strlen(stty_args)) > sizeof(cmd)-1)
+               die("incorrect stty parameters\n");
+       memcpy(cmd, stty_args, n);
+       q = cmd + n;
+       siz = sizeof(cmd) - n;
+       for(p = opt_cmd; p && (s = *p); ++p) {
+               if((n = strlen(s)) > siz-1)
+                       die("stty parameter length too long\n");
+               *q++ = ' ';
+               q = memcpy(q, s, n);
+               q += n;
+               siz-= n + 1;
+       }
+       *q = '\0';
+       system(cmd);
+}
+
 void
 ttynew(void) {
        int m, s;
        struct winsize w = {term.row, term.col, 0, 0};
 
+       if(opt_io) {
+               term.mode |= MODE_PRINT;
+               iofd = (!strcmp(opt_io, "-")) ?
+                         STDOUT_FILENO :
+                         open(opt_io, O_WRONLY | O_CREAT, 0666);
+               if(iofd < 0) {
+                       fprintf(stderr, "Error opening %s:%s\n",
+                               opt_io, strerror(errno));
+               }
+       }
+
+       if (opt_line) {
+               if((cmdfd = open(opt_line, O_RDWR)) < 0)
+                       die("open line failed: %s\n", strerror(errno));
+               close(STDIN_FILENO);
+               dup(cmdfd);
+               stty();
+               return;
+       }
+
        /* seems to work fine on linux, openbsd and freebsd */
        if(openpty(&m, &s, NULL, NULL, &w) < 0)
                die("openpty failed: %s\n", strerror(errno));
@@ -1262,6 +1313,7 @@ ttynew(void) {
                die("fork failed\n");
                break;
        case 0:
+               close(iofd);
                setsid(); /* create a new process group */
                dup2(s, STDIN_FILENO);
                dup2(s, STDOUT_FILENO);
@@ -1276,16 +1328,6 @@ ttynew(void) {
                close(s);
                cmdfd = m;
                signal(SIGCHLD, sigchld);
-               if(opt_io) {
-                       term.mode |= MODE_PRINT;
-                       iofd = (!strcmp(opt_io, "-")) ?
-                                 STDOUT_FILENO :
-                                 open(opt_io, O_WRONLY | O_CREAT, 0666);
-                       if(iofd < 0) {
-                               fprintf(stderr, "Error opening %s:%s\n",
-                                       opt_io, strerror(errno));
-                       }
-               }
                break;
        }
 }
@@ -1416,7 +1458,7 @@ treset(void) {
        term.top = 0;
        term.bot = term.row - 1;
        term.mode = MODE_WRAP;
-       memset(term.trantbl, sizeof(term.trantbl), CS_USA);
+       memset(term.trantbl, CS_USA, sizeof(term.trantbl));
        term.charset = 0;
 
        for(i = 0; i < 2; i++) {
@@ -1571,11 +1613,9 @@ tmoveto(int x, int y) {
                miny = 0;
                maxy = term.row - 1;
        }
-       LIMIT(x, 0, term.col-1);
-       LIMIT(y, miny, maxy);
        term.c.state &= ~CURSOR_WRAPNEXT;
-       term.c.x = x;
-       term.c.y = y;
+       term.c.x = LIMIT(x, 0, term.col-1);
+       term.c.y = LIMIT(y, miny, maxy);
 }
 
 void
@@ -2446,26 +2486,23 @@ tdectest(char c) {
 
 void
 tstrsequence(uchar c) {
-       if (c & 0x80) {
-               switch (c) {
-               case 0x90:   /* DCS -- Device Control String */
-                       c = 'P';
-                       break;
-               case 0x9f:   /* APC -- Application Program Command */
-                       c = '_';
-                       break;
-               case 0x9e:   /* PM -- Privacy Message */
-                       c = '^';
-                       break;
-               case 0x9d:   /* OSC -- Operating System Command */
-                       c = ']';
-                       break;
-               }
+       switch (c) {
+       case 0x90:   /* DCS -- Device Control String */
+               c = 'P';
+               break;
+       case 0x9f:   /* APC -- Application Program Command */
+               c = '_';
+               break;
+       case 0x9e:   /* PM -- Privacy Message */
+               c = '^';
+               break;
+       case 0x9d:   /* OSC -- Operating System Command */
+               c = ']';
+               break;
        }
        strreset();
        strescseq.type = c;
        term.esc |= ESC_STR;
-       return;
 }
 
 void
@@ -2547,7 +2584,6 @@ tcontrolcode(uchar ascii) {
        }
        /* only CAN, SUB, \a and C1 chars interrupt a sequence */
        term.esc &= ~(ESC_STR_END|ESC_STR);
-       return;
 }
 
 /*
@@ -2769,7 +2805,6 @@ tresize(int col, int row) {
        int i;
        int minrow = MIN(row, term.row);
        int mincol = MIN(col, term.col);
-       int slide = term.c.y - row + 1;
        bool *bp;
        TCursor c;
 
@@ -2779,20 +2814,19 @@ tresize(int col, int row) {
                return;
        }
 
-       /* free unneeded rows */
-       i = 0;
-       if(slide > 0) {
-               /*
-                * slide screen to keep cursor where we expect it -
-                * tscrollup would work here, but we can optimize to
-                * memmove because we're freeing the earlier lines
-                */
-               for(/* i = 0 */; i < slide; i++) {
-                       free(term.line[i]);
-                       free(term.alt[i]);
-               }
-               memmove(term.line, term.line + slide, row * sizeof(Line));
-               memmove(term.alt, term.alt + slide, row * sizeof(Line));
+       /*
+        * slide screen to keep cursor where we expect it -
+        * tscrollup would work here, but we can optimize to
+        * memmove because we're freeing the earlier lines
+        */
+       for(i = 0; i <= term.c.y - row; i++) {
+               free(term.line[i]);
+               free(term.alt[i]);
+       }
+       /* ensure that both src and dst are not NULL */
+       if (i > 0) {
+               memmove(term.line, term.line + i, row * sizeof(Line));
+               memmove(term.alt, term.alt + i, row * sizeof(Line));
        }
        for(i += row; i < term.row; i++) {
                free(term.line[i]);
@@ -2872,7 +2906,7 @@ xloadcols(void) {
        Color *cp;
 
        if(loaded) {
-               for (cp = dc.col; cp < dc.col + LEN(dc.col); ++cp)
+               for (cp = dc.col; cp < &dc.col[LEN(dc.col)]; ++cp)
                        XftColorFree(xw.dpy, xw.vis, xw.cmap, cp);
        }
 
@@ -3704,12 +3738,6 @@ drawregion(int x1, int y1, int x2, int y2) {
 
 void
 expose(XEvent *ev) {
-       XExposeEvent *e = &ev->xexpose;
-
-       if(xw.state & WIN_REDRAW) {
-               if(!e->count)
-                       xw.state &= ~WIN_REDRAW;
-       }
        redraw();
 }
 
@@ -3717,12 +3745,7 @@ void
 visibility(XEvent *ev) {
        XVisibilityEvent *e = &ev->xvisibility;
 
-       if(e->state == VisibilityFullyObscured) {
-               xw.state &= ~WIN_VISIBLE;
-       } else if(!(xw.state & WIN_VISIBLE)) {
-               /* need a full redraw for next Expose, not just a buf copy */
-               xw.state |= WIN_VISIBLE | WIN_REDRAW;
-       }
+       MODBIT(xw.state, e->state != VisibilityFullyObscured, WIN_VISIBLE);
 }
 
 void
@@ -3917,17 +3940,13 @@ run(void) {
        long deltatime;
 
        /* Waiting for window mapping */
-       while(1) {
+       do {
                XNextEvent(xw.dpy, &ev);
-               if(XFilterEvent(&ev, None))
-                       continue;
                if(ev.type == ConfigureNotify) {
                        w = ev.xconfigure.width;
                        h = ev.xconfigure.height;
-               } else if(ev.type == MapNotify) {
-                       break;
                }
-       }
+       } while(ev.type != MapNotify);
 
        ttynew();
        cresize(w, h);
@@ -3959,7 +3978,7 @@ run(void) {
 
                clock_gettime(CLOCK_MONOTONIC, &now);
                drawtimeout.tv_sec = 0;
-               drawtimeout.tv_nsec = (1000/xfps) * 1E6;
+               drawtimeout.tv_nsec =  (1000 * 1E6)/ xfps;
                tv = &drawtimeout;
 
                dodraw = 0;
@@ -3970,8 +3989,7 @@ run(void) {
                        dodraw = 1;
                }
                deltatime = TIMEDIFF(now, last);
-               if(deltatime > (xev? (1000/xfps) : (1000/actionfps))
-                               || deltatime < 0) {
+               if(deltatime > 1000 / (xev ? xfps : actionfps)) {
                        dodraw = 1;
                        last = now;
                }
@@ -4014,14 +4032,16 @@ run(void) {
 
 void
 usage(void) {
-       die("%s " VERSION " (c) 2010-2015 st engineers\n" \
+       die("%s " VERSION " (c) 2010-2015 st engineers\n"
        "usage: st [-a] [-v] [-c class] [-f font] [-g geometry] [-o file]\n"
-       "          [-i] [-t title] [-w windowid] [-e command ...]\n", argv0);
+       "          [-i] [-t title] [-w windowid] [-e command ...] [command ...]\n"
+       "       st [-a] [-v] [-c class] [-f font] [-g geometry] [-o file]\n"
+       "          [-i] [-t title] [-w windowid] [-l line] [stty_args ...]\n",
+       argv0);
 }
 
 int
 main(int argc, char *argv[]) {
-       char *titles;
        uint cols = 80, rows = 24;
 
        xw.l = xw.t = 0;
@@ -4036,14 +4056,8 @@ main(int argc, char *argv[]) {
                opt_class = EARGF(usage());
                break;
        case 'e':
-               /* eat all remaining arguments */
-               if(argc > 1) {
-                       opt_cmd = &argv[1];
-                       if(argv[1] != NULL && opt_title == NULL) {
-                               titles = xstrdup(argv[1]);
-                               opt_title = basename(titles);
-                       }
-               }
+               if(argc > 1)
+                       --argc, ++argv;
                goto run;
        case 'f':
                opt_font = EARGF(usage());
@@ -4058,6 +4072,9 @@ main(int argc, char *argv[]) {
        case 'o':
                opt_io = EARGF(usage());
                break;
+       case 'l':
+               opt_line = EARGF(usage());
+               break;
        case 't':
                opt_title = EARGF(usage());
                break;
@@ -4070,6 +4087,12 @@ main(int argc, char *argv[]) {
        } ARGEND;
 
 run:
+       if(argc > 0) {
+               /* eat all remaining arguments */
+               opt_cmd = argv;
+               if(!opt_title && !opt_line)
+                       opt_title = basename(xstrdup(argv[0]));
+       }
        setlocale(LC_CTYPE, "");
        XSetLocaleModifiers("");
        tnew(MAX(cols, 1), MAX(rows, 1));