/* -*-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 <ctype.h>
#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; j<numargs; ++j)
{
switch (args[j].type)
{
case StringArg:
ConsoleMessage(" %s", args[j].value.string_value);
break;
default:
ConsoleMessage(" [unknown arg #: %d]", args[j].type);
}
}
ConsoleMessage(" was called. This should not happen.\n");
return 0;
}
/* the number of JmpArg arguments that have been created, but not yet
resolved into IntArgs. */
static int JmpArgs = 0;
/* icky, I know, but it'll save unnecessary error-checking. */
static Function *parse_function(char **line, char *pstop_char)
{
Function *ftype = (Function *)safemalloc(sizeof(Function));
char *ptr, *name, *tok;
int j, flag;
FunctionType *builtin_functions_i;
ConsoleDebug(CONFIG, "in parse_function\n");
ptr = DoGetNextToken(*line, &name, NULL, ",", pstop_char);
if (name == NULL) {
Free(ftype);
*line = NULL;
return NULL;
}
builtin_functions_i=bsearch((void *)name, (void *)builtin_functions,
num_builtins, sizeof(FunctionType),
funccasecmp);
if (builtin_functions_i) {
Free(name);
ftype->func = 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);
}
syntax highlighted by Code2HTML, v. 0.9.1