1 /*
2 * Copyright © 2005 Novell, Inc.
3 *
4 * Permission to use, copy, modify, distribute, and sell this software
5 * and its documentation for any purpose is hereby granted without
6 * fee, provided that the above copyright notice appear in all copies
7 * and that both that copyright notice and this permission notice
8 * appear in supporting documentation, and that the name of
9 * Novell, Inc. not be used in advertising or publicity pertaining to
10 * distribution of the software without specific, written prior permission.
11 * Novell, Inc. makes no representations about the suitability of this
12 * software for any purpose. It is provided "as is" without express or
13 * implied warranty.
14 *
15 * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
17 * NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
19 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
20 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
21 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 *
23 * Author: David Reveman <davidr@novell.com>
24 */
25
26 #include <stdlib.h>
27 #include <string.h>
28 #include <strings.h>
29 #include <ctype.h>
30 #include <math.h>
31
32 #include <compiz-core.h>
33
34 struct _Modifier {
35 char *name;
36 int modifier;
37 } modifiers[] = {
38 { "<Shift>", ShiftMask },
39 { "<Control>", ControlMask },
40 { "<Mod1>", Mod1Mask },
41 { "<Mod2>", Mod2Mask },
42 { "<Mod3>", Mod3Mask },
43 { "<Mod4>", Mod4Mask },
44 { "<Mod5>", Mod5Mask },
45 { "<Alt>", CompAltMask },
46 { "<Meta>", CompMetaMask },
47 { "<Super>", CompSuperMask },
48 { "<Hyper>", CompHyperMask },
49 { "<ModeSwitch>", CompModeSwitchMask }
50 };
51
52 #define N_MODIFIERS (sizeof (modifiers) / sizeof (struct _Modifier))
53
54 struct _Edge {
55 char *name;
56 char *modifierName;
57 } edges[] = {
58 { "Left", "<LeftEdge>" },
59 { "Right", "<RightEdge>" },
60 { "Top", "<TopEdge>" },
61 { "Bottom", "<BottomEdge>" },
62 { "TopLeft", "<TopLeftEdge>" },
63 { "TopRight", "<TopRightEdge>" },
64 { "BottomLeft", "<BottomLeftEdge>" },
65 { "BottomRight", "<BottomRightEdge>" }
66 };
67
68 void
compInitOptionValue(CompOptionValue * v)69 compInitOptionValue (CompOptionValue *v)
70 {
71 memset (v, 0, sizeof (CompOptionValue));
72 }
73
74 void
compFiniOptionValue(CompOptionValue * v,CompOptionType type)75 compFiniOptionValue (CompOptionValue *v,
76 CompOptionType type)
77 {
78 int i;
79
80 switch (type) {
81 case CompOptionTypeString:
82 if (v->s)
83 free (v->s);
84 break;
85 case CompOptionTypeMatch:
86 matchFini (&v->match);
87 break;
88 case CompOptionTypeList:
89 for (i = 0; i < v->list.nValue; i++)
90 compFiniOptionValue (&v->list.value[i], v->list.type);
91
92 if (v->list.value)
93 free (v->list.value);
94 break;
95 default:
96 break;
97 }
98 }
99
100 void
compInitOption(CompOption * o)101 compInitOption (CompOption *o)
102 {
103 memset (o, 0, sizeof (CompOption));
104 }
105
106 void
compFiniOption(CompOption * o)107 compFiniOption (CompOption *o)
108 {
109 compFiniOptionValue (&o->value, o->type);
110 }
111
112 CompOption *
compFindOption(CompOption * option,int nOption,const char * name,int * index)113 compFindOption (CompOption *option,
114 int nOption,
115 const char *name,
116 int *index)
117 {
118 int i;
119
120 for (i = 0; i < nOption; i++)
121 {
122 if (strcmp (option[i].name, name) == 0)
123 {
124 if (index)
125 *index = i;
126
127 return &option[i];
128 }
129 }
130
131 return 0;
132 }
133
134 Bool
compSetBoolOption(CompOption * option,CompOptionValue * value)135 compSetBoolOption (CompOption *option,
136 CompOptionValue *value)
137 {
138 int b;
139
140 b = (value->b) ? TRUE : FALSE;
141
142 if (option->value.b == b)
143 return FALSE;
144
145 option->value.b = b;
146
147 return TRUE;
148 }
149
150 Bool
compSetIntOption(CompOption * option,CompOptionValue * value)151 compSetIntOption (CompOption *option,
152 CompOptionValue *value)
153 {
154 if (value->i < option->rest.i.min ||
155 value->i > option->rest.i.max ||
156 value->i == option->value.i)
157 return FALSE;
158
159 option->value.i = value->i;
160
161 return TRUE;
162 }
163
164 Bool
compSetFloatOption(CompOption * option,CompOptionValue * value)165 compSetFloatOption (CompOption *option,
166 CompOptionValue *value)
167 {
168 float v, p;
169
170 /* Workaround for float rounding errors */
171 static float equalRange = 1e-5;
172
173 int sign = (value->f < 0 ? -1 : 1);
174
175 p = 1.0f / option->rest.f.precision;
176 v = ((int) (value->f * p + sign * 0.5f)) / p;
177
178 if (v < (option->rest.f.min - equalRange) ||
179 v > (option->rest.f.max + equalRange))
180 return FALSE;
181
182 if (v > (option->value.f - equalRange) &&
183 v < (option->value.f + equalRange))
184 return FALSE;
185
186 option->value.f = v;
187
188 return TRUE;
189 }
190
191 Bool
compSetStringOption(CompOption * option,CompOptionValue * value)192 compSetStringOption (CompOption *option,
193 CompOptionValue *value)
194 {
195 char *s;
196
197 s = value->s;
198 if (!s)
199 s = "";
200
201 if (option->value.s == s)
202 return FALSE;
203
204 if (option->value.s && s)
205 {
206 if (strcmp (option->value.s, s) == 0)
207 return FALSE;
208 }
209
210 if (option->value.s)
211 free (option->value.s);
212
213 option->value.s = strdup (s);
214
215 return TRUE;
216 }
217
218 Bool
compSetColorOption(CompOption * option,CompOptionValue * value)219 compSetColorOption (CompOption *option,
220 CompOptionValue *value)
221 {
222 if (memcmp (value->c, option->value.c, sizeof (value->c)) == 0)
223 return FALSE;
224
225 memcpy (option->value.c, value->c, sizeof (value->c));
226
227 return TRUE;
228 }
229
230 Bool
compSetActionOption(CompOption * option,CompOptionValue * value)231 compSetActionOption (CompOption *option,
232 CompOptionValue *value)
233 {
234 CompAction *action = &option->value.action;
235 CompOptionValue v = *value;
236
237 /* initiate, terminate, priv and state should never be changed */
238 v.action.initiate = action->initiate;
239 v.action.terminate = action->terminate;
240 v.action.state = action->state;
241 v.action.priv = action->priv;
242
243 if (action->type == v.action.type)
244 {
245 switch (option->type) {
246 case CompOptionTypeKey:
247 if (!(action->type & CompBindingTypeKey))
248 return FALSE;
249
250 if (action->key.keycode == v.action.key.keycode &&
251 action->key.modifiers == v.action.key.modifiers)
252 return FALSE;
253 break;
254 case CompOptionTypeButton:
255 if (!(action->type & (CompBindingTypeButton |
256 CompBindingTypeEdgeButton)))
257 return FALSE;
258
259 if (action->type & CompBindingTypeEdgeButton)
260 {
261 if (action->button.button == v.action.button.button &&
262 action->button.modifiers == v.action.button.modifiers &&
263 action->edgeMask == v.action.edgeMask)
264 return FALSE;
265 }
266 else if (action->type & CompBindingTypeButton)
267 {
268 if (action->button.button == v.action.button.button &&
269 action->button.modifiers == v.action.button.modifiers)
270 return FALSE;
271 }
272 break;
273 case CompOptionTypeEdge:
274 if (v.action.edgeMask == action->edgeMask)
275 return FALSE;
276 break;
277 case CompOptionTypeBell:
278 if (v.action.bell == action->bell)
279 return FALSE;
280 break;
281 default:
282 return FALSE;
283 }
284 }
285
286 *action = v.action;
287
288 return TRUE;
289 }
290
291 Bool
compSetMatchOption(CompOption * option,CompOptionValue * value)292 compSetMatchOption (CompOption *option,
293 CompOptionValue *value)
294 {
295 CompDisplay *display = option->value.match.display;
296 CompMatch match;
297
298 if (matchEqual (&option->value.match, &value->match))
299 return FALSE;
300
301 if (!matchCopy (&match, &value->match))
302 return FALSE;
303
304 matchFini (&option->value.match);
305
306 option->value.match.op = match.op;
307 option->value.match.nOp = match.nOp;
308
309 if (display)
310 matchUpdate (display, &option->value.match);
311
312 return TRUE;
313 }
314
315 Bool
compSetOptionList(CompOption * option,CompOptionValue * value)316 compSetOptionList (CompOption *option,
317 CompOptionValue *value)
318 {
319 CompOption o;
320 Bool status = FALSE;
321 int i, min;
322
323 if (value->list.nValue != option->value.list.nValue)
324 {
325 CompOptionValue *v;
326
327 v = malloc (sizeof (CompOptionValue) * value->list.nValue);
328 if (!v)
329 return FALSE;
330
331 min = MIN (value->list.nValue, option->value.list.nValue);
332
333 for (i = min; i < option->value.list.nValue; i++)
334 {
335 switch (option->value.list.type) {
336 case CompOptionTypeString:
337 if (option->value.list.value[i].s)
338 free (option->value.list.value[i].s);
339 break;
340 case CompOptionTypeMatch:
341 matchFini (&option->value.list.value[i].match);
342 default:
343 break;
344 }
345 }
346
347 memset (v, 0, sizeof (CompOptionValue) * value->list.nValue);
348
349 if (min)
350 memcpy (v, option->value.list.value,
351 sizeof (CompOptionValue) * min);
352
353 if (option->value.list.value)
354 free (option->value.list.value);
355
356 option->value.list.value = v;
357 option->value.list.nValue = value->list.nValue;
358
359 status = TRUE;
360 }
361
362 o = *option;
363 o.type = option->value.list.type;
364
365 for (i = 0; i < value->list.nValue; i++)
366 {
367 o.value = option->value.list.value[i];
368
369 switch (o.type) {
370 case CompOptionTypeBool:
371 status |= compSetBoolOption (&o, &value->list.value[i]);
372 break;
373 case CompOptionTypeInt:
374 status |= compSetIntOption (&o, &value->list.value[i]);
375 break;
376 case CompOptionTypeFloat:
377 status |= compSetFloatOption (&o, &value->list.value[i]);
378 break;
379 case CompOptionTypeString:
380 status |= compSetStringOption (&o, &value->list.value[i]);
381 break;
382 case CompOptionTypeColor:
383 status |= compSetColorOption (&o, &value->list.value[i]);
384 break;
385 case CompOptionTypeMatch:
386 status |= compSetMatchOption (&o, &value->list.value[i]);
387 default:
388 break;
389 }
390
391 option->value.list.value[i] = o.value;
392 }
393
394 return status;
395 }
396
397 Bool
compSetOption(CompOption * option,CompOptionValue * value)398 compSetOption (CompOption *option,
399 CompOptionValue *value)
400 {
401 switch (option->type) {
402 case CompOptionTypeBool:
403 return compSetBoolOption (option, value);
404 case CompOptionTypeInt:
405 return compSetIntOption (option, value);
406 case CompOptionTypeFloat:
407 return compSetFloatOption (option, value);
408 case CompOptionTypeString:
409 return compSetStringOption (option, value);
410 case CompOptionTypeColor:
411 return compSetColorOption (option, value);
412 case CompOptionTypeMatch:
413 return compSetMatchOption (option, value);
414 case CompOptionTypeAction:
415 case CompOptionTypeKey:
416 case CompOptionTypeButton:
417 case CompOptionTypeEdge:
418 case CompOptionTypeBell:
419 return compSetActionOption (option, value);
420 case CompOptionTypeList:
421 return compSetOptionList (option, value);
422 }
423
424 return FALSE;
425 }
426
427 Bool
getBoolOptionNamed(CompOption * option,int nOption,const char * name,Bool defaultValue)428 getBoolOptionNamed (CompOption *option,
429 int nOption,
430 const char *name,
431 Bool defaultValue)
432 {
433 while (nOption--)
434 {
435 if (option->type == CompOptionTypeBool)
436 if (strcmp (option->name, name) == 0)
437 return option->value.b;
438
439 option++;
440 }
441
442 return defaultValue;
443 }
444
445 int
getIntOptionNamed(CompOption * option,int nOption,const char * name,int defaultValue)446 getIntOptionNamed (CompOption *option,
447 int nOption,
448 const char *name,
449 int defaultValue)
450 {
451 while (nOption--)
452 {
453 if (option->type == CompOptionTypeInt)
454 if (strcmp (option->name, name) == 0)
455 return option->value.i;
456
457 option++;
458 }
459
460 return defaultValue;
461 }
462
463 float
getFloatOptionNamed(CompOption * option,int nOption,const char * name,float defaultValue)464 getFloatOptionNamed (CompOption *option,
465 int nOption,
466 const char *name,
467 float defaultValue)
468 {
469 while (nOption--)
470 {
471 if (option->type == CompOptionTypeFloat)
472 if (strcmp (option->name, name) == 0)
473 return option->value.f;
474
475 option++;
476 }
477
478 return defaultValue;
479 }
480
481 char *
getStringOptionNamed(CompOption * option,int nOption,const char * name,char * defaultValue)482 getStringOptionNamed (CompOption *option,
483 int nOption,
484 const char *name,
485 char *defaultValue)
486 {
487 while (nOption--)
488 {
489 if (option->type == CompOptionTypeString)
490 if (strcmp (option->name, name) == 0)
491 return option->value.s;
492
493 option++;
494 }
495
496 return defaultValue;
497 }
498
499 unsigned short *
getColorOptionNamed(CompOption * option,int nOption,const char * name,unsigned short * defaultValue)500 getColorOptionNamed (CompOption *option,
501 int nOption,
502 const char *name,
503 unsigned short *defaultValue)
504 {
505 while (nOption--)
506 {
507 if (option->type == CompOptionTypeColor)
508 if (strcmp (option->name, name) == 0)
509 return option->value.c;
510
511 option++;
512 }
513
514 return defaultValue;
515 }
516
517 CompMatch *
getMatchOptionNamed(CompOption * option,int nOption,const char * name,CompMatch * defaultValue)518 getMatchOptionNamed (CompOption *option,
519 int nOption,
520 const char *name,
521 CompMatch *defaultValue)
522 {
523 while (nOption--)
524 {
525 if (option->type == CompOptionTypeMatch)
526 if (strcmp (option->name, name) == 0)
527 return &option->value.match;
528
529 option++;
530 }
531
532 return defaultValue;
533 }
534
535 static char *
stringAppend(char * s,const char * a)536 stringAppend (char *s,
537 const char *a)
538 {
539 char *r;
540 int len;
541
542 len = strlen (a);
543
544 if (s)
545 len += strlen (s);
546
547 r = malloc (len + 1);
548 if (r)
549 {
550 if (s)
551 {
552 sprintf (r, "%s%s", s, a);
553 free (s);
554 }
555 else
556 {
557 sprintf (r, "%s", a);
558 }
559
560 s = r;
561 }
562
563 return s;
564 }
565
566 static char *
modifiersToString(CompDisplay * d,unsigned int modMask)567 modifiersToString (CompDisplay *d,
568 unsigned int modMask)
569 {
570 char *binding = NULL;
571 int i;
572
573 for (i = 0; i < N_MODIFIERS; i++)
574 {
575 if (modMask & modifiers[i].modifier)
576 binding = stringAppend (binding, modifiers[i].name);
577 }
578
579 return binding;
580 }
581
582 static char *
edgeMaskToBindingString(CompDisplay * d,unsigned int edgeMask)583 edgeMaskToBindingString (CompDisplay *d,
584 unsigned int edgeMask)
585 {
586 char *binding = NULL;
587 int i;
588
589 for (i = 0; i < SCREEN_EDGE_NUM; i++)
590 if (edgeMask & (1 << i))
591 binding = stringAppend (binding, edges[i].modifierName);
592
593 return binding;
594 }
595
596 char *
keyBindingToString(CompDisplay * d,CompKeyBinding * key)597 keyBindingToString (CompDisplay *d,
598 CompKeyBinding *key)
599 {
600 char *binding;
601
602 binding = modifiersToString (d, key->modifiers);
603
604 if (key->keycode != 0)
605 {
606 KeySym keysym;
607 char *keyname;
608
609 keysym = XKeycodeToKeysym (d->display, key->keycode, 0);
610 keyname = XKeysymToString (keysym);
611
612 if (keyname)
613 {
614 binding = stringAppend (binding, keyname);
615 }
616 else
617 {
618 char keyCodeStr[256];
619
620 snprintf (keyCodeStr, 256, "0x%x", key->keycode);
621 binding = stringAppend (binding, keyCodeStr);
622 }
623 }
624
625 return binding;
626 }
627
628 char *
buttonBindingToString(CompDisplay * d,CompButtonBinding * button)629 buttonBindingToString (CompDisplay *d,
630 CompButtonBinding *button)
631 {
632 char *binding;
633 char buttonStr[256];
634
635 binding = modifiersToString (d, button->modifiers);
636
637 snprintf (buttonStr, 256, "Button%d", button->button);
638 binding = stringAppend (binding, buttonStr);
639
640 return binding;
641 }
642
643 char *
keyActionToString(CompDisplay * d,CompAction * action)644 keyActionToString (CompDisplay *d,
645 CompAction *action)
646 {
647 char *binding;
648
649 binding = keyBindingToString (d, &action->key);
650 if (!binding)
651 return strdup ("Disabled");
652
653 return binding;
654 }
655
656 char *
buttonActionToString(CompDisplay * d,CompAction * action)657 buttonActionToString (CompDisplay *d,
658 CompAction *action)
659 {
660 char *binding, *edge;
661 char buttonStr[256];
662
663 binding = modifiersToString (d, action->button.modifiers);
664 edge = edgeMaskToBindingString (d, action->edgeMask);
665
666 if (edge)
667 {
668 binding = stringAppend (binding, edge);
669 free (edge);
670 }
671
672 snprintf (buttonStr, 256, "Button%d", action->button.button);
673 binding = stringAppend (binding, buttonStr);
674
675 if (!binding)
676 return strdup ("Disabled");
677
678 return binding;
679 }
680
681 static unsigned int
stringToModifiers(CompDisplay * d,const char * binding)682 stringToModifiers (CompDisplay *d,
683 const char *binding)
684 {
685 unsigned int mods = 0;
686 int i;
687
688 for (i = 0; i < N_MODIFIERS; i++)
689 {
690 if (strstr (binding, modifiers[i].name))
691 mods |= modifiers[i].modifier;
692 }
693
694 return mods;
695 }
696
697 static unsigned int
bindingStringToEdgeMask(CompDisplay * d,const char * binding)698 bindingStringToEdgeMask (CompDisplay *d,
699 const char *binding)
700 {
701 unsigned int edgeMask = 0;
702 int i;
703
704 for (i = 0; i < SCREEN_EDGE_NUM; i++)
705 if (strstr (binding, edges[i].modifierName))
706 edgeMask |= 1 << i;
707
708 return edgeMask;
709 }
710
711 Bool
stringToKeyBinding(CompDisplay * d,const char * binding,CompKeyBinding * key)712 stringToKeyBinding (CompDisplay *d,
713 const char *binding,
714 CompKeyBinding *key)
715 {
716 char *ptr;
717 unsigned int mods;
718 KeySym keysym;
719
720 mods = stringToModifiers (d, binding);
721
722 ptr = strrchr (binding, '>');
723 if (ptr)
724 binding = ptr + 1;
725
726 while (*binding && !isalnum (*binding))
727 binding++;
728
729 if (!*binding)
730 {
731 if (mods)
732 {
733 key->keycode = 0;
734 key->modifiers = mods;
735
736 return TRUE;
737 }
738
739 return FALSE;
740 }
741
742 keysym = XStringToKeysym (binding);
743 if (keysym != NoSymbol)
744 {
745 KeyCode keycode;
746
747 keycode = XKeysymToKeycode (d->display, keysym);
748 if (keycode)
749 {
750 key->keycode = keycode;
751 key->modifiers = mods;
752
753 return TRUE;
754 }
755 }
756
757 if (strncmp (binding, "0x", 2) == 0)
758 {
759 key->keycode = strtol (binding, NULL, 0);
760 key->modifiers = mods;
761
762 return TRUE;
763 }
764
765 return FALSE;
766 }
767
768 Bool
stringToButtonBinding(CompDisplay * d,const char * binding,CompButtonBinding * button)769 stringToButtonBinding (CompDisplay *d,
770 const char *binding,
771 CompButtonBinding *button)
772 {
773 char *ptr;
774 unsigned int mods;
775
776 mods = stringToModifiers (d, binding);
777
778 ptr = strrchr (binding, '>');
779 if (ptr)
780 binding = ptr + 1;
781
782 while (*binding && !isalnum (*binding))
783 binding++;
784
785 if (strncmp (binding, "Button", strlen ("Button")) == 0)
786 {
787 int buttonNum;
788
789 if (sscanf (binding + strlen ("Button"), "%d", &buttonNum) == 1)
790 {
791 button->button = buttonNum;
792 button->modifiers = mods;
793
794 return TRUE;
795 }
796 }
797
798 return FALSE;
799 }
800
801 void
stringToKeyAction(CompDisplay * d,const char * binding,CompAction * action)802 stringToKeyAction (CompDisplay *d,
803 const char *binding,
804 CompAction *action)
805 {
806 if (stringToKeyBinding (d, binding, &action->key))
807 action->type = CompBindingTypeKey;
808 else
809 action->type = CompBindingTypeNone;
810 }
811
812 void
stringToButtonAction(CompDisplay * d,const char * binding,CompAction * action)813 stringToButtonAction (CompDisplay *d,
814 const char *binding,
815 CompAction *action)
816 {
817 if (stringToButtonBinding (d, binding, &action->button))
818 {
819 action->edgeMask = bindingStringToEdgeMask (d, binding);
820 if (action->edgeMask)
821 action->type = CompBindingTypeEdgeButton;
822 else
823 action->type = CompBindingTypeButton;
824 }
825 else
826 {
827 action->type = CompBindingTypeNone;
828 }
829 }
830
831 const char *
edgeToString(unsigned int edge)832 edgeToString (unsigned int edge)
833 {
834 return edges[edge].name;
835 }
836
837 unsigned int
stringToEdgeMask(const char * edge)838 stringToEdgeMask (const char *edge)
839 {
840 unsigned int edgeMask = 0;
841 char *needle;
842 int i;
843
844 for (i = 0; i < SCREEN_EDGE_NUM; i++)
845 {
846 needle = strstr (edge, edgeToString (i));
847 if (needle)
848 {
849 if (needle != edge && isalnum (*(needle - 1)))
850 continue;
851
852 needle += strlen (edgeToString (i));
853
854 if (*needle && isalnum (*needle))
855 continue;
856
857 edgeMask |= 1 << i;
858 }
859 }
860
861 return edgeMask;
862 }
863
864 char *
edgeMaskToString(unsigned int edgeMask)865 edgeMaskToString (unsigned int edgeMask)
866 {
867 char *edge = NULL;
868 int i;
869
870 for (i = 0; i < SCREEN_EDGE_NUM; i++)
871 {
872 if (edgeMask & (1 << i))
873 {
874 if (edge)
875 edge = stringAppend (edge, " | ");
876
877 edge = stringAppend (edge, edgeToString (i));
878 }
879 }
880
881 if (!edge)
882 return strdup ("");
883
884 return edge;
885 }
886
887 Bool
stringToColor(const char * color,unsigned short * rgba)888 stringToColor (const char *color,
889 unsigned short *rgba)
890 {
891 int c[4];
892
893 if (sscanf (color, "#%2x%2x%2x%2x", &c[0], &c[1], &c[2], &c[3]) == 4)
894 {
895 rgba[0] = c[0] << 8 | c[0];
896 rgba[1] = c[1] << 8 | c[1];
897 rgba[2] = c[2] << 8 | c[2];
898 rgba[3] = c[3] << 8 | c[3];
899
900 return TRUE;
901 }
902
903 return FALSE;
904 }
905
906 char *
colorToString(unsigned short * rgba)907 colorToString (unsigned short *rgba)
908 {
909 char tmp[256];
910
911 snprintf (tmp, 256, "#%.2x%.2x%.2x%.2x",
912 rgba[0] / 256, rgba[1] / 256, rgba[2] / 256, rgba[3] / 256);
913
914 return strdup (tmp);
915 }
916
917 const char *
optionTypeToString(CompOptionType type)918 optionTypeToString (CompOptionType type)
919 {
920 switch (type) {
921 case CompOptionTypeBool:
922 return "bool";
923 case CompOptionTypeInt:
924 return "int";
925 case CompOptionTypeFloat:
926 return "float";
927 case CompOptionTypeString:
928 return "string";
929 case CompOptionTypeColor:
930 return "color";
931 case CompOptionTypeAction:
932 return "action";
933 case CompOptionTypeKey:
934 return "key";
935 case CompOptionTypeButton:
936 return "button";
937 case CompOptionTypeEdge:
938 return "edge";
939 case CompOptionTypeBell:
940 return "bell";
941 case CompOptionTypeMatch:
942 return "match";
943 case CompOptionTypeList:
944 return "list";
945 }
946
947 return "unknown";
948 }
949
950 Bool
isActionOption(CompOption * option)951 isActionOption (CompOption *option)
952 {
953 switch (option->type) {
954 case CompOptionTypeAction:
955 case CompOptionTypeKey:
956 case CompOptionTypeButton:
957 case CompOptionTypeEdge:
958 case CompOptionTypeBell:
959 return TRUE;
960 default:
961 break;
962 }
963
964 return FALSE;
965 }
966