
/****************************************************************************
 * This module is all original code 
 * by Rob Nation 
 * Copyright 1993, Robert Nation
 *     You may use this code for any purpose, as long as the original
 *     copyright remains in the source code and all documentation
 ****************************************************************************/

/***********************************************************************
 *
 * fvwm built-in functions
 *
 ***********************************************************************/

#include <FVWMconfig.h>

#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>

#include "fvwm.h"
#include "menus.h"
#include "misc.h"
#include "parse.h"
#include "screen.h"
#include "module.h"

extern XEvent Event;
extern FvwmWindow *Tmp_win;
extern int menuFromFrameOrWindowOrTitlebar;
Bool desperate;

struct functions func_config[] =
{
  {"AddToMenu",    add_item_to_menu, F_ADDMENU,             FUNC_NO_WINDOW},
  {"AddToFunc",    add_item_to_func, F_ADDFUNC,             FUNC_NO_WINDOW},
  {"AddModuleConfig",  AddModConfig, F_ADD_MOD,             FUNC_NO_WINDOW},
  {"Beep",         Bell,             F_BEEP,                FUNC_NO_WINDOW},
  {"ButtonStyle",  ButtonStyle,      F_BUTTON_STYLE,        FUNC_NO_WINDOW},
  {"ClickTime",    SetClick,         F_CLICK,               FUNC_NO_WINDOW},
  {"Close",        close_function,   F_CLOSE,               FUNC_NEEDS_WINDOW},
  {"ColormapFocus",SetColormapFocus, F_COLORMAP_FOCUS,      FUNC_NO_WINDOW},
  {"CursorMove",   movecursor,       F_MOVECURSOR,          FUNC_NO_WINDOW},
  {"DefaultColors",SetStdColor,      F_BORDERCOLOR,         FUNC_NO_WINDOW},
  {"Delete",       delete_function,  F_DELETE,              FUNC_NEEDS_WINDOW},
  {"DesktopSize",  SetDeskSize,       F_SETDESK,            FUNC_NO_WINDOW},
  {"Desk",         changeDesks_func, F_DESK,                FUNC_NO_WINDOW},
  {"DestroyFunc",  destroy_menu,     F_DESTROY_MENU,        FUNC_NO_WINDOW},
  {"DestroyMenu",  destroy_menu,     F_DESTROY_MENU,        FUNC_NO_WINDOW},
  {"DestroyModuleConfig", DestroyModConfig, F_DESTROY_MOD,  FUNC_NO_WINDOW},
  {"Destroy",      destroy_function, F_DESTROY,             FUNC_NEEDS_WINDOW},
  {"EdgeScroll",   SetEdgeScroll,    F_EDGE_SCROLL,         FUNC_NO_WINDOW},
  {"EdgeResistance",SetEdgeResistance,F_EDGE_RES,           FUNC_NO_WINDOW},
  {"Exec",         exec_function,    F_EXEC,                FUNC_NO_WINDOW},
  {"ExecUseSHELL", exec_setup,       F_EXEC_SETUP,          FUNC_NO_WINDOW},
  {"Focus",        focus_func,       F_FOCUS,               FUNC_NEEDS_WINDOW},
  {"Function",     ComplexFunction,  F_FUNCTION,            FUNC_NO_WINDOW},
  {"GotoPage",     goto_page_func,   F_GOTO_PAGE,           FUNC_NO_WINDOW},
  {"HilightColors",SetHiColor,       F_HICOLOR,             FUNC_NO_WINDOW},
  {"Iconify",      iconify_function, F_ICONIFY,             FUNC_NEEDS_WINDOW},
  {"IconFont",     LoadIconFont,     F_ICONFONT,            FUNC_NO_WINDOW},
  {"IconPath",     setIconPath,      F_ICON_PATH,           FUNC_NO_WINDOW},
  {"Key",          ParseKeyEntry,    F_KEY,                 FUNC_NO_WINDOW},
  {"Lower",        lower_function,   F_LOWER,               FUNC_NEEDS_WINDOW},
  {"Maximize",     Maximize,         F_MAXIMIZE,            FUNC_NEEDS_WINDOW},
  {"MenuFont",     SetMenuFont,      F_MENUFONT,            FUNC_NO_WINDOW},
  {"MenuColors",   SetMenuColors,    F_MENUCOLORS,          FUNC_NO_WINDOW},
  {"Menu",         staysup_func,     F_STAYSUP,             FUNC_POPUP},
  {"ModulePath",   setModulePath,    F_MODULE_PATH,         FUNC_NO_WINDOW},
  {"Module",       executeModule,    F_MODULE,              FUNC_NO_WINDOW},
  {"Mouse",        ParseMouseEntry,  F_MOUSE,               FUNC_NO_WINDOW},
  {"Move",         move_window,      F_MOVE,                FUNC_NEEDS_WINDOW},
  {"Nop",          Nop_func,         F_NOP,                 FUNC_NOP},
  {"Next",         NextFunc,         F_NEXT,                FUNC_NO_WINDOW},
  {"None",         NoneFunc,         F_NONE,                FUNC_NO_WINDOW},
  {"OpaqueMoveSize", SetOpaque,      F_OPAQUE,              FUNC_NO_WINDOW},
  {"PipeRead",     PipeRead,         F_READ,                FUNC_NO_WINDOW},
#ifdef XPM
  {"PixmapPath",   setPixmapPath,    F_PIXMAP_PATH,         FUNC_NO_WINDOW},
#endif
  {"PopUp",        popup_func,       F_POPUP,               FUNC_POPUP},
  {"Prev",         PrevFunc,         F_PREV,                FUNC_NO_WINDOW},
  {"Quit",         quit_func,        F_QUIT,                FUNC_NO_WINDOW},
  {"QuitScreen",   quit_screen_func, F_QUIT_SCREEN,         FUNC_NO_WINDOW},
  {"Raise_it",     raise_it_func,    F_RAISE_IT,            FUNC_NO_WINDOW},
  {"RaiseLower",   raiselower_func,  F_RAISELOWER,          FUNC_NEEDS_WINDOW},
  {"Raise",        raise_function,   F_RAISE,               FUNC_NEEDS_WINDOW},
  {"Read",         ReadFile,         F_READ,                FUNC_NO_WINDOW},
  {"Recapture",    Recapture,        F_RECAPTURE,           FUNC_NO_WINDOW},
  {"Refresh",      refresh_function, F_REFRESH,             FUNC_NO_WINDOW},
  {"Resize",       resize_window,    F_RESIZE,              FUNC_NEEDS_WINDOW},
  {"Restart",      restart_function, F_RESTART,             FUNC_NO_WINDOW},
  {"KillModule",   module_zapper,    F_ZAP,                 FUNC_NO_WINDOW},
  {"Scroll",       scroll,           F_SCROLL,              FUNC_NO_WINDOW},
  {"SendToModule", SendStrToModule,  F_SEND_STRING,         FUNC_NO_WINDOW},
  {"Send_ConfigInfo",SendDataToModule, F_CONFIG_LIST,       FUNC_NO_WINDOW},
  {"Send_WindowList",send_list_func, F_SEND_WINDOW_LIST,    FUNC_NO_WINDOW},
  {"set_mask",     set_mask_function,F_SET_MASK,            FUNC_NO_WINDOW},
  {"StickyColors", SetStickyColor,   F_STICKYCOLOR,         FUNC_NO_WINDOW},
  {"Stick",        stick_function,   F_STICK,               FUNC_NEEDS_WINDOW},
  {"Style",        ProcessNewStyle,  F_STYLE,               FUNC_NO_WINDOW},
  {"Title",        Nop_func,         F_TITLE,               FUNC_TITLE},
  {"Wait",         wait_func,        F_WAIT,                FUNC_NO_WINDOW},
  {"WarpToWindow", warp_func,        F_WARP,                FUNC_NEEDS_WINDOW},
  {"WindowFont",   LoadWindowFont,   F_WINDOWFONT,          FUNC_NO_WINDOW},
  {"WindowList",   do_windowList,    F_WINDOWLIST,          FUNC_NO_WINDOW},
  {"WindowsDesk",  changeWindowsDesk,F_CHANGE_WINDOWS_DESK, FUNC_NEEDS_WINDOW},
  {"XORValue",     SetXOR,           F_XOR,                 FUNC_NO_WINDOW},
  {"+",            add_another_item, F_ADDMENU2,            FUNC_NO_WINDOW},
  {"",                    0,0}
};
  


/***********************************************************************
 *
 *  Procedure:
 *	ExecuteFunction - execute a fvwm built in function
 *
 *  Inputs:
 *	func	- the function to execute
 *	action	- the menu action to execute 
 *	w	- the window to execute this function on
 *	tmp_win	- the fvwm window structure
 *	event	- the event that caused the function
 *	context - the context in which the button was pressed
 *      val1,val2 - the distances to move in a scroll operation 
 *
 ***********************************************************************/
void ExecuteFunction(char *Action, FvwmWindow *tmp_win, XEvent *eventp,
		     unsigned long context, int Module)
{
  Window w;
  int matched,j;
  char *function;
  char *action, *taction;
  char *arguments[10];

  for(j=0;j<10;j++)
    arguments[j] = NULL;

  if(tmp_win == NULL)
    w = Scr.Root;
  else
    w = tmp_win->w;

  if((tmp_win) &&(eventp))
    w = eventp->xany.window;
  if((tmp_win)&&(eventp->xbutton.subwindow != None)&&
     (eventp->xany.window != tmp_win->w))
    w = eventp->xbutton.subwindow;

  taction = expand(Action,arguments,tmp_win);
  action = GetNextToken(taction,&function);
  j=0;
  matched = FALSE;

  while((!matched)&&(strlen(func_config[j].keyword)>0))
    {
      if(strcasecmp(function,func_config[j].keyword)==0)
	{
	  matched=TRUE;
	  /* found key word */
	  func_config[j].action(eventp,w,tmp_win,context,action, &Module);
	}
      else
	j++;
    }

  if(!matched)
    {
      desperate = 1;
      ComplexFunction(eventp,w,tmp_win,context,taction, &Module);
      if(desperate)
	executeModule(eventp,w,tmp_win,context,taction, &Module);
      desperate = 0;
    }
  
  /* Only wait for an all-buttons-up condition after calls from
   * regular built-ins, not from complex-functions or modules. */
  if(Module == -1)
    WaitForButtonsUp();

  free(function);
  if(taction != NULL)
    free(taction);
  return;
}




int find_func_type(char *action)
{
  int j;
  Bool matched;
  j=0;
  matched = FALSE;
  while((!matched)&&(strlen(func_config[j].keyword)>0))
    {
      if(strncasecmp(action,func_config[j].keyword,
		       strlen(func_config[j].keyword))==0)
	{
	  matched=TRUE;
	  /* found key word */
	  return (int)func_config[j].code;
	}
      else
	j++;
    }
  /* No clue what the function is. Just return "BEEP" */
  return F_BEEP;
}
