/* -*-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 "FvwmIconMan.h" #include "readconfig.h" #include "xmanager.h" #include "x.h" #include "libs/Module.h" #include "libs/wild.h" static Button *get_select_button(void); static struct { Button *current_button; Function *fp; } function_context; static void init_function_context(Function *func) { function_context.current_button = get_select_button(); function_context.fp = func; } void run_function_list(Function *func) { init_function_context(func); while (function_context.fp) { function_context.fp->func( function_context.fp->numargs, function_context.fp->args); if (function_context.fp) { function_context.fp = function_context.fp->next; } } } static Button *get_select_button(void) { if (globals.select_win) { return globals.select_win->button; } return NULL; } static Button *get_focus_button(void) { if (globals.focus_win) { return globals.focus_win->button; } return NULL; } static WinManager *get_current_man(void) { Button *b = function_context.current_button; if (globals.num_managers==1) { return globals.managers; } if (b && b->drawn_state.win) { return b->drawn_state.win->manager; } return NULL; } static WinData *get_current_win(void) { Button *b = function_context.current_button; if (b && b->drawn_state.win) { return b->drawn_state.win; } return NULL; } static Button *get_current_button(void) { return function_context.current_button; } static Button *button_move(ButtonValue *bv) { Button *b = NULL, *cur; WinManager *man; int i; cur = get_current_button(); switch (bv->base) { case NoButton: ConsoleMessage("gotobutton: need a button to change to\n"); return cur; case SelectButton: b = get_select_button(); break; case FocusButton: b = get_focus_button(); break; case AbsoluteButton: man = get_current_man(); if (man && man->buttons.num_windows > 0) { i = bv->offset % man->buttons.num_windows; if (i < 0) { i += man->buttons.num_windows; } b = man->buttons.buttons[i]; } break; default: man = get_current_man(); if (!cur) { ConsoleDebug( FUNCTIONS, "\tno current button, skipping\n"); return NULL; } switch (bv->base) { case UpButton: b = button_above(man, cur); break; case DownButton: b = button_below(man, cur); break; case LeftButton: b = button_left(man, cur); break; case RightButton: b = button_right(man, cur); break; case NextButton: b = button_next(man, cur); break; case PrevButton: b = button_prev(man, cur); break; default: ConsoleMessage("Internal error in gotobutton\n"); break; } } return b; } int builtin_gotobutton(int numargs, BuiltinArg *args) { Button *b; ButtonValue *bv; ConsoleDebug(FUNCTIONS, "gotobutton: "); print_args(numargs, args); bv = &args[0].value.button_value; b = button_move(bv); if (b) { function_context.current_button = b; } return 0; } int builtin_gotomanager(int numargs, BuiltinArg *args) { ButtonValue *bv; WinManager *man, *new; int i; ConsoleDebug(FUNCTIONS, "gotomanager: "); print_args(numargs, args); bv = &args[0].value.button_value; new = man = get_current_man(); switch (bv->base) { case NoButton: ConsoleMessage("gotomanager: need a manager argument\n"); return 1; case SelectButton: case FocusButton: ConsoleMessage( "gotomanager: \"select\" or \"focus\" does not specify" " a manager\n"); break; case AbsoluteButton: { /* Now we find the manager modulo the VISIBLE managers */ static WinManager **wa = NULL; int i, num_mapped, n; n = globals.num_managers; if (n) { if (wa == NULL) { wa = (WinManager **)safemalloc( n * sizeof(WinManager *)); } for (i = 0, num_mapped = 0; i < n; i++) { if (globals.managers[i].buttons.num_windows > 0 && globals.managers[i].window_mapped) { wa[num_mapped++] = &globals.managers[i]; } } if (num_mapped) { i = bv->offset % num_mapped; if (i < 0) { i += num_mapped; } new = wa[i]; } else { new = NULL; } } } break; case NextButton: if (man) { for (i = man->index + 1, new = man + 1; i < globals.num_managers && new->buttons.num_windows == 0; i++, new++) { ; } if (i == globals.num_managers) { new = man; } } break; case PrevButton: if (man) { for (i = man->index - 1, new = man - 1; i > -1 && new->buttons.num_windows == 0; i--, new--) { ; } if (i == -1) { new = man; } } break; default: ConsoleMessage("gotomanager: bad argument\n"); break; } if (new && new != man && new->buttons.num_windows > 0) { function_context.current_button = new->buttons.buttons[0]; } return 0; } int builtin_select(int numargs, BuiltinArg *args) { WinManager *man = get_current_man(); if (man) { move_highlight(man, get_current_button()); if (get_current_button()) { run_binding(man, SELECT); } } return 0; } int builtin_sendcommand(int numargs, BuiltinArg *args) { WinData *win = get_current_win(); char *command, *tmp; Button *current_button; rectangle r; Window tmpw; if (!win) { return 0; } command = args[0].value.string_value; current_button = win->manager->select_button; r.x = current_button->x; r.y = current_button->y; r.width = current_button->w; r.height = current_button->h; XTranslateCoordinates(theDisplay, win->manager->theWindow, theRoot, r.x, r.y, &r.x, &r.y, &tmpw); tmp = module_expand_action( theDisplay, theScreen, command, &r, NULL, NULL); if (tmp) { command = tmp; } SendFvwmPipe(fvwm_fd, command, win->app_id); if (tmp) { free(tmp); } return 0; } int builtin_printdebug(int numargs, BuiltinArg *args) { int i; for (i = 0; i < globals.num_managers; i++) { ConsoleDebug(FUNCTIONS, "Manager %d\n---------\n", i); ConsoleDebug(FUNCTIONS, "Keys:\n"); print_bindings(globals.managers[i].bindings[KEYPRESS]); ConsoleDebug(FUNCTIONS, "Mice:\n"); print_bindings(globals.managers[i].bindings[MOUSE]); ConsoleDebug(FUNCTIONS, "Select:\n"); print_bindings(globals.managers[i].bindings[SELECT]); ConsoleDebug(FUNCTIONS, "\n"); } return 0; } int builtin_quit(int numargs, BuiltinArg *args) { ConsoleDebug(FUNCTIONS, "quit: "); print_args(numargs, args); ShutMeDown(0); return 0; } static void do_jmp(int off) { int i; ConsoleDebug(FUNCTIONS, "jmp: %d\n", off); if (off < 0) { ConsoleMessage("Can't have a negative relative jump offset\n"); return; } for (i = 0; i < off; i++) { if (function_context.fp) { function_context.fp = function_context.fp->next; } } } static int eval_if(ButtonValue *bv) { Button *cur; WinManager *man; switch (bv->base) { case NoButton: ConsoleMessage("Internal error in eval_if: 1\n"); break; case SelectButton: if (get_select_button()) { return 1; } break; case FocusButton: if (get_focus_button()) { return 1; } break; case AbsoluteButton: if (bv->offset != 0) { return 1; } break; default: cur = get_current_button(); man = get_current_man(); if (!cur || !man) { return 0; } switch (bv->base) { case UpButton: return (button_above(man, cur) != cur); case DownButton: return (button_below(man, cur) != cur); case LeftButton: return (button_left(man, cur) != cur); case RightButton: return (button_right(man, cur) != cur); case NextButton: return (button_next(man, cur) != cur); case PrevButton: return (button_prev(man, cur) != cur); default: ConsoleMessage("Internal error in eval_if: 2\n"); break; } } return 0; } int builtin_bif(int numargs, BuiltinArg *args) { int off = args[1].value.int_value; ConsoleDebug(FUNCTIONS, "bif: off = %d\n", off); if (eval_if(&args[0].value.button_value)) { do_jmp(off); } return 0; } int builtin_bifn(int numargs, BuiltinArg *args) { int off = args[1].value.int_value; ConsoleDebug(FUNCTIONS, "bifn: off = %d\n", off); if (eval_if(&args[0].value.button_value) == 0) { do_jmp(off); } return 0; } int builtin_jmp(int numargs, BuiltinArg *args) { int off = args[0].value.int_value; ConsoleDebug(FUNCTIONS, "jmp: off = %d\n", off); do_jmp(off); return 0; } int builtin_ret(int numargs, BuiltinArg *args) { function_context.fp = NULL; return 0; } int builtin_print(int numargs, BuiltinArg *args) { char *s, buf[256]; ConsoleDebug(FUNCTIONS, "print: %s\n", args[0].value.string_value); s = args[0].value.string_value; if (strlen(s) > 250) { ConsoleMessage("String too long\n"); } else { sprintf(buf, "%s\n", s); ConsoleMessage(buf); } return 0; } int builtin_searchforward(int numargs, BuiltinArg *args) { char *s; Button *b, *cur; WinManager *man; s = args[0].value.string_value; ConsoleDebug(FUNCTIONS, "searchforward: %s\n", s); cur = get_current_button(); man = get_current_man(); b = cur; if (cur) { while (1) { if (cur->drawn_state.display_string && matchWildcards( s, cur->drawn_state.display_string)) { break; } b = button_next(man, cur); if (b == cur) { cur = NULL; break; } cur = b; } } if (cur) { function_context.current_button = cur; } return 0; } int builtin_searchback(int numargs, BuiltinArg *args) { char *s; Button *b, *cur; WinManager *man; s = args[0].value.string_value; ConsoleDebug(FUNCTIONS, "searchback: %s\n", s); cur = get_current_button(); man = get_current_man(); b = cur; if (cur) { while (1) { if (cur->drawn_state.display_string && matchWildcards( s, cur->drawn_state.display_string)) { break; } b = button_prev(man, cur); if (b == cur) { cur = NULL; break; } cur = b; } } if (cur) { function_context.current_button = cur; } return 0; } int builtin_warp(int numargs, BuiltinArg *args) { Button *cur; WinManager *man; int x, y; ConsoleDebug(FUNCTIONS, "warp\n"); cur = get_current_button(); if (cur) { man = get_current_man(); x = cur->x + cur->w / 2; y = cur->y + cur->h / 2; FWarpPointer( theDisplay, None, man->theWindow, 0, 0, 0, 0, x, y); } return 0; } int builtin_refresh(int numargs, BuiltinArg *args) { draw_managers(); return 0; }