Bläddra i källkod

* A few improvements to the screen/splitvt clone project.

tags/v0.99.beta14
Sam Hocevar sam 18 år sedan
förälder
incheckning
9df4f8a821
1 ändrade filer med 174 tillägg och 80 borttagningar
  1. +174
    -80
      test/term.c

+ 174
- 80
test/term.c Visa fil

@@ -20,150 +20,230 @@
# include <stdlib.h>
# include <unistd.h>
# include <fcntl.h>
# include <sys/ioctl.h>
# if defined HAVE_PTY_H
# include <pty.h> /* for openpty and forkpty */
# else
# include <util.h> /* for OS X */
# endif
#endif

#include "cucul.h"
#include "caca.h"

static int run_in_pty(char *cmd);
#define XTAB 3
#define YTAB 2

struct screen
{
cucul_canvas_t *cv;
int fd;
unsigned char *buf;
long int total;
int w, h;
};

static int create_pty(char *cmd, unsigned int w, unsigned int h);
static int set_tty_size(int fd, unsigned int w, unsigned int h);

int main(int argc, char **argv)
{
static cucul_canvas_t *cv, *app[2];
static cucul_canvas_t *cv;
static caca_display_t *dp;
unsigned char *buf[2];
long int total[2];
int ptyfd[2], pty = 0;
int w, h, eof = 0;
static struct screen *screen;
int pty = 0, prevpty = 0, i, n, w, h, eof = 0, refresh = 1, command = 0;

if(argc < 3)
if(argc < 2)
{
fprintf(stderr, "usage: %s <cmd1> <cmd2>\n", argv[0]);
fprintf(stderr, "eg. \"%s bash bash\"\n", argv[0]);
fprintf(stderr, "usage: %s <cmd1> [<cmd2> [<cmd3> ...]]\n", argv[0]);
fprintf(stderr, "eg. \"%s zsh bash\"\n", argv[0]);
return 1;
}

cv = cucul_create_canvas(80 + 7, 24 + 7);
cv = cucul_create_canvas(0, 0);
dp = caca_create_display(cv);
if(!dp)
return 1;

// w = cucul_get_canvas_width(cv) - 7;
// h = cucul_get_canvas_height(cv) - 7;
w = 80; h = 24;
n = argc - 1;
screen = malloc(n * sizeof(struct screen));

if(w < 0 || h < 0)
return 1;
w = cucul_get_canvas_width(cv);
h = cucul_get_canvas_height(cv);

w = w <= XTAB * n ? 1 : w - XTAB * n;
h = h <= YTAB * n ? 1 : h - YTAB * n;

app[0] = cucul_create_canvas(w, h);
app[1] = cucul_create_canvas(w, h);
for(i = 0; i < n; i++)
screen[i].cv = cucul_create_canvas(w, h);

cucul_set_color_ansi(cv, CUCUL_LIGHTRED, CUCUL_BLACK);
cucul_draw_thin_box(cv, pty * 5, pty * 5,
80 + pty * 5 + 1, 24 + pty * 5 + 1);
cucul_draw_cp437_box(cv, (n - 1 - pty) * XTAB, pty * YTAB,
w + (n - 1 - pty) * XTAB + 1, h + pty * YTAB + 1);

caca_refresh_display(dp);

buf[0] = buf[1] = NULL;
total[0] = total[1] = 0;

ptyfd[0] = run_in_pty(argv[1]);
ptyfd[1] = run_in_pty(argv[2]);

if(ptyfd[0] < 0 || ptyfd[1] < 0)
return -1;

fcntl(ptyfd[0], F_SETFL, O_NDELAY);
fcntl(ptyfd[1], F_SETFL, O_NDELAY);
for(i = 0; i < n; i++)
{
screen[i].buf = NULL;
screen[i].total = 0;
screen[i].fd = create_pty(argv[i + 1], w, h);
if(screen[i].fd < 0)
return -1;
}

for(;;)
{
struct timeval tv;
fd_set fdset;
caca_event_t ev;
int i, ret, refresh = 0;

ret = caca_get_event(dp, CACA_EVENT_ANY, &ev, 0);
if(ret && ev.type & CACA_EVENT_KEY_PRESS)
{
switch(ev.data.key.ch)
{
case CACA_KEY_CTRL_A:
cucul_draw_box(cv, pty * 5, pty * 5,
80 + pty * 5 + 1, 24 + pty * 5 + 1, ' ');
pty = 1 - pty;
refresh = 1;
break;
case CACA_KEY_UP:
write(ptyfd[pty], "\x1b[A", 3); break;
case CACA_KEY_DOWN:
write(ptyfd[pty], "\x1b[B", 3); break;
case CACA_KEY_RIGHT:
write(ptyfd[pty], "\x1b[C", 3); break;
case CACA_KEY_LEFT:
write(ptyfd[pty], "\x1b[D", 3); break;
default:
write(ptyfd[pty], &ev.data.key.ch, 1); break;
}
}
int i, maxfd = 0, ret;

/* Read data, if any */
FD_ZERO(&fdset);
FD_SET(ptyfd[0], &fdset);
FD_SET(ptyfd[1], &fdset);
for(i = 0; i < n; i++)
{
FD_SET(screen[i].fd, &fdset);
if(screen[i].fd > maxfd)
maxfd = screen[i].fd;
}
tv.tv_sec = 0;
tv.tv_usec = 50000;
ret = select(ptyfd[0] + ptyfd[1] + 1, &fdset, NULL, NULL, &tv);
ret = select(maxfd + 1, &fdset, NULL, NULL, &tv);

if(ret < 0)
{
if(!total[0] && !total[1])
break;
if(errno == EINTR)
; /* We probably got a SIGWINCH, ignore it */
else
{
for(i = 0; i < n; i++)
if(screen[i].total)
break;
if(i == n)
break;
}
}
else if(ret) for(i = 0; i < 2; i++)
else if(ret) for(i = 0; i < n; i++)
{
if(FD_ISSET(ptyfd[i], &fdset))
if(FD_ISSET(screen[i].fd, &fdset))
{
ssize_t n;

buf[i] = realloc(buf[i], total[i] + 4096);
n = read(ptyfd[i], buf[i] + total[i], 4096);
screen[i].buf = realloc(screen[i].buf, screen[i].total + 4096);
n = read(screen[i].fd, screen[i].buf + screen[i].total, 4096);

if(n > 0)
total[i] += n;
screen[i].total += n;
else if(n == 0 || errno != EWOULDBLOCK)
eof = 1;
}
}

for(i = 0; i < 2; i++) if(total[i])
for(i = 0; i < n; i++) if(screen[i].total)
{
unsigned long int bytes;

bytes = cucul_import_memory(app[i], buf[i], total[i], "utf8");
bytes = cucul_import_memory(screen[i].cv, screen[i].buf, screen[i].total, "utf8");

if(bytes > 0)
{
total[i] -= bytes;
memmove(buf[i], buf[i] + bytes, total[i]);
screen[i].total -= bytes;
memmove(screen[i].buf, screen[i].buf + bytes, screen[i].total);
refresh = 1;
}
}

/* Get events, if any */
ret = caca_get_event(dp, CACA_EVENT_ANY, &ev, 0);
if(ret && (ev.type & CACA_EVENT_KEY_PRESS))
{
if(command)
{
command = 0;

switch(ev.data.key.ch)
{
case CACA_KEY_CTRL_A:
pty ^= prevpty;
prevpty ^= pty;
pty ^= prevpty;
refresh = 1;
break;
case 'n':
case ' ':
case '\0':
case CACA_KEY_CTRL_N:
prevpty = pty;
pty = (pty + 1) % n;
refresh = 1;
break;
case 'p':
case CACA_KEY_CTRL_P:
prevpty = pty;
pty = (pty + n - 1) % n;
refresh = 1;
break;
}
}
else
{
switch(ev.data.key.ch)
{
case CACA_KEY_CTRL_A:
command = 1; break;
case CACA_KEY_UP:
write(screen[pty].fd, "\x1b[A", 3); break;
case CACA_KEY_DOWN:
write(screen[pty].fd, "\x1b[B", 3); break;
case CACA_KEY_RIGHT:
write(screen[pty].fd, "\x1b[C", 3); break;
case CACA_KEY_LEFT:
write(screen[pty].fd, "\x1b[D", 3); break;
default:
write(screen[pty].fd, &ev.data.key.ch, 1); break;
}
}
}
else if(ret && (ev.type & CACA_EVENT_RESIZE))
{
w = cucul_get_canvas_width(cv);
h = cucul_get_canvas_height(cv);
w = w <= XTAB * n ? 1 : w - XTAB * n;
h = h <= YTAB * n ? 1 : h - YTAB * n;
for(i = 0; i < n; i++)
{
cucul_set_canvas_size(screen[i].cv, w, h);
set_tty_size(screen[i].fd, w, h);
}
cucul_clear_canvas(cv);
refresh = 1;
}

/* Refresh screen */
if(refresh)
{
cucul_blit(cv, 5 * !pty + 1, 5 * !pty + 1, app[!pty], NULL);
cucul_blit(cv, 5 * pty + 1, 5 * pty + 1, app[pty], NULL);
cucul_draw_thin_box(cv, pty * 5, pty * 5,
80 + pty * 5 + 1, 24 + pty * 5 + 1);
refresh = 0;

for(i = 0; i < n; i++)
{
int j = (pty + n - 1 - i) % n;
cucul_blit(cv, (n - 1 - j) * XTAB + 1,
j * YTAB + 1, screen[j].cv, NULL);
cucul_draw_cp437_box(cv, (n - 1 - j) * XTAB, j * YTAB,
w + (n - 1 - j) * XTAB + 1, h + j * YTAB + 1);
}
caca_refresh_display(dp);
}

if(eof && !total[0] && !total[1])
break;
if(eof)
{
for(i = 0; i < n; i++)
if(screen[i].total)
break;
if(i == n)
break;
}
}

caca_get_event(dp, CACA_EVENT_KEY_PRESS, NULL, -1);
@@ -171,15 +251,14 @@ int main(int argc, char **argv)
/* Clean up */
caca_free_display(dp);
cucul_free_canvas(cv);
cucul_free_canvas(app[0]);
cucul_free_canvas(app[1]);
for(i = 0; i < n; i++)
cucul_free_canvas(screen[i].cv);

return 0;
}

static int run_in_pty(char *cmd)
static int create_pty(char *cmd, unsigned int w, unsigned int h)
{
#if defined HAVE_PTY_H
char **argv;
int fd;
pid_t pid;
@@ -192,7 +271,9 @@ static int run_in_pty(char *cmd)
}
else if(pid == 0)
{
set_tty_size(0, w, h);
putenv("CACA_DRIVER=slang");
putenv("TERM=xterm");
argv = malloc(2 * sizeof(char *));
argv[0] = cmd;
argv[1] = NULL;
@@ -201,10 +282,23 @@ static int run_in_pty(char *cmd)
return -1;
}

fcntl(fd, F_SETFL, O_NDELAY);
return fd;
#else
#if 0
fprintf(stderr, "forkpty() not available\n");
return -1;
#endif
}

static int set_tty_size(int fd, unsigned int w, unsigned int h)
{
struct winsize ws;

memset(&ws, 0, sizeof(ws));
ws.ws_row = h;
ws.ws_col = w;
ioctl(fd, TIOCSWINSZ, (char *)&ws);

return 0;
}


Laddar…
Avbryt
Spara