/*
 * function.cc
 *
 * Copyright (C) 1995, 1996, 1997, 1997, 1998, 1999, 2000, 2001, 2002 Kenichi Kourai
 * Copyright (C) 1999, 2000, 2001, 2002 Luiz Blanes
 *
 * 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 blwm; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#ifdef __EMX__
#include <process.h>
#endif
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/xpm.h>
#include "main.h"
#include "misc.h"
#include "function.h"
#include "blwm.h"
#include "menu.h"
#include "startmenu.h"
#include "fbutton.h"
#include "parse.h"
#include "event.h"
#include "switcher.h"
#include "blwmrc.h"
#include "exit_dialog.h"
#include "confirm_dialog.h"
#include "paging.h"
#include "pager.h"
#include "icon.h"
#include "focus_mgr.h"
#include "desktop.h"
#include "gnome.h"
#include "hash.h"

/* XXX */
KeyCode swCode;
unsigned int swMod;

 Bool BlFunction::execFunction(FuncNumber fn, Menu* menu, int index)
  {
   if (index < 0 || index >= menu->GetItemNum()) {
  BlwmError("invalid menu item index: %d", index);
  return True;
   }
  
    switch (fn) {
/*
* Extract the menu.
*/
   case Q_DIR:
    menu->ExtractChildMenu(index);
    break;
  
/*
* Execute the external command.
*/
   case Q_EXEC:
    menu->ExecIndexedItem(index);
    break;
  
    default:
    return execFunction(fn, menu);
 }
  
    return True;
 }
  
// functions for a menu or the selected menu item
Bool BlFunction::execFunction(FuncNumber fn, Menu* menu)
{
  Window junkRoot, junkChild;
  Point ptRoot, ptJunk;
  unsigned int mask;
  int borderWidth, topBorder, titleHeight, titleEdge;
  Rect rect;

  ASSERT(menu);

  switch (fn) {
/*
* Popup the menu.
*/
  case Q_POPUP_MENU:
    if (!menu->CheckMapped()) {
   Blwm* blWm = menu->GetBlwm();

   Menu::UnmapAllMenus();

   if (blWm == rootBlwm) {
    XQueryPointer(display, root, &junkRoot, &junkChild,
		      &ptRoot.x, &ptRoot.y, &ptJunk.x, &ptJunk.y, &mask);
	menu->MapMenu(ptRoot.x, ptRoot.y);
}
   else {
	blWm->GetBorderAndTitle(borderWidth, topBorder, titleHeight,
				titleEdge);
	rect = blWm->GetRect();
 	menu->MapMenu(rect.x + topBorder, rect.y + topBorder + titleHeight);
   }
 }
 break;
  
/*
* Popdown one menu.
*/
  case Q_POPDOWN_MENU:
 // Erase only one menu.
 menu->UnmapMenu();
 break;

/*
* Move the focus of menu.
*/
   case Q_UP_FOCUS:
    menu->MoveFocusUp();
     break;
    
  case Q_DOWN_FOCUS:
     menu->MoveFocusDown();
     break;

  case Q_RIGHT_FOCUS:
     menu->MoveFocusRight();
     break;
 
  case Q_LEFT_FOCUS:
     menu->MoveFocusLeft();
     break;
     
/*
* Execute the function of the menu item.
*/
  case Q_ACTION:
     menu->ExecSelectedItem();
     break;

   default:
     return execFunction(fn, menu->GetBlwm());
   }
 
   return True;
 }
  
 Bool BlFunction::execFunction(FuncNumber fn, Blwm* blWm)
 {
   Point pt, ptJunk;
   Rect rect;
   Window junkRoot, junkChild;
   unsigned int mask;
 
   ASSERT(blWm);
 
   Menu::UnmapAllMenus();
 
   switch (fn) {
/*
* Restore the window pos & size.
*/
    case Q_RESTORE:
    if (blWm->CheckStatus(MAXIMIZE_WINDOW) &&
	!blWm->CheckStatus(MINIMIZE_WINDOW)) {
      ASSERT(blWm->fButton[1]);
      blWm->fButton[1]->ChangeImage(FrameButton::MAXIMIZE);
    }
    blWm->RestoreWindow();

    /*
     * After mapped, give the focus to blWm.
     */
    rootBlwm->SetFocus();
    blWm->SetFocus();
    break;

  /*
   * Move the window.
   */
  case Q_MOVE:
    rect = blWm->GetRect();
    XDefineCursor(display, root, cursor[MOVE]);
    XQueryPointer(display, root, &junkRoot, &junkChild, &pt.x, &pt.y,
		  &ptJunk.x, &ptJunk.y, &mask);
    blWm->SetStatus(PRESS_FRAME);
    blWm->MoveWindow(pt, False);
    XDefineCursor(display, root, cursor[SYS]);
    break;

  /*
   * Resize the window.
   */
  case Q_RESIZE:
    rect = blWm->GetRect();
    XDefineCursor(display, root, cursor[MOVE]);
    XQueryPointer(display, root, &junkRoot, &junkChild, &pt.x, &pt.y,
		  &ptJunk.x, &ptJunk.y, &mask);
    blWm->SetStatus(PRESS_FRAME);
    blWm->ResizeWindow(0, False);
    XDefineCursor(display, root, cursor[SYS]);
    break;

  /*
   * Minimize the window.
   */
  case Q_MINIMIZE:
    blWm->MinimizeWindow();
    break;

  /*
   * Maximize the window.
   */
  case Q_MAXIMIZE:
    ASSERT(blWm->fButton[1]);
    blWm->fButton[1]->ChangeImage(FrameButton::RESTORE);
    blWm->MaximizeWindow();
    rootBlwm->SetFocus();
    blWm->SetFocus();
    break;

  /*
   * Expand the window "in place" without obscuring other windows
   */
  case Q_EXPAND:
    blWm->ExpandWindow(EXPAND_LEFT | EXPAND_RIGHT | EXPAND_UP | EXPAND_DOWN);
    rootBlwm->SetFocus();
    blWm->SetFocus();
    break;

  case Q_EXPAND_LEFT:
    blWm->ExpandWindow(EXPAND_LEFT);
    rootBlwm->SetFocus();
    blWm->SetFocus();
    break;

  case Q_EXPAND_RIGHT:
    blWm->ExpandWindow(EXPAND_RIGHT);
    rootBlwm->SetFocus();
    blWm->SetFocus();
    break;

  case Q_EXPAND_UP:
    blWm->ExpandWindow(EXPAND_UP);
    rootBlwm->SetFocus();
    blWm->SetFocus();
    break;

  case Q_EXPAND_DOWN:
    blWm->ExpandWindow(EXPAND_DOWN);
    rootBlwm->SetFocus();
    blWm->SetFocus();
    break;

  /*
   * Close the window.
   */
  case Q_CLOSE:
    if (blWm == rootBlwm) {
       BlFunction::execFunction(Q_EXIT);
     }
     else {
       blWm->FetchWMProtocols();
       if (blWm->CheckFlags(WM_DELETE_WINDOW))
 	blWm->CloseWindow();
       else
 	blWm->KillClient();
    }
    break;

  /*
   * Kill the application.
   */
  case Q_KILL:

     if (blWm != rootBlwm)
    blWm->KillClient();
     break;
 
   /*
    * Raise a window
    */
   case Q_RAISE:
     blWm->RaiseWindow(True);
     break;
     
   /*
    * Lower a window
    */
   case Q_LOWER:
     blWm->LowerWindow();
     break;
 
   /*
    * Toggle switch of an ONTOP attribute
    */
   case Q_TOGGLE_ONTOP:
     if (blWm != rootBlwm) {
       if (blWm->CheckFlags(ONTOP)) {
 	blWm->ResetFlags(ONTOP);
 	desktop.GetOnTopList().Remove(blWm);
 	Gnome::ChangeLayer(blWm, WIN_LAYER_NORMAL);
       }
       else {
 	blWm->SetFlags(ONTOP);
 	desktop.GetOnTopList().InsertTail(blWm);
 	Gnome::ChangeLayer(blWm, WIN_LAYER_ONTOP);
       }
     }
     break;
 
   case Q_TOGGLE_STICKY:
     if (blWm != rootBlwm) {
       if (blWm->CheckFlags(STICKY)) {
 	blWm->ResetFlags(STICKY);
 	blWm->ConfigureNewRect(blWm->GetRect());
 	Gnome::ResetState(blWm, WIN_STATE_STICKY);
       }
       else {
 	blWm->SetFlags(STICKY);
 	blWm->ConfigureNewRect(blWm->GetRect());
 	Gnome::SetState(blWm, WIN_STATE_STICKY);
       }
     }
     break;

   case Q_TOGGLE_BORDER:
     if (blWm != rootBlwm) {
       if (blWm->CheckFlags(BORDER)) {
 	blWm->ResetFlags(BORDER);
 	blWm->ConfigureNewRect(blWm->GetRect());
        blWm->MinimizeWindow();
 	blWm->RestoreWindow ();
       }
       else {
 	blWm->SetFlags(BORDER);
 	blWm->ConfigureNewRect(blWm->GetRect());
	blWm->MinimizeWindow();
 	blWm->RestoreWindow ();
       }
     }
     break;
 
   case Q_TOGGLE_BORDER_EDGE:
     if (blWm != rootBlwm) {
       if (blWm->CheckFlags(BORDER_EDGE)) {
 	blWm->ResetFlags(BORDER_EDGE);
 	blWm->ConfigureNewRect(blWm->GetRect());
	blWm->MinimizeWindow();
 	blWm->RestoreWindow ();
       }
       else {
 	blWm->SetFlags(BORDER_EDGE);
 	blWm->ConfigureNewRect(blWm->GetRect());
	blWm->MinimizeWindow();
 	blWm->RestoreWindow ();
       }
     }
     break;
 
   case Q_TOGGLE_BUTTON1:
     if (blWm != rootBlwm) {
       if (blWm->CheckFlags(BUTTON1)) {
 	blWm->ResetFlags(BUTTON1);
 	blWm->ConfigureNewRect(blWm->GetRect());
        blWm->MinimizeWindow();
 	blWm->RestoreWindow ();
       }
       else {
 	blWm->SetFlags(BUTTON1);
 	blWm->ConfigureNewRect(blWm->GetRect());
        blWm->MinimizeWindow();
 	blWm->RestoreWindow ();
       }
     }
     break;
 
   case Q_TOGGLE_BUTTON2:
     if (blWm != rootBlwm) {
       if (blWm->CheckFlags(BUTTON2)) {
 	blWm->ResetFlags(BUTTON2);
 	blWm->ConfigureNewRect(blWm->GetRect());
	blWm->MinimizeWindow();
 	blWm->RestoreWindow ();
       }
       else {
 	blWm->SetFlags(BUTTON2);
 	blWm->ConfigureNewRect(blWm->GetRect());
        blWm->MinimizeWindow();
 	blWm->RestoreWindow ();
       }
     }
     break;
 
   case Q_TOGGLE_BUTTON3:
     if (blWm != rootBlwm) {
       if (blWm->CheckFlags(BUTTON3)) {
 	blWm->ResetFlags(BUTTON3);
 	blWm->ConfigureNewRect(blWm->GetRect());
	blWm->MinimizeWindow();
 	blWm->RestoreWindow ();
       }
       else {
 	blWm->SetFlags(BUTTON3);
 	blWm->ConfigureNewRect(blWm->GetRect());
	blWm->MinimizeWindow();
 	blWm->RestoreWindow ();
       }
     }
     break;
 
   case Q_TOGGLE_CTRLBTN:
     if (blWm != rootBlwm) {
       if (blWm->CheckFlags(CTRL_MENU)) {
 	blWm->ResetFlags(CTRL_MENU);
 	blWm->ConfigureNewRect(blWm->GetRect());
        blWm->MinimizeWindow();
 	blWm->RestoreWindow ();
       }
       else {
 	blWm->SetFlags(CTRL_MENU);
 	blWm->ConfigureNewRect(blWm->GetRect());
        blWm->MinimizeWindow();
 	blWm->RestoreWindow ();
       }
     }
     break;
 
   case Q_TOGGLE_FOCUS:
     if (blWm != rootBlwm) {
       if (blWm->CheckFlags(NO_FOCUS)) {
 	blWm->ResetFlags(NO_FOCUS);
 	blWm->ConfigureNewRect(blWm->GetRect());
        blWm->MinimizeWindow();
 	blWm->RestoreWindow ();
       }
       else {
 	blWm->SetFlags(NO_FOCUS);
 	blWm->ConfigureNewRect(blWm->GetRect());
        blWm->MinimizeWindow();
 	blWm->RestoreWindow ();
       }
     }
     break;
 
   case Q_TOGGLE_TBUTTON:
     if (blWm != rootBlwm) {
       if (blWm->CheckFlags(NO_TBUTTON)) {
 	blWm->ResetFlags(NO_TBUTTON);
 	blWm->ConfigureNewRect(blWm->GetRect());
	blWm->MinimizeWindow();
 	blWm->RestoreWindow ();
       }
       else {
 	blWm->SetFlags(NO_TBUTTON);
 	blWm->ConfigureNewRect(blWm->GetRect());
	blWm->MinimizeWindow();
 	blWm->RestoreWindow ();
       }
     }
     break;
 
   case Q_TOGGLE_TITLE:
     if (blWm != rootBlwm) {
       if (blWm->CheckFlags(TITLE)) {
 	blWm->ResetFlags(TITLE);
 	blWm->ConfigureNewRect(blWm->GetRect());
	blWm->MinimizeWindow();
 	blWm->RestoreWindow ();
       }
       else {
 	blWm->SetFlags(TITLE);
 	blWm->ConfigureNewRect(blWm->GetRect());
	blWm->MinimizeWindow();
 	blWm->RestoreWindow ();
       }
     }
     break;
 
   default:
     return execFunction(fn);
   }
 
   return True;
 }
 
 Bool BlFunction::execFunction(FuncNumber fn)
 {
   Rect rect;
 
   Menu::UnmapAllMenus(False);
 
   switch (fn) {
/*
* Do nothing.
*/
   case Q_NONE:
     break;
 
/*
* Exit blwm.
*/
  case Q_EXIT:
    if (!UseExitDialog) {
      if (UseConfirmDialog) {
	if (confirmDlg == NULL)
	  confirmDlg = new ConfirmDialog();
	confirmDlg->MapDialog();
	confirmDlg->ProcessDialog();
      }
      else
	FinishBlwm();
    }
    else {
      if (exitDlg == NULL)
	exitDlg = new ExitDialog();
      exitDlg->MapDialog();
      exitDlg->ProcessDialog();
    }
    break;

/*
* Restart blwm.
*/
   case Q_RESTART:
     RestartBlwm();
     break;
  
/*
* Switch the task to another task with the task switcher.
*/
   case Q_SWITCH_TASK:
     if (taskSwitcher == NULL)
     taskSwitcher = new TaskSwitcher();
     taskSwitcher->SwitchTask(True, swCode, swMod);
     break;
  
/*
* Switch back the task to another task with the task switcher.
*/
   case Q_SWITCH_TASK_BACK:
     if (taskSwitcher == NULL)
     taskSwitcher = new TaskSwitcher();
     taskSwitcher->SwitchTask(False, swCode, swMod);
     break;

/*
* Switch the window to next window in focus stack.
*/
   case Q_CHANGE_WINDOW:
    focusMgr.RollFocus(True);
    break;

  case Q_CHANGE_WINDOW_BACK:
    focusMgr.RollFocus(False);
    break;

  case Q_CHANGE_WINDOW_INSCR:
    focusMgr.RollFocusWithinScreen(True);
    break;

  case Q_CHANGE_WINDOW_BACK_INSCR:
    focusMgr.RollFocusWithinScreen(False);
    break;


  case Q_DESKTOP_FOCUS:
     rootBlwm->SetFocus();
     break;

  /*
   * Popup the start menu.
   */
  case Q_POPUP_START_MENU:
    if (startMenu == NULL)
      startMenu = new StartMenu(StartMenuItem);

    if (!startMenu->CheckMapped()) {
      rootBlwm->SetFocus();
      startMenu->MapMenu();
    }
    break;

  /*
   * Popup the desktop menu.
   */
  case Q_POPUP_DESKTOP_MENU:
    rootBlwm->SetFocus();
     BlFunction::execFunction(Q_POPUP_MENU, rootBlwm->ctrlMenu);
      break;
  
    /*
     * Popdown all menu.
     */
    case Q_POPDOWN_ALL_MENU:
     Menu::UnmapAllMenus();
      break;
  
    /*
     * Switch to left virtual page.
     */
    case Q_LEFT_PAGING:
     paging->SwitchPageLeft();
      break;
  
    case Q_RIGHT_PAGING:
     paging->SwitchPageRight();
      break;
  
    case Q_UP_PAGING:
     paging->SwitchPageUp();
      break;
  
    case Q_DOWN_PAGING:
     paging->SwitchPageDown();
     break;
  
     /*
      * Rearrange windows
      */
   case Q_OVERLAP:
     rect = Rect(paging->origin.x, paging->origin.y,
 		rcScreen.width, rcScreen.height);
     desktop.Overlap(True, rect);
     break;
 
   case Q_OVERLAP_INSCR:
     rect = Rect(paging->origin.x, paging->origin.y,
 		rcScreen.width, rcScreen.height);
     desktop.Overlap(False, rect);
     break;
 
   case Q_TILE_HORZ:
     rect = Rect(paging->origin.x, paging->origin.y,
 		rcScreen.width, rcScreen.height);
     desktop.TileHorz(True, rect);
     break;
 
   case Q_TILE_HORZ_INSCR:
     rect = Rect(paging->origin.x, paging->origin.y,
 		rcScreen.width, rcScreen.height);
     desktop.TileHorz(False, rect);
  break;
 
   case Q_TILE_VERT:
     rect = Rect(paging->origin.x, paging->origin.y,
 		rcScreen.width, rcScreen.height);
     desktop.TileVert(True, rect);
  break;
 
   case Q_TILE_VERT_INSCR:
  rect = Rect(paging->origin.x, paging->origin.y,
 		rcScreen.width, rcScreen.height);
     desktop.TileVert(False, rect);
  break;
  
   case Q_MINIMIZE_ALL:
     desktop.MinimizeAll(True);
     break;
 
   case Q_MINIMIZE_ALL_INSCR:
  rect = Rect(paging->origin.x, paging->origin.y,
 		rcScreen.width, rcScreen.height);
     desktop.MinimizeAll(False, rect);
  break;
 
   case Q_RESTORE_ALL:
     desktop.RestoreAll(True);
     break;
 
   case Q_RESTORE_ALL_INSCR:
  rect = Rect(paging->origin.x, paging->origin.y,
 		rcScreen.width, rcScreen.height);
     desktop.RestoreAll(False, rect);
  break;
 
   case Q_CLOSE_ALL:
     desktop.CloseAll(True);
     break;
 
   case Q_CLOSE_ALL_INSCR:
  rect = Rect(paging->origin.x, paging->origin.y,
 		rcScreen.width, rcScreen.height);
     desktop.CloseAll(False, rect);
  break;
 
/*
    * Move taskbar.
 */
   case Q_BOTTOM:
     if (UseTaskbar && !DisableDesktopChange)
       taskBar->MoveTaskbar(Taskbar::BOTTOM);
     break;
 
   case Q_TOP:
     if (UseTaskbar && !DisableDesktopChange)
       taskBar->MoveTaskbar(Taskbar::TOP);
  break;
 
   case Q_LEFT:
     if (UseTaskbar && !DisableDesktopChange)
       taskBar->MoveTaskbar(Taskbar::LEFT);
     break;
 
   case Q_RIGHT:
     if (UseTaskbar && !DisableDesktopChange)
       taskBar->MoveTaskbar(Taskbar::RIGHT);
     break;
 
   case Q_TOGGLE_TASKBAR:
     if (UseTaskbar && !DisableDesktopChange) {
       if (enableTaskbar)
 	execFunction(Q_DISABLE_TASKBAR);
       else
 	execFunction(Q_ENABLE_TASKBAR);
  }
  break;
 
   case Q_ENABLE_TASKBAR:
     if (UseTaskbar && !DisableDesktopChange) {
       if (!enableTaskbar) {
 	enableTaskbar = True;
 	taskBar->MapTaskbar();
    }
     }
     break;
 
   case Q_DISABLE_TASKBAR:
     if (UseTaskbar && !DisableDesktopChange) {
       if (enableTaskbar) {
 	enableTaskbar = False;
 	taskBar->UnmapTaskbar();
    }
  }
  break;
 
    case Q_TOGGLE_AUTOHIDE:
     if (UseTaskbar && !DisableDesktopChange) {
       if (TaskbarAutoHide)
 	execFunction(Q_DISABLE_AUTOHIDE);
       else
 	execFunction(Q_ENABLE_AUTOHIDE);
  }
     break;
 
   case Q_ENABLE_AUTOHIDE:
     if (UseTaskbar && !DisableDesktopChange) {
       if (!TaskbarAutoHide) {
 	TaskbarAutoHide = True;
 	rcScreen = taskBar->GetScreenRectOnHiding();
 	taskBar->HideTaskbar();
 	if (UsePager) {
 	  ASSERT(pager);
 	  pager->RecalcPager();
 	}
    }
  }
  break;
 
   case Q_DISABLE_AUTOHIDE:
     if (UseTaskbar && !DisableDesktopChange) {
       if (TaskbarAutoHide) {
 	TaskbarAutoHide = False;
 	if (taskBar->IsHiding())
 	  taskBar->ShowTaskbar();
 	rcScreen = taskBar->GetScreenRectOnShowing();
 	if (UsePager) {
 	  ASSERT(pager);
 	  pager->RecalcPager();
 	}
       }
     }
      break;
 
    case Q_SHOW_TASKBAR:
     if (UseTaskbar && !DisableDesktopChange)
    if (TaskbarAutoHide && taskBar->IsHiding())
 	taskBar->ShowTaskbar();
  break;
 
    case Q_HIDE_TASKBAR:
     if (UseTaskbar && !DisableDesktopChange)
    if (TaskbarAutoHide && !taskBar->IsHiding())
 	taskBar->HideTaskbar();
  break;
  
    case Q_TOGGLE_PAGER:
     if (UsePager && !DisableDesktopChange) {
       if (enablePager)
 	execFunction(Q_DISABLE_PAGER);
       else
 	execFunction(Q_ENABLE_PAGER);
     }
     break;
         
   case Q_ENABLE_PAGER:
     if (UsePager && !DisableDesktopChange) {
       if (!enablePager) {
 	enablePager = True;
 	pager->MapPager();
    }
  }
  break;
 
   case Q_DISABLE_PAGER:
     if (UsePager && !DisableDesktopChange) {
       if (enablePager) {
 	enablePager = False;
 	pager->UnmapPager();
    }
  }
  break;
 
   /*
    * Line up desktop icons
    */ 
   case Q_LINEUP_ICON:
     desktop.LineUpAllIcons();
  break;
 
   default:
     return False;
}
 
   return True;
 }
  
  /*
  * Table for used variables
   */
 static FuncTable funcTable[] =
   {{"BLWM_NONE",			Q_NONE},
    {"BLWM_SEPARATOR",			Q_SEPARATOR},
    // blwm
    {"BLWM_EXIT",			Q_EXIT},
    {"BLWM_RESTART",			Q_RESTART},
    // window
    {"BLWM_MOVE",			Q_MOVE},
    {"BLWM_RESIZE",			Q_RESIZE},
    {"BLWM_MINIMIZE",			Q_MINIMIZE},
    {"BLWM_MAXIMIZE",			Q_MAXIMIZE},
    {"BLWM_RESTORE",			Q_RESTORE},
    {"BLWM_EXPAND",			Q_EXPAND},
    {"BLWM_EXPAND_LEFT",		Q_EXPAND_LEFT},
    {"BLWM_EXPAND_RIGHT",		Q_EXPAND_RIGHT},
    {"BLWM_EXPAND_UP",			Q_EXPAND_UP},
    {"BLWM_EXPAND_DOWN",		Q_EXPAND_DOWN},
    {"BLWM_RAISE",			Q_RAISE},
    {"BLWM_LOWER",			Q_LOWER},
    {"BLWM_CLOSE",			Q_CLOSE},
    {"BLWM_KILL",			Q_KILL},
    {"BLWM_TOGGLE_ONTOP",		Q_TOGGLE_ONTOP},
    {"BLWM_TOGGLE_STICKY",		Q_TOGGLE_STICKY},
    {"BLWM_TOGGLE_FOCUS",		Q_TOGGLE_FOCUS},
    {"BLWM_TOGGLE_BORDER",		Q_TOGGLE_BORDER},
    {"BLWM_TOGGLE_BORDER_EDGE",		Q_TOGGLE_BORDER_EDGE},
    {"BLWM_TOGGLE_BUTTON1",		Q_TOGGLE_BUTTON1},
    {"BLWM_TOGGLE_BUTTON2",		Q_TOGGLE_BUTTON2},
    {"BLWM_TOGGLE_BUTTON3",		Q_TOGGLE_BUTTON3},
    {"BLWM_TOGGLE_CTRLBTN",		Q_TOGGLE_CTRLBTN},
    {"BLWM_TOGGLE_TBUTTON",		Q_TOGGLE_TBUTTON},
    {"BLWM_TOGGLE_TITLE",		Q_TOGGLE_TITLE},
    // window focus
    {"BLWM_SWITCH_TASK",		Q_SWITCH_TASK},
    {"BLWM_SWITCH_TASK_BACK",		Q_SWITCH_TASK_BACK},
    {"BLWM_CHANGE_WIN",			Q_CHANGE_WINDOW},
    {"BLWM_CHANGE_WIN_BACK",		Q_CHANGE_WINDOW_BACK},
    {"BLWM_CHANGE_WIN_INSCR",		Q_CHANGE_WINDOW_INSCR},
    {"BLWM_CHANGE_WIN_BACK_INSCR",	Q_CHANGE_WINDOW_BACK_INSCR},
    {"BLWM_DESKTOP_FOCUS",		Q_DESKTOP_FOCUS},
    // window rearrangement
    {"BLWM_OVERLAP",			Q_OVERLAP},
    {"BLWM_OVERLAP_INSCR",		Q_OVERLAP_INSCR},
    {"BLWM_TILE_HORZ",			Q_TILE_HORZ},
    {"BLWM_TILE_HORZ_INSCR",		Q_TILE_HORZ_INSCR},
    {"BLWM_TILE_VERT",			Q_TILE_VERT},
    {"BLWM_TILE_VERT_INSCR",		Q_TILE_VERT_INSCR},
    {"BLWM_MINIMIZE_ALL",		Q_MINIMIZE_ALL},
    {"BLWM_MINIMIZE_ALL_INSCR",		Q_MINIMIZE_ALL_INSCR},
    {"BLWM_RESTORE_ALL",		Q_RESTORE_ALL},
    {"BLWM_RESTORE_ALL_INSCR",		Q_RESTORE_ALL_INSCR},
    {"BLWM_CLOSE_ALL",			Q_CLOSE_ALL},
    {"BLWM_CLOSE_ALL_INSCR",		Q_CLOSE_ALL_INSCR},
    // menu
    {"BLWM_POPUP_START_MENU",		Q_POPUP_START_MENU},
    {"BLWM_POPUP_DESKTOP_MENU",		Q_POPUP_DESKTOP_MENU},
    {"BLWM_POPUP_MENU",			Q_POPUP_MENU},
    {"BLWM_POPDOWN_MENU",		Q_POPDOWN_MENU},
    {"BLWM_POPDOWN_ALL_MENU",		Q_POPDOWN_ALL_MENU},
    // paging
    {"BLWM_LEFT_PAGING",		Q_LEFT_PAGING},
    {"BLWM_RIGHT_PAGING",		Q_RIGHT_PAGING},
    {"BLWM_UP_PAGING",			Q_UP_PAGING},
    {"BLWM_DOWN_PAGING",		Q_DOWN_PAGING},
    // taskbar
    {"BLWM_BOTTOM",			Q_BOTTOM},
    {"BLWM_TOP",			Q_TOP},
    {"BLWM_LEFT",			Q_LEFT},
    {"BLWM_RIGHT",			Q_RIGHT},
    {"BLWM_TOGGLE_AUTOHIDE",		Q_TOGGLE_AUTOHIDE},
    {"BLWM_ENABLE_AUTOHIDE",		Q_ENABLE_AUTOHIDE},
    {"BLWM_DISABLE_AUTOHIDE",		Q_DISABLE_AUTOHIDE},
    {"BLWM_TOGGLE_TASKBAR",             Q_TOGGLE_TASKBAR},
    {"BLWM_ENABLE_TASKBAR",             Q_ENABLE_TASKBAR},
    {"BLWM_DISABLE_TASKBAR",            Q_DISABLE_TASKBAR},
    {"BLWM_SHOW_TASKBAR",		Q_SHOW_TASKBAR},
    {"BLWM_HIDE_TASKBAR",		Q_HIDE_TASKBAR},
    // pager
    {"BLWM_TOGGLE_PAGER",               Q_TOGGLE_PAGER},
    {"BLWM_ENABLE_PAGER",               Q_ENABLE_PAGER},
    {"BLWM_DISABLE_PAGER",              Q_DISABLE_PAGER},
    // icon
    {"BLWM_LINEUP_ICON",		Q_LINEUP_ICON},
    {"BLWM_EXEC_ICON",			Q_EXEC_ICON},
    {"BLWM_DELETE_ICON",		Q_DELETE_ICON}
   };
 
 Hash<FuncNumber>* BlFunction::funcHashTable;
 const int FuncTableSize = sizeof(funcTable) / sizeof(FuncTable);
 
 void BlFunction::initialize()
 {
   int i;
 
   funcHashTable = new Hash<FuncNumber>(HashTableSize);
 
   for (i = 0; i < FuncTableSize; i++)
     funcHashTable->SetHashItem(funcTable[i].name, &funcTable[i].num);
  
}


syntax highlighted by Code2HTML, v. 0.9.1