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

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