Changeset 1437
- Timestamp:
- Nov 27, 2006, 3:46:24 PM (17 years ago)
- Location:
- neercs/trunk
- Files:
-
- 2 added
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
neercs/trunk/configure.ac
r1436 r1437 32 32 AC_MSG_ERROR([you need libcaca version 0.99.beta10 or later])]) 33 33 34 AC_CHECK_HEADERS(stdio.h pty.h) 35 36 AC_CHECK_LIB(util, forkpty, UTIL_LIBS="${UTIL_LIBS} -lutil") 37 AC_SUBST(UTIL_LIBS) 38 34 39 # Optimizations 35 40 CFLAGS="${CFLAGS} -g -O2 -fno-strength-reduce -fomit-frame-pointer" -
neercs/trunk/src/Makefile.am
r1436 r1437 2 2 bin_PROGRAMS = neercs 3 3 4 neercs_SOURCES = main.c 4 neercs_SOURCES = main.c neercs.h term.c 5 5 neercs_CFLAGS = `pkg-config --cflags caca` 6 6 neercs_LDFLAGS = `pkg-config --libs caca` 7 neercs_LDADD = @UTIL_LIBS@ 7 8 -
neercs/trunk/src/main.c
r1436 r1437 1 1 /* 2 * $Id$ 2 * neercs console-based window manager 3 * Copyright (c) 2006 Sam Hocevar <sam@zoy.org> 4 * All Rights Reserved 3 5 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 6 * $Id$ 8 7 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the Do What The Fuck You Want To 10 * Public License, Version 2, as published by Sam Hocevar. See 11 * http://sam.zoy.org/wtfpl/COPYING for more details. 17 12 */ 18 13 19 14 #include "config.h" 20 15 16 #include <stdio.h> 17 #include <string.h> 18 #include <stdlib.h> 19 #include <unistd.h> 20 #include <fcntl.h> 21 #include <sys/ioctl.h> 22 #if defined HAVE_PTY_H 23 # include <pty.h> /* for openpty and forkpty */ 24 #else 25 # include <util.h> /* for OS X */ 26 #endif 27 #include <errno.h> 28 #include <cucul.h> 21 29 #include <caca.h> 22 30 23 int main (int argc, char **argv) 31 #include "neercs.h" 32 33 #define XTAB 5 34 #define YTAB 3 35 36 static int create_pty(char *cmd, unsigned int w, unsigned int h); 37 static int set_tty_size(int fd, unsigned int w, unsigned int h); 38 39 int main(int argc, char **argv) 24 40 { 41 static cucul_canvas_t *cv; 42 static caca_display_t *dp; 43 static struct screen *screen; 44 int pty = 0, prevpty = 0, i, n, w, h, eof = 0, refresh = 1, command = 0; 45 46 if(argc < 2) 47 { 48 fprintf(stderr, "usage: %s <cmd1> [<cmd2> [<cmd3> ...]]\n", argv[0]); 49 fprintf(stderr, "eg. \"%s zsh bash\"\n", argv[0]); 50 return 1; 51 } 52 53 cv = cucul_create_canvas(0, 0); 54 dp = caca_create_display(cv); 55 if(!dp) 56 return 1; 57 58 n = argc - 1; 59 screen = malloc(n * sizeof(struct screen)); 60 61 w = cucul_get_canvas_width(cv); 62 h = cucul_get_canvas_height(cv); 63 64 w = w <= XTAB * n ? 1 : w - XTAB * (n - 1) - 2; 65 h = h <= YTAB * n ? 1 : h - YTAB * (n - 1) - 2; 66 67 for(i = 0; i < n; i++) 68 { 69 screen[i].cv = cucul_create_canvas(w, h); 70 screen[i].init = 0; 71 } 72 73 cucul_set_color_ansi(cv, CUCUL_LIGHTRED, CUCUL_BLACK); 74 cucul_draw_cp437_box(cv, (n - 1 - pty) * XTAB, pty * YTAB, 75 w + (n - 1 - pty) * XTAB + 1, h + pty * YTAB + 1); 76 77 caca_refresh_display(dp); 78 79 for(i = 0; i < n; i++) 80 { 81 screen[i].buf = NULL; 82 screen[i].total = 0; 83 screen[i].fd = create_pty(argv[i + 1], w, h); 84 if(screen[i].fd < 0) 85 return -1; 86 } 87 88 for(;;) 89 { 90 struct timeval tv; 91 fd_set fdset; 92 caca_event_t ev; 93 int maxfd = 0, ret; 94 95 /* Read data, if any */ 96 FD_ZERO(&fdset); 97 for(i = 0; i < n; i++) 98 { 99 FD_SET(screen[i].fd, &fdset); 100 if(screen[i].fd > maxfd) 101 maxfd = screen[i].fd; 102 } 103 tv.tv_sec = 0; 104 tv.tv_usec = 50000; 105 ret = select(maxfd + 1, &fdset, NULL, NULL, &tv); 106 107 if(ret < 0) 108 { 109 if(errno == EINTR) 110 ; /* We probably got a SIGWINCH, ignore it */ 111 else 112 { 113 for(i = 0; i < n; i++) 114 if(screen[i].total) 115 break; 116 if(i == n) 117 break; 118 } 119 } 120 else if(ret) for(i = 0; i < n; i++) 121 { 122 /* FIXME: try a new strategy: read all filedescriptors until 123 * each of them starved at least once. */ 124 125 if(!FD_ISSET(screen[i].fd, &fdset)) 126 continue; 127 128 for(;;) 129 { 130 ssize_t nr; 131 132 screen[i].buf = realloc(screen[i].buf, screen[i].total + 1024); 133 nr = read(screen[i].fd, screen[i].buf + screen[i].total, 1024); 134 135 if(nr > 0) 136 { 137 screen[i].total += nr; 138 continue; 139 } 140 141 if(nr == 0 || errno != EWOULDBLOCK) 142 eof = 1; 143 144 break; 145 } 146 } 147 148 for(i = 0; i < n; i++) if(screen[i].total) 149 { 150 unsigned long int bytes; 151 152 bytes = import_term(&screen[i], screen[i].buf, screen[i].total); 153 154 if(bytes > 0) 155 { 156 screen[i].total -= bytes; 157 memmove(screen[i].buf, screen[i].buf + bytes, screen[i].total); 158 refresh = 1; 159 } 160 } 161 162 /* Get events, if any */ 163 ret = caca_get_event(dp, CACA_EVENT_ANY, &ev, 0); 164 if(ret && (ev.type & CACA_EVENT_KEY_PRESS)) 165 { 166 if(command) 167 { 168 command = 0; 169 170 switch(ev.data.key.ch) 171 { 172 case 0x01: //CACA_KEY_CTRL_A: 173 pty ^= prevpty; 174 prevpty ^= pty; 175 pty ^= prevpty; 176 refresh = 1; 177 break; 178 case 'n': 179 case ' ': 180 case '\0': 181 case 0x0e: //CACA_KEY_CTRL_N: 182 prevpty = pty; 183 pty = (pty + 1) % n; 184 refresh = 1; 185 break; 186 case 'p': 187 case 0x10: //CACA_KEY_CTRL_P: 188 prevpty = pty; 189 pty = (pty + n - 1) % n; 190 refresh = 1; 191 break; 192 } 193 } 194 else 195 { 196 switch(ev.data.key.ch) 197 { 198 case 0x01: //CACA_KEY_CTRL_A: 199 command = 1; break; 200 case CACA_KEY_UP: 201 write(screen[pty].fd, "\x1b[A", 3); break; 202 case CACA_KEY_DOWN: 203 write(screen[pty].fd, "\x1b[B", 3); break; 204 case CACA_KEY_RIGHT: 205 write(screen[pty].fd, "\x1b[C", 3); break; 206 case CACA_KEY_LEFT: 207 write(screen[pty].fd, "\x1b[D", 3); break; 208 default: 209 write(screen[pty].fd, &ev.data.key.ch, 1); break; 210 } 211 } 212 } 213 else if(ret && (ev.type & CACA_EVENT_RESIZE)) 214 { 215 w = cucul_get_canvas_width(cv); 216 h = cucul_get_canvas_height(cv); 217 w = w <= XTAB * n ? 1 : w - XTAB * (n - 1) - 2; 218 h = h <= YTAB * n ? 1 : h - YTAB * (n - 1) - 2; 219 for(i = 0; i < n; i++) 220 { 221 cucul_set_canvas_size(screen[i].cv, w, h); 222 set_tty_size(screen[i].fd, w, h); 223 } 224 cucul_clear_canvas(cv); 225 refresh = 1; 226 } 227 228 /* Refresh screen */ 229 if(refresh) 230 { 231 refresh = 0; 232 233 for(i = 0; i < n; i++) 234 { 235 int j = (pty + n - 1 - i) % n; 236 cucul_blit(cv, (n - 1 - j) * XTAB + 1, 237 j * YTAB + 1, screen[j].cv, NULL); 238 cucul_draw_cp437_box(cv, (n - 1 - j) * XTAB, j * YTAB, 239 w + (n - 1 - j) * XTAB + 1, h + j * YTAB + 1); 240 } 241 caca_refresh_display(dp); 242 } 243 244 if(eof) 245 { 246 for(i = 0; i < n; i++) 247 if(screen[i].total) 248 break; 249 if(i == n) 250 break; 251 } 252 } 253 254 caca_get_event(dp, CACA_EVENT_KEY_PRESS, NULL, -1); 255 256 /* Clean up */ 257 caca_free_display(dp); 258 cucul_free_canvas(cv); 259 for(i = 0; i < n; i++) 260 cucul_free_canvas(screen[i].cv); 261 25 262 return 0; 26 263 } 27 264 265 static int create_pty(char *cmd, unsigned int w, unsigned int h) 266 { 267 char **argv; 268 int fd; 269 pid_t pid; 270 271 pid = forkpty(&fd, NULL, NULL, NULL); 272 if(pid < 0) 273 { 274 fprintf(stderr, "forkpty() error\n"); 275 return -1; 276 } 277 else if(pid == 0) 278 { 279 set_tty_size(0, w, h); 280 putenv("CACA_DRIVER=slang"); 281 putenv("TERM=xterm"); 282 argv = malloc(2 * sizeof(char *)); 283 argv[0] = cmd; 284 argv[1] = NULL; 285 execvp(cmd, argv); 286 fprintf(stderr, "execvp() error\n"); 287 return -1; 288 } 289 290 fcntl(fd, F_SETFL, O_NDELAY); 291 return fd; 292 #if 0 293 fprintf(stderr, "forkpty() not available\n"); 294 return -1; 295 #endif 296 } 297 298 static int set_tty_size(int fd, unsigned int w, unsigned int h) 299 { 300 struct winsize ws; 301 302 memset(&ws, 0, sizeof(ws)); 303 ws.ws_row = h; 304 ws.ws_col = w; 305 ioctl(fd, TIOCSWINSZ, (char *)&ws); 306 307 return 0; 308 } 309
Note: See TracChangeset
for help on using the changeset viewer.