1 /*
2  * Copyright (c) 2004 Sasha Vasko <sasha@aftercode.net>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  */
18 
19 #define LOCAL_DEBUG
20 #define EVENT_TRACE
21 
22 #include "../../configure.h"
23 #include "../../libAfterStep/asapp.h"
24 #include <unistd.h>
25 #include "../../libAfterStep/screen.h"
26 #include "../../libAfterStep/module.h"
27 #include "../../libAfterStep/aswindata.h"
28 #include "../../libAfterStep/event.h"
29 #include "../../libAfterStep/wmprops.h"
30 #include "../../libAfterStep/parser.h"
31 #include "../../libAfterStep/session.h"
32 #include "../../libAfterStep/mystyle.h"
33 #include "../../libAfterConf/afterconf.h"
34 
35 #include "ASConfig.h"
36 #include "configfile.h"
37 #include "asproperty.h"
38 #include "xmlrpc.h"
39 
40 /*************************************************************************/
41 
42 
43 ASProperty *Root = NULL;
44 
45 ASConfigTypeInfo ConfigTypeInfo[] =
46 {
47    	{ CONFIG_Base_ID, 		 &BaseSyntax,  0, 					1, {CONFIG_BaseFile_ID}, 			CONFIG_BaseOptions_ID},
48 	{ CONFIG_ColorScheme_ID, &ColorSyntax, 0, 					1, {CONFIG_ColorSchemeFile_ID}, 	CONFIG_ColorSchemeOptions_ID},
49 	{ CONFIG_Functions_ID, 	 &FunctionSyntax, CONFIG_FunctionsFiles_ID,  3, {CONFIG_FeelFile_ID,
50 																			 CONFIG_AfterStepFile_ID,
51 																			 CONFIG_AutoExecFile_ID}, 0},
52 	{ CONFIG_Popups_ID, 	 &PopupSyntax, CONFIG_PopupsFiles_ID,  3, {CONFIG_FeelFile_ID,
53 																	   CONFIG_AfterStepFile_ID,
54 																	   CONFIG_StartDir_ID}, 0},
55 	{ CONFIG_Database_ID, 	 &DatabaseSyntax, 0, 				   1, {CONFIG_DatabaseFile_ID}, 0},
56   	{0}
57 };
58 
59 int AfterStepFeelFiles[]	= {CONFIG_FeelFile_ID, CONFIG_AfterStepFile_ID, -1} ;
60 int AfterStepLookFiles[]	= {CONFIG_LookFile_ID, CONFIG_AfterStepFile_ID, -1} ;
61 int PagerFeelFiles[] 		= {CONFIG_FeelFile_ID, CONFIG_PagerFile_ID, -1} ;
62 int PagerLookFiles[] 		= {CONFIG_LookFile_ID, CONFIG_PagerFile_ID, -1} ;
63 int PagerPrivateFiles[] 	= {CONFIG_PagerFile_ID, -1} ;
64 
65 int WinListFeelFiles[] 		= {CONFIG_FeelFile_ID, CONFIG_WinListFile_ID, -1} ;
66 int WinListLookFiles[] 		= {CONFIG_LookFile_ID, CONFIG_WinListFile_ID, -1} ;
67 int WinListPrivateFiles[] 	= {CONFIG_WinListFile_ID, -1} ;
68 
69 int WharfFeelFiles[] 		= {CONFIG_FeelFile_ID, CONFIG_WharfFile_ID, -1} ;
70 int WharfLookFiles[] 		= {CONFIG_LookFile_ID, CONFIG_WharfFile_ID, -1} ;
71 int WharfPrivateFiles[] 	= {CONFIG_WharfFile_ID, -1} ;
72 
73 ASModuleSyntax MyStylesSyntaxes[] ={{CONFIG_MyStyles_ID,  &ModuleMyStyleSyntax, 	NULL,  CONFIG_LookFiles_ID, PagerLookFiles, 0, NULL },
74 									{-1, NULL, 	NULL, 0, NULL, 0, NULL}};
75 
76 ASModuleSyntax AfterStepLookSyntaxes[] ={{CONFIG_MyStyles_ID,  		&ModuleMyStyleSyntax, 	NULL,  CONFIG_LookFiles_ID, AfterStepLookFiles, 0, NULL },
77 										 {CONFIG_MyFrames_ID,  		&AfterStepMyFrameSyntax, 	NULL,  CONFIG_LookFiles_ID, AfterStepLookFiles, 0, NULL },
78 										 {CONFIG_MyBackgrounds_ID,	&AfterStepMyBackSyntax, 	NULL,  CONFIG_LookFiles_ID, AfterStepLookFiles, 0, NULL },
79 										 {CONFIG_TitleButtons_ID,	&AfterStepTitleButtonSyntax, 	NULL,  CONFIG_LookFiles_ID, AfterStepLookFiles, 0, NULL },
80 										 {-1, NULL, 	NULL, 0, NULL, 0, NULL}};
81 
82 ASModuleSyntax AfterStepFeelSyntaxes[] ={{CONFIG_Cursors_ID,  		&AfterStepCursorSyntax, 	NULL,  CONFIG_FeelFiles_ID, AfterStepFeelFiles, 0, NULL },
83 										 {CONFIG_MouseBindings_ID,	&AfterStepMouseSyntax, 	NULL,  CONFIG_FeelFiles_ID, AfterStepFeelFiles, 0, NULL },
84 										 {CONFIG_KeyBindings_ID,	&AfterStepKeySyntax, 	NULL,  CONFIG_FeelFiles_ID, AfterStepFeelFiles, 0, NULL },
85 										 {CONFIG_WindowBoxes_ID,	&AfterStepWindowBoxSyntax, 	NULL,  CONFIG_FeelFiles_ID, AfterStepFeelFiles, 0, NULL },
86 										 {-1, NULL, 	NULL, 0, NULL, 0, NULL}};
87 
88 ASModuleSyntax AfterStepSyntaxes[]={{CONFIG_AfterStepFeel_ID, &AfterStepFeelSyntax, 	NULL, CONFIG_FeelFiles_ID, AfterStepFeelFiles, CONFIG_FeelOptions_ID, &AfterStepFeelSyntaxes[0] },
89 									{CONFIG_AfterStepLook_ID, &AfterStepLookSyntax, 	NULL, CONFIG_LookFiles_ID, AfterStepLookFiles, CONFIG_LookOptions_ID, &AfterStepLookSyntaxes[0] },
90 									{-1, NULL, 	NULL, 0, NULL, 0, NULL}};
91 
92 
93 ASModuleSyntax PagerSyntaxes[] = {	{CONFIG_PagerFeel_ID, &PagerFeelSyntax, 	NULL, CONFIG_FeelFiles_ID, PagerFeelFiles, CONFIG_FeelOptions_ID, NULL },
94 									{CONFIG_PagerLook_ID, &PagerLookSyntax, 	NULL, CONFIG_LookFiles_ID, PagerLookFiles, CONFIG_LookOptions_ID, &MyStylesSyntaxes[0] },
95 									{0, 	  			  &PagerPrivateSyntax, 	NULL,                0, PagerPrivateFiles, CONFIG_PagerOptions_ID, NULL },
96 									{-1, NULL, 	NULL, 0, NULL, 0, NULL}};
97 
98 ASModuleSyntax WinListSyntaxes[] ={	{CONFIG_WinListFeel_ID, &WinListFeelSyntax, 	NULL, CONFIG_FeelFiles_ID, WinListFeelFiles, CONFIG_FeelOptions_ID, NULL },
99 									{CONFIG_WinListLook_ID, &WinListLookSyntax, 	NULL, CONFIG_LookFiles_ID, WinListLookFiles, CONFIG_LookOptions_ID, &MyStylesSyntaxes[0] },
100 									{0, 	  			    &WinListPrivateSyntax, 	NULL,                0, WinListPrivateFiles, CONFIG_WinListOptions_ID, NULL },
101 									{-1, NULL, 	NULL, 0, NULL, 0, NULL}};
102 
103 ASModuleSyntax WharfSyntaxes[] ={	{CONFIG_WharfFeel_ID, &WharfFeelSyntax, 	NULL, 				CONFIG_FeelFiles_ID, WharfFeelFiles		,CONFIG_FeelOptions_ID, NULL },
104 									{CONFIG_WharfLook_ID, &WharfLookSyntax, 	NULL, 				CONFIG_LookFiles_ID, WharfLookFiles		,CONFIG_LookOptions_ID, &MyStylesSyntaxes[0] },
105 									{0, 	  			  &WharfPrivateSyntax, 	NULL,               0, WharfPrivateFiles	,CONFIG_WharfOptions_ID, NULL },
106 									{CONFIG_WharfFolders_ID,&WharfFolderSyntax,	WharfSpecialFunc,   0, WharfPrivateFiles	,CONFIG_WharfFolders_ID, NULL },
107 									{-1, NULL, 	NULL, 0, NULL, 0, NULL}};
108 
109 ASModuleSpecs ModulesSpecs[] =
110 	{{CLASS_PAGER, 		PagerSyntaxes},
111 	 {CLASS_AFTERSTEP, 	AfterStepSyntaxes},
112 	 {CLASS_WINLIST, 	WinListSyntaxes},
113 	 {CLASS_WHARF, 		WharfSyntaxes},
114 	 {NULL, NULL}
115 	};
116 
117 /*************************************************************************/
118 void
DeadPipe(int foo)119 DeadPipe (int foo)
120 {
121 	{
122 		static int already_dead = False ;
123 		if( already_dead ) 	return;/* non-reentrant function ! */
124 		already_dead = True ;
125 	}
126     FreeMyAppResources();
127 #ifdef DEBUG_ALLOCS
128     print_unfreed_mem ();
129 #endif /* DEBUG_ALLOCS */
130 
131 	if( dpy )
132 	{
133     	XFlush (dpy);
134     	XCloseDisplay (dpy);
135 	}
136     exit (0);
137 }
138 /*************************************************************************/
139 /*************************************************************************/
140 void load_hierarchy();
141 void print_hierarchy( ASProperty *root, int level );
142 void register_special_keywords();
143 void interactive_loop();
144 /*************************************************************************/
145 /*************************************************************************/
146 int
main(int argc,char ** argv)147 main (int argc, char **argv)
148 {
149 	Bool interactive = False ;
150 	Bool do_print_hierarchy = True ;
151 	int i ;
152 	/* Save our program name - for error messages */
153 	set_DeadPipe_handler(DeadPipe);
154     InitMyApp (CLASS_ASCONFIG, argc, argv, NULL, NULL, 0 );
155 	for( i = 1 ; i < argc ; ++i )
156 		if( argv[i] )
157 		{
158 			if( mystrcmp(argv[i],"-i") == 0 || mystrcmp(argv[i],"--interactive") == 0 )
159 				interactive = True;
160 			else if( mystrcmp(argv[i],"-p") == 0 || mystrcmp(argv[i],"--print-hierarchy") == 0 )
161 				interactive = True;
162 
163 		}
164 
165 	LinkAfterStepConfig();
166 
167 	InitSession();
168 
169 	register_special_keywords();
170 	init_ConfigFileInfo();
171 
172 	LOCAL_DEBUG_OUT("loading hierarchy%s","");
173 	load_hierarchy();
174 
175 	if( interactive )
176 	{
177 	 	interactive_loop();
178 	}else if( do_print_hierarchy )
179 		print_hierarchy(Root, 0);
180 
181 	if( dpy )
182     	XCloseDisplay (dpy);
183     return 0;
184 }
185 /**************************************************************************/
register_special_keywords()186 void register_special_keywords()
187 {
188 #define REG_SPEC_KEYWORD(k)		register_keyword_id( #k, CONFIG_##k##_ID )
189 
190 	REG_SPEC_KEYWORD(root);
191 	REG_SPEC_KEYWORD(Base);
192 	REG_SPEC_KEYWORD(ColorScheme);
193 	REG_SPEC_KEYWORD(Functions);
194 	REG_SPEC_KEYWORD(Popups);
195 	REG_SPEC_KEYWORD(Database);
196 	REG_SPEC_KEYWORD(Module);
197 
198 	REG_SPEC_KEYWORD(AfterStep);
199 	REG_SPEC_KEYWORD(Pager);
200 	REG_SPEC_KEYWORD(Wharf);
201 	REG_SPEC_KEYWORD(WinList);
202 
203 	REG_SPEC_KEYWORD(AfterStepLook);
204 	REG_SPEC_KEYWORD(AfterStepFeel);
205 	REG_SPEC_KEYWORD(PagerLook);
206 	REG_SPEC_KEYWORD(PagerFeel);
207 	REG_SPEC_KEYWORD(WharfLook);
208 	REG_SPEC_KEYWORD(WharfFeel);
209 	REG_SPEC_KEYWORD(WharfFolders);
210 	REG_SPEC_KEYWORD(WinListLook);
211 	REG_SPEC_KEYWORD(WinListFeel);
212 
213 	REG_SPEC_KEYWORD(LookFile);
214 	REG_SPEC_KEYWORD(FeelFile);
215 	REG_SPEC_KEYWORD(StartDir);
216 	REG_SPEC_KEYWORD(AutoExecFile);
217 	REG_SPEC_KEYWORD(PagerFile);
218 	REG_SPEC_KEYWORD(WharfFile);
219 	REG_SPEC_KEYWORD(WinListFile);
220 	REG_SPEC_KEYWORD(AfterStepFile);
221 	REG_SPEC_KEYWORD(BaseFile);
222 	REG_SPEC_KEYWORD(ColorSchemeFile);
223 	REG_SPEC_KEYWORD(DatabaseFile);
224 
225 
226 	REG_SPEC_KEYWORD(FunctionsFiles);
227 	REG_SPEC_KEYWORD(PopupsFiles);
228 	REG_SPEC_KEYWORD(LookFiles);
229 	REG_SPEC_KEYWORD(FeelFiles);
230 	REG_SPEC_KEYWORD(BackgroundFiles);
231 	REG_SPEC_KEYWORD(PrivateFiles);
232 	REG_SPEC_KEYWORD(SharedFiles);
233 
234 	REG_SPEC_KEYWORD(BaseOptions);
235 	REG_SPEC_KEYWORD(ColorSchemeOptions);
236 	REG_SPEC_KEYWORD(MyStyles);
237 	REG_SPEC_KEYWORD(MyFrames);
238 	REG_SPEC_KEYWORD(MyBackgrounds);
239 	REG_SPEC_KEYWORD(TitleButtons);
240 	REG_SPEC_KEYWORD(Cursors);
241 	REG_SPEC_KEYWORD(MouseBindings);
242 	REG_SPEC_KEYWORD(KeyBindings);
243 	REG_SPEC_KEYWORD(WindowBoxes);
244 
245 	REG_SPEC_KEYWORD(LookOptions);
246 	REG_SPEC_KEYWORD(FeelOptions);
247 	REG_SPEC_KEYWORD(AfterStepOptions);
248 	REG_SPEC_KEYWORD(PagerOptions);
249 	REG_SPEC_KEYWORD(WharfOptions);
250 	REG_SPEC_KEYWORD(WinListOptions);
251 
252 	REG_SPEC_KEYWORD(flags);
253 	REG_SPEC_KEYWORD(x);
254 	REG_SPEC_KEYWORD(y);
255 	REG_SPEC_KEYWORD(width);
256 	REG_SPEC_KEYWORD(height);
257 
258 	REG_SPEC_KEYWORD(type);
259 	REG_SPEC_KEYWORD(tint);
260 	REG_SPEC_KEYWORD(pixmap);
261 
262 	REG_SPEC_KEYWORD(hotkey);
263 	REG_SPEC_KEYWORD(text);
264 	REG_SPEC_KEYWORD(value);
265 	REG_SPEC_KEYWORD(unit);
266 	REG_SPEC_KEYWORD(IncludeFile);
267 
268 	REG_SPEC_KEYWORD(unpressed);
269 	REG_SPEC_KEYWORD(pressed);
270 
271 	REG_SPEC_KEYWORD(source);
272 	REG_SPEC_KEYWORD(context);
273 	REG_SPEC_KEYWORD(mod);
274 
275 	REG_SPEC_KEYWORD(left);
276 	REG_SPEC_KEYWORD(right);
277 	REG_SPEC_KEYWORD(top);
278 	REG_SPEC_KEYWORD(bottom);
279 
280 	REG_SPEC_KEYWORD(image);
281 	REG_SPEC_KEYWORD(mask);
282 }
283 /*************************************************************************/
284 ASProperty *
special_free_storage2property(FreeStorageElem ** pcurr)285 special_free_storage2property( FreeStorageElem **pcurr )
286 {
287 	FreeStorageElem *curr = *pcurr ;
288 	ASProperty *prop = NULL ;
289 	ConfigItem    item;
290 	item.memory = NULL;
291 
292 	ReadConfigItem (&item, curr);
293 
294 	if( curr->term->id == MYSTYLE_BACKGRADIENT_ID )
295 	{
296 				/* TODO */
297 	}else if( curr->term->id == MYSTYLE_BACKGRADIENT_ID )
298 	{
299 				/* TODO */
300 	}else if( curr->term->id == MYSTYLE_BACKPIXMAP_ID )
301 	{
302 		prop = create_property( curr->term->id, ASProp_Phony, NULL, True );
303 		add_integer_property( CONFIG_type_ID, item.data.integer, prop );
304 
305 		if (curr->argc > 1)
306 		{
307 			if( item.data.integer == TEXTURE_TRANSPARENT || item.data.integer == TEXTURE_TRANSPARENT_TWOWAY )
308 		  		add_string_property( CONFIG_tint_ID, curr->argv[1], prop );
309 			else
310 		  		add_string_property( CONFIG_pixmap_ID, curr->argv[1], prop );
311 		}
312 	}
313 
314 	if( prop == NULL )
315 	{
316 		switch( curr->term->type )
317 		{
318 			case TT_GEOMETRY :
319 				prop = create_property( curr->term->id, ASProp_Phony, NULL, True );
320 				add_integer_property( CONFIG_flags_ID, item.data.geometry.flags, prop );
321 				if( get_flags(item.data.geometry.flags, XValue ) )
322 					add_integer_property( CONFIG_x_ID, item.data.geometry.x, prop );
323 				if( get_flags(item.data.geometry.flags, YValue ) )
324 					add_integer_property( CONFIG_y_ID, item.data.geometry.y, prop );
325 				if( get_flags(item.data.geometry.flags, WidthValue ) )
326 					add_integer_property( CONFIG_width_ID, item.data.geometry.width, prop );
327 				if( get_flags(item.data.geometry.flags, HeightValue ) )
328 					add_integer_property( CONFIG_height_ID, item.data.geometry.height, prop );
329 		    	break ;
330 	 		case TT_FUNCTION :
331 				{
332 					FunctionData *pfunc = (item.data.function);
333 					ASProperty *tmp ;
334 					prop = create_property( curr->term->id, ASProp_Phony, pfunc->name, True );
335 					if( pfunc->hotkey != '\0' )
336 						add_char_property( CONFIG_hotkey_ID, pfunc->hotkey, prop );
337 					if( pfunc->text )
338 					{
339 						add_string_property( CONFIG_text_ID, pfunc->text, prop );
340 
341 						if(
342 							(pfunc->func > F_REFRESH && pfunc->func <= F_MOVECURSOR ) ||
343 							(pfunc->func >= F_DESK && pfunc->func < F_POPUP ) ||
344 						  	pfunc->func == F_RESIZE || pfunc->func == F_MOVE ||
345 						  	pfunc->func == F_SETLAYER || pfunc->func == F_REFRESH ||
346 						  	pfunc->func == F_MAXIMIZE || pfunc->func == F_CHANGE_WINDOWS_DESK )
347 						{
348 							tmp = add_integer_property( CONFIG_value_ID, pfunc->func_val[0], prop );
349 							set_property_index( tmp, 0 );
350 							if( pfunc->unit[0] != '\0' )
351 							{
352 								tmp = add_char_property( CONFIG_unit_ID, pfunc->unit[0], prop );
353 								set_property_index( tmp, 0 );
354 							}
355 							tmp = add_integer_property( CONFIG_value_ID, pfunc->func_val[1], prop );
356 							set_property_index( tmp, 1 );
357 							if( pfunc->unit[1] != '\0' )
358 							{
359 								tmp = add_char_property( CONFIG_unit_ID, pfunc->unit[1], prop );
360 								set_property_index( tmp, 1 );
361 							}
362 						}
363 					}
364 					if( curr->next != NULL )
365 					{
366 						curr = curr->next ;
367 						if( curr->term->id == F_MINIPIXMAP )
368 						{
369 							ReadConfigItem (&item, curr);
370 							pfunc = (item.data.function);
371 							if( pfunc->name != NULL )
372 								add_string_property( F_MINIPIXMAP, pfunc->name, prop );
373 							else
374 								add_string_property( F_MINIPIXMAP, pfunc->text, prop );
375 							*pcurr = curr ;
376 						}
377 					}
378 				}
379 				break ;
380 	 		case TT_BOX :
381 				prop = create_property( curr->term->id, ASProp_Phony, NULL, True );
382 				add_integer_property( CONFIG_flags_ID, item.data.box.flags, prop );
383 				if( get_flags(item.data.box.flags, LeftValue ) )
384 					add_integer_property( CONFIG_left_ID, item.data.box.left, prop );
385 				if( get_flags(item.data.box.flags, RightValue ) )
386 					add_integer_property( CONFIG_right_ID, item.data.box.right, prop );
387 				if( get_flags(item.data.box.flags, TopValue ) )
388 					add_integer_property( CONFIG_top_ID, item.data.box.top, prop );
389 				if( get_flags(item.data.box.flags, BottomValue ) )
390 					add_integer_property( CONFIG_bottom_ID, item.data.box.bottom, prop );
391 				break ;
392 	 		case TT_BUTTON :
393 				prop = create_property( curr->term->id, ASProp_Phony, NULL, True );
394 				set_property_index( prop, item.index );
395 				if( item.data.button )
396 				{
397 					if( item.data.button->shapes[ASB_State_Up] )
398 						add_string_property( CONFIG_unpressed_ID, item.data.button->shapes[ASB_State_Up], prop );
399 					if( item.data.button->shapes[ASB_State_Down] )
400 						add_string_property( CONFIG_pressed_ID, item.data.button->shapes[ASB_State_Down], prop );
401 				}
402 				break ;
403 	 		case TT_BINDING :
404 				prop = create_property( curr->term->id, ASProp_Phony, NULL, True );
405 				if( item.data.binding.sym )
406 					add_string_property( CONFIG_source_ID, item.data.binding.sym, prop );
407 				add_integer_property( CONFIG_context_ID, item.data.binding.context, prop );
408 				add_integer_property( CONFIG_mod_ID, item.data.binding.mods, prop );
409 				break ;
410 	 		case TT_INTARRAY : 	/* TODO */ break ;
411 	 		case TT_CURSOR :
412 				prop = create_property( curr->term->id, ASProp_Phony, NULL, True );
413 				if( item.data.cursor )
414 				{
415 					if( item.data.cursor->image_file )
416 						add_string_property( CONFIG_image_ID, item.data.cursor->image_file, prop );
417 					if( item.data.cursor->mask_file )
418 						add_string_property( CONFIG_mask_ID, item.data.cursor->mask_file, prop );
419 				}
420 				break ;
421 
422 		}
423 	}
424 	ReadConfigItem (&item, NULL);
425 
426 	return prop;
427 }
428 
429 ASProperty*
free_storage2property_list(FreeStorageElem * fs,ASProperty * pl)430 free_storage2property_list( FreeStorageElem *fs, ASProperty *pl )
431 {
432 	FreeStorageElem *curr ;
433 	ConfigItem    item;
434 	ASProperty *prop = NULL;
435 
436 	LOCAL_DEBUG_CALLER_OUT("(%p,%p)", fs, pl );
437 	item.memory = NULL;
438 
439 	for( curr = fs ; curr ; curr = curr->next )
440 	{
441 		if (curr->term == NULL)
442 			continue;
443 		if ( get_flags( curr->term->flags, TF_SYNTAX_TERMINATOR ) )
444 			continue;
445 		if (!ReadConfigItem (&item, curr))
446 			continue;
447 		if( curr == fs && pl->id == curr->term->id )
448 			continue;
449 
450 		if( (curr->term->type == TT_QUOTED_TEXT || curr->term->type == TT_TEXT) &&
451 			 curr->term->sub_syntax != NULL &&
452 			 !get_flags(curr->term->flags, TF_INDEXED|TF_DIRECTION_INDEXED) )
453 		{
454 			prop = create_property( curr->term->id, ASProp_Phony, item.data.string, (curr->sub != NULL) );
455 		}else                  /* we actually have some data */
456 		{
457 			prop = special_free_storage2property( &curr );
458 			if( prop == NULL )
459 			{
460 				int type = ASProp_Phony;
461 				char *name = NULL ;
462 				if( curr->sub == NULL )
463 					switch( curr->term->type )
464 					{
465 						case TT_FLAG :
466 						case TT_INTEGER :
467 						case TT_UINTEGER :
468 						case TT_BITLIST : 	type = ASProp_Integer ; break ;
469 
470 						case TT_COLOR :
471 						case TT_FONT :
472 						case TT_FILENAME :
473 						case TT_PATHNAME :
474 						case TT_TEXT :
475 						case TT_QUOTED_TEXT :
476 						case TT_OPTIONAL_PATHNAME : type = ASProp_Data ; break ;
477 						default:
478 						/* handled by special_ as complex datatype */ break ;
479 					}
480 
481 				prop = create_property( curr->term->id, type, name, (curr->sub != NULL) );
482 				if( type == ASProp_Data )
483 				{
484 					if( item.data.string == NULL )
485 						prop->contents.data = 0 ;
486 					else
487 						prop->contents.data = encode_string( item.data.string );
488 					/* LOCAL_DEBUG_OUT( "stored with id = %d, string = \"%s\"", prop->contents.data, item.data.string ); */
489 				}else
490 					prop->contents.integer = item.data.integer ;
491 			}
492 		}
493 
494 		if( get_flags(curr->term->flags, TF_INDEXED|TF_DIRECTION_INDEXED))
495 			set_property_index( prop, item.index );
496 
497 		if( curr->sub != NULL )
498 			free_storage2property_list( curr->sub, prop ) ;
499 
500 		append_property( pl, prop );
501 	}
502 	return prop;
503 }
504 
505 Bool
merge_prop_into_prop(void * data,void * aux_data)506 merge_prop_into_prop(void *data, void *aux_data)
507 {
508 	ASProperty *dst = (ASProperty*)data;
509 	ASProperty *src = (ASProperty*)aux_data;
510 
511 	if( dst->id != src->id || dst == src )
512 		return True;
513 
514 	if( get_flags( src->flags, ASProp_Indexed ) && get_flags( dst->flags, ASProp_Indexed ) )
515 	{
516 		if( src->index != dst->index )
517 			return True;
518 	}else if( src->name != NULL && dst->name != NULL )
519 		if( strcmp( src->name, dst->name ) )
520 			return True;
521 
522 	/* otherwise we have to merge it  : */
523 	dup_property_contents( src, dst, True );
524 
525 	set_flags( src->flags, ASProp_Merged );
526 	return True;
527 }
528 
529 Bool
merge_prop_into_list(void * data,void * aux_data)530 merge_prop_into_list(void *data, void *aux_data)
531 {
532 	ASProperty *prop = (ASProperty*)data;
533 	ASProperty *dst_prop = (ASProperty*)aux_data;
534 
535 	clear_flags( prop->flags, ASProp_Merged );
536 	iterate_asbidirlist( dst_prop->sub_props, merge_prop_into_prop, prop, NULL, False );
537 	if( !get_flags( prop->flags, ASProp_Merged )  )
538 	{
539 		prop = dup_property( prop, True );
540 		append_property( dst_prop, prop );
541 	}
542 
543 	return True;
544 }
545 
546 void
merge_property_list(ASProperty * src,ASProperty * dst)547 merge_property_list( ASProperty *src, ASProperty *dst )
548 {
549 	if( src->sub_props == NULL && dst->sub_props == NULL )
550 		return;
551 	LOCAL_DEBUG_CALLER_OUT("(%p,%p)", src, dst );
552 	iterate_asbidirlist( src->sub_props, merge_prop_into_list, dst, NULL, False );
553 }
554 /*************************************************************************/
555 ASProperty* asmenu_dir2property( const char *dirname, const char *menu_path, ASProperty *owner_prop, int func, const char *extension, const char *mini_ext );
556 void melt_menu_props( ASProperty *file, ASProperty *opts );
557 void melt_func_props( ASProperty *file, ASProperty *opts );
558 void melt_binding_props( ASProperty *src, ASProperty *dst );
559 
560 
561 ASProperty*
load_current_config_fname(ASProperty * config,int id,const char * filename,const char * myname,SyntaxDef * syntax,SpecialFunc special,int files_id,int file_id,int options_id)562 load_current_config_fname( ASProperty* config, int id, const char *filename, const char *myname,
563 					 SyntaxDef *syntax, SpecialFunc special, int files_id, int file_id, int options_id )
564 {
565 	ASConfigFile *cf = NULL ;
566 	ASProperty *files = NULL ;
567 	ASProperty *file ;
568 	ASProperty *opts ;
569 
570 	if( config == NULL )
571 		config = create_property( id, ASProp_Phony, NULL, True );
572 
573 	if( filename )
574 	{
575 		if( CheckDir(filename) )
576 		{
577 			LOCAL_DEBUG_OUT("loading file \"%s\", myname = \"%s\", syntax = %p, syntax name = \"%s\"", filename, myname, syntax, syntax->display_name );
578 			cf = load_config_file(NULL, filename, myname?myname:"afterstep", syntax, special );
579 		}
580 	}
581 
582 
583 	if( files_id != 0 )
584 	{
585 		files = find_property_by_id( config, files_id );
586 		if( files == NULL )
587 		{
588 			files = create_property( files_id, ASProp_Phony, NULL, True );
589 			append_property( config, files );
590 		}
591 	}
592 
593 	file = find_property_by_id( files?files:config, file_id );
594 	if( file == NULL )
595 	{
596 		file = create_property( file_id, ASProp_File, NULL, True );
597 		append_property( files?files:config, file );
598 	}
599 	file->contents.config_file = cf ;
600 
601 	if( cf )
602 		free_storage2property_list( cf->free_storage, file );
603 	else if( file_id == CONFIG_StartDir_ID )
604 		asmenu_dir2property( filename, "", file, F_NOP, NULL, NULL );
605 
606 	if( options_id != 0 )
607 	{
608 		opts = find_property_by_id( config, options_id );
609 		if( opts == NULL )
610 		{
611 			opts = create_property( options_id, ASProp_Phony, NULL, True );
612 			append_property( config, opts );
613 		}
614 	}else
615 		opts = config ;
616 
617 	if( file_id == CONFIG_StartDir_ID )
618 		melt_menu_props( file, opts );
619 	else if( syntax == &FunctionSyntax )
620 	{
621 		melt_func_props( file, opts );
622 	}else if( id == CONFIG_KeyBindings_ID || id == CONFIG_MouseBindings_ID )
623 		melt_binding_props( file, opts );
624 	else
625 		merge_property_list( file, opts );
626 
627 	return config;
628 }
629 
630 ASProperty*
load_current_config(ASProperty * config,int id,const char * myname,SyntaxDef * syntax,SpecialFunc special,int files_id,int file_id,int options_id)631 load_current_config( ASProperty* config, int id, const char *myname,
632 					 SyntaxDef *syntax, SpecialFunc special, int files_id, int file_id, int options_id )
633 {
634 	const char *filename = get_config_file_name( file_id );
635 	return load_current_config_fname( config, id, filename, myname, syntax, special, files_id, file_id, options_id );
636 
637 }
638 
639 /*************************************************************************/
640 ASProperty*
asmenu_dir2property(const char * dirname,const char * menu_path,ASProperty * owner_prop,int func,const char * extension,const char * mini_ext)641 asmenu_dir2property( const char *dirname, const char *menu_path, ASProperty *owner_prop,
642 					 int func, const char *extension, const char *mini_ext )
643 {
644 	struct direntry  **list;
645 	int list_len, i ;
646 	ASProperty *popup, *include_file = NULL ;
647 	const char *ptr;
648 	ASConfigFile *include_cf = NULL ;
649 	char *new_path ;
650 	ASProperty *item = NULL ;
651 	int mini_ext_len = mini_ext?strlen(mini_ext):0 ;
652 	int ext_len = extension?strlen(extension):0 ;
653 
654 	if( dirname == NULL )
655 		return NULL;
656 
657 	ptr = strrchr(dirname,'/');
658 
659 	list_len = my_scandir ((char*)dirname, &list, no_dots_except_include, NULL);
660 	LOCAL_DEBUG_OUT("dir \"%s\" has %d entries", dirname, list_len );
661 	if( list_len <= 0 )
662 		return NULL;
663 
664 	if( ptr == NULL )
665 		ptr = dirname ;
666 	else
667 		++ptr ;
668 	while( isdigit(*ptr) ) ++ptr;
669 	if( *ptr == '_' )
670 		++ptr ;
671 
672 	new_path = make_file_name( menu_path, ptr );
673 	popup = create_property( F_POPUP, ASProp_Data, new_path, True );
674 	popup->contents.data = encode_string( dirname );
675 	append_property( owner_prop, popup );
676 
677 	for (i = 0; i < list_len; i++)
678 		if( list[i]->d_name[0] == '.' )
679 		{
680 			ASProperty *cmd ;
681 			include_cf = load_config_file(dirname, list[i]->d_name, "afterstep", &includeSyntax, NULL );
682 			include_file = create_property( CONFIG_IncludeFile_ID, ASProp_File, NULL, True );
683 			append_property( popup, include_file );
684 			include_file->contents.config_file = include_cf ;
685 			free_storage2property_list( include_cf->free_storage, include_file );
686 
687 			cmd = find_property_by_id( include_file, INCLUDE_command_ID );
688 
689 			if( cmd )
690 			{
691 				ASProperty *cmd_func = find_property_by_id( cmd, -1 );	 ;
692 				if( cmd_func && cmd_func->id < F_FUNCTIONS_NUM )
693 					func = cmd_func->id ;
694 			}
695 			break;
696 		}
697 	for (i = 0; i < list_len; i++)
698 	{
699 		char *sub_path = make_file_name( dirname, list[i]->d_name );
700 		if ( S_ISDIR (list[i]->d_mode) )
701 		{
702 			ASProperty *sub_menu = asmenu_dir2property( sub_path, new_path, owner_prop, func, extension, mini_ext ) ;
703 			item = create_property( F_POPUP, ASProp_Data, sub_menu->name, True );
704 			item->contents.data = encode_string( sub_path );
705 			append_property( popup, item );
706 		}else if( list[i]->d_name[0] != '.' )
707 		{
708 			int len = strlen(list[i]->d_name);
709 			char *stripped_name = NULL;
710 			char *minipixmap = NULL ;
711 			char hotkey = '\0' ;
712 			int k ;
713 			char *clean_name;
714 			int order = strtol (list[i]->d_name, &clean_name, 10);
715 
716 			if( clean_name == list[i]->d_name )
717 			{
718 				if( isalpha(clean_name[0]) && clean_name[1] == '_' )
719 				{
720 					order = (int)(clean_name[0]) - (int)'0' ;
721 					clean_name += 2 ;
722 					len -= 2 ;
723 				}else
724 					order = -1 ;
725 			}else
726 				len -= (clean_name - list[i]->d_name );
727 
728 			if( ext_len > 0 && len > ext_len )
729 			{
730 				if( strcmp( clean_name + len - ext_len, extension) == 0 )
731 					stripped_name = mystrndup( clean_name, len - ext_len );
732 				else if( strncmp(clean_name, extension, ext_len) == 0 )
733 					stripped_name = mystrdup( clean_name + ext_len );
734 			}
735 			if( stripped_name == NULL )
736 			{
737 				if( mini_ext_len > 0 && len > mini_ext_len )
738 				{
739 					if( strcmp( clean_name + len - mini_ext_len, mini_ext ) == 0 )
740 						continue;
741 					if( strncmp( clean_name, mini_ext, mini_ext_len ) == 0 )
742 						continue;
743 				}
744 				stripped_name = mystrdup( clean_name );
745 			}
746 
747 			if( mini_ext_len > 0 )
748 			{
749 				for(k = 0; k < list_len; k++)
750 					if( k != i && !S_ISDIR (list[k]->d_mode))
751 					{
752 						int mlen = strlen(list[k]->d_name);
753 						if( mlen > mini_ext_len && len - ext_len == mlen - mini_ext_len)
754 						{
755 							if( strcmp( list[k]->d_name + mlen - mini_ext_len, mini_ext ) == 0)
756 							{
757 								if( strncmp( list[k]->d_name, stripped_name, mlen - mini_ext_len ) == 0 )
758 								{  /* found suitable minipixmap */
759 									minipixmap = make_file_name( dirname, list[k]->d_name );
760 									break;
761 								}
762 							}else if( strncmp( list[k]->d_name, mini_ext, mini_ext_len ) == 0)
763 							{
764 								if( strcmp( list[k]->d_name + mini_ext_len, stripped_name ) == 0 )
765 								{  /* found suitable minipixmap */
766 									minipixmap = make_file_name( dirname, list[k]->d_name + mini_ext_len );
767 									break;
768 								}
769 							}
770 						}
771 					}
772 			}
773 
774 			for( k = 0 ; stripped_name[k] != '\0' ; ++k )
775 			{
776 				if( stripped_name[k] == '_' )
777 				{
778 					if( stripped_name[k+1] == '_' )
779 					{
780 						int l ;
781 						for( l = k+2 ; stripped_name[l] != '\0' ; ++l)
782 							stripped_name[l-2] = stripped_name[l] ;
783 						hotkey = stripped_name[k] ;
784 					}else
785 						stripped_name[k] = ' ' ;
786 				}
787 
788 			}
789 
790 			if( func != F_NOP )
791 			{
792 				item = create_property( func, ASProp_Data, stripped_name, True );
793 				item->contents.data = encode_string( sub_path );
794 				append_property( popup, item );
795 				add_string_property( CONFIG_text_ID, sub_path, item );
796 				if( minipixmap )
797 					add_string_property( F_MINIPIXMAP, minipixmap, item );
798 				if( hotkey != '\0' )
799 					add_char_property( CONFIG_hotkey_ID, hotkey, item );
800 			}else
801 			{
802 				ASConfigFile *cf = NULL ;
803 
804 				cf = load_config_file(dirname, list[i]->d_name, "afterstep", pFuncSyntax, NULL );
805 				item = free_storage2property_list( cf->free_storage, popup );
806 				if( item )
807 				{
808 					item->type = ASProp_File ;
809 					item->contents.config_file = cf ;
810 					if( item->name == NULL )
811 					{
812 						item->name = stripped_name ;
813 						stripped_name = NULL ;
814 					}else
815 						hotkey = scan_for_hotkey (stripped_name);
816 
817 					if( minipixmap )
818 						if( find_property_by_id( item, F_MINIPIXMAP ) == NULL )
819 							add_string_property( F_MINIPIXMAP, minipixmap, item );
820 					if( hotkey != '\0' )
821 						if( find_property_by_id( item, CONFIG_hotkey_ID ) == NULL )
822 			   				add_char_property( CONFIG_hotkey_ID, hotkey, item );
823 
824 				}else
825 					destroy_config_file( cf );
826 			}
827 			if( item )
828 				item->order = order ;
829 			if( stripped_name)
830 				free( stripped_name );
831 			if(minipixmap)
832 				free(minipixmap);
833 		}
834 		free( sub_path );
835 		free (list[i]);
836 	}
837 	if( list )
838 		free( list );
839 	free( new_path );
840 	return popup;
841 }
842 
compare_menuitems_handler(void * data1,void * data2)843 int compare_menuitems_handler(void *data1, void *data2)
844 {
845 	ASProperty *item1 = (ASProperty*)data1 ;
846 	ASProperty *item2 = (ASProperty*)data2 ;
847 	static char buffer1[512], buffer2[512] ;
848 	int stored_len1 = 0, stored_len2 = 0 ;
849 	LOCAL_DEBUG_OUT( "comparing items with order %d and %d", item1->order, item2->order );
850 	if( item2->id == F_POPUP && item1->id != F_POPUP)
851 		return 1 ;
852 	else if( item1->id == F_POPUP && item2->id != F_POPUP)
853 		return 0;
854 	if( item2->order >= 0 )
855 	{
856 		if( item1->order  < 0 )
857 			return 1;
858 		return item1->order - item2->order;
859 	}
860 	if( item1->order >= 0 )
861 		return 0;
862 
863 	if( item1->type == ASProp_File && item2->type == ASProp_File )
864 		return mystrcmp( item1->contents.config_file->filename, item2->contents.config_file->filename );
865 	else if( item1->type == ASProp_File && item2->type == ASProp_Data )
866 	{
867 	 	decode_string( item2->contents.data, &(buffer1[0]), 512, &stored_len1 );
868 		return mystrcmp( item1->contents.config_file->filename, &buffer1[0] );
869 	}else if( item2->type == ASProp_File && item1->type == ASProp_Data )
870 	{
871 	 	decode_string( item1->contents.data, &(buffer1[0]), 512, &stored_len1 );
872 		return mystrcmp( &buffer1[0], item2->contents.config_file->filename );
873 	}else if( item2->type == ASProp_Data && item1->type == ASProp_Data )
874 	{
875 		decode_string( item1->contents.data, &(buffer1[0]), 512, &stored_len1 );
876 	 	decode_string( item2->contents.data, &(buffer2[0]), 512, &stored_len2 );
877 		return mystrcmp( &buffer1[0], &buffer2[0] );
878 	}
879 	return 0;
880 }
881 
882 Bool
melt_menu_props_into_list(void * data,void * aux_data)883 melt_menu_props_into_list(void *data, void *aux_data)
884 {
885 	ASProperty *popup = (ASProperty*)data;
886 	ASProperty *dst = (ASProperty*)aux_data ;
887 	ASProperty *incl ;
888 	ASProperty *dst_popup ;
889 	char *name = NULL ;
890 
891 	incl = find_property_by_id( popup, CONFIG_IncludeFile_ID );
892 	dst_popup = find_property_by_id_name( dst, popup->id, popup->name );
893 	if( dst_popup == NULL )
894 	{
895 		dst_popup = dup_property( popup, True );
896 		append_property( dst, dst_popup );
897 	}else
898  		merge_property_list( popup, dst_popup );
899 
900 	if( incl )
901 	{
902 		int func = F_NOP ;
903 #define MAX_EXTENTION 256
904 		char *extension = NULL ;
905 		char *mini_ext = NULL ;
906 		ASBiDirElem *curr ;
907 		ASProperty *phony = NULL;
908 
909 		remove_property_by_id( dst_popup, CONFIG_IncludeFile_ID );
910 		/* Pass 1 : collecting settings first : */
911 		for( curr = LIST_START(incl->sub_props); curr != NULL ; LIST_GOTO_NEXT(curr) )
912 		{
913 			ASProperty *prop = (ASProperty*)LISTELEM_DATA(curr) ;
914 			switch( prop->id )
915 			{
916 				case INCLUDE_keepname_ID           : /* OBSOLETE */   break ;
917 				case INCLUDE_extension_ID          :
918 					if( extension )	free( extension );
919 					extension = decode_string_alloc( prop->contents.data );
920 					break ;
921 				case INCLUDE_miniextension_ID      :
922 					if( mini_ext )	free( mini_ext );
923 					mini_ext = decode_string_alloc( prop->contents.data );
924 					break ;
925 
926 				case INCLUDE_minipixmap_ID         : /* OBSOLETE */   break ;
927 				case INCLUDE_command_ID        	   : /* TODO */   break ;
928 				case INCLUDE_order_ID       	   :
929 					dst_popup->order = prop->contents.integer ; break ;
930 				case INCLUDE_RecentSubmenuItems_ID : /* TODO */   break ;
931 				case INCLUDE_name_ID          	   :
932 					if( name )	free( name );
933 					name = decode_string_alloc( prop->contents.data );
934 					break ;
935 			}
936 		}
937 		/* Pass 2 : including submenus : */
938 		for( curr = LIST_START(incl->sub_props); curr != NULL ; LIST_GOTO_NEXT(curr) )
939 		{
940 			ASProperty *prop = (ASProperty*)LISTELEM_DATA(curr) ;
941 			if( prop->id == INCLUDE_include_ID )
942 			{
943 				ASProperty *text_prop = find_property_by_id( prop, CONFIG_text_ID );
944 				char *fullfilename = PutHome( prop->name );
945 				int incl_func = func ;
946 				ASProperty *sub_popup ;
947 
948 				LOCAL_DEBUG_OUT( "include \"%s\" with text_prop = %p", fullfilename, text_prop );
949 
950 				if( text_prop != NULL )
951 				{
952 					char *txt = decode_string_alloc( text_prop->contents.data );
953 					if( txt )
954 					{
955 						TermDef *fd  ;
956 						if( (fd = txt2fterm( txt, False)) != NULL )
957 							incl_func = fd->id ;
958 						free( txt );
959 					}
960 				}
961 				if( phony == NULL )
962 					phony = create_property( CONFIG_StartDir_ID, ASProp_File, NULL, True );
963 				LOCAL_DEBUG_OUT( "func = (%d) phony = %p, popup = %p", incl_func, phony, popup );
964 				LOCAL_DEBUG_OUT( "popup->name = \"%s\"", popup->name );
965 				sub_popup = asmenu_dir2property( fullfilename, popup->name, phony,
966 					 				 incl_func, extension, mini_ext );
967 
968 				LOCAL_DEBUG_OUT( "sub_popup = %p", sub_popup );
969 				print_hierarchy( sub_popup, 0 );
970 				if( sub_popup != NULL )
971 				{
972 					merge_property_list( sub_popup, dst_popup );
973 					discard_bidirelem( phony->sub_props, sub_popup );
974 					if( phony->sub_props->count > 0 )
975 					{
976 						melt_menu_props( phony, dst );
977 						purge_asbidirlist( phony->sub_props );
978 					}
979 				}
980 				free( fullfilename );
981 			}
982 		}
983 		if( phony != NULL )
984 			destroy_property( phony );
985 		if( extension )
986 			free( extension );
987 		if( mini_ext )
988 			free( mini_ext );
989 	}
990 	/* now we need to sort items according to order */
991 	bubblesort_asbidirlist( dst_popup->sub_props, compare_menuitems_handler );
992 	LOCAL_DEBUG_OUT( "sorted menu \"%s\"", dst_popup->name );
993 	print_hierarchy( dst_popup, 0 );
994 	/* and now we need to add F_TITLE item for menu name */
995 	if( name == NULL )
996 	{
997 		int i = -1;
998 		parse_file_name( dst_popup->name, NULL, &name );
999 		if( name )
1000 			while( name[++i] ) if( name[i] == '_' ) name[i] = ' ' ;
1001 	}
1002 	if( name )
1003 	{
1004 		ASProperty *title ;
1005 		title = create_property( F_TITLE, ASProp_Phony, name, True );
1006 		prepend_property( dst_popup, title  );
1007 		free( name );
1008 	}
1009 
1010 	return True;
1011 }
1012 
1013 void
melt_menu_props(ASProperty * src,ASProperty * dst)1014 melt_menu_props( ASProperty *src, ASProperty *dst )
1015 {
1016 	if( src->sub_props == NULL || dst == NULL )
1017 		return;
1018 	LOCAL_DEBUG_CALLER_OUT("(%p,%p)", src, dst );
1019 	iterate_asbidirlist( src->sub_props, melt_menu_props_into_list, dst, NULL, False );
1020 }
1021 
1022 /*************************************************************************/
1023 Bool
melt_func_props_into_list(void * data,void * aux_data)1024 melt_func_props_into_list(void *data, void *aux_data)
1025 {
1026 	ASProperty *func = (ASProperty*)data;
1027 	ASProperty *dst = (ASProperty*)aux_data ;
1028 	ASProperty *dst_func ;
1029 	int index = 0 ;
1030 	ASBiDirElem *curr = LIST_START(func->sub_props);
1031 
1032 
1033 	dst_func = find_property_by_id_name( dst, func->id, func->name );
1034 
1035 	if( dst_func == NULL )
1036 	{
1037 		dst_func = dup_property( func, False );
1038 		append_property( dst, dst_func );
1039 	}
1040 
1041 	while( curr )
1042 	{
1043 		ASProperty *prop = (ASProperty*)LISTELEM_DATA(curr) ;
1044 		ASProperty *copy ;
1045 		copy = dup_property( prop, True );
1046 		set_property_index( copy, index );
1047 		append_property( dst_func, copy );
1048 
1049 		++index ;
1050 
1051 		LIST_GOTO_NEXT(curr);
1052 	}
1053 	return True;
1054 }
1055 
1056 void
melt_func_props(ASProperty * src,ASProperty * dst)1057 melt_func_props( ASProperty *src, ASProperty *dst )
1058 {
1059 	if( src->sub_props == NULL || dst == NULL )
1060 		return;
1061 	LOCAL_DEBUG_CALLER_OUT("(%p,%p)", src, dst );
1062 	iterate_asbidirlist( src->sub_props, melt_func_props_into_list, dst, NULL, False );
1063 }
1064 /*************************************************************************/
1065 void
melt_binding_props(ASProperty * src,ASProperty * dst)1066 melt_binding_props( ASProperty *src, ASProperty *dst )
1067 {
1068 	LOCAL_DEBUG_CALLER_OUT("(%p,%p)", src, dst );
1069 	if( src->sub_props != NULL && dst != NULL )
1070 	{
1071 		int index = 0 ;
1072 		ASBiDirElem *curr = LIST_START(src->sub_props);
1073 		while( curr )
1074 		{
1075 			ASProperty *prop = (ASProperty*)LISTELEM_DATA(curr) ;
1076 			ASProperty *copy ;
1077 			copy = dup_property( prop, True );
1078 			set_property_index( copy, index );
1079 			append_property( dst, copy );
1080 
1081 			++index ;
1082 
1083 			LIST_GOTO_NEXT(curr);
1084 		}
1085 	}
1086 }
1087 /*************************************************************************/
1088 void load_global_configs();
1089 void add_module_config( const char *module_class, const char *module_name );
1090 
1091 
1092 void
load_hierarchy()1093 load_hierarchy()
1094 {
1095 	Root = create_property( CONFIG_root_ID, ASProp_Phony, "", True );
1096 
1097 	load_global_configs();
1098 	add_module_config( CLASS_AFTERSTEP, "afterstep" );
1099 	add_module_config( CLASS_PAGER, "Pager" );
1100 	add_module_config( CLASS_WINLIST, "WinList" );
1101 	add_module_config( CLASS_WHARF, "Wharf" );
1102 }
1103 
1104 /*************************************************************************/
1105 void
load_global_configs()1106 load_global_configs()
1107 {
1108 	int i ;
1109 	ASProperty *tmp ;
1110 
1111 	for( i = 0 ; ConfigTypeInfo[i].config_id != 0 ; ++i )
1112 	{
1113 		int k ;
1114 		tmp = NULL ;
1115 		for( k = 0 ; k < ConfigTypeInfo[i].config_file_ids_count ; ++k )
1116 		{
1117 			tmp = load_current_config( 	tmp,
1118 										ConfigTypeInfo[i].config_id, NULL,
1119 										ConfigTypeInfo[i].syntax,
1120 										NULL,
1121 										ConfigTypeInfo[i].config_files_id,
1122 										ConfigTypeInfo[i].config_file_ids[k],
1123 										ConfigTypeInfo[i].config_options_id);
1124 		}
1125 		if( tmp )
1126 			append_property( Root, tmp );
1127 	}
1128 }
1129 
handle_module_syntaxes(ASProperty * owner,const char * module_name,ASModuleSyntax * syntaxes)1130 void handle_module_syntaxes( ASProperty *owner, const char *module_name, ASModuleSyntax *syntaxes )
1131 {
1132 	int k ;
1133 	ASProperty *tmp ;
1134 	for( k = 0 ; syntaxes[k].config_id >= 0 ; ++k )
1135 	{
1136 		ASModuleSyntax *ms = &(syntaxes[k]);
1137 		int l ;
1138 
1139 		if( ms->config_id == 0 )
1140 		{
1141 			load_current_config( 	owner,
1142 									ms->config_id, module_name,
1143 									ms->syntax,
1144 									ms->special,
1145 									0,
1146 									ms->files[0],
1147 									ms->config_options_id);
1148 		}else
1149 		{
1150 			tmp = NULL ;
1151 			for( l = 0 ; ms->files[l] >= 0 ; ++l )
1152 			{
1153 				tmp = load_current_config( 	tmp,
1154 											ms->config_id, module_name,
1155 											ms->syntax,
1156 											ms->special,
1157 											ms->config_files_id,
1158 											ms->files[l],
1159 											ms->config_options_id);
1160 			}
1161 			if( tmp )
1162 				append_property( owner, tmp );
1163 
1164 			if( ms->subsyntaxes )
1165 				handle_module_syntaxes( tmp, module_name, ms->subsyntaxes );
1166 		}
1167 	}
1168 }
1169 
1170 void
add_module_config(const char * module_class,const char * module_name)1171 add_module_config( const char *module_class, const char *module_name )
1172 {
1173 	int i ;
1174 	ASProperty *config;
1175 
1176 	for( i = 0 ; ModulesSpecs[i].module_class != NULL ; ++i )
1177 		if( mystrcmp( ModulesSpecs[i].module_class, module_class ) == 0 )
1178 		{
1179 			config = create_property( CONFIG_Module_ID, ASProp_Phony, module_name, True );
1180 			append_property( Root, config );
1181 
1182 			handle_module_syntaxes( config, module_name, ModulesSpecs[i].syntaxes );
1183 		}
1184 }
1185 
1186 
1187 
1188 /*************************************************************************/
1189 void print_hierarchy( ASProperty *root, int level );
1190 
1191 Bool
print_hierarchy_iter_func(void * data,void * aux_data)1192 print_hierarchy_iter_func(void *data, void *aux_data)
1193 {
1194     ASProperty *prop = (ASProperty*)data;
1195 	int level = (int)aux_data ;
1196 	print_hierarchy( prop, level );
1197 	return True;
1198 }
1199 
1200 void
print_hierarchy(ASProperty * root,int level)1201 print_hierarchy( ASProperty *root, int level )
1202 {
1203 	int i ;
1204 
1205 	//LOCAL_DEBUG_CALLER_OUT("(%p,%d)",root, level );
1206 
1207 	if( root == NULL )
1208 		return ;
1209 
1210 	for( i = 0 ; i < level ; ++i )
1211 		fputc( '\t', stderr);
1212 	fprintf( stderr, "%s(%ld) ", get_property_keyword( root ), root->id );
1213 	if( root->order >= 0 )
1214 		fprintf( stderr, "order=%d ", root->order );
1215 	if( get_flags( root->flags, ASProp_Indexed ) )
1216 	   	fprintf( stderr, "[%d] ", root->index );
1217 	else if( root->name )
1218 		fprintf( stderr, "\"%s\" ", root->name );
1219 
1220 	if( root->type == ASProp_Integer )
1221 		fprintf( stderr, "= %d;", root->contents.integer );
1222 	else if( root->type == ASProp_Data )
1223 	{
1224 		static char string[128] ;
1225 		int bytes_out, orig_bytes ;
1226 		/*LOCAL_DEBUG_OUT( "fetching data with id = %d", root->contents.data );  */
1227 		bytes_out = decode_string( root->contents.data, &string[0], 128, &orig_bytes );
1228 		/* LOCAL_DEBUG_OUT( "fetched %d bytes", bytes_out ); */
1229 		if( bytes_out < orig_bytes )
1230 			fprintf( stderr, "= %d of %d chars:", bytes_out, orig_bytes );
1231 		else
1232 			fprintf( stderr, "= ");
1233 		fprintf( stderr, "\"%s\"", string );
1234 		fputc( ';', stderr);
1235 	}else if( root->type == ASProp_File )
1236 	{
1237 		if( root->contents.config_file )
1238 			fprintf( stderr, "loaded from [%s]", root->contents.config_file->fullname );
1239 		else
1240 			fprintf( stderr, "not loaded" );
1241 	}
1242 
1243 	fputc( '\n', stderr);
1244 	if( root->sub_props )
1245 	{
1246 	 	iterate_asbidirlist( root->sub_props, print_hierarchy_iter_func, (void*)(level+1), NULL, False );
1247 	}
1248 
1249 }
1250 
1251 void
handle_asconfig_command(char * buffer,int buffer_len,FILE * out_stream)1252 handle_asconfig_command(char *buffer, int buffer_len, FILE *out_stream)
1253 {
1254 	ASXmlRPCPacket *packet = safecalloc( 1, sizeof(ASXmlRPCPacket) );
1255 
1256 	packet->xml = mystrndup(buffer, buffer_len) ;
1257 	packet->size = packet->allocated_size = buffer_len ;
1258 
1259 	if( xml2rpc_packet( packet ) )
1260 	{
1261 	}else
1262 		show_warning( "failed to parse rpc packet" );
1263 	print_rpc_packet( packet ) ;
1264 	destroy_rpc_packet( &packet );
1265 }
1266 
interactive_loop()1267 void interactive_loop()
1268 {
1269 #define BUFFER_SIZE 8192
1270 	char buffer[BUFFER_SIZE] ;
1271 
1272 	fprintf( stdout, "#" );
1273 	while( fgets( &buffer[0], BUFFER_SIZE, stdin ) != NULL )
1274 	{
1275 		/* now we need to process the command */
1276 		handle_asconfig_command(buffer, strlen(buffer)-1, stdout);
1277 		fprintf( stdout, "#" );
1278 	}
1279 }
1280