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

Last change on this file since 2447 was 2447, checked in by Jean-Yves Lamoureux, 13 years ago
  • Added an ugly-not-finished-yet screensaver
  • Property svn:keywords set to Id
File size: 11.3 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 2447 2008-06-18 13:47:59Z 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 = (10) * 1000000;
125
126
127    recurrent_list = (struct recurrent_list*) malloc(sizeof(struct recurrent_list));
128    recurrent_list->recurrent = (struct recurrent**) malloc(sizeof(struct recurrent*));
129    if(!recurrent_list->recurrent)
130    {
131        fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__, __LINE__);
132        return -1;
133    }
134    recurrent_list->count = 0;
135
136    for(;;)
137    {
138        int option_index = 0;
139        static struct myoption long_options[] =
140            {
141#ifdef USE_GRAB
142                { "pid",         1, NULL, 'P' },
143#endif
144                { "help",        0, NULL, 'h' },
145                { "version",     0, NULL, 'v' },
146            };
147        int c = mygetopt(argc, argv, "P:hv", long_options, &option_index);
148        if(c == -1)
149            break;
150
151        switch(c)
152        {
153#ifdef USE_GRAB
154        case 'P': /* --pid */
155            add_screen(screen_list,create_screen_grab(w, h, atoi(myoptarg)));
156            s+=2;
157            break;
158#endif
159        case 'h': /* --help */
160            //   usage(argc, argv);
161            return 0;
162            break;
163        case 'v': /* --version */
164            version();
165            goto end;
166            break;
167        default:
168            fprintf(stderr, "Unknow argument #%d\n", myoptind);
169            return -1;
170            break;
171        }
172    }
173
174
175    if(s == 0 && argc<2)
176    {
177        add_screen(screen_list, create_screen(w, h, default_shell));
178    }
179
180    /* Launch command line processes */
181    for(i=0; i<(argc-1) - s; i++)
182    {
183        add_screen(screen_list, create_screen(w, h, argv[i+s+1]));
184    }
185
186
187    /* Windows are in a temporary state, resize them to the right dimensions */
188    update_windows_props(cv, screen_list);
189
190    last_key_time = get_ms();
191
192    /* Refresh */
193    caca_refresh_display(dp);
194
195    for(;;)
196    {
197        caca_event_t ev;
198        int ret;
199
200        refresh |= update_screens_contents(screen_list);
201
202        /* No more screens, exit */
203        if(!screen_list->count) break;
204
205        /* Update each screen canvas  */
206        refresh |= update_terms(screen_list);
207
208        /* Get events, if any */
209        ret = caca_get_event(dp, CACA_EVENT_ANY, &ev, 0);
210        if(ret && (caca_get_event_type(&ev) & CACA_EVENT_KEY_PRESS))
211        {
212            unsigned int c = caca_get_event_key_ch(&ev);
213
214            if(command)
215            {
216                command = 0;
217
218                switch(c)
219                {
220                case 0x01: //CACA_KEY_CTRL_A:
221                    screen_list->pty ^= screen_list->prevpty;
222                    screen_list->prevpty ^= screen_list->pty;
223                    screen_list->pty ^= screen_list->prevpty;
224                    refresh = 1;
225                    break;
226                case 'm':
227                case 0x0d: //CACA_KEY_CTRL_M:
228                    screen_list->mini = !screen_list->mini;
229                    refresh = 1;
230                    break;
231                case 'n':
232                case ' ':
233                case '\0':
234                case 0x0e: //CACA_KEY_CTRL_N:
235                    screen_list->prevpty = screen_list->pty;
236                    screen_list->pty = (screen_list->pty + 1) % screen_list->count;
237                    refresh = 1;
238                    break;
239                case 'p':
240                case 0x10: //CACA_KEY_CTRL_P:
241                    screen_list->prevpty = screen_list->pty;
242                    screen_list->pty = (screen_list->pty + screen_list->count - 1) % screen_list->count;
243                    refresh = 1;
244                    break;
245                case 'c':
246                case 0x03: //CACA_KEY_CTRL_C:
247                    screen_list->prevpty = screen_list->pty;
248                    screen_list->pty =
249                        add_screen(screen_list, create_screen(w, h, default_shell));
250                    refresh = 1;
251                    break;
252                case 'w':
253                case 0x17: //CACA_KEY_CTRL_W:
254                    screen_list->wm_type = (screen_list->wm_type==(WM_MAX-1)?
255                                            screen_list->wm_type=0:
256                                            screen_list->wm_type+1);
257                    refresh = 1;
258                    break;
259                case 0x0b: //CACA_KEY_CTRL_K:
260                    add_recurrent(recurrent_list, close_screen_recurrent, cv);
261                    refresh = 1;
262                    break;
263                case 'h':
264                case 0x08: //CACA_KEY_CTRL_H:
265                    screen_list->help = !screen_list->help;
266                    refresh = 1;
267                    break;
268                }
269            }
270            else
271            {
272                switch(c)
273                {
274                case 0x01: //CACA_KEY_CTRL_A:
275                    command = 1; break;
276                case CACA_KEY_UP:
277                    write(screen_list->screen[screen_list->pty]->fd, "\x1b[A", 3); break;
278                case CACA_KEY_DOWN:
279                    write(screen_list->screen[screen_list->pty]->fd, "\x1b[B", 3); break;
280                case CACA_KEY_RIGHT:
281                    write(screen_list->screen[screen_list->pty]->fd, "\x1b[C", 3); break;
282                case CACA_KEY_LEFT:
283                    write(screen_list->screen[screen_list->pty]->fd, "\x1b[D", 3); break;
284                case CACA_KEY_ESCAPE:
285                    if(screen_list->help) screen_list->help = 0;
286                default:
287                    write(screen_list->screen[screen_list->pty]->fd, &c, 1); break;
288                }
289            }
290            last_key_time = get_ms();
291            caca_set_cursor(dp, 1);
292        }
293        else if(ret && (caca_get_event_type(&ev) & CACA_EVENT_RESIZE))
294        {
295            update_windows_props(cv, screen_list);
296            cucul_clear_canvas(cv);
297            refresh = 1;
298        }
299        else if(ret && (caca_get_event_type(&ev) & CACA_EVENT_QUIT))
300        {
301            break;
302        }
303
304        /* Recurrent functions */
305        for(i=0; i<recurrent_list->count; i++)
306        {
307            if(recurrent_list->recurrent[i]->function)
308            {
309                refresh |= recurrent_list->recurrent[i]->function(screen_list,
310                                                                  recurrent_list->recurrent[i],
311                                                                  recurrent_list->recurrent[i]->user,
312                                                                  get_ms());
313            }
314        }
315       /* Delete recurrent functions */
316        for(i=0; i<recurrent_list->count; i++)
317        {
318            if(recurrent_list->recurrent[i]->kill_me)
319            {
320                remove_recurrent(recurrent_list, i);
321                i = 0;
322            }
323        }
324
325        /* Resfresh screen */
326        if((refresh || screen_list->in_bell) &&
327           (get_ms() - last_key_time < screen_list->screensaver_timeout))
328        {
329            refresh = 0;
330            refresh_screens(cv, dp, screen_list);
331        }
332        if((get_ms() - last_key_time > screen_list->screensaver_timeout))
333        {
334            caca_set_cursor(dp, 0);
335            draw_screensaver(cv, dp, screen_list);
336            caca_refresh_display(dp);
337        }
338
339        eof = 1;
340        for(i = 0; i < screen_list->count; i++)
341            if(screen_list->screen[i]->fd >= 0)
342                eof = 0;
343        if(eof)
344            break;
345    }
346
347end:
348    /* Clean up */
349    caca_free_display(dp);
350    cucul_free_canvas(cv);
351    for(i = 0; i < screen_list->count; i++)
352    {
353        destroy_screen(screen_list->screen[i]);
354    }
355
356    free(screen_list->screen);
357    free(screen_list);
358
359
360    for(i=0; i<recurrent_list->count; i++)
361    {
362        remove_recurrent(recurrent_list, i);
363        i = 0;
364    }
365
366    free(recurrent_list->recurrent);
367    free(recurrent_list);
368
369
370    return 0;
371}
372
373
374
375long long get_ms(void)
376{
377    struct timeval tv;
378    gettimeofday(&tv, NULL);
379
380
381    return (tv.tv_sec*(1000000) + tv.tv_usec);
382}
Note: See TracBrowser for help on using the repository browser.