OpenCores
URL https://opencores.org/ocsvn/or1k_old/or1k_old/trunk

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [mw/] [src/] [demos/] [nanox/] [launcher.c] - Blame information for rev 1782

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 673 markom
/*
2
 * The contents of this file are subject to the Mozilla Public License
3
 * Version 1.1 (the "License"); you may not use this file except in
4
 * compliance with the License. You may obtain a copy of the License at
5
 * http://www.mozilla.org/MPL/
6
 *
7
 * Software distributed under the License is distributed on an "AS IS"
8
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
9
 * License for the specific language governing rights and limitations
10
 * under the License.
11
 *
12
 * The Original Code is NanoLauncher.
13
 *
14
 * The Initial Developer of the Original Code is Alex Holden.
15
 * Portions created by Alex Holden are Copyright (C) 2000
16
 * Alex Holden <alex@linuxhacker.org>. All Rights Reserved.
17
 *
18
 * Contributor(s):
19
 *
20
 * Alternatively, the contents of this file may be used under the terms
21
 * of the GNU General Public license (the  "[GNU] License"), in which case the
22
 * provisions of [GNU] License are applicable instead of those
23
 * above.  If you wish to allow use of your version of this file only
24
 * under the terms of the [GNU] License and not to allow others to use
25
 * your version of this file under the MPL, indicate your decision by
26
 * deleting  the provisions above and replace  them with the notice and
27
 * other provisions required by the [GNU] License.  If you do not delete
28
 * the provisions above, a recipient may use your version of this file
29
 * under either the MPL or the [GNU] License.
30
 */
31
 
32
/*
33
 * A simple application launcher for Nano-X by Alex Holden.
34
 *
35
 * The application needs to be started with the first argument specifying
36
 * the location of it's configuration file. The format of the file is
37
 * extremely simple- each line can contain either a comment (indicated by
38
 * beginning the line with a '#' symbol) or an item description.
39
 * An item description consists of the name of the item (the title which
40
 * appears underneath the icon on the launcher button) followed by the name
41
 * of the icon file (or '-' for no icon) and the command to execute when the
42
 * item is clicked on. The command can optionally be followed by a limited
43
 * number of arguments to pass to the program when it is executed (increase
44
 * MAX_ARGUMENTS in launcher.h if you need more). The program will currently
45
 * only allow one icon size (specified at compile time by the ICON_WIDTH and
46
 * ICON_HEIGHT parameters). The program only loads each icon file once even if
47
 * it is used multiple times, so you can save a small amount of memory by
48
 * using the same icon for several programs. If you want to change the size
49
 * of the item buttons, change ITEM_WIDTH and ITEM_HEIGHT in launcher.h.
50
 * The way the launcher decides whether to draw a vertical panel on the left
51
 * hand side of the screen or a horizontal panel along the bottom is by
52
 * looking at the width and height of the screen- the panel will be placed on
53
 * the side on portrait screens and on the bottom on landscape screens.
54
 */
55
 
56
#include <stdio.h>
57
#include <errno.h>
58
#include <stdlib.h>
59
#include <string.h>
60
#include <ctype.h>
61
#include <signal.h>
62
#include <unistd.h>
63
#include <sys/wait.h>
64
 
65
#define MWINCLUDECOLORS
66
#include "nano-X.h"
67
#include "launcher.h"
68
 
69
void reaper(int signum) { while(waitpid(WAIT_ANY, NULL, WNOHANG) > 0); }
70
 
71
void *my_malloc(size_t size)
72
{
73
        void *ret;
74
 
75
        if(!(ret = malloc(size))) {
76
                fprintf(stderr, "Out of memory\n");
77
                exit(1);
78
        }
79
 
80
        return ret;
81
}
82
 
83
void usage(void)
84
{
85
        fprintf(stderr, "Usage: launcher <config-file>\n");
86
        exit(3);
87
}
88
 
89
prog_item *make_prog_item(char *buf, int lineno)
90
{
91
        char *p, *pp, *command;
92
        prog_item *prog;
93
        int n;
94
 
95
        p = buf;
96
 
97
        prog = my_malloc(sizeof(prog_item));
98
 
99
        for(n = 0; n < MAX_ARGUMENTS; n++) prog->argv[n] = NULL;
100
 
101
        while(isspace(*p)) p++;
102
        if(!*p) {
103
                fprintf(stderr, "Premature end of line on line %d of config "
104
                                "file\n", lineno);
105
                return 0;
106
        }
107
        command = p;
108
        while(*p && (!isspace(*p))) p++;
109
        *p++ = 0;
110
        if(!(prog->command = strdup(command))) {
111
                free(prog);
112
                goto nomem;
113
        }
114
        pp = p - 1;
115
        while(--pp != command) {
116
                if(*pp == '/') {
117
                        pp++;
118
                        break;
119
                }
120
        }
121
        if(!(prog->argv[0] = strdup(pp))) {
122
                free(prog->command);
123
                free(prog);
124
                goto nomem;
125
        }
126
 
127
        n = 1;
128
        while(*p) {
129
                while(isspace(*p)) p++;
130
                if(!*p) break;
131
                pp = p;
132
                while(*p && (!isspace(*p))) p++;
133
                *p++ = 0;
134
                if(!(prog->argv[n] = strdup(pp))) {
135
                        for(n = MAX_ARGUMENTS; n; n--)
136
                                if(prog->argv[n]) free(prog->argv[n]);
137
                        free(prog->command);
138
                        free(prog);
139
                        goto nomem;
140
                }
141
                if(++n == (MAX_ARGUMENTS - 1)) {
142
                        fprintf(stderr, "Too many arguments on line "
143
                                "%d of the config file\n", lineno);
144
                        break;
145
                }
146
        }
147
 
148
        return prog;
149
 
150
nomem:
151
        fprintf(stderr, "Out of memory parsing line %d of the config "
152
                        "file\n", lineno);
153
        return 0;
154
}
155
 
156
void set_window_background_colour(char *buf, int lineno)
157
{
158
        GR_WM_PROPERTIES props;
159
        char *p = buf, *pp;
160
 
161
        while(isspace(*p)) p++;
162
        if(!*p) {
163
                fprintf(stderr, "Premature end of line on line %d of config "
164
                                "file\n", lineno);
165
                return;
166
        }
167
        pp = p;
168
        while(*p && (!isspace(*p))) p++;
169
        *p = 0;
170
 
171
        if(!strcmp(pp, "BLACK")) props.background = BLACK;
172
        else if(!strcmp(pp, "BLUE")) props.background = BLUE;
173
        else if(!strcmp(pp, "GREEN")) props.background = GREEN;
174
        else if(!strcmp(pp, "CYAN")) props.background = CYAN;
175
        else if(!strcmp(pp, "RED")) props.background = RED;
176
        else if(!strcmp(pp, "MAGENTA")) props.background = MAGENTA;
177
        else if(!strcmp(pp, "BROWN")) props.background = BROWN;
178
        else if(!strcmp(pp, "LTGRAY")) props.background = LTGRAY;
179
        else if(!strcmp(pp, "GRAY")) props.background = GRAY;
180
        else if(!strcmp(pp, "LTBLUE")) props.background = LTBLUE;
181
        else if(!strcmp(pp, "LTGREEN")) props.background = LTGREEN;
182
        else if(!strcmp(pp, "LTCYAN")) props.background = LTCYAN;
183
        else if(!strcmp(pp, "LTRED")) props.background = LTRED;
184
        else if(!strcmp(pp, "LTMAGENTA")) props.background = LTMAGENTA;
185
        else if(!strcmp(pp, "YELLOW")) props.background = YELLOW;
186
        else if(!strcmp(pp, "WHITE")) props.background = WHITE;
187
        else {
188
                fprintf(stderr, "Invalid colour \"%s\" on line %d of config "
189
                                                        "file\n", pp, lineno);
190
                return;
191
        }
192
 
193
        props.flags = GR_WM_FLAGS_BACKGROUND;
194
        GrSetWMProperties(GR_ROOT_WINDOW_ID, &props);
195
}
196
 
197
void parse_config_line(lstate *state, char *buf, int lineno)
198
{
199
        char *p, *pp, *name, *icon;
200
        int n;
201
        litem *new_litem, *li;
202
        sitem *new_sitem;
203
        GR_IMAGE_INFO imageinfo;
204
 
205
        p = buf;
206
 
207
        if((!*p) || (*p == '#') || (*p == '\n')) return;
208
 
209
        while(isspace(*p)) p++;
210
        name = p;
211
        while(*p && (!isspace(*p))) p++;
212
        if(!*p) goto premature;
213
        *p++ = 0;
214
 
215
        if(!strcmp(name, "$screensaver")) {
216
                new_sitem = my_malloc(sizeof(sitem));
217
                if(!(new_sitem->prog = make_prog_item(p, lineno))) {
218
                        free(new_sitem);
219
                        return;
220
                }
221
                new_sitem->next = NULL;
222
                if(!state->sitems) {
223
                        state->sitems = new_sitem;
224
                        state->cursitem = new_sitem;
225
                } else {
226
                        new_sitem->next = state->sitems;
227
                        state->sitems = new_sitem;
228
                }
229
                return;
230
        } else if(!strcmp(name, "$screensaver_timeout")) {
231
                n = strtol(p, NULL, 10);
232
                GrSetScreenSaverTimeout(n);
233
                return;
234
        } else if(!strcmp(name, "$window_background_image")) {
235
                while(isspace(*p)) p++;
236
                if(!*p) goto premature;
237
                pp = p;
238
                while(*p && (!isspace(*p))) p++;
239
                *p = 0;
240
                state->window_background_image = strdup(pp);
241
                return;
242
        } else if(!strcmp(name, "$window_background_mode")) {
243
                state->window_background_mode = (int) strtol(p, NULL, 10);
244
                return;
245
        } else if(!strcmp(name, "$window_background_colour")) {
246
                set_window_background_colour(p, lineno);
247
                return;
248
        }
249
 
250
        while(isspace(*p)) p++;
251
        if(!*p) goto premature;
252
        icon = p;
253
        while(*p && (!isspace(*p))) p++;
254
        if(!*p) goto premature;
255
        *p++ = 0;
256
 
257
        new_litem = my_malloc(sizeof(litem));
258
        if(!(new_litem->name = strdup(name))) {
259
                free(new_litem);
260
                goto nomem;
261
        }
262
        if(!(new_litem->icon = strdup(icon))) {
263
                free(new_litem->name);
264
                free(new_litem);
265
                goto nomem;
266
        }
267
        if(!(new_litem->prog = make_prog_item(p, lineno))) {
268
                free(new_litem->name);
269
                free(new_litem->icon);
270
                free(new_litem);
271
                return;
272
        }
273
        new_litem->iconid = 0;
274
        if(strcmp("-", icon)) {
275
                li = state->litems;
276
                while(li) {
277
                        if(!(strcmp(icon, li->name))) {
278
                                new_litem->iconid = li->iconid;
279
                                break;
280
                        }
281
                        li = li->next;
282
                }
283
                if(!new_litem->iconid) {
284
                        if(!(new_litem->iconid = GrLoadImageFromFile(icon, 0))){
285
                                fprintf(stderr, "Couldn't load icon \"%s\"\n",
286
                                                                        icon);
287
                        } else {
288
                                GrGetImageInfo(new_litem->iconid, &imageinfo);
289
                                if((imageinfo.width != ICON_WIDTH) ||
290
                                        (imageinfo.height != ICON_HEIGHT)) {
291
                                        fprintf(stderr, "Icon \"%s\" is the "
292
                                        "wrong size (%dx%d instead of %dx%d)"
293
                                        "\n", icon, imageinfo.width,
294
                                        imageinfo.height, ICON_WIDTH,
295
                                        ICON_HEIGHT);
296
                                        GrFreeImage(new_litem->iconid);
297
                                        new_litem->iconid = 0;
298
                                }
299
                        }
300
                }
301
        }
302
 
303
        new_litem->prev = NULL;
304
        new_litem->next = NULL;
305
        if(!state->litems) {
306
                state->lastlitem = new_litem;
307
                state->litems = new_litem;
308
        } else {
309
                new_litem->next = state->litems;
310
                state->litems->prev = new_litem;
311
                state->litems = new_litem;
312
        }
313
 
314
        state->numlitems++;
315
 
316
        return;
317
 
318
nomem:
319
        fprintf(stderr, "Out of memory\n");
320
        exit(1);
321
 
322
premature:
323
        fprintf(stderr, "Premature end of line on line %d of config file\n",
324
                                                                lineno);
325
}
326
 
327
void read_config(lstate *state)
328
{
329
        int lineno = 1;
330
        FILE *fp;
331
        char *buf = my_malloc(256);
332
 
333
        if(!(fp = fopen(state->config_file, "r"))) {
334
                fprintf(stderr, "Couldn't open config file \"%s\"\n",
335
                                                        state->config_file);
336
                exit(2);
337
        }
338
 
339
        state->litems = NULL;
340
        state->numlitems = 0;
341
        state->sitems = NULL;
342
 
343
        while(fgets(buf, 256, fp)) {
344
                parse_config_line(state, buf, lineno);
345
                lineno++;
346
        }
347
 
348
        fclose(fp);
349
        free(buf);
350
 
351
        if(!state->numlitems) {
352
                fprintf(stderr, "No valid launcher items in config file\n");
353
                exit(5);
354
        }
355
}
356
 
357
void draw_item(lstate *state, litem *item)
358
{
359
        GR_SIZE width, height, base, x, len;
360
 
361
        GrDrawImageToFit(item->wid, state->gc, ICON_X_POSITION, ICON_Y_POSITION,
362
                                ICON_WIDTH, ICON_HEIGHT, item->iconid);
363
 
364
        len = strlen(item->name);
365
        GrGetGCTextSize(state->gc, item->name, len, 0, &width, &height, &base);
366
        if(width >= ITEM_WIDTH) x = 0;
367
        else x = (ITEM_WIDTH - width) / 2;
368
 
369
        GrText(item->wid, state->gc, x, TEXT_Y_POSITION, item->name, len, 0);
370
}
371
 
372
void handle_exposure_event(lstate *state)
373
{
374
        GR_EVENT_EXPOSURE *event = &state->event.exposure;
375
        litem *i = state->litems;
376
 
377
        if(event->wid == state->main_window) return;
378
 
379
        while(i) {
380
                if(event->wid == i->wid) {
381
                        draw_item(state, i);
382
                        return;
383
                }
384
                i = i->next;
385
        }
386
 
387
        fprintf(stderr, "Got exposure event for unknown window %d\n",
388
                                                        event->wid);
389
}
390
 
391
void launch_program(prog_item *prog)
392
{
393
        pid_t pid;
394
 
395
        if((pid = fork()) == -1) perror("Couldn't fork");
396
        else if(!pid) {
397
                if(execvp(prog->command, prog->argv) == -1)
398
                        fprintf(stderr, "Couldn't start \"%s\": %s\n",
399
                                        prog->command, strerror(errno));
400
                exit(7);
401
        }
402
}
403
 
404
void handle_mouse_event(lstate *state)
405
{
406
        GR_EVENT_MOUSE *event = &state->event.mouse;
407
        litem *i = state->litems;
408
 
409
        if(event->wid == state->main_window) return;
410
 
411
        while(i) {
412
                if(event->wid == i->wid) {
413
                        launch_program(i->prog);
414
                        return;
415
                }
416
                i = i->next;
417
        }
418
 
419
        fprintf(stderr, "Got mouse event for unknown window %d\n", event->wid);
420
}
421
 
422
void handle_screensaver_event(lstate *state)
423
{
424
        GR_EVENT_SCREENSAVER *event = &state->event.screensaver;
425
 
426
        if(event->activate != GR_TRUE) return;
427
 
428
        if(!state->sitems) {
429
                fprintf(stderr, "Got screensaver activate event with no "
430
                                "screensavers defined\n");
431
                return;
432
        }
433
 
434
        state->cursitem = state->cursitem->next;
435
        if(!state->cursitem) state->cursitem = state->sitems;
436
 
437
        launch_program(state->cursitem->prog);
438
}
439
 
440
void handle_event(lstate *state)
441
{
442
        switch(state->event.type) {
443
                case GR_EVENT_TYPE_EXPOSURE:
444
                        handle_exposure_event(state);
445
                        break;
446
                case GR_EVENT_TYPE_BUTTON_DOWN:
447
                        handle_mouse_event(state);
448
                        break;
449
                case GR_EVENT_TYPE_CLOSE_REQ:
450
                        break;
451
                case GR_EVENT_TYPE_SCREENSAVER:
452
                        handle_screensaver_event(state);
453
                        break;
454
                case GR_EVENT_TYPE_NONE:
455
                        break;
456
                default:
457
                        fprintf(stderr, "Got unknown event type %d\n",
458
                                                        state->event.type);
459
                        break;
460
        }
461
}
462
 
463
void do_event_loop(lstate *state)
464
{
465
        do {
466
                GrGetNextEvent(&state->event);
467
                handle_event(state);
468
        } while(state->event.type != GR_EVENT_TYPE_CLOSE_REQ);
469
}
470
 
471
void initialise(lstate *state)
472
{
473
        GR_SCREEN_INFO si;
474
        GR_IMAGE_ID back_image;
475
        GR_IMAGE_INFO imageinfo;
476
        int rows = 1, columns = 1, width, height, x = 0, y = 1;
477
        GR_WM_PROPERTIES props;
478
        litem *i;
479
 
480
        if(GrOpen() < 0) {
481
                fprintf(stderr, "Couldn't connect to Nano-X server\n");
482
                exit(4);
483
        }
484
 
485
        state->window_background_mode = 0;
486
        state->window_background_image = NULL;
487
 
488
        read_config(state);
489
 
490
        GrGetScreenInfo(&si);
491
 
492
        if(si.rows > si.cols) {
493
                rows = state->numlitems;
494
                while((((rows / columns) + rows % columns) * ITEM_HEIGHT) >
495
                                                                si.rows) {
496
                        columns++;
497
                }
498
                if((columns * ITEM_WIDTH) > si.cols) goto toomany;
499
                rows = (rows / columns) + (rows % columns);
500
                width = columns * ITEM_WIDTH + 1 + columns;
501
                height = rows * ITEM_HEIGHT + 1 + rows;
502
        } else {
503
                columns = state->numlitems;
504
                while((((columns / rows) + (columns % rows)) * ITEM_WIDTH) >
505
                                                                si.cols) {
506
                        rows++;
507
                }
508
                if((rows * ITEM_HEIGHT) > si.rows) goto toomany;
509
                columns = (columns / rows) + (columns % rows);
510
                width = columns * ITEM_WIDTH + 1 + columns;
511
                height = (rows * ITEM_HEIGHT) + 1 + rows;
512
                y = si.rows - (rows * ITEM_HEIGHT) - 1 - rows;
513
        }
514
 
515
        state->gc = GrNewGC();
516
        GrSetGCForeground(state->gc, ITEM_TEXT_COLOUR);
517
        GrSetGCBackground(state->gc, ITEM_BACKGROUND_COLOUR);
518
 
519
        if(state->window_background_image) {
520
                if(!(back_image = GrLoadImageFromFile(
521
                                        state->window_background_image, 0))) {
522
                        fprintf(stderr, "Couldn't load background image\n");
523
                } else {
524
                        GrGetImageInfo(back_image, &imageinfo);
525
                        if(!(state->background_pixmap = GrNewPixmap(
526
                                                        imageinfo.width,
527
                                                imageinfo.height, NULL))) {
528
                                fprintf(stderr, "Couldn't allocate pixmap "
529
                                                "for background image\n");
530
                        } else {
531
                                GrDrawImageToFit(state->background_pixmap,
532
                                        state->gc, 0, 0, imageinfo.width,
533
                                        imageinfo.height, back_image);
534
                                GrFreeImage(back_image);
535
                                GrSetBackgroundPixmap(GR_ROOT_WINDOW_ID,
536
                                        state->background_pixmap,
537
                                        state->window_background_mode);
538
                                GrClearWindow(GR_ROOT_WINDOW_ID, GR_TRUE);
539
                        }
540
                }
541
        }
542
 
543
        if(state->sitems)
544
                GrSelectEvents(GR_ROOT_WINDOW_ID, GR_EVENT_MASK_SCREENSAVER);
545
 
546
        state->main_window = GrNewWindow(GR_ROOT_WINDOW_ID, 0, y, width, height,
547
                                                0, ITEM_BACKGROUND_COLOUR, 0);
548
        GrSelectEvents(state->main_window, GR_EVENT_MASK_CLOSE_REQ);
549
        props.flags = GR_WM_FLAGS_PROPS;
550
        props.props = GR_WM_PROPS_NOMOVE | GR_WM_PROPS_NODECORATE |
551
                        GR_WM_PROPS_NOAUTOMOVE | GR_WM_PROPS_NOAUTORESIZE;
552
        GrSetWMProperties(state->main_window, &props);
553
 
554
        i = state->lastlitem;
555
        y = 0;
556
        while(i) {
557
                i->wid = GrNewWindow(state->main_window,
558
                                        (x * ITEM_WIDTH) + x + 1,
559
                                        (y * ITEM_HEIGHT) + y + 1, ITEM_WIDTH,
560
                                        ITEM_HEIGHT, 1, ITEM_BACKGROUND_COLOUR,
561
                                                        ITEM_BORDER_COLOUR);
562
                GrSelectEvents(i->wid, GR_EVENT_MASK_EXPOSURE |
563
                                        GR_EVENT_MASK_BUTTON_DOWN);
564
                GrMapWindow(i->wid);
565
                i = i->prev;
566
                if(++x == columns) {
567
                        x = 0;
568
                        y++;
569
                }
570
        }
571
 
572
        GrMapWindow(state->main_window);
573
 
574
        signal(SIGCHLD, &reaper);
575
 
576
        return;
577
 
578
toomany:
579
        fprintf(stderr, "Too many items to fit on screen\n");
580
        exit(6);
581
}
582
 
583
int main(int argc, char *argv[])
584
{
585
        lstate *state;
586
 
587
        if(argc != 2) usage();
588
 
589
        state = my_malloc(sizeof(lstate));
590
        state->config_file = strdup(argv[1]);
591
 
592
        initialise(state);
593
 
594
        do_event_loop(state);
595
 
596
        GrClose();
597
 
598
        return 0;
599
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.