Changeset 1432 for libcaca


Ignore:
Timestamp:
Nov 27, 2006, 2:58:00 AM (14 years ago)
Author:
Sam Hocevar
Message:
  • A few improvements to the screen/splitvt clone project.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • libcaca/trunk/test/term.c

    r1427 r1432  
    2121#   include <unistd.h>
    2222#   include <fcntl.h>
     23#   include <sys/ioctl.h>
    2324#   if defined HAVE_PTY_H
    2425#       include <pty.h>  /* for openpty and forkpty */
     26#   else
     27#       include <util.h> /* for OS X */
    2528#   endif
    2629#endif
     
    2932#include "caca.h"
    3033
    31 static int run_in_pty(char *cmd);
     34#define XTAB 3
     35#define YTAB 2
     36
     37struct screen
     38{
     39    cucul_canvas_t *cv;
     40    int fd;
     41    unsigned char *buf;
     42    long int total;
     43    int w, h;
     44};
     45
     46static int create_pty(char *cmd, unsigned int w, unsigned int h);
     47static int set_tty_size(int fd, unsigned int w, unsigned int h);
    3248
    3349int main(int argc, char **argv)
    3450{
    35     static cucul_canvas_t *cv, *app[2];
     51    static cucul_canvas_t *cv;
    3652    static caca_display_t *dp;
    37     unsigned char *buf[2];
    38     long int total[2];
    39     int ptyfd[2], pty = 0;
    40     int w, h, eof = 0;
    41 
    42     if(argc < 3)
    43     {
    44         fprintf(stderr, "usage: %s <cmd1> <cmd2>\n", argv[0]);
    45         fprintf(stderr, "eg. \"%s bash bash\"\n", argv[0]);
     53    static struct screen *screen;
     54    int pty = 0, prevpty = 0, i, n, w, h, eof = 0, refresh = 1, command = 0;
     55
     56    if(argc < 2)
     57    {
     58        fprintf(stderr, "usage: %s <cmd1> [<cmd2> [<cmd3> ...]]\n", argv[0]);
     59        fprintf(stderr, "eg. \"%s zsh bash\"\n", argv[0]);
    4660        return 1;
    4761    }
    4862
    49     cv = cucul_create_canvas(80 + 7, 24 + 7);
     63    cv = cucul_create_canvas(0, 0);
    5064    dp = caca_create_display(cv);
    5165    if(!dp)
    5266        return 1;
    5367
    54 //    w = cucul_get_canvas_width(cv) - 7;
    55 //    h = cucul_get_canvas_height(cv) - 7;
    56     w = 80; h = 24;
    57 
    58     if(w < 0 || h < 0)
    59         return 1;
    60 
    61     app[0] = cucul_create_canvas(w, h);
    62     app[1] = cucul_create_canvas(w, h);
     68    n = argc - 1;
     69    screen = malloc(n * sizeof(struct screen));
     70
     71    w = cucul_get_canvas_width(cv);
     72    h = cucul_get_canvas_height(cv);
     73
     74    w = w <= XTAB * n ? 1 : w - XTAB * n;
     75    h = h <= YTAB * n ? 1 : h - YTAB * n;
     76
     77    for(i = 0; i < n; i++)
     78        screen[i].cv = cucul_create_canvas(w, h);
    6379
    6480    cucul_set_color_ansi(cv, CUCUL_LIGHTRED, CUCUL_BLACK);
    65     cucul_draw_thin_box(cv, pty * 5, pty * 5,
    66                         80 + pty * 5 + 1, 24 + pty * 5 + 1);
     81    cucul_draw_cp437_box(cv, (n - 1 - pty) * XTAB, pty * YTAB,
     82                         w + (n - 1 - pty) * XTAB + 1, h + pty * YTAB + 1);
    6783
    6884    caca_refresh_display(dp);
    6985
    70     buf[0] = buf[1] = NULL;
    71     total[0] = total[1] = 0;
    72 
    73     ptyfd[0] = run_in_pty(argv[1]);
    74     ptyfd[1] = run_in_pty(argv[2]);
    75 
    76     if(ptyfd[0] < 0 || ptyfd[1] < 0)
    77         return -1;
    78 
    79     fcntl(ptyfd[0], F_SETFL, O_NDELAY);
    80     fcntl(ptyfd[1], F_SETFL, O_NDELAY);
     86    for(i = 0; i < n; i++)
     87    {
     88        screen[i].buf = NULL;
     89        screen[i].total = 0;
     90        screen[i].fd = create_pty(argv[i + 1], w, h);
     91        if(screen[i].fd < 0)
     92            return -1;
     93    }
    8194
    8295    for(;;)
     
    8598        fd_set fdset;
    8699        caca_event_t ev;
    87         int i, ret, refresh = 0;
    88 
    89         ret = caca_get_event(dp, CACA_EVENT_ANY, &ev, 0);
    90         if(ret && ev.type & CACA_EVENT_KEY_PRESS)
    91         {
    92             switch(ev.data.key.ch)
    93             {
    94             case CACA_KEY_CTRL_A:
    95                 cucul_draw_box(cv, pty * 5, pty * 5,
    96                                80 + pty * 5 + 1, 24 + pty * 5 + 1, ' ');
    97                 pty = 1 - pty;
    98                 refresh = 1;
    99                 break;
    100             case CACA_KEY_UP:
    101                 write(ptyfd[pty], "\x1b[A", 3); break;
    102             case CACA_KEY_DOWN:
    103                 write(ptyfd[pty], "\x1b[B", 3); break;
    104             case CACA_KEY_RIGHT:
    105                 write(ptyfd[pty], "\x1b[C", 3); break;
    106             case CACA_KEY_LEFT:
    107                 write(ptyfd[pty], "\x1b[D", 3); break;
    108             default:
    109                 write(ptyfd[pty], &ev.data.key.ch, 1); break;
    110             }
    111         }
     100        int i, maxfd = 0, ret;
    112101
    113102        /* Read data, if any */
    114103        FD_ZERO(&fdset);
    115         FD_SET(ptyfd[0], &fdset);
    116         FD_SET(ptyfd[1], &fdset);
     104        for(i = 0; i < n; i++)
     105        {
     106            FD_SET(screen[i].fd, &fdset);
     107            if(screen[i].fd > maxfd)
     108                maxfd = screen[i].fd;
     109        }
    117110        tv.tv_sec = 0;
    118111        tv.tv_usec = 50000;
    119         ret = select(ptyfd[0] + ptyfd[1] + 1, &fdset, NULL, NULL, &tv);
     112        ret = select(maxfd + 1, &fdset, NULL, NULL, &tv);
    120113
    121114        if(ret < 0)
    122115        {
    123             if(!total[0] && !total[1])
    124                 break;
    125         }
    126         else if(ret) for(i = 0; i < 2; i++)
    127         {
    128             if(FD_ISSET(ptyfd[i], &fdset))
     116            if(errno == EINTR)
     117                ; /* We probably got a SIGWINCH, ignore it */
     118            else
     119            {
     120                for(i = 0; i < n; i++)
     121                    if(screen[i].total)
     122                        break;
     123                if(i == n)
     124                    break;
     125            }
     126        }
     127        else if(ret) for(i = 0; i < n; i++)
     128        {
     129            if(FD_ISSET(screen[i].fd, &fdset))
    129130            {
    130131                ssize_t n;
    131132
    132                 buf[i] = realloc(buf[i], total[i] + 4096);
    133                 n = read(ptyfd[i], buf[i] + total[i], 4096);
     133                screen[i].buf = realloc(screen[i].buf, screen[i].total + 4096);
     134                n = read(screen[i].fd, screen[i].buf + screen[i].total, 4096);
    134135
    135136                if(n > 0)
    136                     total[i] += n;
     137                    screen[i].total += n;
    137138                else if(n == 0 || errno != EWOULDBLOCK)
    138139                    eof = 1;
     
    140141        }
    141142
    142         for(i = 0; i < 2; i++) if(total[i])
     143        for(i = 0; i < n; i++) if(screen[i].total)
    143144        {
    144145            unsigned long int bytes;
    145146
    146             bytes = cucul_import_memory(app[i], buf[i], total[i], "utf8");
     147            bytes = cucul_import_memory(screen[i].cv, screen[i].buf, screen[i].total, "utf8");
    147148
    148149            if(bytes > 0)
    149150            {
    150                 total[i] -= bytes;
    151                 memmove(buf[i], buf[i] + bytes, total[i]);
     151                screen[i].total -= bytes;
     152                memmove(screen[i].buf, screen[i].buf + bytes, screen[i].total);
    152153                refresh = 1;
    153154            }
    154155        }
    155156
     157        /* Get events, if any */
     158        ret = caca_get_event(dp, CACA_EVENT_ANY, &ev, 0);
     159        if(ret && (ev.type & CACA_EVENT_KEY_PRESS))
     160        {
     161            if(command)
     162            {
     163                command = 0;
     164
     165                switch(ev.data.key.ch)
     166                {
     167                case CACA_KEY_CTRL_A:
     168                    pty ^= prevpty;
     169                    prevpty ^= pty;
     170                    pty ^= prevpty;
     171                    refresh = 1;
     172                    break;
     173                case 'n':
     174                case ' ':
     175                case '\0':
     176                case CACA_KEY_CTRL_N:
     177                    prevpty = pty;
     178                    pty = (pty + 1) % n;
     179                    refresh = 1;
     180                    break;
     181                case 'p':
     182                case CACA_KEY_CTRL_P:
     183                    prevpty = pty;
     184                    pty = (pty + n - 1) % n;
     185                    refresh = 1;
     186                    break;
     187                }
     188            }
     189            else
     190            {
     191                switch(ev.data.key.ch)
     192                {
     193                case CACA_KEY_CTRL_A:
     194                    command = 1; break;
     195                case CACA_KEY_UP:
     196                    write(screen[pty].fd, "\x1b[A", 3); break;
     197                case CACA_KEY_DOWN:
     198                    write(screen[pty].fd, "\x1b[B", 3); break;
     199                case CACA_KEY_RIGHT:
     200                    write(screen[pty].fd, "\x1b[C", 3); break;
     201                case CACA_KEY_LEFT:
     202                    write(screen[pty].fd, "\x1b[D", 3); break;
     203                default:
     204                    write(screen[pty].fd, &ev.data.key.ch, 1); break;
     205                }
     206            }
     207        }
     208        else if(ret && (ev.type & CACA_EVENT_RESIZE))
     209        {
     210            w = cucul_get_canvas_width(cv);
     211            h = cucul_get_canvas_height(cv);
     212            w = w <= XTAB * n ? 1 : w - XTAB * n;
     213            h = h <= YTAB * n ? 1 : h - YTAB * n;
     214            for(i = 0; i < n; i++)
     215            {
     216                cucul_set_canvas_size(screen[i].cv, w, h);
     217                set_tty_size(screen[i].fd, w, h);
     218            }
     219            cucul_clear_canvas(cv);
     220            refresh = 1;
     221        }
     222
     223        /* Refresh screen */
    156224        if(refresh)
    157225        {
    158             cucul_blit(cv, 5 * !pty + 1, 5 * !pty + 1, app[!pty], NULL);
    159             cucul_blit(cv, 5 * pty + 1, 5 * pty + 1, app[pty], NULL);
    160             cucul_draw_thin_box(cv, pty * 5, pty * 5,
    161                                 80 + pty * 5 + 1, 24 + pty * 5 + 1);
     226            refresh = 0;
     227
     228            for(i = 0; i < n; i++)
     229            {
     230                int j = (pty + n - 1 - i) % n;
     231                cucul_blit(cv, (n - 1 - j) * XTAB + 1,
     232                               j * YTAB + 1, screen[j].cv, NULL);
     233                cucul_draw_cp437_box(cv, (n - 1 - j) * XTAB, j * YTAB,
     234                                     w + (n - 1 - j) * XTAB + 1, h + j * YTAB + 1);
     235            }
    162236            caca_refresh_display(dp);
    163237        }
    164238
    165         if(eof && !total[0] && !total[1])
    166             break;
     239        if(eof)
     240        {
     241            for(i = 0; i < n; i++)
     242                if(screen[i].total)
     243                    break;
     244            if(i == n)
     245                break;
     246        }
    167247    }
    168248
     
    172252    caca_free_display(dp);
    173253    cucul_free_canvas(cv);
    174     cucul_free_canvas(app[0]);
    175     cucul_free_canvas(app[1]);
     254    for(i = 0; i < n; i++)
     255        cucul_free_canvas(screen[i].cv);
    176256
    177257    return 0;
    178258}
    179259
    180 static int run_in_pty(char *cmd)
     260static int create_pty(char *cmd, unsigned int w, unsigned int h)
    181261{
    182 #if defined HAVE_PTY_H
    183262    char **argv;
    184263    int fd;
     
    193272    else if(pid == 0)
    194273    {
     274        set_tty_size(0, w, h);
    195275        putenv("CACA_DRIVER=slang");
     276        putenv("TERM=xterm");
    196277        argv = malloc(2 * sizeof(char *));
    197278        argv[0] = cmd;
     
    202283    }
    203284
     285    fcntl(fd, F_SETFL, O_NDELAY);
    204286    return fd;
    205 #else
     287#if 0
    206288    fprintf(stderr, "forkpty() not available\n");
    207289    return -1;
     
    209291}
    210292
     293static int set_tty_size(int fd, unsigned int w, unsigned int h)
     294{
     295    struct winsize ws;
     296
     297    memset(&ws, 0, sizeof(ws));
     298    ws.ws_row = h;
     299    ws.ws_col = w;
     300    ioctl(fd, TIOCSWINSZ, (char *)&ws);
     301
     302    return 0;
     303}
     304
Note: See TracChangeset for help on using the changeset viewer.