1 /*
2  * Copyright (C) 2000 Sasha Vasko <sasha at 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17  *
18  */
19 
20 #include "../configure.h"
21 
22 #define LOCAL_DEBUG
23 #include "asapp.h"
24 #include "afterstep.h"
25 #include "asdatabase.h"
26 #include "screen.h"
27 #include "functions.h"
28 #include "clientprops.h"
29 #include "hints.h"
30 #include "desktop_category.h"
31 #include "freestor.h"
32 #include "../libAfterImage/afterimage.h"
33 
34 
35 /*********************************************************************************
36  * Raw Hints must be aggregated into usable forma :
37  *********************************************************************************/
init_ashints(ASHints * hints)38 static void init_ashints (ASHints * hints)
39 {
40 	if (hints) {									/* some defaults to start with : */
41 		hints->flags =
42 				AS_HitPager | AS_Gravity | AS_AcceptsFocus | AS_Titlebar |
43 				AS_IconTitle | AS_Handles | AS_Border;
44 		/* can't gracefully close the window if it does not support WM_DELETE_WINDOW */
45 		hints->function_mask = ~(AS_FuncClose | AS_FuncPinMenu);
46 		hints->gravity = NorthWestGravity;
47 		hints->border_width = 1;
48 	}
49 }
50 
get_asdb_hint_mask(ASDatabaseRecord * db_rec)51 ASFlagType get_asdb_hint_mask (ASDatabaseRecord * db_rec)
52 {
53 	ASFlagType hint_mask = ASFLAGS_EVERYTHING;
54 
55 	if (db_rec) {
56 		if (get_flags (db_rec->set_flags, STYLE_GROUP_HINTS)
57 				&& !get_flags (db_rec->flags, STYLE_GROUP_HINTS))
58 			clear_flags (hint_mask, (0x01 << HINTS_GroupLead));
59 		if (get_flags (db_rec->set_flags, STYLE_TRANSIENT_HINTS)
60 				&& !get_flags (db_rec->flags, STYLE_TRANSIENT_HINTS))
61 			clear_flags (hint_mask, (0x01 << HINTS_Transient));
62 		if (get_flags (db_rec->set_flags, STYLE_MOTIF_HINTS)
63 				&& !get_flags (db_rec->flags, STYLE_MOTIF_HINTS))
64 			clear_flags (hint_mask, (0x01 << HINTS_Motif));
65 		if (get_flags (db_rec->set_flags, STYLE_GNOME_HINTS)
66 				&& !get_flags (db_rec->flags, STYLE_GNOME_HINTS))
67 			clear_flags (hint_mask, (0x01 << HINTS_Gnome));
68 		if (get_flags (db_rec->set_flags, STYLE_EXTWM_HINTS)
69 				&& !get_flags (db_rec->flags, STYLE_EXTWM_HINTS))
70 			clear_flags (hint_mask, (0x01 << HINTS_ExtendedWM));
71 		if (get_flags (db_rec->set_flags, STYLE_KDE_HINTS)
72 				&& !get_flags (db_rec->flags, STYLE_KDE_HINTS))
73 			clear_flags (hint_mask, (0x01 << HINTS_KDE));
74 		if (get_flags (db_rec->set_flags, STYLE_XRESOURCES_HINTS)
75 				&& !get_flags (db_rec->flags, STYLE_XRESOURCES_HINTS))
76 			clear_flags (hint_mask, (0x01 << HINTS_XResources));
77 	}
78 	return hint_mask;
79 }
80 
81 static ASFlagType
get_afterstep_resources(XrmDatabase db,ASStatusHints * status)82 get_afterstep_resources (XrmDatabase db, ASStatusHints * status)
83 {
84 	ASFlagType found = 0;
85 
86 	if (db != NULL && status) {
87 		if (read_int_resource
88 				(db, "afterstep*desk", "AS*Desk", &(status->desktop)))
89 			set_flags (found, AS_StartDesktop);
90 		if (read_int_resource
91 				(db, "afterstep*layer", "AS*Layer", &(status->layer)))
92 			set_flags (found, AS_StartLayer);
93 		if (read_int_resource
94 				(db, "afterstep*viewportx", "AS*ViewportX", &(status->viewport_x)))
95 			set_flags (found, AS_StartViewportX);
96 		if (read_int_resource
97 				(db, "afterstep*viewporty", "AS*ViewportY", &(status->viewport_y)))
98 			set_flags (found, AS_StartViewportY);
99 		set_flags (status->flags, found);
100 	}
101 	return found;
102 }
103 
104 void
merge_command_line(ASHints * clean,ASStatusHints * status,ASRawHints * raw)105 merge_command_line (ASHints * clean, ASStatusHints * status,
106 										ASRawHints * raw)
107 {
108 	static XrmOptionDescRec xrm_cmd_opts[] = {
109 		/* Want to accept -xrm "afterstep*desk:N" as options
110 		 * to specify the desktop. Have to include dummy options that
111 		 * are meaningless since Xrm seems to allow -x to match -xrm
112 		 * if there would be no ambiguity. */
113 		{"-xrnblahblah", NULL, XrmoptionResArg, (caddr_t) NULL},
114 		{"-xrm", NULL, XrmoptionResArg, (caddr_t) NULL},
115 	};
116 
117 	if (raw == NULL)
118 		return;
119 	if (raw->wm_cmd_argc > 0 && raw->wm_cmd_argv != NULL) {
120 		XrmDatabase cmd_db = NULL;	/* otherwise it will try to use value as if it was database */
121 		ASFlagType found;
122 
123 		init_xrm ();
124 
125 		XrmParseCommand (&cmd_db, xrm_cmd_opts, 2, "afterstep",
126 										 &(raw->wm_cmd_argc), raw->wm_cmd_argv);
127 		if (status != NULL) {
128 			found = get_afterstep_resources (cmd_db, status);
129 
130 			if (!get_flags (found, AS_StartDesktop)) {	/* checking for CDE workspace specification */
131 				if (read_int_resource
132 						(cmd_db, "*workspaceList", "*WorkspaceList",
133 						 &(status->desktop)))
134 					set_flags (status->flags, AS_StartDesktop);
135 			}
136 			XrmDestroyDatabase (cmd_db);
137 		}
138 		if (raw->wm_client_machine && clean)
139 			clean->client_host = text_property2string (raw->wm_client_machine);
140 
141 		if (raw->wm_cmd_argc > 0 && clean) {
142 			int i;
143 			int len = 0;
144 
145 			/* there still are some args left ! lets save it for future use : */
146 			/* first check to remove any geometry settings : */
147 			for (i = 0; i < raw->wm_cmd_argc; i++)
148 				if (raw->wm_cmd_argv[i]) {
149 					if (i + 1 < raw->wm_cmd_argc)
150 						if (raw->wm_cmd_argv[i + 1] != NULL) {
151 							register char *g = raw->wm_cmd_argv[i + 1];
152 
153 							if (isdigit ((int)*g)
154 									|| ((*g == '-' || *g == '+') && isdigit ((int)*(g + 1))))
155 								if (mystrcasecmp (raw->wm_cmd_argv[i], "-g") == 0
156 										|| mystrcasecmp (raw->wm_cmd_argv[i],
157 																		 "-geometry") == 0) {
158 									raw->wm_cmd_argv[i] = NULL;
159 									raw->wm_cmd_argv[++i] = NULL;
160 									continue;
161 								}
162 						}
163 					len += strlen (raw->wm_cmd_argv[i]) + 1;
164 				}
165 			if (len > 0) {
166 				register char *trg, *src;
167 
168 				if (clean->client_cmd)
169 					free (clean->client_cmd);
170 				trg = clean->client_cmd =
171 						safecalloc (1, len + raw->wm_cmd_argc * 2 + 1);
172 				for (i = 0; i < raw->wm_cmd_argc; i++)
173 					if ((src = raw->wm_cmd_argv[i]) != NULL) {
174 						register int k;
175 						Bool add_quotes = False;
176 
177 						for (k = 0; src[k]; k++)
178 							if (isspace (src[k]) ||
179 									src[k] == '#' ||
180 									src[k] == '*' ||
181 									src[k] == '$' ||
182 									src[k] == ';' ||
183 									src[k] == '&' || src[k] == '<' || src[k] == '>'
184 									|| src[k] == '|' || iscntrl (src[k])) {
185 								add_quotes = True;
186 								break;
187 							}
188 
189 						if (add_quotes) {
190 							trg[0] = '"';
191 							++trg;
192 						}
193 						for (k = 0; src[k]; k++)
194 							trg[k] = src[k];
195 						if (add_quotes) {
196 							trg[k] = '"';
197 							++k;
198 						}
199 						trg[k] = ' ';
200 						trg += k + 1;
201 					}
202 				if (trg > clean->client_cmd)
203 					trg--;
204 				*trg = '\0';
205 			}
206 		}
207 	}
208 }
209 
210 void
check_hints_sanity(ScreenInfo * scr,ASHints * clean,ASStatusHints * status,Window client)211 check_hints_sanity (ScreenInfo * scr, ASHints * clean,
212 										ASStatusHints * status, Window client)
213 {
214 	if (clean) {
215 		if (clean->border_width == 0
216 				|| clean->border_width > scr->MyDisplayHeight / 2)
217 			clear_flags (clean->flags, AS_Border);
218 
219 		if (clean->handle_width > scr->MyDisplayHeight / 2)
220 			clean->handle_width = 0;
221 
222 		if (get_flags (clean->flags, AS_SizeInc)) {
223 			if (clean->width_inc == 0)
224 				clean->width_inc = 1;
225 			if (clean->height_inc == 0)
226 				clean->height_inc = 1;
227 		}
228 
229 		if (get_flags (clean->flags, AS_Aspect))
230 			if ((clean->min_aspect.x == 0 || clean->min_aspect.y == 0) &&
231 					(clean->max_aspect.x == 0 || clean->max_aspect.y == 0))
232 				clear_flags (clean->flags, AS_Aspect);
233 
234 		if (get_flags (clean->flags, AS_Icon))
235 			if (clean->icon_file == NULL && clean->icon.pixmap == None)
236 				clear_flags (clean->flags, AS_Icon);
237 
238 		if (status && status->width <= 2 && status->height <= 2) {
239 			if (clean->res_class
240 					&& strcasecmp (clean->res_class, "DockApp") == 0)
241 				set_flags (clean->flags, AS_WMDockApp);
242 		}
243 
244 		if (clean->icon.window == client) {
245 			clean->icon.window = None;
246 			clear_flags (clean->function_mask, AS_FuncMinimize);
247 			clear_flags (clean->client_icon_flags, AS_ClientIcon);
248 		}
249 
250 
251 		if (clean->frame_name == NULL)
252 			clear_flags (clean->flags, AS_Frame);
253 		if (clean->windowbox_name == NULL)
254 			clear_flags (clean->flags, AS_Windowbox);
255 	}
256 }
257 
check_status_sanity(ScreenInfo * scr,ASStatusHints * status)258 void check_status_sanity (ScreenInfo * scr, ASStatusHints * status)
259 {
260 	if (status) {
261 		/* we want to limit user specifyed layers to AS_LayerDesktop < layer < AS_LayerMenu
262 		 * which is reasonable, since you cannot be lower then Desktop and higher then Menu
263 		 */
264 		if (get_flags (status->flags, AS_StartPositionUser))
265 			set_flags (status->flags, AS_StartPosition);
266 
267 		if (status->layer <= AS_LayerDesktop)
268 			status->layer = AS_LayerDesktop + 1;
269 		else if (status->layer >= AS_LayerMenu)
270 			status->layer = AS_LayerMenu - 1;
271 
272 		if (status->desktop == INVALID_DESK)
273 			clear_flags (status->flags, AS_StartDesktop);
274 		LOCAL_DEBUG_OUT ("viewport_x = %d", status->viewport_x);
275 		status->viewport_x = FIT_IN_RANGE (0, status->viewport_x, scr->VxMax);
276 		LOCAL_DEBUG_OUT ("viewport_x = %d", status->viewport_x);
277 		status->viewport_y = FIT_IN_RANGE (0, status->viewport_y, scr->VyMax);
278 		if (status->width < 2)
279 			status->width = 2;
280 		if (status->height < 2)
281 			status->height = 2;
282 		if (status->border_width == 0
283 				|| status->border_width > scr->MyDisplayHeight / 2)
284 			clear_flags (status->flags, AS_StartBorderWidth);
285 	}
286 }
287 
get_hint_name_encoding(ASHints * hints,int name_idx)288 unsigned char get_hint_name_encoding (ASHints * hints, int name_idx)
289 {
290 	if (hints && name_idx >= 0 && name_idx <= MAX_WINDOW_NAMES)
291 		return hints->names_encoding[name_idx];
292 	return AS_Text_ASCII;
293 }
294 
295 /* Hints merging functions : */
merge_hints(ASRawHints * raw,ASDatabase * db,ASStatusHints * status,ASSupportedHints * list,ASFlagType what,ASHints * reusable_memory,Window client)296 ASHints *merge_hints (ASRawHints * raw, ASDatabase * db,
297 											ASStatusHints * status, ASSupportedHints * list,
298 											ASFlagType what, ASHints * reusable_memory,
299 											Window client)
300 {
301 	ASHints *clean = NULL;
302 	ASDatabaseRecord db_rec, *pdb_rec;
303 	int i;
304 	ASFlagType hints_types = ASFLAGS_EVERYTHING;
305 
306 	if (raw == NULL || list == NULL || what == 0)
307 		return NULL;
308 	if ((clean = reusable_memory) == NULL)
309 		clean = (ASHints *) safecalloc (1, sizeof (ASHints));
310 	else
311 		memset (clean, 0x00, sizeof (ASHints));
312 	if (status)
313 		memset (status, 0x00, sizeof (ASStatusHints));
314 
315 	init_ashints (clean);
316 
317 	/* collect the names first */
318 	if (get_flags (what, HINT_NAME)) {
319 		for (i = 0; i < list->hints_num; i++)
320 			(list->merge_funcs[i]) (clean, raw, NULL, status, HINT_NAME);
321 
322 		what &= ~HINT_NAME;
323 	}
324 	if (clean->names[0] == NULL) {
325 		clean->names[0] = mystrdup ("");	/* must have at least one valid name string - even if empty */
326 		clean->names_encoding[0] = AS_Text_ASCII;
327 	}
328 	/* we want to make sure that we have Icon Name at all times, if at all possible */
329 	if (clean->icon_name == NULL) {
330 		clean->icon_name = clean->names[0];
331 		clean->icon_name_idx = 0;
332 	}
333 	/* we don't want to do anything else if all that was requested are names */
334 	if (what == 0)
335 		return clean;
336 
337 	pdb_rec = fill_asdb_record (db, clean->names, &db_rec, False);
338 
339 	if (clean->matched_name0)
340 		free (clean->matched_name0);
341 	clean->matched_name0 = mystrdup (clean->names[0]);
342 	clean->matched_name0_encoding = clean->names_encoding[0];
343 
344 
345 	LOCAL_DEBUG_OUT ("printing db record %p for names %p and db %p", pdb_rec,
346 									 clean->names, db);
347 	if (is_output_level_under_threshold (OUTPUT_LEVEL_DATABASE))
348 		print_asdb_matched_rec (NULL, NULL, db, pdb_rec);
349 
350 	hints_types = get_asdb_hint_mask (pdb_rec);
351 	hints_types &=
352 			raw->hints_types | (0x01 << HINTS_ASDatabase) | (0x01 <<
353 																											 HINTS_XResources);
354 
355 	/* now do the rest : */
356 	if (what != 0)
357 		for (i = 0; i < list->hints_num; i++) {	/* only do work if needed */
358 			if (get_flags (hints_types, (0x01 << list->hints_types[i]))) {
359 				(list->merge_funcs[i]) (clean, raw, pdb_rec, status, what);
360 				LOCAL_DEBUG_OUT ("merging hints %d (of %d ) - flags == 0x%lX", i,
361 												 list->hints_num, clean->flags);
362 			}
363 		}
364 	if (get_flags (what, HINT_STARTUP))
365 		merge_command_line (clean, status, raw);
366 
367 	check_hints_sanity (raw->scr, clean, status, client);
368 	check_status_sanity (raw->scr, status);
369 
370 	/* this is needed so if user changes the list of supported hints -
371 	 * we could track what was used, and if we need to remerge them
372 	 */
373 	clean->hints_types_raw = raw->hints_types;
374 	clean->hints_types_clean =
375 			get_flags (raw->hints_types, list->hints_flags);
376 
377 	return clean;
378 }
379 
380 /*
381  * few function - shortcuts to implement update of selected hints :
382  */
383 /* returns True if protocol/function hints actually changed :*/
384 Bool
update_protocols(ScreenInfo * scr,Window w,ASSupportedHints * list,ASFlagType * pprots,ASFlagType * pfuncs)385 update_protocols (ScreenInfo * scr, Window w, ASSupportedHints * list,
386 									ASFlagType * pprots, ASFlagType * pfuncs)
387 {
388 	ASRawHints raw;
389 	ASHints clean;
390 	Bool changed = False;
391 
392 	if (w == None)
393 		return False;
394 
395 	if (collect_hints (scr, w, HINT_PROTOCOL, &raw) != NULL) {
396 		if (merge_hints (&raw, NULL, NULL, list, HINT_PROTOCOL, &clean, w) !=
397 				NULL) {
398 			if (pprots)
399 				if ((changed = (*pprots != clean.protocols)))
400 					*pprots = clean.protocols;
401 			if (pfuncs)
402 				if ((changed = (*pfuncs != clean.function_mask)))
403 					*pfuncs = clean.function_mask;
404 			destroy_hints (&clean, True);
405 		}
406 		destroy_raw_hints (&raw, True);
407 	}
408 	return changed;
409 }
410 
411 /* returns True if protocol/function hints actually changed :*/
412 Bool
update_colormaps(ScreenInfo * scr,Window w,ASSupportedHints * list,CARD32 ** pcmap_windows)413 update_colormaps (ScreenInfo * scr, Window w, ASSupportedHints * list,
414 									CARD32 ** pcmap_windows)
415 {
416 	ASRawHints raw;
417 	ASHints clean;
418 	Bool changed = False;
419 	register CARD32 *old_win, *new_win;
420 
421 
422 	if (w == None || pcmap_windows == NULL)
423 		return False;
424 
425 	if (collect_hints (scr, w, HINT_COLORMAP, &raw) != NULL) {
426 		if (merge_hints (&raw, NULL, NULL, list, HINT_COLORMAP, &clean, w) !=
427 				NULL) {
428 			old_win = *pcmap_windows;
429 			new_win = clean.cmap_windows;
430 			changed = (old_win != new_win);
431 			if (new_win != NULL && old_win != NULL) {
432 				while (*old_win == *new_win && *old_win != None) {
433 					old_win++;
434 					new_win++;
435 				}
436 				changed = (*old_win != *new_win);
437 			}
438 			if (changed) {
439 				if (*pcmap_windows != NULL)
440 					free (*pcmap_windows);
441 				*pcmap_windows = clean.cmap_windows;
442 				clean.cmap_windows = NULL;
443 			}
444 			destroy_hints (&clean, True);
445 		}
446 		destroy_raw_hints (&raw, True);
447 	}
448 	return changed;
449 }
450 
451 /****************************************************************************
452  * The following functions actually implement hints merging :
453  ****************************************************************************/
454 static int
add_name_to_list(ASHints * hints,char * name,unsigned char encoding,Bool to_front)455 add_name_to_list (ASHints * hints, char *name, unsigned char encoding,
456 									Bool to_front)
457 {
458 	register int i;
459 	char **list = hints->names;
460 	unsigned char *encoding_list = hints->names_encoding;
461 
462 	if (name == NULL)
463 		return -1;
464 
465 	for (i = 0; i < MAX_WINDOW_NAMES; i++) {
466 		if (list[i] == NULL)
467 			break;
468 		if (encoding_list[i] == encoding && strcmp (name, list[i]) == 0) {
469 			free (name);
470 			return i;
471 		}
472 	}
473 	if (i >= MAX_WINDOW_NAMES) {	/* tough luck - no more space */
474 		free (name);
475 		return -1;
476 	}
477 
478 	if (to_front) {
479 		for (; i > 0; i--) {
480 			list[i] = list[i - 1];
481 			encoding_list[i] = encoding_list[i - 1];
482 		}
483 		if (hints->res_name_idx >= 0)
484 			++(hints->res_name_idx);
485 		if (hints->res_class_idx >= 0)
486 			++(hints->res_class_idx);
487 		if (hints->icon_name_idx >= 0)
488 			++(hints->icon_name_idx);
489 	}
490 	list[i] = name;
491 	encoding_list[i] = encoding;
492 	return i;
493 }
494 
pointer_name_to_index_in_list(char ** list,char * name)495 static int pointer_name_to_index_in_list (char **list, char *name)
496 {
497 	register int i;
498 
499 	if (name)
500 		for (i = 0; i < MAX_WINDOW_NAMES; i++) {
501 			if (list[i] == NULL)
502 				break;
503 			if (name == list[i])
504 				return i;
505 		}
506 	return MAX_WINDOW_NAMES;
507 }
508 
509 
510 static void
merge_icccm_hints(ASHints * clean,ASRawHints * raw,ASDatabaseRecord * db_rec,ASStatusHints * status,ASFlagType what)511 merge_icccm_hints (ASHints * clean, ASRawHints * raw,
512 									 ASDatabaseRecord * db_rec, ASStatusHints * status,
513 									 ASFlagType what)
514 {
515 	if (raw == NULL)
516 		return;
517 	if (get_flags (what, HINT_NAME)) {	/* adding all the possible window names in order of increasing importance */
518 		if (raw->wm_name)
519 			add_name_to_list (clean, text_property2string (raw->wm_name),
520 												AS_Text_ASCII, True);
521 		if (raw->wm_icon_name) {
522 			clean->icon_name_idx =
523 					add_name_to_list (clean,
524 														text_property2string (raw->wm_icon_name),
525 														AS_Text_ASCII, False);
526 			clean->icon_name =
527 					(clean->icon_name_idx <
528 					 0) ? NULL : clean->names[clean->icon_name_idx];
529 		}
530 		if (raw->wm_class) {
531 			if (raw->wm_class->res_class) {
532 				clean->res_class_idx =
533 						add_name_to_list (clean, stripcpy (raw->wm_class->res_class),
534 															AS_Text_ASCII, False);
535 				clean->res_class =
536 						(clean->res_class_idx <
537 						 0) ? NULL : clean->names[clean->res_class_idx];
538 			}
539 			if (raw->wm_class->res_name) {
540 				clean->res_name_idx =
541 						add_name_to_list (clean, stripcpy (raw->wm_class->res_name),
542 															AS_Text_ASCII, False);
543 				clean->res_name =
544 						(clean->res_name_idx <
545 						 0) ? NULL : clean->names[clean->res_name_idx];
546 			}
547 		}
548 	}
549 
550 	if (get_flags (what, HINT_STARTUP) && status != NULL) {
551 		Bool position_user = False;
552 
553 		if (raw->wm_hints) {
554 			if (get_flags (raw->wm_hints->flags, StateHint)) {
555 				if (raw->wm_hints->input == IconicState)
556 					set_flags (status->flags, AS_StartsIconic);
557 				else
558 					clear_flags (status->flags, AS_StartsIconic);
559 			}
560 			if (get_flags (raw->wm_hints->flags, UrgencyHint)) {
561 				status->layer = AS_LayerUrgent;
562 				set_flags (status->flags, AS_StartLayer);
563 				set_flags (status->flags, AS_Urgent);
564 			}
565 		}
566 
567 		if (raw->wm_normal_hints)
568 			position_user =
569 					(get_flags (raw->wm_normal_hints->flags, USPosition));
570 
571 		if (!get_flags (status->flags, AS_StartPositionUser) || position_user) {
572 			status->x = raw->placement.x;
573 			status->y = raw->placement.y;
574 			set_flags (status->flags, AS_StartPosition);
575 			if (position_user)
576 				set_flags (status->flags, AS_StartPositionUser);
577 		}
578 		status->width = raw->placement.width;
579 		status->height = raw->placement.height;
580 		set_flags (status->flags, AS_StartSize);
581 		status->border_width = raw->border_width;
582 		set_flags (status->flags, AS_StartBorderWidth);
583 		if (status->border_width > 0) {
584 			clean->border_width = status->border_width;
585 			set_flags (clean->flags, AS_Border);
586 		}
587 
588 		if (raw->wm_state == IconicState)
589 			set_flags (status->flags, AS_StartsIconic);
590 		if (raw->wm_state_icon_win != None)
591 			status->icon_window = raw->wm_state_icon_win;
592 	}
593 
594 	if (get_flags (what, HINT_GENERAL)) {
595 		if (raw->wm_hints) {
596 			XWMHints *wmh = raw->wm_hints;
597 
598 			if (get_flags (wmh->flags, InputHint)) {
599 				if (wmh->input)
600 					set_flags (clean->flags, AS_AcceptsFocus);
601 				else
602 					clear_flags (clean->flags, AS_AcceptsFocus);
603 			}
604 
605 			if (get_flags (wmh->flags, IconWindowHint)
606 					&& wmh->icon_window != None) {
607 				clean->icon.window = wmh->icon_window;
608 				set_flags (clean->client_icon_flags, AS_ClientIcon);
609 				clear_flags (clean->client_icon_flags, AS_ClientIconPixmap);
610 				if (get_flags (wmh->flags, IconWindowIsChildHint))
611 					set_flags (clean->flags, AS_WMDockApp);
612 			} else if (get_flags (wmh->flags, IconPixmapHint)
613 								 && wmh->icon_pixmap != None) {
614 				clean->icon.pixmap = wmh->icon_pixmap;
615 				if (get_flags (wmh->flags, IconMaskHint) && wmh->icon_mask != None)
616 					clean->icon_mask = wmh->icon_mask;
617 				set_flags (clean->client_icon_flags, AS_ClientIcon);
618 				set_flags (clean->client_icon_flags, AS_ClientIconPixmap);
619 			}
620 
621 			if (get_flags (wmh->flags, IconPositionHint)) {
622 				clean->icon_x = wmh->icon_x;
623 				clean->icon_y = wmh->icon_y;
624 				set_flags (clean->client_icon_flags, AS_ClientIconPosition);
625 			}
626 		}
627 
628 		if (raw->wm_normal_hints) {
629 			XSizeHints *nh = raw->wm_normal_hints;
630 
631 			if (get_flags (nh->flags, PMinSize)) {
632 				clean->min_width = nh->min_width;
633 				clean->min_height = nh->min_height;
634 				set_flags (clean->flags, AS_MinSize);
635 			}
636 			if (get_flags (nh->flags, PMaxSize)) {
637 				clean->max_width = nh->max_width;
638 				clean->max_height = nh->max_height;
639 				set_flags (clean->flags, AS_MaxSize);
640 			}
641 			if (get_flags (nh->flags, PResizeInc)) {
642 				clean->width_inc = nh->width_inc;
643 				clean->height_inc = nh->height_inc;
644 				set_flags (clean->flags, AS_SizeInc);
645 			}
646 			if (get_flags (nh->flags, PAspect)) {
647 				clean->min_aspect.x = nh->min_aspect.x;
648 				clean->min_aspect.y = nh->min_aspect.y;
649 				clean->max_aspect.x = nh->max_aspect.x;
650 				clean->max_aspect.y = nh->max_aspect.y;
651 				set_flags (clean->flags, AS_Aspect);
652 			}
653 			if (get_flags (nh->flags, PBaseSize)) {
654 				clean->base_width = nh->base_width;
655 				clean->base_height = nh->base_height;
656 				set_flags (clean->flags, AS_BaseSize);
657 			}
658 			if (get_flags (nh->flags, PWinGravity)) {
659 				clean->gravity = nh->win_gravity;
660 				set_flags (clean->flags, AS_Gravity);
661 			}
662 		}
663 
664 	}
665 
666 	if (get_flags (what, HINT_COLORMAP)) {
667 		if (raw->wm_cmap_windows && raw->wm_cmap_win_count > 0) {
668 			register int i;
669 
670 			if (clean->cmap_windows)
671 				free (clean->cmap_windows);
672 			clean->cmap_windows =
673 					safecalloc (raw->wm_cmap_win_count + 1, sizeof (CARD32));
674 			for (i = 0; i < raw->wm_cmap_win_count; i++)
675 				clean->cmap_windows[i] = raw->wm_cmap_windows[i];
676 			clean->cmap_windows[i] = None;
677 		}
678 	}
679 
680 	if (get_flags (what, HINT_PROTOCOL)) {
681 		clean->protocols |= raw->wm_protocols;
682 		if (get_flags (clean->protocols, AS_DoesWmDeleteWindow))
683 			set_flags (clean->function_mask, AS_FuncClose);
684 	}
685 }
686 
687 static void
merge_parent_hints(ASParentHints * hints,ASStatusHints * status)688 merge_parent_hints (ASParentHints * hints, ASStatusHints * status)
689 {
690 	if (get_flags (hints->flags, AS_StartDesktop))
691 		status->desktop = hints->desktop;
692 	if (get_flags (hints->flags, AS_StartViewportX))
693 		status->viewport_x = hints->viewport_x;
694 	if (get_flags (hints->flags, AS_StartViewportY))
695 		status->viewport_y = hints->viewport_y;
696 	set_flags (status->flags, hints->flags);
697 }
698 
699 static void
merge_group_hints(ASHints * clean,ASRawHints * raw,ASDatabaseRecord * db_rec,ASStatusHints * status,ASFlagType what)700 merge_group_hints (ASHints * clean, ASRawHints * raw,
701 									 ASDatabaseRecord * db_rec, ASStatusHints * status,
702 									 ASFlagType what)
703 {
704 	if (raw == NULL)
705 		return;
706 	if (raw->group_leader) {
707 		if (get_flags (what, HINT_STARTUP) && status != NULL)
708 			merge_parent_hints (raw->group_leader, status);
709 
710 		if (get_flags (what, HINT_GENERAL))
711 			clean->group_lead = raw->group_leader->parent;
712 	}
713 }
714 
715 static void
merge_transient_hints(ASHints * clean,ASRawHints * raw,ASDatabaseRecord * db_rec,ASStatusHints * status,ASFlagType what)716 merge_transient_hints (ASHints * clean, ASRawHints * raw,
717 											 ASDatabaseRecord * db_rec, ASStatusHints * status,
718 											 ASFlagType what)
719 {
720 	if (raw == NULL)
721 		return;
722 	if (raw->transient_for) {
723 		if (get_flags (what, HINT_STARTUP) && status != NULL)
724 			merge_parent_hints (raw->transient_for, status);
725 
726 		if (get_flags (what, HINT_GENERAL)) {
727 			clean->transient_for = raw->transient_for->parent;
728 			set_flags (clean->flags, AS_Transient);
729 			set_flags (clean->flags, AS_ShortLived);
730 		}
731 	}
732 }
733 
734 static void
decode_flags(ASFlagType * dst_flags,ASFlagsXref * xref,ASFlagType set_flags,ASFlagType flags)735 decode_flags (ASFlagType * dst_flags, ASFlagsXref * xref,
736 							ASFlagType set_flags, ASFlagType flags)
737 {
738 	if (dst_flags == NULL || set_flags == 0)
739 		return;
740 	LOCAL_DEBUG_CALLER_OUT
741 			("dst_flags = %lX, set_flags = %lX, flags = 0x%lX", *dst_flags,
742 			 set_flags, flags);
743 	while ((*xref)[0] != 0) {
744 		ASFlagType to_set;
745 		ASFlagType to_clear;
746 		int point;
747 
748 		if (get_flags (set_flags, (*xref)[0])) {
749 			point = (get_flags (flags, (*xref)[0])) ? 1 : 3;
750 			to_set = (*xref)[point];
751 			to_clear = (*xref)[point + 1];
752 			if (to_set != 0)
753 				set_flags (*dst_flags, to_set);
754 			if (to_clear != 0)
755 				clear_flags (*dst_flags, to_clear);
756 		}
757 		xref++;
758 	}
759 }
760 
761 static void
encode_flags(ASFlagType * dst_flags,ASFlagsXref * xref,ASFlagType set_flags,ASFlagType flags)762 encode_flags (ASFlagType * dst_flags, ASFlagsXref * xref,
763 							ASFlagType set_flags, ASFlagType flags)
764 {
765 	if (dst_flags == NULL || set_flags == 0)
766 		return;
767 
768 	while ((*xref)[0] != 0) {
769 		if (get_flags (set_flags, (*xref)[0])) {
770 			if (((flags & (*xref)[1]) == (*xref)[1])
771 					&& (flags & (*xref)[2]) == 0)
772 				set_flags (*dst_flags, (*xref)[0]);
773 			else if (((flags & (*xref)[3]) == (*xref)[3])
774 							 && (flags & (*xref)[4]) == 0)
775 				clear_flags (*dst_flags, (*xref)[0]);
776 		}
777 		xref++;
778 	}
779 }
780 
781 #define decode_simple_flags(dst,xref,flags) decode_flags((dst),(xref),ASFLAGS_EVERYTHING,(flags))
782 #define encode_simple_flags(dst,xref,flags) encode_flags((dst),(xref),ASFLAGS_EVERYTHING,(flags))
783 
check_motif_hints_sanity(MwmHints * motif_hints)784 void check_motif_hints_sanity (MwmHints * motif_hints)
785 {
786 
787 	if (get_flags (motif_hints->decorations, MWM_DECOR_ALL))
788 		motif_hints->decorations =
789 				MWM_DECOR_EVERYTHING & ~(motif_hints->decorations);
790 
791 	/* Now I have the un-altered decor and functions, but with the
792 	 * ALL attribute cleared and interpreted. I need to modify the
793 	 * decorations that are affected by the functions */
794 	if (get_flags (motif_hints->flags, MWM_HINTS_FUNCTIONS)) {
795 		if (get_flags (motif_hints->functions, MWM_FUNC_ALL))
796 			motif_hints->functions =
797 					MWM_FUNC_EVERYTHING & ~(motif_hints->functions);
798 		if (!get_flags (motif_hints->functions, MWM_FUNC_RESIZE))
799 			motif_hints->decorations &= ~MWM_DECOR_RESIZEH;
800 		/* MWM_FUNC_MOVE has no impact on decorations. */
801 		if (!get_flags (motif_hints->functions, MWM_FUNC_MINIMIZE))
802 			motif_hints->decorations &= ~MWM_DECOR_MINIMIZE;
803 		if (!get_flags (motif_hints->functions, MWM_FUNC_MAXIMIZE))
804 			motif_hints->decorations &= ~MWM_DECOR_MAXIMIZE;
805 		/* MWM_FUNC_CLOSE has no impact on decorations. */
806 	}
807 	/* This rule is implicit, but its easier to deal with if
808 	 * I take care of it now */
809 	if (motif_hints->decorations & (MWM_DECOR_MENU | MWM_DECOR_MINIMIZE |
810 																	MWM_DECOR_MAXIMIZE))
811 		motif_hints->decorations |= MWM_DECOR_TITLE;
812 }
813 
814 static ASFlagsXref mwm_decor_xref[] = {	/*Flag              Set if Set    ,Clear if Set,Set if Clear, Clear if Clear  */
815 	{MWM_DECOR_BORDER, AS_Border, 0, 0, AS_Border | AS_Frame},
816 	{MWM_DECOR_RESIZEH, AS_Handles, 0, 0, AS_Handles},
817 	{MWM_DECOR_TITLE, AS_Titlebar, 0, 0, AS_Titlebar},
818 	{0, 0, 0, 0, 0}
819 };
820 
821 static ASFlagsXref mwm_decor_func_xref[] = {	/*Flag              Set if Set,  Clear if Set, Set if Clear, Clear if Clear  */
822 	{MWM_DECOR_RESIZEH, AS_FuncResize, 0, 0, AS_Handles},
823 	{MWM_DECOR_MENU, AS_FuncPopup, 0, 0, AS_FuncPopup},
824 	{MWM_DECOR_MINIMIZE, AS_FuncMinimize, 0, 0, AS_FuncMinimize},
825 	{MWM_DECOR_MAXIMIZE, AS_FuncMaximize, 0, 0, AS_FuncMaximize},
826 	{0, 0, 0, 0, 0}
827 };
828 
829 static ASFlagsXref mwm_func_xref[] = {	/*Flag              Set if Set,  Clear if Set, Set if Clear, Clear if Clear  */
830 	{MWM_FUNC_RESIZE, AS_FuncResize, 0, 0, AS_FuncResize},
831 	{MWM_FUNC_MOVE, AS_FuncMove, 0, 0, AS_FuncMove},
832 	{MWM_FUNC_MINIMIZE, AS_FuncMinimize, 0, 0, AS_FuncMinimize},
833 	{MWM_FUNC_MAXIMIZE, AS_FuncMaximize, 0, 0, AS_FuncMaximize},
834 	{MWM_FUNC_CLOSE, AS_FuncClose | AS_FuncKill, 0, 0,
835 	 AS_FuncClose | AS_FuncKill},
836 	{0, 0, 0, 0, 0}
837 };
838 
839 static void
merge_motif_hints(ASHints * clean,ASRawHints * raw,ASDatabaseRecord * db_rec,ASStatusHints * status,ASFlagType what)840 merge_motif_hints (ASHints * clean, ASRawHints * raw,
841 									 ASDatabaseRecord * db_rec, ASStatusHints * status,
842 									 ASFlagType what)
843 {
844 	CARD32 decor = MWM_DECOR_EVERYTHING;
845 	CARD32 funcs = MWM_FUNC_EVERYTHING;
846 
847 	if (raw == NULL)
848 		return;
849 	if (raw->motif_hints) {
850 		INT32 input_mode = 0;
851 
852 		if (get_flags (raw->motif_hints->flags, MWM_HINTS_INPUT_MODE))
853 			input_mode = raw->motif_hints->inputMode;
854 
855 		if (get_flags (what, HINT_STARTUP) && status && input_mode != 0) {
856 			if (input_mode == MWM_INPUT_SYSTEM_MODAL) {
857 				status->layer = AS_LayerUrgent;
858 				set_flags (status->flags, AS_StartLayer);
859 				set_flags (status->flags, AS_StartsSticky);
860 			}
861 			if (input_mode == MWM_INPUT_FULL_APPLICATION_MODAL) {
862 				status->layer = AS_LayerTop;
863 				set_flags (status->flags, AS_StartLayer);
864 			}
865 		}
866 
867 		check_motif_hints_sanity (raw->motif_hints);
868 
869 		if (get_flags (raw->motif_hints->flags, MWM_HINTS_FUNCTIONS))
870 			funcs = raw->motif_hints->functions;
871 		if (get_flags (raw->motif_hints->flags, MWM_HINTS_DECORATIONS))
872 			decor = raw->motif_hints->decorations;
873 
874 		/* finally we can apply conglomerated hints to our flags : */
875 		if (get_flags (what, HINT_GENERAL)) {
876 			decode_simple_flags (&(clean->flags), mwm_decor_xref, decor);
877 			LOCAL_DEBUG_OUT ("motif decor = 0x%lX, clean_flags = 0x%lX", decor,
878 											 clean->flags);
879 		}
880 		if (get_flags (what, HINT_PROTOCOL)) {
881 			decode_simple_flags (&(clean->function_mask), mwm_decor_func_xref,
882 													 decor);
883 			decode_simple_flags (&(clean->function_mask), mwm_func_xref, funcs);
884 		}
885 	}
886 }
887 
888 static ASFlagsXref gnome_state_xref[] = {	/*Flag                    Set if Set,  Clear if Set, Set if Clear, Clear if Clear  */
889 	{WIN_STATE_STICKY, AS_StartsSticky, 0, 0, 0},
890 	{WIN_STATE_MINIMIZED, AS_StartsIconic, 0, 0, 0},
891 	{WIN_STATE_MAXIMIZED_VERT, AS_StartsMaximizedY, 0, 0, 0},
892 	{WIN_STATE_MAXIMIZED_HORIZ, AS_StartsMaximizedX, 0, 0, 0},
893 	{WIN_STATE_HIDDEN, 0, 0, 0, 0},
894 	{WIN_STATE_SHADED, AS_StartsShaded, 0, 0, 0},
895 	{WIN_STATE_HID_WORKSPACE, 0, 0, 0, 0},
896 	{WIN_STATE_HID_TRANSIENT, 0, 0, 0, 0},
897 	{WIN_STATE_FIXED_POSITION, 0, 0, 0, 0},
898 	{WIN_STATE_ARRANGE_IGNORE, 0, 0, 0, 0},
899 	{0, 0, 0, 0, 0}
900 };
901 
902 static ASFlagsXref gnome_hints_xref[] = {	/*Flag                    Set if Set,  Clear if Set, Set if Clear, Clear if Clear  */
903 	{WIN_HINTS_SKIP_FOCUS, 0, AS_AcceptsFocus, 0, 0},
904 	{WIN_HINTS_SKIP_WINLIST, AS_SkipWinList, 0, 0, 0},
905 	{WIN_HINTS_SKIP_TASKBAR, AS_SkipWinList, 0, 0, 0},
906 	{WIN_HINTS_GROUP_TRANSIENT, 0, 0, 0, 0},
907 	{WIN_HINTS_FOCUS_ON_CLICK, AS_ClickToFocus, 0, 0, 0},
908 	{0, 0, 0, 0, 0}
909 };
910 
911 #define GNOME_AFFECTED_STATE  (AS_StartsSticky|AS_StartsIconic| \
912 							   AS_StartsMaximizedY|AS_StartsMaximizedX| \
913 							   AS_StartsShaded)
914 
915 Bool
decode_gnome_state(ASFlagType state,ASHints * clean,ASStatusHints * status)916 decode_gnome_state (ASFlagType state, ASHints * clean,
917 										ASStatusHints * status)
918 {
919 	Bool changed = False;
920 	ASFlagType new_state = 0, disable_func = 0;
921 
922 	decode_simple_flags (&new_state, gnome_state_xref, state);
923 	if ((new_state ^ (status->flags & GNOME_AFFECTED_STATE)) != 0) {
924 		changed = True;
925 		status->flags = new_state | (status->flags & ~GNOME_AFFECTED_STATE);
926 	}
927 	if (get_flags (new_state, WIN_STATE_FIXED_POSITION))
928 		disable_func = AS_FuncMove;
929 
930 	if ((disable_func ^ (clean->function_mask & AS_FuncMove)) != 0) {
931 		changed = True;
932 		clean->function_mask =
933 				disable_func | (clean->function_mask & ~AS_FuncMove);
934 	}
935 	return changed;
936 }
937 
938 static ASFlagType
encode_gnome_state(ASHints * clean,ASStatusHints * status)939 encode_gnome_state (ASHints * clean, ASStatusHints * status)
940 {
941 	ASFlagType new_state = 0;
942 
943 	if (status)
944 		encode_simple_flags (&new_state, gnome_state_xref, status->flags);
945 
946 	if (get_flags (clean->function_mask, AS_FuncMove))
947 		set_flags (new_state, WIN_STATE_FIXED_POSITION);
948 
949 	return new_state;
950 }
951 
952 static void
merge_gnome_hints(ASHints * clean,ASRawHints * raw,ASDatabaseRecord * db_rec,ASStatusHints * status,ASFlagType what)953 merge_gnome_hints (ASHints * clean, ASRawHints * raw,
954 									 ASDatabaseRecord * db_rec, ASStatusHints * status,
955 									 ASFlagType what)
956 {
957 	register GnomeHints *gh;
958 
959 	if (raw == NULL)
960 		return;
961 	gh = &(raw->gnome_hints);
962 	if (gh->flags == 0)
963 		return;
964 
965 	if (get_flags (what, HINT_STARTUP) && status != NULL) {
966 		if (get_flags (gh->flags, GNOME_LAYER)) {
967 			status->layer = gh->layer;	/*No clue why we used to do that  :  (gh->layer - WIN_LAYER_NORMAL) >> 1; */
968 			set_flags (status->flags, AS_StartLayer);
969 		}
970 		if (get_flags (gh->flags, GNOME_WORKSPACE)) {
971 			status->desktop = gh->workspace;
972 			set_flags (status->flags, AS_StartDesktop);
973 		}
974 		if (get_flags (gh->flags, GNOME_STATE) && gh->state != 0) {
975 			decode_gnome_state (gh->state, clean, status);
976 		}
977 	}
978 
979 	if (get_flags (what, HINT_GENERAL)) {
980 		if (get_flags (gh->flags, GNOME_HINTS) && gh->hints != 0) {
981 			decode_simple_flags (&(clean->flags), gnome_hints_xref, gh->hints);
982 			if (get_flags (gh->hints, WIN_HINTS_SKIP_FOCUS))
983 				clear_flags (clean->protocols, AS_DoesWmTakeFocus);
984 		}
985 	}
986 }
987 
988 static void
merge_kde_hints(ASHints * clean,ASRawHints * raw,ASDatabaseRecord * db_rec,ASStatusHints * status,ASFlagType what)989 merge_kde_hints (ASHints * clean, ASRawHints * raw,
990 								 ASDatabaseRecord * db_rec, ASStatusHints * status,
991 								 ASFlagType what)
992 {
993 	register KDEHints *kh;
994 
995 	if (raw == NULL)
996 		return;
997 	kh = &(raw->kde_hints);
998 	if (kh->flags == 0)
999 		return;
1000 
1001 	if (get_flags (what, HINT_STARTUP) && status != NULL) {
1002 		if (get_flags (kh->flags, KDE_SysTrayWindowFor))
1003 			set_flags (status->flags, AS_StartsSticky);
1004 	}
1005 
1006 	if (get_flags (what, HINT_GENERAL)) {
1007 		if (get_flags (kh->flags, KDE_DesktopWindow))
1008 			set_flags (clean->protocols, AS_DoesKIPC);
1009 		if (get_flags (kh->flags, KDE_SysTrayWindowFor)) {
1010 			set_flags (clean->flags, AS_SkipWinList | AS_DontCirculate);
1011 			clear_flags (clean->flags, AS_Handles | AS_Frame);
1012 		}
1013 	}
1014 }
1015 
1016 static ASFlagsXref extwm_state_xref[] = {	/*Flag                    Set if Set,  Clear if Set, Set if Clear, Clear if Clear  */
1017 	{EXTWM_StateSticky, AS_StartsSticky, 0, 0, 0},
1018 	{EXTWM_StateMaximizedV, AS_StartsMaximizedY, 0, 0, 0},
1019 	{EXTWM_StateMaximizedH, AS_StartsMaximizedX, 0, 0, 0},
1020 	{EXTWM_StateShaded, AS_StartsShaded, 0, 0, 0},
1021 	{EXTWM_StateFullscreen, AS_Fullscreen, 0, 0, 0},
1022 	{EXTWM_StateDemandsAttention, AS_Urgent, 0, 0, 0},
1023 	{0, 0, 0, 0, 0}
1024 };
1025 
1026 #define EXTWM_AFFECTED_STATE  (AS_StartsSticky|AS_StartsMaximizedY| \
1027 							   AS_StartsMaximizedX|AS_StartsShaded|AS_Fullscreen)
1028 
1029 static ASFlagType extwm_types_start_properties[][3] = {
1030 	{EXTWM_TypeDesktop, AS_LayerOtherDesktop, AS_StartsSticky},
1031 	{EXTWM_TypeDock, AS_LayerService, AS_StartsSticky},
1032 	{EXTWM_TypeToolbar, AS_LayerNormal, 0},
1033 	{EXTWM_TypeMenu, AS_LayerUrgent, AS_StartsSticky},
1034 	{EXTWM_TypeDialog, AS_LayerTop, 0},
1035 	{EXTWM_TypeNormal, AS_LayerNormal, 0},
1036 	{EXTWM_TypeUtility, AS_LayerTop, 0},
1037 	{EXTWM_TypeSplash, AS_LayerTop, AS_ShortLived},
1038 	{EXTWM_TypeASModule, AS_LayerNormal, AS_StartsSticky},
1039 	{0, 0, 0}
1040 };
1041 
1042 static ASFlagType extwm_states_start_properties[][3] = {
1043 	{EXTWM_StateFullscreen, AS_LayerUrgent, AS_Fullscreen},
1044 	{EXTWM_StateAbove, AS_LayerTop, 0},
1045 	{EXTWM_StateBelow, AS_LayerBack, 0},
1046 	{EXTWM_StateDemandsAttention, AS_LayerUrgent, 0},
1047 	{0, 0, 0}
1048 };
1049 
1050 static ASFlagsXref extwm_type_xref[] = {	/*Flag              Set if Set,      Clear if Set,     Set if Clear,    Clear if Clear  */
1051 	{EXTWM_TypeDesktop, AS_SkipWinList | AS_DontCirculate,
1052 	 AS_Titlebar | AS_Handles | AS_Frame, 0, 0},
1053 	{EXTWM_TypeDock, AS_AvoidCover, AS_Handles | AS_Frame | AS_Titlebar, 0,
1054 	 0},
1055 	{EXTWM_TypeToolbar, 0, AS_Handles | AS_Frame, 0, 0},
1056 	{EXTWM_TypeMenu, AS_SkipWinList | AS_DontCirculate,
1057 	 AS_Handles | AS_Frame, 0, 0},
1058 	{EXTWM_TypeDialog, AS_ShortLived, 0 /*may need to remove handles */ , 0,
1059 	 0},
1060 	{EXTWM_TypeASModule, AS_Module, 0, 0, AS_Module},
1061 	{0, 0, 0, 0, 0}
1062 };
1063 
1064 static ASFlagsXref extwm_type_func_mask[] = {	/*Flag             Set if Set,  Clear if Set,     Set if Clear  , Clear if Clear  */
1065 	{EXTWM_TypeDesktop, 0,
1066 	 AS_FuncResize | AS_FuncMinimize | AS_FuncMaximize | AS_FuncMove, 0, 0},
1067 	{EXTWM_TypeDock, 0, AS_FuncResize | AS_FuncMinimize | AS_FuncMaximize, 0,
1068 	 0},
1069 	{EXTWM_TypeToolbar, 0, AS_FuncResize, 0, 0},
1070 	{EXTWM_TypeMenu, 0, AS_FuncResize | AS_FuncMinimize | AS_FuncMaximize, 0,
1071 	 0},
1072 	{0, 0, 0, 0, 0}
1073 };
1074 
extwm_state2as_state_flags(ASFlagType extwm_flags)1075 ASFlagType extwm_state2as_state_flags (ASFlagType extwm_flags)
1076 {
1077 	ASFlagType as_flags = 0;
1078 
1079 	decode_simple_flags (&as_flags, extwm_state_xref, extwm_flags);
1080 	return as_flags;
1081 }
1082 
select_client_icon_argb(CARD32 * icon,int icon_length)1083 static CARD32 *select_client_icon_argb (CARD32 * icon, int icon_length)
1084 {
1085 	int offset = 0;
1086 	CARD32 *res = NULL;
1087 
1088 	if (icon == NULL || icon_length <= 2)
1089 		return NULL;
1090 	while (res == NULL && offset + 2 < icon_length) {
1091 		int width = icon[offset];
1092 		int height = icon[offset + 1];
1093 		int len = width * height;
1094 
1095 		if (len < 0)
1096 			break;
1097 		if (len <= (icon_length - offset - 2))
1098 			if (width == 48 && height == 48) {
1099 				res = safemalloc ((2 + len) * sizeof (CARD32));
1100 				memcpy (res, &(icon[offset]), (2 + len) * sizeof (CARD32));
1101 			}
1102 		offset += 2 + len;
1103 	}
1104 	offset = 0;
1105 	while (res == NULL && offset + 2 < icon_length) {
1106 		int width = icon[offset];
1107 		int height = icon[offset + 1];
1108 		int len = width * height;
1109 
1110 		if (len < 0)
1111 			break;
1112 		if (len <= (icon_length - offset - 2))
1113 			if (width >= 32 && height >= 32) {
1114 				res = safemalloc ((2 + len) * sizeof (CARD32));
1115 				memcpy (res, &(icon[offset]), (2 + len) * sizeof (CARD32));
1116 			}
1117 		offset += 2 + len;
1118 	}
1119 	if (res == NULL) {
1120 		int width = icon[0];
1121 		int height = icon[1];
1122 		int size = width * height;
1123 
1124 		icon_length -= 2;
1125 		if (size > 0) {
1126 			if (size + 2 > icon_length) {
1127 				for (width = 128; width > 0; width -= 8)
1128 					if (icon_length > width * width) {
1129 						height = width;
1130 						size = width * width;
1131 						break;
1132 					}
1133 			}
1134 			res = safecalloc (size + 2, sizeof (CARD32));
1135 			memcpy (res + 2, &(icon[2]), size * sizeof (CARD32));
1136 			res[0] = width;
1137 			res[1] = height;
1138 		}
1139 	}
1140 	return res;
1141 }
1142 
1143 static void
merge_extwm_hints(ASHints * clean,ASRawHints * raw,ASDatabaseRecord * db_rec,ASStatusHints * status,ASFlagType what)1144 merge_extwm_hints (ASHints * clean, ASRawHints * raw,
1145 									 ASDatabaseRecord * db_rec, ASStatusHints * status,
1146 									 ASFlagType what)
1147 {
1148 
1149 	register ExtendedWMHints *eh;
1150 
1151 	if (raw == NULL)
1152 		return;
1153 	eh = &(raw->extwm_hints);
1154 
1155 	if (get_flags (what, HINT_NAME)) {
1156 		if (eh->name)
1157 			add_name_to_list (clean, stripcpy ((const char *)(eh->name->value)),
1158 												AS_Text_UTF8, True);
1159 		if (eh->visible_name)
1160 			add_name_to_list (clean,
1161 												stripcpy ((const char *)(eh->visible_name->value)),
1162 												AS_Text_UTF8, True);
1163 		if (eh->icon_name)
1164 			clean->icon_name_idx =
1165 					add_name_to_list (clean,
1166 														stripcpy ((const char *)(eh->
1167 																										 icon_name->value)),
1168 														AS_Text_UTF8, False);
1169 		if (eh->visible_icon_name)
1170 			clean->icon_name_idx =
1171 					add_name_to_list (clean,
1172 														stripcpy ((const char
1173 																			 *)(eh->visible_icon_name->value)),
1174 														AS_Text_UTF8, False);
1175 		clean->icon_name =
1176 				(clean->icon_name_idx <
1177 				 0) ? NULL : clean->names[clean->icon_name_idx];
1178 	}
1179 
1180 	if (get_flags (what, HINT_STARTUP) && status != NULL) {
1181 		if (get_flags (eh->flags, EXTWM_DESKTOP)) {
1182 			LOCAL_DEBUG_OUT ("EXTWM Hints Desktop = 0x%X", eh->desktop);
1183 			if (eh->desktop == 0xFFFFFFFF)
1184 				set_flags (status->flags, AS_StartsSticky);
1185 			else {
1186 				status->desktop = eh->desktop;
1187 				set_flags (status->flags, AS_StartDesktop);
1188 			}
1189 		}
1190 		/* window state hints : */
1191 		if (get_flags (eh->flags, EXTWM_StateSet)) {
1192 			if (get_flags (eh->state_flags, EXTWM_StateModal)) {
1193 				status->layer = AS_LayerTop;
1194 				set_flags (status->flags, AS_StartLayer);
1195 			}
1196 			decode_simple_flags (&(status->flags), extwm_state_xref,
1197 													 eh->state_flags);
1198 		}
1199 		/* window type hints : */
1200 		if (get_flags
1201 				(eh->type_flags, (EXTWM_TypeEverything & (~EXTWM_TypeNormal)))) {
1202 			register int i;
1203 
1204 			for (i = 0; extwm_types_start_properties[i][0] != 0; i++)
1205 				if (get_flags (eh->type_flags, extwm_types_start_properties[i][0])) {
1206 					if (!get_flags (status->flags, AS_StartLayer)
1207 							|| status->layer < extwm_types_start_properties[i][1])
1208 						status->layer = extwm_types_start_properties[i][1];
1209 					set_flags (status->flags, AS_StartLayer);
1210 					set_flags (status->flags, extwm_types_start_properties[i][2]);
1211 				}
1212 		}
1213 		if (get_flags
1214 				(eh->state_flags,
1215 				 EXTWM_StateFullscreen | EXTWM_StateAbove | EXTWM_StateBelow)) {
1216 			register int i;
1217 
1218 			for (i = 0; extwm_states_start_properties[i][0] != 0; i++)
1219 				if (get_flags
1220 						(eh->state_flags, extwm_states_start_properties[i][0])) {
1221 					if (!get_flags (status->flags, AS_StartLayer)
1222 							|| status->layer < extwm_states_start_properties[i][1])
1223 						status->layer = extwm_states_start_properties[i][1];
1224 					set_flags (status->flags, AS_StartLayer);
1225 					set_flags (status->flags, extwm_states_start_properties[i][2]);
1226 				}
1227 		}
1228 	}
1229 	if (get_flags (what, HINT_GENERAL)) {
1230 		if (get_flags (eh->flags, EXTWM_PID)) {
1231 			clean->pid = eh->pid;
1232 			set_flags (clean->flags, AS_PID);
1233 		}
1234 		if (get_flags (eh->flags, EXTWM_WINDOW_OPACITY)) {
1235 			clean->window_opacity = eh->window_opacity;
1236 			set_flags (clean->flags, AS_WindowOpacity);
1237 		}
1238 		if (get_flags (eh->flags, EXTWM_ICON)) {
1239 			if (clean->icon_argb)
1240 				free (clean->icon_argb);
1241 			clean->icon_argb =
1242 					select_client_icon_argb (eh->icon, eh->icon_length);
1243 			set_flags (clean->flags, AS_Icon);
1244 			set_flags (clean->client_icon_flags,
1245 								 AS_ClientIcon | AS_ClientIconARGB);
1246 		}
1247 		if (get_flags (eh->state_flags, EXTWM_StateSkipTaskbar))
1248 			set_flags (clean->flags, AS_SkipWinList);
1249 
1250 		if (get_flags (eh->flags, EXTWM_TypeSet)) {
1251 			clean->extwm_window_type = eh->type_flags;
1252 			decode_simple_flags (&(clean->flags), extwm_type_xref,
1253 													 eh->type_flags);
1254 		}
1255 	}
1256 	if (get_flags (what, HINT_PROTOCOL)) {
1257 		if (get_flags (eh->flags, EXTWM_DoesWMPing))
1258 			set_flags (clean->protocols, AS_DoesWmPing);
1259 		if (get_flags (eh->flags, EXTWM_NAME) && eh->name != NULL)
1260 			set_flags (clean->protocols, AS_NeedsVisibleName);
1261 		if (get_flags (eh->flags, EXTWM_VISIBLE_NAME)
1262 				&& eh->visible_name != NULL)
1263 			set_flags (clean->protocols, AS_NeedsVisibleName);
1264 		if (get_flags (eh->flags, EXTWM_TypeSet))
1265 			decode_simple_flags (&(clean->function_mask), extwm_type_func_mask,
1266 													 eh->type_flags);
1267 	}
1268 }
1269 
1270 static void
merge_xresources_hints(ASHints * clean,ASRawHints * raw,ASDatabaseRecord * db_rec,ASStatusHints * status,ASFlagType what)1271 merge_xresources_hints (ASHints * clean, ASRawHints * raw,
1272 												ASDatabaseRecord * db_rec, ASStatusHints * status,
1273 												ASFlagType what)
1274 {
1275 	XrmDatabase db = NULL;
1276 	extern XrmDatabase as_xrm_user_db;
1277 	char *rm_string;
1278 
1279 
1280 	if (raw == NULL || status == NULL || !get_flags (what, HINT_STARTUP))
1281 		return;
1282 
1283 	init_xrm ();
1284 
1285 	if ((rm_string = XResourceManagerString (dpy)) != NULL)
1286 		db = XrmGetStringDatabase (rm_string);
1287 	else
1288 		db = as_xrm_user_db;
1289 
1290 	if (db) {
1291 		get_afterstep_resources (db, status);
1292 		if (db != as_xrm_user_db)
1293 			XrmDestroyDatabase (db);
1294 	}
1295 }
1296 
1297 CARD32
set_hints_window_opacity_percent(ASHints * clean,int opaque_percent)1298 set_hints_window_opacity_percent (ASHints * clean, int opaque_percent)
1299 {
1300 	CARD32 res = NET_WM_WINDOW_OPACITY_OPAQUE;
1301 
1302 	if (opaque_percent <= 0)
1303 		res = 0;
1304 	else if (opaque_percent < 100)
1305 		res = (NET_WM_WINDOW_OPACITY_OPAQUE / 100) * opaque_percent;
1306 	if (clean) {
1307 		clean->window_opacity = res;
1308 		set_flags (clean->flags, AS_WindowOpacity);
1309 	}
1310 	return res;
1311 }
1312 
1313 
1314 void
merge_asdb_hints(ASHints * clean,ASRawHints * raw,ASDatabaseRecord * db_rec,ASStatusHints * status,ASFlagType what)1315 merge_asdb_hints (ASHints * clean, ASRawHints * raw,
1316 									ASDatabaseRecord * db_rec, ASStatusHints * status,
1317 									ASFlagType what)
1318 {
1319 	static ASFlagsXref asdb_startup_xref[] = {	/*Flag                    Set if Set    ,Clear if Set    , Set if Clear, Clear if Clear  */
1320 		{STYLE_STICKY, AS_StartsSticky, 0, 0, AS_StartsSticky},
1321 		{STYLE_START_ICONIC, AS_StartsIconic, 0, 0, AS_StartsIconic},
1322 		{STYLE_PPOSITION, AS_StartPositionUser, 0, 0, AS_StartPosition},
1323 		{STYLE_FULLSCREEN, AS_Fullscreen, 0, 0, AS_Fullscreen},
1324 		{0, 0, 0, 0, 0}
1325 	};
1326 	static ASFlagsXref asdb_hints_xref[] = {	/*Flag                  Set if Set      ,Clear if Set    ,Set if Clear       ,Clear if Clear  */
1327 		{STYLE_TITLE, AS_Titlebar, 0, 0, AS_Titlebar},
1328 		{STYLE_CIRCULATE, 0, AS_DontCirculate, AS_DontCirculate, 0},
1329 		{STYLE_WINLIST, 0, AS_SkipWinList, AS_SkipWinList, 0},
1330 		{STYLE_ICON_TITLE, AS_IconTitle, 0, 0, AS_IconTitle},
1331 		{STYLE_FOCUS, AS_AcceptsFocus, 0, 0, AS_AcceptsFocus},
1332 		{STYLE_AVOID_COVER, AS_AvoidCover, 0, 0, AS_AvoidCover},
1333 		{STYLE_VERTICAL_TITLE, AS_VerticalTitle, 0, 0, AS_VerticalTitle},
1334 		{STYLE_HANDLES, AS_Handles, 0, 0, AS_Handles},
1335 		{STYLE_FOCUS_ON_MAP, AS_FocusOnMap, 0, 0, AS_FocusOnMap},
1336 		{STYLE_LONG_LIVING, 0, AS_ShortLived, AS_ShortLived, 0},
1337 		{STYLE_IGNORE_CONFIG, AS_IgnoreConfigRequest, 0, 0,
1338 		 AS_IgnoreConfigRequest},
1339 		{STYLE_IGNORE_RESTACK, AS_IgnoreRestackRequest, 0, 0,
1340 		 AS_IgnoreRestackRequest},
1341 		{STYLE_CURRENT_VIEWPORT, AS_UseCurrentViewport, 0, 0,
1342 		 AS_UseCurrentViewport},
1343 		{STYLE_PAGER, AS_HitPager, 0, 0, AS_HitPager},
1344 		{0, 0, 0, 0, 0}
1345 	};
1346 
1347 	LOCAL_DEBUG_CALLER_OUT ("0x%lX", what);
1348 
1349 	if (db_rec == NULL)
1350 		return;
1351 	if (get_flags (what, HINT_STARTUP) && status != NULL) {
1352 		if (get_flags (db_rec->set_data_flags, STYLE_STARTUP_DESK)) {
1353 			status->desktop = db_rec->desk;
1354 			set_flags (status->flags, AS_StartDesktop);
1355 		}
1356 		if (get_flags (db_rec->set_data_flags, STYLE_VIEWPORTX)) {
1357 			status->viewport_x = db_rec->viewport_x;
1358 			LOCAL_DEBUG_OUT ("viewport_x = %d", status->viewport_x);
1359 			set_flags (status->flags, AS_StartViewportX);
1360 		}
1361 		if (get_flags (db_rec->set_data_flags, STYLE_VIEWPORTY)) {
1362 			status->viewport_y = db_rec->viewport_y;
1363 			set_flags (status->flags, AS_StartViewportY);
1364 		}
1365 		if (get_flags (db_rec->set_data_flags, STYLE_LAYER)) {
1366 			status->layer = db_rec->layer;
1367 			set_flags (status->flags, AS_StartLayer);
1368 		}
1369 
1370 		/*not exactly clean solution for the default geometry, but I don't see any other way : */
1371 		if (raw != NULL
1372 				&& get_flags (db_rec->set_data_flags, STYLE_DEFAULT_GEOMETRY)
1373 				&& !get_flags (status->flags, AS_StartPositionUser)) {
1374 			register ASGeometry *g = &(db_rec->default_geometry);
1375 
1376 			if (get_flags (g->flags, WidthValue))
1377 				status->width = g->width;
1378 			else if (!get_flags (status->flags, AS_StartSize))	/* defaulting to the startup width */
1379 				status->width = raw->placement.width;
1380 
1381 			if (get_flags (g->flags, HeightValue))
1382 				status->height = g->height;
1383 			else if (!get_flags (status->flags, AS_StartSize))	/* defaulting to the startup height */
1384 				status->height = raw->placement.height;
1385 
1386 			set_flags (status->flags, AS_StartSize);
1387 
1388 			if (get_flags (g->flags, XValue))
1389 				status->x = get_flags (g->flags, XNegative) ?
1390 						raw->scr->MyDisplayWidth - raw->border_width * 2 -
1391 						status->width - g->x : g->x;
1392 			else if (!get_flags (status->flags, AS_StartPosition))
1393 				status->x = raw->placement.x;
1394 
1395 			if (get_flags (g->flags, YValue))
1396 				status->y = get_flags (g->flags, YNegative) ?
1397 						raw->scr->MyDisplayHeight - raw->border_width * 2 -
1398 						status->height - g->y : g->y;
1399 			else if (!get_flags (status->flags, AS_StartPosition))
1400 				status->y = raw->placement.y;
1401 
1402 			if (get_flags (g->flags, YValue | XValue))
1403 				set_flags (status->flags, AS_StartPosition | AS_StartPositionUser);
1404 		}
1405 		/* taking care of startup status flags : */
1406 		decode_flags (&(status->flags), asdb_startup_xref, db_rec->set_flags,
1407 									db_rec->flags);
1408 	}
1409 	if (get_flags (what, HINT_GENERAL)) {
1410 		if (get_flags (db_rec->set_data_flags, STYLE_ICON))
1411 			set_string_value (&(clean->icon_file), mystrdup (db_rec->icon_file),
1412 												&(clean->flags), AS_Icon);
1413 		/* the following should fix NoIcon handling in the database : */
1414 		if (get_flags (db_rec->set_flags, STYLE_ICON)) {
1415 			if (get_flags (db_rec->flags, STYLE_ICON))
1416 				set_flags (clean->flags, AS_Icon);
1417 			else
1418 				clear_flags (clean->flags, AS_Icon);
1419 		}
1420 		if (get_flags (db_rec->set_data_flags, STYLE_BORDER_WIDTH)) {
1421 			clean->border_width = db_rec->border_width;
1422 			set_flags (clean->flags, AS_Border);
1423 		}
1424 		if (get_flags (db_rec->set_data_flags, STYLE_HANDLE_WIDTH)) {
1425 			clean->handle_width = db_rec->resize_width;
1426 			set_flags (clean->flags, AS_Handles);
1427 		}
1428 		if (get_flags (db_rec->set_data_flags, STYLE_GRAVITY)) {
1429 			clean->gravity = db_rec->gravity;
1430 			set_flags (clean->flags, AS_Gravity);
1431 		}
1432 		if (get_flags (db_rec->set_data_flags, STYLE_WINDOW_OPACITY))
1433 			set_hints_window_opacity_percent (clean, db_rec->window_opacity);
1434 
1435 		if (get_flags (db_rec->set_data_flags, STYLE_FRAME))
1436 			set_string_value (&(clean->frame_name),
1437 												mystrdup (db_rec->frame_name), &(clean->flags),
1438 												AS_Frame);
1439 		if (get_flags (db_rec->set_data_flags, STYLE_WINDOWBOX))
1440 			set_string_value (&(clean->windowbox_name),
1441 												mystrdup (db_rec->windowbox_name), &(clean->flags),
1442 												AS_Windowbox);
1443 		if (get_flags (db_rec->set_data_flags, STYLE_MYSTYLES)) {
1444 			register int i;
1445 
1446 			for (i = 0; i < BACK_STYLES; i++)
1447 				if (db_rec->window_styles[i])
1448 					set_string (&(clean->mystyle_names[i]),
1449 											mystrdup (db_rec->window_styles[i]));
1450 		}
1451 		/* taking care of flags : */
1452 		decode_flags (&(clean->flags), asdb_hints_xref, db_rec->set_flags,
1453 									db_rec->flags);
1454 		if (get_flags (db_rec->set_flags, STYLE_FOCUS)
1455 				&& !get_flags (db_rec->flags, STYLE_FOCUS))
1456 			clear_flags (clean->protocols, AS_DoesWmTakeFocus);
1457 
1458 		clean->disabled_buttons = (~(db_rec->buttons)) & (db_rec->set_buttons);
1459 	}
1460 }
1461 
1462 /* Don't forget to Cleanup after yourself : */
destroy_hints(ASHints * clean,Bool reusable)1463 void destroy_hints (ASHints * clean, Bool reusable)
1464 {
1465 	if (clean) {
1466 		register int i;
1467 
1468 		for (i = 0; i < MAX_WINDOW_NAMES; i++)
1469 			if (clean->names[i] == NULL)
1470 				break;
1471 			else
1472 				free (clean->names[i]);
1473 
1474 		if (clean->matched_name0)
1475 			free (clean->matched_name0);
1476 
1477 		if (clean->cmap_windows)
1478 			free (clean->cmap_windows);
1479 		if (clean->icon_file)
1480 			free (clean->icon_file);
1481 		if (clean->icon_argb)
1482 			free (clean->icon_argb);
1483 		if (clean->frame_name)
1484 			free (clean->frame_name);
1485 		if (clean->windowbox_name)
1486 			free (clean->windowbox_name);
1487 		for (i = 0; i < BACK_STYLES; i++)
1488 			if (clean->mystyle_names[i])
1489 				free (clean->mystyle_names[i]);
1490 
1491 		if (clean->client_host)
1492 			free (clean->client_host);
1493 		if (clean->client_cmd)
1494 			free (clean->client_cmd);
1495 
1496 		if (reusable)								/* we are being paranoid */
1497 			memset (clean, 0x00, sizeof (ASHints));
1498 		else
1499 			free (clean);
1500 	}
1501 }
1502 
1503 Bool
update_property_hints(Window w,Atom property,ASHints * hints,ASStatusHints * status)1504 update_property_hints (Window w, Atom property, ASHints * hints,
1505 											 ASStatusHints * status)
1506 {
1507 	ASRawHints raw;
1508 	Bool changed = False;
1509 
1510 	if (status == NULL || hints == NULL)
1511 		return False;
1512 	memset (&raw, 0x00, sizeof (ASRawHints));
1513 	raw.wm_state_icon_win = status->icon_window;
1514 	raw.scr = ASDefaultScr;
1515 	if (handle_client_property_update (w, property, &raw)) {
1516 		/* Here we are only interested in properties updtaed by the Window Manager : */
1517 		if (property == _XA_WM_STATE) {
1518 			unsigned long new_state =
1519 					(raw.wm_state == IconicState) ? AS_Iconic : 0;
1520 
1521 			if ((changed = ((new_state ^ (status->flags & AS_Iconic)) != 0 ||
1522 											raw.wm_state_icon_win != status->icon_window))) {
1523 				status->icon_window = raw.wm_state_icon_win;
1524 				status->flags = (status->flags & (~AS_Iconic)) | new_state;
1525 			}
1526 		} else if (property == _XA_WIN_LAYER) {
1527 			if ((changed = (raw.gnome_hints.layer != status->layer)))
1528 				status->layer = raw.gnome_hints.layer;
1529 		} else if (property == _XA_WIN_STATE) {
1530 			changed = decode_gnome_state (raw.gnome_hints.state, hints, status);
1531 		} else if (property == _XA_WIN_WORKSPACE) {
1532 			if ((changed = (raw.gnome_hints.workspace != status->desktop)))
1533 				status->desktop = raw.gnome_hints.workspace;
1534 		} else if (property == _XA_NET_WM_DESKTOP) {	/* Extended WM-Hints : */
1535 			if ((changed = (raw.extwm_hints.desktop != status->desktop)))
1536 				status->desktop = raw.extwm_hints.desktop;
1537 		} else if (property == _XA_NET_WM_STATE) {
1538 			ASFlagType new_state = 0;
1539 
1540 			decode_simple_flags (&new_state, extwm_state_xref,
1541 													 raw.extwm_hints.state_flags);
1542 			if ((changed =
1543 					 (((status->flags & EXTWM_AFFECTED_STATE) ^ new_state) != 0)))
1544 				status->flags = new_state | (status->flags & EXTWM_AFFECTED_STATE);
1545 		}
1546 		destroy_raw_hints (&raw, True);
1547 
1548 	}
1549 	return changed;
1550 }
1551 
1552 /* same as above only for window manager : */
1553 void
update_cmd_line_hints(Window w,Atom property,ASHints * hints,ASStatusHints * status)1554 update_cmd_line_hints (Window w, Atom property, ASHints * hints,
1555 											 ASStatusHints * status)
1556 {
1557 	ASRawHints raw;
1558 
1559 	memset (&raw, 0x00, sizeof (ASRawHints));
1560 	raw.scr = ASDefaultScr;
1561 	show_debug (__FILE__, __FUNCTION__, __LINE__,
1562 							"trying to handle property change for WM_COMMAND");
1563 	if (handle_manager_property_update (w, property, &raw)) {
1564 		merge_command_line (hints, status, &raw);
1565 		destroy_raw_hints (&raw, True);
1566 	}
1567 }
1568 
1569 /* same as above only for window manager : */
1570 Bool
update_property_hints_manager(Window w,Atom property,ASSupportedHints * list,ASDatabase * db,ASHints * hints,ASStatusHints * status)1571 update_property_hints_manager (Window w, Atom property,
1572 															 ASSupportedHints * list, ASDatabase * db,
1573 															 ASHints * hints, ASStatusHints * status)
1574 {
1575 	ASRawHints raw;
1576 	Bool changed = False;
1577 
1578 	memset (&raw, 0x00, sizeof (ASRawHints));
1579 	raw.scr = ASDefaultScr;
1580 	if (status)
1581 		raw.wm_state_icon_win = status->icon_window;
1582 	show_debug (__FILE__, __FUNCTION__, __LINE__,
1583 							"trying to handle property change");
1584 	if (handle_manager_property_update (w, property, &raw)) {
1585 		ASHints clean;
1586 
1587 		memset (&clean, 0x00, sizeof (ASHints));
1588 		clean.res_name_idx = clean.res_class_idx = clean.icon_name_idx = -1;
1589 
1590 		show_debug (__FILE__, __FUNCTION__, __LINE__,
1591 								"property update handled");
1592 		if (property == _XA_WM_STATE) {
1593 			if (status) {
1594 				unsigned long new_state =
1595 						(raw.wm_state == IconicState) ? AS_Iconic : 0;
1596 
1597 				if ((changed = ((new_state ^ (status->flags & AS_Iconic)) != 0 ||
1598 												raw.wm_state_icon_win != status->icon_window))) {
1599 					status->icon_window = raw.wm_state_icon_win;
1600 					status->flags = (status->flags & (~AS_Iconic)) | new_state;
1601 				}
1602 			}
1603 			return changed;
1604 		}
1605 		if (hints
1606 				&& merge_hints (&raw, db, NULL, list, HINT_ANY, &clean,
1607 												w) != NULL) {
1608 			show_debug (__FILE__, __FUNCTION__, __LINE__, "hints merged");
1609 			if (IsNameProp (property)) {
1610 				int i;
1611 
1612 				if (hints->names_encoding[0] == clean.names_encoding[0] &&
1613 						mystrcmp (hints->names[0], clean.names[0]) != 0)
1614 					changed = True;
1615 				else if (mystrcmp (hints->res_name, clean.res_name) != 0)
1616 					changed = True;
1617 				else if (mystrcmp (hints->res_class, clean.res_class) != 0)
1618 					changed = True;
1619 				else if (mystrcmp (hints->icon_name, clean.icon_name) != 0)
1620 					changed = True;
1621 
1622 				for (i = 0; i <= MAX_WINDOW_NAMES; ++i)
1623 					if (hints->names[i] != NULL) {
1624 						free (hints->names[i]);
1625 						hints->names[i] = NULL;
1626 					} else
1627 						break;
1628 
1629 				for (i = 0; i <= MAX_WINDOW_NAMES; ++i) {
1630 					hints->names_encoding[i] = clean.names_encoding[i];
1631 					hints->names[i] = clean.names[i];
1632 					clean.names[i] = NULL;
1633 				}
1634 				hints->res_name = clean.res_name;
1635 				hints->res_name_idx = clean.res_name_idx;
1636 				hints->res_class = clean.res_class;
1637 				hints->res_class_idx = clean.res_class_idx;
1638 				hints->icon_name = clean.icon_name;
1639 				hints->icon_name_idx = clean.icon_name_idx;
1640 				show_debug (__FILE__, __FUNCTION__, __LINE__, "names set");
1641 
1642 				/* Must not do that as it requires sugnificant changes in decorations and stuff :
1643 				 * and should be done only when FollowTitleChanges is requested */
1644 				/* hints->flags = clean.flags ;
1645 				   hints->function_mask = clean.function_mask ;
1646 				 */
1647 			} else if (property == XA_WM_HINTS) {
1648 
1649 			} else if (property == XA_WM_NORMAL_HINTS) {
1650 
1651 			} else if (property == _XA_WM_PROTOCOLS) {
1652 
1653 			} else if (property == _XA_WM_COLORMAP_WINDOWS) {
1654 			}
1655 		}
1656 		destroy_hints (&clean, True);
1657 		destroy_raw_hints (&raw, True);
1658 	} else
1659 		show_debug (__FILE__, __FUNCTION__, __LINE__,
1660 								"failed to handle property update");
1661 
1662 	return changed;
1663 }
1664 
compare_strings(char * str1,char * str2)1665 static Bool compare_strings (char *str1, char *str2)
1666 {
1667 	if (str1 != NULL && str2 != NULL)
1668 		return (strcmp (str1, str2) != 0);
1669 	return (str1 != str2);
1670 }
1671 
compare_names(ASHints * old,ASHints * hints)1672 Bool compare_names (ASHints * old, ASHints * hints)
1673 {
1674 	register int i;
1675 
1676 	if (old != NULL && hints != NULL) {
1677 		for (i = 0; i < MAX_WINDOW_NAMES; i++)
1678 			if (compare_strings (old->names[i], hints->names[i]))
1679 				return True;
1680 			else if (old->names[i] == NULL)
1681 				break;
1682 	} else if (old != hints)
1683 		return True;
1684 
1685 	return False;
1686 }
1687 
compare_hints(ASHints * old,ASHints * hints)1688 ASFlagType compare_hints (ASHints * old, ASHints * hints)
1689 {
1690 	ASFlagType changed = 0;
1691 
1692 	if (old != NULL && hints != NULL) {
1693 		if (compare_strings (old->names[0], hints->names[0]))
1694 			set_flags (changed, AS_HintChangeName);
1695 		if (compare_strings (old->res_class, hints->res_class))
1696 			set_flags (changed, AS_HintChangeClass);
1697 		if (compare_strings (old->res_name, hints->res_name))
1698 			set_flags (changed, AS_HintChangeResName);
1699 		if (compare_strings (old->icon_name, hints->icon_name))
1700 			set_flags (changed, AS_HintChangeIconName);
1701 	} else if (old != hints)
1702 		changed = AS_HintChangeEverything;
1703 	return changed;
1704 }
1705 
function2mask(int function)1706 ASFlagType function2mask (int function)
1707 {
1708 	static ASFlagType as_function_masks[F_PIN_MENU + 1 -
1709 																			F_WINDOW_FUNC_START] = {
1710 		AS_FuncMove,								/* F_MOVE,               30 */
1711 		AS_FuncResize,							/* F_RESIZE,             */
1712 		0,													/* F_RAISE,              */
1713 		0,													/* F_LOWER,              */
1714 		0,													/* F_RAISELOWER,         */
1715 		0,													/* F_PUTONTOP,           */
1716 		0,													/* F_PUTONBACK,          */
1717 		0,													/* F_SETLAYER,           */
1718 		0,													/* F_TOGGLELAYER,        */
1719 		0,													/* F_SHADE,              */
1720 		AS_FuncKill,								/* F_DELETE,             */
1721 		0,													/* F_DESTROY,            */
1722 		AS_FuncClose,								/* F_CLOSE,              */
1723 		AS_FuncMinimize,						/* F_ICONIFY,            */
1724 		AS_FuncMaximize,						/* F_MAXIMIZE,           */
1725 		AS_FuncMaximize,						/* F_FULLSCREEN,         */
1726 		0,													/* F_STICK,              */
1727 		0,													/* F_FOCUS,              */
1728 		0,													/* F_CHANGEWINDOW_UP     */
1729 		0,													/* F_CHANGEWINDOW_DOWN   */
1730 		0,													/* F_GOTO_BOOKMARK     */
1731 		0,													/* F_GETHELP,            */
1732 		0,													/* F_PASTE_SELECTION,    */
1733 		0,													/* F_CHANGE_WINDOWS_DESK, */
1734 		0,													/* F_BOOKMARK_WINDOW,  */
1735 		AS_FuncPinMenu							/* F_PIN_MENU           */
1736 	};
1737 
1738 	if (function == F_POPUP)
1739 		return AS_FuncPopup;
1740 	if (function <= F_WINDOW_FUNC_START || function > F_PIN_MENU)
1741 		return 0;
1742 	return as_function_masks[function - (F_WINDOW_FUNC_START + 1)];
1743 }
1744 
1745 /****************************************************************************
1746  * Initial placement/anchor management code
1747  ****************************************************************************/
1748 
1749 void
constrain_size(ASHints * hints,ASStatusHints * status,int max_width,int max_height)1750 constrain_size (ASHints * hints, ASStatusHints * status, int max_width,
1751 								int max_height)
1752 {
1753 	int minWidth = 1, minHeight = 1;
1754 	int xinc = 1, yinc = 1, delta;
1755 	int baseWidth = 0, baseHeight = 0;
1756 	int clean_width =
1757 			status->width - (status->frame_size[FR_W] +
1758 											 status->frame_size[FR_E]);
1759 	int clean_height =
1760 			status->height - (status->frame_size[FR_N] +
1761 												status->frame_size[FR_S]);
1762 
1763 	if (get_flags (hints->flags, AS_MinSize)) {
1764 		if (minWidth < hints->min_width)
1765 			minWidth = hints->min_width;
1766 		if (minHeight < hints->min_height)
1767 			minHeight = hints->min_height;
1768 	} else if (get_flags (hints->flags, AS_BaseSize)) {
1769 		if (minWidth < hints->base_width)
1770 			minWidth = hints->base_width;
1771 		if (minHeight < hints->base_height)
1772 			minHeight = hints->base_height;
1773 	}
1774 
1775 	if (get_flags (hints->flags, AS_BaseSize)) {
1776 		baseWidth = hints->base_width;
1777 		baseHeight = hints->base_height;
1778 	} else if (get_flags (hints->flags, AS_MinSize)) {
1779 		baseWidth = minWidth;
1780 		baseHeight = minHeight;
1781 	}
1782 
1783 	if (get_flags (hints->flags, AS_MaxSize)
1784 			&& !get_flags (status->flags, AS_Fullscreen)) {
1785 		if (max_width == 0 || max_width > hints->max_width)
1786 			max_width = hints->max_width;
1787 		if (max_height == 0 || max_height > hints->max_height)
1788 			max_height = hints->max_height;
1789 	} else {
1790 		if (max_width == 0)
1791 			max_width = MAX ((unsigned int)minWidth, clean_width);
1792 		if (max_height == 0)
1793 			max_height = MAX ((unsigned int)minHeight, clean_height);
1794 	}
1795 	LOCAL_DEBUG_OUT
1796 			("base_size = %dx%d, min_size = %dx%d, curr_size = %dx%d, max_size = %dx%d",
1797 			 baseWidth, baseHeight, minWidth, minHeight, clean_width,
1798 			 clean_height, max_width, max_height);
1799 	/* First, clamp to min and max values  */
1800 	clean_width = FIT_IN_RANGE (minWidth, clean_width, max_width);
1801 	clean_height = FIT_IN_RANGE (minHeight, clean_height, max_height);
1802 	LOCAL_DEBUG_OUT ("clumped_size = %dx%d", clean_width, clean_height);
1803 
1804 	/* Second, fit to base + N * inc */
1805 	if (get_flags (hints->flags, AS_SizeInc)) {
1806 		xinc = hints->width_inc;
1807 		yinc = hints->height_inc;
1808 		clean_width = (((clean_width - baseWidth) / xinc) * xinc) + baseWidth;
1809 		clean_height =
1810 				(((clean_height - baseHeight) / yinc) * yinc) + baseHeight;
1811 		LOCAL_DEBUG_OUT ("inced_size = %dx%d", clean_width, clean_height);
1812 	}
1813 
1814 	/* Third, adjust for aspect ratio */
1815 #define maxAspectX hints->max_aspect.x
1816 #define maxAspectY hints->max_aspect.y
1817 #define minAspectX hints->min_aspect.x
1818 #define minAspectY hints->min_aspect.y
1819 #define makemult(a,b) ((b==1) ? (a) : (((int)((a)/(b))) * (b)) )
1820 
1821 	/* The math looks like this:
1822 
1823 	 * minAspectX    dwidth     maxAspectX
1824 	 * ---------- <= ------- <= ----------
1825 	 * minAspectY    dheight    maxAspectY
1826 	 *
1827 	 * If that is multiplied out, then the width and height are
1828 	 * invalid in the following situations:
1829 	 *
1830 	 * minAspectX * dheight > minAspectY * dwidth
1831 	 * maxAspectX * dheight < maxAspectY * dwidth
1832 	 *
1833 	 */
1834 
1835 	if (get_flags (hints->flags, AS_Aspect)) {
1836 		if ((minAspectX * clean_height > minAspectY * clean_width)) {
1837 			delta =
1838 					makemult (minAspectX * clean_height / minAspectY - clean_width,
1839 										xinc);
1840 			if (clean_width + delta <= max_width)
1841 				clean_width += delta;
1842 			else {
1843 				delta =
1844 						makemult (clean_height - clean_width * minAspectY / minAspectX,
1845 											yinc);
1846 				if (clean_height - delta >= minHeight)
1847 					clean_height -= delta;
1848 			}
1849 		}
1850 		if (maxAspectX * clean_height < maxAspectY * clean_width) {
1851 			delta =
1852 					makemult (clean_width * maxAspectY / maxAspectX - clean_height,
1853 										yinc);
1854 			if (clean_height + delta <= max_height)
1855 				clean_height += delta;
1856 			else {
1857 				delta =
1858 						makemult (clean_width - maxAspectX * clean_height / maxAspectY,
1859 											xinc);
1860 				if (clean_width - delta >= minWidth)
1861 					clean_width -= delta;
1862 			}
1863 		}
1864 		LOCAL_DEBUG_OUT ("aspected_size = %dx%d", clean_width, clean_height);
1865 	}
1866 	status->width =
1867 			clean_width + status->frame_size[FR_W] + status->frame_size[FR_E];
1868 	status->height =
1869 			clean_height + status->frame_size[FR_N] + status->frame_size[FR_S];
1870 }
1871 
1872 static int _as_gravity_offsets[11][2] = {
1873 	{0, 0},												/* ForgetGravity */
1874 	{-1, -1},											/* NorthWestGravity */
1875 	{2, -1},											/* NorthGravity */
1876 	{1, -1},											/* NorthEastGravity */
1877 	{-1, 2},											/* WestGravity */
1878 	{0, 0},												/* CenterGravity */
1879 	{1, 2},												/* EastGravity */
1880 	{-1, 1},											/* SouthWestGravity */
1881 	{2, 1},												/* SouthGravity */
1882 	{1, 1},												/* SouthEastGravity */
1883 	{2, 2}												/* StaticGravity */
1884 };
1885 
get_gravity_offsets(ASHints * hints,int * xp,int * yp)1886 void get_gravity_offsets (ASHints * hints, int *xp, int *yp)
1887 {
1888 	register int g = NorthWestGravity;
1889 
1890 	if (get_flags (hints->flags, AS_Gravity))
1891 		g = hints->gravity;
1892 
1893 	if (g < ForgetGravity || g > StaticGravity)
1894 		*xp = *yp = 0;
1895 	else {
1896 		*xp = (int)_as_gravity_offsets[g][0];
1897 		*yp = (int)_as_gravity_offsets[g][1];
1898 	}
1899 }
1900 
1901 int
translate_asgeometry(ScreenInfo * scr,ASGeometry * asg,int * px,int * py,unsigned int * pwidth,unsigned int * pheight)1902 translate_asgeometry (ScreenInfo * scr, ASGeometry * asg, int *px, int *py,
1903 											unsigned int *pwidth, unsigned int *pheight)
1904 {
1905 	int grav = NorthWestGravity;
1906 	unsigned int width = 1, height = 1;
1907 
1908 	if (scr == NULL)
1909 		scr = ASDefaultScr;
1910 
1911 	if (asg) {
1912 		if (get_flags (asg->flags, XNegative)) {
1913 			if (get_flags (asg->flags, YNegative))
1914 				grav = SouthEastGravity;
1915 			else
1916 				grav = NorthEastGravity;
1917 		} else if (get_flags (asg->flags, YNegative))
1918 			grav = SouthWestGravity;
1919 	}
1920 	if (asg && get_flags (asg->flags, WidthValue)) {
1921 		width = asg->width;
1922 		if (pwidth)
1923 			*pwidth = width;
1924 	} else if (pwidth)
1925 		width = *pwidth;
1926 
1927 	if (asg && get_flags (asg->flags, HeightValue)) {
1928 		height = asg->height;
1929 		if (pheight)
1930 			*pheight = height;
1931 	} else if (pheight)
1932 		height = *pheight;
1933 	if (asg) {
1934 		if (get_flags (asg->flags, XValue) && px) {
1935 			if (get_flags (asg->flags, XNegative)) {
1936 				if (asg->x <= 0)
1937 					*px = scr->MyDisplayWidth + asg->x;
1938 				else
1939 					*px = scr->MyDisplayWidth - asg->x;
1940 				*px -= width;
1941 			} else
1942 				*px = asg->x;
1943 		}
1944 		if (get_flags (asg->flags, YValue) && py) {
1945 			if (get_flags (asg->flags, YNegative)) {
1946 				if (asg->x <= 0)
1947 					*py = scr->MyDisplayHeight + asg->y;
1948 				else
1949 					*py = scr->MyDisplayHeight - asg->y;
1950 				*py -= height;
1951 			} else
1952 				*py = asg->y;
1953 		}
1954 	} else {
1955 		if (px)
1956 			*px = 0;
1957 		if (py)
1958 			*py = 0;
1959 	}
1960 
1961 	return grav;
1962 }
1963 
1964 int
make_anchor_pos(ASStatusHints * status,int pos,int size,int vpos,int grav,int max_pos)1965 make_anchor_pos (ASStatusHints * status, int pos, int size, int vpos,
1966 								 int grav, int max_pos)
1967 {																/* anchor position is always in virtual coordinates */
1968 	int bw = 0;
1969 
1970 	if (get_flags (status->flags, AS_StartBorderWidth))
1971 		bw = status->border_width;
1972 
1973 	/* position of the sticky window is stored in real coordinates */
1974 	if (!get_flags (status->flags, AS_Sticky))
1975 		pos += vpos;
1976 
1977 	/* trying to place window partly on screen, unless user really wants it */
1978 	if (!get_flags (status->flags, AS_StartPositionUser)) {
1979 		if (pos > max_pos)
1980 			pos = max_pos;
1981 		else if (pos + size < 16)
1982 			pos = 16 - size;
1983 	}
1984 
1985 	switch (grav) {
1986 	case 0:											/* Center */
1987 		pos += bw + (size >> 1);
1988 		break;
1989 	case 1:											/* East */
1990 		pos += bw + size + bw;
1991 		break;
1992 	case 2:											/* Static */
1993 		pos += bw;
1994 		break;
1995 	default:											/* West */
1996 		break;
1997 	}
1998 	return pos;
1999 }
2000 
2001 /* reverse transformation */
2002 int
make_status_pos(ASStatusHints * status,int pos,unsigned int size,int vpos,int grav)2003 make_status_pos (ASStatusHints * status, int pos, unsigned int size,
2004 								 int vpos, int grav)
2005 {																/* status position is always in real coordinates */
2006 	unsigned int bw = 0;
2007 
2008 	if (get_flags (status->flags, AS_StartBorderWidth))
2009 		bw = status->border_width;
2010 
2011 	/* position of the sticky window is stored in real coordinates */
2012 	if (!get_flags (status->flags, AS_Sticky))
2013 		pos -= vpos;
2014 
2015 	switch (grav) {
2016 	case 0:											/* Center */
2017 		pos -= bw + (size >> 1);
2018 		break;
2019 	case 1:											/* East */
2020 		pos -= bw + size + bw;
2021 		break;
2022 	case 2:											/* Static */
2023 		pos -= bw;
2024 		break;
2025 	default:											/* West */
2026 		break;
2027 	}
2028 	return pos;
2029 }
2030 
2031 void
make_detach_pos(ASHints * hints,ASStatusHints * status,XRectangle * anchor,int * detach_x,int * detach_y)2032 make_detach_pos (ASHints * hints, ASStatusHints * status,
2033 								 XRectangle * anchor, int *detach_x, int *detach_y)
2034 {
2035 	unsigned int bw = 0;
2036 	int x = 0, y = 0;
2037 	int grav_x, grav_y;
2038 
2039 	if (hints == NULL || status == NULL || anchor == NULL)
2040 		return;
2041 
2042 	if (get_flags (status->flags, AS_StartBorderWidth))
2043 		bw = status->border_width;
2044 
2045 	get_gravity_offsets (hints, &grav_x, &grav_y);
2046 
2047 	/* position of the sticky window is stored in real coordinates */
2048 	x = anchor->x;
2049 	y = anchor->y;
2050 	if (!get_flags (status->flags, AS_Sticky)) {
2051 		x -= status->viewport_x;
2052 		y -= status->viewport_y;
2053 	}
2054 
2055 	if (detach_x) {
2056 		APPLY_GRAVITY (grav_x, x, anchor->width, bw, bw);
2057 		*detach_x = x;
2058 	}
2059 	if (detach_y) {
2060 		APPLY_GRAVITY (grav_y, y, anchor->height, bw, bw);
2061 		*detach_y = y;
2062 	}
2063 }
2064 
2065 /***** New Code : *****************************************************/
2066 
2067 /*
2068  * frame_size[] must be set to the real frame decoration size if window
2069  * is being moved by us or to border_width if moved by client.
2070  *
2071  * width and height must be that of a client
2072  *
2073  * x, y are of top left corner of the client.
2074  * 		North  		Central 		South 			Static
2075  * y	-FR_N       +height/2       +height+FR_S    +0
2076  *
2077  * 		West   		Central 		East  			Static
2078  * x	-FR_W       +width/2       +width+FR_E      +0
2079  */
2080 
2081 void
status2anchor(XRectangle * anchor,ASHints * hints,ASStatusHints * status,int vwidth,int vheight)2082 status2anchor (XRectangle * anchor, ASHints * hints,
2083 							 ASStatusHints * status, int vwidth, int vheight)
2084 {
2085 	if (get_flags (status->flags, AS_Size)) {
2086 		int w, h;
2087 
2088 		constrain_size (hints, status, vwidth, vheight);
2089 		w = (int)status->width - ((int)status->frame_size[FR_W] +
2090 															(int)status->frame_size[FR_E]);
2091 		if (w > 0)
2092 			anchor->width = w;
2093 		h = (int)status->height - ((int)status->frame_size[FR_N] +
2094 															 (int)status->frame_size[FR_S]);
2095 		if (h > 0)
2096 			anchor->height = h;
2097 	}
2098 
2099 	if (get_flags (status->flags, AS_Position)) {
2100 		int grav_x = -1, grav_y = -1;
2101 		int offset;
2102 
2103 		get_gravity_offsets (hints, &grav_x, &grav_y);
2104 
2105 		LOCAL_DEBUG_OUT
2106 				("grav_x = %d, width = %d, bw1 = %d, bw2 = %d, status_x = %d",
2107 				 grav_x, anchor->width, status->frame_size[FR_W],
2108 				 status->frame_size[FR_E], status->x);
2109 		offset = 0;
2110 		APPLY_GRAVITY (grav_x, offset, anchor->width,
2111 									 status->frame_size[FR_W] + status->frame_border_width,
2112 									 status->frame_size[FR_E] + status->frame_border_width);
2113 		anchor->x = status->x - offset;
2114 
2115 		LOCAL_DEBUG_OUT
2116 				("grav_y = %d, height = %d, bw1 = %d, bw2 = %d, status_y = %d",
2117 				 grav_y, anchor->height, status->frame_size[FR_N],
2118 				 status->frame_size[FR_S], status->y);
2119 
2120 		offset = 0;
2121 		APPLY_GRAVITY (grav_y, offset, anchor->height,
2122 									 status->frame_size[FR_N] + status->frame_border_width,
2123 									 status->frame_size[FR_S] + status->frame_border_width);
2124 		anchor->y = status->y - offset;
2125 
2126 		LOCAL_DEBUG_OUT ("anchor = %+d%+d", anchor->x, anchor->y);
2127 		if (!get_flags (status->flags, AS_Sticky)) {
2128 			anchor->x += (int)status->viewport_x;
2129 			anchor->y += (int)status->viewport_y;
2130 		}
2131 		LOCAL_DEBUG_OUT ("anchor = %+d%+d", anchor->x, anchor->y);
2132 	}
2133 }
2134 
2135 void
anchor2status(ASStatusHints * status,ASHints * hints,XRectangle * anchor)2136 anchor2status (ASStatusHints * status, ASHints * hints,
2137 							 XRectangle * anchor)
2138 {
2139 	int grav_x = -1, grav_y = -1;
2140 	int offset;
2141 
2142 	status->width =
2143 			anchor->width + status->frame_size[FR_W] + status->frame_size[FR_E];
2144 	status->height =
2145 			anchor->height + status->frame_size[FR_N] + status->frame_size[FR_S];
2146 	set_flags (status->flags, AS_Size);
2147 
2148 	get_gravity_offsets (hints, &grav_x, &grav_y);
2149 
2150 	LOCAL_DEBUG_OUT
2151 			("grav_x = %d, width = %d, bw1 = %d, bw2 = %d, anchor_x = %d",
2152 			 grav_x, anchor->width, status->frame_size[FR_W],
2153 			 status->frame_size[FR_E], anchor->x);
2154 	offset = 0;
2155 	APPLY_GRAVITY (grav_x, offset, anchor->width,
2156 								 status->frame_size[FR_W] + status->frame_border_width,
2157 								 status->frame_size[FR_E] + status->frame_border_width);
2158 	status->x = anchor->x + offset;
2159 
2160 	LOCAL_DEBUG_OUT
2161 			("grav_y = %d, height = %d, bw1 = %d, bw2 = %d, anchor_y = %d",
2162 			 grav_y, anchor->height, status->frame_size[FR_N],
2163 			 status->frame_size[FR_S], anchor->y);
2164 
2165 	offset = 0;
2166 	APPLY_GRAVITY (grav_y, offset, anchor->height,
2167 								 status->frame_size[FR_N] + status->frame_border_width,
2168 								 status->frame_size[FR_S] + status->frame_border_width);
2169 	status->y = anchor->y + offset;
2170 
2171 	LOCAL_DEBUG_OUT ("status = %+d%+d", status->x, status->y);
2172 	if (!get_flags (status->flags, AS_Sticky)) {
2173 		status->x -= (int)status->viewport_x;
2174 		status->y -= (int)status->viewport_y;
2175 	}
2176 	LOCAL_DEBUG_OUT ("status = %+d%+d", status->x, status->y);
2177 	set_flags (status->flags, AS_Position);
2178 }
2179 
2180 
2181 /***** Old Code : *****************************************************/
2182 
2183 ASFlagType
change_placement(ScreenInfo * scr,ASHints * hints,ASStatusHints * status,XPoint * anchor,ASStatusHints * new_status,int vx,int vy,ASFlagType what)2184 change_placement (ScreenInfo * scr, ASHints * hints,
2185 									ASStatusHints * status, XPoint * anchor,
2186 									ASStatusHints * new_status, int vx, int vy,
2187 									ASFlagType what)
2188 {
2189 	ASFlagType todo = 0;
2190 	int grav_x, grav_y;
2191 	register int max_x = scr->MyDisplayWidth - 16;
2192 	register int max_y = scr->MyDisplayHeight - 16;
2193 	int new_x, new_y;
2194 
2195 	if (!get_flags (what, AS_Size | AS_Position) || status == NULL
2196 			|| new_status == NULL)
2197 		return 0;
2198 
2199 	new_x = status->x - (vx - status->viewport_x);
2200 	new_y = status->y - (vy - status->viewport_y);
2201 	get_gravity_offsets (hints, &grav_x, &grav_y);
2202 	if (!get_flags (status->flags, AS_Sticky)) {
2203 		max_x += scr->VxMax;
2204 		max_y += scr->VyMax;
2205 	}
2206 
2207 	if (get_flags (what, AS_Size)) {
2208 		constrain_size (hints, new_status, scr->VxMax + scr->MyDisplayWidth,
2209 										scr->VyMax + scr->MyDisplayHeight);
2210 		if (new_status->width != status->width) {
2211 			status->width = new_status->width;
2212 			set_flags (todo, TODO_RESIZE_X);
2213 			if (grav_x == 0 || grav_x == 1)
2214 				set_flags (todo, TODO_MOVE_X);
2215 		}
2216 		if (new_status->height != status->height) {
2217 			status->height = new_status->height;
2218 			set_flags (todo, TODO_RESIZE_Y);
2219 			if (grav_y == 0 || grav_y == 1)
2220 				set_flags (todo, TODO_MOVE_Y);
2221 		}
2222 	}
2223 
2224 	if (!get_flags (what, AS_BorderWidth)
2225 			&& new_status->border_width != status->border_width) {
2226 		status->border_width = new_status->border_width;
2227 		set_flags (todo, TODO_MOVE);
2228 	}
2229 
2230 	if (!get_flags (status->flags, AS_Sticky)
2231 			&& (status->viewport_x != vx || status->viewport_y != vy))
2232 		set_flags (todo, TODO_MOVE);
2233 
2234 	if (get_flags (what, AS_Position)) {
2235 		if (status->x != new_status->x) {
2236 			new_x = new_status->x;
2237 			set_flags (todo, TODO_MOVE_X);
2238 		} else
2239 				if (make_anchor_pos
2240 						(status, new_x, status->width, vx, max_x, grav_x) != anchor->x)
2241 			set_flags (todo, TODO_MOVE_X);
2242 
2243 		if (status->y != new_status->y) {
2244 			new_y = new_status->y;
2245 			set_flags (todo, TODO_MOVE_Y);
2246 		} else
2247 				if (make_anchor_pos
2248 						(status, new_y, status->height, vy, max_y,
2249 						 grav_y) != anchor->y)
2250 			set_flags (todo, TODO_MOVE_Y);
2251 	}
2252 	if (get_flags (todo, TODO_MOVE_X)) {
2253 		anchor->x =
2254 				make_anchor_pos (status, new_x, status->width, vx, max_x, grav_x);
2255 		status->x =
2256 				make_status_pos (status, anchor->x, status->width, vx, grav_x);
2257 	}
2258 	if (get_flags (todo, TODO_MOVE_Y)) {
2259 		anchor->y =
2260 				make_anchor_pos (status, new_y, status->height, vy, max_y, grav_y);
2261 		status->y =
2262 				make_status_pos (status, anchor->y, status->height, vy, grav_y);
2263 	}
2264 	if (!get_flags (status->flags, AS_Sticky)) {
2265 		status->viewport_x = vx;
2266 		status->viewport_y = vy;
2267 	}
2268 
2269 	return what;
2270 }
2271 
2272 int
calculate_viewport(int * ppos,int size,int scr_vpos,int scr_size,int max_viewport)2273 calculate_viewport (int *ppos, int size, int scr_vpos, int scr_size,
2274 										int max_viewport)
2275 {
2276 	int viewport = -1;
2277 	int pos = ppos ? *ppos : 0;
2278 
2279 	if (pos >= scr_size)
2280 		viewport = pos / scr_size;
2281 	else if (pos + size < 0) {
2282 		if (pos + scr_vpos > 0)
2283 			viewport = (scr_vpos + pos) / scr_size;
2284 		else
2285 			viewport = 0;
2286 	} else
2287 		return scr_vpos;
2288 
2289 	viewport *= scr_size;
2290 	viewport = MIN (viewport, max_viewport);
2291 	if (ppos)
2292 		*ppos = pos + (scr_vpos - viewport);
2293 	return viewport;
2294 }
2295 
2296 int
gravitate_position(int pos,unsigned int size,unsigned int scr_size,int grav,unsigned int bw)2297 gravitate_position (int pos, unsigned int size, unsigned int scr_size,
2298 										int grav, unsigned int bw)
2299 {
2300 	if (pos < 0 || pos + size > scr_size)
2301 		return pos;
2302 	if (grav == 1)								/* East or South gravity */
2303 		pos = (int)scr_size - (int)(pos + bw + size + bw);
2304 
2305 	return pos;
2306 }
2307 
2308 /***********************************************************************************
2309  * we build a command line here, so we can restart an app with exactly the same
2310  * parameters:
2311  ***********************************************************************************/
format_geometry_string(int x,int y,int width,int height,int unit_width,int unit_height,int screen_size_x,int screen_size_y,int gravity)2312 static char *format_geometry_string (int x, int y, int width, int height,
2313 																		 int unit_width, int unit_height,
2314 																		 int screen_size_x, int screen_size_y,
2315 																		 int gravity)
2316 {
2317 	char *g =
2318 			safemalloc (15 + 1 + 15 + 1 + 15 + 1 + 15 + 1 /* large enough */ );
2319 	char x_sign = '+';
2320 	char y_sign = '+';
2321 	int x2 = x + width, y2 = y + height;
2322 
2323 #define FGS_CHECK_SIGN(d)  do{if(d<0){d = 0;/* d##_sign = '-';*/} }while(0)
2324 #define FGS_APPLY_NEGATIVE_GRAV(d)  do{ d = screen_size_##d - d##2; if(d<0) d=0; d##_sign = '-' ;}while(0)
2325 	if (gravity == SouthWestGravity) {
2326 		FGS_APPLY_NEGATIVE_GRAV (y);
2327 		FGS_CHECK_SIGN (x);
2328 	} else if (gravity == SouthEastGravity) {
2329 		FGS_APPLY_NEGATIVE_GRAV (x);
2330 		FGS_APPLY_NEGATIVE_GRAV (y);
2331 	} else if (gravity == NorthEastGravity) {
2332 		FGS_APPLY_NEGATIVE_GRAV (x);
2333 		FGS_CHECK_SIGN (y);
2334 	} else {
2335 		FGS_CHECK_SIGN (x);
2336 		FGS_CHECK_SIGN (y);
2337 	}
2338 #undef FGS_CHECK_SIGN
2339 #undef FGS_APPLY_NEGATIVE_GRAV
2340 
2341 	sprintf (g, "%dx%d%c%d%c%d ", unit_width, unit_height, x_sign, x, y_sign,
2342 					 y);
2343 	return g;
2344 }
2345 
make_client_geometry_string(ScreenInfo * scr,ASHints * hints,ASStatusHints * status,XRectangle * anchor,int vx,int vy,char ** pure_geometry)2346 char *make_client_geometry_string (ScreenInfo * scr, ASHints * hints,
2347 																	 ASStatusHints * status,
2348 																	 XRectangle * anchor, int vx, int vy,
2349 																	 char **pure_geometry)
2350 {
2351 	char *geom = NULL;
2352 	int detach_x, detach_y;
2353 	int grav_x, grav_y;
2354 	int bw = 0;
2355 	int width, height, unit_width, unit_height;
2356 
2357 	if (hints == NULL || status == NULL || anchor == NULL)
2358 		return NULL;
2359 
2360 	if (get_flags (status->flags, AS_StartBorderWidth))
2361 		bw = status->border_width;
2362 
2363 	make_detach_pos (hints, status, anchor, &detach_x, &detach_y);
2364 
2365 	vx = calculate_viewport (&detach_x, anchor->width, vx,
2366 													 scr->MyDisplayWidth, scr->VxMax);
2367 	vy = calculate_viewport (&detach_y, anchor->height, vy,
2368 													 scr->MyDisplayHeight, scr->VyMax);
2369 
2370 	get_gravity_offsets (hints, &grav_x, &grav_y);
2371 
2372 	detach_x =
2373 			gravitate_position (detach_x, anchor->width, bw, scr->MyDisplayWidth,
2374 													grav_x);
2375 	detach_y =
2376 			gravitate_position (detach_y, anchor->height, bw,
2377 													scr->MyDisplayHeight, grav_y);
2378 
2379 	width = anchor->width;
2380 	height = anchor->height;
2381 
2382 	unit_width =
2383 			(hints->width_inc >
2384 			 0) ? (width - hints->base_width) / hints->width_inc : width;
2385 	unit_height =
2386 			(hints->height_inc >
2387 			 0) ? (height - hints->base_height) / hints->height_inc : height;
2388 
2389 	if (pure_geometry) {
2390 		*pure_geometry =
2391 				format_geometry_string (detach_x, detach_y, width, height, width,
2392 																height, scr->MyDisplayWidth,
2393 																scr->MyDisplayHeight, hints->gravity);
2394 	}
2395 	geom =
2396 			format_geometry_string (detach_x, detach_y, width, height,
2397 															unit_width, unit_height, scr->MyDisplayWidth,
2398 															scr->MyDisplayHeight, hints->gravity);;
2399 	return geom;
2400 }
2401 
make_client_command(ScreenInfo * scr,ASHints * hints,ASStatusHints * status,XRectangle * anchor,int vx,int vy)2402 char *make_client_command (ScreenInfo * scr, ASHints * hints,
2403 													 ASStatusHints * status, XRectangle * anchor,
2404 													 int vx, int vy)
2405 {
2406 	char *client_cmd = NULL;
2407 	char *geom =
2408 			make_client_geometry_string (scr, hints, status, anchor, vx, vy,
2409 																	 NULL);
2410 
2411 	if (hints->client_cmd == NULL || geom == NULL)
2412 		return NULL;
2413 
2414 	/* supplying everything as : -xrm "afterstep*desk:N" */
2415 	client_cmd =
2416 			safemalloc (strlen (hints->client_cmd) + 11 + strlen (geom) + 1 + 1);
2417 	sprintf (client_cmd, "%s -geometry %s ", hints->client_cmd, geom);
2418 	/*, status->desktop, status->layer, status->viewport_x, status->viewport_y */
2419 	return client_cmd;
2420 }
2421 
2422 /***********************************************************************
2423  * Setrting Hints on the window :
2424  ***********************************************************************/
2425 static Bool
client_hints2wm_hints(XWMHints * wm_hints,ASHints * hints,ASStatusHints * status)2426 client_hints2wm_hints (XWMHints * wm_hints, ASHints * hints,
2427 											 ASStatusHints * status)
2428 {
2429 	memset (wm_hints, 0x00, sizeof (XWMHints));
2430 
2431 	if (status) {
2432 		wm_hints->flags = StateHint;
2433 		if (get_flags (status->flags, AS_StartsIconic))
2434 			wm_hints->initial_state = IconicState;
2435 		else
2436 			wm_hints->initial_state = WithdrawnState;
2437 	}
2438 	/* does this application rely on the window manager to get keyboard input? */
2439 	if (get_flags (hints->flags, AS_AcceptsFocus)) {
2440 		set_flags (wm_hints->flags, InputHint);
2441 		wm_hints->input = True;
2442 	}
2443 
2444 	/* window to be used as icon */
2445 	if (get_flags (hints->client_icon_flags, AS_ClientIcon)) {
2446 		if (!get_flags (hints->client_icon_flags, AS_ClientIconPixmap)) {
2447 			wm_hints->icon_window = hints->icon.window;
2448 			set_flags (wm_hints->flags, IconWindowHint);
2449 		} else {										/* pixmap to be used as icon */
2450 			set_flags (wm_hints->flags, IconPixmapHint);
2451 			wm_hints->icon_pixmap = hints->icon.pixmap;
2452 
2453 			if (hints->icon_mask) {		/* pixmap to be used as mask for icon_pixmap */
2454 				set_flags (wm_hints->flags, IconMaskHint);
2455 				wm_hints->icon_mask = hints->icon_mask;
2456 			}
2457 		}
2458 	}
2459 
2460 	/* initial position of icon */
2461 	if (get_flags (hints->client_icon_flags, AS_ClientIconPosition)) {
2462 		set_flags (wm_hints->flags, IconPositionHint);
2463 		wm_hints->icon_x = hints->icon_x;
2464 		wm_hints->icon_y = hints->icon_y;
2465 	}
2466 
2467 	if (hints->group_lead) {
2468 		set_flags (wm_hints->flags, WindowGroupHint);
2469 		wm_hints->window_group = hints->group_lead;
2470 	}
2471 
2472 /*	if( get_flags( hints->flags, AS_AvoidCover ) )
2473 		set_flags( wm_hints->flags, UrgencyHint );
2474  */
2475 	return (wm_hints->flags != StateHint
2476 					|| wm_hints->initial_state == IconicState);
2477 }
2478 
2479 static Bool
client_hints2size_hints(XSizeHints * size_hints,ASHints * hints,ASStatusHints * status)2480 client_hints2size_hints (XSizeHints * size_hints, ASHints * hints,
2481 												 ASStatusHints * status)
2482 {
2483 	memset (size_hints, 0x00, sizeof (XSizeHints));
2484 	if (status) {
2485 		if (get_flags (status->flags, AS_StartPosition | AS_StartPositionUser)) {
2486 			if (get_flags (status->flags, AS_StartPositionUser))
2487 				set_flags (size_hints->flags, USPosition);
2488 			else
2489 				set_flags (size_hints->flags, PPosition);
2490 		}
2491 
2492 		if (get_flags (status->flags, AS_StartSize | AS_StartSizeUser)) {
2493 			if (get_flags (status->flags, AS_StartSizeUser))
2494 				set_flags (size_hints->flags, USSize);
2495 			else
2496 				set_flags (size_hints->flags, PSize);
2497 		}
2498 	}
2499 	if (get_flags (hints->flags, AS_MinSize)) {
2500 		size_hints->min_width = hints->min_width;
2501 		size_hints->min_height = hints->min_height;
2502 		set_flags (size_hints->flags, PMinSize);
2503 	}
2504 	if (get_flags (hints->flags, AS_MaxSize)) {
2505 		size_hints->max_width = hints->max_width;
2506 		size_hints->max_height = hints->max_height;
2507 		set_flags (size_hints->flags, PMaxSize);
2508 	}
2509 	if (get_flags (hints->flags, AS_SizeInc)) {
2510 		size_hints->width_inc = hints->width_inc;
2511 		size_hints->height_inc = hints->height_inc;
2512 		set_flags (size_hints->flags, PResizeInc);
2513 	}
2514 	if (get_flags (hints->flags, AS_Aspect)) {
2515 		size_hints->min_aspect.x = hints->min_aspect.x;
2516 		size_hints->min_aspect.y = hints->min_aspect.y;
2517 		size_hints->max_aspect.x = hints->max_aspect.x;
2518 		size_hints->max_aspect.y = hints->max_aspect.y;
2519 		set_flags (size_hints->flags, PAspect);
2520 	}
2521 	if (get_flags (hints->flags, AS_BaseSize)) {
2522 		size_hints->base_width = hints->base_width;
2523 		size_hints->base_height = hints->base_height;
2524 		set_flags (size_hints->flags, PBaseSize);
2525 	}
2526 	if (get_flags (hints->flags, AS_Gravity)) {
2527 		size_hints->win_gravity = hints->gravity;
2528 		set_flags (size_hints->flags, PWinGravity);
2529 	}
2530 	return (size_hints->flags != 0);
2531 }
2532 
2533 static Bool
client_hints2wm_protocols(ASFlagType * protocols,ASHints * hints)2534 client_hints2wm_protocols (ASFlagType * protocols, ASHints * hints)
2535 {
2536 	if (protocols == NULL || hints == NULL)
2537 		return False;
2538 
2539 	*protocols =
2540 			hints->protocols & (AS_DoesWmDeleteWindow | AS_DoesWmTakeFocus);
2541 	return (*protocols != 0);
2542 }
2543 
2544 static Bool
client_hints2motif_hints(MwmHints * motif_hints,ASHints * hints,ASStatusHints * status)2545 client_hints2motif_hints (MwmHints * motif_hints, ASHints * hints,
2546 													ASStatusHints * status)
2547 {
2548 	ASFlagType tmp;
2549 
2550 	memset (motif_hints, 0x00, sizeof (MwmHints));
2551 
2552 	if (status) {
2553 		if (get_flags (status->flags, AS_StartLayer)) {
2554 			if (status->layer == AS_LayerUrgent
2555 					&& get_flags (status->flags, AS_StartsSticky)) {
2556 				motif_hints->inputMode = MWM_INPUT_SYSTEM_MODAL;
2557 				set_flags (motif_hints->flags, MWM_HINTS_INPUT_MODE);
2558 			} else if (status->layer == AS_LayerTop) {
2559 				motif_hints->inputMode = MWM_INPUT_SYSTEM_MODAL;
2560 				set_flags (motif_hints->flags, MWM_INPUT_FULL_APPLICATION_MODAL);
2561 			}
2562 		}
2563 	}
2564 	/* finally we can apply conglomerated hints to our flags : */
2565 	tmp = motif_hints->decorations;
2566 	encode_simple_flags (&tmp, mwm_decor_xref, hints->flags);
2567 	encode_simple_flags (&tmp, mwm_decor_func_xref, hints->function_mask);
2568 	motif_hints->decorations = tmp;
2569 	tmp = motif_hints->functions;
2570 	encode_simple_flags (&tmp, mwm_func_xref, hints->function_mask);
2571 	motif_hints->functions = tmp;
2572 
2573 	check_motif_hints_sanity (motif_hints);
2574 
2575 	if (motif_hints->functions != 0)
2576 		set_flags (motif_hints->flags, MWM_HINTS_FUNCTIONS);
2577 	if (motif_hints->decorations != 0)
2578 		set_flags (motif_hints->flags, MWM_HINTS_DECORATIONS);
2579 
2580 	return (motif_hints->flags != 0);
2581 }
2582 
2583 static Bool
client_hints2gnome_hints(GnomeHints * gnome_hints,ASHints * hints,ASStatusHints * status)2584 client_hints2gnome_hints (GnomeHints * gnome_hints, ASHints * hints,
2585 													ASStatusHints * status)
2586 {
2587 	ASFlagType tmp = 0;
2588 
2589 	memset (gnome_hints, 0x00, sizeof (GnomeHints));
2590 
2591 	if (status) {
2592 		if (get_flags (status->flags, AS_StartLayer)) {
2593 			gnome_hints->layer = (status->layer << 1) + WIN_LAYER_NORMAL;
2594 			set_flags (gnome_hints->flags, GNOME_LAYER);
2595 		}
2596 
2597 		if (get_flags (status->flags, AS_StartDesktop)) {
2598 			gnome_hints->workspace = status->desktop;
2599 			set_flags (gnome_hints->flags, GNOME_WORKSPACE);
2600 		}
2601 	}
2602 	gnome_hints->state = encode_gnome_state (hints, status);
2603 	if (gnome_hints->state != 0)
2604 		set_flags (gnome_hints->flags, GNOME_STATE);
2605 
2606 	tmp = gnome_hints->hints;
2607 	encode_simple_flags (&tmp, gnome_hints_xref, hints->flags);
2608 	gnome_hints->hints = tmp;
2609 	if (gnome_hints->hints != 0)
2610 		set_flags (gnome_hints->flags, GNOME_HINTS);
2611 
2612 	return (gnome_hints->flags != 0);
2613 }
2614 
2615 static Bool
client_hints2extwm_hints(ExtendedWMHints * extwm_hints,ASHints * hints,ASStatusHints * status)2616 client_hints2extwm_hints (ExtendedWMHints * extwm_hints, ASHints * hints,
2617 													ASStatusHints * status)
2618 {
2619 	memset (extwm_hints, 0x00, sizeof (ExtendedWMHints));
2620 
2621 	if (status) {
2622 		if (get_flags (status->flags, AS_StartsSticky)) {
2623 			extwm_hints->desktop = 0xFFFFFFFF;
2624 			set_flags (extwm_hints->flags, EXTWM_DESKTOP);
2625 		} else if (get_flags (status->flags, AS_StartDesktop)) {
2626 			extwm_hints->desktop = status->desktop;
2627 			set_flags (extwm_hints->flags, EXTWM_DESKTOP);
2628 		}
2629 		/* window state hints : */
2630 		if (get_flags (status->flags, AS_StartLayer)
2631 				&& status->layer >= AS_LayerTop) {
2632 			set_flags (extwm_hints->state_flags, EXTWM_StateModal);
2633 			set_flags (extwm_hints->flags, EXTWM_StateSet);
2634 			encode_simple_flags (&(extwm_hints->state_flags), extwm_state_xref,
2635 													 status->flags);
2636 		}
2637 		if (get_flags (status->flags, AS_SkipWinList)) {
2638 			set_flags (extwm_hints->state_flags, EXTWM_StateSkipTaskbar);
2639 			set_flags (extwm_hints->flags, EXTWM_StateSet);
2640 		}
2641 
2642 		/* window type hints : */
2643 		if (get_flags (status->flags, AS_StartLayer)
2644 				&& status->layer != AS_LayerNormal) {
2645 			register int i;
2646 
2647 			for (i = 0; extwm_types_start_properties[i][0] != 0; i++)
2648 				if (status->layer == extwm_types_start_properties[i][1] &&
2649 						(get_flags (status->flags, extwm_types_start_properties[i][2])
2650 						 || extwm_types_start_properties[i][2] == 0)) {
2651 					set_flags (extwm_hints->type_flags,
2652 										 extwm_types_start_properties[i][0]);
2653 				}
2654 		}
2655 	}
2656 
2657 	encode_simple_flags (&(extwm_hints->type_flags), extwm_type_xref,
2658 											 hints->flags);
2659 	encode_simple_flags (&(extwm_hints->type_flags), extwm_type_func_mask,
2660 											 hints->function_mask);
2661 	if (extwm_hints->type_flags != 0)
2662 		set_flags (extwm_hints->flags, EXTWM_TypeSet);
2663 
2664 	if (hints->pid >= 0 && get_flags (hints->flags, AS_PID)) {
2665 		set_flags (extwm_hints->flags, EXTWM_PID);
2666 		extwm_hints->pid = hints->pid;
2667 	}
2668 	if (hints->icon_argb != NULL
2669 			&& get_flags (hints->client_icon_flags, AS_ClientIcon)) {
2670 		set_flags (extwm_hints->flags, EXTWM_ICON);
2671 		extwm_hints->icon_length =
2672 				hints->icon_argb[0] * hints->icon_argb[1] + 2;
2673 		extwm_hints->icon =
2674 				safemalloc (extwm_hints->icon_length * sizeof (CARD32));
2675 		memcpy (extwm_hints->icon, hints->icon_argb,
2676 						extwm_hints->icon_length * sizeof (CARD32));
2677 	}
2678 	if (get_flags (hints->protocols, AS_DoesWmPing))
2679 		set_flags (extwm_hints->flags, EXTWM_DoesWMPing);
2680 
2681 	return (extwm_hints->flags != 0);
2682 }
2683 
2684 
2685 Bool
set_all_client_hints(Window w,ASHints * hints,ASStatusHints * status,Bool set_command)2686 set_all_client_hints (Window w, ASHints * hints, ASStatusHints * status,
2687 											Bool set_command)
2688 {
2689 	XWMHints wm_hints;
2690 	XSizeHints size_hints;
2691 	ASFlagType protocols = 0;
2692 	MwmHints mwm_hints;
2693 	GnomeHints gnome_hints;
2694 	ExtendedWMHints extwm_hints;
2695 
2696 	if (w == None || hints == NULL)
2697 		return False;
2698 
2699 	set_client_names (w, hints->names[0], hints->icon_name, hints->res_class,
2700 										hints->res_name);
2701 
2702 	if (client_hints2wm_hints (&wm_hints, hints, status))
2703 		XSetWMHints (dpy, w, &wm_hints);
2704 
2705 	if (get_flags (hints->flags, AS_Transient))
2706 		XSetTransientForHint (dpy, w, hints->transient_for);
2707 
2708 	if (client_hints2size_hints (&size_hints, hints, status))
2709 		XSetWMNormalHints (dpy, w, &size_hints);
2710 
2711 	if (client_hints2extwm_hints (&extwm_hints, hints, status))
2712 		set_extwm_hints (w, &extwm_hints);
2713 
2714 	if (client_hints2wm_protocols (&protocols, hints)
2715 			|| get_flags (extwm_hints.flags, EXTWM_DoesWMPing))
2716 		set_client_protocols (w, protocols, extwm_hints.flags);
2717 
2718 #if 0
2719 	if (set_command) {
2720 		char *host_name = safecalloc (MAXHOSTNAME + 1, sizeof (char));
2721 
2722 		if (mygethostname (host_name, MAXHOSTNAME))
2723 			set_text_property (w, XA_WM_CLIENT_MACHINE, &host_name, 1,
2724 												 TPE_String);
2725 
2726 		if (MyArgs.saved_argc > 0 && MyArgs.saved_argv)
2727 			set_text_property (w, XA_WM_COMMAND, MyArgs.saved_argv,
2728 												 MyArgs.saved_argc, TPE_String);
2729 		free (host_name);
2730 	}
2731 #endif
2732 	if (client_hints2motif_hints (&mwm_hints, hints, status))
2733 		set_multi32bit_property (w, _XA_MwmAtom, XA_CARDINAL, 4,
2734 														 mwm_hints.flags, mwm_hints.functions,
2735 														 mwm_hints.decorations, mwm_hints.inputMode);
2736 
2737 	if (client_hints2gnome_hints (&gnome_hints, hints, status))
2738 		set_gnome_hints (w, &gnome_hints);
2739 
2740 	return True;
2741 }
2742 
2743 
get_client_icon_image(ScreenInfo * scr,ASHints * hints,int desired_size)2744 ASImage *get_client_icon_image (ScreenInfo * scr, ASHints * hints,
2745 																int desired_size)
2746 {
2747 	ASImage *im = NULL;
2748 
2749 	if (hints) {
2750 		char *icon_file = hints->icon_file;
2751 		ASImage *icon_file_im = NULL;
2752 		Bool icon_file_isDefault = False;
2753 
2754 		if (icon_file && Database) {
2755 			if (Database->style_default.icon_file != NULL
2756 					&& strcmp (icon_file, Database->style_default.icon_file) == 0)
2757 				icon_file_isDefault = True;
2758 		}
2759 		if (get_flags (hints->client_icon_flags, AS_ClientIcon)) {
2760 			Bool use_client_icon = (hints->icon_file == NULL
2761 															|| Database == NULL);
2762 
2763 			if (!use_client_icon) {
2764 				if (icon_file_isDefault)
2765 					use_client_icon = True;
2766 				else {
2767 					icon_file_im =
2768 							get_asimage (scr->image_manager, icon_file, 0xFFFFFFFF, 100);
2769 					if (icon_file_im == NULL)
2770 						use_client_icon = True;
2771 					LOCAL_DEBUG_OUT ("loaded icon from file \"%s\" into %p",
2772 													 icon_file ? icon_file : "(null)", im);
2773 				}
2774 
2775 			}
2776 			if (use_client_icon) {
2777 				/* first try ARGB icon If provided by the application : */
2778 				if (get_flags (hints->client_icon_flags, AS_ClientIconARGB)
2779 						&& hints->icon_argb != NULL) {
2780 					/* TODO: we also need to check for newfashioned ARGB icon from
2781 					 * extended WM specs here
2782 					 */
2783 					int width = hints->icon_argb[0];
2784 					int height = hints->icon_argb[1];
2785 
2786 					im = convert_argb2ASImage (scr->asv, width, height,
2787 																		 hints->icon_argb + 2, NULL);
2788 					LOCAL_DEBUG_OUT ("converted client's ARGB into an icon %dx%d %p",
2789 													 width, height, im);
2790 
2791 				}
2792 				if (im == NULL && get_flags (hints->client_icon_flags, AS_ClientIconPixmap) && hints->icon.pixmap != None) {	/* convert client's icon into ASImage */
2793 					unsigned int width, height;
2794 
2795 					get_drawable_size (hints->icon.pixmap, &width, &height);
2796 					im = picture2asimage (scr->asv, hints->icon.pixmap,
2797 																hints->icon_mask, 0, 0, width, height,
2798 																0xFFFFFFFF, False, 100);
2799 
2800 					LOCAL_DEBUG_OUT
2801 							("converted client's pixmap into an icon %dx%d %p", width,
2802 							 height, im);
2803 				}
2804 			}
2805 		}
2806 		LOCAL_DEBUG_OUT ("im =  %p", im);
2807 		if (im == NULL) {
2808 			if (CombinedCategories != NULL) {
2809 				ASDesktopEntry *de = NULL;
2810 
2811 				if (hints->names[0]) {
2812 					char *name = hints->names[0];
2813 					int i = 0;
2814 					char old;
2815 
2816 					while (name[i] && !isspace (name[i]))
2817 						++i;
2818 					if (i > 0) {
2819 						old = name[i];
2820 						name[i] = '\0';
2821 						de = fetch_desktop_entry (CombinedCategories, name);
2822 						LOCAL_DEBUG_OUT
2823 								("found desktop entry %p, for name[0] = \"%s\"", de, name);
2824 						name[i] = old;
2825 					}
2826 				}
2827 				LOCAL_DEBUG_OUT ("icon file = %p, default = %d", icon_file,
2828 												 icon_file_isDefault);
2829 				if (de == NULL && (icon_file == NULL || icon_file_isDefault)) {
2830 					LOCAL_DEBUG_OUT ("CombinedCategories = %p", CombinedCategories);
2831 
2832 					de = fetch_desktop_entry (CombinedCategories, hints->res_name);
2833 					LOCAL_DEBUG_OUT ("found desktop entry %p, for res_name = \"%s\"",
2834 													 de, hints->res_name);
2835 					if (de == NULL)
2836 						de = fetch_desktop_entry (CombinedCategories,
2837 																			hints->res_class);
2838 					LOCAL_DEBUG_OUT
2839 							("found desktop entry %p, for res_class = \"%s\"", de,
2840 							 hints->res_class);
2841 				}
2842 				if (de) {
2843 					if (de && de->ref_count > 0 && de->Icon) {
2844 						if (icon_file_im) {
2845 							safe_asimage_destroy (icon_file_im);
2846 							icon_file_im = NULL;
2847 						}
2848 						icon_file = de->Icon;
2849 					}
2850 				}
2851 
2852 			}
2853 			if (icon_file) {
2854 				if (icon_file_im)
2855 					im = icon_file_im;
2856 				else
2857 					im = load_environment_icon_any (icon_file, desired_size);
2858 				/*get_asimage (scr->image_manager, icon_file, 0xFFFFFFFF, 100); */
2859 				LOCAL_DEBUG_OUT ("loaded icon from \"%s\" into %dx%d %p",
2860 												 icon_file, im ? im->width : 0,
2861 												 im ? im->height : 0, im);
2862 			} else {
2863 				LOCAL_DEBUG_OUT ("no icon to use %s", "");
2864 			}
2865 		}
2866 	}
2867 	return im;
2868 }
2869 
2870 
2871 /***********************************************************************************
2872  * Hints printing functions :
2873  ***********************************************************************************/
2874 
print_clean_hints(stream_func func,void * stream,ASHints * clean)2875 void print_clean_hints (stream_func func, void *stream, ASHints * clean)
2876 {
2877 	register int i;
2878 
2879 	if (!pre_print_check
2880 			(&func, &stream, clean, "No hints available(NULL)."))
2881 		return;
2882 	for (i = 0; i < MAX_WINDOW_NAMES && clean->names[i]; i++) {
2883 		func (stream, "CLEAN.NAMES[%d] = \"%s\";\n", i, clean->names[i]);
2884 		func (stream, "CLEAN.NAMES_ENCODING[%d] = %d;\n", i,
2885 					clean->names_encoding[i]);
2886 	}
2887 	if (clean->icon_name) {
2888 		func (stream, "CLEAN.icon_name = \"%s\";\n", clean->icon_name);
2889 		func (stream, "CLEAN.icon_name_encoding = %d;\n",
2890 					clean->names_encoding[clean->icon_name_idx]);
2891 	}
2892 	if (clean->res_name) {
2893 		func (stream, "CLEAN.res_name = \"%s\";\n", clean->res_name);
2894 		func (stream, "CLEAN.res_name_encoding = %d;\n",
2895 					clean->names_encoding[clean->res_name_idx]);
2896 	}
2897 	if (clean->res_class) {
2898 		func (stream, "CLEAN.res_class = \"%s\";\n", clean->res_class);
2899 		func (stream, "CLEAN.res_class_encoding = %d;\n",
2900 					clean->names_encoding[clean->res_class_idx]);
2901 	}
2902 	func (stream, "CLEAN.flags = 0x%lX;\n", clean->flags);
2903 	func (stream, "CLEAN.protocols = 0x%lX;\n", clean->protocols);
2904 	func (stream, "CLEAN.function_mask = 0x%lX;\n", clean->function_mask);
2905 
2906 	if (get_flags (clean->flags, AS_Icon)) {
2907 		if (get_flags (clean->client_icon_flags, AS_ClientIcon)) {
2908 			if (get_flags (clean->client_icon_flags, AS_ClientIconARGB)
2909 					&& clean->icon_argb) {
2910 				func (stream, "CLEAN.icon.argb.width = 0x%lX;\n",
2911 							clean->icon_argb[0]);
2912 				func (stream, "CLEAN.icon.argb.height = 0x%lX;\n",
2913 							clean->icon_argb[1]);
2914 			} else if (get_flags (clean->client_icon_flags, AS_ClientIconPixmap))
2915 				func (stream, "CLEAN.icon.pixmap = 0x%lX;\n", clean->icon.pixmap);
2916 			else
2917 				func (stream, "CLEAN.icon.window = 0x%lX;\n", clean->icon.window);
2918 			func (stream, "CLEAN.icon_mask = 0x%lX;\n", clean->icon_mask);
2919 			if (get_flags (clean->client_icon_flags, AS_ClientIconPosition))
2920 				func (stream, "CLEAN.icon_x = %d;\nCLEAN.icon_y = %d;\n",
2921 							clean->icon_x, clean->icon_y);
2922 		} else if (clean->icon_file)
2923 			func (stream, "CLEAN.icon_file = \"%s\";\n", clean->icon_file);
2924 	}
2925 	if (get_flags (clean->flags, AS_MinSize))
2926 		func (stream, "CLEAN.min_width = %u;\nCLEAN.min_height = %u;\n",
2927 					clean->min_width, clean->min_height);
2928 	if (get_flags (clean->flags, AS_MaxSize))
2929 		func (stream, "CLEAN.max_width = %u;\nCLEAN.max_height = %u;\n",
2930 					clean->max_width, clean->max_height);
2931 	if (get_flags (clean->flags, AS_SizeInc))
2932 		func (stream, "CLEAN.width_inc = %u;\nCLEAN.height_inc = %u;\n",
2933 					clean->width_inc, clean->height_inc);
2934 	if (get_flags (clean->flags, AS_Aspect)) {
2935 		func (stream, "CLEAN.min_aspect.x = %d;\nCLEAN.min_aspect.y = %d;\n",
2936 					clean->min_aspect.x, clean->min_aspect.y);
2937 		func (stream, "CLEAN.max_aspect.x = %d;\nCLEAN.max_aspect.y = %d;\n",
2938 					clean->max_aspect.x, clean->max_aspect.y);
2939 	}
2940 	if (get_flags (clean->flags, AS_BaseSize))
2941 		func (stream, "CLEAN.base_width = %u;\nCLEAN.base_height = %u;\n",
2942 					clean->base_width, clean->base_height);
2943 	if (get_flags (clean->flags, AS_Gravity))
2944 		func (stream, "CLEAN.gravity = %d;\n", clean->gravity);
2945 	if (get_flags (clean->flags, AS_Border))
2946 		func (stream, "CLEAN.border_width = %u;\n", clean->border_width);
2947 	if (get_flags (clean->flags, AS_Handles))
2948 		func (stream, "CLEAN.handle_width = %u;\n", clean->handle_width);
2949 
2950 	if (clean->group_lead)
2951 		func (stream, "CLEAN.group_lead = 0x%lX;\n", clean->group_lead);
2952 	if (get_flags (clean->flags, AS_Transient))
2953 		func (stream, "CLEAN.transient_for = 0x%lX;\n", clean->transient_for);
2954 
2955 	if (clean->cmap_windows)
2956 		for (i = 0; clean->cmap_windows[i] != None; i++)
2957 			func (stream, "CLEAN.cmap_windows[%d] = 0x%lX;\n", i,
2958 						clean->cmap_windows[i]);
2959 
2960 	if (get_flags (clean->flags, AS_PID))
2961 		func (stream, "CLEAN.pid = %d;\n", clean->pid);
2962 	if (clean->frame_name && get_flags (clean->flags, AS_Frame))
2963 		func (stream, "CLEAN.frame_name = \"%s\";\n", clean->frame_name);
2964 	if (clean->windowbox_name && get_flags (clean->flags, AS_Windowbox))
2965 		func (stream, "CLEAN.windowbox_name = \"%s\";\n",
2966 					clean->windowbox_name);
2967 
2968 	for (i = 0; i < BACK_STYLES; i++)
2969 		if (clean->mystyle_names[i])
2970 			func (stream, "CLEAN.mystyle_names[%d] = \"%s\";\n", i,
2971 						clean->mystyle_names[i]);
2972 
2973 	func (stream, "CLEAN.disabled_buttons = 0x%lX;\n",
2974 				clean->disabled_buttons);
2975 
2976 	func (stream, "CLEAN.hints_types_raw = 0x%lX;\n",
2977 				clean->hints_types_raw);
2978 	func (stream, "CLEAN.hints_types_clean = 0x%lX;\n",
2979 				clean->hints_types_clean);
2980 
2981 	if (clean->client_host)
2982 		func (stream, "CLEAN.client_host = \"%s\";\n", clean->client_host);
2983 	if (clean->client_cmd)
2984 		func (stream, "CLEAN.client_cmd = \"%s\";\n", clean->client_cmd);
2985 
2986 	func (stream, "CLEAN.extwm_window_type = \"%s\";\n", clean->extwm_window_type);
2987 }
2988 
2989 void
print_status_hints(stream_func func,void * stream,ASStatusHints * status)2990 print_status_hints (stream_func func, void *stream, ASStatusHints * status)
2991 {
2992 	if (!pre_print_check
2993 			(&func, &stream, status, "No status available(NULL)."))
2994 		return;
2995 
2996 	func (stream, "STATUS.flags = 0x%lX;\n", status->flags);
2997 
2998 	if (get_flags (status->flags, AS_StartPositionUser)) {
2999 		func (stream, "STATUS.user_x = %d;\n", status->x);
3000 		func (stream, "STATUS.user_y = %d;\n", status->y);
3001 	} else {
3002 		func (stream, "STATUS.x = %d;\n", status->x);
3003 		func (stream, "STATUS.y = %d;\n", status->y);
3004 	}
3005 	if (get_flags (status->flags, AS_Size)) {
3006 		func (stream, "STATUS.width = %d;\n", status->width);
3007 		func (stream, "STATUS.height = %d;\n", status->height);
3008 	}
3009 	if (get_flags (status->flags, AS_Desktop))
3010 		func (stream, "STATUS.desktop = %d;\n", status->desktop);
3011 	if (get_flags (status->flags, AS_Layer))
3012 		func (stream, "STATUS.layer = %d;\n", status->layer);
3013 	if (get_flags (status->flags, AS_StartViewportX | AS_StartViewportX)) {
3014 		func (stream, "STATUS.viewport_x = %d;\n", status->viewport_x);
3015 		func (stream, "STATUS.viewport_y = %d;\n", status->viewport_y);
3016 	}
3017 }
3018 
3019 /*********************************************************************************
3020  *  serialization for purpose of inter-module communications                     *
3021  *********************************************************************************/
serialize_string(char * string,ASVector * buf)3022 void serialize_string (char *string, ASVector * buf)
3023 {
3024 	if (buf) {
3025 		register CARD32 *ptr;
3026 		register char *src = string;
3027 		register int i = string ? strlen (string) >> 2 : 0;	/* assume CARD32 == 4*CARD8 :)) */
3028 
3029 		append_vector (buf, NULL, 1 + i + 1);
3030 		ptr = VECTOR_TAIL (CARD32, *buf);
3031 		VECTOR_USED (*buf) += i + 1;
3032 		ptr[0] = i + 1;
3033 		++ptr;
3034 		if (string == NULL) {
3035 			ptr[0] = 0;
3036 			return;
3037 		}
3038 		src = &(string[i << 2]);
3039 		/* unrolling loop here : */
3040 		ptr[i] = src[0] & 0x0FF;
3041 		if (src[0]) {
3042 			if (src[1]) {							/* we don't really want to use bitwise operations */
3043 				/* so we get "true" number and later can do ENDIANNES transformations */
3044 				ptr[i] |= (((CARD32) src[1]) << 8) & 0x0FF00;
3045 				if (src[2])
3046 					ptr[i] |= (((CARD32) src[2]) << 16) & 0x0FF0000;
3047 			}
3048 		}
3049 		while (--i >= 0) {
3050 			src -= 4;
3051 			ptr[i] =
3052 					(((CARD32) src[0]) & 0x0FF) | (((CARD32) src[1] << 8) & 0x0FF00)
3053 					| (((CARD32) src[2] << 16) & 0x0FF0000)
3054 					| (((CARD32) src[3] << 24) & 0xFF000000);
3055 		}
3056 	}
3057 }
3058 
serialize_CARD32_zarray(CARD32 * array,ASVector * buf)3059 void serialize_CARD32_zarray (CARD32 * array, ASVector * buf)
3060 {
3061 	register int i = 0;
3062 	register CARD32 *ptr;
3063 
3064 	if (array)
3065 		while (array[i])
3066 			i++;
3067 	i++;
3068 	append_vector (buf, NULL, 1 + i);
3069 	ptr = VECTOR_TAIL (CARD32, *buf);
3070 	VECTOR_USED (*buf) += i;
3071 	ptr[0] = i;
3072 	ptr++;
3073 	if (array == NULL)
3074 		ptr[0] = 0;
3075 	else
3076 		while (--i >= 0)
3077 			ptr[i] = array[i];
3078 }
3079 
serialize_clean_hints(ASHints * clean,ASVector * buf)3080 Bool serialize_clean_hints (ASHints * clean, ASVector * buf)
3081 {
3082 	register CARD32 *ptr;
3083 	register int i = 0;
3084 
3085 	if (clean == NULL || buf == NULL)
3086 		return False;
3087 
3088 	/* we expect CARD32 vector here : */
3089 	if (VECTOR_UNIT (*buf) != sizeof (CARD32))
3090 		return False;
3091 
3092 	append_vector (buf, NULL, ASHINTS_STATIC_DATA);
3093 	ptr = VECTOR_TAIL (CARD32, *buf);
3094 	ptr[i++] = clean->flags;
3095 	ptr[i++] = clean->protocols;
3096 	ptr[i++] = clean->function_mask;
3097 	ptr[i++] = clean->icon.window;
3098 	ptr[i++] = clean->icon_mask;
3099 	ptr[i++] = clean->icon_x;
3100 	ptr[i++] = clean->icon_y;
3101 
3102 	ptr[i++] = clean->min_width;
3103 	ptr[i++] = clean->min_height;
3104 	ptr[i++] = clean->max_width;
3105 	ptr[i++] = clean->max_height;
3106 	ptr[i++] = clean->width_inc;
3107 	ptr[i++] = clean->height_inc;
3108 	ptr[i++] = clean->min_aspect.x;
3109 	ptr[i++] = clean->min_aspect.y;
3110 	ptr[i++] = clean->max_aspect.x;
3111 	ptr[i++] = clean->max_aspect.y;
3112 	ptr[i++] = clean->base_width;
3113 	ptr[i++] = clean->base_height;
3114 
3115 	ptr[i++] = clean->gravity;
3116 	ptr[i++] = clean->border_width;
3117 	ptr[i++] = clean->handle_width;
3118 
3119 	ptr[i++] = clean->group_lead;
3120 	ptr[i++] = clean->transient_for;
3121 
3122 	ptr[i++] = clean->pid;
3123 
3124 	ptr[i++] = clean->disabled_buttons;
3125 
3126 	ptr[i++] = clean->hints_types_raw;
3127 	ptr[i++] = clean->hints_types_clean;
3128 	VECTOR_USED (*buf) += i;
3129 
3130 	serialize_CARD32_zarray (clean->cmap_windows, buf);
3131 
3132 	serialize_string (clean->icon_file, buf);
3133 	serialize_string (clean->frame_name, buf);
3134 	serialize_string (clean->windowbox_name, buf);
3135 
3136 	for (i = 0; i < BACK_STYLES; i++)
3137 		serialize_string (clean->mystyle_names[i], buf);
3138 
3139 	serialize_string (clean->client_host, buf);
3140 	serialize_string (clean->client_cmd, buf);
3141 
3142 	return True;
3143 }
3144 
serialize_names(ASHints * clean,ASVector * buf)3145 Bool serialize_names (ASHints * clean, ASVector * buf)
3146 {
3147 	CARD32 header[4];
3148 	register int i;
3149 
3150 	if (clean == NULL || buf == NULL)
3151 		return False;
3152 	header[0] =
3153 			pointer_name_to_index_in_list (clean->names, clean->res_name);
3154 	header[1] =
3155 			pointer_name_to_index_in_list (clean->names, clean->res_class);
3156 	header[2] =
3157 			pointer_name_to_index_in_list (clean->names, clean->icon_name);
3158 	for (i = 0; clean->names[i] != NULL && i < MAX_WINDOW_NAMES; i++) ;
3159 	header[3] = i;
3160 	append_vector (buf, &(header[0]), 4);
3161 
3162 	for (i = 0; clean->names[i] != NULL && i < MAX_WINDOW_NAMES; i++)
3163 		serialize_string (clean->names[i], buf);
3164 
3165 	return True;
3166 }
3167 
serialize_status_hints(ASStatusHints * status,ASVector * buf)3168 Bool serialize_status_hints (ASStatusHints * status, ASVector * buf)
3169 {
3170 	register CARD32 *ptr;
3171 	register int i = 0;
3172 
3173 	if (status == NULL || buf == NULL)
3174 		return False;
3175 
3176 	/* we expect CARD32 vector here : */
3177 	if (VECTOR_UNIT (*buf) != sizeof (CARD32))
3178 		return False;
3179 
3180 	append_vector (buf, NULL, ASSTATUSHINTS_STATIC_DATA);
3181 	ptr = VECTOR_TAIL (CARD32, *buf);
3182 	ptr[i++] = status->flags;
3183 
3184 	ptr[i++] = status->x;
3185 	ptr[i++] = status->y;
3186 	ptr[i++] = status->width;
3187 	ptr[i++] = status->height;
3188 	ptr[i++] = status->border_width;
3189 	ptr[i++] = status->viewport_x;
3190 	ptr[i++] = status->viewport_y;
3191 	ptr[i++] = status->desktop;
3192 	ptr[i++] = status->layer;
3193 	ptr[i++] = status->icon_window;
3194 	VECTOR_USED (*buf) += i;
3195 
3196 	return True;
3197 }
3198 
3199 /*********************************************************************************
3200  *  deserialization so that module can read out communications 	                 *
3201  *********************************************************************************/
deserialize_string(CARD32 ** pbuf,size_t * buf_size)3202 char *deserialize_string (CARD32 ** pbuf, size_t * buf_size)
3203 {
3204 	char *string;
3205 	CARD32 *buf = *pbuf;
3206 	size_t len;
3207 	register int i;
3208 	register char *str;
3209 
3210 	if (*pbuf == NULL)
3211 		return NULL;
3212 	if (buf_size && *buf_size < 2)
3213 		return NULL;
3214 	len = buf[0];
3215 	if (buf_size && len > *buf_size + 1)
3216 		return NULL;
3217 	buf++;
3218 	str = string = safemalloc (len << 2);
3219 	for (i = 0; i < len; i++) {
3220 		str[0] = (buf[i] & 0x0FF);
3221 		str[1] = (buf[i] >> 8) & 0x0FF;
3222 		str[2] = (buf[i] >> 16) & 0x0FF;
3223 		str[3] = (buf[i] >> 24) & 0x0FF;
3224 		str += 4;
3225 	}
3226 
3227 	if (buf_size)
3228 		*buf_size -= len;
3229 	*pbuf += len;
3230 
3231 	return string;
3232 }
3233 
deserialize_CARD32_zarray(CARD32 ** pbuf,size_t * buf_size)3234 CARD32 *deserialize_CARD32_zarray (CARD32 ** pbuf, size_t * buf_size)
3235 {
3236 	CARD32 *array;
3237 	CARD32 *buf = *pbuf;
3238 	size_t len;
3239 	register int i;
3240 
3241 	if (*pbuf == NULL || *buf_size < 2)
3242 		return NULL;
3243 	len = buf[0];
3244 	if (len > *buf_size + 1)
3245 		return NULL;
3246 	buf++;
3247 	array = safemalloc (len * sizeof (CARD32));
3248 	for (i = 0; i < len; i++)
3249 		array[i] = buf[i];
3250 
3251 	*buf_size -= len;
3252 	*pbuf += len;
3253 
3254 	return array;
3255 }
3256 
deserialize_clean_hints(CARD32 ** pbuf,size_t * buf_size,ASHints * reusable_memory)3257 ASHints *deserialize_clean_hints (CARD32 ** pbuf, size_t * buf_size,
3258 																	ASHints * reusable_memory)
3259 {
3260 	ASHints *clean = reusable_memory;
3261 	register int i = 0;
3262 	register CARD32 *buf = *pbuf;
3263 
3264 	if (buf == NULL || *buf_size < ASHINTS_STATIC_DATA)
3265 		return False;
3266 
3267 	if (clean == NULL)
3268 		clean = safecalloc (1, sizeof (ASHints));
3269 
3270 	clean->flags = buf[i++];
3271 	clean->protocols = buf[i++];
3272 	clean->function_mask = buf[i++];
3273 
3274 	clean->icon.window = buf[i++];
3275 	clean->icon_mask = buf[i++];
3276 	clean->icon_x = buf[i++];
3277 	clean->icon_y = buf[i++];
3278 
3279 	clean->min_width = buf[i++];
3280 	clean->min_height = buf[i++];
3281 	clean->max_width = buf[i++];
3282 	clean->max_height = buf[i++];
3283 	clean->width_inc = buf[i++];
3284 	clean->height_inc = buf[i++];
3285 	clean->min_aspect.x = buf[i++];
3286 	clean->min_aspect.y = buf[i++];
3287 	clean->max_aspect.x = buf[i++];
3288 	clean->max_aspect.y = buf[i++];
3289 	clean->base_width = buf[i++];
3290 	clean->base_height = buf[i++];
3291 	clean->gravity = buf[i++];
3292 	clean->border_width = buf[i++];
3293 	clean->handle_width = buf[i++];
3294 	clean->group_lead = buf[i++];
3295 	clean->transient_for = buf[i++];
3296 	clean->pid = buf[i++];
3297 	clean->disabled_buttons = buf[i++];
3298 
3299 	clean->hints_types_raw = buf[i++];
3300 	clean->hints_types_clean = buf[i++];
3301 
3302 	*buf_size -= i;
3303 	*pbuf += i;
3304 	if (clean->cmap_windows)
3305 		free (clean->cmap_windows);
3306 	clean->cmap_windows = deserialize_CARD32_zarray (pbuf, buf_size);
3307 
3308 	if (clean->icon_file)
3309 		free (clean->icon_file);
3310 	clean->icon_file = deserialize_string (pbuf, buf_size);
3311 	if (clean->frame_name)
3312 		free (clean->frame_name);
3313 	clean->frame_name = deserialize_string (pbuf, buf_size);
3314 	if (clean->windowbox_name)
3315 		free (clean->windowbox_name);
3316 	clean->windowbox_name = deserialize_string (pbuf, buf_size);
3317 
3318 	for (i = 0; i < BACK_STYLES; i++) {
3319 		if (clean->mystyle_names[i])
3320 			free (clean->mystyle_names[i]);
3321 		clean->mystyle_names[i] = deserialize_string (pbuf, buf_size);
3322 	}
3323 	if (clean->client_host)
3324 		free (clean->client_host);
3325 	clean->client_host = deserialize_string (pbuf, buf_size);
3326 	if (clean->client_cmd)
3327 		free (clean->client_cmd);
3328 	clean->client_cmd = deserialize_string (pbuf, buf_size);
3329 
3330 	return clean;
3331 }
3332 
deserialize_names(ASHints * clean,CARD32 ** pbuf,size_t * buf_size)3333 Bool deserialize_names (ASHints * clean, CARD32 ** pbuf, size_t * buf_size)
3334 {
3335 	CARD32 header[4];
3336 	CARD32 *buf = *pbuf;
3337 	register int i;
3338 
3339 	if (clean == NULL || buf == NULL || *buf_size < 4)
3340 		return False;
3341 
3342 	header[0] = buf[0];
3343 	header[1] = buf[1];
3344 	header[2] = buf[2];
3345 	header[3] = buf[3];
3346 
3347 	if (header[3] <= 0 || header[3] >= MAX_WINDOW_NAMES)
3348 		return False;
3349 
3350 	*buf_size -= 4;
3351 	*pbuf += 4;
3352 
3353 	for (i = 0; i < header[3]; i++) {
3354 		if (clean->names[i])
3355 			free (clean->names[i]);
3356 		clean->names[i] = deserialize_string (pbuf, buf_size);
3357 	}
3358 	clean->res_name =
3359 			(header[0] < MAX_WINDOW_NAMES) ? clean->names[header[0]] : NULL;
3360 	clean->res_name_idx = 0;
3361 	clean->res_class =
3362 			(header[1] < MAX_WINDOW_NAMES) ? clean->names[header[1]] : NULL;
3363 	clean->res_class_idx = 0;
3364 	clean->icon_name =
3365 			(header[2] < MAX_WINDOW_NAMES) ? clean->names[header[2]] : NULL;
3366 	clean->icon_name_idx = 0;
3367 
3368 	return True;
3369 }
3370 
3371 
deserialize_status_hints(CARD32 ** pbuf,size_t * buf_size,ASStatusHints * reusable_memory)3372 ASStatusHints *deserialize_status_hints (CARD32 ** pbuf, size_t * buf_size,
3373 																				 ASStatusHints * reusable_memory)
3374 {
3375 	ASStatusHints *status = reusable_memory;
3376 	register int i = 0;
3377 	register CARD32 *buf = *pbuf;
3378 
3379 	if (buf == NULL || *buf_size < ASSTATUSHINTS_STATIC_DATA)
3380 		return False;
3381 
3382 	if (status == NULL)
3383 		status = safecalloc (1, sizeof (ASStatusHints));
3384 
3385 	status->flags = buf[i++];
3386 	status->x = buf[i++];
3387 	status->y = buf[i++];
3388 	status->width = buf[i++];
3389 	status->height = buf[i++];
3390 	status->border_width = buf[i++];
3391 	status->viewport_x = buf[i++];
3392 	status->viewport_y = buf[i++];
3393 	status->desktop = buf[i++];
3394 	status->layer = buf[i++];
3395 	status->icon_window = buf[i++];
3396 	*buf_size -= i;
3397 	*pbuf += i;
3398 
3399 	return status;
3400 }
3401 
3402 /*********************************************************************************
3403  *                  List of Supported Hints management                           *
3404  *********************************************************************************/
create_hints_list()3405 ASSupportedHints *create_hints_list ()
3406 {
3407 	ASSupportedHints *list;
3408 
3409 	list = (ASSupportedHints *) safecalloc (1, sizeof (ASSupportedHints));
3410 	return list;
3411 }
3412 
destroy_hints_list(ASSupportedHints ** plist)3413 void destroy_hints_list (ASSupportedHints ** plist)
3414 {
3415 	if (*plist) {
3416 		free (*plist);
3417 		*plist = NULL;
3418 	}
3419 }
3420 
HintsTypes2Func(HintsTypes type)3421 static hints_merge_func HintsTypes2Func (HintsTypes type)
3422 {
3423 	switch (type) {
3424 	case HINTS_ICCCM:
3425 		return merge_icccm_hints;
3426 	case HINTS_GroupLead:
3427 		return merge_group_hints;
3428 	case HINTS_Transient:
3429 		return merge_transient_hints;
3430 	case HINTS_Motif:
3431 		return merge_motif_hints;
3432 	case HINTS_Gnome:
3433 		return merge_gnome_hints;
3434 	case HINTS_KDE:
3435 		return merge_kde_hints;
3436 	case HINTS_ExtendedWM:
3437 		return merge_extwm_hints;
3438 	case HINTS_XResources:
3439 		return merge_xresources_hints;
3440 	case HINTS_ASDatabase:
3441 		return merge_asdb_hints;
3442 	case HINTS_Supported:
3443 		break;
3444 	}
3445 	return NULL;
3446 }
3447 
Func2HintsTypes(hints_merge_func func)3448 HintsTypes Func2HintsTypes (hints_merge_func func)
3449 {
3450 	if (func == merge_group_hints)
3451 		return HINTS_GroupLead;
3452 	else if (func == merge_transient_hints)
3453 		return HINTS_Transient;
3454 	else if (func == merge_motif_hints)
3455 		return HINTS_Motif;
3456 	else if (func == merge_gnome_hints)
3457 		return HINTS_Gnome;
3458 	else if (func == merge_extwm_hints)
3459 		return HINTS_ExtendedWM;
3460 	else if (func == merge_kde_hints)
3461 		return HINTS_KDE;
3462 	else if (func == merge_xresources_hints)
3463 		return HINTS_XResources;
3464 	else if (func == merge_asdb_hints)
3465 		return HINTS_ASDatabase;
3466 	return HINTS_ICCCM;
3467 }
3468 
enable_hints_support(ASSupportedHints * list,HintsTypes type)3469 Bool enable_hints_support (ASSupportedHints * list, HintsTypes type)
3470 {
3471 	if (list) {
3472 		if (list->hints_num >= HINTS_Supported)
3473 			list->hints_num = HINTS_Supported - 1;	/* we are being paranoid */
3474 
3475 		if (get_flags (list->hints_flags, (0x01 << type)))	/* checking for duplicates */
3476 			return False;
3477 
3478 		if ((list->merge_funcs[list->hints_num] =
3479 				 HintsTypes2Func (type)) == NULL)
3480 			return False;
3481 
3482 		list->hints_types[list->hints_num] = type;
3483 		set_flags (list->hints_flags, (0x01 << type));
3484 		list->hints_num++;
3485 		return True;
3486 	}
3487 	return False;
3488 }
3489 
disable_hints_support(ASSupportedHints * list,HintsTypes type)3490 Bool disable_hints_support (ASSupportedHints * list, HintsTypes type)
3491 {
3492 	if (list) {
3493 		register int i;
3494 
3495 		if (list->hints_num > HINTS_Supported)
3496 			list->hints_num = HINTS_Supported;	/* we are being paranoid */
3497 		for (i = 0; i < list->hints_num; i++)
3498 			if (list->hints_types[i] == type) {
3499 				list->hints_num--;
3500 				for (; i < list->hints_num; i++) {
3501 					list->merge_funcs[i] = list->merge_funcs[i + 1];
3502 					list->hints_types[i] = list->hints_types[i + 1];
3503 				}
3504 				list->merge_funcs[i] = NULL;
3505 				list->hints_types[i] = HINTS_Supported;
3506 				clear_flags (list->hints_flags, (0x01 << type));
3507 				return True;
3508 			}
3509 	}
3510 	return False;
3511 }
3512 
supported_hints_types(ASSupportedHints * list,int * num_return)3513 HintsTypes *supported_hints_types (ASSupportedHints * list,
3514 																	 int *num_return)
3515 {
3516 	HintsTypes *types = NULL;
3517 	int curr = 0;
3518 
3519 	if (list)
3520 		if ((curr = list->hints_num) > 0)
3521 			types = list->hints_types;
3522 
3523 	if (num_return)
3524 		*num_return = curr;
3525 	return types;
3526 }
3527