/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "config.h" #include #include "FvwmIconMan.h" #include "readconfig.h" #include "xmanager.h" #include "libs/defaults.h" #include "libs/fvwmlib.h" #include "libs/FScreen.h" #include "libs/FShape.h" #include "libs/Module.h" #include "libs/Parse.h" #include "libs/Strings.h" /* * * Builtin functions: * */ extern int builtin_quit(int numargs, BuiltinArg *args); extern int builtin_printdebug(int numargs, BuiltinArg *args); extern int builtin_gotobutton(int numargs, BuiltinArg *args); extern int builtin_gotomanager(int numargs, BuiltinArg *args); extern int builtin_refresh(int numargs, BuiltinArg *args); extern int builtin_select(int numargs, BuiltinArg *args); extern int builtin_sendcommand(int numargs, BuiltinArg *args); extern int builtin_bif(int numargs, BuiltinArg *args); extern int builtin_bifn(int numargs, BuiltinArg *args); extern int builtin_print(int numargs, BuiltinArg *args); extern int builtin_jmp(int numargs, BuiltinArg *args); extern int builtin_ret(int numargs, BuiltinArg *args); extern int builtin_searchforward(int numargs, BuiltinArg *args); extern int builtin_searchback(int numargs, BuiltinArg *args); extern int builtin_warp(int numargs, BuiltinArg *args); /* compiler pseudo-functions */ static int builtin_label(int numargs, BuiltinArg *args); typedef struct { char *name; int (*func)(int numargs, BuiltinArg *args); int numargs; BuiltinArgType args[MAX_ARGS]; } FunctionType; /* * these are now sorted so we can use bsearch on them. */ FunctionType builtin_functions[] = { { "bif", builtin_bif, 2, { ButtonArg, JmpArg } }, { "bifn", builtin_bifn, 2, { ButtonArg, JmpArg } }, { "gotobutton", builtin_gotobutton, 1, { ButtonArg } }, { "gotomanager", builtin_gotomanager, 1, { ManagerArg } }, { "jmp", builtin_jmp, 1, { JmpArg } }, { "label", builtin_label, 1, { StringArg } }, { "print", builtin_print, 1, { StringArg } }, { "printdebug", builtin_printdebug, 0, {0} }, { "quit", builtin_quit, 0, {0} }, { "refresh", builtin_refresh, 0, {0} }, { "ret", builtin_ret, 0, {0} }, { "searchback", builtin_searchback, 1, { StringArg } }, { "searchforward", builtin_searchforward, 1, { StringArg } }, { "select", builtin_select, 0, {0} }, { "sendcommand", builtin_sendcommand, 1, { StringArg } }, { "warp", builtin_warp, 0, {0} } }; static int num_builtins = sizeof(builtin_functions) / sizeof(FunctionType); /* This is only used for printing out the .fvwmrc line if an error occured */ #define PRINT_LINE_LENGTH 80 static char current_line[PRINT_LINE_LENGTH]; static void save_current_line(char *s) { char *p = current_line; while (*s && p < current_line + PRINT_LINE_LENGTH - 1) { if (*s == '\n') { *p = '\0'; return; } else { *p++ = *s++; } } *p = '\0'; } void print_args(int numargs, BuiltinArg *args) { #ifdef FVWM_DEBUG_MSGS int i; for (i = 0; i < numargs; i++) { switch (args[i].type) { case NoArg: ConsoleDebug(CONFIG, "NoArg "); break; case IntArg: ConsoleDebug( CONFIG, "Int: %d ", args[i].value.int_value); break; case StringArg: ConsoleDebug( CONFIG, "String: %s ", args[i].value.string_value); break; case ButtonArg: ConsoleDebug( CONFIG, "Button: %d %d ", args[i].value.button_value.offset, args[i].value.button_value.base); break; case WindowArg: ConsoleDebug( CONFIG, "Window: %d %d ", args[i].value.button_value.offset, args[i].value.button_value.base); break; case ManagerArg: ConsoleDebug( CONFIG, "Manager: %d %d ", args[i].value.button_value.offset, args[i].value.button_value.base); break; case JmpArg: ConsoleDebug( CONFIG, "Unprocessed Label Jump: %s ", args[i].value.string_value); break; default: ConsoleDebug(CONFIG, "bad "); break; } } ConsoleDebug(CONFIG, "\n"); #endif } #ifdef FVWM_DEBUG_MSGS static void print_binding(Binding *binding) { int i; Function *func; if (binding->type == BIND_BUTTONPRESS) { ConsoleDebug(CONFIG, "\tMouse: %d\n", binding->Button_Key); } else { ConsoleDebug( CONFIG, "\tKey or action: %d %s\n", binding->Button_Key, binding->key_name); } ConsoleDebug(CONFIG, "\tModifiers: %d\n", binding->Modifier); ConsoleDebug(CONFIG, "\tAction: %s\n", (char *) binding->Action); ConsoleDebug(CONFIG, "\tFunction struct: 0x%x\n", (unsigned int) binding->Action2); func = (Function *)(binding->Action2); while (func) { for (i = 0; i < num_builtins; i++) { if (func->func == builtin_functions[i].func) { ConsoleDebug( CONFIG, "\tFunction: %s 0x%x ", builtin_functions[i].name, (unsigned int) func->func); break; } } if (i > num_builtins) { ConsoleDebug( CONFIG, "\tFunction: not found 0x%x ", (unsigned int) func->func); } print_args(func->numargs, func->args); func = func->next; } } void print_bindings(Binding *list) { ConsoleDebug(CONFIG, "binding list:\n"); while (list != NULL) { print_binding(list); ConsoleDebug(CONFIG, "\n"); list = list->NextBinding; } } #else void print_bindings(Binding *list) { } #endif static int iswhite(char c) { if (c == ' ' || c == '\t' || c == '\0') { return 1; } return 0; } static void trim(char *p) { int length = strlen(p) -1; int index; for (index = length; index > 0; index --) { if (p[index] == ' ' || p[index] == '\t') { p[index] = '\0'; } else { return; } } } static void skip_space(char **p) { while (**p == ' ' || **p == '\t') { (*p)++; } } static void add_to_binding(Binding **list, Binding *binding) { ConsoleDebug(CONFIG, "In add_to_binding:\n"); binding->NextBinding = *list; *list = binding; return; } static int extract_int(char *p, int *n) { char *s; int sign = 1; while (isspace((unsigned char)*p) && *p) { p++; } if (*p == '-') { sign = -1; p++; } else if (*p == '+') { sign = 1; p++; } if (*p == '\0') { return 0; } for (s = p; *s; s++) { if (*s < '0' || *s > '9') { return 0; } } *n = atoi(p) * sign; return 1; } static char *parse_button(char *string, BuiltinArg *arg, int *flag, char *pstop_char) { char *rest, *token; ButtonValue *bv; int n; ConsoleDebug(CONFIG, "parse_term: %s\n", string); *flag = 1; arg->type = ButtonArg; bv = &arg->value.button_value; bv->offset = 0; bv->base = AbsoluteButton; rest = DoGetNextToken(string, &token, NULL, ",", pstop_char); if (token == NULL) { bv->base = NoButton; *flag = 0; Free(token); return NULL; } if (!strcasecmp(token, "focus")) { bv->base = FocusButton; } else if (!strcasecmp(token, "select")) { bv->base = SelectButton; } else if (!strcasecmp(token, "up")) { bv->base = UpButton; } else if (!strcasecmp(token, "down")) { bv->base = DownButton; } else if (!strcasecmp(token, "left")) { bv->base = LeftButton; } else if (!strcasecmp(token, "right")) { bv->base = RightButton; } else if (!strcasecmp(token, "next")) { bv->base = NextButton; } else if (!strcasecmp(token, "prev")) { bv->base = PrevButton; } else if (extract_int(token, &n)) { bv->base = AbsoluteButton; bv->offset = n; } else { ConsoleMessage("Bad button: %s\n", token); bv->base = NoButton; Free(token); *flag = 0; return NULL; } Free(token); return rest; } static void free_function_list(Function *func) { int i; Function *fp = func; while (fp) { for (i = 0; i < fp->numargs; i++) { if (fp->args[i].type == StringArg) { Free(fp->args[i].value.string_value); } } func = fp; fp = fp->next; Free(func); } } static int funccasecmp( const void *key /* actually char* */, const void *member /* actually FunctionType* */) { return strcasecmp((char *)key, ((FunctionType *)member)->name); } /* * The label function. Should never be called, but we need a pointer to it, * and it's useful for debugging purposes to have it defined. */ static int builtin_label(int numargs, BuiltinArg *args) { int j; /* we should _never_ be called */ ConsoleMessage( "label" ); for (j=0; jfunc = builtin_functions_i->func; ftype->numargs = builtin_functions_i->numargs; ftype->next = NULL; for (j = 0; j < builtin_functions_i->numargs && *pstop_char != ','; j++) { ftype->args[j].type = builtin_functions_i->args[j]; switch (builtin_functions_i->args[j]) { case IntArg: ptr = DoGetNextToken(ptr, &tok, NULL, ",", pstop_char); if (!tok) { ConsoleMessage("%s: too few arguments\n", builtin_functions_i->name); Free(ftype); *line = NULL; return NULL; } if (extract_int(tok, &ftype->args[j].value.int_value) == 0) { ConsoleMessage("%s: expect integer argument: %s\n", builtin_functions_i->name, tok); Free(tok); Free(ftype); *line = NULL; return NULL; } Free(tok); break; case StringArg: ptr = DoGetNextToken(ptr, &ftype->args[j].value.string_value,NULL, ",", pstop_char); if (!ftype->args[j].value.string_value) { ConsoleMessage("%s: too few arguments\n", builtin_functions_i->name); *line = NULL; Free(ftype->args[j].value.string_value); Free(ftype); return NULL; } ftype->args[j].type = builtin_functions_i->args[j]; break; case ButtonArg: case WindowArg: case ManagerArg: ptr = parse_button(ptr, &ftype->args[j], &flag, pstop_char); if (!flag) { ConsoleMessage("%s: too few arguments\n", builtin_functions_i->name); Free(ftype); *line = NULL; return NULL; } ftype->args[j].type = builtin_functions_i->args[j]; break; /* JmpArg can be a string or an int. However, if 'JmpArg' * is recorded as the argument type in the argument array * for a command, it means it is a string; the code for * 'IntArg' is used instead for numbers. Note also that * if the C function recieves a 'JmpArg' argument it means something * went wrong, since they should all be translated to integer * jump offsets at compile time. */ case JmpArg: ptr = DoGetNextToken(ptr, &tok, NULL, ",", pstop_char); if (!tok) { ConsoleMessage("%s: too few arguments\n", builtin_functions_i->name); Free(tok); Free(ftype); *line=NULL; return NULL; } if (extract_int(tok, &ftype->args[j].value.int_value) == 0) { ftype->args[j].value.string_value=tok; ftype->args[j].type = JmpArg; ++JmpArgs; } else { ftype->args[j].type = IntArg; Free(tok); } break; default: ConsoleMessage("internal error in parse_function\n"); Free(ftype); *line = NULL; return NULL; } } if (j != builtin_functions_i->numargs) { ConsoleMessage("%s: too few arguments\n", builtin_functions_i->name); Free(ftype); *line = NULL; return NULL; } *line = ptr; return ftype; } ConsoleMessage("Unknown function: %s\n", name); Free(name); *line = NULL; return NULL; } /* This is O(N^2) where N = number of instructions. Seems we could do better. We'll see how this addition settles before monkeying with it */ static Function *parse_function_list(char *line) { Function *ret = NULL, *tail = NULL, *f, *i; char *token; int jump_count, j; char stop_char; char c; JmpArgs=0; while (line && (f = parse_function(&line, &stop_char))) { ConsoleDebug(CONFIG, "parse_function: 0x%lx\n", (unsigned long)f->func); /* extra code to check for and remove a 'label' pseudo-function */ if (f->func==builtin_label) { /* scan backwards to fix up references */ jump_count=0; for (i=tail; i!=NULL; i=i->prev) { /* scan the command arguments for a 'JmpArg' type */ for (j=0; j<(i->numargs); ++j) { if (i->args[j].type==JmpArg) { /* we have a winner! */ if (!strcasecmp(f->args[0].value.string_value, i->args[j].value.string_value)) { /* the label matches it, so replace with the jump_count */ i->args[j].type = IntArg; i->args[j].value.int_value = jump_count; --JmpArgs; } } } ++jump_count; } Free(f); /* label pseudo-functions never get added to the chain */ } else { if (tail) tail->next = f; else ret = f; f->prev=tail; tail = f; } DoGetNextToken(line, &token, NULL, ",", &c); if (token && stop_char != ',') { ConsoleMessage("Bad function list, comma expected\n"); Free(token); return NULL; } stop_char = c; Free(token); } if (JmpArgs!=0) { /* someone made a typo and we need to scan to find out what it * was. */ for (f=tail; f; f=f->prev) { for (j=0; j<(f->numargs); ++j) { if (f->args[j].type==JmpArg) { ConsoleMessage("Attempt to jump to non-existant label %s; " "aborting function list.\n", f->args[j].value.string_value); --JmpArgs; } } } if (JmpArgs!=0) ConsoleMessage( "Internal Error: JmpArgs %d not accounted for!\n", JmpArgs ); tail=NULL; f=NULL; free_function_list(ret); ret=NULL; return NULL; } if (ret == NULL) ConsoleMessage("No function defined\n"); return ret; } Binding *ParseMouseEntry(char *tline) { char modifiers[20],*action,*token; Binding *new; int button; int n1=0,n2=0; int mods; /* tline points after the key word "key" */ action = DoGetNextToken(tline,&token, NULL, ",", NULL); if(token != NULL) { n1 = sscanf(token,"%d",&button); if (n1 == 1 && (button < 0 || button > NUMBER_OF_EXTENDED_MOUSE_BUTTONS)) { /* syntax error */ n1 = 0; } Free(token); } action = DoGetNextToken(action,&token, NULL, ",", NULL); if(token != NULL) { n2 = sscanf(token,"%19s",modifiers); Free(token); } if((n1 != 1)||(n2 != 1)) ConsoleMessage("Mouse binding: Syntax error"); modifiers_string_to_modmask(modifiers, &mods); if((mods & AnyModifier)&&(mods&(~AnyModifier))) { ConsoleMessage("Binding specified AnyModifier and other modifers too. " "Excess modifiers will be ignored."); } new = (Binding *)safemalloc(sizeof(Binding)); memset(new, 0, sizeof(Binding)); new->type = BIND_BUTTONPRESS; new->Button_Key = button; new->Modifier = mods; new->Action = stripcpy(action); new->Action2 = parse_function_list(action); if (!new->Action2) { ConsoleMessage("Bad action: %s\n", action); Free(new->Action); Free(new); return NULL; } ConsoleDebug(CONFIG, "Mouse: %d %d %s\n", new->Button_Key, new->Modifier, (char*)new->Action); return new; } static Binding *ParseKeyEntry(char *tline) { char *action,modifiers[20],key[20],*ptr, *token, *actionstring, *keystring; Binding *new = NULL, *temp, *last = NULL; Function *func = NULL; int i,min,max; int n1=0,n2=0; KeySym keysym; int mods; /* tline points after the key word "key" */ ptr = tline; ptr = DoGetNextToken(ptr,&token, NULL, ",", NULL); if(token != NULL) { n1 = sscanf(token,"%19s",key); Free(token); } action = DoGetNextToken(ptr,&token, NULL, ",", NULL); if(token != NULL) { n2 = sscanf(token,"%19s",modifiers); Free(token); } if((n1 != 1)||(n2 != 1)) ConsoleMessage("Syntax error in line %s",tline); modifiers_string_to_modmask(modifiers, &mods); if((mods & AnyModifier)&&(mods&(~AnyModifier))) { ConsoleMessage("Binding specified AnyModifier and other modifers too. Excess modifiers will be ignored."); } /* * Don't let a 0 keycode go through, since that means AnyKey to the * XGrabKey call in GrabKeys(). */ if ((keysym = XStringToKeysym(key)) == NoSymbol || XKeysymToKeycode(theDisplay, keysym) == 0) { ConsoleMessage("Can't find keysym: %s\n", key); return NULL; } XDisplayKeycodes(theDisplay, &min, &max); for (i=min; i<=max; i++) { if (XKeycodeToKeysym(theDisplay, i, 0) == keysym) { if (!func) { func = parse_function_list(action); if (!func) { ConsoleMessage("Bad action: %s\n", action); return NULL; } actionstring = stripcpy(action); keystring = stripcpy(key); } else { actionstring = keystring = NULL; } temp = new; new = (Binding *)safemalloc(sizeof(Binding)); memset(new, 0, sizeof(Binding)); new->type = BIND_KEYPRESS; new->Button_Key = i; new->key_name = keystring; new->Modifier = mods; new->Action = actionstring; new->Action2 = func; new->NextBinding = temp; if (!last) { last = new; } ConsoleDebug(CONFIG, "Key: %d %s %d %s\n", i, new->key_name, mods, (char*)new->Action); } } return new; } static Binding *ParseSimpleEntry(char *tline) { Binding *new; Function *func; func = parse_function_list(tline); if (func == NULL) { return NULL; } new = (Binding *)safemalloc(sizeof(Binding)); memset(new, 0, sizeof(Binding)); new->type = BIND_KEYPRESS; new->key_name = "select"; new->Action = stripcpy(tline); new->Action2 = func; return new; } void run_binding(WinManager *man, Action action) { Binding *binding = man->bindings[action]; ConsoleDebug(CONFIG, "run_binding:\n"); print_bindings(binding); if (binding && binding->Action2 && ((Function *)(binding->Action2))->func) { run_function_list(binding->Action2); } } void execute_function(char *string) { Function *func = parse_function_list(string); if (func == NULL) { return; } else { run_function_list(func); free_function_list(func); } } static int GetConfigLineWrapper(int *fd, char **tline) { char *temp; GetConfigLine(fd, tline); if (*tline) { if (strncasecmp(*tline, "Colorset", 8) == 0) { LoadColorset(&(*tline)[8]); } else if (strncasecmp( *tline, XINERAMA_CONFIG_STRING, sizeof(XINERAMA_CONFIG_STRING) - 1) == 0) { FScreenConfigureModule( (*tline) + sizeof(XINERAMA_CONFIG_STRING) - 1); } else if (strncasecmp(*tline, "IgnoreModifiers", 15) == 0) { sscanf((*tline) + 16, "%d", &mods_unused); } temp = strchr(*tline, '\n'); if (temp) { *temp = '\0'; } /* grok the global config lines */ return 1; } return 0; } static char *read_next_cmd(ReadOption flag) { static ReadOption status; static char *buffer; static char *retstring, *cur_pos; char *end_pos; retstring = NULL; if (flag != READ_LINE && !(flag & status)) { return NULL; } switch (flag) { case READ_LINE: while (GetConfigLineWrapper(fvwm_fd, &buffer)) { cur_pos = buffer; skip_space(&cur_pos); if (!strncasecmp(Module, cur_pos, ModuleLen)) { retstring = cur_pos; cur_pos += ModuleLen; if (*cur_pos == '*') { cur_pos++; } skip_space(&cur_pos); if (isalnum(*cur_pos)) { status = READ_OPTION; } else { status = READ_LINE; } break; } } break; case READ_OPTION: retstring = cur_pos; while (*cur_pos != '*' && !iswhite(*cur_pos)) { cur_pos++; } end_pos = cur_pos; if (*cur_pos == '*') { cur_pos++; } skip_space(&cur_pos); if (!*cur_pos) { status = READ_LINE; } else if (isdigit(*retstring) || !strncmp( retstring, "transient", 9)) { status = READ_OPTION; } else if (*cur_pos) { status = READ_ARG; } *end_pos = '\0'; break; case READ_ARG: retstring = cur_pos; while (!iswhite(*cur_pos)) { cur_pos++; } end_pos = cur_pos; skip_space(&cur_pos); if (*cur_pos) { status = READ_ARG; } else { status = READ_LINE; } *end_pos = '\0'; break; case READ_REST_OF_LINE: status = READ_LINE; retstring = cur_pos; break; } if (retstring && retstring[0] == '\0') { retstring = NULL; } return retstring; } static char *conditional_copy_string(char **s1, char *s2) { if (*s1) { return *s1; } else { return copy_string(s1, s2); } } static NameType parse_format_dependencies(char *format) { NameType flags = NO_NAME; ConsoleDebug(CONFIG, "Parsing format: %s\n", format); while (*format) { if (*format != '%') { format++; } else { format++; if (*format == 'i') { flags |= ICON_NAME; } else if (*format == 't') { flags |= TITLE_NAME; } else if (*format == 'c') { flags |= CLASS_NAME; } else if (*format == 'r') { flags |= RESOURCE_NAME; } else if (*format != '%') { ConsoleMessage( "Bad format string: %s\n", format); } } } #ifdef FVWM_DEBUG_MSGS ConsoleDebug(CONFIG, "Format depends on: "); if (flags & ICON_NAME) { ConsoleDebug(CONFIG, "Icon "); } if (flags & TITLE_NAME) { ConsoleDebug(CONFIG, "Title "); } if (flags & CLASS_NAME) { ConsoleDebug(CONFIG, "Class "); } if (flags & RESOURCE_NAME) { ConsoleDebug(CONFIG, "Resource "); } ConsoleDebug(CONFIG, "\n"); #endif return flags; } #define SET_MANAGER(manager,field,value) \ do \ { \ int id = manager; \ if (id == -1) \ { \ for (id = 0; id < globals.num_managers; id++) \ { \ globals.managers[id]. field = value; \ } \ } \ else if (id < globals.num_managers) \ { \ globals.managers[id]. field = value; \ } \ else \ { \ ConsoleMessage( \ "Internal error in SET_MANAGER: %d\n", id); \ } \ } while (0) static void handle_button_config(int manager, int context, char *option) { char *p; ButtonState state; p = read_next_cmd(READ_ARG); if (!p) { ConsoleMessage("Bad line: %s\n", current_line); ConsoleMessage("Need argument to %s\n", option); return; } else if (!strcasecmp(p, "flat")) { state = BUTTON_FLAT; } else if (!strcasecmp(p, "up")) { state = BUTTON_UP; } else if (!strcasecmp(p, "down")) { state = BUTTON_DOWN; } else if (!strcasecmp(p, "raisededge")) { state = BUTTON_EDGEUP; } else if (!strcasecmp(p, "sunkedge")) { state = BUTTON_EDGEDOWN; } else { ConsoleMessage("Bad line: %s\n", current_line); ConsoleMessage("This isn't a valid button state: %s\n", p); return; } ConsoleDebug( CONFIG, "Setting buttonState[%s] to %s\n", contextDefaults[context].name, p); SET_MANAGER(manager, buttonState[context], state); /* check for optional fore color */ p = read_next_cmd(READ_ARG); if (!p) { return; } SET_MANAGER( manager, foreColorName[context], copy_string(&globals.managers[id]. foreColorName[context], p)); /* check for optional back color */ p = read_next_cmd(READ_ARG); if (!p) { return; } ConsoleDebug( CONFIG, "Setting backColorName[%s] to %s\n", contextDefaults[context].name, p); SET_MANAGER( manager, backColorName[context], copy_string(&globals.managers[id].backColorName[context], p)); } static void add_weighted_sort(WinManager *man, WeightedSort *weighted_sort) { WeightedSort *p; int i; if (man->weighted_sorts_len == man->weighted_sorts_size) { i = man->weighted_sorts_size; man->weighted_sorts_size += 16; man->weighted_sorts = (WeightedSort *)saferealloc( (char *)man->weighted_sorts, man->weighted_sorts_size * sizeof(WeightedSort)); } p = &man->weighted_sorts[man->weighted_sorts_len]; p->resname = NULL; p->classname = NULL; p->titlename = NULL; p->iconname = NULL; if (weighted_sort->resname) { copy_string(&p->resname, weighted_sort->resname); } if (weighted_sort->classname) { copy_string(&p->classname, weighted_sort->classname); } if (weighted_sort->titlename) { copy_string(&p->titlename, weighted_sort->titlename); } if (weighted_sort->iconname) { copy_string(&p->iconname, weighted_sort->iconname); } p->weight = weighted_sort->weight; ++man->weighted_sorts_len; } void read_in_resources(void) { char *p, *q; int i, n, manager; char *option1; Binding *binding = NULL; Resolution r; Reverse rv; InitGetConfigLine(fvwm_fd, Module); while ((p = read_next_cmd(READ_LINE))) { ConsoleDebug(CONFIG, "line: %s\n", p); save_current_line(p); option1 = read_next_cmd(READ_OPTION); if (option1 == NULL) continue; ConsoleDebug(CONFIG, "option1: %s\n", option1); if (!strcasecmp(option1, "nummanagers")) { /* If in transient mode, just use the default of 1 manager */ if (!globals.transient) { p = read_next_cmd(READ_ARG); if (!p) { ConsoleMessage("Bad line: %s\n", current_line); continue; } if (extract_int(p, &n) == 0) { ConsoleMessage("This is not a number: %s\n", p); ConsoleMessage("Bad line: %s\n", current_line); continue; } if (n > 0) { allocate_managers(n); ConsoleDebug(CONFIG, "num managers: %d\n", n); } else { ConsoleMessage("Bad line: %s\n", current_line); ConsoleMessage("You can't have zero managers. " "I'll give you one.\n"); allocate_managers(1); } } } else { /* these all can specify a specific manager */ if (globals.managers == NULL) { ConsoleDebug(CONFIG, "I'm assuming you only want one manager\n"); allocate_managers(1); } manager = 0; if (option1[0] >= '0' && option1[0] <= '9') { if (globals.transient) { ConsoleDebug(CONFIG, "In transient mode. Ignoring this line\n"); continue; } if (extract_int(option1, &manager) == 0 || manager <= 0 || manager > globals.num_managers) { ConsoleMessage("Bad line: %s\n", current_line); ConsoleMessage("This is not a valid manager: %s.\n", option1); manager = 0; } option1 = read_next_cmd(READ_OPTION); if (!option1) { ConsoleMessage("Bad line: %s\n", current_line); continue; } } else if (!strcasecmp(option1, "transient")) { if (globals.transient) { ConsoleDebug(CONFIG, "Transient manager config line\n"); manager = 1; option1 = read_next_cmd(READ_OPTION); if (!option1) { ConsoleMessage("Bad line: %s\n", current_line); continue; } } else { ConsoleDebug(CONFIG, "Not in transient mode. Ignoring this line\n"); continue; } } manager--; /* -1 means global */ ConsoleDebug(CONFIG, "Applying %s to manager %d\n", option1, manager); if (!strcasecmp(option1, "action")) { p = read_next_cmd(READ_ARG); if (!p) { ConsoleMessage("Bad line: %s\n", current_line); continue; } if (!strcasecmp(p, "mouse")) { i = MOUSE; } else if (!strcasecmp(p, "key")) { i = KEYPRESS; } else if (!strcasecmp(p, "select")) { i = SELECT; } else { ConsoleMessage("Bad line: %s\n", current_line); ConsoleMessage("This isn't a valid action name: %s\n", p); continue; } q = read_next_cmd(READ_REST_OF_LINE); if (!q) { ConsoleMessage("Bad line: %s\n", current_line); ConsoleMessage("Need an action\n"); continue; } switch (i) { case MOUSE: binding = ParseMouseEntry(q); break; case KEYPRESS: binding = ParseKeyEntry(q); break; case SELECT: binding = ParseSimpleEntry(q); break; } if (binding == NULL) { ConsoleMessage("Offending line: %s\n", current_line); ConsoleMessage("Bad action\n"); continue; } if (manager == -1) { int j; for (j = 0; j < globals.num_managers; j++) { add_to_binding(&globals.managers[j].bindings[i], binding); } } else if (manager < globals.num_managers) { add_to_binding(&globals.managers[manager].bindings[i], binding); } else { ConsoleMessage("Bad line: %s\n", current_line); ConsoleMessage("There's no manager %d\n", manager); } } else if (!strcasecmp(option1, "colorset")) { p = read_next_cmd(READ_ARG); if (!p) { ConsoleMessage("Bad line: %s\n", current_line); continue; } if (extract_int(p, &n) == 0) { ConsoleMessage("This is not a number: %s\n", p); ConsoleMessage("Bad line: %s\n", current_line); continue; } for ( i = 0; i < NUM_CONTEXTS; i++ ) { if (i != DEFAULT && i != TITLE_CONTEXT) SET_MANAGER(manager, colorsets[i], -2); else SET_MANAGER(manager, colorsets[i], n); } AllocColorset(n); } else if (!strcasecmp(option1, "background")) { p = read_next_cmd(READ_ARG); if (!p) { ConsoleMessage("Bad line: %s\n", current_line); continue; } ConsoleDebug(CONFIG, "default background: %s\n", p); for ( i = 0; i < NUM_CONTEXTS; i++ ) SET_MANAGER(manager, backColorName[i], conditional_copy_string(&globals.managers[id].backColorName[i], p)); } else if (!strcasecmp(option1, "buttongeometry")) { p = read_next_cmd(READ_ARG); if (!p) { ConsoleMessage("Bad line: %s\n", current_line); continue; } SET_MANAGER(manager, button_geometry_str, copy_string(&globals.managers[id].button_geometry_str, p)); } else if (!strcasecmp(option1, "maxbuttonwidth")) { p = read_next_cmd(READ_ARG); if (!p) { n = 0; } else if (extract_int(p, &n) == 0) { ConsoleMessage("This is not a number: %s\n", p); ConsoleMessage("Bad line: %s\n", current_line); continue; } SET_MANAGER(manager, max_button_width, n); SET_MANAGER(manager, max_button_width_columns, 0); } else if (!strcasecmp(option1, "maxbuttonwidthbycolumns")) { p = read_next_cmd(READ_ARG); if (!p) { n = 0; } else if (extract_int(p, &n) == 0) { ConsoleMessage("This is not a number: %s\n", p); ConsoleMessage("Bad line: %s\n", current_line); continue; } SET_MANAGER(manager, max_button_width, 0); SET_MANAGER(manager, max_button_width_columns, n); } else if (!strcasecmp(option1, "dontshow")) { char *token = NULL; p = read_next_cmd(READ_REST_OF_LINE); if (!p) { ConsoleMessage("Bad line: %s\n", current_line); continue; } p = DoGetNextToken(p, &token, NULL, ",", NULL); if (!token) { ConsoleMessage("Bad line: %s\n", current_line); continue; } do { ConsoleDebug(CONFIG, "dont show: %s\n", token); if (manager == -1) { int i; for (i = 0; i < globals.num_managers; i++) add_to_stringlist(&globals.managers[i].dontshow, token); } else { add_to_stringlist(&globals.managers[manager].dontshow, token); } Free(token); p = DoGetNextToken(p, &token, NULL, ",", NULL); } while (token); if (token) Free(token); } else if (!strcasecmp(option1, "drawicons")) { if (!FMiniIconsSupported) { ConsoleMessage("DrawIcons support not compiled in\n"); } else { p = read_next_cmd(READ_ARG); if (!p) { ConsoleMessage("Bad line: %s\n", current_line); ConsoleMessage("Need argument to drawicons\n"); continue; } if (!strcasecmp(p, "true")) { i = 1; } /* [NFM 3 Dec 97] added support for drawicons "always" */ else if (!strcasecmp(p, "always")) { i = 2; } else if (!strcasecmp(p, "false")) { i = 0; } else { ConsoleMessage("Bad line: %s\n", current_line); ConsoleMessage("What is this: %s?\n", p); continue; } ConsoleDebug(CONFIG, "Setting drawicons to: %d\n", i); SET_MANAGER(manager, draw_icons, i); } } else if (!strcasecmp(option1, "followfocus")) { p = read_next_cmd(READ_ARG); if (!p) { ConsoleMessage("Bad line: %s\n", current_line); ConsoleMessage("Need argument to followfocus\n"); continue; } if (!strcasecmp(p, "true")) { i = 1; } else if (!strcasecmp(p, "false")) { i = 0; } else { ConsoleMessage("Bad line: %s\n", current_line); ConsoleMessage("What is this: %s?\n", p); continue; } ConsoleDebug(CONFIG, "Setting followfocus to: %d\n", i); SET_MANAGER(manager, followFocus, i); } else if (!strcasecmp(option1, "showtransient")) { p = read_next_cmd(READ_ARG); if (!p) { ConsoleMessage("Bad line: %s\n", current_line); ConsoleMessage("Need argument to showtransient\n"); continue; } if (!strcasecmp(p, "true")) { i = 1; } else if (!strcasecmp(p, "false")) { i = 0; } else { ConsoleMessage("Bad line: %s\n", current_line); ConsoleMessage("What is this: %s?\n", p); continue; } ConsoleDebug(CONFIG, "Setting showtransient to: %d\n", i); SET_MANAGER(manager, showtransient, i); } else if( !strcasecmp(option1, "showonlyfocused")) { p = read_next_cmd(READ_ARG); if (!p) { ConsoleMessage("Bad line: %s\n", current_line); ConsoleMessage("Need argument to showonlyfocused\n"); continue; } if (!strcasecmp(p, "true")) { i = 1; } else if (!strcasecmp(p, "false")) { i = 0; } else { ConsoleMessage("Bad line: %s\n", current_line); ConsoleMessage("What is this: %s?\n", p); continue; } ConsoleMessage("Show only focused to: %d\n", i); SET_MANAGER( manager, showonlyfocused, i); } else if (!strcasecmp(option1, "showonlyicons")) { p = read_next_cmd(READ_ARG); if (!p) { ConsoleMessage("Bad line: %s\n", current_line); ConsoleMessage("Need argument to showonlyicons\n"); continue; } if (!strcasecmp(p, "true")) { i = 1; } else if (!strcasecmp(p, "false")) { i = 0; } else { ConsoleMessage("Bad line: %s\n", current_line); ConsoleMessage("What is this: %s?\n", p); continue; } ConsoleDebug(CONFIG, "Setting showonlyicons to: %d\n", i); SET_MANAGER(manager, showonlyiconic, i); } else if (!strcasecmp(option1, "shownoicons")) { p = read_next_cmd(READ_ARG); if (!p) { ConsoleMessage("Bad line: %s\n", current_line); ConsoleMessage("Need argument to shownoicons\n"); continue; } if (!strcasecmp(p, "true")) { i = 1; } else if (!strcasecmp(p, "false")) { i = 0; } else { ConsoleMessage("Bad line: %s\n", current_line); ConsoleMessage("What is this: %s?\n", p); continue; } ConsoleDebug(CONFIG, "Setting shownoicons to: %d\n", i); SET_MANAGER(manager, shownoiconic, i); } else if (!strcasecmp(option1, "font")) { char *f; p = read_next_cmd(READ_REST_OF_LINE); trim(p); if (!p) { ConsoleMessage("Bad line: %s\n", current_line); continue; } CopyStringWithQuotes(&f, p); ConsoleDebug(CONFIG, "font: %s\n", f); SET_MANAGER(manager, fontname, copy_string(&globals.managers[id].fontname, f)); free(f); } else if (!strcasecmp(option1, "foreground")) { p = read_next_cmd(READ_ARG); if (!p) { ConsoleMessage("Bad line: %s\n", current_line); continue; } ConsoleDebug(CONFIG, "default foreground: %s\n", p); for ( i = 0; i < NUM_CONTEXTS; i++ ) SET_MANAGER(manager, foreColorName[i], conditional_copy_string(&globals.managers[id].foreColorName[i], p)); } else if (!strcasecmp(option1, "format")) { char *token; NameType flags; p = read_next_cmd(READ_REST_OF_LINE); if (!p) { ConsoleMessage("Bad line: %s\n", current_line); continue; } DoGetNextToken(p, &token, NULL, ",", NULL); if (!token) { token = (char *)safemalloc(1); *token = 0; } SET_MANAGER(manager, formatstring, copy_string (&globals.managers[id].formatstring, token)); flags = parse_format_dependencies(token); SET_MANAGER(manager, format_depend, flags); Free(token); } else if (!strcasecmp(option1, "geometry")) { ConsoleMessage("Geometry option no longer supported.\n"); ConsoleMessage("Use ManagerGeometry and ButtonGeometry.\n"); } else if (!strcasecmp(option1, "iconname")) { char *token; p = read_next_cmd(READ_REST_OF_LINE); if (!p) { ConsoleMessage("Bad line: %s\n", current_line); continue; } DoGetNextToken(p, &token, NULL, ",", NULL); if (!token) { token = (char *)safemalloc(1); *token = 0; } SET_MANAGER(manager, iconname, copy_string(&globals.managers[id].iconname, token)); Free(token); } else if (!strcasecmp(option1, "managergeometry")) { p = read_next_cmd(READ_ARG); if (!p) { ConsoleMessage("Bad line: %s\n", current_line); continue; } SET_MANAGER(manager, geometry_str, copy_string(&globals.managers[id].geometry_str, p)); } else if (!strcasecmp(option1, "resolution")) { p = read_next_cmd(READ_ARG); if (!p) { ConsoleMessage("Bad line: %s\n", current_line); continue; } ConsoleDebug(CONFIG, "resolution: %s\n", p); if (!strcasecmp(p, "global")) r = SHOW_GLOBAL; else if (!strcasecmp(p, "desk")) r = SHOW_DESKTOP; else if (!strcasecmp(p, "page")) r = SHOW_PAGE; else if (!strcasecmp(p, "screen")) r = SHOW_SCREEN; else if (!strcasecmp(p, "!desk")) r = NO_SHOW_DESKTOP; else if (!strcasecmp(p, "!page")) r = NO_SHOW_PAGE; else if (!strcasecmp(p, "!screen")) r = NO_SHOW_SCREEN; else { ConsoleMessage("Bad line: %s\n", current_line); ConsoleMessage("What kind of resolution is this?\n"); continue; } SET_MANAGER(manager, res, r); } else if (!strcasecmp(option1, "reverse")) { p = read_next_cmd(READ_ARG); if (!p) { ConsoleMessage("Bad line: %s\n", current_line); continue; } ConsoleDebug(CONFIG, "reverse: %s\n", p); if (!strcasecmp(p, "none")) rv = REVERSE_NONE; else if (!strcasecmp(p, "icon")) rv = REVERSE_ICON; else if (!strcasecmp(p, "normal")) rv = REVERSE_NORMAL; else { ConsoleMessage("Bad line: %s\n", current_line); ConsoleMessage("What kind of reverse is this?\n"); continue; } SET_MANAGER(manager, rev, rv); } else if (!strcasecmp(option1, "shape")) { p = read_next_cmd(READ_ARG); if (!p) { ConsoleMessage("Bad line: %s\n", current_line); ConsoleMessage("Need argument to shape\n"); continue; } if (!strcasecmp(p, "true")) { i = 1; } else if (!strcasecmp(p, "false")) { i = 0; } else { ConsoleMessage("Bad line: %s\n", current_line); ConsoleMessage("What is this: %s?\n", p); continue; } if (!FHaveShapeExtension && i) { ConsoleMessage("Shape support not compiled in\n"); continue; } ConsoleDebug(CONFIG, "Setting shape to: %d\n", i); SET_MANAGER(manager, shaped, i); } else if (!strcasecmp(option1, "show")) { char *token = NULL; p = read_next_cmd(READ_REST_OF_LINE); if (!p) { ConsoleMessage("Bad line: %s\n", current_line); continue; } p = DoGetNextToken(p, &token, NULL, ",", NULL); if (!token) { ConsoleMessage("Bad line: %s\n", current_line); continue; } do { ConsoleDebug(CONFIG, "show: %s\n", token); if (manager == -1) { int i; for (i = 0; i < globals.num_managers; i++) add_to_stringlist(&globals.managers[i].show, token); } else { add_to_stringlist(&globals.managers[manager].show, token); } Free(token); p = DoGetNextToken(p, &token, NULL, ",", NULL); } while (token); if (token) Free(token); } else if (!strcasecmp(option1, "showtitle")) { ConsoleMessage("Bad line: %s\n", current_line); ConsoleMessage("showtitle is no longer an option. Use format\n"); continue; } else if (!strcasecmp(option1, "sort")) { p = read_next_cmd(READ_ARG); if (!p) { ConsoleMessage("Bad line: %s\n", current_line); ConsoleMessage("Need argument to sort\n"); continue; } if (!strcasecmp(p, "name")) { i = SortName; } else if (!strcasecmp(p, "namewithcase")) { i = SortNameCase; } else if (!strcasecmp(p, "id")) { i = SortId; } else if (!strcasecmp(p, "none")) { i = SortNone; } else if (!strcasecmp(p, "weighted")) { i = SortWeighted; } else if (!strcasecmp(p, "false") || !strcasecmp(p, "true")) { /* Old options */ ConsoleMessage("FvwmIconMan: sort option no longer takes " "true or false value\n" "Please read the latest manpage\n"); continue; } else { ConsoleMessage("Bad line: %s\n", current_line); ConsoleMessage("What is this: %s?\n", p); continue; } ConsoleDebug(CONFIG, "Setting sort to: %d\n", i); SET_MANAGER(manager, sort, i); } else if (!strcasecmp(option1, "sortweight")) { WeightedSort weighted_sort; p = read_next_cmd(READ_ARG); if (!p) { ConsoleMessage("Bad line: %s\n", current_line); continue; } if (extract_int(p, &n) == 0) { ConsoleMessage("This is not a number: %s\n", p); ConsoleMessage("Bad line: %s\n", current_line); continue; } weighted_sort.resname = NULL; weighted_sort.classname = NULL; weighted_sort.titlename = NULL; weighted_sort.iconname = NULL; weighted_sort.weight = n; p = read_next_cmd(READ_ARG); while (p) { if (!strncasecmp(p, "resource=", 9)) { copy_string(&weighted_sort.resname, p + 9); } else if (!strncasecmp(p, "class=", 6)) { copy_string(&weighted_sort.classname, p + 6); } else if (!strncasecmp(p, "title=", 6)) { copy_string(&weighted_sort.titlename, p + 6); } else if (!strncasecmp(p, "icon=", 5)) { copy_string(&weighted_sort.iconname, p + 5); } else { ConsoleMessage("Unknown sortweight field: %s\n", p); ConsoleMessage("Bad line: %s\n", current_line); } p = read_next_cmd(READ_ARG); } if (manager == -1) { for (i = 0; i < globals.num_managers; i++) { add_weighted_sort(&globals.managers[i], &weighted_sort); } } else { add_weighted_sort(&globals.managers[manager], &weighted_sort); } if (weighted_sort.resname) { Free(weighted_sort.resname); } if (weighted_sort.resname) { Free(weighted_sort.classname); } if (weighted_sort.resname) { Free(weighted_sort.titlename); } if (weighted_sort.resname) { Free(weighted_sort.iconname); } } else if (!strcasecmp(option1, "NoIconAction")) { char *token; p = read_next_cmd(READ_REST_OF_LINE); if (!p) { ConsoleMessage("Bad line: %s\n", current_line); continue; } DoGetNextToken(p, &token, NULL, ",", NULL); if (!token) { token = (char *)safemalloc(1); *token = 0; } SET_MANAGER(manager, AnimCommand, copy_string(&globals.managers[id].AnimCommand, token)); Free(token); } else if (!strcasecmp(option1, "title")) { char *token; p = read_next_cmd(READ_REST_OF_LINE); if (!p) { ConsoleMessage("Bad line: %s\n", current_line); continue; } DoGetNextToken(p, &token, NULL, ",", NULL); if (!token) { token = (char *)safemalloc(1); *token = 0; } SET_MANAGER(manager, titlename, copy_string(&globals.managers[id].titlename, token)); Free(token); } else if (!strcasecmp(option1, "iconButton")) { handle_button_config(manager, ICON_CONTEXT, option1); } else if (!strcasecmp(option1, "plainButton")) { handle_button_config(manager, PLAIN_CONTEXT, option1); } else if (!strcasecmp(option1, "selectButton")) { handle_button_config(manager, SELECT_CONTEXT, option1); } else if (!strcasecmp(option1, "focusButton")) { handle_button_config(manager, FOCUS_CONTEXT, option1); } else if (!strcasecmp(option1, "focusandselectButton")) { handle_button_config(manager, FOCUS_SELECT_CONTEXT, option1); } else if (!strcasecmp(option1, "titlebutton")) { handle_button_config(manager, TITLE_CONTEXT, option1); } else if (!strcasecmp(option1, "titlecolorset")) { p = read_next_cmd(READ_ARG); if (!p) { ConsoleMessage("Bad line: %s\n", current_line); continue; } if (extract_int(p, &n) == 0) { ConsoleMessage("This is not a number: %s\n", p); ConsoleMessage("Bad line: %s\n", current_line); continue; } SET_MANAGER(manager, colorsets[TITLE_CONTEXT], n); AllocColorset(n); } else if (!strcasecmp(option1, "focusandselectcolorset")) { p = read_next_cmd(READ_ARG); if (!p) { ConsoleMessage("Bad line: %s\n", current_line); continue; } if (extract_int(p, &n) == 0) { ConsoleMessage("This is not a number: %s\n", p); ConsoleMessage("Bad line: %s\n", current_line); continue; } SET_MANAGER(manager, colorsets[FOCUS_SELECT_CONTEXT], n); AllocColorset(n); } else if (!strcasecmp(option1, "focuscolorset")) { p = read_next_cmd(READ_ARG); if (!p) { ConsoleMessage("Bad line: %s\n", current_line); continue; } if (extract_int(p, &n) == 0) { ConsoleMessage("This is not a number: %s\n", p); ConsoleMessage("Bad line: %s\n", current_line); continue; } SET_MANAGER(manager, colorsets[FOCUS_CONTEXT], n); AllocColorset(n); } else if (!strcasecmp(option1, "selectcolorset")) { p = read_next_cmd(READ_ARG); if (!p) { ConsoleMessage("Bad line: %s\n", current_line); continue; } if (extract_int(p, &n) == 0) { ConsoleMessage("This is not a number: %s\n", p); ConsoleMessage("Bad line: %s\n", current_line); continue; } SET_MANAGER(manager, colorsets[SELECT_CONTEXT], n); AllocColorset(n); } else if (!strcasecmp(option1, "plaincolorset")) { p = read_next_cmd(READ_ARG); if (!p) { ConsoleMessage("Bad line: %s\n", current_line); continue; } if (extract_int(p, &n) == 0) { ConsoleMessage("This is not a number: %s\n", p); ConsoleMessage("Bad line: %s\n", current_line); continue; } SET_MANAGER(manager, colorsets[PLAIN_CONTEXT], n); AllocColorset(n); } else if (!strcasecmp(option1, "iconcolorset")) { p = read_next_cmd(READ_ARG); if (!p) { ConsoleMessage("Bad line: %s\n", current_line); continue; } if (extract_int(p, &n) == 0) { ConsoleMessage("This is not a number: %s\n", p); ConsoleMessage("Bad line: %s\n", current_line); continue; } SET_MANAGER(manager, colorsets[ICON_CONTEXT], n); AllocColorset(n); } else if (!strcasecmp(option1, "usewinlist")) { p = read_next_cmd(READ_ARG); if (!p) { ConsoleMessage("Bad line: %s\n", current_line); ConsoleMessage("Need argument to usewinlist\n"); continue; } if (!strcasecmp(p, "true")) { i = 1; } else if (!strcasecmp(p, "false")) { i = 0; } else { ConsoleMessage("Bad line: %s\n", current_line); ConsoleMessage("What is this: %s?\n", p); continue; } ConsoleDebug(CONFIG, "Setting usewinlist to: %d\n", i); SET_MANAGER(manager, usewinlist, i); } else if (!strcasecmp(option1, "reliefthickness")) { p = read_next_cmd(READ_ARG); if (!p) { ConsoleMessage("Bad line: %s\n", current_line); continue; } if (extract_int(p, &n) == 0) { ConsoleMessage("This is not a number: %s\n", p); ConsoleMessage("Bad line: %s\n", current_line); continue; } SET_MANAGER(manager, relief_thickness, n); } else if (!strcasecmp(option1, "tips")) { p = read_next_cmd(READ_ARG); if (!p) { ConsoleMessage("Bad line: %s\n", current_line); continue; } if (!strcasecmp(p, "always")) { i = TIPS_ALWAYS; } else if (!strcasecmp(p, "false")) { i = TIPS_NEVER; } else if (!strcasecmp(p, "needed")) { i = TIPS_NEEDED; } else { ConsoleMessage("Bad line: %s\n", current_line); ConsoleMessage("What is this: %s?\n", p); continue; } SET_MANAGER(manager, tips, i); } else if (!strcasecmp(option1, "tipsfont")) { char *f; p = read_next_cmd(READ_REST_OF_LINE); trim(p); if (!p) { ConsoleMessage("Bad line: %s\n", current_line); continue; } CopyStringWithQuotes(&f, p); ConsoleDebug(CONFIG, "tipsfont: %s\n", f); SET_MANAGER(manager, tips_fontname, copy_string(&globals.managers[id].tips_fontname, f)); free(f); } else if (!strcasecmp(option1, "tipscolorset")) { p = read_next_cmd(READ_ARG); if (!p) { ConsoleMessage("Bad line: %s\n", current_line); continue; } if (extract_int(p, &n) == 0) { ConsoleMessage("This is not a number: %s\n", p); ConsoleMessage("Bad line: %s\n", current_line); continue; } SET_MANAGER(manager, tips_conf->colorset, n); if (n >= 0) { AllocColorset(n); } } else if (!strcasecmp(option1, "tipsdelays")) { p = read_next_cmd(READ_ARG); if (!p) { ConsoleMessage("Bad line: %s\n", current_line); continue; } if (extract_int(p, &n) == 0) { ConsoleMessage("This is not a number: %s\n", p); ConsoleMessage("Bad line: %s\n", current_line); continue; } if (n < 0) { ConsoleMessage("No negative delay: %s\n", p); ConsoleMessage("Bad line: %s\n", current_line); continue; } SET_MANAGER(manager, tips_conf->delay, n); p = read_next_cmd(READ_ARG); if (!p) { SET_MANAGER(manager, tips_conf->mapped_delay, n); continue; } if (extract_int(p, &n) == 0) { ConsoleMessage("This is not a number: %s\n", p); ConsoleMessage("Bad line: %s\n", current_line); continue; } if (n < 0) { ConsoleMessage("No negative delay: %s\n", p); ConsoleMessage("Bad line: %s\n", current_line); continue; } SET_MANAGER(manager, tips_conf->mapped_delay, n); } else if (!strcasecmp(option1, "tipsformat")) { char *token; /*NameType flags;*/ p = read_next_cmd(READ_REST_OF_LINE); if (!p) { ConsoleMessage("Bad line: %s\n", current_line); continue; } DoGetNextToken(p, &token, NULL, ",", NULL); if (!token) { token = (char *)safemalloc(1); *token = 0; } SET_MANAGER(manager, tips_formatstring, copy_string ( &globals.managers[id].tips_formatstring, token)); #if 0 flags = parse_format_dependencies(token); SET_MANAGER(manager, format_depend, flags); Free(token); #endif } else if (!strcasecmp(option1, "tipsborderwidth")) { p = read_next_cmd(READ_ARG); if (!p) { ConsoleMessage("Bad line: %s\n", current_line); continue; } if (extract_int(p, &n) == 0) { ConsoleMessage("This is not a number: %s\n", p); ConsoleMessage("Bad line: %s\n", current_line); continue; } if (n < 0) { n = 0; } SET_MANAGER(manager, tips_conf->border_width, n); } else if (!strcasecmp(option1, "tipsoffsets")) { p = read_next_cmd(READ_ARG); if (!p) { ConsoleMessage("Bad line: %s\n", current_line); continue; } if (extract_int(p, &n) == 0) { ConsoleMessage("This is not a number: %s\n", p); ConsoleMessage("Bad line: %s\n", current_line); continue; } if (n < 1) { ConsoleMessage("A tips offset must be positive: %s\n", p); ConsoleMessage("Bad line: %s\n", current_line); continue; } SET_MANAGER(manager, tips_conf->placement_offset, n); p = read_next_cmd(READ_ARG); if (!p) { ConsoleMessage("Bad line: %s\n", current_line); continue; } if (extract_int(p, &n) == 0) { ConsoleMessage("This is not a number: %s\n", p); ConsoleMessage("Bad line: %s\n", current_line); continue; } if (n < 1) { ConsoleMessage("A tips offset must be positive: %s\n", p); ConsoleMessage("Bad line: %s\n", current_line); continue; } SET_MANAGER(manager, tips_conf->justification_offset, n); } else if (!strcasecmp(option1, "tipsplacement")) { p = read_next_cmd(READ_ARG); if (!p) { ConsoleMessage("Bad line: %s\n", current_line); continue; } if (!strcasecmp(p, "up")) { i = FTIPS_PLACEMENT_UP; } else if (!strcasecmp(p, "down")) { i = FTIPS_PLACEMENT_DOWN; } else if (!strcasecmp(p, "left")) { i = FTIPS_PLACEMENT_LEFT; } else if (!strcasecmp(p, "right")) { i = FTIPS_PLACEMENT_RIGHT; } else if (!strcasecmp(p, "updown")) { i = FTIPS_PLACEMENT_AUTO_UPDOWN; } else if (!strcasecmp(p, "leftright")) { i = FTIPS_PLACEMENT_AUTO_LEFTRIGHT; } else { ConsoleMessage("Bad line: %s\n", current_line); ConsoleMessage("What is this: %s?\n", p); continue; } SET_MANAGER(manager, tips_conf->placement, i); } else if (!strcasecmp(option1, "tipsjustification")) { p = read_next_cmd(READ_ARG); if (!p) { ConsoleMessage("Bad line: %s\n", current_line); continue; } if (!strcasecmp(p, "center")) { i = FTIPS_JUSTIFICATION_CENTER; } else if (!strcasecmp(p, "leftup")) { i = FTIPS_JUSTIFICATION_LEFT_UP; } else if (!strcasecmp(p, "rightdown")) { i = FTIPS_JUSTIFICATION_RIGHT_DOWN; } else { ConsoleMessage("Bad line: %s\n", current_line); ConsoleMessage("What is this: %s?\n", p); continue; } SET_MANAGER(manager, tips_conf->justification, i); } else { ConsoleMessage("Bad line: %s\n", current_line); ConsoleMessage("Unknown option: %s\n", p); } } } if (globals.managers == NULL) { ConsoleDebug(CONFIG, "I'm assuming you only want one manager\n"); allocate_managers(1); } print_managers(); } void process_dynamic_config_line(char *line) { int manager = 0; char *token; extern void remanage_winlist(void); /* don't support dynamic config for transient */ if (globals.transient) { return; } line += ModuleLen; line = GetNextToken(line, &token); if (token && isdigit(*token)) { if (extract_int(token, &manager) == 0 || manager <= 0 || manager > globals.num_managers) { manager = 0; } free(token); line = GetNextToken(line, &token); } if (!token) { return; } manager--; /* currently supports only "resolution" and "tips" */ if (strcasecmp(token, "resolution") == 0) { int value; free(token); line = GetNextToken(line, &token); if (!token) { return; } if (!strcasecmp(token, "global")) value = SHOW_GLOBAL; else if (!strcasecmp(token, "desk")) value = SHOW_DESKTOP; else if (!strcasecmp(token, "page")) value = SHOW_PAGE; else if (!strcasecmp(token, "screen")) value = SHOW_SCREEN; else if (!strcasecmp(token, "!desk")) value = NO_SHOW_DESKTOP; else if (!strcasecmp(token, "!page")) value = NO_SHOW_PAGE; else if (!strcasecmp(token, "!screen")) value = NO_SHOW_SCREEN; else { fprintf( stderr, "%s: unknown resolution %s.\n", MyName, token); free(token); return; } SET_MANAGER(manager, res, value); remanage_winlist(); } else if (strcasecmp(token, "tips") == 0) { int value; free(token); line = GetNextToken(line, &token); if (!token) { return; } if (!strcasecmp(token, "always")) { value = TIPS_ALWAYS; } else if (!strcasecmp(token, "false")) { value = TIPS_NEVER; } else if (!strcasecmp(token, "needed")) { value = TIPS_NEEDED; } else { ConsoleMessage("Bad line: %s\n", line); ConsoleMessage("What is this: %s?\n", token); free(token); return; } SET_MANAGER(manager, tips, value); if (manager == -1) { tips_cancel(NULL); } else { tips_cancel(&globals.managers[manager]); } } free(token); }