source: neercs/trunk/src/screens.c

Last change on this file was 4366, checked in by Sam Hocevar, 12 years ago

Clean up source code, copyright information, author names, SVN keywords...

  • Property svn:keywords set to Id
File size: 8.7 KB
Line 
1/*
2 *  neercs        console-based window manager
3 *  Copyright (c) 2006-2010 Sam Hocevar <sam@hocevar.net>
4 *                2008-2010 Jean-Yves Lamoureux <jylam@lnxscene.org>
5 *                All Rights Reserved
6 *
7 *  This program is free software. It comes without any warranty, to
8 *  the extent permitted by applicable law. You can redistribute it
9 *  and/or modify it under the terms of the Do What The Fuck You Want
10 *  To Public License, Version 2, as published by Sam Hocevar. See
11 *  http://sam.zoy.org/wtfpl/COPYING for more details.
12 */
13
14#include "config.h"
15
16#include <stdio.h>
17#include <string.h>
18#include <stdlib.h>
19#include <sys/types.h>
20#include <signal.h>
21#include <sys/wait.h>
22#include <errno.h>
23#include <unistd.h>
24
25#include <caca.h>
26
27#include "neercs.h"
28
29struct screen *create_screen_grab(int w, int h, int pid)
30{
31    struct screen *s = (struct screen *)malloc(sizeof(struct screen));
32
33    s->cv = caca_create_canvas(w, h);
34    caca_set_color_ansi(s->cv, CACA_BLACK, CACA_BLACK);
35    caca_clear_canvas(s->cv);
36    s->init = 0;
37
38    s->buf = NULL;
39    s->title = NULL;
40    s->total = 0;
41    s->w = w;
42    s->h = h;
43    s->bell = 0;
44    s->report_mouse = MOUSE_NONE;
45
46    s->fd = create_pty_grab(pid, w, h, &s->pid);
47
48    if (s->fd < 0)
49    {
50        caca_free_canvas(s->cv);
51        free(s);
52        return NULL;
53    }
54    return s;
55}
56
57struct screen *create_screen(int w, int h, char *command)
58{
59    struct screen *s = (struct screen *)malloc(sizeof(struct screen));
60
61    s->cv = caca_create_canvas(w, h);
62    caca_set_color_ansi(s->cv, CACA_BLACK, CACA_BLACK);
63    caca_clear_canvas(s->cv);
64    s->init = 0;
65
66    s->buf = NULL;
67    s->title = NULL;
68    s->total = 0;
69    s->w = w + 1;
70    s->h = h + 1;
71    s->bell = 0;
72    s->visible = 1;
73    s->scroll = 0;
74    s->report_mouse = MOUSE_NONE;
75    s->fd = create_pty(command, w, h, &s->pid);
76
77    s->orig_w = s->w;
78    s->orig_h = s->h;
79    s->orig_x = s->x;
80    s->orig_y = s->y;
81
82
83    if (s->fd < 0)
84    {
85        caca_free_canvas(s->cv);
86        free(s);
87        return NULL;
88    }
89    return s;
90}
91
92int destroy_screen(struct screen *s)
93{
94    if (s->fd >= 0)
95        close(s->fd);
96    if (s->buf)
97        free(s->buf);
98    if (s->title)
99        free(s->title);
100    s->buf = NULL;
101    if (s->cv)
102        caca_free_canvas(s->cv);
103    s->cv = NULL;
104    free(s);
105    return 1;
106}
107
108int add_screen(struct screen_list *list, struct screen *s)
109{
110    if (list == NULL || s == NULL)
111        return -1;
112
113    else
114    {
115        list->screen = (struct screen **)realloc(list->screen,
116                                                 sizeof(sizeof
117                                                        (struct screen *)) *
118                                                 (list->count + 1));
119        if (!list->screen)
120            fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__,
121                    __LINE__);
122        list->screen[list->count] = s;
123        list->count++;
124    }
125
126    list->changed = 1;
127
128    return list->count - 1;
129}
130
131int remove_screen(struct screen_list *list, int n, int please_kill)
132{
133
134    if (n >= list->count)
135        return -1;
136
137    if (please_kill)
138    {
139        int status = 0;
140        int ret = 0;
141        /* FIXME */
142        close(list->screen[n]->fd);
143        list->screen[n]->fd = -1;
144        kill(list->screen[n]->pid, SIGINT);
145        ret = waitpid(list->screen[n]->pid, &status,
146                      WNOHANG | WUNTRACED | WCONTINUED);
147        if (!ret)
148            kill(list->screen[n]->pid, SIGQUIT);
149        ret = waitpid(list->screen[n]->pid, &status,
150                      WNOHANG | WUNTRACED | WCONTINUED);
151        if (!ret)
152            kill(list->screen[n]->pid, SIGABRT);
153        ret = waitpid(list->screen[n]->pid, &status,
154                      WNOHANG | WUNTRACED | WCONTINUED);
155        if (!ret)
156            kill(list->screen[n]->pid, SIGKILL);
157
158    }
159    destroy_screen(list->screen[n]);
160
161    memmove(&list->screen[n],
162            &list->screen[n + 1],
163            sizeof(struct screen *) * (list->count - (n + 1)));
164
165    list->screen = (struct screen **)realloc(list->screen,
166                                             sizeof(sizeof(struct screen *))
167                                             * (list->count));
168    if (!list->screen)
169        fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__,
170                __LINE__);
171
172
173
174    list->count--;
175    list->changed = 1;
176    return 1;
177}
178
179
180
181void refresh_screens(struct screen_list *screen_list)
182{
183    int i;
184
185    if (!screen_list->count)
186        return;
187
188
189    screen_list->width = caca_get_canvas_width(screen_list->cv);
190    screen_list->height =
191        caca_get_canvas_height(screen_list->cv) - (screen_list->modals.mini * 6) -
192        screen_list->modals.status;
193
194    if (!screen_list->dont_update_coords)
195    {
196        update_windows_props(screen_list);
197    }
198
199    if (screen_list->changed)
200    {
201        caca_set_color_ansi(screen_list->cv, CACA_DEFAULT, CACA_DEFAULT);
202        caca_clear_canvas(screen_list->cv);
203    }
204
205    wm_refresh(screen_list);
206
207    caca_gotoxy(screen_list->cv,
208                screen_list->screen[screen_list->pty]->x +
209                caca_get_cursor_x(screen_list->screen[screen_list->pty]->cv),
210                screen_list->screen[screen_list->pty]->y +
211                caca_get_cursor_y(screen_list->screen[screen_list->pty]->cv));
212
213
214    if (screen_list->modals.mini)
215    {
216        draw_thumbnails(screen_list);
217    }
218    if (screen_list->modals.status)
219    {
220        draw_status(screen_list);
221    }
222    if (screen_list->modals.help)
223    {
224        draw_help(screen_list);
225    }
226    if (screen_list->modals.window_list)
227    {
228        draw_list(screen_list);
229    }
230#ifdef USE_PYTHON
231    debug("py : command is %d (at %p)\n", screen_list->modals.python_command, &screen_list->modals.python_command);
232    if(screen_list->modals.python_command)
233    {
234         draw_python_command(screen_list);
235    }
236#endif
237    screen_list->changed = 0;
238    for (i = screen_list->count - 1; i >= 0; i--)
239        screen_list->screen[i]->changed = 0;
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            /* FIXME: Useless since break will mean that we return 0 But I
271               don't know what was the purpose of this code */
272            for (i = 0; i < screen_list->count; i++)
273                if (screen_list->screen[i]->total)
274                    break;
275            if (i == screen_list->count)
276                return 0;
277        }
278    }
279    else if (ret)
280    {
281
282        for (i = 0; i < screen_list->count; i++)
283        {
284            /* FIXME: try a new strategy: read all filedescriptors until each
285               of them starved at least once. */
286
287            if (screen_list->screen[i]->fd < 0 ||
288                !FD_ISSET(screen_list->screen[i]->fd, &fdset))
289                continue;
290
291            for (;;)
292            {
293                ssize_t nr;
294
295                screen_list->screen[i]->buf =
296                    realloc(screen_list->screen[i]->buf,
297                            screen_list->screen[i]->total + 1024);
298                if (!screen_list->screen[i]->buf)
299                    fprintf(stderr, "Can't allocate memory at %s:%d\n",
300                            __FUNCTION__, __LINE__);
301
302                nr = read(screen_list->screen[i]->fd,
303                          screen_list->screen[i]->buf +
304                          screen_list->screen[i]->total, 1024);
305
306                if (nr > 0)
307                {
308                    screen_list->screen[i]->total += nr;
309                    continue;
310                }
311
312                if (nr == 0 || errno != EWOULDBLOCK)
313                {
314                    remove_screen(screen_list, i, 0);
315                    if (i < screen_list->prevpty)
316                        screen_list->prevpty--;
317                    if (i == screen_list->pty)
318                    {
319                        screen_list->pty = screen_list->prevpty;
320                        screen_list->prevpty = 0;
321                    }
322                    if (i < (screen_list->pty))
323                        (screen_list->pty)--;
324                    /* Don't skip the element which is now at position i */
325                    i--;
326                    refresh = 1;
327                }
328
329                break;
330            }
331        }
332    }
333    return refresh;
334}
Note: See TracBrowser for help on using the repository browser.