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

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