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

Last change on this file since 4064 was 4064, checked in by Jean-Yves Lamoureux, 13 years ago
  • Don't forget to refresh on python_command key
  • Property svn:keywords set to Id
File size: 8.7 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 4064 2009-11-29 12:58:03Z 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#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;
45    s->h = h;
46    s->bell = 0;
47    s->report_mouse = 0;
48
49    s->fd = create_pty_grab(pid, w, h, &s->pid);
50
51    if (s->fd < 0)
52    {
53        caca_free_canvas(s->cv);
54        free(s);
55        return NULL;
56    }
57    return s;
58}
59
60struct screen *create_screen(int w, int h, char *command)
61{
62    struct screen *s = (struct screen *)malloc(sizeof(struct screen));
63
64    s->cv = caca_create_canvas(w, h);
65    caca_set_color_ansi(s->cv, CACA_BLACK, CACA_BLACK);
66    caca_clear_canvas(s->cv);
67    s->init = 0;
68
69    s->buf = NULL;
70    s->title = NULL;
71    s->total = 0;
72    s->w = w + 1;
73    s->h = h + 1;
74    s->bell = 0;
75    s->visible = 1;
76    s->scroll = 0;
77    s->report_mouse = 0;
78    s->fd = create_pty(command, w, h, &s->pid);
79
80    s->orig_w = s->w;
81    s->orig_h = s->h;
82    s->orig_x = s->x;
83    s->orig_y = s->y;
84
85
86    if (s->fd < 0)
87    {
88        caca_free_canvas(s->cv);
89        free(s);
90        return NULL;
91    }
92    return s;
93}
94
95int destroy_screen(struct screen *s)
96{
97    if (s->fd >= 0)
98        close(s->fd);
99    if (s->buf)
100        free(s->buf);
101    if (s->title)
102        free(s->title);
103    s->buf = NULL;
104    if (s->cv)
105        caca_free_canvas(s->cv);
106    s->cv = NULL;
107    free(s);
108    return 1;
109}
110
111int add_screen(struct screen_list *list, struct screen *s)
112{
113    if (list == NULL || s == NULL)
114        return -1;
115
116    else
117    {
118        list->screen = (struct screen **)realloc(list->screen,
119                                                 sizeof(sizeof
120                                                        (struct screen *)) *
121                                                 (list->count + 1));
122        if (!list->screen)
123            fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__,
124                    __LINE__);
125        list->screen[list->count] = s;
126        list->count++;
127    }
128
129    list->changed = 1;
130
131    return list->count - 1;
132}
133
134int remove_screen(struct screen_list *list, int n, int please_kill)
135{
136
137    if (n >= list->count)
138        return -1;
139
140    if (please_kill)
141    {
142        int status = 0;
143        int ret = 0;
144        /* FIXME */
145        close(list->screen[n]->fd);
146        list->screen[n]->fd = -1;
147        kill(list->screen[n]->pid, SIGINT);
148        ret = waitpid(list->screen[n]->pid, &status,
149                      WNOHANG | WUNTRACED | WCONTINUED);
150        if (!ret)
151            kill(list->screen[n]->pid, SIGQUIT);
152        ret = waitpid(list->screen[n]->pid, &status,
153                      WNOHANG | WUNTRACED | WCONTINUED);
154        if (!ret)
155            kill(list->screen[n]->pid, SIGABRT);
156        ret = waitpid(list->screen[n]->pid, &status,
157                      WNOHANG | WUNTRACED | WCONTINUED);
158        if (!ret)
159            kill(list->screen[n]->pid, SIGKILL);
160
161    }
162    destroy_screen(list->screen[n]);
163
164    memmove(&list->screen[n],
165            &list->screen[n + 1],
166            sizeof(struct screen *) * (list->count - (n + 1)));
167
168    list->screen = (struct screen **)realloc(list->screen,
169                                             sizeof(sizeof(struct screen *))
170                                             * (list->count));
171    if (!list->screen)
172        fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__,
173                __LINE__);
174
175
176
177    list->count--;
178    list->changed = 1;
179    return 1;
180}
181
182
183
184void refresh_screens(struct screen_list *screen_list)
185{
186    int i;
187
188    if (!screen_list->count)
189        return;
190
191
192    screen_list->width = caca_get_canvas_width(screen_list->cv);
193    screen_list->height =
194        caca_get_canvas_height(screen_list->cv) - (screen_list->modals.mini * 6) -
195        screen_list->modals.status;
196
197    if (!screen_list->dont_update_coords)
198    {
199        update_windows_props(screen_list);
200    }
201
202    if (screen_list->changed)
203    {
204        caca_set_color_ansi(screen_list->cv, CACA_DEFAULT, CACA_DEFAULT);
205        caca_clear_canvas(screen_list->cv);
206    }
207
208    wm_refresh(screen_list);
209
210    caca_gotoxy(screen_list->cv,
211                screen_list->screen[screen_list->pty]->x +
212                caca_get_cursor_x(screen_list->screen[screen_list->pty]->cv),
213                screen_list->screen[screen_list->pty]->y +
214                caca_get_cursor_y(screen_list->screen[screen_list->pty]->cv));
215
216
217    if (screen_list->modals.mini)
218    {
219        draw_thumbnails(screen_list);
220    }
221    if (screen_list->modals.status)
222    {
223        draw_status(screen_list);
224    }
225    if (screen_list->modals.help)
226    {
227        draw_help(screen_list);
228    }
229    if (screen_list->modals.window_list)
230    {
231        draw_list(screen_list);
232    }
233#ifdef USE_PYTHON
234    debug("py : command is %d (at %p)\n", screen_list->modals.python_command, &screen_list->modals.python_command);
235    if(screen_list->modals.python_command)
236    {
237        draw_python_command(screen_list);
238    }
239#endif
240    screen_list->changed = 0;
241    for (i = screen_list->count - 1; i >= 0; i--)
242        screen_list->screen[i]->changed = 0;
243}
244
245
246int update_screens_contents(struct screen_list *screen_list)
247{
248    int i, refresh = 0;
249    int maxfd = 0;
250    struct timeval tv;
251    fd_set fdset;
252    int ret;
253
254    /* Read data, if any */
255    FD_ZERO(&fdset);
256    for (i = 0; i < screen_list->count; i++)
257    {
258        if (screen_list->screen[i]->fd >= 0)
259            FD_SET(screen_list->screen[i]->fd, &fdset);
260        if (screen_list->screen[i]->fd > maxfd)
261            maxfd = screen_list->screen[i]->fd;
262    }
263    tv.tv_sec = 0;
264    tv.tv_usec = 50000;
265    ret = select(maxfd + 1, &fdset, NULL, NULL, &tv);
266
267    if (ret < 0)
268    {
269        if (errno == EINTR)
270            ;                   /* We probably got a SIGWINCH, ignore it */
271        else
272        {
273            /* FIXME: Useless since break will mean that we return 0 But I
274               don't know what was the purpose of this code */
275            for (i = 0; i < screen_list->count; i++)
276                if (screen_list->screen[i]->total)
277                    break;
278            if (i == screen_list->count)
279                return 0;
280        }
281    }
282    else if (ret)
283    {
284
285        for (i = 0; i < screen_list->count; i++)
286        {
287            /* FIXME: try a new strategy: read all filedescriptors until each
288               of them starved at least once. */
289
290            if (screen_list->screen[i]->fd < 0 ||
291                !FD_ISSET(screen_list->screen[i]->fd, &fdset))
292                continue;
293
294            for (;;)
295            {
296                ssize_t nr;
297
298                screen_list->screen[i]->buf =
299                    realloc(screen_list->screen[i]->buf,
300                            screen_list->screen[i]->total + 1024);
301                if (!screen_list->screen[i]->buf)
302                    fprintf(stderr, "Can't allocate memory at %s:%d\n",
303                            __FUNCTION__, __LINE__);
304
305                nr = read(screen_list->screen[i]->fd,
306                          screen_list->screen[i]->buf +
307                          screen_list->screen[i]->total, 1024);
308
309                if (nr > 0)
310                {
311                    screen_list->screen[i]->total += nr;
312                    continue;
313                }
314
315                if (nr == 0 || errno != EWOULDBLOCK)
316                {
317                    remove_screen(screen_list, i, 0);
318                    if (i < screen_list->prevpty)
319                        screen_list->prevpty--;
320                    if (i == screen_list->pty)
321                    {
322                        screen_list->pty = screen_list->prevpty;
323                        screen_list->prevpty = 0;
324                    }
325                    if (i < (screen_list->pty))
326                        (screen_list->pty)--;
327                    /* Don't skip the element which is now at position i */
328                    i--;
329                    refresh = 1;
330                }
331
332                break;
333            }
334        }
335    }
336    return refresh;
337}
Note: See TracBrowser for help on using the repository browser.