Fix CursorMove command to correctly honour EdgeScroll settings.
[fvwm.git] / modules / FvwmIconMan / readconfig.c
blob57b9527466ff1ad51464c5d7453474719db4a4d6
1 /* -*-c-*- */
2 /* This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 #include "config.h"
18 #include <ctype.h>
19 #include "FvwmIconMan.h"
20 #include "readconfig.h"
21 #include "xmanager.h"
22 #include "libs/defaults.h"
23 #include "libs/fvwmlib.h"
24 #include "libs/FScreen.h"
25 #include "libs/FShape.h"
26 #include "libs/Module.h"
27 #include "libs/Parse.h"
28 #include "libs/Strings.h"
32 * Builtin functions:
36 extern int builtin_quit(int numargs, BuiltinArg *args);
37 extern int builtin_printdebug(int numargs, BuiltinArg *args);
38 extern int builtin_gotobutton(int numargs, BuiltinArg *args);
39 extern int builtin_gotomanager(int numargs, BuiltinArg *args);
40 extern int builtin_refresh(int numargs, BuiltinArg *args);
41 extern int builtin_select(int numargs, BuiltinArg *args);
42 extern int builtin_sendcommand(int numargs, BuiltinArg *args);
43 extern int builtin_bif(int numargs, BuiltinArg *args);
44 extern int builtin_bifn(int numargs, BuiltinArg *args);
45 extern int builtin_print(int numargs, BuiltinArg *args);
46 extern int builtin_jmp(int numargs, BuiltinArg *args);
47 extern int builtin_ret(int numargs, BuiltinArg *args);
48 extern int builtin_searchforward(int numargs, BuiltinArg *args);
49 extern int builtin_searchback(int numargs, BuiltinArg *args);
50 extern int builtin_warp(int numargs, BuiltinArg *args);
52 /* compiler pseudo-functions */
53 static int builtin_label(int numargs, BuiltinArg *args);
55 typedef struct {
56 char *name;
57 int (*func)(int numargs, BuiltinArg *args);
58 int numargs;
59 BuiltinArgType args[MAX_ARGS];
60 } FunctionType;
63 * these are now sorted so we can use bsearch on them.
65 FunctionType builtin_functions[] = {
66 { "bif", builtin_bif, 2, { ButtonArg, JmpArg } },
67 { "bifn", builtin_bifn, 2, { ButtonArg, JmpArg } },
68 { "gotobutton", builtin_gotobutton, 1, { ButtonArg } },
69 { "gotomanager", builtin_gotomanager, 1, { ManagerArg } },
70 { "jmp", builtin_jmp, 1, { JmpArg } },
71 { "label", builtin_label, 1, { StringArg } },
72 { "print", builtin_print, 1, { StringArg } },
73 { "printdebug", builtin_printdebug, 0, {0} },
74 { "quit", builtin_quit, 0, {0} },
75 { "refresh", builtin_refresh, 0, {0} },
76 { "ret", builtin_ret, 0, {0} },
77 { "searchback", builtin_searchback, 1, { StringArg } },
78 { "searchforward", builtin_searchforward, 1, { StringArg } },
79 { "select", builtin_select, 0, {0} },
80 { "sendcommand", builtin_sendcommand, 1, { StringArg } },
81 { "warp", builtin_warp, 0, {0} }
84 static int num_builtins = sizeof(builtin_functions) / sizeof(FunctionType);
86 /* This is only used for printing out the .fvwmrc line if an error
87 occured */
89 #define PRINT_LINE_LENGTH 80
90 static char current_line[PRINT_LINE_LENGTH];
92 static void save_current_line(char *s)
94 char *p = current_line;
96 while (*s && p < current_line + PRINT_LINE_LENGTH - 1) {
97 if (*s == '\n')
99 *p = '\0';
100 return;
102 else
104 *p++ = *s++;
107 *p = '\0';
110 void print_args(int numargs, BuiltinArg *args)
112 #ifdef FVWM_DEBUG_MSGS
113 int i;
115 for (i = 0; i < numargs; i++) {
116 switch (args[i].type) {
117 case NoArg:
118 ConsoleDebug(CONFIG, "NoArg ");
119 break;
121 case IntArg:
122 ConsoleDebug(
123 CONFIG, "Int: %d ", args[i].value.int_value);
124 break;
126 case StringArg:
127 ConsoleDebug(
128 CONFIG, "String: %s ",
129 args[i].value.string_value);
130 break;
132 case ButtonArg:
133 ConsoleDebug(
134 CONFIG, "Button: %d %d ",
135 args[i].value.button_value.offset,
136 args[i].value.button_value.base);
137 break;
139 case WindowArg:
140 ConsoleDebug(
141 CONFIG, "Window: %d %d ",
142 args[i].value.button_value.offset,
143 args[i].value.button_value.base);
144 break;
146 case ManagerArg:
147 ConsoleDebug(
148 CONFIG, "Manager: %d %d ",
149 args[i].value.button_value.offset,
150 args[i].value.button_value.base);
151 break;
153 case JmpArg:
154 ConsoleDebug(
155 CONFIG, "Unprocessed Label Jump: %s ",
156 args[i].value.string_value);
157 break;
159 default:
160 ConsoleDebug(CONFIG, "bad ");
161 break;
164 ConsoleDebug(CONFIG, "\n");
165 #endif
168 #ifdef FVWM_DEBUG_MSGS
169 static void print_binding(Binding *binding)
171 int i;
172 Function *func;
174 if (binding->type == BIND_BUTTONPRESS)
176 ConsoleDebug(CONFIG, "\tMouse: %d\n", binding->Button_Key);
178 else
180 ConsoleDebug(
181 CONFIG, "\tKey or action: %d %s\n",
182 binding->Button_Key, binding->key_name);
185 ConsoleDebug(CONFIG, "\tModifiers: %d\n", binding->Modifier);
186 ConsoleDebug(CONFIG, "\tAction: %s\n", (char *) binding->Action);
187 ConsoleDebug(CONFIG, "\tFunction struct: 0x%x\n",
188 (unsigned int) binding->Action2);
189 func = (Function *)(binding->Action2);
190 while (func)
192 for (i = 0; i < num_builtins; i++)
194 if (func->func == builtin_functions[i].func)
196 ConsoleDebug(
197 CONFIG, "\tFunction: %s 0x%x ",
198 builtin_functions[i].name,
199 (unsigned int) func->func);
200 break;
203 if (i > num_builtins)
205 ConsoleDebug(
206 CONFIG, "\tFunction: not found 0x%x ",
207 (unsigned int) func->func);
209 print_args(func->numargs, func->args);
210 func = func->next;
214 void print_bindings(Binding *list)
216 ConsoleDebug(CONFIG, "binding list:\n");
217 while (list != NULL)
219 print_binding(list);
220 ConsoleDebug(CONFIG, "\n");
221 list = list->NextBinding;
224 #else
225 void print_bindings(Binding *list)
228 #endif
230 static int iswhite(char c)
232 if (c == ' ' || c == '\t' || c == '\0')
234 return 1;
236 return 0;
239 static void trim(char *p)
241 int length = strlen(p) -1;
242 int index;
243 for (index = length; index > 0; index --)
245 if (p[index] == ' ' || p[index] == '\t')
247 p[index] = '\0';
249 else
251 return;
256 static void skip_space(char **p)
258 while (**p == ' ' || **p == '\t')
260 (*p)++;
264 static void add_to_binding(Binding **list, Binding *binding)
266 ConsoleDebug(CONFIG, "In add_to_binding:\n");
268 binding->NextBinding = *list;
269 *list = binding;
270 return;
273 static int extract_int(char *p, int *n)
275 char *s;
276 int sign = 1;
278 while (isspace((unsigned char)*p) && *p)
280 p++;
283 if (*p == '-')
285 sign = -1;
286 p++;
288 else if (*p == '+') {
289 sign = 1;
290 p++;
293 if (*p == '\0')
295 return 0;
298 for (s = p; *s; s++)
300 if (*s < '0' || *s > '9')
302 return 0;
306 *n = atoi(p) * sign;
308 return 1;
311 static char *parse_button(char *string, BuiltinArg *arg, int *flag,
312 char *pstop_char)
314 char *rest, *token;
315 ButtonValue *bv;
316 int n;
318 ConsoleDebug(CONFIG, "parse_term: %s\n", string);
320 *flag = 1;
322 arg->type = ButtonArg;
323 bv = &arg->value.button_value;
324 bv->offset = 0;
325 bv->base = AbsoluteButton;
327 rest = DoGetNextToken(string, &token, NULL, ",", pstop_char);
328 if (token == NULL)
330 bv->base = NoButton;
331 *flag = 0;
332 Free(token);
333 return NULL;
335 if (!strcasecmp(token, "focus"))
337 bv->base = FocusButton;
339 else if (!strcasecmp(token, "select"))
341 bv->base = SelectButton;
343 else if (!strcasecmp(token, "up"))
345 bv->base = UpButton;
347 else if (!strcasecmp(token, "down"))
349 bv->base = DownButton;
351 else if (!strcasecmp(token, "left"))
353 bv->base = LeftButton;
355 else if (!strcasecmp(token, "right"))
357 bv->base = RightButton;
359 else if (!strcasecmp(token, "next"))
361 bv->base = NextButton;
363 else if (!strcasecmp(token, "prev"))
365 bv->base = PrevButton;
367 else if (extract_int(token, &n))
369 bv->base = AbsoluteButton;
370 bv->offset = n;
372 else
374 ConsoleMessage("Bad button: %s\n", token);
375 bv->base = NoButton;
376 Free(token);
377 *flag = 0;
378 return NULL;
381 Free(token);
382 return rest;
385 static void free_function_list(Function *func)
387 int i;
388 Function *fp = func;
390 while (fp)
392 for (i = 0; i < fp->numargs; i++)
394 if (fp->args[i].type == StringArg)
396 Free(fp->args[i].value.string_value);
399 func = fp;
400 fp = fp->next;
401 Free(func);
405 static int funccasecmp(
406 const void *key /* actually char* */,
407 const void *member /* actually FunctionType* */)
409 return strcasecmp((char *)key, ((FunctionType *)member)->name);
413 * The label function. Should never be called, but we need a pointer to it,
414 * and it's useful for debugging purposes to have it defined.
416 static int builtin_label(int numargs, BuiltinArg *args)
418 int j;
419 /* we should _never_ be called */
420 ConsoleMessage( "label" );
421 for (j=0; j<numargs; ++j)
423 switch (args[j].type)
425 case StringArg:
426 ConsoleMessage(" %s", args[j].value.string_value);
427 break;
429 default:
430 ConsoleMessage(" [unknown arg #: %d]", args[j].type);
433 ConsoleMessage(" was called. This should not happen.\n");
434 return 0;
437 /* the number of JmpArg arguments that have been created, but not yet
438 resolved into IntArgs. */
439 static int JmpArgs = 0;
440 /* icky, I know, but it'll save unnecessary error-checking. */
442 static Function *parse_function(char **line, char *pstop_char)
444 Function *ftype = (Function *)safemalloc(sizeof(Function));
445 char *ptr, *name, *tok;
446 int j, flag;
447 FunctionType *builtin_functions_i;
449 ConsoleDebug(CONFIG, "in parse_function\n");
451 ptr = DoGetNextToken(*line, &name, NULL, ",", pstop_char);
452 if (name == NULL) {
453 Free(ftype);
454 *line = NULL;
455 return NULL;
458 builtin_functions_i=bsearch((void *)name, (void *)builtin_functions,
459 num_builtins, sizeof(FunctionType),
460 funccasecmp);
461 if (builtin_functions_i) {
462 Free(name);
463 ftype->func = builtin_functions_i->func;
464 ftype->numargs = builtin_functions_i->numargs;
465 ftype->next = NULL;
467 for (j = 0; j < builtin_functions_i->numargs && *pstop_char != ','; j++) {
468 ftype->args[j].type = builtin_functions_i->args[j];
469 switch (builtin_functions_i->args[j]) {
470 case IntArg:
471 ptr = DoGetNextToken(ptr, &tok, NULL, ",", pstop_char);
472 if (!tok) {
473 ConsoleMessage("%s: too few arguments\n",
474 builtin_functions_i->name);
475 Free(ftype);
476 *line = NULL;
477 return NULL;
479 if (extract_int(tok, &ftype->args[j].value.int_value) == 0) {
480 ConsoleMessage("%s: expect integer argument: %s\n",
481 builtin_functions_i->name, tok);
482 Free(tok);
483 Free(ftype);
484 *line = NULL;
485 return NULL;
487 Free(tok);
488 break;
490 case StringArg:
491 ptr = DoGetNextToken(ptr, &ftype->args[j].value.string_value,NULL,
492 ",", pstop_char);
493 if (!ftype->args[j].value.string_value) {
494 ConsoleMessage("%s: too few arguments\n",
495 builtin_functions_i->name);
496 *line = NULL;
497 Free(ftype->args[j].value.string_value);
498 Free(ftype);
499 return NULL;
501 ftype->args[j].type = builtin_functions_i->args[j];
502 break;
504 case ButtonArg:
505 case WindowArg:
506 case ManagerArg:
507 ptr = parse_button(ptr, &ftype->args[j], &flag, pstop_char);
508 if (!flag) {
509 ConsoleMessage("%s: too few arguments\n",
510 builtin_functions_i->name);
511 Free(ftype);
512 *line = NULL;
513 return NULL;
515 ftype->args[j].type = builtin_functions_i->args[j];
516 break;
518 /* JmpArg can be a string or an int. However, if 'JmpArg'
519 * is recorded as the argument type in the argument array
520 * for a command, it means it is a string; the code for
521 * 'IntArg' is used instead for numbers. Note also that
522 * if the C function recieves a 'JmpArg' argument it means something
523 * went wrong, since they should all be translated to integer
524 * jump offsets at compile time.
526 case JmpArg:
527 ptr = DoGetNextToken(ptr, &tok, NULL, ",", pstop_char);
528 if (!tok) {
529 ConsoleMessage("%s: too few arguments\n",
530 builtin_functions_i->name);
531 Free(tok);
532 Free(ftype);
533 *line=NULL;
534 return NULL;
536 if (extract_int(tok, &ftype->args[j].value.int_value) == 0) {
537 ftype->args[j].value.string_value=tok;
538 ftype->args[j].type = JmpArg;
539 ++JmpArgs;
540 } else {
541 ftype->args[j].type = IntArg;
542 Free(tok);
544 break;
546 default:
547 ConsoleMessage("internal error in parse_function\n");
548 Free(ftype);
549 *line = NULL;
550 return NULL;
554 if (j != builtin_functions_i->numargs) {
555 ConsoleMessage("%s: too few arguments\n", builtin_functions_i->name);
556 Free(ftype);
557 *line = NULL;
558 return NULL;
561 *line = ptr;
562 return ftype;
565 ConsoleMessage("Unknown function: %s\n", name);
566 Free(name);
568 *line = NULL;
569 return NULL;
573 /* This is O(N^2) where N = number of instructions. Seems we could do better.
574 We'll see how this addition settles before monkeying with it */
576 static Function *parse_function_list(char *line)
578 Function *ret = NULL, *tail = NULL, *f, *i;
579 char *token;
580 int jump_count, j;
581 char stop_char;
582 char c;
584 JmpArgs=0;
585 while (line && (f = parse_function(&line, &stop_char))) {
586 ConsoleDebug(CONFIG, "parse_function: 0x%lx\n", (unsigned long)f->func);
587 /* extra code to check for and remove a 'label' pseudo-function */
588 if (f->func==builtin_label) {
589 /* scan backwards to fix up references */
590 jump_count=0;
591 for (i=tail; i!=NULL; i=i->prev) {
592 /* scan the command arguments for a 'JmpArg' type */
593 for (j=0; j<(i->numargs); ++j) {
594 if (i->args[j].type==JmpArg) {
595 /* we have a winner! */
596 if (!strcasecmp(f->args[0].value.string_value,
597 i->args[j].value.string_value)) {
598 /* the label matches it, so replace with the jump_count */
599 i->args[j].type = IntArg;
600 i->args[j].value.int_value = jump_count;
601 --JmpArgs;
605 ++jump_count;
607 Free(f); /* label pseudo-functions never get added to the chain */
608 } else {
609 if (tail)
610 tail->next = f;
611 else
612 ret = f;
613 f->prev=tail;
614 tail = f;
616 DoGetNextToken(line, &token, NULL, ",", &c);
617 if (token && stop_char != ',') {
618 ConsoleMessage("Bad function list, comma expected\n");
619 Free(token);
620 return NULL;
622 stop_char = c;
623 Free(token);
626 if (JmpArgs!=0) {
627 /* someone made a typo and we need to scan to find out what it
628 * was.
630 for (f=tail; f; f=f->prev) {
631 for (j=0; j<(f->numargs); ++j) {
632 if (f->args[j].type==JmpArg) {
633 ConsoleMessage("Attempt to jump to non-existant label %s; "
634 "aborting function list.\n",
635 f->args[j].value.string_value);
636 --JmpArgs;
640 if (JmpArgs!=0)
641 ConsoleMessage( "Internal Error: JmpArgs %d not accounted for!\n",
642 JmpArgs );
643 tail=NULL;
644 f=NULL;
645 free_function_list(ret);
646 ret=NULL;
647 return NULL;
649 if (ret == NULL)
650 ConsoleMessage("No function defined\n");
651 return ret;
655 Binding *ParseMouseEntry(char *tline)
657 char modifiers[20],*action,*token;
658 Binding *new;
659 int button;
660 int n1=0,n2=0;
661 int mods;
663 /* tline points after the key word "key" */
664 action = DoGetNextToken(tline,&token, NULL, ",", NULL);
665 if(token != NULL) {
666 n1 = sscanf(token,"%d",&button);
667 if (n1 == 1 && (button < 0 || button > NUMBER_OF_EXTENDED_MOUSE_BUTTONS))
669 /* syntax error */
670 n1 = 0;
672 Free(token);
675 action = DoGetNextToken(action,&token, NULL, ",", NULL);
676 if(token != NULL) {
677 n2 = sscanf(token,"%19s",modifiers);
678 Free(token);
680 if((n1 != 1)||(n2 != 1))
681 ConsoleMessage("Mouse binding: Syntax error");
683 modifiers_string_to_modmask(modifiers, &mods);
684 if((mods & AnyModifier)&&(mods&(~AnyModifier))) {
685 ConsoleMessage("Binding specified AnyModifier and other modifers too. "
686 "Excess modifiers will be ignored.");
689 new = (Binding *)safemalloc(sizeof(Binding));
690 memset(new, 0, sizeof(Binding));
691 new->type = BIND_BUTTONPRESS;
692 new->Button_Key = button;
693 new->Modifier = mods;
694 new->Action = stripcpy(action);
695 new->Action2 = parse_function_list(action);
697 if (!new->Action2) {
698 ConsoleMessage("Bad action: %s\n", action);
699 Free(new->Action);
700 Free(new);
701 return NULL;
704 ConsoleDebug(CONFIG, "Mouse: %d %d %s\n", new->Button_Key,
705 new->Modifier, (char*)new->Action);
707 return new;
710 static Binding *ParseKeyEntry(char *tline)
712 char *action,modifiers[20],key[20],*ptr, *token, *actionstring, *keystring;
713 Binding *new = NULL, *temp, *last = NULL;
714 Function *func = NULL;
715 int i,min,max;
716 int n1=0,n2=0;
717 KeySym keysym;
718 int mods;
720 /* tline points after the key word "key" */
721 ptr = tline;
723 ptr = DoGetNextToken(ptr,&token, NULL, ",", NULL);
724 if(token != NULL) {
725 n1 = sscanf(token,"%19s",key);
726 Free(token);
729 action = DoGetNextToken(ptr,&token, NULL, ",", NULL);
730 if(token != NULL) {
731 n2 = sscanf(token,"%19s",modifiers);
732 Free(token);
735 if((n1 != 1)||(n2 != 1))
736 ConsoleMessage("Syntax error in line %s",tline);
738 modifiers_string_to_modmask(modifiers, &mods);
739 if((mods & AnyModifier)&&(mods&(~AnyModifier))) {
740 ConsoleMessage("Binding specified AnyModifier and other modifers too. Excess modifiers will be ignored.");
744 * Don't let a 0 keycode go through, since that means AnyKey to the
745 * XGrabKey call in GrabKeys().
747 if ((keysym = XStringToKeysym(key)) == NoSymbol ||
748 XKeysymToKeycode(theDisplay, keysym) == 0) {
749 ConsoleMessage("Can't find keysym: %s\n", key);
750 return NULL;
754 XDisplayKeycodes(theDisplay, &min, &max);
755 for (i=min; i<=max; i++) {
756 if (XKeycodeToKeysym(theDisplay, i, 0) == keysym) {
757 if (!func) {
758 func = parse_function_list(action);
759 if (!func) {
760 ConsoleMessage("Bad action: %s\n", action);
761 return NULL;
763 actionstring = stripcpy(action);
764 keystring = stripcpy(key);
765 } else {
766 actionstring = keystring = NULL;
768 temp = new;
769 new = (Binding *)safemalloc(sizeof(Binding));
770 memset(new, 0, sizeof(Binding));
771 new->type = BIND_KEYPRESS;
772 new->Button_Key = i;
773 new->key_name = keystring;
774 new->Modifier = mods;
775 new->Action = actionstring;
776 new->Action2 = func;
777 new->NextBinding = temp;
778 if (!last) {
779 last = new;
782 ConsoleDebug(CONFIG, "Key: %d %s %d %s\n", i, new->key_name,
783 mods, (char*)new->Action);
786 return new;
789 static Binding *ParseSimpleEntry(char *tline)
791 Binding *new;
792 Function *func;
794 func = parse_function_list(tline);
795 if (func == NULL)
797 return NULL;
800 new = (Binding *)safemalloc(sizeof(Binding));
801 memset(new, 0, sizeof(Binding));
802 new->type = BIND_KEYPRESS;
803 new->key_name = "select";
804 new->Action = stripcpy(tline);
805 new->Action2 = func;
807 return new;
810 void run_binding(WinManager *man, Action action)
812 Binding *binding = man->bindings[action];
813 ConsoleDebug(CONFIG, "run_binding:\n");
814 print_bindings(binding);
816 if (binding && binding->Action2 &&
817 ((Function *)(binding->Action2))->func)
819 run_function_list(binding->Action2);
823 void execute_function(char *string)
825 Function *func = parse_function_list(string);
826 if (func == NULL)
828 return;
830 else
832 run_function_list(func);
833 free_function_list(func);
837 static int GetConfigLineWrapper(int *fd, char **tline)
839 char *temp;
841 GetConfigLine(fd, tline);
842 if (*tline)
844 if (strncasecmp(*tline, "Colorset", 8) == 0)
846 LoadColorset(&(*tline)[8]);
848 else if (strncasecmp(
849 *tline, XINERAMA_CONFIG_STRING,
850 sizeof(XINERAMA_CONFIG_STRING) - 1) == 0)
852 FScreenConfigureModule(
853 (*tline) + sizeof(XINERAMA_CONFIG_STRING) - 1);
855 else if (strncasecmp(*tline, "IgnoreModifiers", 15) == 0)
857 sscanf((*tline) + 16, "%d", &mods_unused);
859 temp = strchr(*tline, '\n');
860 if (temp)
862 *temp = '\0';
864 /* grok the global config lines */
866 return 1;
869 return 0;
872 static char *read_next_cmd(ReadOption flag)
874 static ReadOption status;
875 static char *buffer;
876 static char *retstring, *cur_pos;
877 char *end_pos;
879 retstring = NULL;
880 if (flag != READ_LINE && !(flag & status))
882 return NULL;
885 switch (flag)
887 case READ_LINE:
888 while (GetConfigLineWrapper(fvwm_fd, &buffer))
890 cur_pos = buffer;
891 skip_space(&cur_pos);
892 if (!strncasecmp(Module, cur_pos, ModuleLen))
894 retstring = cur_pos;
895 cur_pos += ModuleLen;
897 if (*cur_pos == '*')
899 cur_pos++;
901 skip_space(&cur_pos);
903 if (isalnum(*cur_pos))
905 status = READ_OPTION;
907 else
909 status = READ_LINE;
911 break;
914 break;
916 case READ_OPTION:
917 retstring = cur_pos;
918 while (*cur_pos != '*' && !iswhite(*cur_pos))
920 cur_pos++;
922 end_pos = cur_pos;
924 if (*cur_pos == '*')
926 cur_pos++;
928 skip_space(&cur_pos);
930 if (!*cur_pos)
932 status = READ_LINE;
934 else if (isdigit(*retstring) || !strncmp(
935 retstring, "transient", 9))
937 status = READ_OPTION;
939 else if (*cur_pos)
941 status = READ_ARG;
944 *end_pos = '\0';
945 break;
947 case READ_ARG:
948 retstring = cur_pos;
949 while (!iswhite(*cur_pos))
951 cur_pos++;
953 end_pos = cur_pos;
955 skip_space(&cur_pos);
957 if (*cur_pos)
959 status = READ_ARG;
961 else
963 status = READ_LINE;
966 *end_pos = '\0';
967 break;
969 case READ_REST_OF_LINE:
970 status = READ_LINE;
971 retstring = cur_pos;
972 break;
975 if (retstring && retstring[0] == '\0')
977 retstring = NULL;
980 return retstring;
983 static char *conditional_copy_string(char **s1, char *s2)
985 if (*s1)
987 return *s1;
989 else
991 return copy_string(s1, s2);
995 static NameType parse_format_dependencies(char *format)
997 NameType flags = NO_NAME;
999 ConsoleDebug(CONFIG, "Parsing format: %s\n", format);
1001 while (*format)
1003 if (*format != '%')
1005 format++;
1007 else {
1008 format++;
1009 if (*format == 'i')
1011 flags |= ICON_NAME;
1013 else if (*format == 't')
1015 flags |= TITLE_NAME;
1017 else if (*format == 'c')
1019 flags |= CLASS_NAME;
1021 else if (*format == 'r')
1023 flags |= RESOURCE_NAME;
1025 else if (*format != '%')
1027 ConsoleMessage(
1028 "Bad format string: %s\n", format);
1032 #ifdef FVWM_DEBUG_MSGS
1033 ConsoleDebug(CONFIG, "Format depends on: ");
1034 if (flags & ICON_NAME)
1036 ConsoleDebug(CONFIG, "Icon ");
1038 if (flags & TITLE_NAME)
1040 ConsoleDebug(CONFIG, "Title ");
1042 if (flags & CLASS_NAME)
1044 ConsoleDebug(CONFIG, "Class ");
1046 if (flags & RESOURCE_NAME)
1048 ConsoleDebug(CONFIG, "Resource ");
1050 ConsoleDebug(CONFIG, "\n");
1051 #endif
1053 return flags;
1056 #define SET_MANAGER(manager,field,value) \
1057 do \
1059 int id = manager; \
1060 if (id == -1) \
1062 for (id = 0; id < globals.num_managers; id++) \
1064 globals.managers[id]. field = value; \
1067 else if (id < globals.num_managers) \
1069 globals.managers[id]. field = value; \
1071 else \
1073 ConsoleMessage( \
1074 "Internal error in SET_MANAGER: %d\n", id); \
1076 } while (0)
1078 static void handle_button_config(int manager, int context, char *option)
1080 char *p;
1081 ButtonState state;
1083 p = read_next_cmd(READ_ARG);
1084 if (!p)
1086 ConsoleMessage("Bad line: %s\n", current_line);
1087 ConsoleMessage("Need argument to %s\n", option);
1088 return;
1090 else if (!strcasecmp(p, "flat"))
1092 state = BUTTON_FLAT;
1094 else if (!strcasecmp(p, "up"))
1096 state = BUTTON_UP;
1098 else if (!strcasecmp(p, "down"))
1100 state = BUTTON_DOWN;
1102 else if (!strcasecmp(p, "raisededge"))
1104 state = BUTTON_EDGEUP;
1106 else if (!strcasecmp(p, "sunkedge"))
1108 state = BUTTON_EDGEDOWN;
1110 else
1112 ConsoleMessage("Bad line: %s\n", current_line);
1113 ConsoleMessage("This isn't a valid button state: %s\n", p);
1114 return;
1116 ConsoleDebug(
1117 CONFIG, "Setting buttonState[%s] to %s\n",
1118 contextDefaults[context].name, p);
1119 SET_MANAGER(manager, buttonState[context], state);
1121 /* check for optional fore color */
1122 p = read_next_cmd(READ_ARG);
1123 if (!p)
1125 return;
1128 SET_MANAGER(
1129 manager, foreColorName[context],
1130 copy_string(&globals.managers[id]. foreColorName[context], p));
1132 /* check for optional back color */
1133 p = read_next_cmd(READ_ARG);
1134 if (!p)
1136 return;
1139 ConsoleDebug(
1140 CONFIG, "Setting backColorName[%s] to %s\n",
1141 contextDefaults[context].name, p);
1142 SET_MANAGER(
1143 manager, backColorName[context],
1144 copy_string(&globals.managers[id].backColorName[context], p));
1147 static void add_weighted_sort(WinManager *man, WeightedSort *weighted_sort)
1149 WeightedSort *p;
1150 int i;
1152 if (man->weighted_sorts_len == man->weighted_sorts_size)
1154 i = man->weighted_sorts_size;
1155 man->weighted_sorts_size += 16;
1156 man->weighted_sorts = (WeightedSort *)saferealloc(
1157 (char *)man->weighted_sorts,
1158 man->weighted_sorts_size * sizeof(WeightedSort));
1160 p = &man->weighted_sorts[man->weighted_sorts_len];
1161 p->resname = NULL;
1162 p->classname = NULL;
1163 p->titlename = NULL;
1164 p->iconname = NULL;
1165 if (weighted_sort->resname)
1167 copy_string(&p->resname, weighted_sort->resname);
1169 if (weighted_sort->classname)
1171 copy_string(&p->classname, weighted_sort->classname);
1173 if (weighted_sort->titlename)
1175 copy_string(&p->titlename, weighted_sort->titlename);
1177 if (weighted_sort->iconname)
1179 copy_string(&p->iconname, weighted_sort->iconname);
1181 p->weight = weighted_sort->weight;
1182 ++man->weighted_sorts_len;
1185 void read_in_resources(void)
1187 char *p, *q;
1188 int i, n, manager;
1189 char *option1;
1190 Binding *binding = NULL;
1191 Resolution r;
1192 Reverse rv;
1194 InitGetConfigLine(fvwm_fd, Module);
1196 while ((p = read_next_cmd(READ_LINE))) {
1197 ConsoleDebug(CONFIG, "line: %s\n", p);
1198 save_current_line(p);
1200 option1 = read_next_cmd(READ_OPTION);
1201 if (option1 == NULL)
1202 continue;
1204 ConsoleDebug(CONFIG, "option1: %s\n", option1);
1205 if (!strcasecmp(option1, "nummanagers")) {
1206 /* If in transient mode, just use the default of 1 manager */
1207 if (!globals.transient) {
1208 p = read_next_cmd(READ_ARG);
1209 if (!p) {
1210 ConsoleMessage("Bad line: %s\n", current_line);
1211 continue;
1213 if (extract_int(p, &n) == 0) {
1214 ConsoleMessage("This is not a number: %s\n", p);
1215 ConsoleMessage("Bad line: %s\n", current_line);
1216 continue;
1218 if (n > 0) {
1219 allocate_managers(n);
1220 ConsoleDebug(CONFIG, "num managers: %d\n", n);
1222 else {
1223 ConsoleMessage("Bad line: %s\n", current_line);
1224 ConsoleMessage("You can't have zero managers. "
1225 "I'll give you one.\n");
1226 allocate_managers(1);
1230 else {
1231 /* these all can specify a specific manager */
1233 if (globals.managers == NULL) {
1234 ConsoleDebug(CONFIG, "I'm assuming you only want one manager\n");
1235 allocate_managers(1);
1238 manager = 0;
1240 if (option1[0] >= '0' && option1[0] <= '9') {
1241 if (globals.transient) {
1242 ConsoleDebug(CONFIG, "In transient mode. Ignoring this line\n");
1243 continue;
1245 if (extract_int(option1, &manager) == 0 ||
1246 manager <= 0 || manager > globals.num_managers) {
1247 ConsoleMessage("Bad line: %s\n", current_line);
1248 ConsoleMessage("This is not a valid manager: %s.\n", option1);
1249 manager = 0;
1251 option1 = read_next_cmd(READ_OPTION);
1252 if (!option1) {
1253 ConsoleMessage("Bad line: %s\n", current_line);
1254 continue;
1257 else if (!strcasecmp(option1, "transient")) {
1258 if (globals.transient) {
1259 ConsoleDebug(CONFIG, "Transient manager config line\n");
1260 manager = 1;
1261 option1 = read_next_cmd(READ_OPTION);
1262 if (!option1) {
1263 ConsoleMessage("Bad line: %s\n", current_line);
1264 continue;
1267 else {
1268 ConsoleDebug(CONFIG, "Not in transient mode. Ignoring this line\n");
1269 continue;
1273 manager--; /* -1 means global */
1275 ConsoleDebug(CONFIG, "Applying %s to manager %d\n", option1, manager);
1277 if (!strcasecmp(option1, "action")) {
1278 p = read_next_cmd(READ_ARG);
1279 if (!p) {
1280 ConsoleMessage("Bad line: %s\n", current_line);
1281 continue;
1284 if (!strcasecmp(p, "mouse")) {
1285 i = MOUSE;
1287 else if (!strcasecmp(p, "key")) {
1288 i = KEYPRESS;
1290 else if (!strcasecmp(p, "select")) {
1291 i = SELECT;
1293 else {
1294 ConsoleMessage("Bad line: %s\n", current_line);
1295 ConsoleMessage("This isn't a valid action name: %s\n", p);
1296 continue;
1299 q = read_next_cmd(READ_REST_OF_LINE);
1300 if (!q) {
1301 ConsoleMessage("Bad line: %s\n", current_line);
1302 ConsoleMessage("Need an action\n");
1303 continue;
1306 switch (i) {
1307 case MOUSE:
1308 binding = ParseMouseEntry(q);
1309 break;
1311 case KEYPRESS:
1312 binding = ParseKeyEntry(q);
1313 break;
1315 case SELECT:
1316 binding = ParseSimpleEntry(q);
1317 break;
1320 if (binding == NULL) {
1321 ConsoleMessage("Offending line: %s\n", current_line);
1322 ConsoleMessage("Bad action\n");
1323 continue;
1326 if (manager == -1) {
1327 int j;
1328 for (j = 0; j < globals.num_managers; j++) {
1329 add_to_binding(&globals.managers[j].bindings[i], binding);
1332 else if (manager < globals.num_managers) {
1333 add_to_binding(&globals.managers[manager].bindings[i], binding);
1335 else {
1336 ConsoleMessage("Bad line: %s\n", current_line);
1337 ConsoleMessage("There's no manager %d\n", manager);
1340 else if (!strcasecmp(option1, "colorset")) {
1341 p = read_next_cmd(READ_ARG);
1342 if (!p) {
1343 ConsoleMessage("Bad line: %s\n", current_line);
1344 continue;
1346 if (extract_int(p, &n) == 0) {
1347 ConsoleMessage("This is not a number: %s\n", p);
1348 ConsoleMessage("Bad line: %s\n", current_line);
1349 continue;
1351 for ( i = 0; i < NUM_CONTEXTS; i++ ) {
1352 if (i != DEFAULT && i != TITLE_CONTEXT)
1353 SET_MANAGER(manager, colorsets[i], -2);
1354 else
1355 SET_MANAGER(manager, colorsets[i], n);
1357 AllocColorset(n);
1359 else if (!strcasecmp(option1, "background")) {
1360 p = read_next_cmd(READ_ARG);
1361 if (!p) {
1362 ConsoleMessage("Bad line: %s\n", current_line);
1363 continue;
1365 ConsoleDebug(CONFIG, "default background: %s\n", p);
1367 for ( i = 0; i < NUM_CONTEXTS; i++ )
1368 SET_MANAGER(manager, backColorName[i],
1369 conditional_copy_string(&globals.managers[id].backColorName[i],
1370 p));
1372 else if (!strcasecmp(option1, "buttongeometry")) {
1373 p = read_next_cmd(READ_ARG);
1374 if (!p) {
1375 ConsoleMessage("Bad line: %s\n", current_line);
1376 continue;
1379 SET_MANAGER(manager, button_geometry_str,
1380 copy_string(&globals.managers[id].button_geometry_str, p));
1382 else if (!strcasecmp(option1, "maxbuttonwidth")) {
1383 p = read_next_cmd(READ_ARG);
1384 if (!p) {
1385 n = 0;
1387 else if (extract_int(p, &n) == 0) {
1388 ConsoleMessage("This is not a number: %s\n", p);
1389 ConsoleMessage("Bad line: %s\n", current_line);
1390 continue;
1392 SET_MANAGER(manager, max_button_width, n);
1393 SET_MANAGER(manager, max_button_width_columns, 0);
1395 else if (!strcasecmp(option1, "maxbuttonwidthbycolumns")) {
1396 p = read_next_cmd(READ_ARG);
1397 if (!p) {
1398 n = 0;
1400 else if (extract_int(p, &n) == 0) {
1401 ConsoleMessage("This is not a number: %s\n", p);
1402 ConsoleMessage("Bad line: %s\n", current_line);
1403 continue;
1405 SET_MANAGER(manager, max_button_width, 0);
1406 SET_MANAGER(manager, max_button_width_columns, n);
1408 else if (!strcasecmp(option1, "dontshow")) {
1409 char *token = NULL;
1410 p = read_next_cmd(READ_REST_OF_LINE);
1411 if (!p) {
1412 ConsoleMessage("Bad line: %s\n", current_line);
1413 continue;
1415 p = DoGetNextToken(p, &token, NULL, ",", NULL);
1416 if (!token) {
1417 ConsoleMessage("Bad line: %s\n", current_line);
1418 continue;
1420 do {
1421 ConsoleDebug(CONFIG, "dont show: %s\n", token);
1422 if (manager == -1) {
1423 int i;
1424 for (i = 0; i < globals.num_managers; i++)
1425 add_to_stringlist(&globals.managers[i].dontshow, token);
1427 else {
1428 add_to_stringlist(&globals.managers[manager].dontshow, token);
1430 Free(token);
1431 p = DoGetNextToken(p, &token, NULL, ",", NULL);
1432 } while (token);
1433 if (token)
1434 Free(token);
1436 else if (!strcasecmp(option1, "drawicons")) {
1437 if (!FMiniIconsSupported)
1439 ConsoleMessage("DrawIcons support not compiled in\n");
1441 else
1443 p = read_next_cmd(READ_ARG);
1444 if (!p) {
1445 ConsoleMessage("Bad line: %s\n", current_line);
1446 ConsoleMessage("Need argument to drawicons\n");
1447 continue;
1449 if (!strcasecmp(p, "true")) {
1450 i = 1;
1452 /* [NFM 3 Dec 97] added support for drawicons "always" */
1453 else if (!strcasecmp(p, "always")) {
1454 i = 2;
1456 else if (!strcasecmp(p, "false")) {
1457 i = 0;
1459 else {
1460 ConsoleMessage("Bad line: %s\n", current_line);
1461 ConsoleMessage("What is this: %s?\n", p);
1462 continue;
1464 ConsoleDebug(CONFIG, "Setting drawicons to: %d\n", i);
1465 SET_MANAGER(manager, draw_icons, i);
1468 else if (!strcasecmp(option1, "followfocus")) {
1469 p = read_next_cmd(READ_ARG);
1470 if (!p) {
1471 ConsoleMessage("Bad line: %s\n", current_line);
1472 ConsoleMessage("Need argument to followfocus\n");
1473 continue;
1475 if (!strcasecmp(p, "true")) {
1476 i = 1;
1478 else if (!strcasecmp(p, "false")) {
1479 i = 0;
1481 else {
1482 ConsoleMessage("Bad line: %s\n", current_line);
1483 ConsoleMessage("What is this: %s?\n", p);
1484 continue;
1486 ConsoleDebug(CONFIG, "Setting followfocus to: %d\n", i);
1487 SET_MANAGER(manager, followFocus, i);
1489 else if (!strcasecmp(option1, "showtransient")) {
1490 p = read_next_cmd(READ_ARG);
1491 if (!p) {
1492 ConsoleMessage("Bad line: %s\n", current_line);
1493 ConsoleMessage("Need argument to showtransient\n");
1494 continue;
1496 if (!strcasecmp(p, "true")) {
1497 i = 1;
1499 else if (!strcasecmp(p, "false")) {
1500 i = 0;
1502 else {
1503 ConsoleMessage("Bad line: %s\n", current_line);
1504 ConsoleMessage("What is this: %s?\n", p);
1505 continue;
1507 ConsoleDebug(CONFIG, "Setting showtransient to: %d\n", i);
1508 SET_MANAGER(manager, showtransient, i);
1510 else if( !strcasecmp(option1, "showonlyfocused")) {
1511 p = read_next_cmd(READ_ARG);
1512 if (!p) {
1513 ConsoleMessage("Bad line: %s\n", current_line);
1514 ConsoleMessage("Need argument to showonlyfocused\n");
1515 continue;
1517 if (!strcasecmp(p, "true")) {
1518 i = 1;
1520 else if (!strcasecmp(p, "false")) {
1521 i = 0;
1523 else {
1524 ConsoleMessage("Bad line: %s\n", current_line);
1525 ConsoleMessage("What is this: %s?\n", p);
1526 continue;
1528 ConsoleMessage("Show only focused to: %d\n", i);
1529 SET_MANAGER( manager, showonlyfocused, i);
1531 else if (!strcasecmp(option1, "showonlyicons")) {
1532 p = read_next_cmd(READ_ARG);
1533 if (!p) {
1534 ConsoleMessage("Bad line: %s\n", current_line);
1535 ConsoleMessage("Need argument to showonlyicons\n");
1536 continue;
1538 if (!strcasecmp(p, "true")) {
1539 i = 1;
1541 else if (!strcasecmp(p, "false")) {
1542 i = 0;
1544 else {
1545 ConsoleMessage("Bad line: %s\n", current_line);
1546 ConsoleMessage("What is this: %s?\n", p);
1547 continue;
1549 ConsoleDebug(CONFIG, "Setting showonlyicons to: %d\n", i);
1550 SET_MANAGER(manager, showonlyiconic, i);
1552 else if (!strcasecmp(option1, "shownoicons")) {
1553 p = read_next_cmd(READ_ARG);
1554 if (!p) {
1555 ConsoleMessage("Bad line: %s\n", current_line);
1556 ConsoleMessage("Need argument to shownoicons\n");
1557 continue;
1559 if (!strcasecmp(p, "true")) {
1560 i = 1;
1562 else if (!strcasecmp(p, "false")) {
1563 i = 0;
1565 else {
1566 ConsoleMessage("Bad line: %s\n", current_line);
1567 ConsoleMessage("What is this: %s?\n", p);
1568 continue;
1570 ConsoleDebug(CONFIG, "Setting shownoicons to: %d\n", i);
1571 SET_MANAGER(manager, shownoiconic, i);
1573 else if (!strcasecmp(option1, "font")) {
1574 char *f;
1575 p = read_next_cmd(READ_REST_OF_LINE);
1576 trim(p);
1577 if (!p) {
1578 ConsoleMessage("Bad line: %s\n", current_line);
1579 continue;
1581 CopyStringWithQuotes(&f, p);
1582 ConsoleDebug(CONFIG, "font: %s\n", f);
1584 SET_MANAGER(manager, fontname,
1585 copy_string(&globals.managers[id].fontname, f));
1586 free(f);
1588 else if (!strcasecmp(option1, "foreground")) {
1589 p = read_next_cmd(READ_ARG);
1590 if (!p) {
1591 ConsoleMessage("Bad line: %s\n", current_line);
1592 continue;
1594 ConsoleDebug(CONFIG, "default foreground: %s\n", p);
1596 for ( i = 0; i < NUM_CONTEXTS; i++ )
1597 SET_MANAGER(manager, foreColorName[i],
1598 conditional_copy_string(&globals.managers[id].foreColorName[i],
1599 p));
1601 else if (!strcasecmp(option1, "format")) {
1602 char *token;
1603 NameType flags;
1605 p = read_next_cmd(READ_REST_OF_LINE);
1606 if (!p) {
1607 ConsoleMessage("Bad line: %s\n", current_line);
1608 continue;
1610 DoGetNextToken(p, &token, NULL, ",", NULL);
1611 if (!token)
1613 token = (char *)safemalloc(1);
1614 *token = 0;
1617 SET_MANAGER(manager, formatstring,
1618 copy_string (&globals.managers[id].formatstring, token));
1619 flags = parse_format_dependencies(token);
1620 SET_MANAGER(manager, format_depend, flags);
1621 Free(token);
1623 else if (!strcasecmp(option1, "geometry")) {
1624 ConsoleMessage("Geometry option no longer supported.\n");
1625 ConsoleMessage("Use ManagerGeometry and ButtonGeometry.\n");
1627 else if (!strcasecmp(option1, "iconname")) {
1628 char *token;
1629 p = read_next_cmd(READ_REST_OF_LINE);
1630 if (!p) {
1631 ConsoleMessage("Bad line: %s\n", current_line);
1632 continue;
1634 DoGetNextToken(p, &token, NULL, ",", NULL);
1635 if (!token)
1637 token = (char *)safemalloc(1);
1638 *token = 0;
1641 SET_MANAGER(manager, iconname,
1642 copy_string(&globals.managers[id].iconname, token));
1643 Free(token);
1645 else if (!strcasecmp(option1, "managergeometry")) {
1646 p = read_next_cmd(READ_ARG);
1647 if (!p) {
1648 ConsoleMessage("Bad line: %s\n", current_line);
1649 continue;
1652 SET_MANAGER(manager, geometry_str,
1653 copy_string(&globals.managers[id].geometry_str, p));
1655 else if (!strcasecmp(option1, "resolution")) {
1656 p = read_next_cmd(READ_ARG);
1657 if (!p) {
1658 ConsoleMessage("Bad line: %s\n", current_line);
1659 continue;
1661 ConsoleDebug(CONFIG, "resolution: %s\n", p);
1662 if (!strcasecmp(p, "global"))
1663 r = SHOW_GLOBAL;
1664 else if (!strcasecmp(p, "desk"))
1665 r = SHOW_DESKTOP;
1666 else if (!strcasecmp(p, "page"))
1667 r = SHOW_PAGE;
1668 else if (!strcasecmp(p, "screen"))
1669 r = SHOW_SCREEN;
1670 else if (!strcasecmp(p, "!desk"))
1671 r = NO_SHOW_DESKTOP;
1672 else if (!strcasecmp(p, "!page"))
1673 r = NO_SHOW_PAGE;
1674 else if (!strcasecmp(p, "!screen"))
1675 r = NO_SHOW_SCREEN;
1676 else {
1677 ConsoleMessage("Bad line: %s\n", current_line);
1678 ConsoleMessage("What kind of resolution is this?\n");
1679 continue;
1682 SET_MANAGER(manager, res, r);
1684 else if (!strcasecmp(option1, "reverse")) {
1685 p = read_next_cmd(READ_ARG);
1686 if (!p) {
1687 ConsoleMessage("Bad line: %s\n", current_line);
1688 continue;
1690 ConsoleDebug(CONFIG, "reverse: %s\n", p);
1691 if (!strcasecmp(p, "none"))
1692 rv = REVERSE_NONE;
1693 else if (!strcasecmp(p, "icon"))
1694 rv = REVERSE_ICON;
1695 else if (!strcasecmp(p, "normal"))
1696 rv = REVERSE_NORMAL;
1697 else {
1698 ConsoleMessage("Bad line: %s\n", current_line);
1699 ConsoleMessage("What kind of reverse is this?\n");
1700 continue;
1703 SET_MANAGER(manager, rev, rv);
1705 else if (!strcasecmp(option1, "shape")) {
1706 p = read_next_cmd(READ_ARG);
1707 if (!p) {
1708 ConsoleMessage("Bad line: %s\n", current_line);
1709 ConsoleMessage("Need argument to shape\n");
1710 continue;
1712 if (!strcasecmp(p, "true")) {
1713 i = 1;
1715 else if (!strcasecmp(p, "false")) {
1716 i = 0;
1718 else {
1719 ConsoleMessage("Bad line: %s\n", current_line);
1720 ConsoleMessage("What is this: %s?\n", p);
1721 continue;
1723 if (!FHaveShapeExtension && i) {
1724 ConsoleMessage("Shape support not compiled in\n");
1725 continue;
1727 ConsoleDebug(CONFIG, "Setting shape to: %d\n", i);
1728 SET_MANAGER(manager, shaped, i);
1730 else if (!strcasecmp(option1, "show")) {
1731 char *token = NULL;
1732 p = read_next_cmd(READ_REST_OF_LINE);
1733 if (!p) {
1734 ConsoleMessage("Bad line: %s\n", current_line);
1735 continue;
1737 p = DoGetNextToken(p, &token, NULL, ",", NULL);
1738 if (!token) {
1739 ConsoleMessage("Bad line: %s\n", current_line);
1740 continue;
1742 do {
1743 ConsoleDebug(CONFIG, "show: %s\n", token);
1744 if (manager == -1) {
1745 int i;
1746 for (i = 0; i < globals.num_managers; i++)
1747 add_to_stringlist(&globals.managers[i].show, token);
1749 else {
1750 add_to_stringlist(&globals.managers[manager].show, token);
1752 Free(token);
1753 p = DoGetNextToken(p, &token, NULL, ",", NULL);
1754 } while (token);
1755 if (token)
1756 Free(token);
1758 else if (!strcasecmp(option1, "showtitle")) {
1759 ConsoleMessage("Bad line: %s\n", current_line);
1760 ConsoleMessage("showtitle is no longer an option. Use format\n");
1761 continue;
1763 else if (!strcasecmp(option1, "sort")) {
1764 p = read_next_cmd(READ_ARG);
1765 if (!p) {
1766 ConsoleMessage("Bad line: %s\n", current_line);
1767 ConsoleMessage("Need argument to sort\n");
1768 continue;
1770 if (!strcasecmp(p, "name")) {
1771 i = SortName;
1773 else if (!strcasecmp(p, "namewithcase")) {
1774 i = SortNameCase;
1776 else if (!strcasecmp(p, "id")) {
1777 i = SortId;
1779 else if (!strcasecmp(p, "none")) {
1780 i = SortNone;
1782 else if (!strcasecmp(p, "weighted")) {
1783 i = SortWeighted;
1785 else if (!strcasecmp(p, "false") || !strcasecmp(p, "true")) {
1786 /* Old options */
1787 ConsoleMessage("FvwmIconMan: sort option no longer takes "
1788 "true or false value\n"
1789 "Please read the latest manpage\n");
1790 continue;
1792 else {
1793 ConsoleMessage("Bad line: %s\n", current_line);
1794 ConsoleMessage("What is this: %s?\n", p);
1795 continue;
1797 ConsoleDebug(CONFIG, "Setting sort to: %d\n", i);
1798 SET_MANAGER(manager, sort, i);
1800 else if (!strcasecmp(option1, "sortweight")) {
1801 WeightedSort weighted_sort;
1802 p = read_next_cmd(READ_ARG);
1803 if (!p) {
1804 ConsoleMessage("Bad line: %s\n", current_line);
1805 continue;
1807 if (extract_int(p, &n) == 0) {
1808 ConsoleMessage("This is not a number: %s\n", p);
1809 ConsoleMessage("Bad line: %s\n", current_line);
1810 continue;
1812 weighted_sort.resname = NULL;
1813 weighted_sort.classname = NULL;
1814 weighted_sort.titlename = NULL;
1815 weighted_sort.iconname = NULL;
1816 weighted_sort.weight = n;
1817 p = read_next_cmd(READ_ARG);
1818 while (p) {
1819 if (!strncasecmp(p, "resource=", 9)) {
1820 copy_string(&weighted_sort.resname, p + 9);
1821 } else if (!strncasecmp(p, "class=", 6)) {
1822 copy_string(&weighted_sort.classname, p + 6);
1823 } else if (!strncasecmp(p, "title=", 6)) {
1824 copy_string(&weighted_sort.titlename, p + 6);
1825 } else if (!strncasecmp(p, "icon=", 5)) {
1826 copy_string(&weighted_sort.iconname, p + 5);
1827 } else {
1828 ConsoleMessage("Unknown sortweight field: %s\n", p);
1829 ConsoleMessage("Bad line: %s\n", current_line);
1831 p = read_next_cmd(READ_ARG);
1833 if (manager == -1) {
1834 for (i = 0; i < globals.num_managers; i++) {
1835 add_weighted_sort(&globals.managers[i], &weighted_sort);
1838 else {
1839 add_weighted_sort(&globals.managers[manager], &weighted_sort);
1841 if (weighted_sort.resname) {
1842 Free(weighted_sort.resname);
1844 if (weighted_sort.resname) {
1845 Free(weighted_sort.classname);
1847 if (weighted_sort.resname) {
1848 Free(weighted_sort.titlename);
1850 if (weighted_sort.resname) {
1851 Free(weighted_sort.iconname);
1854 else if (!strcasecmp(option1, "NoIconAction")) {
1855 char *token;
1856 p = read_next_cmd(READ_REST_OF_LINE);
1857 if (!p) {
1858 ConsoleMessage("Bad line: %s\n", current_line);
1859 continue;
1861 DoGetNextToken(p, &token, NULL, ",", NULL);
1862 if (!token)
1864 token = (char *)safemalloc(1);
1865 *token = 0;
1868 SET_MANAGER(manager, AnimCommand,
1869 copy_string(&globals.managers[id].AnimCommand, token));
1870 Free(token);
1872 else if (!strcasecmp(option1, "title")) {
1873 char *token;
1874 p = read_next_cmd(READ_REST_OF_LINE);
1875 if (!p) {
1876 ConsoleMessage("Bad line: %s\n", current_line);
1877 continue;
1879 DoGetNextToken(p, &token, NULL, ",", NULL);
1880 if (!token)
1882 token = (char *)safemalloc(1);
1883 *token = 0;
1886 SET_MANAGER(manager, titlename,
1887 copy_string(&globals.managers[id].titlename, token));
1888 Free(token);
1890 else if (!strcasecmp(option1, "iconButton")) {
1891 handle_button_config(manager, ICON_CONTEXT, option1);
1893 else if (!strcasecmp(option1, "plainButton")) {
1894 handle_button_config(manager, PLAIN_CONTEXT, option1);
1896 else if (!strcasecmp(option1, "selectButton")) {
1897 handle_button_config(manager, SELECT_CONTEXT, option1);
1899 else if (!strcasecmp(option1, "focusButton")) {
1900 handle_button_config(manager, FOCUS_CONTEXT, option1);
1902 else if (!strcasecmp(option1, "focusandselectButton")) {
1903 handle_button_config(manager, FOCUS_SELECT_CONTEXT, option1);
1905 else if (!strcasecmp(option1, "titlebutton")) {
1906 handle_button_config(manager, TITLE_CONTEXT, option1);
1908 else if (!strcasecmp(option1, "titlecolorset")) {
1909 p = read_next_cmd(READ_ARG);
1910 if (!p) {
1911 ConsoleMessage("Bad line: %s\n", current_line);
1912 continue;
1914 if (extract_int(p, &n) == 0) {
1915 ConsoleMessage("This is not a number: %s\n", p);
1916 ConsoleMessage("Bad line: %s\n", current_line);
1917 continue;
1919 SET_MANAGER(manager, colorsets[TITLE_CONTEXT], n);
1920 AllocColorset(n);
1922 else if (!strcasecmp(option1, "focusandselectcolorset")) {
1923 p = read_next_cmd(READ_ARG);
1924 if (!p) {
1925 ConsoleMessage("Bad line: %s\n", current_line);
1926 continue;
1928 if (extract_int(p, &n) == 0) {
1929 ConsoleMessage("This is not a number: %s\n", p);
1930 ConsoleMessage("Bad line: %s\n", current_line);
1931 continue;
1933 SET_MANAGER(manager, colorsets[FOCUS_SELECT_CONTEXT], n);
1934 AllocColorset(n);
1936 else if (!strcasecmp(option1, "focuscolorset")) {
1937 p = read_next_cmd(READ_ARG);
1938 if (!p) {
1939 ConsoleMessage("Bad line: %s\n", current_line);
1940 continue;
1942 if (extract_int(p, &n) == 0) {
1943 ConsoleMessage("This is not a number: %s\n", p);
1944 ConsoleMessage("Bad line: %s\n", current_line);
1945 continue;
1947 SET_MANAGER(manager, colorsets[FOCUS_CONTEXT], n);
1948 AllocColorset(n);
1950 else if (!strcasecmp(option1, "selectcolorset")) {
1951 p = read_next_cmd(READ_ARG);
1952 if (!p) {
1953 ConsoleMessage("Bad line: %s\n", current_line);
1954 continue;
1956 if (extract_int(p, &n) == 0) {
1957 ConsoleMessage("This is not a number: %s\n", p);
1958 ConsoleMessage("Bad line: %s\n", current_line);
1959 continue;
1961 SET_MANAGER(manager, colorsets[SELECT_CONTEXT], n);
1962 AllocColorset(n);
1964 else if (!strcasecmp(option1, "plaincolorset")) {
1965 p = read_next_cmd(READ_ARG);
1966 if (!p) {
1967 ConsoleMessage("Bad line: %s\n", current_line);
1968 continue;
1970 if (extract_int(p, &n) == 0) {
1971 ConsoleMessage("This is not a number: %s\n", p);
1972 ConsoleMessage("Bad line: %s\n", current_line);
1973 continue;
1975 SET_MANAGER(manager, colorsets[PLAIN_CONTEXT], n);
1976 AllocColorset(n);
1978 else if (!strcasecmp(option1, "iconcolorset")) {
1979 p = read_next_cmd(READ_ARG);
1980 if (!p) {
1981 ConsoleMessage("Bad line: %s\n", current_line);
1982 continue;
1984 if (extract_int(p, &n) == 0) {
1985 ConsoleMessage("This is not a number: %s\n", p);
1986 ConsoleMessage("Bad line: %s\n", current_line);
1987 continue;
1989 SET_MANAGER(manager, colorsets[ICON_CONTEXT], n);
1990 AllocColorset(n);
1992 else if (!strcasecmp(option1, "usewinlist")) {
1993 p = read_next_cmd(READ_ARG);
1994 if (!p) {
1995 ConsoleMessage("Bad line: %s\n", current_line);
1996 ConsoleMessage("Need argument to usewinlist\n");
1997 continue;
1999 if (!strcasecmp(p, "true")) {
2000 i = 1;
2002 else if (!strcasecmp(p, "false")) {
2003 i = 0;
2005 else {
2006 ConsoleMessage("Bad line: %s\n", current_line);
2007 ConsoleMessage("What is this: %s?\n", p);
2008 continue;
2010 ConsoleDebug(CONFIG, "Setting usewinlist to: %d\n", i);
2011 SET_MANAGER(manager, usewinlist, i);
2013 else if (!strcasecmp(option1, "reliefthickness")) {
2014 p = read_next_cmd(READ_ARG);
2015 if (!p) {
2016 ConsoleMessage("Bad line: %s\n", current_line);
2017 continue;
2019 if (extract_int(p, &n) == 0) {
2020 ConsoleMessage("This is not a number: %s\n", p);
2021 ConsoleMessage("Bad line: %s\n", current_line);
2022 continue;
2024 SET_MANAGER(manager, relief_thickness, n);
2026 else if (!strcasecmp(option1, "tips")) {
2027 p = read_next_cmd(READ_ARG);
2028 if (!p) {
2029 ConsoleMessage("Bad line: %s\n", current_line);
2030 continue;
2032 if (!strcasecmp(p, "always")) {
2033 i = TIPS_ALWAYS;
2036 else if (!strcasecmp(p, "false")) {
2037 i = TIPS_NEVER;
2039 else if (!strcasecmp(p, "needed")) {
2040 i = TIPS_NEEDED;
2042 else {
2043 ConsoleMessage("Bad line: %s\n", current_line);
2044 ConsoleMessage("What is this: %s?\n", p);
2045 continue;
2047 SET_MANAGER(manager, tips, i);
2049 else if (!strcasecmp(option1, "tipsfont")) {
2050 char *f;
2051 p = read_next_cmd(READ_REST_OF_LINE);
2052 trim(p);
2053 if (!p) {
2054 ConsoleMessage("Bad line: %s\n", current_line);
2055 continue;
2057 CopyStringWithQuotes(&f, p);
2058 ConsoleDebug(CONFIG, "tipsfont: %s\n", f);
2060 SET_MANAGER(manager, tips_fontname,
2061 copy_string(&globals.managers[id].tips_fontname, f));
2062 free(f);
2064 else if (!strcasecmp(option1, "tipscolorset")) {
2065 p = read_next_cmd(READ_ARG);
2066 if (!p) {
2067 ConsoleMessage("Bad line: %s\n", current_line);
2068 continue;
2070 if (extract_int(p, &n) == 0) {
2071 ConsoleMessage("This is not a number: %s\n", p);
2072 ConsoleMessage("Bad line: %s\n", current_line);
2073 continue;
2075 SET_MANAGER(manager, tips_conf->colorset, n);
2076 if (n >= 0)
2078 AllocColorset(n);
2081 else if (!strcasecmp(option1, "tipsdelays")) {
2082 p = read_next_cmd(READ_ARG);
2083 if (!p) {
2084 ConsoleMessage("Bad line: %s\n", current_line);
2085 continue;
2087 if (extract_int(p, &n) == 0) {
2088 ConsoleMessage("This is not a number: %s\n", p);
2089 ConsoleMessage("Bad line: %s\n", current_line);
2090 continue;
2092 if (n < 0) {
2093 ConsoleMessage("No negative delay: %s\n", p);
2094 ConsoleMessage("Bad line: %s\n", current_line);
2095 continue;
2097 SET_MANAGER(manager, tips_conf->delay, n);
2098 p = read_next_cmd(READ_ARG);
2099 if (!p)
2101 SET_MANAGER(manager, tips_conf->mapped_delay, n);
2102 continue;
2104 if (extract_int(p, &n) == 0) {
2105 ConsoleMessage("This is not a number: %s\n", p);
2106 ConsoleMessage("Bad line: %s\n", current_line);
2107 continue;
2109 if (n < 0) {
2110 ConsoleMessage("No negative delay: %s\n", p);
2111 ConsoleMessage("Bad line: %s\n", current_line);
2112 continue;
2114 SET_MANAGER(manager, tips_conf->mapped_delay, n);
2116 else if (!strcasecmp(option1, "tipsformat")) {
2117 char *token;
2118 /*NameType flags;*/
2120 p = read_next_cmd(READ_REST_OF_LINE);
2121 if (!p) {
2122 ConsoleMessage("Bad line: %s\n", current_line);
2123 continue;
2125 DoGetNextToken(p, &token, NULL, ",", NULL);
2126 if (!token)
2128 token = (char *)safemalloc(1);
2129 *token = 0;
2132 SET_MANAGER(manager, tips_formatstring,
2133 copy_string (
2134 &globals.managers[id].tips_formatstring, token));
2135 #if 0
2136 flags = parse_format_dependencies(token);
2137 SET_MANAGER(manager, format_depend, flags);
2138 Free(token);
2139 #endif
2141 else if (!strcasecmp(option1, "tipsborderwidth")) {
2142 p = read_next_cmd(READ_ARG);
2143 if (!p) {
2144 ConsoleMessage("Bad line: %s\n", current_line);
2145 continue;
2147 if (extract_int(p, &n) == 0) {
2148 ConsoleMessage("This is not a number: %s\n", p);
2149 ConsoleMessage("Bad line: %s\n", current_line);
2150 continue;
2152 if (n < 0)
2154 n = 0;
2156 SET_MANAGER(manager, tips_conf->border_width, n);
2158 else if (!strcasecmp(option1, "tipsoffsets")) {
2159 p = read_next_cmd(READ_ARG);
2160 if (!p) {
2161 ConsoleMessage("Bad line: %s\n", current_line);
2162 continue;
2164 if (extract_int(p, &n) == 0) {
2165 ConsoleMessage("This is not a number: %s\n", p);
2166 ConsoleMessage("Bad line: %s\n", current_line);
2167 continue;
2169 if (n < 1) {
2170 ConsoleMessage("A tips offset must be positive: %s\n", p);
2171 ConsoleMessage("Bad line: %s\n", current_line);
2172 continue;
2174 SET_MANAGER(manager, tips_conf->placement_offset, n);
2175 p = read_next_cmd(READ_ARG);
2176 if (!p)
2178 ConsoleMessage("Bad line: %s\n", current_line);
2179 continue;
2181 if (extract_int(p, &n) == 0) {
2182 ConsoleMessage("This is not a number: %s\n", p);
2183 ConsoleMessage("Bad line: %s\n", current_line);
2184 continue;
2186 if (n < 1) {
2187 ConsoleMessage("A tips offset must be positive: %s\n", p);
2188 ConsoleMessage("Bad line: %s\n", current_line);
2189 continue;
2191 SET_MANAGER(manager, tips_conf->justification_offset, n);
2193 else if (!strcasecmp(option1, "tipsplacement")) {
2194 p = read_next_cmd(READ_ARG);
2195 if (!p) {
2196 ConsoleMessage("Bad line: %s\n", current_line);
2197 continue;
2199 if (!strcasecmp(p, "up")) {
2200 i = FTIPS_PLACEMENT_UP;
2202 else if (!strcasecmp(p, "down")) {
2203 i = FTIPS_PLACEMENT_DOWN;
2205 else if (!strcasecmp(p, "left")) {
2206 i = FTIPS_PLACEMENT_LEFT;
2208 else if (!strcasecmp(p, "right")) {
2209 i = FTIPS_PLACEMENT_RIGHT;
2211 else if (!strcasecmp(p, "updown")) {
2212 i = FTIPS_PLACEMENT_AUTO_UPDOWN;
2214 else if (!strcasecmp(p, "leftright")) {
2215 i = FTIPS_PLACEMENT_AUTO_LEFTRIGHT;
2217 else {
2218 ConsoleMessage("Bad line: %s\n", current_line);
2219 ConsoleMessage("What is this: %s?\n", p);
2220 continue;
2222 SET_MANAGER(manager, tips_conf->placement, i);
2224 else if (!strcasecmp(option1, "tipsjustification")) {
2225 p = read_next_cmd(READ_ARG);
2226 if (!p) {
2227 ConsoleMessage("Bad line: %s\n", current_line);
2228 continue;
2230 if (!strcasecmp(p, "center")) {
2231 i = FTIPS_JUSTIFICATION_CENTER;
2233 else if (!strcasecmp(p, "leftup")) {
2234 i = FTIPS_JUSTIFICATION_LEFT_UP;
2236 else if (!strcasecmp(p, "rightdown")) {
2237 i = FTIPS_JUSTIFICATION_RIGHT_DOWN;
2239 else {
2240 ConsoleMessage("Bad line: %s\n", current_line);
2241 ConsoleMessage("What is this: %s?\n", p);
2242 continue;
2244 SET_MANAGER(manager, tips_conf->justification, i);
2246 else {
2247 ConsoleMessage("Bad line: %s\n", current_line);
2248 ConsoleMessage("Unknown option: %s\n", p);
2253 if (globals.managers == NULL) {
2254 ConsoleDebug(CONFIG, "I'm assuming you only want one manager\n");
2255 allocate_managers(1);
2257 print_managers();
2260 void process_dynamic_config_line(char *line)
2262 int manager = 0;
2263 char *token;
2264 extern void remanage_winlist(void);
2266 /* don't support dynamic config for transient */
2267 if (globals.transient)
2269 return;
2272 line += ModuleLen;
2273 line = GetNextToken(line, &token);
2274 if (token && isdigit(*token))
2276 if (extract_int(token, &manager) == 0
2277 || manager <= 0 || manager > globals.num_managers)
2279 manager = 0;
2281 free(token);
2282 line = GetNextToken(line, &token);
2285 if (!token)
2287 return;
2289 manager--;
2291 /* currently supports only "resolution" and "tips" */
2292 if (strcasecmp(token, "resolution") == 0)
2294 int value;
2296 free(token);
2297 line = GetNextToken(line, &token);
2298 if (!token)
2300 return;
2302 if (!strcasecmp(token, "global"))
2303 value = SHOW_GLOBAL;
2304 else if (!strcasecmp(token, "desk"))
2305 value = SHOW_DESKTOP;
2306 else if (!strcasecmp(token, "page"))
2307 value = SHOW_PAGE;
2308 else if (!strcasecmp(token, "screen"))
2309 value = SHOW_SCREEN;
2310 else if (!strcasecmp(token, "!desk"))
2311 value = NO_SHOW_DESKTOP;
2312 else if (!strcasecmp(token, "!page"))
2313 value = NO_SHOW_PAGE;
2314 else if (!strcasecmp(token, "!screen"))
2315 value = NO_SHOW_SCREEN;
2316 else
2318 fprintf(
2319 stderr, "%s: unknown resolution %s.\n",
2320 MyName, token);
2321 free(token);
2322 return;
2325 SET_MANAGER(manager, res, value);
2326 remanage_winlist();
2328 else if (strcasecmp(token, "tips") == 0)
2330 int value;
2332 free(token);
2333 line = GetNextToken(line, &token);
2334 if (!token)
2336 return;
2338 if (!strcasecmp(token, "always"))
2340 value = TIPS_ALWAYS;
2342 else if (!strcasecmp(token, "false"))
2344 value = TIPS_NEVER;
2346 else if (!strcasecmp(token, "needed"))
2348 value = TIPS_NEEDED;
2350 else
2352 ConsoleMessage("Bad line: %s\n", line);
2353 ConsoleMessage("What is this: %s?\n", token);
2354 free(token);
2355 return;
2357 SET_MANAGER(manager, tips, value);
2358 if (manager == -1)
2360 tips_cancel(NULL);
2362 else
2364 tips_cancel(&globals.managers[manager]);
2368 free(token);