#include "FvwmIconMan.h" #include "readconfig.h" #include "xmanager.h" static char const rcsid[] = "$Id: functions.c,v 1.2 2021/01/24 09:21:21 matthieu Exp $"; 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 ("gotomanger: \"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(); if (!win) { return 0; } SendFvwmPipe (args[0].value.string_value, win->app_id); 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; 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 { ConsoleMessage ("%s\n", s); } 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; XWarpPointer (theDisplay, None, man->theWindow, 0, 0, 0, 0, x, y); } return 0; } int builtin_refresh (int numargs, BuiltinArg *args) { draw_managers(); return 0; }