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

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