/* -*-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 */ /* ---------------------------- included header files ----------------------- */ #include "config.h" #include #include /* the following 5 are just to satisfy X11/extensions/shape.h on some systems */ #include #include #include #include #include #include "libs/Module.h" #include "libs/Strings.h" #include "libs/Parse.h" #include "FvwmButtons.h" #include "button.h" #include "draw.h" #include "icons.h" /* ---------------------------- local definitions --------------------------- */ /* ---------------------------- local macros -------------------------------- */ /* ---------------------------- imports ------------------------------------- */ extern int Width, Height; extern int screen; /* ---------------------------- included code files ------------------------- */ /* ---------------------------- local types --------------------------------- */ /* ---------------------------- forward declarations ------------------------ */ /* ---------------------------- local variables ----------------------------- */ static Bool silent = False; /* ---------------------------- exported variables (globals) ---------------- */ /* ---------------------------- local functions ----------------------------- */ static void show_error(const char *msg, ...) { va_list args; if (silent == True) { return; } va_start(args, msg); vfprintf(stderr, CatString3(MyName, ": ", msg), args); va_end(args); } #if 0 /* to be used in module_expand_action */ static module_expand_vars mev = { /* number of vars */ 4, /* array of var names */ { "title", "icon", } /* array of values, void *, will be filled later */ { NULL, NULL }, /* array of booleans, 0 if string, 1 if int */ { 0, 0, }, }; #endif static char *expand_button_vars(const button_info *b, const char *line) { /* not fully implemented yet, should expand $title, $icon and so on */ rectangle r; char *expanded_line; /* there should be a function evaluating fore/back from colorset */ char *fore = (b->flags.b_Fore) ? b->fore : "black"; char *back = (b->flags.b_Back) ? b->back : "gray"; get_button_root_geometry(&r, b); expanded_line = module_expand_action( Dpy, screen, (char *)line, &r, fore, back); return expanded_line; } static button_info *parse_button_id(char **line) { button_info *b = NULL, *ub = UberButton; int mask; int x, y; int count, i; char *rest; char *s; s = PeekToken(*line, &rest); *line = NULL; if (!s) { show_error("No button id specified\n"); return NULL; } if (*s == '+') { unsigned int JunkWidth; unsigned int JunkHeight; mask = XParseGeometry(s, &x, &y, &JunkWidth, &JunkHeight); if (!(mask & XValue) || (mask & XNegative) || !(mask & YValue) || (mask & YNegative)) { show_error("Illegal button position '%s'\n", s); return NULL; } if (x < 0 || y < 0) { show_error("Button column/row must not be negative\n"); return NULL; } b = get_xy_button(ub, y, x); if (b == NULL) { show_error( "Button at column %d row %d not found\n", x, y); return NULL; } } else if (isdigit(*s)) { x = atoi(s); i = count = -1; /* find the button */ while (NextButton(&ub, &b, &i, 0)) { if (++count == x) break; } if (count != x || b == NULL) { show_error("Button number %d not found\n", x); return NULL; } } else if (isalpha(*s)) { Bool found = False; i = -1; /* find the button */ while (NextButton(&ub, &b, &i, 0)) { if (b->flags.b_Id && StrEquals(b->id, s)) { found = True; break; } } if (found == False) { show_error("Button id '%s' does not exist\n", s); return NULL; } } else { show_error("Invalid button id '%s' specified\n", s); return NULL; } *line = rest; return b; } /* ---------------------------- interface functions ------------------------- */ static char *actions[] = { "Silent", "ChangeButton", "ExpandButtonVars", "PressButton", NULL }; static char *button_options[] = { "Title", "Icon", "ActiveTitle", "ActiveIcon", "PressTitle", "PressIcon", NULL }; void parse_message_line(char *line) { char *rest; int action = -1; button_info *b; char *act; char *buttonn; int mousebutton; silent = False; do { action = GetTokenIndex(line, actions, -1, &rest); if (action == -1) { show_error("Message not understood: %s", line); return; } if (action == 0) { silent = True; line = rest; } } while (action == 0); /* find out which button */ b = parse_button_id(&rest); if (!b || !rest) { return; } switch (action) { case 1: /* ChangeButton */ /* The dimensions of individual buttons (& the overall size of * the FvwmButtons window) is based on the initial * configuration for the module. In some configurations, * dynamically adding/changing a title/icon may mean it no * longer fits on a button. Currently, there are no checks for * this occurance. */ while (rest && rest[0] != '\0') { char *option_pair; int option; char *value0, *value; FvwmPicture *icon; /* parse option and value and give diagnostics */ rest = GetQuotedString( rest, &option_pair, ",", NULL, NULL, NULL); while (isspace(*rest)) { rest++; } if (!option_pair) continue; option = GetTokenIndex( option_pair, button_options, -1, &value0); if (option < 0) { show_error( "Unsupported button option line '%s'\n", option_pair); free(option_pair); continue; } GetNextToken(value0, &value); free(option_pair); if (value == NULL) { show_error( "No title/icon to change specified.\n"); continue; } switch (option) { case 0: /* Title */ if (b->flags.b_Title) free(b->title); b->flags.b_Title = 1; CopyString(&b->title, value); break; case 2: /* ActiveTitle */ if (b->flags.b_ActiveTitle) free(b->activeTitle); b->flags.b_ActiveTitle = 1; CopyString(&b->activeTitle, value); break; case 4: /* PressTitle */ if (b->flags.b_PressTitle) free(b->pressTitle); b->flags.b_PressTitle = 1; CopyString(&b->pressTitle, value); break; default: if ( LoadIconFile( value, &icon, b->colorset) == 0) { show_error( "Cannot load icon \"%s\"\n", value); } else { switch (option) { case 1: /* Icon */ if (b->flags.b_Icon) { free(b->icon_file); PDestroyFvwmPicture( Dpy, b->icon); } b->flags.b_Icon = 1; CopyString( &b->icon_file, value); b->icon = icon; break; case 3: /* ActiveIcon */ if (b->flags.b_ActiveIcon) { free(b->active_icon_file); PDestroyFvwmPicture( Dpy, b->activeicon); } b->flags.b_ActiveIcon = 1; CopyString( &b->active_icon_file, value); b->activeicon = icon; break; case 5: /* PressIcon */ if (b->flags.b_PressIcon) { free(b->press_icon_file); PDestroyFvwmPicture( Dpy, b->pressicon); } b->flags.b_PressIcon = 1; CopyString( &b->press_icon_file, value); b->pressicon = icon; break; } } break; } if (value) { free(value); } } RedrawButton(b, DRAW_FORCE, NULL); if (UberButton->c->flags.b_TransBack) { SetTransparentBackground(UberButton, Width, Height); } break; case 2: /* ExpandButtonVars */ line = expand_button_vars(b, rest); if (line) { SendText(fd, line, 0); free(line); } break; case 3: /* PressButton */ rest = GetQuotedString(rest, &buttonn, "", NULL, NULL, NULL); if (buttonn) { mousebutton = atoi(buttonn); free(buttonn); if ( mousebutton <= 0 || mousebutton > NUMBER_OF_EXTENDED_MOUSE_BUTTONS) { mousebutton = 1; } } else { mousebutton = 1; } CurrentButton = b; act = GetButtonAction(b, mousebutton); ButtonPressProcess(b, &act); if (act) { free(act); } CurrentButton = NULL; break; } return; }