/* winmenu.c - command menu for windows
 * 
 *  WindowMaker window manager
 * 
 *  Copyright (c) 1997 Alfredo K. Kojima
 * 
 *  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., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include "wconfig.h"

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

#include <X11/Xlib.h>
#include <X11/Xutil.h>

#include "generic/wwmlib.h"
#include "WindowMaker.h"
#include "actions.h"
#include "menu.h"
#include "funcs.h" 
#include "window.h"
#include "client.h"
#include "application.h"
#include "keybind.h"

#define MC_MAXIMIZE	0
#define MC_MINIATURIZE	1
#define MC_SHADE	2
#define MC_HIDE		3
#define MC_HIDE_OTHERS	4

/*#define MC_DOCK		5*/

#define MC_CLOSE	5
#define MC_KILL		6
#define MC_LOCK_CMAP	7


#define MC_MOVE		8
#define MC_RESIZE	9
#define MC_PROPERTIES	10

/**** Global data ***/
extern Time LastTimestamp;
extern Atom _XA_WM_DELETE_WINDOW;
extern Atom _XA_GNUSTEP_WM_MINIATURIZE_WINDOW;

extern WShortKey *wKeyBindings[WKBD_LAST];



/* Dirty, ugly, nasty kludge */
static WWindow *TheWindow;
static WApplication *TheApp;

static void
execMenuCommand(WMenu *menu, WMenuEntry *entry)
{
    switch ((int)entry->clientdata) {
     case MC_CLOSE:
	/* send delete message */
	wClientSendProtocol(TheWindow, _XA_WM_DELETE_WINDOW, LastTimestamp);
	break;
     case MC_KILL:
	wClientKill(TheWindow);
	break;
     case MC_MINIATURIZE:
	if (TheWindow->protocols.MINIATURIZE_WINDOW) {
	    wClientSendProtocol(TheWindow, _XA_GNUSTEP_WM_MINIATURIZE_WINDOW,
				LastTimestamp);
	} else {
	    wIconifyWindow(TheWindow);
	}
	break;
     case MC_MAXIMIZE:
	if (TheWindow->flags.maximized)
	  wUnmaximizeWindow(TheWindow);
	else
	  wMaximizeWindow(TheWindow, True);
	break;
     case MC_SHADE:
	if (TheWindow->flags.shaded)
	  wUnshadeWindow(TheWindow);
	else
	  wShadeWindow(TheWindow);
	break;
     case MC_HIDE:
	 wHideApplication(TheApp);
	break;
     case MC_HIDE_OTHERS:
	wHideOtherApplications(TheWindow);
	break;
	/*
     case MC_DOCK:
	{
	    char *args;

	    args = wInputDialog(menu->frame->screen_ptr, 
				_("Dock Application"), 
				_("Enter Command line"), NULL);
	    wfree(args);
	}
	break;
	 */
    }
}




static WMenu*
createWindowMenu(WScreen *scr)
{
    WMenu *menu;
    KeyCode kcode;
    WMenuEntry *entry;
    char *tmp;

    menu = wMenuCreate(scr, NULL, False);
    entry = wMenuAddCallback(menu, _("(Un)Maximize"), execMenuCommand, 
			     (void*)MC_MAXIMIZE);
    entry = wMenuAddCallback(menu, _("Miniaturize"), execMenuCommand, 
			     (void*)MC_MINIATURIZE);
    
    if (wKeyBindings[WKBD_MINIATURIZE]) {
	kcode = wKeyBindings[WKBD_MINIATURIZE]->keycode;
	
	if (kcode && (tmp = XKeysymToString(XKeycodeToKeysym(dpy, kcode, 0))))
	  entry->rtext = strdup(tmp);
    }
    
    entry = wMenuAddCallback(menu, _("(Un)Shade"), execMenuCommand,
			     (void*)MC_SHADE);
    if (wKeyBindings[WKBD_SHADE]) {
	kcode = wKeyBindings[WKBD_SHADE]->keycode;
	
	if (kcode && (tmp = XKeysymToString(XKeycodeToKeysym(dpy, kcode, 0))))
	  entry->rtext = strdup(tmp);
    }
    
    entry = wMenuAddCallback(menu, _("Hide"), execMenuCommand, (void*)MC_HIDE);
    if (wKeyBindings[WKBD_HIDE]) {
	kcode = wKeyBindings[WKBD_HIDE]->keycode;
	
	if (kcode && (tmp = XKeysymToString(XKeycodeToKeysym(dpy, kcode, 0))))
	  entry->rtext = strdup(tmp);
	
    }
    entry = wMenuAddCallback(menu, _("Hide Others"), execMenuCommand, 
			     (void*)MC_HIDE_OTHERS);

    /*    
    entry = wMenuAddCallback(menu, _("Force Dock"), execMenuCommand, 
			     (void*)MC_DOCK);
*/


    entry = wMenuAddCallback(menu, _("Close"), execMenuCommand, 
			     (void*)MC_CLOSE);
    if (wKeyBindings[WKBD_CLOSE]) {
	kcode = wKeyBindings[WKBD_CLOSE]->keycode;
	if (kcode && (tmp = XKeysymToString(XKeycodeToKeysym(dpy, kcode, 0))))
	  entry->rtext = strdup(tmp);
    }
    
    entry = wMenuAddCallback(menu, _("Kill"), execMenuCommand, (void*)MC_KILL);

    
    return menu;
}


void
CloseWindowMenu(WScreen *scr)
{
    if (scr->window_menu && scr->window_menu->flags.mapped)
      wMenuUnmap(scr->window_menu);
}

void
OpenWindowMenu(WWindow *wwin, int x, int y)
{
    WMenu *menu;

    if (!wwin->screen_ptr->window_menu) {
	wwin->screen_ptr->window_menu = createWindowMenu(wwin->screen_ptr);
    }
    menu = wwin->screen_ptr->window_menu;
    if (menu->flags.mapped) {
	wMenuUnmap(menu);
	if (TheWindow==wwin) {
	    return;
	}
    }
    TheWindow = wwin;
    TheApp = wApplicationOf(wwin->main_window);
    
    wMenuSetEnabled(menu, MC_HIDE, TheApp!=NULL);
    wMenuSetEnabled(menu, MC_CLOSE, 
		    (wwin->protocols.DELETE_WINDOW
		     && wwin->window_flags.closable));
    wMenuSetEnabled(menu, MC_MINIATURIZE, wwin->window_flags.miniaturizable);
    wMenuSetEnabled(menu, MC_SHADE, wwin->window_flags.shadeable);
    /*
    if (wwin->wm_class || wwin->wm_instance) {
	if (wwin->main_window == None 
	    || wwin->main_window != wwin->client_win) {
	    wMenuSetEnabled(menu, MC_DOCK, True);
	} else {
	    wMenuSetEnabled(menu, MC_DOCK, False);
	}
    } else {
	wMenuSetEnabled(menu, MC_DOCK, False);
    }
     */
    
    if (!menu->flags.realized)
      wMenuRealize(menu);
    
    x -= menu->frame->width/2;
    if (x + menu->frame->width > wwin->frame_x + wwin->frame->width)
      x = wwin->frame_x + wwin->frame->width - menu->frame->width;
    if (x < wwin->frame_x) 
      x = wwin->frame_x;

    if (!wwin->flags.internal_window &&  !wwin->wm_gnustep_attr)
      wMenuMapAt(menu, x, y);
}
