site: end of line message, adesklets is not dead.
[adesklets.git] / src / adesklets.c
blobab1450625a445318bff14cc0044667da0debd519
1 /*--- adesklets.c --------------------------------------------------------------
2 Copyright (C) 2004, 2005, 2006 Sylvain Fourmanoit <syfou@users.sourceforge.net>
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to
6 deal in the Software without restriction, including without limitation the
7 rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8 sell copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
11 The above copyright notice and this permission notice shall be included in
12 all copies of the Software and its documentation and acknowledgment shall be
13 given in the documentation and software packages that this Software was
14 used.
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 ------------------------------------------------------------------------------*/
23 #include "adesklets.h" /* Application main header */
25 /*----------------------------------------------------------------------------*/
26 #define welcome(stream) fprintf(stream,\
27 "%s\n[%s]\n",WELCOME_LINE_1,WELCOME_LINE_2)
29 /*----------------------------------------------------------------------------*/
30 t_adesklets adesklets = {
31 0, /* pid_t ppid */
32 NULL, /* Display * display */
33 NULL, /* Visual * visual */
34 0, /* Window root */
35 0, /* Window window */
36 0, /* int depth */
37 X_POLLING_PERIOD, /* int polling */
38 0, /* int transparency */
39 X_DISPLAY_SUPPORT, /* int background_grab */
40 -1, /* int user_background_image */
41 0, /* int managed */
42 BASE_EVENT_MASK, /* long event_mask */
43 0, /* long user_event_mask */
44 NULL, /* cfgfile_item * params */
45 NULL, /* vector * menus */
46 NULL, /* vector * images */
47 NULL, /* vector * fonts */
48 NULL, /* vector * color_ranges */
49 NULL, /* vector * color_modifiers */
50 NULL, /* vector * imlib_filters */
51 NULL, /* vector * polygons */
52 NULL, /* vector * variables */
53 "", /* char * lock_filename */
54 NULL, /* FILE * lock */
55 0, /* int quit_flag */
56 0, /* int restart_flag */
57 0 /* int user_quit_flag */
60 /*----------------------------------------------------------------------------*/
61 /* Termination handler prototype for adesklets_free()
63 void termination_handler(int);
65 /*----------------------------------------------------------------------------*/
66 /* Reinstate the menus in pristine state: only one default menu with two
67 or three items: Move (if applicable), Restart (if applicable)
68 and Quit - all managed internally.
69 If an already filled menu could not get reset, returns 0 instead
70 of the successful 1.
72 int
73 adesklets_menus_reset(void)
75 int result=0;
76 xmenu * menu;
78 if (adesklets.menus)
79 adesklets.menus=vector_free(adesklets.menus);
80 if (!adesklets.menus)
81 if ((adesklets.menus=vector_init())) {
82 adesklets.menus->vector_free_item=xmenu_vector_free_item;
83 menu=xmenu_init();
84 #ifndef X_DISPLAY_MISSING
85 // if(!xwindow_window_managed(adesklets.display,adesklets.window))
86 if (!adesklets.managed)
87 #endif
88 xmenu_push_item(menu,"Move");
89 /* A lock file is needed if we want
90 the restart mechanism to work */
91 if (adesklets.lock) xmenu_push_item(menu,"Restart");
92 xmenu_push_item(menu,"Quit");
93 vector_push(adesklets.menus,menu);
94 result=1;
96 return result;
99 /*----------------------------------------------------------------------------*/
100 /* Recompute the background image based on present main window
101 width and height. Also create or resize foreground image as needed.
102 Returns 1 if both final and background images were dutifully produced,
103 0 otherwise.
105 int
106 adesklets_images_reset_background(int force_size, ...)
108 int i, j, old_width, old_height, foreground_active, background_active;
109 uint width, height;
110 int * pos;
111 vector * index;
112 va_list ap;
113 Imlib_Image image;
115 /* Get window dimension by all means necessary */
116 if (force_size) {
117 va_start(ap,force_size);
118 width=va_arg(ap,uint);
119 height=va_arg(ap,uint);
120 va_end(ap);
121 } else
122 #ifndef X_DISPLAY_MISSING
123 if (!xwindow_window_size(adesklets.display,adesklets.window,&width,&height))
124 #endif
125 width=height=1;
127 /* Save context states */
128 xwindow_context_save(IMLIB_BLEND|IMLIB_COLOR|IMLIB_IMAGE);
130 /* Record if Imlib's context image has to be changed at the end */
131 image=imlib_context_get_image();
132 foreground_active=(image && image==adesklets.images->content[0]);
133 background_active=(image && image==adesklets.images->content[1]);
135 /* Determine what images to resize */
136 if ((index=vector_init())) {
137 /* Always resize foreground */
138 if((pos=malloc(sizeof(int)))) {
139 *pos=0;
140 vector_push(index,pos);
142 /* Resize background when:
143 - We do not have X support
144 - We have X support, but there is no X connection or no window
145 - We have X support, there is a valid X connection and window,
146 but we do not grab the background
148 if(!X_DISPLAY_SUPPORT ||
149 !adesklets.background_grab ||
150 !adesklets.display || !adesklets.window) {
151 if((pos=malloc(sizeof(int)))) {
152 *pos=1;
153 vector_push(index,pos);
156 /* Resize user selected background when:
157 - It exists
159 if(adesklets.user_background_image!=-1) {
160 if ((pos=malloc(sizeof(int)))) {
161 *pos=adesklets.user_background_image;
162 vector_push(index,pos);
167 /* Create/update image(s) */
168 for(j=0;index && j<index->pos;++j) {
169 i=*((int*)index->content[j]);
170 if (!adesklets.images->content[i]) {
171 /* Create new final window image */
172 if ((adesklets.images->content[i]=imlib_create_image(width,height))) {
173 /* Select it */
174 imlib_context_set_image(adesklets.images->content[i]);
176 /* Make sure it has an alpha channel */
177 imlib_image_set_has_alpha(1);
179 /* Fill image with transparent black for foreground,
180 and opaque black for background, if applicable */
181 imlib_context_set_blend(0);
182 imlib_context_set_color(0, 0, 0, (i==0)?0:255);
183 imlib_image_fill_rectangle(0,0,width,height);
185 } else {
186 /* Update (by resizing image) */
187 imlib_context_set_image(adesklets.images->content[i]);
188 old_width=imlib_image_get_width();
189 old_height=imlib_image_get_height();
190 if((width!=old_width || height!=old_height) &&
191 (image=imlib_create_image(width,height))){
192 /* Need resizing */
193 imlib_context_set_image(image);
195 /* Make sure it has an alpha channel */
196 imlib_image_set_has_alpha(1);
198 /* Fill image with opaque black */
199 imlib_context_set_blend(0);
200 imlib_context_set_color(0,0,0,255);
201 imlib_image_fill_rectangle(0,0,width,height);
203 /* Finally, copy the original foreground image, with scaling */
204 imlib_blend_image_onto_image(adesklets.images->content[i],1,
205 0,0,old_width,old_height,
206 0,0,width,height);
208 /* Clean up : free original image */
209 imlib_context_set_image(adesklets.images->content[i]);
210 imlib_free_image();
211 adesklets.images->content[i]=image;
216 #ifndef X_DISPLAY_MISSING
217 if(adesklets.background_grab && adesklets.display && adesklets.window) {
218 /* If it exists, free background image */
219 adesklets.images->content[1]=
220 image_vector_free_item(adesklets.images->content[1]);
222 /* Create new background image */
223 adesklets.images->content[1]=
224 xwindow_grab_background(adesklets.display,adesklets.params->scr,
225 adesklets.window);
226 if (adesklets.user_event_mask&BackgroundGrabMask)
227 event("backgroundgrab\n");
229 #endif
230 /* Free index, if applicable */
231 vector_free(index);
233 /* Switch back to original context */
234 xwindow_context_restore();
236 /* Modify active image if it was originally set on foreground */
237 if(foreground_active) imlib_context_set_image(adesklets.images->content[0]);
238 if(background_active) imlib_context_set_image(adesklets.images->content[1]);
240 return adesklets.images->content[0] && adesklets.images->content[1];
243 /*----------------------------------------------------------------------------*/
244 /* Reinstate the image vector in pristine state,
245 including the regeneration of final and background image.
246 Take care of dangling context image, if applicable.
247 Returns 1 if successful, 0 in case of failure.
249 int
250 adesklets_images_reset(void)
252 int result=0;
253 if (adesklets.images)
254 adesklets.images=vector_free(adesklets.images);
255 if (!adesklets.images)
256 if((adesklets.images=vector_init())) {
257 adesklets.images->vector_free_item=image_vector_free_item;
258 adesklets.user_background_image=-1;
259 /* Recreate Final window and background images */
260 if((result=adesklets_images_reset_background(0))) {
261 adesklets.images->pos=2;
262 /* Reset current image if useful */
263 if (imlib_context_get_image()!=adesklets.images->content[0] &&
264 imlib_context_get_image()!=adesklets.images->content[1])
265 imlib_context_set_image(adesklets.images->content[0]);
268 return result;
271 /*----------------------------------------------------------------------------*/
272 /* Set/Reset main window. Also call adesklets_menu_reset and
273 adeslets_images_reset as needed. */
275 adesklets_window_reset(int managed)
277 int result=0;
278 #ifndef X_DISPLAY_MISSING
279 int mapped;
280 uint width, height;
281 XWindowAttributes attr;
282 XTextProperty text_prop_name;
283 Atom atom;
284 const char * name = PACKAGE;
285 const long valuemask = CWBackPixmap;
287 /* Determine if the old window was mapped, then destroy it as needed */
288 if(adesklets.display) {
289 if(adesklets.window) {
290 mapped=(XGetWindowAttributes(adesklets.display,
291 adesklets.window,&attr))?
292 (attr.map_state!=IsUnmapped):0;
293 XDestroyWindow(adesklets.display,adesklets.window);
294 } else
295 mapped=0;
297 /* Determine new window dimensions */
298 width=(adesklets.window)?attr.width:1;
299 height=(adesklets.window)?attr.height:1;
301 xwindow_error_reset();
302 /* Create main desklet window */
303 adesklets.root=(managed)?
304 RootWindow(adesklets.display,adesklets.params->scr):
305 xwindow_get_root_window(adesklets.display,
306 adesklets.params->scr);
307 debug("Root window is : 0x%x\n", adesklets.root);
309 adesklets.window=
310 XCreateWindow(adesklets.display,
311 adesklets.root,
312 adesklets.params->x, adesklets.params->y,
313 width, height, 0,
314 DefaultDepth(adesklets.display,
315 adesklets.params->scr),
316 InputOutput,
317 adesklets.visual,
318 (managed)?valuemask:(valuemask|CWOverrideRedirect),
319 &XDefaultWindowAttributes);
321 if (xwindow_error_check()) {
322 /* Set this window size */
323 xwindow_resize_window(adesklets.display,adesklets.window,
324 adesklets.params,width,height,1);
325 /* Set this window event mask */
326 XSelectInput(adesklets.display,adesklets.window,adesklets.event_mask);
328 /* Set this window as imlib2's default drawable */
329 imlib_context_set_drawable(adesklets.window);
331 /* Set window stacking order, and various properties if applicable */
332 if(managed) {
333 XRaiseWindow(adesklets.display,adesklets.window);
334 /* Window name */
335 if (XmbTextListToTextProperty(adesklets.display,
336 (char**)&name,1,
337 XCompoundTextStyle,
338 &text_prop_name)==Success)
339 XSetWMName(adesklets.display, adesklets.window, &text_prop_name);
341 /* Window delete protocol registration */
342 if ((atom=XInternAtom(adesklets.display,
343 "WM_DELETE_WINDOW",False))!=None)
344 XSetWMProtocols(adesklets.display,
345 adesklets.window, &atom, 1);
347 else
348 XLowerWindow(adesklets.display,adesklets.window);
350 /* Map the window if needed */
351 if (mapped) XMapWindow(adesklets.display,adesklets.window);
353 /* Eventually add capture of PropertyNotify on root window:
354 used for dynamic background reinitialisation */
355 XSelectInput(adesklets.display,
356 DefaultRootWindow(adesklets.display),
357 ((adesklets.background_grab)?PropertyChangeMask:0));
359 /* Store new value */
360 adesklets.managed = managed;
362 result=1;
363 } else
364 adesklets.window=(Window)0;
365 } else
366 adesklets.window=(Window)0;
367 #endif
368 return result;
371 /*----------------------------------------------------------------------------*/
372 /* Reste to nothing the vector of fonts, color_ranges and color_modifiers.
373 Returns 1 if successful, 0 otherwise.
375 #define ADESKLETS_RESET_FUNCTION(name)\
376 int \
377 adesklets_ ## name ## s_reset(void)\
379 int result=0;\
380 if(adesklets.name ## s)\
381 adesklets.name ## s=vector_free(adesklets.name ## s);\
382 if(!adesklets.name ## s) {\
383 if((adesklets.name ## s=vector_init())) {\
384 adesklets.name## s->vector_free_item=\
385 name ## _vector_free_item;\
386 imlib_context_set_ ## name(NULL);\
387 result=1;\
390 return result;\
393 ADESKLETS_RESET_FUNCTION(font)
394 ADESKLETS_RESET_FUNCTION(color_range)
395 ADESKLETS_RESET_FUNCTION(color_modifier)
396 ADESKLETS_RESET_FUNCTION(filter)
397 #undef ADESKLETS_RESET_FUNCTION
399 /*----------------------------------------------------------------------------*/
400 /* Reset to nothing a generic vector of something; you need
401 to provide a reference to the vector and another to a
402 vector_free_item_func function
405 adesklets_generic_reset(vector ** vec, vector_free_item_func func)
407 int result=0;
408 if(*vec)
409 *vec=vector_free(*vec);
410 if(!(*vec)) {
411 if((*vec=vector_init())) {
412 (*vec)->vector_free_item=func;
413 result=1;
416 return result;
419 /*----------------------------------------------------------------------------*/
420 /* Generate placeholder function using preceeding generic function
422 #define ADESKLETS_RESET_FUNCTION(name) \
423 int \
424 adesklets_ ## name ## s_reset(void) \
426 return adesklets_generic_reset(&adesklets.name ## s,\
427 name ## _vector_free_item);\
430 ADESKLETS_RESET_FUNCTION(polygon)
431 ADESKLETS_RESET_FUNCTION(variable)
432 #undef ADESKLETS_RESET_FUNCTION
434 /*----------------------------------------------------------------------------*/
435 /* Wrapper for xmenu_fire() that intercepts non-maskable events
436 from default menu ("Move", "Restart" and "Quit" events)
439 adesklets_menu_fire(int index, char ** return_str)
441 #ifndef X_DISPLAY_MISSING
442 int result=0;
443 if(index>=0 && index<adesklets.menus->pos) {
444 *return_str=xmenu_fire(adesklets.display,adesklets.params->scr,
445 adesklets.window,
446 adesklets.images->content[
447 (adesklets.user_background_image==-1)?
448 1:adesklets.user_background_image],
449 adesklets.images->content[0],
450 adesklets.transparency,
451 MENU(index));
452 /* Intercept default actions move and quit on the way back */
453 if(index==0 && *return_str) {
454 /* For move: verify the main window is not managed,
455 to avoid false move due to user-added "Move" */
456 if (
457 #ifndef X_DISPLAY_MISSING
458 !adesklets.managed &&
459 #endif
460 strcmp(*return_str,"Move")==0) {
461 if(xwindow_move_window(adesklets.display,
462 adesklets.root, adesklets.window,
463 adesklets.params)) {
464 XMapWindow(adesklets.display,adesklets.window);
465 if(!adesklets.params->no_update)
466 cfgfile_update(adesklets.params);
468 *return_str=NULL;
469 } else {
470 /* For restart: verify there is a lock file open,
471 to avoid false restart due to user-added "Restart"
472 item in default menu */
473 if(adesklets.lock && strcmp(*return_str,"Restart")==0) {
474 debug("Restart!\n");
475 adesklets.restart_flag=1;
476 *return_str=NULL;
477 } else {
478 if(strcmp(*return_str,"Quit")==0) {
479 adesklets.user_quit_flag=adesklets.quit_flag=1;
480 debug("Quit!\n");
481 *return_str=NULL;
486 result=1;
488 return result;
489 #else
490 return 0;
491 #endif
494 /*----------------------------------------------------------------------------*/
495 /* Return 1 if current image is potentially shown on screen, 0 otherwise.
496 Mainly used to determine needs for screen updates */
498 image_is_shown()
500 Imlib_Image image;
501 image = imlib_context_get_image();
503 return (image==adesklets.images->content[0]) ||
504 (adesklets.transparency &&
505 ((adesklets.user_background_image!=-1 &&
506 image==adesklets.images->content[adesklets.user_background_image]) ||
507 (image==adesklets.images->content[1])));
510 /*----------------------------------------------------------------------------*/
511 void usage(const char * name)
513 int em = (int)(getenv("ADESKLETS_EMBEDDED")!=NULL);
514 if (!em)
515 printf("Usage: %s [OPTIONS] [script_id]\n\
516 adesklets interpreter and desklets launcher\n\n", name);
517 printf("Options:\n\
518 -h, --help Display this help message\n");
519 if (!em)
520 printf("\
521 -v, --version Get package version\n\
522 -f, --file In interpreter mode, use file as\n\
523 input stream instead of stdin\n");
524 printf("\n");
525 #ifdef FRONTEND_SHELL_DRIVER
526 printf("Warning: for some reason, the shell frontend driver was not used.\n");
527 #else
528 printf("Warning: the shell frontend driver support was not compiled in.\n");
529 #endif
532 /*----------------------------------------------------------------------------*/
534 adesklets_init(int argc, char ** argv)
536 int pos=1, result=0;
537 char * adesklets_id, * polling;
538 char str[CFGFILE_NAME_SIZE];
539 FILE * file;
540 struct flock lock;
541 struct sigaction new_action, old_action;
543 const char * OPTIONS[] = {"-h", "--help", "-f", "--file", "-v", "--version" };
545 /* Seek --help string: otherwise, it is either a script name of junk */
546 if(argc>=2) {
547 if(strncmp(argv[1],OPTIONS[0],strlen(OPTIONS[0]))==0 ||
548 strncmp(argv[1],OPTIONS[1],strlen(OPTIONS[1]))==0) {
549 usage(argv[0]);
550 return 0;
551 } else {
552 if (strncmp(argv[1],OPTIONS[4],strlen(OPTIONS[4]))==0 ||
553 strncmp(argv[1],OPTIONS[5],strlen(OPTIONS[5]))==0) {
554 printf("%s %s\n",PACKAGE,VERSION);
555 return 0;
556 } else {
557 if (strncmp(argv[1],OPTIONS[2],strlen(OPTIONS[2]))==0 ||
558 strncmp(argv[1],OPTIONS[3],strlen(OPTIONS[3]))==0) {
559 if(argc>=3) {
560 if (!((file=fopen(argv[2],"r"))&&
561 dup2(fileno(file),fileno(stdin))>=0)) {
562 welcome(stderr);
563 fprintf(stderr,"Could not open file '%s' for reading\n",
564 argv[2]);
565 return 0;
567 } else {
568 usage(argv[0]);
569 return 0;
571 pos+=2;
577 /* Get original parent process id */
578 adesklets.ppid=getppid();
580 /* Get desklet ID from environment */
581 adesklets_id = getenv("ADESKLETS_ID");
583 /* Get polling period from environment */
584 if ((polling = getenv("ADESKLETS_POLLING"))) {
585 adesklets.polling = atoi(polling);
586 adesklets.polling = (adesklets.polling <= 0)?
587 X_POLLING_PERIOD:(1000000/adesklets.polling);
590 /* Set stdout and stderr to be unbuffered: this is needed
591 for proper pipe operation. stderr is always
592 unbuffered */
593 if (setvbuf(stdout,NULL,_IONBF,0)!=0) {
594 fprintf(stderr,"Could not remove stdout buffer\n");
595 return 0;
597 if (setvbuf(stderr,NULL,_IONBF,0)!=0) {
598 fprintf(stderr,"Could not remove stderr buffer\n");
599 return 0;
602 /* Determine if interactive use */
603 command.interactive=isatty(fileno(stdin));
605 /* Retrieve all parameters from config file */
606 adesklets.params = cfgfile_getinfo((!command.interactive)?argv[pos]:NULL,
607 ((adesklets_id!=NULL)?
608 atoi(adesklets_id):-1));
610 /* Make sure ADESKLETS_ID is set in current environment */
611 if(!adesklets_id)
612 if (sprintf(str,"%u",adesklets.params->id)>0)
613 setenv("ADESKLETS_ID",str,1);
615 /* If interactive use, print welcome message */
616 if(command.interactive) {
617 welcome(stdout);
618 printf("Press TAB for hints.\n");
619 /* But if not, build and acquire lock file name */
620 } else if (adesklets_valid_desklet(argv[pos],0)) {
621 strncpy(str,argv[1],CFGFILE_NAME_SIZE-1);
622 str[CFGFILE_NAME_SIZE-1]=0;
623 if (snprintf(adesklets.lock_filename,CFGFILE_NAME_SIZE-1,
624 "%s/%s_uid%u_%s_%u.lock",
625 LOCKFILES_DIR,
626 PACKAGE,
627 getuid(),
628 (char*)basename(str),
629 adesklets.params->id)<CFGFILE_NAME_SIZE)
630 adesklets.lock_filename[CFGFILE_NAME_SIZE-1]=0;
631 /* Now, lock the file: this will wait forever */
632 if ((adesklets.lock=fdopen(open(adesklets.lock_filename,
633 O_CREAT|O_TRUNC|O_WRONLY,
634 S_IRUSR|S_IWUSR),
635 "w"))) {
636 lock.l_type=F_WRLCK;
637 lock.l_whence=SEEK_SET;
638 lock.l_start=0;
639 lock.l_len=0;
640 debug("Lock file: acquiring %s\n",adesklets.lock_filename);
641 TRY_RESET;
642 TRY(fcntl(fileno(adesklets.lock),F_SETLKW,&lock));
643 if (TRY_SUCCESS) {
644 /* Write PPID and PID to lock file */
645 fprintf(adesklets.lock,"%d %d\n",adesklets.ppid,getpid());
646 fflush(adesklets.lock);
647 } else {
648 debug("Lock file: could not get lock\n");
649 fclose(adesklets.lock);
650 adesklets.lock=NULL;
655 /* Force config file entry removal (or, at least, no registration)
656 at next update if invalid */
657 adesklets.params->no_update=!
658 adesklets_valid_desklet(adesklets.params->applet,1);
660 #ifndef X_DISPLAY_MISSING
661 /* Perform X Windows initialisation */
662 if ((adesklets.display=XOpenDisplay(NULL))) {
663 /* Correct screen determination */
664 adesklets.params->scr=(adesklets.params->scr>=0 &&
665 adesklets.params->scr<
666 ScreenCount(adesklets.display))?
667 adesklets.params->scr:
668 DefaultScreen(adesklets.display);
670 /* X related imlib2 settings */
671 adesklets.visual=imlib_get_best_visual(adesklets.display,
672 adesklets.params->scr,
673 &adesklets.depth);
674 imlib_context_set_display(adesklets.display);
675 imlib_context_set_visual(adesklets.visual);
676 imlib_context_set_colormap(DefaultColormap(adesklets.display,
677 adesklets.params->scr));
679 /* Create main desklet window: managed if interactive,
680 unmanaged if not */
681 adesklets_window_reset(command.interactive);
682 /* Install custom error handler */
683 XSetErrorHandler(xwindow_non_fatal_error_handler);
685 #ifdef DEBUG
686 else
687 debug("Could not connect to X server '%s'\n",XDisplayName(NULL));
688 #endif
689 #endif
691 /* Locate true type fonts system-wide */
692 xwindow_locate_truetype_fonts();
694 /* Various Others imlib2 settings */
695 imlib_set_cache_size(2048*1024);
696 imlib_set_font_cache_size(512*1024);
697 imlib_set_color_usage(128);
698 imlib_context_set_dither(1);
699 imlib_context_set_blend(1);
700 imlib_context_set_color(255,255,255,255);
702 /* Set events in proper echo mode: no echo if interactive, echo otherwise. */
703 events_echo=!command.interactive;
705 /* Initial settings */
706 if (adesklets_menus_reset()) {
707 if (adesklets_images_reset()) {
708 if (adesklets_fonts_reset()) {
709 if (adesklets_color_ranges_reset()) {
710 if (adesklets_color_modifiers_reset()) {
711 if (adesklets_filters_reset()) {
712 if (adesklets_polygons_reset()) {
713 if (adesklets_variables_reset()) {
714 /* Setup command interpreter */
715 if(command_interpreter_reset()) {
716 #ifdef FORCE_EXTENDED_CHARACTERS_INPUT
717 rl_variable_bind("input-meta", "on");
718 rl_variable_bind("convert-meta", "off");
719 rl_variable_bind("output-meta", "on");
720 #endif
721 /* Finally, set up event handler. This code snipset
722 was copied verbatim from the GNU C Library
723 Reference Manual (sigaction Function
724 Example section) */
725 new_action.sa_handler = termination_handler;
726 sigemptyset (&new_action.sa_mask);
727 new_action.sa_flags = 0;
728 sigaction (SIGINT, NULL, &old_action);
729 if (old_action.sa_handler != SIG_IGN)
730 sigaction (SIGINT, &new_action, NULL);
731 sigaction (SIGHUP, NULL, &old_action);
732 if (old_action.sa_handler != SIG_IGN)
733 sigaction (SIGHUP, &new_action, NULL);
734 sigaction (SIGTERM, NULL, &old_action);
735 if (old_action.sa_handler != SIG_IGN)
736 sigaction (SIGTERM, &new_action, NULL);
737 /* If applicable, make an initial setup of
738 config file, just in case */
739 if (X_DISPLAY_SUPPORT &&
740 adesklets.display && adesklets.window)
741 cfgfile_update(adesklets.params);
742 result=1;
743 event("ready!\n");
744 } else
745 fprintf(stderr, "Cannot initialize command interpreter\n");
746 } else
747 fprintf(stderr, "Cannot initialize variables\n");
748 } else
749 fprintf(stderr, "Cannot initialize imlib polygons\n");
750 } else
751 fprintf(stderr, "Cannot initialize imlib filters\n");
752 } else
753 fprintf(stderr, "Cannot initialize imlib color modifiers\n");
754 } else
755 fprintf(stderr, "Cannot initialize imlib color ranges\n");
756 } else
757 fprintf(stderr, "Cannot initialize imlib fonts\n");
758 } else
759 fprintf(stderr, "Cannot initialize imlib images\n");
760 } else
761 fprintf(stderr, "Cannot initialize menus\n");
763 return result;
766 /*----------------------------------------------------------------------------*/
767 void
768 adesklets_events_loop(void)
770 char *menu_str;
771 var_item * variable;
772 char ** list;
773 int x,y,i,j,k;
774 uint width, height;
775 #ifndef X_DISPLAY_MISSING
776 long mask;
777 #endif
778 double angle;
779 struct timespec sleep_time;
780 command_enum command_type;
781 vector * params;
782 #ifndef X_DISPLAY_MISSING
783 XEvent ev;
784 #endif
785 #ifdef HAVE_READLINE_HISTORY_H
786 HIST_ENTRY ** history;
787 FILE * file;
788 #endif
789 #ifdef HAVE_ICONV_H
790 iconv_t cd;
791 #endif
792 Imlib_Updates updates;
793 Imlib_Image image;
794 Imlib_Color color;
795 Imlib_Font font;
796 Imlib_Color_Range color_range;
797 Imlib_Color_Modifier color_modifier;
798 Imlib_Filter filter;
799 ImlibPolygon polygon;
800 Imlib_Load_Error error;
801 DATA32 * data;
802 DATA8 * tables[4];
804 debug("---------------------------------------------------------------\n");
805 do {
806 updates = imlib_updates_init();
807 if (command.ready) {
808 if (command.line) {
809 command.message_out=0;
810 variable_expansion(adesklets.variables,&command.line);
811 params=command_splitter(command.line,&command_type);
813 if (!command.recording ||
814 command_type==CMD_PLAY ||
815 command_type==CMD_START_RECORDING ||
816 command_type==CMD_STOP_RECORDING) {
817 switch(command_type) {
818 case CMD_TIME_GATE:
819 /* NOTE : for semi-automated generation of an adesklets'
820 API for scripting languages, you should include
821 a prototype declaration similar to this one
822 in a comment (multi-lines comments allowed)
823 directly below case declaration. Look at protoize.sh
824 for further details. Commands that are also
825 Imlib2 primitives do not need to have prototypes
826 most of the time.
828 prototype(double gate) */
829 if (command.replay_pos) {
830 if (params->pos>=2) {
831 angle=atof(params->content[1]);
832 #ifndef X_DISPLAY_MISSING
833 if (command.replay_abort_on_events) {
834 sleep_time.tv_sec=0; sleep_time.tv_nsec=adesklets.polling/10;
835 while (angle>command_gate_chronometer())
836 if (adesklets.display && adesklets.window &&
837 (XCheckWindowEvent(adesklets.display,
838 DefaultRootWindow(adesklets.display),
839 PropertyChangeMask, &ev) ||
840 XCheckWindowEvent(adesklets.display,adesklets.window,
841 adesklets.event_mask,&ev) ||
842 XCheckTypedWindowEvent(adesklets.display,adesklets.window,
843 ClientMessage,&ev))) {
844 XPutBackEvent(adesklets.display,&ev);
845 break;
846 } else
847 nanosleep(&sleep_time,NULL);
848 } else {
849 #endif
850 if ((angle-=command_gate_chronometer())>0) {
851 sleep_time.tv_sec=(time_t)angle;
852 sleep_time.tv_nsec=(long)((angle-floor(angle))*1E9);
854 debug("Sleep time: %f, or %d %d\n",
855 angle,sleep_time.tv_sec,sleep_time.tv_nsec);
857 nanosleep(&sleep_time,NULL);
859 #ifndef X_DISPLAY_MISSING
861 #endif
862 } else
863 command_error("time gate not given\n");
864 } else
865 command_error("ignoring timer gate, interpreter not replaying\n");
866 break;
867 case CMD_HELP:
868 /* prototype([const char * command]) */
869 if(params->pos>=2) {
870 for(i=0;
871 COMMANDS[i].name &&
872 strcmp(params->content[1],COMMANDS[i].name);
873 ++i);
874 if (COMMANDS[i].name)
875 command_ok("%s - %s\n",COMMANDS[i].name, COMMANDS[i].doc);
876 else
877 command_error("no help on '%s'\n", (char*)params->content[1]);
878 } else {
879 for(i=0;COMMANDS[i].name;++i)
880 command_printf("%-25s -\t%s\n",COMMANDS[i].name, COMMANDS[i].doc);
882 break;
883 case CMD_PING:
884 /* prototype(void) */
885 command_ok("pong!\n");
886 break;
887 case CMD_PAUSE:
888 /* prototype([int delay]) */
889 i=(params->pos>=2)?
890 (((i=atoi(params->content[1]))>0)?i:5):5;
891 debug("Pausing for %d seconds.\n",i);
892 sleep(i);
893 break;
894 case CMD_VERSION:
895 /* prototype(void) */
896 command_ok("%s %s\n",PACKAGE,VERSION);
897 break;
898 case CMD_GET_ID:
899 /* prototype(void) */
900 command_ok("adesklets id %u\n", adesklets.params->id);
901 break;
902 case CMD_HISTORY:
903 /* prototype([const char * filename]) */
904 #ifdef HAVE_READLINE_HISTORY_H
905 if ((history=history_list())) {
906 for(i=0;history[i];++i);
907 command_printf("%d commands in history\n",i);
908 if((file=(params->pos>=2)?
909 fopen(command_subsplitter(command.line,1),"w"):stdout)) {
910 for(i=0;history[i];++i)
911 if (params->pos>=2 || !command.interactive)
912 fprintf(file,"%s\n",history[i]->line);
913 else
914 fprintf(file,"%d\t%s\n",i,history[i]->line);
915 if(file!=stdout) fclose(file);
916 } else
917 command_error("could not open output file for writing\n");
918 } else
919 command_error("could not retrieve history list\n");
920 #else
921 command_error("history support not compiled in\n");
922 #endif
923 break;
924 case CMD_SET:
925 /* prototype([const * char name, const * char value]) */
926 if ((i=params->pos)>1) {
927 /* Verify variable name does not include a dollar character */
928 for(j=0;
929 ((char*)params->content[1])[j] &&
930 ((char*)params->content[1])[j]!='$';
931 ++j);
932 if (j==strlen((char*)params->content[1])) {
933 /* First, search for existing variable */
934 variable=(var_item*)
935 vector_find(adesklets.variables,(uint*)&j,
936 variable_search_func,(void*)params->content[1]);
938 /* Then, if it exists, just delete it */
939 if (variable)
940 vector_delete(adesklets.variables,(uint)j);
941 else
942 if (i==2)
943 command_error("variable '%s' does not exist\n",
944 params->content[1]);
946 if (i>2) {
947 /* Then, set it back if there is a new content */
948 vector_push(adesklets.variables,
949 (void*)variable_create(
950 (char*)params->content[1],
951 (char*)command_subsplitter(command.line,2)));
953 } else
954 command_error("variable name contains '$'\n");
955 } else {
956 /* Print out all variables */
957 command_printf("%d variable(s)\n", adesklets.variables->pos);
958 for (i=0;i<adesklets.variables->pos;++i)
959 command_printf("%s=%s\n",
960 ((var_item*)adesklets.variables->content[i])->name,
961 ((var_item*)adesklets.variables->content[i])->value);
963 break;
964 case CMD_UNSET_ALL:
965 /* prototype(void) */
966 adesklets_variables_reset();
967 break;
968 case CMD_ECHO:
969 /* prototype(const char * string) */
970 break;
971 case CMD_START_RECORDING:
972 /* prototype(void) */
973 #ifdef HAVE_READLINE_HISTORY_H
974 /* This is a special case: you have to make sure to abort
975 current macro recording if called recursively from direct mode.
977 But this is not enough: you also need to ckeck we are not inside
978 a replay loop (indirect mode) because it would still be possible
979 to insert hidden calls to 'start_recording' inside a macro using
980 textual expansion (text variables) */
981 if (!command.recording && !command.replay_pos)
982 command.recording=history_size()+1;
983 else {
984 /* In non interactive mode, purge newly created history
985 entries */
986 if (command.recording && !command.interactive)
987 for(i=history_size()-1;i>=command.recording-1;--i)
988 free_history_entry(remove_history(i));
989 command.recording=command.replay_pos=0;
990 command_error("cannot call this while already recording or \
991 replaying, aborded\n");
993 #else
994 command_error("compiled without GNU history support\n");
995 #endif
996 break;
997 case CMD_STOP_RECORDING:
998 /* prototype(void) */
999 #ifdef HAVE_READLINE_HISTORY_H
1000 if (!command.replay_pos) {
1001 if (command.recording) {
1002 --command.recording;
1003 j=history_size()-1;
1004 if(!command.interactive)
1005 /* In case of non interactive use, remove
1006 the reference to the 'stop_record' command */
1007 free_history_entry(remove_history(j));
1008 if (command.recording!=j)
1009 command_ok("recorded_commands %d %d\n",
1010 command.recording,
1011 j-1);
1012 else
1013 command_error("no command recorded\n");
1014 } else
1015 command_error("no recording taking place right now\n");
1016 } else
1017 command_error("cannot call stop while replaying, replay aborded\n");
1018 command.recording=0;
1019 #else
1020 command_error("compiled without GNU history support\n");
1021 #endif
1022 break;
1023 case CMD_PLAY_GET_ABORT_ON_EVENTS:
1024 /* prototype(void) */
1025 command_ok("abort_on_event %d\n",command.replay_abort_on_events);
1026 break;
1027 case CMD_PLAY_SET_ABORT_ON_EVENTS:
1028 /* prototype(bool abort) */
1029 if (!command.replay_pos) {
1030 if (params->pos>=2)
1031 command.replay_abort_on_events=atoi((char*)params->content[1]);
1032 else
1033 command_error("abort on event value not given\n");
1034 } else
1035 command_error("cannot be called inside a replay\n");
1036 break;
1037 case CMD_PLAY:
1038 /* prototype(int beginning, int end) */
1039 #ifdef HAVE_READLINE_HISTORY_H
1040 if (!command.recording && !command.replay_pos) {
1041 if (params->pos>=3) {
1042 if (((i=atoi(params->content[1]))<(j=history_size())) &&
1043 ((k=atoi(params->content[2]))<j)) {
1044 if (i>=0 && k>=0 && (i<=k)) {
1045 gettimeofday(&command.replay_time,NULL);
1046 command.replay_pos=i+1;
1047 command.replay_stop=k;
1048 events_delay=1;
1049 } else
1050 command_error("invalid limits\n");
1051 } else
1052 command_error("limits out of range\n");
1053 } else
1054 command_error("missing start and stop limits\n");
1055 } else {
1056 command.recording=command.replay_pos=0;
1057 command_error("cannot call this now, aborded\n");
1059 #else
1060 command_error("compiled without GNU history support\n");
1061 #endif
1062 break;
1063 case CMD_CONTEXT_GET_DITHER:
1064 command_ok("context dither %hhu\n",imlib_context_get_dither());
1065 break;
1066 case CMD_CONTEXT_GET_ANTI_ALIAS:
1067 command_ok("context antialias %hhu\n",imlib_context_get_anti_alias());
1068 break;
1069 case CMD_CONTEXT_GET_BLEND:
1070 command_ok("context blend %hhu\n",imlib_context_get_blend());
1071 break;
1072 case CMD_CONTEXT_GET_OPERATION:
1073 i=imlib_context_get_operation();
1074 command_ok("context operation %d (%s)\n",
1075 i, OPERATIONS[i]);
1076 break;
1077 case CMD_CONTEXT_GET_CLIPRECT:
1078 /* prototype(void) */
1079 imlib_context_get_cliprect(&x,&y,&i,&j);
1080 command_ok("context cliprect %d %d %d %d\n",x,y,i,j);
1081 break;
1082 case CMD_CONTEXT_GET_IMAGE:
1083 image=imlib_context_get_image();
1084 for(i=0;i<adesklets.images->pos;++i)
1085 if(adesklets.images->content[i]==image)
1086 command_ok("context image %d\n",i);
1087 break;
1088 case CMD_CONTEXT_GET_FONT:
1089 if ((font=imlib_context_get_font())) {
1090 for(i=0;i<adesklets.fonts->pos;++i)
1091 if(adesklets.fonts->content[i]==font)
1092 command_ok("context font %d\n",i);
1093 } else
1094 command_ok("context font -1 (unset)\n");
1095 break;
1096 case CMD_CONTEXT_GET_COLOR_RANGE:
1097 if ((color_range=imlib_context_get_color_range())) {
1098 for(i=0;i<adesklets.color_ranges->pos;++i)
1099 if(adesklets.color_ranges->content[i]==color_range)
1100 command_ok("context colorrange %d\n",i);
1101 } else
1102 command_ok("context colorrange -1 (unset)\n");
1103 break;
1104 case CMD_CONTEXT_GET_COLOR_MODIFIER:
1105 if ((color_modifier=imlib_context_get_color_modifier())) {
1106 for(i=0;i<adesklets.color_modifiers->pos;++i)
1107 if(adesklets.color_modifiers->content[i]==color_modifier)
1108 command_ok("context colormodifier %d\n",i);
1109 } else
1110 command_ok("context colormodifier -1 (unset)\n");
1111 break;
1112 case CMD_CONTEXT_GET_FILTER:
1113 if ((filter=imlib_context_get_filter())) {
1114 for(i=0;i<adesklets.filters->pos;++i)
1115 if(adesklets.filters->content[i]==filter)
1116 command_ok("context filter %d\n",i);
1117 } else
1118 command_ok("context filter -1 (unset)\n");
1119 break;
1120 case CMD_CONTEXT_GET_COLOR:
1121 /* prototype(void) */
1122 imlib_context_get_color(&x,&y,&i,&j);
1123 command_ok("context color %hhu %hhu %hhu %hhu\n",
1124 x&255,y&255,i&255,j&255);
1125 break;
1126 case CMD_CONTEXT_GET_ANGLE:
1127 angle=imlib_context_get_angle();
1128 command_ok("context angle %4.2f\n",angle);
1129 break;
1130 case CMD_CONTEXT_GET_DIRECTION:
1131 i=imlib_context_get_direction();
1132 command_ok("context direction %d (%s)\n",
1133 i, DIRECTIONS[i]);
1134 break;
1135 case CMD_CONTEXT_SET_DITHER:
1136 /* prototype(bool dither) */
1137 if (params->pos>=2)
1138 imlib_context_set_dither((char)atoi(params->content[1]));
1139 else
1140 command_error("dither value not given\n");
1141 break;
1142 case CMD_CONTEXT_SET_ANTI_ALIAS:
1143 /* prototype(bool anti_alias) */
1144 if (params->pos>=2)
1145 imlib_context_set_anti_alias((char)atoi(params->content[1]));
1146 else
1147 command_error("anti alias value not given\n");
1148 break;
1149 case CMD_CONTEXT_SET_BLEND:
1150 /* prototype(bool blend) */
1151 if (params->pos>=2)
1152 imlib_context_set_blend((char)atoi(params->content[1]));
1153 else
1154 command_error("blend value not given\n");
1155 break;
1156 case CMD_CONTEXT_SET_OPERATION:
1157 /* prototype(enum OPERATIONS operation) */
1158 if(params->pos>=2) {
1159 for(i=0;OPERATIONS[i];++i)
1160 if(strncmp(OPERATIONS[i],params->content[1],
1161 strlen(params->content[1]))==0)
1162 break;
1163 imlib_context_set_operation((OPERATIONS[i])?
1164 i:((j=atoi(params->content[1])))<4?j:0);
1165 } else
1166 command_error("operation not given\n");
1167 break;
1168 case CMD_CONTEXT_SET_CLIPRECT:
1169 if (params->pos>=5) {
1170 if ((x=atoi((char*)params->content[1]))>=0 &&
1171 (y=atoi((char*)params->content[2]))>=0 &&
1172 (i=atoi((char*)params->content[3]))>=0 &&
1173 (j=atoi((char*)params->content[4]))>=0) {
1174 imlib_context_set_cliprect(x,y,i,j);
1175 } else
1176 command_error("clipping rectangle coordinates out of range\n");
1177 } else
1178 command_error("clipping rectangle description not given\n");
1179 break;
1180 case CMD_CONTEXT_SET_IMAGE:
1181 if (params->pos>=2) {
1182 if ((i=atoi((char*)params->content[1]))>=0 &&
1183 i<adesklets.images->pos) {
1184 imlib_context_set_image(adesklets.images->content[i]);
1185 } else
1186 command_error("image ID %d out of range\n",i);
1187 } else
1188 command_error("image ID not given\n");
1189 break;
1190 case CMD_CONTEXT_SET_FONT:
1191 /* prototype([int font]) */
1192 j=0;
1193 if (params->pos>=2) {
1194 if ((i=atoi((char*)params->content[1]))>=0 &&
1195 i<adesklets.fonts->pos) {
1196 imlib_context_set_font(adesklets.fonts->content[i]);
1197 } else {
1198 if(i==-1) {
1199 j=1;
1200 imlib_context_set_font(NULL);
1201 } else
1202 command_error("font ID %d out of range\n",i);
1204 } else {
1205 j=1;
1206 imlib_context_set_font(NULL);
1208 if(j) command_ok("context font unset\n");
1209 break;
1210 case CMD_CONTEXT_SET_COLOR_RANGE:
1211 /* prototype([int color_range]) */
1212 j=0;
1213 if (params->pos>=2) {
1214 if ((i=atoi((char*)params->content[1]))>=0 &&
1215 i<adesklets.color_ranges->pos) {
1216 imlib_context_set_color_range(adesklets.color_ranges->content[i]);
1217 } else {
1218 if(i==-1) {
1219 j=1;
1220 imlib_context_set_color_range(NULL);
1221 } else
1222 command_error("color range ID %d out of range\n",i);
1224 } else {
1225 j=1;
1226 imlib_context_set_color_range(NULL);
1228 if(j) command_ok("context color range unset\n");
1229 break;
1230 case CMD_CONTEXT_SET_COLOR_MODIFIER:
1231 /* prototype([int color_modifier]) */
1232 j=0;
1233 if (params->pos>=2) {
1234 if ((i=atoi((char*)params->content[1]))>=0 &&
1235 i<adesklets.color_modifiers->pos) {
1236 imlib_context_set_color_modifier(
1237 adesklets.color_modifiers->content[i]);
1238 } else {
1239 if(i==-1) {
1240 j=1;
1241 imlib_context_set_color_modifier(NULL);
1242 } else
1243 command_error("color modifier ID %d out of range\n",i);
1245 } else {
1246 j=1;
1247 imlib_context_set_color_modifier(NULL);
1249 if(j) command_ok("context color modifier unset\n");
1250 break;
1251 case CMD_CONTEXT_SET_FILTER:
1252 /* prototype([int filter]) */
1253 j=0;
1254 if (params->pos>=2) {
1255 if ((i=atoi((char*)params->content[1]))>=0 &&
1256 i<adesklets.filters->pos) {
1257 imlib_context_set_filter(adesklets.filters->content[i]);
1258 } else {
1259 if(i==-1) {
1260 j=1;
1261 imlib_context_set_filter(NULL);
1262 } else
1263 command_error("filter ID %d out of range\n",i);
1265 } else {
1266 j=1;
1267 imlib_context_set_filter(NULL);
1269 if(j) command_ok("context filter unset\n");
1270 break;
1271 case CMD_CONTEXT_SET_COLOR:
1272 if (params->pos>=5)
1273 imlib_context_set_color(atoi(params->content[1]),
1274 atoi(params->content[2]),
1275 atoi(params->content[3]),
1276 atoi(params->content[4]));
1277 else
1278 command_error("color RGBA description not given\n");
1279 break;
1280 case CMD_CONTEXT_SET_ANGLE:
1281 if (params->pos>=2) {
1282 imlib_context_set_angle(atof(params->content[1]));
1283 } else
1284 command_error("angle not given\n");
1285 break;
1286 case CMD_CONTEXT_SET_DIRECTION:
1287 /* prototype(enum DIRECTIONS direction) */
1288 if(params->pos>=2) {
1289 for(i=0;DIRECTIONS[i];++i)
1290 if(strncmp(DIRECTIONS[i],params->content[1],
1291 strlen(params->content[1]))==0)
1292 break;
1293 imlib_context_set_direction((DIRECTIONS[i])?
1294 i:((j=atoi(params->content[1])))<5?j:0);
1295 } else
1296 command_error("direction not given\n");
1297 break;
1298 case CMD_ADD_COLOR_TO_COLOR_RANGE:
1299 if(imlib_context_get_color_range()) {
1300 i=(params->pos>=2)?atoi(params->content[1]):0;
1301 imlib_add_color_to_color_range(i);
1302 } else
1303 command_error("no color range selected\n");
1304 break;
1305 case CMD_BLEND_IMAGE_ONTO_IMAGE:
1306 if (params->pos>=11) {
1307 if((i=atoi((char*)params->content[1]))>=0 &&
1308 i<adesklets.images->pos) {
1309 imlib_blend_image_onto_image(adesklets.images->content[i],
1310 atoi(params->content[2]),
1311 atoi(params->content[3]),
1312 atoi(params->content[4]),
1313 atoi(params->content[5]),
1314 atoi(params->content[6]),
1315 atoi(params->content[7]),
1316 atoi(params->content[8]),
1317 atoi(params->content[9]),
1318 atoi(params->content[10]));
1319 if (image_is_shown())
1320 updates = imlib_update_append_rect(updates,
1321 atoi(params->content[7]),
1322 atoi(params->content[8]),
1323 atoi(params->content[9]),
1324 atoi(params->content[10]));
1325 } else
1326 command_error("image ID %d out of range\n",i);
1327 } else
1328 command_error("not enough parameters given - need ten\n");
1329 break;
1330 case CMD_BLEND_IMAGE_ONTO_IMAGE_AT_ANGLE:
1331 if (params->pos>=11) {
1332 if((i=atoi((char*)params->content[1]))>=0 &&
1333 i<adesklets.images->pos) {
1334 imlib_blend_image_onto_image_at_angle(
1335 adesklets.images->content[i],
1336 atoi(params->content[2]),
1337 atoi(params->content[3]),
1338 atoi(params->content[4]),
1339 atoi(params->content[5]),
1340 atoi(params->content[6]),
1341 atoi(params->content[7]),
1342 atoi(params->content[8]),
1343 atoi(params->content[9]),
1344 atoi(params->content[10]));
1345 if (image_is_shown())
1346 /* We do not bother: we update everything */
1347 updates = imlib_update_append_rect(updates,
1348 0,0,
1349 imlib_image_get_width(),
1350 imlib_image_get_height());
1351 } else
1352 command_error("image ID %d out of range\n",i);
1353 } else
1354 command_error("not enough parameters given - need ten\n");
1355 break;
1356 case CMD_BLEND_IMAGE_ONTO_IMAGE_SKEWED:
1357 if (params->pos>=12) {
1358 if((i=atoi((char*)params->content[1]))>=0 &&
1359 i<adesklets.images->pos) {
1360 imlib_blend_image_onto_image_skewed(adesklets.images->content[i],
1361 atoi(params->content[2]),
1362 atoi(params->content[3]),
1363 atoi(params->content[4]),
1364 atoi(params->content[5]),
1365 atoi(params->content[6]),
1366 atoi(params->content[7]),
1367 atoi(params->content[8]),
1368 atoi(params->content[9]),
1369 atoi(params->content[10]),
1370 atoi(params->content[11]),
1371 atoi(params->content[12]));
1372 if (image_is_shown())
1373 /* We do not bother: we update everything */
1374 updates = imlib_update_append_rect(updates,
1375 0,0,
1376 imlib_image_get_width(),
1377 imlib_image_get_height());
1378 } else
1379 command_error("image ID %d out of range\n",i);
1380 } else
1381 command_error("not enough parameters given - need twelve\n");
1382 break;
1383 case CMD_APPLY_FILTER:
1384 /* WARNING: there is a initialisation bug in imlib2 prior
1385 version 1.2.0 (cvs of 11/20/04) that sets the dynamic filters
1386 never to work if an image loader is not used
1387 at least once before (this has to do with
1388 lt_dlinit() being called at the wrong place...).
1389 We can do nothing about this: upgrade your imlib2 lib!
1391 prototype(const char * script)
1393 if(params->pos>=2) {
1394 menu_str=command_subsplitter(command.line,1);
1395 if(!strstr(menu_str,"[]")) {
1396 imlib_apply_filter(menu_str);
1397 if (image_is_shown())
1398 updates=imlib_update_append_rect(updates,0,0,
1399 imlib_image_get_width(),
1400 imlib_image_get_height());
1402 else
1403 command_error("variadic filters forbidden\n");
1404 } else
1405 command_error("filter description not given\n");
1408 "tint(x=0,y=0,w=100,h=100,alpha=100,red=155,green=25,blue=25);"
1410 break;
1411 case CMD_GET_TEXT_SIZE:
1412 /* prototype(const char * text) */
1413 if(imlib_context_get_font()) {
1414 if(params->pos>=2) {
1415 menu_str=dupstr_utf8(command_subsplitter(command.line,1));
1416 imlib_get_text_size(menu_str,
1417 &i,&j);
1418 free(menu_str);
1419 command_ok("text size %d %d\n",i,j);
1420 } else
1421 command_error("text string not given or blank\n");
1422 } else
1423 command_error("no font selected.\n");
1424 break;
1425 case CMD_GET_TEXT_ADVANCE:
1426 /* prototype(const char * text) */
1427 if(imlib_context_get_font()) {
1428 if(params->pos>=2) {
1429 menu_str=dupstr_utf8(command_subsplitter(command.line,1));
1430 imlib_get_text_advance(menu_str,&i,&j);
1431 free(menu_str);
1432 command_ok("text advance %d %d\n",i,j);
1433 } else
1434 command_error("text string not given or blank\n");
1435 } else
1436 command_error("no font selected.\n");
1437 break;
1438 case CMD_TEXT_DRAW:
1439 if(imlib_context_get_font()) {
1440 if(params->pos>=4) {
1441 menu_str=dupstr_utf8(command_subsplitter(command.line,3));
1442 imlib_text_draw(atoi(params->content[1]),
1443 atoi(params->content[2]),
1444 menu_str);
1445 if (image_is_shown()) {
1446 imlib_get_text_size(menu_str,&x,&y);
1447 updates = imlib_update_append_rect(updates,
1448 atoi(params->content[1]),
1449 atoi(params->content[2]),
1450 x,y);
1452 free(menu_str);
1453 } else
1454 command_error("text string not given or blank\n");
1455 } else
1456 command_error("no font selected.\n");
1457 break;
1458 case CMD_MODIFY_COLOR_MODIFIER_GAMMA:
1459 if(imlib_context_get_color_modifier()) {
1460 if(params->pos>=2) {
1461 imlib_modify_color_modifier_gamma(atof(params->content[1]));
1462 } else
1463 command_error("gamma value not given\n");
1464 } else
1465 command_error("no context color modifier selected\n");
1466 break;
1467 case CMD_MODIFY_COLOR_MODIFIER_BRIGHTNESS:
1468 if(imlib_context_get_color_modifier()) {
1469 if(params->pos>=2) {
1470 imlib_modify_color_modifier_brightness(atof(params->content[1]));
1471 } else
1472 command_error("brightness value not given\n");
1473 } else
1474 command_error("no context color modifier selected\n");
1475 break;
1476 case CMD_MODIFY_COLOR_MODIFIER_CONTRAST:
1477 if(imlib_context_get_color_modifier()) {
1478 if(params->pos>=2) {
1479 imlib_modify_color_modifier_contrast(atof(params->content[1]));
1480 } else
1481 command_error("contrast value not given\n");
1482 } else
1483 command_error("no context color modifier selected\n");
1484 break;
1485 case CMD_GET_COLOR_MODIFIER_TABLES:
1486 /* prototype(void) */
1487 /* Throw all 1024 table entries in RGBA orders */
1488 if(imlib_context_get_color_modifier()) {
1489 if((tables[0]=(DATA8*)malloc(sizeof(DATA8)*256))&&
1490 (tables[1]=(DATA8*)malloc(sizeof(DATA8)*256))&&
1491 (tables[2]=(DATA8*)malloc(sizeof(DATA8)*256))&&
1492 (tables[3]=(DATA8*)malloc(sizeof(DATA8)*256))) {
1493 imlib_get_color_modifier_tables(tables[0],tables[1],
1494 tables[2],tables[3]);
1495 for(i=0;i<4;++i)
1496 for(j=0;j<256;++j)
1497 command_printf("%hhu ", tables[i][j]);
1498 command_printf("\n");
1499 } else
1500 command_error("memory allocation problem\n");
1501 for(i=0;i<4;++i)
1502 if(tables[i]) free(tables[i]);
1503 } else
1504 command_error("no context color modifier selected\n");
1505 break;
1506 break;
1507 case CMD_SET_COLOR_MODIFIER_TABLES:
1508 /* prototype(unsigned char * table) */
1509 if(imlib_context_get_color_modifier()) {
1510 if (params->pos==1025) {
1511 if((tables[0]=(DATA8*)malloc(sizeof(DATA8)*256))&&
1512 (tables[1]=(DATA8*)malloc(sizeof(DATA8)*256))&&
1513 (tables[2]=(DATA8*)malloc(sizeof(DATA8)*256))&&
1514 (tables[3]=(DATA8*)malloc(sizeof(DATA8)*256))) {
1515 for(i=0;i<4;++i)
1516 for(j=0;j<256;++j)
1517 tables[i][j]=(DATA8)atoi(params->content[(i*256)+j+1]);
1518 imlib_set_color_modifier_tables(tables[0],tables[1],
1519 tables[2],tables[3]);
1520 command_ok("set_color_modifier_tables\n");
1521 } else
1522 command_error("memory allocation problem");
1523 for(i=0;i<4;++i)
1524 if(tables[i]) free(tables[i]);
1525 } else
1526 command_error("Invalid number of entries - need 1024\n");
1527 } else
1528 command_error("no context color modifier selected\n");
1529 break;
1530 case CMD_GET_COLOR_MODIFIER_VALUE:
1531 /* prototype(enum RGBA_TABLES table, int index) */
1532 /* NOTE: this is not an original imlib2 function.
1533 it was included as a convenience for
1534 interactive use. */
1535 if(imlib_context_get_color_modifier()) {
1536 if (params->pos>=3) {
1537 for(i=0;RGBA_TABLES[i];++i)
1538 if(strncmp(RGBA_TABLES[i],
1539 params->content[1],
1540 strlen(params->content[1]))==0)
1541 break;
1542 i=(RGBA_TABLES[i])?i:atoi(params->content[1])%4;
1544 if((j=atoi(params->content[2]))<256 && j>=0) {
1545 if((tables[0]=(DATA8*)malloc(sizeof(DATA8)*256))&&
1546 (tables[1]=(DATA8*)malloc(sizeof(DATA8)*256))&&
1547 (tables[2]=(DATA8*)malloc(sizeof(DATA8)*256))&&
1548 (tables[3]=(DATA8*)malloc(sizeof(DATA8)*256))) {
1549 imlib_get_color_modifier_tables(tables[0],tables[1],
1550 tables[2],tables[3]);
1551 command_ok("value %s %hhu\n",
1552 RGBA_TABLES[i],
1553 (char)tables[i][j]&255);
1555 } else
1556 command_error("memory allocation problem\n");
1557 for(i=0;i<4;++i)
1558 if(tables[i]) free(tables[i]);
1559 } else
1560 command_error("index value %d out of range\n",j);
1561 } else
1562 command_error("parameters not given - need two\n");
1563 } else
1564 command_error("no context color modifier selected\n");
1565 break;
1566 case CMD_SET_COLOR_MODIFIER_VALUE:
1567 /* prototype(enum RGBA_TABLES table, int index, int value) */
1568 /* NOTE: this is not an original imlib2 function.
1569 it was included as a convenience for
1570 interactive use. */
1571 if(imlib_context_get_color_modifier()) {
1572 if (params->pos>=4) {
1573 for(i=0;RGBA_TABLES[i];++i)
1574 if(strncmp(RGBA_TABLES[i],
1575 params->content[1],
1576 strlen(params->content[1]))==0)
1577 break;
1578 i=(RGBA_TABLES[i])?i:atoi(params->content[1])%4;
1580 if((j=atoi(params->content[2]))<256 && j>=0) {
1581 if ((x=atoi(params->content[3]))<256 && x>=0) {
1582 if((tables[0]=(DATA8*)malloc(sizeof(DATA8)*256))&&
1583 (tables[1]=(DATA8*)malloc(sizeof(DATA8)*256))&&
1584 (tables[2]=(DATA8*)malloc(sizeof(DATA8)*256))&&
1585 (tables[3]=(DATA8*)malloc(sizeof(DATA8)*256))) {
1586 imlib_get_color_modifier_tables(tables[0],tables[1],
1587 tables[2],tables[3]);
1588 tables[i][j]=x;
1589 imlib_set_color_modifier_tables(tables[0],tables[1],
1590 tables[2],tables[3]);
1591 } else
1592 command_error("memory allocation problem\n");
1593 for(i=0;i<4;++i)
1594 if(tables[i]) free(tables[i]);
1595 } else
1596 command_error("value %d out of range\n",x);
1597 } else
1598 command_error("index value %d out of range\n",j);
1599 } else
1600 command_error("parameters not given - need three\n");
1601 } else
1602 command_error("no context color modifier selected\n");
1603 break;
1604 case CMD_APPLY_COLOR_MODIFIER:
1605 if(imlib_context_get_color_modifier()) {
1606 imlib_apply_color_modifier();
1607 if(image_is_shown())
1608 updates=imlib_update_append_rect(updates,0,0,
1609 imlib_image_get_width(),
1610 imlib_image_get_height());
1611 } else
1612 command_error("no context color modifier selected\n");
1613 break;
1614 case CMD_APPLY_COLOR_MODIFIER_TO_RECTANGLE:
1615 if(imlib_context_get_color_modifier()) {
1616 if (params->pos>=5) {
1617 imlib_apply_color_modifier_to_rectangle(
1618 (x=atoi(params->content[1])),
1619 (y=atoi(params->content[2])),
1620 (i=atoi(params->content[3])),
1621 (j=atoi(params->content[4])));
1622 if (image_is_shown())
1623 updates=imlib_update_append_rect(updates,x,y,i,j);
1624 } else
1625 command_error("rectangles coordinates not given\n");
1626 } else
1627 command_error("no context color modifier selected\n");
1628 break;
1629 case CMD_LOAD_IMAGE_WITHOUT_CACHE:
1630 if (params->pos>=2) {
1631 menu_str=command_subsplitter(command.line,1);
1632 if ((image=imlib_load_image_without_cache(menu_str))) {
1633 if (vector_push(adesklets.images,image))
1634 command_ok("new image %d\n",adesklets.images->pos-1);
1635 else
1636 command_error("memory allocation problem\n");
1637 } else
1638 command_error("could not load image '%s'\n", menu_str);
1639 } else
1640 command_error("image file name not given\n");
1641 break;
1642 case CMD_LOAD_IMAGE:
1643 if (params->pos>=2) {
1644 menu_str=command_subsplitter(command.line,1);
1645 if ((image=imlib_load_image_with_error_return(menu_str,&error))) {
1646 if (vector_push(adesklets.images,image))
1647 command_ok("new image %d\n",adesklets.images->pos-1);
1648 else
1649 command_error("memory allocation problem\n");
1650 } else
1651 command_error("could not load image '%s' - %s\n",
1652 menu_str,LOAD_ERRORS[(int)error]);
1653 } else
1654 command_error("image file name not given\n");
1655 break;
1656 case CMD_SAVE_IMAGE:
1657 if (params->pos>=2) {
1658 menu_str=command_subsplitter(command.line,1);
1659 imlib_save_image_with_error_return(menu_str,&error);
1660 if(error!=IMLIB_LOAD_ERROR_NONE)
1661 command_error("%s\n",LOAD_ERRORS[(int)error]);
1662 } else
1663 command_error("image file name not given\n");
1664 break;
1665 case CMD_CREATE_IMAGE:
1666 if (params->pos>=3) {
1667 if((i=atoi(params->content[1]))>0 &&
1668 (j=atoi(params->content[2]))>0) {
1669 if((image=imlib_create_image(i,j))) {
1670 xwindow_context_save(IMLIB_IMAGE|IMLIB_BLEND|IMLIB_COLOR);
1671 imlib_context_set_image(image);
1672 imlib_image_set_has_alpha(1);
1673 imlib_context_set_blend(0);
1674 imlib_context_set_color(0,0,0,0);
1675 imlib_image_fill_rectangle(0,0,i,j);
1676 xwindow_context_restore();
1677 if (vector_push(adesklets.images,image))
1678 command_ok("new image %d\n",adesklets.images->pos-1);
1679 else
1680 command_error("memory allocation problem\n");
1681 } else
1682 command_error("imlib image allocation error\n");
1683 } else
1684 command_error("image dimensions out of range\n");
1685 } else
1686 command_error("image dimensions were not given\n");
1687 break;
1688 case CMD_CREATE_IMAGE_USING_DATA:
1689 /* This uses imlib_create_image_using_copied_data(),
1690 so DATA * data can be freed afterward.
1691 As in CMD_IMAGE_GET_DATA, data is expected to be
1692 RGBA ordered. */
1693 if (params->pos>=3) {
1694 if ((width=atoi(params->content[1]))>0 &&
1695 (height=atoi(params->content[2]))>0) {
1696 if(width*height*4==params->pos-3) {
1697 if((data=(DATA32*)malloc(sizeof(DATA32)*width*height))) {
1698 for(i=0;i<width*height;++i)
1699 data[i]=
1700 ((atoi((char*)params->content[i*4+3])&255)<<16)|
1701 ((atoi((char*)params->content[i*4+4])&255)<<8)|
1702 ((atoi((char*)params->content[i*4+5])&255)<<0)|
1703 ((atoi((char*)params->content[i*4+6])&255)<<24);
1704 if ((image=imlib_create_image_using_copied_data(width,
1705 height,
1706 data))) {
1707 xwindow_context_save(IMLIB_IMAGE);
1708 imlib_context_set_image(image);
1709 imlib_image_set_has_alpha(1);
1710 xwindow_context_restore();
1711 if(vector_push(adesklets.images,image))
1712 command_ok("new image %d\n",adesklets.images->pos-1);
1713 else
1714 command_error("memory allocation problem");
1715 } else
1716 command_error("imlib image allocation error\n");
1717 free(data);
1719 else
1720 command_error("memory allocation problem\n");
1721 } else
1722 command_error("image dimensions and data lenght mismatch\n");
1723 } else
1724 command_error("image dimensions out of range\n");
1725 } else
1726 command_error("image dimensions were not given\n");
1727 break;
1728 case CMD_CLONE_IMAGE:
1729 if((image=imlib_clone_image())) {
1730 if (vector_push(adesklets.images,image))
1731 command_ok("cloned image %d\n",adesklets.images->pos-1);
1732 else
1733 command_error("memory allocation problem");
1734 } else
1735 command_error("imlib image allocation error\n");
1736 break;
1737 case CMD_FREE_IMAGE:
1738 /* This does not react as imlib_free_image:
1739 - image ID has to be given
1740 - If current context image is freed, context
1741 is put back on foreground image
1742 - If image corresponding to user_background_image
1743 is freed, user_background_image is reset.
1745 prototype(int image)
1747 if(params->pos>=2) {
1748 if((i=atoi((char*)params->content[1]))<adesklets.images->pos &&
1749 i>=0) {
1750 if(i>=2) {
1751 j=(imlib_context_get_image()==adesklets.images->content[i]);
1752 if (vector_delete(adesklets.images,i)) {
1753 if(i==adesklets.user_background_image) {
1754 adesklets.user_background_image=-1;
1755 xwindow_context_save(IMLIB_IMAGE);
1756 imlib_context_set_image(adesklets.images->content[0]);
1757 updates=imlib_update_append_rect(updates,0,0,
1758 imlib_image_get_width(),
1759 imlib_image_get_height());
1760 xwindow_context_restore();
1762 else
1763 if(i<adesklets.user_background_image)
1764 --adesklets.user_background_image;
1765 if (j)
1766 imlib_context_set_image(adesklets.images->content[0]);
1767 } else
1768 command_error("memory desallocation problem\n");
1769 } else
1770 command_error("it is forbidden to unload image %d\n",i);
1771 } else
1772 command_error("image ID %d out of range\n",i);
1773 } else
1774 command_error("image ID not given\n");
1775 break;
1776 case CMD_LOAD_FONT:
1777 if(params->pos>=2) {
1778 if (strlen(params->content[1])>=3 &&
1779 index(params->content[1],'/')) {
1780 if ((font=imlib_load_font(params->content[1]))) {
1781 if(vector_push(adesklets.fonts,font))
1782 command_ok("new font %d\n", adesklets.fonts->pos-1);
1783 else
1784 command_error("memory allocation problem");
1785 } else
1786 command_error("font '%s' could not be loaded\n",
1787 (char*)params->content[1]);
1788 } else
1789 command_error(
1790 "font description incorrect - should be `name/size'\n");
1791 } else
1792 command_error("font description not given\n");
1793 break;
1794 case CMD_FREE_FONT:
1795 /* This does not react as imlib_free_font:
1796 - font ID has to be given
1797 - If current font is freed, context
1798 is put back on NULL
1800 prototype(int font)
1802 if(params->pos>=2) {
1803 if((i=atoi((char*)params->content[1]))
1804 <adesklets.fonts->pos &&
1805 i>=0) {
1806 j=(imlib_context_get_font()==
1807 adesklets.fonts->content[i]);
1808 if (vector_delete(adesklets.fonts,i)) {
1809 if (j)
1810 imlib_context_set_font(NULL);
1811 } else
1812 command_error("memory desallocation problem\n");
1813 } else
1814 command_error("font ID %d out of range\n",i);
1815 } else
1816 command_error("font ID not given\n");
1817 break;
1818 case CMD_LIST_FONTS:
1819 /* prototype(void) */
1820 list=imlib_list_fonts(&j);
1821 command_printf("%d fonts found\n",j);
1822 for(i=0;i<j;++i)
1823 command_printf("%s ",list[i]);
1824 command_printf("\n");
1825 imlib_free_font_list(list,j);
1826 break;
1827 case CMD_LIST_FONT_PATH:
1828 /* prototype(void) */
1829 list=imlib_list_font_path(&j);
1830 command_printf("%d font_path found\n",j);
1831 for(i=0;i<j;++i)
1832 command_printf("%s\n",list[i]);
1833 break;
1834 case CMD_ADD_PATH_TO_FONT_PATH:
1835 if(params->pos>=2) {
1836 imlib_add_path_to_font_path(command_subsplitter(command.line,1));
1837 } else
1838 command_error("font path not given\n");
1839 break;
1840 case CMD_REMOVE_PATH_FROM_FONT_PATH:
1841 if(params->pos>=2) {
1842 imlib_remove_path_from_font_path(
1843 command_subsplitter(command.line,1));
1844 debug("%s\n",command_subsplitter(command.line,1));
1845 } else
1846 command_error("font path not given\n");
1847 break;
1848 case CMD_CREATE_COLOR_RANGE:
1849 if((color_range=imlib_create_color_range())) {
1850 if(vector_push(adesklets.color_ranges,color_range))
1851 command_ok("new colorrange %d\n",adesklets.color_ranges->pos-1);
1852 else
1853 command_error("memory allocation problem\n");
1854 } else
1855 command_error("imlib allocation problem\n");
1856 break;
1857 case CMD_FREE_COLOR_RANGE:
1858 /* This does not react as imlib_free_color_range:
1859 - color_range ID has to be given
1860 - If current color range is freed, context
1861 is put back on NULL
1863 prototype(int color_range)
1865 if(params->pos>=2) {
1866 if((i=atoi((char*)params->content[1]))
1867 <adesklets.color_ranges->pos &&
1868 i>=0) {
1869 j=(imlib_context_get_color_range()==
1870 adesklets.color_ranges->content[i]);
1871 if (vector_delete(adesklets.color_ranges,i)) {
1872 if (j)
1873 imlib_context_set_color_range(NULL);
1874 } else
1875 command_error("memory desallocation problem\n");
1876 } else
1877 command_error("color range ID %d out of range\n",i);
1878 } else
1879 command_error("color range ID not given\n");
1880 break;
1881 case CMD_CREATE_FILTER:
1882 /* prototype(void) */
1883 if((filter=imlib_create_filter(0))) {
1884 if(vector_push(adesklets.filters,filter))
1885 command_ok("new filter %d\n",adesklets.filters->pos-1);
1886 else
1887 command_error("memory allocation problem\n");
1888 } else
1889 command_error("imlib allocation problem\n");
1890 break;
1891 case CMD_FREE_FILTER:
1892 /* This does not react as imlib_free_filter:
1893 - filter ID has to be given
1894 - If current filter is freed, context
1895 is put back on NULL
1897 prototype(int filter)
1899 if(params->pos>=2) {
1900 if((i=atoi((char*)params->content[1]))
1901 <adesklets.filters->pos &&
1902 i>=0) {
1903 j=(imlib_context_get_filter()==
1904 adesklets.filters->content[i]);
1905 if (vector_delete(adesklets.filters,i)) {
1906 if (j)
1907 imlib_context_set_filter(NULL);
1908 } else
1909 command_error("memory desallocation problem\n");
1910 } else
1911 command_error("filter ID %d out of range\n",i);
1912 } else
1913 command_error("filter ID not given\n");
1914 break;
1915 case CMD_CREATE_COLOR_MODIFIER:
1916 if((color_modifier=imlib_create_color_modifier())) {
1917 if(vector_push(adesklets.color_modifiers,color_modifier))
1918 command_ok("new colormodifier %d\n",
1919 adesklets.color_modifiers->pos-1);
1920 else
1921 command_error("memory allocation problem\n");
1922 } else
1923 command_error("imlib allocation problem\n");
1924 break;
1925 case CMD_FREE_COLOR_MODIFIER:
1926 /* This does not react as imlib_free_color_modifier:
1927 - color_range ID has to be given
1928 - If current color modifier is freed, context
1929 is put back on NULL
1931 prototype(int color_modifier)
1933 if(params->pos>=2) {
1934 if((i=atoi((char*)params->content[1]))
1935 <adesklets.color_modifiers->pos &&
1936 i>=0) {
1937 j=(imlib_context_get_color_modifier()==
1938 adesklets.color_modifiers->content[i]);
1939 if (vector_delete(adesklets.color_modifiers,i)) {
1940 if (j)
1941 imlib_context_set_color_modifier(NULL);
1942 } else
1943 command_error("memory desallocation problem\n");
1944 } else
1945 command_error("color modifier ID %d out of range\n",i);
1946 } else
1947 command_error("color modifier ID not given\n");
1948 break;
1949 case CMD_POLYGON_NEW:
1950 if((polygon=imlib_polygon_new())) {
1951 if(vector_push(adesklets.polygons,polygon))
1952 command_ok("new polygon %d\n",adesklets.polygons->pos-1);
1953 else
1954 command_error("memory allocation problem\n");
1955 } else
1956 command_error("imlib allocation problem\n");
1957 break;
1958 case CMD_POLYGON_FREE:
1959 if(params->pos>=2) {
1960 if((i=atoi(params->content[1]))>=0 &&
1961 i<adesklets.polygons->pos) {
1962 if(!vector_delete(adesklets.polygons,i))
1963 command_error("memory desallocation problem\n");
1964 } else
1965 command_error("polygon ID %d out of range\n",i);
1966 } else
1967 command_error("polygon ID not given\n");
1968 break;
1969 case CMD_POLYGON_ADD_POINT:
1970 if(params->pos>=4) {
1971 if((i=atoi(params->content[1]))>=0 && i<adesklets.polygons->pos) {
1972 imlib_polygon_add_point(adesklets.polygons->content[i],
1973 atoi(params->content[2]),
1974 atoi(params->content[3]));
1975 } else
1976 command_error("polygon ID %d out of range\n",i);
1977 } else
1978 command_error("not enough parameters given - need 3\n");
1979 break;
1980 case CMD_IMAGES_RESET_ALL:
1981 /* prototype(void) */
1982 adesklets_images_reset();
1983 break;
1984 case CMD_IMAGES_INFO:
1985 /* prototype(void) */
1986 xwindow_context_save(IMLIB_IMAGE);
1987 command_printf("%d images\n",adesklets.images->pos);
1988 for(i=0;i<adesklets.images->pos;++i) {
1989 imlib_context_set_image(adesklets.images->content[i]);
1990 command_printf("id %d width %d height %d alpha %hhu filename %s\n",
1992 imlib_image_get_width(), imlib_image_get_height(),
1993 imlib_image_has_alpha(), imlib_image_get_filename());
1995 xwindow_context_restore();
1996 break;
1997 case CMD_FONTS_RESET_ALL:
1998 /* prototype(void) */
1999 adesklets_fonts_reset();
2000 break;
2001 case CMD_FONTS_INFO:
2002 /* prototype(void) */
2003 command_printf("%d fonts\n",adesklets.fonts->pos);
2004 break;
2005 case CMD_COLOR_RANGES_RESET_ALL:
2006 /* prototype(void) */
2007 adesklets_color_ranges_reset();
2008 break;
2009 case CMD_COLOR_RANGES_INFO:
2010 /* prototype(void) */
2011 command_printf("%d color ranges\n",adesklets.color_ranges->pos);
2012 break;
2013 case CMD_COLOR_MODIFIERS_RESET_ALL:
2014 /* prototype(void) */
2015 adesklets_color_modifiers_reset();
2016 break;
2017 case CMD_COLOR_MODIFIERS_INFO:
2018 /* prototype(void) */
2019 command_printf("%d color modifiers\n",adesklets.color_modifiers->pos);
2020 break;
2021 case CMD_FILTERS_RESET_ALL:
2022 /* prototype(void) */
2023 adesklets_filters_reset();
2024 break;
2025 case CMD_FILTERS_INFO:
2026 /* prototype(void) */
2027 command_printf("%d filters\n",adesklets.filters->pos);
2028 break;
2029 case CMD_POLYGONS_RESET_ALL:
2030 /* prototype(void) */
2031 adesklets_polygons_reset();
2032 break;
2033 case CMD_POLYGONS_INFO:
2034 /* prototype(void) */
2035 command_printf("%d polygons\n",adesklets.polygons->pos);
2036 break;
2037 case CMD_IMAGE_HAS_ALPHA:
2038 command_ok("image alpha %hhu\n",imlib_image_has_alpha());
2039 break;
2040 case CMD_IMAGE_GET_WIDTH:
2041 command_ok("image width %d\n",imlib_image_get_width());
2042 break;
2043 case CMD_IMAGE_GET_HEIGHT:
2044 command_ok("image height %d\n",imlib_image_get_height());
2045 break;
2046 case CMD_IMAGE_GET_FILENAME:
2047 command_ok("image filename %s\n",imlib_image_get_filename());
2048 break;
2049 case CMD_IMAGE_GET_DATA:
2050 /* This uses imlib_image_get_data_for_reading_only(),
2051 so there is no need to invalidate image. Print final result
2052 in rgba format */
2053 if((data=imlib_image_get_data_for_reading_only())) {
2054 width=imlib_image_get_width();
2055 height=imlib_image_get_height();
2056 command_printf("image data - %d %d\n",width,height);
2057 for(i=0;i<width*height;++i)
2058 command_printf("%hhu %hhu %hhu %hhu ",
2059 ((data[i]&(255<<16))>>16),
2060 ((data[i]&(255<<8))>>8),
2061 (data[i]&255),
2062 ((data[i]&(255<<24))>>24));
2063 command_printf("\n");
2064 } else
2065 command_error("imlib data fetch problem\n");
2066 break;
2067 case CMD_IMAGE_QUERY_PIXEL:
2068 /* prototype(int x, int y) */
2069 if (params->pos>=2) {
2070 imlib_image_query_pixel(atoi(params->content[1]),
2071 atoi(params->content[2]),
2072 &color);
2073 command_ok("pixel value %hhu %hhu %hhu %hhu\n",
2074 (char)color.red&255,(char)color.green&255,
2075 (char)color.blue&255,(char)color.alpha&255);
2076 } else
2077 command_error("pixel coordinates not given\n");
2078 break;
2079 case CMD_IMAGE_SET_HAS_ALPHA:
2080 /* prototype(bool has_alpha) */
2081 if (params->pos>=2)
2082 imlib_image_set_has_alpha((char)atoi(params->content[1]));
2083 else
2084 command_error("alpha value not given\n");
2085 break;
2086 case CMD_IMAGE_SET_CHANGES_ON_DISK:
2087 /* prototype(void) */
2088 imlib_image_set_changes_on_disk();
2089 break;
2090 case CMD_IMAGE_SET_FORMAT:
2091 if (params->pos>=2)
2092 imlib_image_set_format(params->content[1]);
2093 else
2094 command_error("format string not given\n");
2095 break;
2096 case CMD_IMAGE_FILTER_RECURSE:
2097 /* prototype(void) */
2098 if(imlib_context_get_filter()) {
2099 for(i=0,j=imlib_image_get_width();i<j;++i) {
2100 imlib_image_filter();
2101 #ifdef DEBUG
2102 if(i%(j/10)==(j/10)-1)
2103 debug("We are %d0 percents through.\n", (i+1)*10/j);
2104 #endif
2106 if(image_is_shown())
2107 updates=imlib_update_append_rect(updates,0,0,
2108 imlib_image_get_width(),
2109 imlib_image_get_height());
2111 else
2112 command_error("no filter selected\n");
2113 break;
2114 case CMD_IMAGE_DRAW_LINE:
2115 if(params->pos>=5) {
2116 imlib_image_draw_line(atoi(params->content[1]),
2117 atoi(params->content[2]),
2118 atoi(params->content[3]),
2119 atoi(params->content[4]),0);
2120 if (image_is_shown())
2121 updates = imlib_update_append_rect(updates,
2122 atoi(params->content[1]),
2123 atoi(params->content[2]),
2124 atoi(params->content[3])-
2125 atoi(params->content[1]),
2126 atoi(params->content[4])-
2127 atoi(params->content[2]));
2128 } else
2129 command_error("line coordinates not given\n");
2130 break;
2131 case CMD_IMAGE_DRAW_RECTANGLE:
2132 if(params->pos>=5) {
2133 imlib_image_draw_rectangle(atoi(params->content[1]),
2134 atoi(params->content[2]),
2135 atoi(params->content[3]),
2136 atoi(params->content[4]));
2137 if (image_is_shown())
2138 updates = imlib_update_append_rect(updates,
2139 atoi(params->content[1]),
2140 atoi(params->content[2]),
2141 atoi(params->content[3]),
2142 atoi(params->content[4]));
2143 } else
2144 command_error("rectangle description not given\n");
2145 break;
2146 case CMD_IMAGE_FILL_RECTANGLE:
2147 if(params->pos>=5) {
2148 imlib_image_fill_rectangle(atoi(params->content[1]),
2149 atoi(params->content[2]),
2150 atoi(params->content[3]),
2151 atoi(params->content[4]));
2152 if (image_is_shown())
2153 updates = imlib_update_append_rect(updates,
2154 atoi(params->content[1]),
2155 atoi(params->content[2]),
2156 atoi(params->content[3]),
2157 atoi(params->content[4]));
2158 } else
2159 command_error("rectangle description not given\n");
2160 break;
2161 case CMD_IMAGE_FILL_COLOR_RANGE_RECTANGLE:
2162 if (imlib_context_get_color_range()) {
2163 if(params->pos>=6) {
2164 imlib_image_fill_color_range_rectangle(atoi(params->content[1]),
2165 atoi(params->content[2]),
2166 atoi(params->content[3]),
2167 atoi(params->content[4]),
2168 atof(params->content[5]));
2169 if (image_is_shown())
2170 updates = imlib_update_append_rect(updates,
2171 atoi(params->content[1]),
2172 atoi(params->content[2]),
2173 atoi(params->content[3]),
2174 atoi(params->content[4]));
2175 } else
2176 command_error("not enough parameters given - need five\n");
2177 } else
2178 command_error("no color range selected\n");
2179 break;
2180 case CMD_IMAGE_DRAW_ELLIPSE:
2181 if(params->pos>=5) {
2182 imlib_image_draw_ellipse(atoi(params->content[1]),
2183 atoi(params->content[2]),
2184 atoi(params->content[3]),
2185 atoi(params->content[4]));
2186 if (image_is_shown())
2187 updates = imlib_update_append_rect(updates,
2188 atoi(params->content[1])-
2189 atoi(params->content[3]),
2190 atoi(params->content[2])-
2191 atoi(params->content[4]),
2192 2*atoi(params->content[3]),
2193 2*atoi(params->content[4]));
2194 } else
2195 command_error("ellipse description not given\n");
2196 break;
2197 case CMD_IMAGE_FILL_ELLIPSE:
2198 if(params->pos>=5) {
2199 imlib_image_fill_ellipse(atoi(params->content[1]),
2200 atoi(params->content[2]),
2201 atoi(params->content[3]),
2202 atoi(params->content[4]));
2203 if (image_is_shown())
2204 updates = imlib_update_append_rect(updates,
2205 atoi(params->content[1])-
2206 atoi(params->content[3]),
2207 atoi(params->content[2])-
2208 atoi(params->content[4]),
2209 2*atoi(params->content[3]),
2210 2*atoi(params->content[4]));
2211 } else
2212 command_error("ellipse description not given\n");
2213 break;
2214 case CMD_IMAGE_COPY_ALPHA_TO_IMAGE:
2215 if(params->pos>=4) {
2216 if((i=atoi(params->content[1]))>=0 &&
2217 i<adesklets.images->pos) {
2218 imlib_image_copy_alpha_to_image(adesklets.images->content[i],
2219 atoi(params->content[2]),
2220 atoi(params->content[3]));
2221 if(image_is_shown()) {
2222 xwindow_context_save(IMLIB_IMAGE);
2223 imlib_context_set_image(adesklets.images->content[i]);
2224 updates = imlib_update_append_rect(updates,
2225 atoi(params->content[2]),
2226 atoi(params->content[3]),
2227 imlib_image_get_width(),
2228 imlib_image_get_height());
2229 xwindow_context_restore();
2231 } else
2232 command_error("image ID out of range\n");
2233 } else
2234 command_error("parameters not given\n");
2235 break;
2236 case CMD_IMAGE_COPY_ALPHA_RECTANGLE_TO_IMAGE:
2237 if(params->pos>=8) {
2238 if((i=atoi(params->content[1]))>=0 &&
2239 i<adesklets.images->pos) {
2240 imlib_image_copy_alpha_rectangle_to_image(
2241 adesklets.images->content[i],
2242 atoi(params->content[2]),
2243 atoi(params->content[3]),
2244 atoi(params->content[4]),
2245 atoi(params->content[5]),
2246 atoi(params->content[6]),
2247 atoi(params->content[7]));
2249 if(image_is_shown())
2250 updates= imlib_update_append_rect(updates,
2251 atoi(params->content[6]),
2252 atoi(params->content[7]),
2253 atoi(params->content[4]),
2254 atoi(params->content[5]));
2255 } else
2256 command_error("image ID out of range\n");
2257 } else
2258 command_error("parameters not given - need height\n");
2259 break;
2260 case CMD_IMAGE_DRAW_POLYGON:
2261 if (params->pos>=3) {
2262 if ((i=atoi(params->content[1]))>=0 && i<adesklets.polygons->pos) {
2263 imlib_image_draw_polygon(adesklets.polygons->content[i],
2264 ((char*)params->content[2])[0]);
2265 if(image_is_shown()) {
2266 imlib_polygon_get_bounds(adesklets.polygons->content[i],
2267 &x, &y, &i, &j);
2268 updates= imlib_update_append_rect(updates,x,y,i-x,j-y);
2270 } else
2271 command_error("polygon ID %d out of range\n",i);
2272 } else
2273 command_error("parameters not given\n");
2274 break;
2275 case CMD_IMAGE_FILL_POLYGON:
2276 if (params->pos>=2) {
2277 if ((i=atoi(params->content[1]))>=0 && i<adesklets.polygons->pos) {
2278 imlib_image_fill_polygon(adesklets.polygons->content[i]);
2279 if(image_is_shown()) {
2280 imlib_polygon_get_bounds(adesklets.polygons->content[i],
2281 &x, &y, &i, &j);
2282 updates= imlib_update_append_rect(updates,x,y,i-x,j-y);
2284 } else
2285 command_error("polygon ID %d out of range\n",i);
2286 } else
2287 command_error("polygon ID not given\n");
2288 break;
2289 case CMD_IMAGE_FLIP_HORIZONTAL:
2290 imlib_image_flip_horizontal();
2291 if (image_is_shown())
2292 updates=imlib_update_append_rect(updates,0,0,
2293 imlib_image_get_width(),
2294 imlib_image_get_height());
2295 break;
2296 case CMD_IMAGE_FLIP_VERTICAL:
2297 imlib_image_flip_vertical();
2298 if (image_is_shown())
2299 updates=imlib_update_append_rect(updates,0,0,
2300 imlib_image_get_width(),
2301 imlib_image_get_height());
2302 break;
2303 case CMD_IMAGE_FLIP_DIAGONAL:
2304 if(((image=imlib_context_get_image()))!=
2305 adesklets.images->content[0] &&
2306 image != adesklets.images->content[1] &&
2307 (adesklets.user_background_image==-1 ||
2308 image != adesklets.images->content[
2309 adesklets.user_background_image]))
2310 imlib_image_flip_diagonal();
2311 else
2312 command_error("operation forbidden on this image\n");
2313 break;
2314 case CMD_IMAGE_ORIENTATE:
2315 if (params->pos>=2) {
2316 if((i=atoi(params->content[1])%4)%2==0 ||
2317 (((image=imlib_context_get_image())!=
2318 adesklets.images->content[0] &&
2319 image != adesklets.images->content[1])))
2320 imlib_image_orientate(i);
2321 else
2322 command_error("operation forbidden on this image\n");
2323 } else
2324 command_error("orientation not given\n");
2325 break;
2326 case CMD_IMAGE_BLUR:
2327 if (params->pos>=2) {
2328 imlib_image_blur(atof(params->content[1]));
2329 updates=imlib_update_append_rect(updates,0,0,
2330 imlib_image_get_width(),
2331 imlib_image_get_height());
2332 } else
2333 command_error("Blur radius not given\n");
2334 break;
2335 case CMD_IMAGE_SHARPEN:
2336 if (params->pos>=2) {
2337 imlib_image_sharpen(atof(params->content[1]));
2338 updates=imlib_update_append_rect(updates,0,0,
2339 imlib_image_get_width(),
2340 imlib_image_get_height());
2341 } else
2342 command_error("Sharpen radius not given\n");
2343 break;
2344 #define FILTER_SET(op)\
2345 if(imlib_context_get_filter()) {\
2346 if (params->pos>=7)\
2347 imlib_filter_set ## op(atoi(params->content[1]),\
2348 atoi(params->content[2]),\
2349 atoi(params->content[3]),\
2350 atoi(params->content[4]),\
2351 atoi(params->content[5]),\
2352 atoi(params->content[6]));\
2353 else\
2354 command_error("missing parameters - need six\n");\
2355 } else\
2356 command_error("no filter selected\n")
2357 case CMD_FILTER_SET:
2358 /* prototype(int xoff, int yoff, int a, int r, int g, int b) */
2359 FILTER_SET( );
2360 break;
2361 case CMD_FILTER_SET_RED:
2362 /* prototype(int xoff, int yoff, int a, int r, int g, int b) */
2363 FILTER_SET(_red);
2364 break;
2365 case CMD_FILTER_SET_GREEN:
2366 /* prototype(int xoff, int yoff, int a, int r, int g, int b) */
2367 FILTER_SET(_green);
2368 break;
2369 case CMD_FILTER_SET_BLUE:
2370 /* prototype(int xoff, int yoff, int a, int r, int g, int b) */
2371 FILTER_SET(_blue);
2372 break;
2373 case CMD_FILTER_SET_ALPHA:
2374 /* prototype(int xoff, int yoff, int a, int r, int g, int b) */
2375 FILTER_SET(_alpha);
2376 break;
2377 #undef FILTER_SET
2378 #define FILTER_SET(op)\
2379 if(imlib_context_get_filter()) {\
2380 if (params->pos>=5)\
2381 imlib_filter_ ## op(atoi(params->content[1]),\
2382 atoi(params->content[2]),\
2383 atoi(params->content[3]),\
2384 atoi(params->content[4]));\
2385 else\
2386 command_error("missing parameters - need four\n");\
2387 } else\
2388 command_error("no filter selected\n")
2389 case CMD_FILTER_CONSTANTS:
2390 /* prototype(int a, int r, int g, int b) */
2391 FILTER_SET(constants);
2392 break;
2393 case CMD_FILTER_DIVISORS:
2394 /* prototype(int a, int r, int g, int b) */
2395 FILTER_SET(divisors);
2396 break;
2397 #undef FILTER_SET
2398 case CMD_MENU_FIRE:
2399 /* prototype(int menu) */
2400 #ifndef X_DISPLAY_MISSING
2401 if (adesklets.display && adesklets.window) {
2402 if(params->pos>=2) {
2403 i=atoi((char*)params->content[1]);
2404 if (adesklets_menu_fire(i,(char**)&menu_str)) {
2405 if (adesklets.user_event_mask&MenuFireMask)
2406 event("menufire %d %s\n",i,menu_str);
2407 } else
2408 command_error("menu fire error\n");
2410 else
2411 command_error("menu ID not given\n");
2412 } else
2413 #endif
2414 command_error("X connection or window missing\n");
2415 break;
2416 case CMD_MENU_RESET_ALL:
2417 /* prototype(void) */
2418 if (!adesklets_menus_reset())
2419 command_error("internal consistency problem with menu\n");
2420 break;
2421 case CMD_MENU_ADD_MENU:
2422 /* prototype(void) */
2423 if (!vector_push(adesklets.menus,xmenu_init()))
2424 command_error("could not add a new menu\n");
2425 else
2426 command_ok("new menu %d\n",adesklets.menus->pos-1);
2427 break;
2428 case CMD_MENU_ADD_SUBMENU:
2429 /* prototype(const char * submenu) */
2430 if (params->pos>=2) {
2431 if (!xmenu_push_submenu(MENU(adesklets.menus->pos-1),
2432 command.line+1+
2433 strlen(COMMANDS[CMD_MENU_ADD_SUBMENU].name)))
2434 command_error("could not create submenu\n");
2436 if ((menu_str=dupstr_utf8(command_subsplitter(command.line,1)))) {
2437 if (!xmenu_push_submenu(MENU(adesklets.menus->pos-1),menu_str))
2438 command_error("could not create submenu\n");
2439 free(menu_str);
2442 } else
2443 command_error("submenu description not given\n");
2444 break;
2445 case CMD_MENU_ADD_ITEM:
2446 /* prototype(const char * add_item) */
2447 if(params->pos>=2) {
2448 if(!xmenu_push_item(MENU(adesklets.menus->pos-1),
2449 command.line+1+
2450 strlen(COMMANDS[CMD_MENU_ADD_ITEM].name)))
2451 command_error("could not create item\n");
2452 } else
2453 command_error("item description not given\n");
2454 break;
2455 case CMD_MENU_ADD_SEPARATOR:
2456 /* prototype(void) */
2457 if(!xmenu_push_item(MENU(adesklets.menus->pos-1),"-"))
2458 command_error("could not add separator\n");
2459 break;
2460 case CMD_MENU_END_SUBMENU:
2461 /* prototype(void) */
2462 if(!xmenu_end_submenu(MENU(adesklets.menus->pos-1)))
2463 command_error("could not end submenu\n");
2464 break;
2465 case CMD_EVENT_CATCH:
2466 /* prototype(voidvoid) */
2467 #ifndef X_DISPLAY_MISSING
2468 if (adesklets.display && adesklets.window) {
2469 if(params->pos>=2) {
2470 for(i=0;X_WINDOW_EVENTS[i].name;++i)
2471 if(strncmp(X_WINDOW_EVENTS[i].name,params->content[1],
2472 strlen(X_WINDOW_EVENTS[i].name))==0)
2473 break;
2474 adesklets.user_event_mask|=
2475 X_WINDOW_EVENTS[(X_WINDOW_EVENTS[i].name)?
2476 i:atoi(params->content[1])%i].mask;
2477 adesklets.event_mask=(BASE_EVENT_MASK)|
2478 (adesklets.user_event_mask&
2479 ~(BackgroundGrabMask|MenuFireMask));
2480 XSelectInput(adesklets.display,adesklets.window,
2481 adesklets.event_mask);
2482 } else
2483 command_error("event to catch not given\n");
2484 } else
2485 #endif
2486 command_error("X connection or window missing\n");
2487 break;
2488 case CMD_EVENT_UNCATCH:
2489 /* prototype(voidvoid) */
2490 #ifndef X_DISPLAY_MISSING
2491 if(adesklets.display && adesklets.window) {
2492 if(params->pos>=2) {
2493 for(i=0;X_WINDOW_EVENTS[i].name;++i)
2494 if(strncmp(X_WINDOW_EVENTS[i].name,params->content[1],
2495 strlen(X_WINDOW_EVENTS[i].name))==0)
2496 break;
2497 mask=X_WINDOW_EVENTS[(X_WINDOW_EVENTS[i].name)?
2498 i:atoi(params->content[1])%i].mask;
2499 /* If event was already selected, purge all remaining
2500 events of that type if applicable */
2501 if(mask!=BackgroundGrabMask &&
2502 mask!=MenuFireMask &&
2503 (adesklets.event_mask&mask) &&
2504 !((BASE_EVENT_MASK)&mask))
2505 while(XCheckWindowEvent(adesklets.display,
2506 adesklets.window,mask,&ev));
2507 adesklets.user_event_mask&=~mask;
2508 adesklets.event_mask=(BASE_EVENT_MASK)|
2509 (adesklets.user_event_mask
2510 &~(BackgroundGrabMask|MenuFireMask));
2511 XSelectInput(adesklets.display,adesklets.window,
2512 adesklets.event_mask);
2513 } else
2514 command_error("event to uncatch not given\n");
2515 } else
2516 #endif
2517 command_error("X connection or window missing\n");
2518 break;
2519 case CMD_EVENTS_RESET_ALL:
2520 /* prototype(voidvoid) */
2521 #ifndef X_DISPLAY_MISSING
2522 if(adesklets.display && adesklets.window) {
2523 XSelectInput(adesklets.display,adesklets.window,
2524 BASE_EVENT_MASK);
2525 while(XCheckWindowEvent(adesklets.display,adesklets.window,
2526 adesklets.user_event_mask&
2527 ~(BASE_EVENT_MASK)&~BackgroundGrabMask&
2528 ~MenuFireMask,
2529 &ev));
2530 adesklets.user_event_mask=0;
2531 adesklets.event_mask=BASE_EVENT_MASK;
2532 } else
2533 #endif
2534 command_error("X connection or window missing\n");
2535 break;
2536 case CMD_EVENTS_INFO:
2537 /* prototype(void) */
2538 #ifndef X_DISPLAY_MISSING
2539 if (adesklets.display && adesklets.window) {
2540 for(i=0,j=0;X_WINDOW_EVENTS[i].name;++i)
2541 if(adesklets.user_event_mask&X_WINDOW_EVENTS[i].mask)
2542 ++j;
2543 command_printf("%d events caught\n",j);
2544 for(i=0;X_WINDOW_EVENTS[i].name;++i)
2545 if(adesklets.user_event_mask&X_WINDOW_EVENTS[i].mask)
2546 command_printf("%d (%s)\n",i , X_WINDOW_EVENTS[i].name);
2547 } else
2548 #endif
2549 command_error("X connection or window missing\n");
2550 break;
2551 case CMD_EVENTS_GET_ECHO:
2552 /* prototype(void) */
2553 command_ok("events echo %d\n", events_echo);
2554 break;
2555 case CMD_EVENTS_SET_ECHO:
2556 /* prototype(voidvoid) */
2557 if(params->pos>=2) {
2558 if (events_echo!=(i=atoi(params->content[1]))) {
2559 events_echo=i;
2560 if(i)
2561 events_purge();
2564 else
2565 command_error("echo value not given\n");
2566 break;
2567 case CMD_EVENTS_GET_SEND_SIGUSR1:
2568 /* prototype(void) */
2569 command_ok("events send_sigusr1 %d\n",(events_ppid)?1:0);
2570 break;
2571 case CMD_EVENTS_SET_SEND_SIGUSR1:
2572 /* prototype(voidvoid) */
2573 if (params->pos>=2)
2574 events_ppid=(atoi(params->content[1]))?adesklets.ppid:0;
2575 else
2576 command_error("send SIGUSR1 status not given\n");
2577 break;
2578 case CMD_EVENTS_PURGE:
2579 /* prototype(voidvoid) */
2580 command_printf("%d events to purge\n",(events)?events->pos:0);
2581 events_purge();
2582 break;
2583 case CMD_WINDOW_RESET:
2584 /* prototype(enum WINDOW_MANAGER manager) */
2585 if(params->pos>=2) {
2586 for(i=0;WINDOW_MANAGER[i];++i)
2587 if(strncmp(WINDOW_MANAGER[i],params->content[1],
2588 strlen(params->content[1]))==0)
2589 break;
2590 if (adesklets_window_reset((WINDOW_MANAGER[i])?i:
2591 atoi(params->content[1]))) {
2592 if (adesklets_menus_reset()) {
2593 if (!adesklets_images_reset_background(0))
2594 command_error("could not reset background images\n");
2595 } else
2596 command_error("could not reset menus\n");
2597 } else
2598 command_error("could not reset main window\n");
2599 } else
2600 command_error("Window manager status not given\n");
2601 break;
2602 case CMD_WINDOW_SHOW:
2603 /* prototype(void) */
2604 #ifndef X_DISPLAY_MISSING
2605 if (adesklets.display && adesklets.window) {
2606 if (!XMapWindow(adesklets.display,adesklets.window))
2607 command_error("could not map the window\n");
2608 } else
2609 #endif
2610 command_error("X connection or window missing\n");
2611 break;
2612 case CMD_WINDOW_HIDE:
2613 /* prototype(void) */
2614 #ifndef X_DISPLAY_MISSING
2615 if (adesklets.display && adesklets.window) {
2616 if(!XUnmapWindow(adesklets.display,adesklets.window))
2617 command_error("could not unmap the window\n");
2618 } else
2619 #endif
2620 command_error("X connection or window missing\n");
2621 break;
2622 case CMD_WINDOW_RESIZE:
2623 /* prototype(int width, int height) */
2624 if (params->pos>=3) {
2625 if((i=atoi(params->content[1]))>0 &&
2626 (j=atoi(params->content[2]))>0) {
2627 #ifndef X_DISPLAY_MISSING
2628 if (adesklets.display && adesklets.window) {
2629 if (!xwindow_resize_window(adesklets.display,adesklets.window,
2630 adesklets.params,i,j,0))
2631 command_error("did not resize window\n");
2632 } else {
2633 #endif
2634 if (!adesklets_images_reset_background(1,i,j))
2635 command_error("no window, and could not resize images\n");
2636 #ifndef X_DISPLAY_MISSING
2638 #endif
2639 } else command_error("resize out of range\n");
2640 } else command_error("resize dimensions no given\n");
2641 break;
2642 case CMD_WINDOW_GET_TRANSPARENCY:
2643 /* prototype(void) */
2644 command_ok("window transparency %d\n",adesklets.transparency);
2645 break;
2646 case CMD_WINDOW_GET_BACKGROUND_GRAB:
2647 /* prototype(void) */
2648 if(X_DISPLAY_SUPPORT && adesklets.display && adesklets.window)
2649 command_ok("window backgroundgrab %d\n",adesklets.background_grab);
2650 else
2651 command_error(
2652 "background grab irrelevant - no X window connection or window\n");
2653 break;
2654 case CMD_WINDOW_GET_BACKGROUND_IMAGE:
2655 /* prototype(void) */
2656 if(X_DISPLAY_SUPPORT && adesklets.display && adesklets.window)
2657 command_ok("background image %d\n",
2658 (adesklets.user_background_image!=-1)?
2659 adesklets.user_background_image:1);
2660 else
2661 command_error(
2662 "background window irrelevant - no X window connection or window\n");
2663 break;
2664 case CMD_WINDOW_GET_MANAGED_STATUS:
2665 /* prototype(void) */
2666 #ifndef X_DISPLAY_MISSING
2667 if(adesklets.display && adesklets.window) {
2668 command_ok("window managedstatus %d (%s)\n",
2669 adesklets.managed,
2670 WINDOW_MANAGER[adesklets.managed]);
2671 } else
2672 command_error("X connection or window missing\n");
2673 #else
2674 command_error("X connection or window missing\n");
2675 #endif
2676 break;
2677 case CMD_WINDOW_SET_TRANSPARENCY:
2678 /* prototype(bool transparency) */
2679 if (params->pos>=2) {
2680 i=atoi((char*)params->content[1]);
2681 if (adesklets.transparency!=i) {
2682 adesklets.transparency=i;
2683 /* If there is a chance, invalidate the entire window */
2684 #ifndef X_DISPLAY_MISSING
2685 xwindow_window_size(adesklets.display,adesklets.window,
2686 &width,&height);
2687 updates = imlib_update_append_rect(updates,
2688 0,0,(int)width,(int)height);
2689 #endif
2691 } else command_error("transparency value not given\n");
2692 break;
2693 case CMD_WINDOW_SET_BACKGROUND_GRAB:
2694 /* prototype(bool grab) */
2695 if (params->pos>=2) {
2696 if (adesklets.background_grab!=(i=atoi(params->content[1]))) {
2697 if ((adesklets.background_grab=i))
2698 adesklets_images_reset_background(0);
2699 else {
2700 xwindow_context_save(IMLIB_IMAGE|IMLIB_BLEND|IMLIB_COLOR);
2701 imlib_context_set_image(adesklets.images->content[1]);
2702 imlib_context_set_color(0,0,0,255);
2703 imlib_context_set_blend(0);
2704 imlib_image_fill_rectangle(0,0,
2705 imlib_image_get_width(),
2706 imlib_image_get_height());
2707 xwindow_context_restore();
2710 #ifndef X_DISPLAY_MISSING
2711 xwindow_window_size(adesklets.display,adesklets.window,
2712 &width,&height);
2713 updates = imlib_update_append_rect(updates,
2714 0,0,(int)width,(int)height);
2715 #endif
2717 } else
2718 command_error("background grab value not given\n");
2719 break;
2720 case CMD_WINDOW_SET_BACKGROUND_IMAGE:
2721 /* prototype(int image) */
2722 if (X_DISPLAY_SUPPORT && adesklets.display && adesklets.window) {
2723 if(params->pos>=2) {
2724 if((i=atoi(params->content[1]))>=0 && i<adesklets.images->pos) {
2725 if(i!=0) {
2726 xwindow_context_save(IMLIB_IMAGE);
2727 imlib_context_set_image(adesklets.images->content[0]);
2728 j=imlib_image_get_width();
2729 k=imlib_image_get_height();
2730 if(i!=1) {
2731 imlib_context_set_image(adesklets.images->content[i]);
2732 x=imlib_image_get_width();
2733 y=imlib_image_get_height();
2734 if (x==j && y==k) {
2735 adesklets.user_background_image=i;
2736 updates = imlib_update_append_rect(updates,
2737 0,0,x,y);
2739 else
2740 command_error("incorrect dimensions image\n");
2741 } else {
2742 /* Drop silently reset to actual foreground */
2743 adesklets.user_background_image=-1;
2744 updates = imlib_update_append_rect(updates,
2745 0,0,j,k);
2747 xwindow_context_restore();
2748 } else
2749 command_error(
2750 "foreground image cannot be selected as background\n");
2751 } else
2752 command_error("image ID %d out of range\n",i);
2753 } else
2754 command_error("background image ID not given\n");
2755 } else
2756 command_error(
2757 "background window irrelevant - no X window connection or window\n");
2758 break;
2759 case CMD_SCREEN_GET_WIDTH:
2760 /* prototype(void) */
2761 #ifndef X_DISPLAY_MISSING
2762 if (adesklets.display) {
2763 command_ok("screen width %d\n",
2764 WidthOfScreen(ScreenOfDisplay(adesklets.display,
2765 adesklets.params->scr)));
2766 } else
2767 command_error("X connection missing\n");
2768 #else
2769 command_error("X connection missing\n");
2770 #endif
2771 break;
2772 case CMD_SCREEN_GET_HEIGHT:
2773 /* prototype(void) */
2774 #ifndef X_DISPLAY_MISSING
2775 if(adesklets.display) {
2776 command_ok("screen height %d\n",
2777 HeightOfScreen(ScreenOfDisplay(adesklets.display,
2778 adesklets.params->scr)));
2779 } else
2780 command_error("X connection missing\n");
2781 #else
2782 command_error("X connection missing\n");
2783 #endif
2784 break;
2785 case CMD_SCREEN_GET_DEPTH:
2786 /* prototype(void) */
2787 if(adesklets.display)
2788 command_ok("screen depth %d\n",adesklets.depth);
2789 else
2790 command_error("X connection missing\n");
2791 break;
2792 case CMD_GET_CHARSET:
2793 /* prototype(void) */
2794 #ifdef HAVE_ICONV_H
2795 if (command.from_page)
2796 command_ok("charset %s\n",command.from_page);
2797 else
2798 #endif
2799 command_ok("charset -1 (unset)\n");
2800 break;
2801 case CMD_SET_CHARSET:
2802 /* prototype(const char * charset) */
2803 #ifdef HAVE_ICONV_H
2804 if (params->pos>=2) {
2805 if ((cd=iconv_open("UTF8",params->content[1]))!=(iconv_t)(-1)) {
2806 if (command.cd) {
2807 iconv_close(command.cd);
2808 command.cd=NULL;
2810 if (command.from_page) {
2811 free(command.from_page);
2812 command.from_page=NULL;
2814 command.from_page=dupstr(params->content[1]);
2815 command.cd=cd;
2816 } else
2817 command_error("could not establish conversion from '%s' to 'UTF8'\n",
2818 params->content[1]);
2819 } else {
2820 if (command.cd) {
2821 iconv_close(command.cd);
2822 command.cd=NULL;
2824 if (command.from_page) {
2825 free(command.from_page);
2826 command.from_page=NULL;
2828 command_ok("charset -1 (unset)\n");
2830 #else
2831 command_error("charset conversion not compiled in\n");
2832 #endif
2833 break;
2834 case CMD_CHARSET_STATUS:
2835 /* prototype(void) */
2836 #ifdef HAVE_ICONV_H
2837 command_ok("charset_status 1\n");
2838 #else
2839 command_ok("charset_status 0 (charset conversion not compiled in)\n");
2840 #endif
2841 break;
2842 case CMD_X_STATUS:
2843 /* prototype(void) */
2844 #ifndef X_DISPLAY_MISSING
2845 command_ok("x_status %d (%s%s')\n",(adesklets.display)?1:0,
2846 (adesklets.display)?"connected to '":"disconnected from '",
2847 XDisplayName(NULL));
2848 #else
2849 command_ok("x_status 0 (X Window support not compiled in)\n");
2850 #endif
2851 break;
2852 case CMD_QUIT:
2853 /* prototype(void) */
2854 command_ok("quitting...\n");
2855 adesklets.quit_flag=1;
2856 break;
2857 default:
2858 if(blank_line(command.line))
2859 command.message_out=1;
2860 else
2861 command_error("syntax error\n");
2862 } /* switch(command_type) */
2863 } /* if command.recording */
2864 if (!command.message_out) command_ok("%s\n",command.line);
2865 vector_free(params);
2866 free(command.line);
2867 command.ready=0; ++command.rank;
2868 if (command.interactive && !command.replay_pos &&
2869 !adesklets.quit_flag && !adesklets.restart_flag)
2870 command_interpreter_reset();
2871 } else {printf("\n"); adesklets.quit_flag=1;} /* if (command.line) */
2872 } /* if(command.ready) */
2874 #ifndef X_DISPLAY_MISSING
2875 while(adesklets.display && adesklets.window &&
2876 (XCheckWindowEvent(adesklets.display,
2877 DefaultRootWindow(adesklets.display),
2878 PropertyChangeMask, &ev) ||
2879 XCheckWindowEvent(adesklets.display,adesklets.window,
2880 adesklets.event_mask,&ev) ||
2881 XCheckTypedWindowEvent(adesklets.display,adesklets.window,
2882 ClientMessage,&ev))) {
2883 switch(ev.type) {
2884 case Expose:
2885 /* Refresh updates list */
2886 updates = imlib_update_append_rect(updates,
2887 ev.xexpose.x,ev.xexpose.y,
2888 ev.xexpose.width,ev.xexpose.height);
2889 break;
2890 case PropertyNotify:
2891 /* This event is generated from root window only:
2892 we use it to check for dynamic root window background change,
2893 as enlightment has used it for years. Look at
2894 xwindow_updated_background() for details */
2895 if (ev.xproperty.atom != None &&
2896 ev.xproperty.atom == XInternAtom (adesklets.display,
2897 "_XROOTPMAP_ID", True) &&
2898 adesklets.background_grab &&
2899 xwindow_updated_background(adesklets.display,
2900 ev.xproperty.window,
2901 ev.xproperty.atom))
2902 /* Recompute the background images */
2903 adesklets_images_reset_background(0);
2905 /* Because the setting of background_pixmap as ParentRelative
2906 on the main window, there is no need to invalidate
2907 it here: an Expose event will be automatically generated. */
2908 break;
2909 case ButtonPress:
2910 /* Fire default menu on left button click */
2911 if(ev.xbutton.button==3) {
2912 #ifdef CONTROL_ON_CONTEXT_MENU
2913 if (ev.xbutton.state & ControlMask) {
2914 #endif
2915 if ((adesklets_menu_fire(0,&menu_str)) &&
2916 (adesklets.user_event_mask&MenuFireMask))
2917 event("menufire 0 %s\n",menu_str);
2918 #ifdef CONTROL_ON_CONTEXT_MENU
2919 } else {
2920 ev.xbutton.window = adesklets.root ;
2921 XSendEvent(adesklets.display, ev.xbutton.window,
2922 False, ButtonPressMask, &ev);
2923 debug("menu call redirected to root\n");
2925 #endif
2926 } else
2927 if(adesklets.user_event_mask&ButtonPressMask)
2928 event("buttonpress %d %d %d\n",
2929 ev.xbutton.x,ev.xbutton.y,ev.xbutton.button);
2930 break;
2931 case ButtonRelease:
2932 if(ev.xbutton.button!=3)
2933 event("buttonrelease %d %d %d\n",
2934 ev.xbutton.x,ev.xbutton.y,ev.xbutton.button);
2935 break;
2936 case MotionNotify:
2937 event("motionnotify %d %d\n",
2938 ev.xmotion.x, ev.xmotion.y);
2939 break;
2940 case EnterNotify:
2941 event("enternotify %d %d\n",
2942 ev.xcrossing.x, ev.xcrossing.y);
2943 break;
2944 case LeaveNotify:
2945 event("leavenotify %d %d\n",
2946 ev.xcrossing.x, ev.xcrossing.y);
2947 break;
2948 case ConfigureNotify:
2949 if (ev.xconfigure.window==adesklets.window)
2950 if (xwindow_window_moved_or_resized(ev.xconfigure.x,
2951 ev.xconfigure.y,
2952 ev.xconfigure.width,
2953 ev.xconfigure.height))
2954 adesklets_images_reset_background(0);
2955 break;
2956 case ClientMessage:
2957 /* Check for the "WM_WINDOW_DELETE" protocol */
2958 if (ev.xclient.data.l[0] == XInternAtom(adesklets.display,
2959 "WM_DELETE_WINDOW",
2960 False)) {
2961 debug("Message from window manager: quitting!\n");
2962 adesklets.user_quit_flag=adesklets.quit_flag=1;
2963 } else
2964 debug("Unknown client message sent.\n");
2965 break;
2966 default:
2967 /* Untreated cases */
2968 break;
2972 /* Now, performs main window updates as needed */
2973 xwindow_update_window(adesklets.window, &updates,
2974 adesklets.images->content[
2975 (adesklets.user_background_image!=-1)?
2976 adesklets.user_background_image:1],
2977 adesklets.images->content[0],
2978 adesklets.transparency);
2979 #endif
2980 if(updates) imlib_updates_free(updates);
2982 } while(!adesklets.quit_flag && !adesklets.restart_flag &&
2983 (command_replayer() || command_interpreter(adesklets.polling)));
2986 /*----------------------------------------------------------------------------*/
2987 int adesklets_free(void)
2989 int i, fd_null;
2990 struct flock lock;
2992 debug("---------------------------------------------------------------\n");
2993 /* Ultimate update : take care of potential applet removal
2994 if user asked for it. */
2995 adesklets.params->no_update|=adesklets.user_quit_flag;
2996 cfgfile_update(adesklets.params);
2998 /* X Windows cleanup */
2999 #ifndef X_DISPLAY_MISSING
3000 if(adesklets.display) {
3001 if(adesklets.window) {
3002 XUnmapWindow(adesklets.display,adesklets.window);
3003 XDestroyWindow(adesklets.display,adesklets.window);
3005 XCloseDisplay(adesklets.display);
3007 #endif
3009 /* For terminal reset, if it was not cleanly performed
3010 (will happen when quitting from the default left click
3011 menu, for instance) */
3012 rl_callback_handler_remove();
3014 /* Send SIGTERM notification signal to parent process:
3015 in all case but restart, adesklets do not
3016 go further to ensure parent termination. */
3017 kill(adesklets.ppid,SIGTERM);
3019 /* if Lock exist: handle possible restart */
3020 if(adesklets.lock) {
3021 if(adesklets.restart_flag) {
3022 /* Wait for adesklets parent process to exit
3023 SIGKILL_TIMEOUT seconds, then send a SIGKILL. */
3024 for(i=0;i<SIGKILL_TIMEOUT && adesklets.ppid==getppid();++i)
3025 sleep(1);
3026 if (i==SIGKILL_TIMEOUT) kill(adesklets.ppid,SIGKILL);
3027 while(adesklets.ppid==getppid()) sleep(1);
3028 if (fork()==0) {
3029 /* Redirect stdout and stderr to /dev/null to avoid
3030 output buffer overflow */
3031 if ((fd_null=open("/dev/null",O_WRONLY))>=0) {
3032 dup2(fd_null,1);
3033 dup2(fd_null,2);
3034 close(fd_null);
3036 execl(adesklets.params->applet,
3037 adesklets.params->applet,
3038 NULL);
3039 /* debug("Restart: could not exec `%s'",adesklets.params->applet); */
3040 exit(EXIT_FAILURE);
3044 /* Release the lock */
3045 lock.l_type=F_UNLCK;
3046 lock.l_whence=SEEK_SET;
3047 lock.l_start=0;
3048 lock.l_len=0;
3049 fcntl(fileno(adesklets.lock),F_SETLK,&lock);
3050 fclose(adesklets.lock);
3052 /* Try to unlink the lock file:
3053 thanks to POSIX, this will fail gracefully
3054 if a process is still using the file */
3055 unlink(adesklets.lock_filename);
3058 /* Free structures */
3059 if(events) vector_free(events);
3060 adesklets.menus=vector_free(adesklets.menus);
3061 adesklets.images=vector_free(adesklets.images);
3062 adesklets.fonts=vector_free(adesklets.fonts);
3063 adesklets.color_ranges=vector_free(adesklets.color_ranges);
3064 adesklets.color_modifiers=vector_free(adesklets.color_modifiers);
3065 adesklets.filters=vector_free(adesklets.filters);
3066 adesklets.polygons=vector_free(adesklets.polygons);
3067 adesklets.variables=vector_free(adesklets.variables);
3069 return !adesklets.menus &&
3070 !adesklets.images &&
3071 !adesklets.fonts &&
3072 !adesklets.color_ranges &&
3073 !adesklets.color_modifiers &&
3074 !adesklets.filters &&
3075 !adesklets.polygons &&
3076 !adesklets.variables;
3079 /*----------------------------------------------------------------------------*/
3080 /* Signal wrapper for adesklets_free()
3082 void
3083 termination_handler(int signum)
3085 exit((adesklets_free())?EXIT_SUCCESS:EXIT_FAILURE);
3088 /*----------------------------------------------------------------------------*/
3089 /* Since we cannot verify if applet is a script of a binary without trying
3090 to execute it, we require it to have both read and execute permissions for
3091 the current user... Better _portable_ solution is welcomed.
3093 int
3094 adesklets_valid_desklet(char * applet, int register_flag)
3096 int result = 0;
3098 if(applet)
3099 if((register_flag && applet[0]=='/') || !register_flag)
3100 result=(access(applet,R_OK|X_OK)==0);
3101 return result;
3104 /*----------------------------------------------------------------------------*/
3105 /* Our image generator function (have a look at command.c) */
3106 char *
3107 image_generator(const char * text, int state)
3109 return generic_index_generator(text,state,adesklets.images->pos);
3112 /*----------------------------------------------------------------------------*/
3113 /* Our font name generator function (have a look at command.c) */
3114 char *
3115 base_font_generator(const char * text, int state)
3117 char * result;
3118 static int number;
3119 static char ** fonts;
3121 if (!state) {
3122 fonts=imlib_list_fonts(&number);
3124 if(!(result=generic_generator(text,state,fonts,number))) {
3125 imlib_free_font_list(fonts,number);
3127 return result;
3130 /*----------------------------------------------------------------------------*/
3131 char *
3132 base_font_path_generator(const char * text, int state)
3134 static int number;
3135 static char ** font_path;
3137 if (!state) {
3138 font_path=imlib_list_font_path(&number);
3140 return generic_generator(text,state,font_path,number);
3143 /*----------------------------------------------------------------------------*/
3144 char *
3145 font_generator (const char * text, int state)
3147 return generic_index_generator(text,state,adesklets.fonts->pos);
3150 /*----------------------------------------------------------------------------*/
3151 char *
3152 font_generator_with_null (const char * text, int state)
3154 return generic_index_generator_with_null(text,state,adesklets.fonts->pos);
3157 /*----------------------------------------------------------------------------*/
3158 /* Our menu generator function (have a look at command.c) */
3159 char *
3160 menu_generator(const char * text, int state)
3162 return generic_index_generator(text,state,adesklets.menus->pos);
3165 /*----------------------------------------------------------------------------*/
3166 /* Our color ranges generator function (have a look at command.c) */
3167 char *
3168 color_range_generator(const char * text, int state)
3170 return generic_index_generator(text,state,adesklets.color_ranges->pos);
3173 /*----------------------------------------------------------------------------*/
3174 /* Our color ranges generator function (have a look at command.c) */
3175 char *
3176 color_range_generator_with_null(const char * text, int state)
3178 return generic_index_generator_with_null(text,state,
3179 adesklets.color_ranges->pos);
3182 /*----------------------------------------------------------------------------*/
3183 /* Our color modifiers generator function (have a look at command.c) */
3184 char *
3185 color_modifier_generator(const char * text, int state)
3187 return generic_index_generator(text,state,adesklets.color_modifiers->pos);
3190 /*----------------------------------------------------------------------------*/
3191 /* Our color modifiers generator function (have a look at command.c) */
3192 char *
3193 color_modifier_generator_with_null(const char * text, int state)
3195 return generic_index_generator_with_null(text,state,
3196 adesklets.color_modifiers->pos);
3199 /*----------------------------------------------------------------------------*/
3200 /* Our filters generator function (have a look at command.c) */
3201 char *
3202 filter_generator(const char * text, int state)
3204 return generic_index_generator(text,state,adesklets.filters->pos);
3207 /*----------------------------------------------------------------------------*/
3208 /* Our filters generator function (have a look at command.c) */
3209 char *
3210 filter_generator_with_null(const char * text, int state)
3212 return generic_index_generator_with_null(text,state,
3213 adesklets.filters->pos);
3216 /*----------------------------------------------------------------------------*/
3217 /* Our polygon generator function (have a look at command.c) */
3218 char *
3219 polygon_generator(const char * text, int state)
3221 return generic_index_generator(text,state,adesklets.polygons->pos);
3224 /*----------------------------------------------------------------------------*/
3225 /* We have to put this generator here because variables vector is part of
3226 the adesklets structure */
3227 char *
3228 variable_generator(const char * text, int state)
3230 static int list_index, len;
3231 char * name;
3233 if(!state) {
3234 list_index=0;
3235 len=strlen(text);
3238 while (list_index<adesklets.variables->pos) {
3239 name=((var_item*)adesklets.variables->content[list_index])->name;
3240 ++list_index;
3241 if(strncmp(name,text,len)==0)
3242 return dupstr(name);
3245 return NULL;
3248 /*----------------------------------------------------------------------------*/
3250 /* Generic generator mecanism: used for different wrappers.*/
3252 char * generic_generator(const char * text, int state,
3253 char ** names, int number)
3255 static int list_index, len;
3256 char * name;
3258 if(!state) {
3259 list_index=0;
3260 len=strlen(text);
3263 while((number==-1 || list_index<number) &&
3264 (name=names[list_index])) {
3265 ++list_index;
3266 if(strncmp(name,text,len)==0)
3267 return(dupstr(name));
3270 return NULL;