source: neercs/trunk/src/screens.c @ 2426

Last change on this file since 2426 was 2426, checked in by Pascal Terjan, 14 years ago
  • First attempt to grab a process when started with -P <pid>
File size: 9.9 KB
Line 
1/*
2 *  neercs        console-based window manager
3 *  Copyright (c) 2006 Sam Hocevar <sam@zoy.org>
4 *                2008 Jean-Yves Lamoureux <jylam@lnxscene.org>
5 *                All Rights Reserved
6 *
7 *  $Id: main.c 2401 2008-06-15 12:50:12Z jylam $
8 *
9 *  This program is free software. It comes without any warranty, to
10 *  the extent permitted by applicable law. You can redistribute it
11 *  and/or modify it under the terms of the Do What The Fuck You Want
12 *  To Public License, Version 2, as published by Sam Hocevar. See
13 *  http://sam.zoy.org/wtfpl/COPYING for more details.
14 */
15
16#include "config.h"
17
18#include <stdio.h>
19#include <string.h>
20#include <stdlib.h>
21#include <sys/types.h>
22#include <signal.h>
23#include <sys/wait.h>
24#include <errno.h>
25
26#include <cucul.h>
27#include <caca.h>
28
29#include "neercs.h"
30
31struct screen* create_screen_grab(int w, int h, int pid)
32{
33    struct screen *s = (struct screen*) malloc(sizeof(struct screen));
34
35    s->cv = cucul_create_canvas(w, h);
36    cucul_set_color_ansi(s->cv, CUCUL_BLACK, CUCUL_BLACK);
37    cucul_clear_canvas(s->cv);
38    s->init = 0;
39
40    s->buf = NULL;
41    s->title = NULL;
42    s->total = 0;
43    s->w = w+1;
44    s->h = h+1;
45    s->bell = 0;
46    s->pid = pid;
47
48    s->fd = create_pty_grab(pid, w, h);
49
50    if(s->fd < 0)
51    {
52        cucul_free_canvas(s->cv);
53        free(s);
54        return NULL;
55    }
56    return s;
57}
58
59struct screen* create_screen(int w, int h, char *command)
60{
61    struct screen *s = (struct screen*) malloc(sizeof(struct screen));
62
63    s->cv = cucul_create_canvas(w, h);
64    cucul_set_color_ansi(s->cv, CUCUL_BLACK, CUCUL_BLACK);
65    cucul_clear_canvas(s->cv);
66    s->init = 0;
67
68    s->buf = NULL;
69    s->title = NULL;
70    s->total = 0;
71    s->w = w+1;
72    s->h = h+1;
73    s->bell = 0;
74    s->visible = 1;
75    s->scroll = 0;
76    s->fd = create_pty(command, w, h, &s->pid);
77
78    if(s->fd < 0)
79    {
80        cucul_free_canvas(s->cv);
81        free(s);
82        return NULL;
83    }
84    return s;
85}
86
87int destroy_screen(struct screen *s)
88{
89    if(s->fd>0)
90        close(s->fd);
91    if(s->buf)
92        free(s->buf);
93    if(s->title)
94        free(s->title);
95    s->buf = NULL;
96    if(s->cv)
97        cucul_free_canvas(s->cv);
98    s->cv = NULL;
99    if(s)
100        free(s);
101    s = NULL;
102    return 1;
103}
104
105int add_screen(struct screen_list *list, struct screen *s)
106{
107    if(list == NULL || s == NULL) return -1;
108
109    else
110    {
111        list->screen = (struct screen**) realloc(list->screen,
112                                                 sizeof(sizeof(struct screen*))
113                                                 * (list->count+1));
114        if(!list->screen)
115            fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__, __LINE__);
116        list->screen[list->count] = s;
117        list->count++;
118    }
119
120    return list->count-1;
121}
122
123int remove_screen(struct screen_list *list, int n, int please_kill)
124{
125
126    if(n>=list->count) return -1;
127
128    if(please_kill)
129    {
130        int status = 0;
131        int ret = 0;
132        /* FIXME */
133        close(list->screen[n]->fd);
134        list->screen[n]->fd = -1;
135        kill(list->screen[n]->pid, SIGINT);
136        ret = waitpid(list->screen[n]->pid, &status,
137                      WNOHANG|WUNTRACED|WCONTINUED);
138        if(!ret)
139            kill(list->screen[n]->pid, SIGQUIT);
140        ret = waitpid(list->screen[n]->pid, &status,
141                      WNOHANG|WUNTRACED|WCONTINUED);
142        if(!ret)
143            kill(list->screen[n]->pid, SIGABRT);
144        ret = waitpid(list->screen[n]->pid, &status,
145                      WNOHANG|WUNTRACED|WCONTINUED);
146        if(!ret)
147            kill(list->screen[n]->pid, SIGKILL);
148
149    }
150    destroy_screen(list->screen[n]);
151
152    memmove(&list->screen[n],
153            &list->screen[n+1],
154            sizeof(struct screen*)*(list->count-(n+1)));
155
156    list->screen = (struct screen**) realloc(list->screen,
157                                             sizeof(sizeof(struct screen*))
158                                             * (list->count));
159    if(!list->screen)
160        fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__, __LINE__);
161
162
163
164    list->count--;
165    return 1;
166}
167
168
169
170void refresh_screens(cucul_canvas_t *cv,
171                     caca_display_t *dp,
172                     struct screen_list *screen_list)
173{
174    int i;
175
176    if(!screen_list->count) return;
177
178    screen_list->width  = cucul_get_canvas_width(cv);
179    screen_list->height = cucul_get_canvas_height(cv) - (screen_list->mini*6);
180
181    update_windows_props(cv, screen_list);
182
183    if(screen_list->screen[screen_list->pty]->title)
184        caca_set_display_title(dp, screen_list->screen[screen_list->pty]->title);
185    else
186        caca_set_display_title(dp, PACKAGE_STRING);
187
188    cucul_set_color_ansi(cv, CUCUL_DEFAULT, CUCUL_DEFAULT);
189    cucul_clear_canvas(cv);
190    cucul_set_color_ansi(cv, CUCUL_LIGHTRED, CUCUL_BLACK);
191
192    for(i = screen_list->count - 1; i >=0; i--)
193    {
194        if(i!=screen_list->pty && screen_list->screen[i]->visible)
195        {
196            cucul_blit(cv,
197                       screen_list->screen[i]->x,
198                       screen_list->screen[i]->y,
199                       screen_list->screen[i]->cv, NULL);
200            cucul_draw_cp437_box(cv,
201                                 screen_list->screen[i]->x - 1,
202                                 screen_list->screen[i]->y - 1,
203                                 screen_list->screen[i]->w + 2,
204                                 screen_list->screen[i]->h + 2);
205            if(screen_list->screen[i]->title)
206                cucul_printf(cv,
207                             screen_list->screen[i]->x,
208                             screen_list->screen[i]->y - 1,
209                             " %.*s ",
210                             screen_list->screen[i]->w - 3,
211                             screen_list->screen[i]->title);
212        }
213    }
214
215    cucul_blit(cv,
216               screen_list->screen[screen_list->pty]->x,
217               screen_list->screen[screen_list->pty]->y,
218               screen_list->screen[screen_list->pty]->cv, NULL);
219
220    if(screen_list->screen[screen_list->pty]->bell)
221    {
222        cucul_set_color_ansi(cv, CUCUL_RED, CUCUL_BLACK);
223        screen_list->screen[screen_list->pty]->bell = 0;
224        screen_list->in_bell--;
225    }
226    else
227    {
228        cucul_set_color_ansi(cv, CUCUL_LIGHTGREEN, CUCUL_BLACK);
229    }
230
231    cucul_draw_cp437_box(cv,
232                         screen_list->screen[screen_list->pty]->x - 1,
233                         screen_list->screen[screen_list->pty]->y - 1,
234                         screen_list->screen[screen_list->pty]->w + 2,
235                         screen_list->screen[screen_list->pty]->h + 2);
236
237    if(screen_list->screen[screen_list->pty]->title)
238    {
239        cucul_printf(cv,
240                     screen_list->screen[screen_list->pty]->x,
241                     screen_list->screen[screen_list->pty]->y - 1,
242                     " %.*s ",
243                     screen_list->screen[screen_list->pty]->w - 3,
244                     screen_list->screen[screen_list->pty]->title);
245    }
246
247    cucul_gotoxy(cv,
248                 screen_list->screen[screen_list->pty]->x +
249                 cucul_get_cursor_x(screen_list->screen[screen_list->pty]->cv),
250                 screen_list->screen[screen_list->pty]->y +
251                 cucul_get_cursor_y(screen_list->screen[screen_list->pty]->cv));
252
253
254    if(screen_list->mini)
255    {
256        draw_thumbnails(cv, screen_list);
257    }
258    if(screen_list->status)
259    {
260        draw_status(cv, screen_list);
261    }
262    if(screen_list->help)
263    {
264        draw_help(cv, screen_list);
265    }
266
267    caca_refresh_display(dp);
268}
269
270
271int update_screens_contents(struct screen_list* screen_list)
272{
273    int i, refresh = 0;
274    int maxfd = 0;
275    struct timeval tv;
276    fd_set fdset;
277    int ret;
278
279    /* Read data, if any */
280    FD_ZERO(&fdset);
281    for(i = 0; i < screen_list->count; i++)
282    {
283        if(screen_list->screen[i]->fd >= 0)
284            FD_SET(screen_list->screen[i]->fd, &fdset);
285        if(screen_list->screen[i]->fd > maxfd)
286            maxfd = screen_list->screen[i]->fd;
287    }
288    tv.tv_sec = 0;
289    tv.tv_usec = 50000;
290    ret = select(maxfd + 1, &fdset, NULL, NULL, &tv);
291
292    if(ret < 0)
293    {
294        if(errno == EINTR)
295            ; /* We probably got a SIGWINCH, ignore it */
296        else
297        {
298            for(i = 0; i < screen_list->count; i++)
299                if(screen_list->screen[i]->total)
300                    break;
301            if(i == screen_list->count)
302                return 0;
303        }
304    }
305    else if(ret)
306    {
307
308    for(i = 0; i < screen_list->count; i++)
309    {
310        /* FIXME: try a new strategy: read all filedescriptors until
311         * each of them starved at least once. */
312
313        if(screen_list->screen[i]->fd < 0 ||
314           !FD_ISSET(screen_list->screen[i]->fd, &fdset))
315            continue;
316
317        for(;;)
318        {
319            ssize_t nr;
320
321            screen_list->screen[i]->buf =
322                realloc(screen_list->screen[i]->buf,
323                        screen_list->screen[i]->total + 1024);
324            if(!screen_list->screen[i]->buf)
325                fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__, __LINE__);
326
327            nr = read(screen_list->screen[i]->fd,
328                      screen_list->screen[i]->buf +
329                      screen_list->screen[i]->total, 1024);
330
331            if(nr > 0)
332            {
333                screen_list->screen[i]->total += nr;
334                continue;
335            }
336
337            if(nr == 0 || errno != EWOULDBLOCK) {
338                close(screen_list->screen[i]->fd);
339                screen_list->screen[i]->fd = -1;
340                destroy_screen(screen_list->screen[i]);
341                remove_screen(screen_list, i, 0);
342                if(i < screen_list->prevpty) screen_list->prevpty--;
343                if(i == screen_list->pty)
344                {
345                    screen_list->pty = screen_list->prevpty;
346                    screen_list->prevpty = 0;
347                }
348                if(i < (screen_list->pty)) (screen_list->pty)--;
349                refresh = 1;
350            }
351
352            break;
353        }
354    }
355    }
356    return refresh;
357}
358
359
Note: See TracBrowser for help on using the repository browser.