/* -*-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 */ /* * * code for processing module configuration commands * * Modification History * * Created 09/23/98 by Dan Espen: * * - Some of this logic used to reside in "read.c", preceeded by a * comment about whether it belonged there. Time tells. * * - Added logic to execute module config commands by passing to the * modules that want "active command pipes". * * ******************************************************************** */ #include "config.h" #include #include "libs/fvwmlib.h" #include "libs/Parse.h" #include "libs/Strings.h" #include "libs/wild.h" #include "fvwm.h" #include "externs.h" #include "cursor.h" #include "functions.h" #include "bindings.h" #include "misc.h" #include "screen.h" #include "module_list.h" #include "module_interface.h" #include "colorset.h" #include "libs/FScreen.h" extern int nColorsets; /* in libs/Colorset.c */ /* do not send ColorLimit, it is not used anymore but maybe by non * "official" modules */ #define DISABLE_COLORLIMIT_CONFIG_INFO #define MODULE_CONFIG_DELIM ':' struct moduleInfoList { char *data; unsigned char alias_len; struct moduleInfoList *next; }; struct moduleInfoList *modlistroot = NULL; static struct moduleInfoList *AddToModList(char *tline); static void SendConfigToModule( fmodule *module, const struct moduleInfoList *entry, char *match, int match_len); /* * ModuleConfig handles commands starting with "*". * * Each command is added to a list from which modules request playback * thru "sendconfig". * * Some modules request that module config commands be sent to them * as the commands are entered. Send to modules that want it. */ void ModuleConfig(char *action) { int end; fmodule_list_itr moditr; fmodule *module; struct moduleInfoList *new_entry; end = strlen(action) - 1; if (action[end] == '\n') action[end] = '\0'; /* save for config request */ new_entry = AddToModList(action); /* look at all possible pipes */ module_list_itr_init(&moditr); while ( (module = module_list_itr_next(&moditr)) != NULL) { if (IS_MESSAGE_SELECTED(module, M_SENDCONFIG)) { /* module wants config cmds */ char *name = MOD_NAME(module); if (MOD_ALIAS(module)) { name = MOD_ALIAS(module); } SendConfigToModule( module, new_entry, CatString2("*", name), 0); } } return; } static struct moduleInfoList *AddToModList(char *tline) { struct moduleInfoList *t, *prev, *this; char *rline = tline; char *alias_end = skipModuleAliasToken(tline + 1); /* Find end of list */ t = modlistroot; prev = NULL; while(t != NULL) { prev = t; t = t->next; } this = (struct moduleInfoList *)safemalloc( sizeof(struct moduleInfoList)); this->alias_len = 0; if (alias_end && alias_end[0] == MODULE_CONFIG_DELIM) { /* migo (01-Sep-2000): construct an old-style config line */ char *conf_start = alias_end + 1; while (isspace(*conf_start)) conf_start++; *alias_end = '\0'; rline = CatString2(tline, conf_start); *alias_end = MODULE_CONFIG_DELIM; this->alias_len = alias_end - tline; } this->data = (char *)safemalloc(strlen(rline)+1); strcpy(this->data, rline); this->next = NULL; if(prev == NULL) { modlistroot = this; } else { prev->next = this; } return this; } /* * delete from module configuration */ void CMD_DestroyModuleConfig(F_CMD_ARGS) { struct moduleInfoList *current, *next, *prev; char *info; /* info to be deleted - may contain wildcards */ char *mi; char *alias_end; int alias_len = 0; while (isspace(*action)) { action++; } alias_end = skipModuleAliasToken(action); if (alias_end && alias_end[0] == MODULE_CONFIG_DELIM) { /* migo: construct an old-style config line */ char *conf_start = alias_end + 1; while (isspace(*conf_start)) conf_start++; *alias_end = '\0'; GetNextToken(conf_start, &conf_start); if (conf_start == NULL) { return; } info = stripcpy(CatString2(action, conf_start)); *alias_end = MODULE_CONFIG_DELIM; /* +1 for a leading '*' */ alias_len = alias_end - action + 1; free(conf_start); } else { GetNextToken(action, &info); if (info == NULL) { return; } } current = modlistroot; prev = NULL; while (current != NULL) { GetNextToken(current->data, &mi); next = current->next; if ((!alias_len || !current->alias_len || alias_len == current->alias_len) && matchWildcards(info, mi+1)) { free(current->data); free(current); if( prev ) { prev->next = next; } else { modlistroot = next; } } else { prev = current; } current = next; if (mi) { free(mi); } } free(info); return; } static void send_xinerama_state(fmodule *module) { SendName(module, M_CONFIG_INFO, 0, 0, 0, FScreenGetConfiguration()); return; } static void send_desktop_names(fmodule *module) { DesktopsInfo *d; char *name; for (d = Scr.Desktops->next; d != NULL; d = d->next) { if (d->name != NULL) { name = (char *)safemalloc(strlen(d->name) + 44); sprintf(name,"DesktopName %d %s", d->desk, d->name); SendName(module, M_CONFIG_INFO, 0, 0, 0, name); free(name); } } return; } static void send_desktop_geometry(fmodule *module) { char msg[64]; sprintf(msg, "DesktopSize %d %d\n", Scr.VxMax / Scr.MyDisplayWidth + 1, Scr.VyMax / Scr.MyDisplayHeight + 1); SendName(module, M_CONFIG_INFO, 0, 0, 0, msg); return; } static void send_image_path(fmodule *module) { char *msg; char *ImagePath = PictureGetImagePath(); if (ImagePath && *ImagePath != 0) { msg = safemalloc(strlen(ImagePath) + 12); sprintf(msg, "ImagePath %s\n", ImagePath); SendName(module, M_CONFIG_INFO, 0, 0, 0, msg); free(msg); } return; } static void send_color_limit(fmodule *module) { #ifndef DISABLE_COLORLIMIT_CONFIG_INFO char msg[64]; sprintf(msg, "ColorLimit %d\n", Scr.ColorLimit); SendName(module, M_CONFIG_INFO, 0, 0, 0, msg); #endif return; } static void send_colorsets(fmodule *module) { int n; /* dump the colorsets (0 first as others copy it) */ for (n = 0; n < nColorsets; n++) { SendName( module, M_CONFIG_INFO, 0, 0, 0, DumpColorset(n, &Colorset[n])); } return; } static void send_click_time(fmodule *module) { char msg[64]; /* Dominik Vogt (8-Nov-1998): Scr.ClickTime patch to set ClickTime to * 'not at all' during InitFunction and RestartFunction. */ sprintf(msg,"ClickTime %d\n", (Scr.ClickTime < 0) ? -Scr.ClickTime : Scr.ClickTime); SendName(module, M_CONFIG_INFO, 0, 0, 0, msg); return; } static void send_move_threshold(fmodule *module) { char msg[64]; sprintf(msg, "MoveThreshold %d\n", Scr.MoveThreshold); SendName(module, M_CONFIG_INFO, 0, 0, 0, msg); return; } void send_ignore_modifiers(fmodule *module) { char msg[64]; sprintf(msg, "IgnoreModifiers %d\n", GetUnusedModifiers()); SendName(module, M_CONFIG_INFO, 0, 0, 0, msg); return; } void CMD_Send_ConfigInfo(F_CMD_ARGS) { struct moduleInfoList *t; /* matching criteria for module cmds */ char *match; /* get length once for efficiency */ int match_len = 0; fmodule *mod = exc->m.module; send_desktop_geometry(mod); /* send ImagePath and ColorLimit first */ send_image_path(mod); send_color_limit(mod); send_xinerama_state(mod); send_colorsets(mod); send_click_time(mod); send_move_threshold(mod); match = PeekToken(action, &action); if (match) { match_len = strlen(match); } for (t = modlistroot; t != NULL; t = t->next) { SendConfigToModule(mod, t, match, match_len); } send_desktop_names(mod); send_ignore_modifiers(mod); SendPacket( mod, M_END_CONFIG_INFO, (long)0, (long)0, (long)0, (long)0, (long)0, (long)0, (long)0, (long)0); return; } static void SendConfigToModule( fmodule *module, const struct moduleInfoList *entry, char *match, int match_len) { if (match) { if (match_len == 0) { match_len = strlen(match); } if (entry->alias_len > 0 && entry->alias_len != match_len) { return; } /* migo: this should be strncmp not strncasecmp probably. */ if (strncasecmp(entry->data, match, match_len) != 0) { return; } } SendName(module, M_CONFIG_INFO, 0, 0, 0, entry->data); return; }