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