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

Last change on this file since 3893 was 3893, checked in by Pascal Terjan, 11 years ago
  • Add FIXME in front of some useless code I don't understand
  • Property svn:keywords set to Id
File size: 10.5 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: screens.c 3893 2009-11-06 18:15:32Z pterjan $
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 <caca.h>
28#include <caca.h>
29
30#include "neercs.h"
31
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 = caca_create_canvas(w, h);
37    caca_set_color_ansi(s->cv, CACA_BLACK, CACA_BLACK);
38    caca_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
48    s->fd = create_pty_grab(pid, w, h, &s->pid);
49
50    if(s->fd < 0)
51    {
52        caca_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 = caca_create_canvas(w, h);
64    caca_set_color_ansi(s->cv, CACA_BLACK, CACA_BLACK);
65    caca_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    s->orig_w = s->w;
79    s->orig_h = s->h;
80    s->orig_x = s->x;
81    s->orig_y = s->y;
82
83
84    if(s->fd < 0)
85    {
86        caca_free_canvas(s->cv);
87        free(s);
88        return NULL;
89    }
90    return s;
91}
92
93int destroy_screen(struct screen *s)
94{
95    if(s->fd>=0)
96        close(s->fd);
97    if(s->buf)
98        free(s->buf);
99    if(s->title)
100        free(s->title);
101    s->buf = NULL;
102    if(s->cv)
103        caca_free_canvas(s->cv);
104    s->cv = NULL;
105    free(s);
106    return 1;
107}
108
109int add_screen(struct screen_list *list, struct screen *s)
110{
111    if(list == NULL || s == NULL) return -1;
112
113    else
114    {
115        list->screen = (struct screen**) realloc(list->screen,
116                                                 sizeof(sizeof(struct screen*))
117                                                 * (list->count+1));
118        if(!list->screen)
119            fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__, __LINE__);
120        list->screen[list->count] = s;
121        list->count++;
122    }
123
124    list->changed = 1;
125
126    return list->count-1;
127}
128
129int remove_screen(struct screen_list *list, int n, int please_kill)
130{
131
132    if(n>=list->count) return -1;
133
134    if(please_kill)
135    {
136        int status = 0;
137        int ret = 0;
138        /* FIXME */
139        close(list->screen[n]->fd);
140        list->screen[n]->fd = -1;
141        kill(list->screen[n]->pid, SIGINT);
142        ret = waitpid(list->screen[n]->pid, &status,
143                      WNOHANG|WUNTRACED|WCONTINUED);
144        if(!ret)
145            kill(list->screen[n]->pid, SIGQUIT);
146        ret = waitpid(list->screen[n]->pid, &status,
147                      WNOHANG|WUNTRACED|WCONTINUED);
148        if(!ret)
149            kill(list->screen[n]->pid, SIGABRT);
150        ret = waitpid(list->screen[n]->pid, &status,
151                      WNOHANG|WUNTRACED|WCONTINUED);
152        if(!ret)
153            kill(list->screen[n]->pid, SIGKILL);
154
155    }
156    destroy_screen(list->screen[n]);
157
158    memmove(&list->screen[n],
159            &list->screen[n+1],
160            sizeof(struct screen*)*(list->count-(n+1)));
161
162    list->screen = (struct screen**) realloc(list->screen,
163                                             sizeof(sizeof(struct screen*))
164                                             * (list->count));
165    if(!list->screen)
166        fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__, __LINE__);
167
168
169
170    list->count--;
171    list->changed = 1;
172    return 1;
173}
174
175
176
177void refresh_screens(struct screen_list *screen_list)
178{
179    int i;
180
181    if(!screen_list->count) return;
182
183
184    debug("Current pty is %d\n", screen_list->pty);
185
186    screen_list->width  = caca_get_canvas_width(screen_list->cv);
187    screen_list->height = caca_get_canvas_height(screen_list->cv) - (screen_list->mini*6) - screen_list->status;
188
189    if(!screen_list->dont_update_coords)
190        update_windows_props(screen_list);
191
192    if(screen_list->changed)
193    {
194        caca_set_color_ansi(screen_list->cv, CACA_DEFAULT, CACA_DEFAULT);
195        caca_clear_canvas(screen_list->cv);
196    }
197    caca_set_color_ansi(screen_list->cv, CACA_LIGHTRED, CACA_BLACK);
198
199    for(i = screen_list->count - 1; i >=0; i--)
200    {
201        if(i!=screen_list->pty && screen_list->screen[i]->visible &&
202           (screen_list->screen[i]->changed || screen_list->changed || screen_list->wm_type==WM_CARD))
203        {
204            caca_blit(screen_list->cv,
205                       screen_list->screen[i]->x,
206                       screen_list->screen[i]->y,
207                       screen_list->screen[i]->cv, NULL);
208
209            caca_draw_cp437_box(screen_list->cv,
210                                 screen_list->screen[i]->x - 1,
211                                 screen_list->screen[i]->y - 1,
212                                 screen_list->screen[i]->w + 2,
213                                 screen_list->screen[i]->h + 2);
214            if(screen_list->screen[i]->title)
215                caca_printf(screen_list->cv,
216                             screen_list->screen[i]->x,
217                             screen_list->screen[i]->y - 1,
218                             " %.*s ",
219                             screen_list->screen[i]->w - 3,
220                             screen_list->screen[i]->title);
221        }
222    }
223
224    if(screen_list->screen[screen_list->pty]->changed || screen_list->changed || screen_list->wm_type==WM_CARD)
225        caca_blit(screen_list->cv,
226                  screen_list->screen[screen_list->pty]->x,
227                  screen_list->screen[screen_list->pty]->y,
228                  screen_list->screen[screen_list->pty]->cv, NULL);
229
230    if(screen_list->screen[screen_list->pty]->bell)
231    {
232        caca_set_color_ansi(screen_list->cv, CACA_RED, CACA_BLACK);
233        screen_list->screen[screen_list->pty]->bell = 0;
234        screen_list->in_bell--;
235    }
236    else
237    {
238        caca_set_color_ansi(screen_list->cv, CACA_LIGHTGREEN, CACA_BLACK);
239    }
240
241    caca_draw_cp437_box(screen_list->cv,
242                         screen_list->screen[screen_list->pty]->x - 1,
243                         screen_list->screen[screen_list->pty]->y - 1,
244                         screen_list->screen[screen_list->pty]->w + 2,
245                         screen_list->screen[screen_list->pty]->h + 2);
246
247    if(screen_list->screen[screen_list->pty]->title)
248    {
249        caca_printf(screen_list->cv,
250                     screen_list->screen[screen_list->pty]->x,
251                     screen_list->screen[screen_list->pty]->y - 1,
252                     " %.*s ",
253                     screen_list->screen[screen_list->pty]->w - 3,
254                     screen_list->screen[screen_list->pty]->title);
255    }
256
257    caca_gotoxy(screen_list->cv,
258                 screen_list->screen[screen_list->pty]->x +
259                 caca_get_cursor_x(screen_list->screen[screen_list->pty]->cv),
260                 screen_list->screen[screen_list->pty]->y +
261                 caca_get_cursor_y(screen_list->screen[screen_list->pty]->cv));
262
263
264    if(screen_list->mini)
265    {
266        draw_thumbnails(screen_list);
267    }
268    if(screen_list->status)
269    {
270        draw_status(screen_list);
271    }
272    if(screen_list->help)
273    {
274        draw_help(screen_list);
275    }
276    if(screen_list->window_list)
277    {
278        draw_list(screen_list);
279    }
280    screen_list->changed = 0;
281    for(i = screen_list->count - 1; i >=0; i--)
282        screen_list->screen[i]->changed = 0;
283}
284
285
286int update_screens_contents(struct screen_list* screen_list)
287{
288    int i, refresh = 0;
289    int maxfd = 0;
290    struct timeval tv;
291    fd_set fdset;
292    int ret;
293
294    /* Read data, if any */
295    FD_ZERO(&fdset);
296    for(i = 0; i < screen_list->count; i++)
297    {
298        if(screen_list->screen[i]->fd >= 0)
299            FD_SET(screen_list->screen[i]->fd, &fdset);
300        if(screen_list->screen[i]->fd > maxfd)
301            maxfd = screen_list->screen[i]->fd;
302    }
303    tv.tv_sec = 0;
304    tv.tv_usec = 50000;
305    ret = select(maxfd + 1, &fdset, NULL, NULL, &tv);
306
307    if(ret < 0)
308    {
309        if(errno == EINTR)
310            ; /* We probably got a SIGWINCH, ignore it */
311        else
312        {
313            /* FIXME: Useless since break will mean that we return 0
314             * But I don't know what was the purpose of this code */
315            for(i = 0; i < screen_list->count; i++)
316                if(screen_list->screen[i]->total)
317                    break;
318            if(i == screen_list->count)
319                return 0;
320        }
321    }
322    else if(ret)
323    {
324
325    for(i = 0; i < screen_list->count; i++)
326    {
327        /* FIXME: try a new strategy: read all filedescriptors until
328         * each of them starved at least once. */
329
330        if(screen_list->screen[i]->fd < 0 ||
331           !FD_ISSET(screen_list->screen[i]->fd, &fdset))
332            continue;
333
334        for(;;)
335        {
336            ssize_t nr;
337
338            screen_list->screen[i]->buf =
339                realloc(screen_list->screen[i]->buf,
340                        screen_list->screen[i]->total + 1024);
341            if(!screen_list->screen[i]->buf)
342                fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__, __LINE__);
343
344            nr = read(screen_list->screen[i]->fd,
345                      screen_list->screen[i]->buf +
346                      screen_list->screen[i]->total, 1024);
347
348            if(nr > 0)
349            {
350                screen_list->screen[i]->total += nr;
351                continue;
352            }
353
354            if(nr == 0 || errno != EWOULDBLOCK)
355            {
356                remove_screen(screen_list, i, 0);
357                if(i < screen_list->prevpty) screen_list->prevpty--;
358                if(i == screen_list->pty)
359                {
360                    screen_list->pty = screen_list->prevpty;
361                    screen_list->prevpty = 0;
362                }
363                if(i < (screen_list->pty)) (screen_list->pty)--;
364                /* Don't skip the element which is now at position i */
365                i--;
366                refresh = 1;
367            }
368
369            break;
370        }
371    }
372    }
373    return refresh;
374}
375
376
Note: See TracBrowser for help on using the repository browser.