source: trunk/tools/neercs/old/screens.c @ 2183

Last change on this file since 2183 was 2183, checked in by sam, 7 years ago

build: fix the WTFPL site URL in all code comments.

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