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

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