1 /*
2 * Copyright (c) 2003 Sasha Vasko <sasha@aftercode.net>
3 * Copyright (c) 2001 Eric Kowalski <eric@beancrock.net>
4 * Copyright (c) 2001 Ethan Fisher <allanon@crystaltokyo.com>
5 *
6 * This module is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 *
20 */
21
22 /*#define DO_CLOCKING */
23 #define LOCAL_DEBUG
24 #define EVENT_TRACE
25
26 #include "../../configure.h"
27 #include "../../libAfterStep/asapp.h"
28
29 #include <signal.h>
30 #include <unistd.h>
31
32 #include "../../libAfterImage/afterimage.h"
33
34 #include "../../libAfterStep/afterstep.h"
35 #include "../../libAfterConf/afterconf.h"
36 #include "../../libAfterStep/colorscheme.h"
37 #include "../../libAfterStep/module.h"
38 #include "../../libAfterStep/event.h"
39 #include "../../libAfterStep/wmprops.h"
40
41 #include <X11/keysym.h>
42
43 struct
44 {
45 Window main_window ;
46
47 char *doc_str ;
48 char *doc_file;
49 char *img_save;
50 char *img_save_type;
51 char *img_compress;
52 char *cs_save;
53 Bool display ;
54 Bool onroot ;
55 Bool default_only ;
56
57 ARGB32 base_color ;
58 int base_hue, base_sat, base_val ;
59 int angle ;
60
61 ASColorScheme *cs ;
62
63 ASGeometry geometry ;
64 int gravity ;
65
66 Bool user_geometry ;
67
68 ASImage *cs_im ;
69
70 enum
71 {
72 ASC_PARAM_BaseHue =0,
73 ASC_PARAM_BaseSat ,
74 ASC_PARAM_BaseVal ,
75 ASC_PARAM_Angle
76 } curr_param ;
77
78 }ASColorState;
79
ascolor_usage()80 void ascolor_usage()
81 {
82 fprintf( stdout,
83 "ASColor is a simple GUI to create colorschemes for AfterStep.\n"
84 " It writes the result into a file named colorscheme in current directory- \n"
85 "override it with -o option (see below).\n"
86 " There are 4 parameters to the color scheme - Angle, Hue, Saturation and Value.\n"
87 " Pressing arrow keys in ASColor window will change the currently selected parameter.\n"
88 " To select parameter - press 'a', 'h', 's' or 'v' keys.\n"
89 " ASColor will also create .mini file suitable to be used as minipixmap\n"
90 "in the AfterStep menu.\n\n"
91 " Rename and copy both colorscheme and .mini files into ~/.afterstep/colorschemes\n"
92 "directory and refresh AfterStep menu. New entry should show up.\n"
93 "Select it to apply new colorscheme.\n"
94 "\n"
95 "ascolor [-h] [-f file] [-o file] [-s string] [-t type] [-v] [-V]"
96 #ifndef X_DISPLAY_MISSING
97 " [-n] [-r]"
98 #endif /* X_DISPLAY_MISSING */
99 "\n"
100 " -h --help display this help and exit\n"
101 " -f --file file an XML file to use as input\n"
102 #ifndef X_DISPLAY_MISSING
103 " -n --no-display don't display the final image\n"
104 " -r --root-window draw result image on root window\n"
105 #endif /* X_DISPLAY_MISSING */
106 " -o --output file output to file\n"
107 " -s --string string an XML string to use as input\n"
108 " -t --type type type of file to output to\n"
109 " -c --compress level compression level\n"
110 " -v --version display version and exit\n"
111 " -V --verbose increase verbosity\n"
112 " -D --debug show everything and debug messages\n"
113 );
114 }
115
116 /****** ascolor/sample
117 * EXAMPLE
118 * Here is the default script that gets executed by ascompose, if no
119 * parameters are given :
120 * SOURCE
121 */
122 static char* default_doc_str = " \
123 <composite> \
124 <gradient angle=45 width=640 height=480 colors=\"BaseDark BaseLight\"/> \
125 <composite x=20 y=40> \
126 <bevel id=\"inactive_back_beveled\" colors=\"Inactive1Light Inactive1Dark\" border=\"2 2 3 3\" solid=0> \
127 <gradient id=\"inactive_back\" angle=90 width=340 height=25 colors=\"Inactive1Dark Inactive1Light\"/> \
128 </bevel> \
129 <text x=5 y=3 font=\"DefaultBold.ttf\" point=22 fgcolor=\"InactiveText1\">Unfocused title bar text</text> \
130 </composite> \
131 <composite x=10 y=290> \
132 <recall srcid=\"inactive_back_beveled\"/> \
133 <text x=5 y=3 font=\"DefaultBold.ttf\" point=22 fgcolor=\"InactiveText1\">Unfocused title bar text</text> \
134 </composite> \
135 <composite x=290 y=250> \
136 <recall srcid=\"inactive_back_beveled\"/> \
137 <text x=5 y=3 font=\"DefaultBold.ttf\" point=22 fgcolor=\"InactiveText1\">Unfocused title bar text</text> \
138 </composite> \
139 <composite x=250 y=80> \
140 <bevel colors=\"Inactive2Light Inactive2Dark\" border=\"2 2 3 3\" solid=0> \
141 <gradient angle=90 width=350 height=25 colors=\"Inactive2Dark Inactive2Light\"/> \
142 </bevel> \
143 <text x=5 y=3 font=\"DefaultBold.ttf\" point=22 fgcolor=\"InactiveText2\">Sticky title bar text</text> \
144 </composite> \
145 <composite x=150 y=60> \
146 <bevel colors=\"ActiveLight ActiveDark\" border=\"2 2 3 3\" solid=0> \
147 <gradient angle=90 width=400 height=25 colors=\"ActiveDark ActiveLight\"/> \
148 </bevel> \
149 <text x=5 y=3 font=\"DefaultBold.ttf\" point=22 fgcolor=\"ActiveText\">Focused title bar text</text> \
150 </composite> \
151 \
152 <composite x=50 y=200> \
153 <bevel colors=\"HighInactiveLight HighInactiveDark\" border=\"2 2 3 3\" solid=0> \
154 <gradient angle=90 width=180 height=20 colors=\"HighInactiveDark HighInactiveLight\"/> \
155 </bevel> \
156 <text x=5 y=3 font=\"DefaultBold.ttf\" point=20 fgcolor=\"InactiveText1\">Unfocused menu</text> \
157 </composite> \
158 <composite x=50 y=220> \
159 <bevel id=\"inactive_menu_item_back\" colors=\"HighInactiveBackLight HighInactiveBackDark\" border=\"2 2 3 3\" solid=0> \
160 <gradient angle=90 width=180 height=20 colors=\"HighInactiveBackDark HighInactiveBackLight\"/> \
161 </bevel> \
162 <text x=5 y=3 font=\"DefaultBoldOblique.ttf\" point=20 fgcolor=\"HighInactiveText\">Menu item 1</text> \
163 </composite> \
164 <composite x=50 y=240> \
165 <recall srcid=\"inactive_menu_item_back\"/> \
166 <text x=5 y=3 font=\"DefaultBoldOblique.ttf\" point=20 fgcolor=\"DisabledText\">Disabled item </text> \
167 </composite> \
168 <composite x=50 y=260> \
169 <recall srcid=\"inactive_menu_item_back\"/> \
170 <text x=5 y=3 font=\"DefaultBoldOblique.ttf\" point=20 fgcolor=\"HighInactiveText\">Menu item 2</text> \
171 </composite> \
172 <composite x=50 y=280> \
173 <recall srcid=\"inactive_menu_item_back\"/> \
174 <text x=5 y=3 font=\"DefaultBoldOblique.ttf\" point=20 fgcolor=\"HighInactiveText\">Menu item 3</text> \
175 </composite> \
176 \
177 <composite x=220 y=230> \
178 <bevel colors=\"HighActiveLight HighActiveDark\" border=\"2 2 3 3\" solid=0> \
179 <gradient angle=90 width=180 height=20 colors=\"HighActiveDark HighActiveLight\"/> \
180 </bevel> \
181 <text x=5 y=3 font=\"DefaultBold.ttf\" point=20 fgcolor=\"ActiveText\">Focused menu</text> \
182 </composite> \
183 <composite x=220 y=250> \
184 <recall srcid=\"inactive_menu_item_back\"/> \
185 <text x=5 y=3 font=\"DefaultBoldOblique.ttf\" point=20 fgcolor=\"HighInactiveText\">Menu item 1</text> \
186 </composite> \
187 <composite x=220 y=270> \
188 <bevel colors=\"HighActiveBackLight HighActiveBackDark\" border=\"2 2 3 3\" solid=0> \
189 <gradient angle=90 width=180 height=20 colors=\"HighActiveBackDark HighActiveBackLight\"/> \
190 </bevel> \
191 <text x=5 y=3 font=\"DefaultBoldOblique.ttf\" point=20 fgcolor=\"HighActiveText\">Selected item</text> \
192 </composite> \
193 <composite x=220 y=290> \
194 <recall srcid=\"inactive_menu_item_back\"/> \
195 <text x=5 y=3 font=\"DefaultBoldOblique.ttf\" point=20 fgcolor=\"DisabledText\">Disabled item </text> \
196 </composite> \
197 \
198 <composite x=320 y=380> \
199 <bevel colors=\"HighInactiveLight HighInactiveDark\" border=\"2 2 3 3\" solid=0> \
200 <gradient angle=90 width=180 height=20 colors=\"HighInactiveDark HighInactiveLight\"/> \
201 </bevel> \
202 <text x=5 y=3 font=\"DefaultBold.ttf\" point=20 fgcolor=\"InactiveText1\">Unfocused menu</text> \
203 </composite> \
204 <composite x=320 y=400> \
205 <recall srcid=\"inactive_menu_item_back\"/> \
206 <text x=5 y=3 font=\"DefaultBoldOblique.ttf\" point=20 fgcolor=\"DisabledText\">Disabled item </text> \
207 </composite> \
208 <composite x=320 y=420> \
209 <recall srcid=\"inactive_menu_item_back\"/> \
210 <text x=5 y=3 font=\"DefaultBoldOblique.ttf\" point=20 fgcolor=\"HighInactiveText\">Menu item 2</text> \
211 </composite> \
212 <composite x=320 y=440> \
213 <recall srcid=\"inactive_menu_item_back\"/> \
214 <text x=5 y=3 font=\"DefaultBoldOblique.ttf\" point=20 fgcolor=\"HighInactiveText\">Menu item 3</text> \
215 </composite> \
216 \
217 </composite> \
218 ";
219 /*******/
220 void GetBaseOptions (const char *filename);
221 Window create_main_window();
222 void HandleEvents();
223 void do_colorscheme();
224 void do_change_param( int val );
225 void DispatchEvent (ASEvent * event);
226
227 char *default_cs_save = "colorscheme";
228
main(int argc,char ** argv)229 int main(int argc, char** argv)
230 {
231 int i;
232
233 /* Save our program name - for error messages */
234 InitMyApp (CLASS_ASCOLOR, argc, argv, NULL, ascolor_usage, 0 );
235
236 memset( &ASColorState, 0x00, sizeof(ASColorState ));
237 ASColorState.doc_str = default_doc_str;
238 ASColorState.cs_save = default_cs_save;
239 ASColorState.display = 1;
240 ASColorState.base_color = 0xff555577;
241 ASColorState.angle = ASCS_DEFAULT_ANGLE ;
242
243 /* Parse command line. */
244 for (i = 1 ; i < argc ; i++) {
245 if( argv[i] == NULL )
246 continue;
247 if ((!strcmp(argv[i], "--base_color") || !strcmp(argv[i], "-b")) && i+1 < argc) {
248 parse_argb_color( argv[++i], &(ASColorState.base_color) );
249 show_progress ( "base color set to #%lX", (ASColorState.base_color) );
250 } else if ((!strcmp(argv[i], "--angle") || !strcmp(argv[i], "-a")) && i+1 < argc) {
251 ASColorState.angle = atoi(argv[++i]);
252 } else if ((!strcmp(argv[i], "--file") || !strcmp(argv[i], "-f")) && i < argc + 1) {
253 ASColorState.doc_file = argv[++i];
254 } else if ((!strcmp(argv[i], "--string") || !strcmp(argv[i], "-s")) && i < argc + 1) {
255 ASColorState.doc_str = argv[++i];
256 } else if ((!strcmp(argv[i], "--save-image") || !strcmp(argv[i], "-i")) && i < argc + 1) {
257 ASColorState.img_save = argv[++i];
258 } else if ((!strcmp(argv[i], "--type") || !strcmp(argv[i], "-t")) && i < argc + 1) {
259 ASColorState.img_save_type = argv[++i];
260 } else if ((!strcmp(argv[i], "--compress") || !strcmp(argv[i], "-c")) && i < argc + 1) {
261 ASColorState.img_compress = argv[++i];
262 } else if ((!strcmp(argv[i], "--output") || !strcmp(argv[i], "-o")) && i < argc + 1) {
263 ASColorState.cs_save = argv[++i];
264 } else if (!strcmp(argv[i], "--no-display") || !strcmp(argv[i], "-n")) {
265 ASColorState.display = 0;
266 } else if ((!strcmp(argv[i], "--root-window") || !strcmp(argv[i], "-r")) && i < argc + 1) {
267 ASColorState.onroot = 1;
268 } else if ((!strcmp(argv[i], "--default-scheme") || !strcmp(argv[i], "-z")) && i < argc + 1) {
269 ASColorState.default_only = 1;
270 }
271 }
272
273 /* Load the document from file, if one was given. */
274 if (ASColorState.doc_file)
275 {
276 ASColorState.doc_str = load_file(ASColorState.doc_file);
277 if (!ASColorState.doc_str)
278 {
279 show_error("Unable to load file [%s]: %s.", ASColorState.doc_file, strerror(errno));
280 exit(1);
281 }
282 }
283 /* Automagically determine the output type, if none was given. */
284 if (ASColorState.img_save && !ASColorState.img_save_type)
285 {
286 ASColorState.img_save_type = strrchr(ASColorState.img_save, '.');
287 if (ASColorState.img_save_type)
288 ASColorState.img_save_type++;
289 }
290
291
292 if( ASColorState.display )
293 {
294 ConnectX( ASDefaultScr, 0 );
295 ConnectAfterStep ( 0, 0 );
296 LoadBaseConfig (GetBaseOptions);
297 }else
298 {
299 Scr.asv = create_asvisual( NULL, 0, 0, NULL );
300 }
301
302 if( !get_flags( ASColorState.geometry.flags, WidthValue ) )
303 ASColorState.geometry.width = 640 ;
304 if( !get_flags( ASColorState.geometry.flags, HeightValue ) )
305 ASColorState.geometry.height = 480 ;
306 if( !get_flags( ASColorState.geometry.flags, XValue ) )
307 ASColorState.geometry.x = (Scr.MyDisplayWidth - ASColorState.geometry.width)/2 ;
308 if( !get_flags( ASColorState.geometry.flags, YValue ) )
309 ASColorState.geometry.y = (Scr.MyDisplayHeight - ASColorState.geometry.height)/2 ;
310
311
312
313 if( ASColorState.display )
314 ASColorState.main_window = create_main_window();
315
316 {
317 CARD32 hue16, sat16, val16 ;
318
319 hue16 = rgb2hsv( ARGB32_RED16(ASColorState.base_color), ARGB32_GREEN16(ASColorState.base_color), ARGB32_BLUE16(ASColorState.base_color), &sat16, &val16 );
320
321 ASColorState.base_hue = hue162degrees(hue16);
322 ASColorState.base_sat = val162percent(sat16);
323 ASColorState.base_val = val162percent(val16);
324 }
325 do_colorscheme();
326
327 if( ASColorState.display )
328 HandleEvents();
329 return 0;
330 }
331
332 void
GetBaseOptions(const char * filename)333 GetBaseOptions (const char *filename)
334 {
335 START_TIME(started);
336
337 ReloadASEnvironment( NULL, NULL, NULL, False, False );
338
339 SHOW_TIME("BaseConfigParsingTime",started);
340 }
341
342 void
DeadPipe(int nonsense)343 DeadPipe (int nonsense)
344 {
345 FreeMyAppResources();
346
347 #ifdef DEBUG_ALLOCS
348 print_unfreed_mem ();
349 #endif /* DEBUG_ALLOCS */
350
351 XFlush (dpy); /* need this for SetErootPixmap to take effect */
352 XCloseDisplay (dpy); /* need this for SetErootPixmap to take effect */
353 exit (0);
354 }
355
356 void
HandleEvents()357 HandleEvents()
358 {
359 ASEvent event;
360 Bool has_x_events = False ;
361 while (True)
362 {
363 while((has_x_events = XPending (dpy)))
364 {
365 if( ASNextEvent (&(event.x), True) )
366 {
367 event.client = NULL ;
368 setup_asevent_from_xevent( &event );
369 DispatchEvent( &event );
370 }
371 }
372 module_wait_pipes_input ( NULL );
373 }
374 }
375
376 void
DispatchEvent(ASEvent * event)377 DispatchEvent (ASEvent * event)
378 {
379 SHOW_EVENT_TRACE(event);
380
381 event->client = NULL ;
382 event->widget = NULL ;
383
384 switch (event->x.type)
385 {
386 case ConfigureNotify:
387 break;
388 case KeyPress :
389 {
390 int val = 10 ;
391 if( (event->x.xkey.state&ControlMask) )
392 val = 1 ;
393 LOCAL_DEBUG_OUT( "keysym = 0x%lX", XLookupKeysym (&(event->x.xkey),0) );
394 switch( XLookupKeysym (&(event->x.xkey), 0) )
395 {
396 case XK_a : ASColorState.curr_param = ASC_PARAM_Angle ;
397 do_colorscheme();
398 break ;
399 case XK_h : ASColorState.curr_param = ASC_PARAM_BaseHue ;
400 do_colorscheme();
401 break ;
402 case XK_s : ASColorState.curr_param = ASC_PARAM_BaseSat ;
403 do_colorscheme();
404 break ;
405 case XK_v : ASColorState.curr_param = ASC_PARAM_BaseVal ;
406 do_colorscheme();
407 break ;
408 case XK_Left :
409 do_change_param( -val );
410 break ;
411 case XK_Right :
412 do_change_param( val );
413 break ;
414 }
415 }
416 break ;
417 case KeyRelease :
418 break ;
419 case ButtonPress:
420 {
421 int val = 10 ;
422 if( (event->x.xbutton.state&ControlMask) )
423 val = 1 ;
424 if( event->x.xbutton.button == Button1 )
425 val = -val ;
426 do_change_param(val);
427 }
428 break;
429 case ButtonRelease:
430 break;
431 case ClientMessage:
432 LOCAL_DEBUG_OUT("ClientMessage(\"%s\",data=(%lX,%lX,%lX,%lX,%lX)", XGetAtomName( dpy, event->x.xclient.message_type ), event->x.xclient.data.l[0], event->x.xclient.data.l[1], event->x.xclient.data.l[2], event->x.xclient.data.l[3], event->x.xclient.data.l[4]);
433 if ( event->x.xclient.format == 32 &&
434 event->x.xclient.data.l[0] == _XA_WM_DELETE_WINDOW )
435 {
436 DeadPipe(0);
437 }else if( event->x.xclient.format == 32 &&
438 event->x.xclient.message_type == _AS_BACKGROUND && event->x.xclient.data.l[1] != None )
439 {
440 }
441
442 break;
443 case PropertyNotify:
444 if( event->x.xproperty.atom == _XROOTPMAP_ID && event->w == Scr.Root )
445 {
446 LOCAL_DEBUG_OUT( "root background updated!%s","");
447 safe_asimage_destroy( Scr.RootImage );
448 Scr.RootImage = NULL ;
449 }
450 break;
451 default:
452 return;
453 }
454 }
455
456
457 Window
create_main_window()458 create_main_window()
459 {
460 Window w;
461 XSizeHints shints;
462 ExtendedWMHints extwm_hints ;
463 int x, y ;
464 int width = ASColorState.geometry.width;
465 int height = ASColorState.geometry.height;
466 XSetWindowAttributes attr;
467
468 LOCAL_DEBUG_OUT("configured geometry is %dx%d%+d%+d", width, height, ASColorState.geometry.x, ASColorState.geometry.y );
469 switch( ASColorState.gravity )
470 {
471 case NorthEastGravity :
472 x = Scr.MyDisplayWidth - width + ASColorState.geometry.x ;
473 y = ASColorState.geometry.y ;
474 break;
475 case SouthEastGravity :
476 x = Scr.MyDisplayWidth - width + ASColorState.geometry.x ;
477 y = Scr.MyDisplayHeight - height + ASColorState.geometry.y ;
478 break;
479 case SouthWestGravity :
480 x = ASColorState.geometry.x ;
481 y = Scr.MyDisplayHeight - height + ASColorState.geometry.y ;
482 break;
483 case NorthWestGravity :
484 default :
485 x = ASColorState.geometry.x ;
486 y = ASColorState.geometry.y ;
487 break;
488 }
489 attr.event_mask = StructureNotifyMask|ButtonPressMask|KeyPressMask|ButtonReleaseMask|PointerMotionMask|PropertyChangeMask ;
490 w = create_visual_window( Scr.asv, Scr.Root, x, y, width, height, 4, InputOutput, CWEventMask, &attr);
491 set_client_names( w, MyName, MyName, CLASS_ASCOLOR, MyName );
492
493 Scr.RootClipArea.x = x;
494 Scr.RootClipArea.y = y;
495 Scr.RootClipArea.width = width;
496 Scr.RootClipArea.height = height;
497
498 shints.flags = USSize|PMinSize|PResizeInc|PWinGravity;
499 if( ASColorState.user_geometry )
500 shints.flags |= USPosition ;
501 else
502 shints.flags |= PPosition ;
503
504 shints.min_width = 640;
505 shints.min_height = 480;
506 shints.width_inc = 1;
507 shints.height_inc = 1;
508 shints.win_gravity = ASColorState.gravity ;
509
510 extwm_hints.pid = getpid();
511 extwm_hints.flags = EXTWM_PID|EXTWM_TypeSet ;
512 extwm_hints.type_flags = EXTWM_TypeMenu ;
513
514 set_client_hints( w, NULL, &shints, AS_DoesWmDeleteWindow, &extwm_hints );
515 set_client_cmd (w);
516
517 /* showing window to let user see that we are doing something */
518 XMapRaised (dpy, w);
519 LOCAL_DEBUG_OUT( "mapping main window at %ux%u%+d%+d", width, height, x, y );
520 /* final cleanup */
521 XFlush (dpy);
522 sleep (1); /* we have to give AS a chance to spot us */
523 /* we will need to wait for PropertyNotify event indicating transition
524 into Withdrawn state, so selecting event mask: */
525 return w ;
526 }
527
528 void
do_colorscheme()529 do_colorscheme()
530 {
531 if( ASColorState.cs )
532 free( ASColorState.cs );
533
534 /* Done with the image, finally. */
535 if( ASColorState.cs_im )
536 {
537 destroy_asimage(&ASColorState.cs_im);
538 ASColorState.cs_im = NULL ;
539 }
540
541 forget_asimage_name( Scr.image_manager, "inactive_back_beveled" );
542 forget_asimage_name( Scr.image_manager, "inactive_back" );
543 forget_asimage_name( Scr.image_manager, "inactive_menu_item_back" );
544
545 /* now we need to calculate color scheme and populate XML env vars with colors */
546 if( ASColorState.default_only )
547 {
548 ASColorState.cs = make_default_ascolor_scheme();
549 ASColorState.default_only = False ;
550 }else
551 ASColorState.cs = make_ascolor_scheme( ASColorState.base_color, ASColorState.angle );
552
553 populate_ascs_colors_rgb( ASColorState.cs );
554 populate_ascs_colors_xml( ASColorState.cs );
555
556 ASColorState.cs_im = compose_asimage_xml(Scr.asv, NULL, NULL, ASColorState.doc_str, ASFLAGS_EVERYTHING, False, None, NULL);
557
558 if( ASColorState.cs_im == NULL )
559 {
560 show_error( "failed to generate colorscheme image. Exiting." );
561 exit(1);
562 }
563
564 /* Save the result image if desired. */
565 if (ASColorState.img_save && ASColorState.img_save_type)
566 {
567 char *fname = ASColorState.img_save;
568 if( strchr( fname ,'%' ) != NULL )
569 {
570 fname = safemalloc( strlen( ASColorState.img_save ) + 64 ) ;
571 sprintf( fname, ASColorState.img_save, ASColorState.cs->main_colors[ASMC_Base] );
572 }
573 if(!save_asimage_to_file(fname, ASColorState.cs_im, ASColorState.img_save_type, ASColorState.img_compress, NULL, 0, 1))
574 show_error("Image Save failed.");
575 else
576 show_progress("Image Save successful.");
577
578 if( fname != ASColorState.img_save )
579 free( fname );
580 }
581
582 /* Save the result colorscheme if desired. */
583 if ( ASColorState.cs_save )
584 {
585 ColorConfig *config = ASColorScheme2ColorConfig( ASColorState.cs );
586 char *fname = ASColorState.cs_save;
587 if( strchr( fname ,'%' ) != NULL )
588 {
589 fname = safemalloc( strlen( ASColorState.cs_save ) + 64 ) ;
590 sprintf( fname, ASColorState.cs_save, ASColorState.cs->main_colors[ASMC_Base] );
591 }
592 if( WriteColorOptions (fname, MyName, config, 0) == 0 )
593 {
594 char *minipixmap_file = safemalloc( strlen( fname ) +6 ) ;
595 FILE *mini_f ;
596 sprintf( minipixmap_file, "%s.mini", fname );
597 show_progress("Color Scheme Saved to \"%s\".", fname);
598 if( (mini_f = fopen( minipixmap_file, "w" )) != NULL )
599 {
600 fprintf( mini_f, "<composite>\n" );
601 fprintf( mini_f, " <gradient width=48 height=48 colors=\"#%8.8lX #%8.8lX\" angle=45/>\n", (unsigned long)ASColorState.cs->main_colors[ASMC_BaseDark], (unsigned long)ASColorState.cs->main_colors[ASMC_BaseLight] );
602 fprintf( mini_f, " <gradient x=10 y=10 width=20 height=10 colors=\"#%8.8lX #%8.8lX\" angle=90 />\n", (unsigned long)ASColorState.cs->main_colors[ASMC_Inactive1Dark], (unsigned long)ASColorState.cs->main_colors[ASMC_Inactive1Light] );
603 fprintf( mini_f, " <gradient x=20 y=20 width=20 height=10 colors=\"#%8.8lX #%8.8lX\" angle=90 />\n", (unsigned long)ASColorState.cs->main_colors[ASMC_ActiveDark], (unsigned long)ASColorState.cs->main_colors[ASMC_ActiveLight] );
604 fprintf( mini_f, " <gradient x=13 y=30 width=20 height=10 colors=\"#%8.8lX #%8.8lX\" angle=90 />\n", (unsigned long)ASColorState.cs->main_colors[ASMC_Inactive2Dark], (unsigned long)ASColorState.cs->main_colors[ASMC_Inactive2Light] );
605 fprintf( mini_f, "</composite>\n" );
606 fclose( mini_f );
607 }
608 free( minipixmap_file );
609 }else
610 show_error("Color Scheme Save to \"%s\" unsuccessful.", fname);
611 if( fname != ASColorState.cs_save )
612 free( fname );
613 }
614
615 /* Display the image if desired. */
616 if (ASColorState.display)
617 {
618 Pixmap p = asimage2pixmap( Scr.asv, Scr.Root, ASColorState.cs_im, NULL, False );
619 char legend_str [256] ;
620 Pixmap legend_p ;
621 ASImage *legend_im ;
622
623 if( ASColorState.base_hue == -1 ||
624 (ASColorState.base_hue == 0 && ASColorState.base_sat == 0 ) )
625 {
626 sprintf( &(legend_str[0]), "<text font=\"DefaultBold.ttf\" fgcolor=white bgcolor=black>Base color : #%8.8lX</text>", (unsigned long)ASColorState.cs->main_colors[ASMC_Base] );
627 }else
628 {
629 char *param_text[] = { "hue", "Saturation", "Value", "Angle" };
630 sprintf( &(legend_str[0]), "<text font=\"DefaultBold.ttf\" fgcolor=white bgcolor=black>"
631 "Base color : #%8.8lX; "
632 "Hue %d; "
633 "Saturation %d; "
634 "Value %d; "
635 "Angle %d; "
636 "[Now Changing (%s)]"
637 "</text>",
638 (unsigned long)ASColorState.cs->main_colors[ASMC_Base],
639 ASColorState.cs->main_hues[ASMC_Base],
640 ASColorState.cs->main_saturations[ASMC_Base],
641 ASColorState.cs->main_values[ASMC_Base],
642 ASColorState.angle,
643 param_text[ASColorState.curr_param]);
644 }
645
646 legend_im = compose_asimage_xml(Scr.asv, NULL, NULL, legend_str, ASFLAGS_EVERYTHING, False, None, NULL);
647 legend_p = asimage2pixmap( Scr.asv, Scr.Root, legend_im, NULL, False );
648
649 XCopyArea( dpy, legend_p, p, DefaultGC(dpy, Scr.screen), 0, 0, legend_im->width, legend_im->height,
650 0, ASColorState.cs_im->height - legend_im->height );
651
652 XSetWindowBackgroundPixmap( dpy, ASColorState.main_window, p );
653 XClearWindow( dpy, ASColorState.main_window );
654 XFlush( dpy );
655 XFreePixmap( dpy, p );
656 XFreePixmap( dpy, legend_p );
657 safe_asimage_destroy( legend_im );
658 }
659 }
660
661 #define normalize_percent_val(v) (((v)<=5)?5:(((v)>100)?100:(v)))
662
663 void
do_change_param(int val)664 do_change_param( int val )
665 {
666 if( ASColorState.base_hue == -1 ||
667 (ASColorState.base_hue == 0 && ASColorState.base_sat == 0 ) )
668 {
669 CARD32 base_alpha = ARGB32_ALPHA16(ASColorState.base_color);
670 int shade = ARGB32_GREEN16(ASColorState.base_color);
671 shade = val162percent( shade );
672 shade += val ;
673 while( shade > 100 ) shade -= 100 ;
674 while( shade < 0 ) shade += 100 ;
675
676 shade = percent2val16(shade)>>8;
677 ASColorState.base_color = MAKE_ARGB32_GREY8(base_alpha, shade);
678 }else
679 {
680 switch( ASColorState.curr_param )
681 {
682 case ASC_PARAM_BaseHue :
683 ASColorState.base_hue = normalize_degrees_val(ASColorState.base_hue + val) ;
684 break ;
685 case ASC_PARAM_BaseSat :
686 ASColorState.base_sat = normalize_percent_val(ASColorState.base_sat + val) ;
687 break ;
688 case ASC_PARAM_BaseVal :
689 ASColorState.base_val = normalize_percent_val(ASColorState.base_val + val) ;
690 break ;
691 case ASC_PARAM_Angle :
692 ASColorState.angle += val ;
693 if( ASColorState.angle < 10 )
694 ASColorState.angle = 10 ;
695 else if( ASColorState.angle > 60 )
696 ASColorState.angle = 60 ;
697 break ;
698 }
699 LOCAL_DEBUG_OUT( "val = %d, base hsv: %d, %d, %d", val, ASColorState.base_hue,
700 ASColorState.base_sat,
701 ASColorState.base_val );
702 ASColorState.base_color = make_color_scheme_argb( NULL, 0, 0xFFFF, ASColorState.base_hue,
703 ASColorState.base_sat,
704 ASColorState.base_val );
705 }
706
707 do_colorscheme();
708 }
709
710