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

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