/* -*-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;
}
syntax highlighted by Code2HTML, v. 0.9.1