source: neercs/trunk/src/main.c @ 2456

Last change on this file since 2456 was 2456, checked in by jylam, 7 years ago
  • Don't send key that closed help window to current terminal
  • Property svn:keywords set to Id
File size: 12.0 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 2456 2008-06-19 07:53:39Z 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 <unistd.h>
22#include <fcntl.h>
23#include <signal.h>
24#include <sys/ioctl.h>
25#include <sys/types.h>
26#include <sys/wait.h>
27#include <sys/time.h>
28#include <time.h>
29
30#if defined HAVE_PTY_H
31#   include <pty.h>  /* for openpty and forkpty */
32#else
33#   include <util.h> /* for OS X */
34#endif
35#if !defined HAVE_GETOPT_LONG
36#   include "mygetopt.h"
37#elif defined HAVE_GETOPT_H
38#   include <getopt.h>
39#endif
40#if defined HAVE_GETOPT_LONG
41#   define mygetopt getopt_long
42#   define myoptind optind
43#   define myoptarg optarg
44#   define myoption option
45#endif
46#include <errno.h>
47#include <cucul.h>
48#include <caca.h>
49
50#include "neercs.h"
51
52
53void version(void)
54{
55    printf("%s\n", PACKAGE_STRING);
56    printf("Copyright (C) 2006, 2008 Sam Hocevar <sam@zoy.org>\n");
57    printf("                         Jean-Yves Lamoureux <jylam@lnxscene.org>\n\n");
58    printf("This is free software.  You may redistribute copies of it under the\n");
59    printf("terms of the Do What The Fuck You Want To Public License, Version 2\n");
60    printf("<http://sam.zoy.org/wtfpl/>.\n");
61    printf("There is NO WARRANTY, to the extent permitted by law.\n");
62    printf("\n");
63    printf("For more informations, visit http://libcaca.zoy.org/wiki/neercs\n");
64}
65
66
67int main(int argc, char **argv)
68{
69    static cucul_canvas_t *cv;
70    static caca_display_t *dp;
71    struct screen_list *screen_list = NULL;
72    struct recurrent_list *recurrent_list = NULL;
73    char *default_shell = NULL;
74    int i, w, h, args, s=0;
75    int eof = 0, refresh = 1, command = 0;
76    long long unsigned int last_key_time = 0;
77
78    default_shell = getenv("SHELL");
79
80    args = argc -1;
81    if(default_shell == NULL  && args <= 0)
82    {
83        fprintf(stderr, "Environment variable SHELL not set and no arguments given. kthxbye.\n");
84        return -1;
85    }
86
87    if(args==0)
88        args = 1;
89
90    /* Create main canvas and associated caca window */
91    cv = cucul_create_canvas(0, 0);
92    dp = caca_create_display(cv);
93    if(!dp)
94        return 1;
95    caca_set_cursor(dp, 1);
96
97    w = cucul_get_canvas_width(cv);
98    h = cucul_get_canvas_height(cv);
99
100
101    /* Create screen list */
102    screen_list = (struct screen_list*)     malloc(sizeof(struct screen_list));
103    if(!screen_list)
104    {
105        fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__, __LINE__);
106        return -1;
107    }
108    screen_list->screen = (struct screen**) malloc(sizeof(sizeof(struct screen*)));
109    if(!screen_list->screen)
110    {
111        fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__, __LINE__);
112        return -1;
113    }
114    screen_list->count = 0;
115    screen_list->width  = cucul_get_canvas_width(cv);
116    screen_list->mini = 1;
117    screen_list->help = 0;
118    screen_list->status = 1;
119    screen_list->height = cucul_get_canvas_height(cv) - ((screen_list->mini*6) + (screen_list->status));
120    screen_list->wm_type = WM_VSPLIT;
121    screen_list->in_bell = 0;
122    screen_list->pty = screen_list->prevpty = 0;
123    screen_list->dont_update_coords = 0;
124    screen_list->screensaver_timeout = (60) * 1000000;
125    screen_list->screensaver_data = NULL;
126    screen_list->in_screensaver = 0;
127
128    recurrent_list = (struct recurrent_list*) malloc(sizeof(struct recurrent_list));
129    recurrent_list->recurrent = (struct recurrent**) malloc(sizeof(struct recurrent*));
130    if(!recurrent_list->recurrent)
131    {
132        fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__, __LINE__);
133        return -1;
134    }
135    recurrent_list->count = 0;
136
137    for(;;)
138    {
139        int option_index = 0;
140        static struct myoption long_options[] =
141        {
142#if defined USE_GRAB
143            { "pid",         1, NULL, 'P' },
144#endif
145            { "help",        0, NULL, 'h' },
146            { "version",     0, NULL, 'v' },
147        };
148#if defined USE_GRAB
149        int c = mygetopt(argc, argv, "P:hv", long_options, &option_index);
150#else
151        int c = mygetopt(argc, argv, "hv", long_options, &option_index);
152#endif
153        if(c == -1)
154            break;
155
156        switch(c)
157        {
158        case 'P': /* --pid */
159            add_screen(screen_list,create_screen_grab(w, h, atoi(myoptarg)));
160            s+=2;
161            break;
162        case 'h': /* --help */
163            //   usage(argc, argv);
164            return 0;
165            break;
166        case 'v': /* --version */
167            version();
168            goto end;
169            break;
170        default:
171            fprintf(stderr, "Unknow argument #%d\n", myoptind);
172            return -1;
173            break;
174        }
175    }
176
177
178    if(s == 0 && argc<2)
179    {
180        add_screen(screen_list, create_screen(w, h, default_shell));
181    }
182
183    /* Launch command line processes */
184    for(i=0; i<(argc-1) - s; i++)
185    {
186        add_screen(screen_list, create_screen(w, h, argv[i+s+1]));
187    }
188
189
190    /* Windows are in a temporary state, resize them to the right dimensions */
191    update_windows_props(cv, screen_list);
192
193    last_key_time = get_ms();
194
195    /* Refresh */
196    caca_refresh_display(dp);
197
198    for(;;)
199    {
200        caca_event_t ev;
201        int ret;
202
203        refresh |= update_screens_contents(screen_list);
204
205        /* No more screens, exit */
206        if(!screen_list->count) break;
207
208        /* Update each screen canvas  */
209        refresh |= update_terms(screen_list);
210
211        /* Get events, if any */
212        ret = caca_get_event(dp, CACA_EVENT_ANY, &ev, 0);
213
214        if(ret && (caca_get_event_type(&ev) & CACA_EVENT_KEY_PRESS))
215        {
216            unsigned int c = caca_get_event_key_ch(&ev);
217
218            if(command)
219            {
220                command = 0;
221
222                switch(c)
223                {
224                case 0x01: //CACA_KEY_CTRL_A:
225                    screen_list->pty ^= screen_list->prevpty;
226                    screen_list->prevpty ^= screen_list->pty;
227                    screen_list->pty ^= screen_list->prevpty;
228                    refresh = 1;
229                    break;
230                case 'm':
231                case 0x0d: //CACA_KEY_CTRL_M:
232                    screen_list->mini = !screen_list->mini;
233                    refresh = 1;
234                    break;
235                case 'n':
236                case ' ':
237                case '\0':
238                case 0x0e: //CACA_KEY_CTRL_N:
239                    screen_list->prevpty = screen_list->pty;
240                    screen_list->pty = (screen_list->pty + 1) % screen_list->count;
241                    refresh = 1;
242                    break;
243                case 'p':
244                case 0x10: //CACA_KEY_CTRL_P:
245                    screen_list->prevpty = screen_list->pty;
246                    screen_list->pty = (screen_list->pty + screen_list->count - 1) % screen_list->count;
247                    refresh = 1;
248                    break;
249                case 'c':
250                case 0x03: //CACA_KEY_CTRL_C:
251                    screen_list->prevpty = screen_list->pty;
252                    screen_list->pty =
253                        add_screen(screen_list, create_screen(w, h, default_shell));
254                    refresh = 1;
255                    break;
256                case 'w':
257                case 0x17: //CACA_KEY_CTRL_W:
258                    screen_list->wm_type = (screen_list->wm_type==(WM_MAX-1)?
259                                            screen_list->wm_type=0:
260                                            screen_list->wm_type+1);
261                    refresh = 1;
262                    break;
263                case 0x0b: //CACA_KEY_CTRL_K:
264                    add_recurrent(recurrent_list, close_screen_recurrent, cv);
265                    refresh = 1;
266                    break;
267                case 'h':
268                case 0x08: //CACA_KEY_CTRL_H:
269                    screen_list->help = !screen_list->help;
270                    refresh = 1;
271                    break;
272                }
273            }
274            else
275            {
276
277                last_key_time = get_ms();
278                caca_set_cursor(dp, 1);
279
280                if(screen_list->in_screensaver)
281                {
282                    screensaver_kill(cv, dp, screen_list);
283                    screen_list->in_screensaver = 0;
284                    refresh = 1;
285                    continue;
286                }
287
288
289                switch(c)
290                {
291                case 0x01: //CACA_KEY_CTRL_A:
292                    command = 1; break;
293                case CACA_KEY_UP:
294                    write(screen_list->screen[screen_list->pty]->fd, "\x1b[A", 3); break;
295                case CACA_KEY_DOWN:
296                    write(screen_list->screen[screen_list->pty]->fd, "\x1b[B", 3); break;
297                case CACA_KEY_RIGHT:
298                    write(screen_list->screen[screen_list->pty]->fd, "\x1b[C", 3); break;
299                case CACA_KEY_LEFT:
300                    write(screen_list->screen[screen_list->pty]->fd, "\x1b[D", 3); break;
301                case CACA_KEY_ESCAPE:
302                    if(screen_list->help)
303                    {
304                        screen_list->help = 0;
305                        refresh = 1;
306                        break;
307                    }
308                default:
309                    write(screen_list->screen[screen_list->pty]->fd, &c, 1); break;
310                }
311            }
312        }
313        else if(ret && (caca_get_event_type(&ev) & CACA_EVENT_RESIZE))
314        {
315            update_windows_props(cv, screen_list);
316            cucul_clear_canvas(cv);
317            refresh = 1;
318        }
319        else if(ret && (caca_get_event_type(&ev) & CACA_EVENT_QUIT))
320        {
321            break;
322        }
323
324        /* Recurrent functions */
325        for(i=0; i<recurrent_list->count; i++)
326        {
327            if(recurrent_list->recurrent[i]->function)
328            {
329                refresh |= recurrent_list->recurrent[i]->function(screen_list,
330                                                                  recurrent_list->recurrent[i],
331                                                                  recurrent_list->recurrent[i]->user,
332                                                                  get_ms());
333            }
334        }
335       /* Delete recurrent functions */
336        for(i=0; i<recurrent_list->count; i++)
337        {
338            if(recurrent_list->recurrent[i]->kill_me)
339            {
340                remove_recurrent(recurrent_list, i);
341                i = 0;
342            }
343        }
344
345        /* Resfresh screen */
346        if((refresh || screen_list->in_bell) &&
347           (get_ms() - last_key_time < screen_list->screensaver_timeout))
348        {
349            refresh = 0;
350            refresh_screens(cv, dp, screen_list);
351        }
352        if((get_ms() - last_key_time > screen_list->screensaver_timeout))
353        {
354            if(!screen_list->in_screensaver)
355                screensaver_init(cv, dp, screen_list);
356            screen_list->in_screensaver = 1;
357
358            caca_set_cursor(dp, 0);
359            draw_screensaver(cv, dp, screen_list);
360            caca_refresh_display(dp);
361        }
362
363        eof = 1;
364        for(i = 0; i < screen_list->count; i++)
365            if(screen_list->screen[i]->fd >= 0)
366                eof = 0;
367        if(eof)
368            break;
369    }
370
371end:
372    /* Clean up */
373    caca_free_display(dp);
374    cucul_free_canvas(cv);
375    for(i = 0; i < screen_list->count; i++)
376    {
377        destroy_screen(screen_list->screen[i]);
378    }
379
380    free(screen_list->screen);
381    free(screen_list);
382
383
384    for(i=0; i<recurrent_list->count; i++)
385    {
386        remove_recurrent(recurrent_list, i);
387        i = 0;
388    }
389
390    free(recurrent_list->recurrent);
391    free(recurrent_list);
392
393
394    return 0;
395}
396
397
398
399long long get_ms(void)
400{
401    struct timeval tv;
402    gettimeofday(&tv, NULL);
403
404
405    return (tv.tv_sec*(1000000) + tv.tv_usec);
406}
Note: See TracBrowser for help on using the repository browser.