/*
 * GraphApp - Cross-Platform Graphics Programming Library.
 *
 * File: menus.c -- creating menus, menubars, etc.
 * Platform: Windows  Version: 2.35  Date: 1998/04/04
 *
 * Version: 1.00  Changes: Original version by Lachlan Patrick.
 * Version: 2.00  Changes: New object class system.
 * Version: 2.15  Changes: Added submenu creation function.
 * Version: 2.20  Changes: New menuitem constructor.
 * Version: 2.30  Changes: Modified the shortcut key selector.
 * Version: 2.35  Changes: New reference count technique.
 */

/* Copyright (C) 1993-1998 Lachlan Patrick

   This file is part of GraphApp, a cross-platform C graphics library.

   GraphApp is free software; you can redistribute it and/or modify it
   under the terms of the GNU Library General Public License.
   GraphApp is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY.

   See the file COPYLIB.TXT for details.
*/

/*
 *  When you create menubars, menus and menuitems, they are added
 *  to the currentwindow. Menus are added to the current_menubar and
 *  menuitems are added to the current_menu.
 */

/* Copyright (C) 2004	The R Foundation

   Change for R - Chris Jackson.  Enabled menu shortcut keys, don't
   execute shortcut if menu item is grayed out */

#include "internal.h"
/*#include "config.h" */
#include <wchar.h>
#define mbs_init(x) memset(&x,0,sizeof(x))
size_t Rf_mbrtowc(wchar_t *wc, const char *s, size_t n, mbstate_t *ps);

/*
 *  Menu variables.
 */

	PROTECTED int     menus_active = 1;

	PROTECTED menubar current_menubar = NULL;
	PROTECTED menu    current_menu    = NULL;

	static    int     id = MinMenuID;

	PROTECTED HACCEL hAccel = 0;

/*
 *  Initialise menus. Actually, all we do here is load accelerators.
 *  The accelarator resource must have the name "ACCELS".
 *  If there are no accelerator resources, hAccel will be zero.
 */
PROTECTED
void init_menus(void)
{
    if (this_instance != 0)
	hAccel = LoadAccelerators(this_instance, "ACCELS");
}

/*
 *  Find the position of a menu on its parent menubar.
 *  Return zero for the first menu, one for the next etc.
 */
static int find_menu_position(menu parent, char *name)
{
    menu m, first;
    int which = 0;

    first = m = parent->child;
    if (first) {
	do {
	    if (strcmp(m->text, name) == 0)
		break;
	    which ++;
	    m = m->next;
	} while (m != first);
    }
    return which;
}

/*
 *  Private menu deletion function.
 */
static void private_delmenu(menu m)
{
    window w = parentwindow(m);
    if (m->kind == MenuitemObject)
	RemoveMenu(m->parent->handle, m->id, MF_BYCOMMAND);
    else if (m->kind == MenuObject) {
	DeleteMenu(m->parent->handle,
		   find_menu_position(m->parent, m->text),
		   MF_BYPOSITION);
    }
    else
	DestroyMenu(m->handle);
    if (w)
	DrawMenuBar(w->handle);
}

/*
 *  Find a char within a string.
 *  Return -1 if not found, or a number from 0 to strlen(str)-1
 *  to indicate where the char is.
 */
char *Rf_strchr(const char *s, int c); /* from util.c, MBCS-aware */

static int find_char(int ch, const char *str)
{
    char *p;
    p = Rf_strchr(str, ch);
    if(!p) return -1; else return p - str;
}

/*
 *  This function forms a search string, to look for the best
 *  letter to underline in a menu item. It first tries the
 *  accelerator key, then the uppercase letters from the menu name,
 *  then the digits, and finally the lowercase letters.
 *  It ignores spaces.
 */
static void set_search_string(char *search, const char *name, int key)
{
    int source;
    int dest = 0;
    int mb_len;
    mbstate_t mb_st;

    /* handle a couple of special cases first */
    if (! string_diff(name, "Cut"))  search[dest++] = 't';
    if (! string_diff(name, "Exit")) search[dest++] = 'x';
    if (! string_diff(name, "?")) search[dest++] = '?';

    {
	/* If there is an '&' in the string, use the next letter first */
	char *p = strchr(name, '&');
	if (p && *(p+1)) search[dest++] = *(p+1);
    }

    /* add the accelerator key if it is in the name string */
    if (key) {
	key = toupper(key);
	if (find_char(key, name) >= 0)
	    search[dest++] = (char) key;
	else {
	    key = tolower(key);
	    if (find_char(key, name) >= 0)
		search[dest++] = (char) key;
	}
    }
    /* add the uppercase letters */
    for (source=0; name[source]; source++) {
	mbs_init(mb_st);
	mb_len = Rf_mbrtowc(NULL, name + source, MB_CUR_MAX,&mb_st);
	if (mb_len > 1) source += mb_len-1;
	else
	    if (isupper(name[source])) search[dest++] = name[source];
    }
    /* add the digits */
    for (source=0; name[source]; source++) {
	mbs_init(mb_st);
	mb_len = Rf_mbrtowc(NULL, name + source, MB_CUR_MAX,&mb_st);
	if (mb_len > 1) source += mb_len-1;
	else
	    if (isdigit(name[source])) search[dest++] = name[source];
    }
    /* add the lowercase letters */
    for (source=0; name[source]; source++) {
	mbs_init(mb_st);
	mb_len = Rf_mbrtowc(NULL, name + source, MB_CUR_MAX,&mb_st);
	if (mb_len > 1) source += mb_len-1;
	else
	    if (islower(name[source])) search[dest++] = name[source];
    }
    /* end the search string */
    search[dest] = '\0';
}

/*
 *  Look through the list of siblings of the given object, and
 *  find a shortcut key from the search string which hasn't already
 *  been used by some other object. Return the valid shortcut char,
 *  or else zero if we can't find one.
 */
static int find_shortcut(object me, char *search)
{
    int source;
    object first, obj;

    first = me->parent->child;

    for (source = 0; search[source]; source++)
    {
	int mb_len;
	mbstate_t mb_st;
	mbs_init(mb_st);
	mb_len = Rf_mbrtowc(NULL, search + source, MB_CUR_MAX, &mb_st);
	if ( mb_len > 1 ) {
	    source += mb_len - 1;
	} else
	    /* for each character in the search string */
	    /* look through every sibling object */

	    for (obj = first; obj; obj = obj->next)
	    {
		if (obj == me) /* at end of list, success! */
		    return search[source];

		/* use uppercase comparisons */
		if (obj->shortcut == toupper(search[source]))
		    break; /* can't use this shortcut */

	    }
    }

    return 0;
}

/*
 *  Take "Open..." and 'O' and produce the string "Open...\tCtrl+O".
 *  This function also sets an object's shortcut key, which is the
 *  underlined letter in a menu item in Windows or X-Windows.
 */
static void setmenustring(object obj, char *buf, const char *name, int key)
{
    char search[256];
    int ch, where, source, dest = 0;
    char *extra = "\tCtrl+";

    set_search_string(search, name, key);
    ch = find_shortcut(obj, search);

    if (ch) /* found a valid shortcut key */
    {
	obj->shortcut = toupper(ch); /* case-insensitive */
	where = find_char(ch, name);

	for (source=0; source < where; source++)
	{
	    int mb_len;
	    int i;
	    mbstate_t mb_st;
	    mbs_init(mb_st);
	    mb_len = Rf_mbrtowc(NULL, name + source, MB_CUR_MAX, &mb_st);
	    if ( mb_len > 1 ) {
		for (i = 0 ; i < mb_len ; i++)
		    buf[dest++] = name[source+i];
		source += mb_len-1;
	    } else if(name[source] == '&') {
		/* skip it */
	    } else
		buf[dest++] = name[source];
	}
	buf[dest++] = '&';
	for (; name[source]; source++)
	    buf[dest++] = name[source];
    }
    else /* no shortcut key, just copy the name string except '&' */
    {
	for (source = 0; name[source]; source++)
	    if(name[source] != '&') buf[dest++] = name[source];
    }

    if (key) {
	for (source=0; extra[source]; source++)
	    buf[dest++] = extra[source];
	buf[dest++] = key;
    }

    buf[dest] = '\0';
}

/*
 *  Menu functions.
 */
menubar newmenubar(actionfn adjust_menus)
{
    object obj;
    HMENU hm;

    if (! current_window) {
	current_window = simple_window();
	show(current_window);
    }

    hm = CreateMenu();
    obj = new_object(MenubarObject, hm, current_window);
    if (obj) {
	current_window->menubar = obj;
	obj->menubar = NULL;
	obj->die = private_delmenu;
	obj->id = id++;
	obj->action = adjust_menus;
	obj->text = new_string("Menubar");
	current_menubar = obj;
	SetMenu(current_window->handle, hm);
    }
    return (menubar) obj;
}

BOOL myAppendMenu(HMENU h, UINT flags, UINT_PTR id, LPCTSTR name)
{
    if(localeCP > 0 && (localeCP != GetACP())) {
	wchar_t wc[100];
	mbstowcs(wc, name, 100);
	return AppendMenuW(h, flags, id, wc);
    } else
	return AppendMenuA(h, flags, id, name);
}


menu newsubmenu(menu parent, const char *name)
{
    object obj;
    HMENU hm;
    UINT flags = MF_POPUP;
    char str[256];
    if (! parent) {
	if (! current_menubar)
	    current_menubar = newmenubar(NULL);
	parent = current_menubar;
    }

    if (! parent)
	return NULL;
    if (! name)
	name = "";
    if (name[0] == '\t') {
	name += 1;
	flags |= MF_HELP;
    }

    if (parent->kind == WindowObject)
	hm = CreatePopupMenu();
    else
	hm = CreateMenu();
    obj = new_object(MenuObject, hm, parent);
    if (obj) {
	obj->die = private_delmenu;
	obj->id = id++;
	obj->text = new_string(name);
	setmenustring(obj, str, name, 0);
	name = str;
	current_menu = obj;
    }
    if (parent->kind != WindowObject)
	myAppendMenu(parent->handle, flags, (UINT_PTR) hm, name);
    if (parent == current_menubar)
	DrawMenuBar(current_menubar->parent->handle);

    return (menu) obj;
}

menu newmenu(const char *name)
{
    return newsubmenu(current_menubar, name);
}


menuitem newmenuitem(const char *name, int key, menufn fn)
{
    object obj;
    UINT flags;
    char str[256];

    if (! current_menu)
	current_menu = newmenu("Special");
    if (! current_menu)
	return NULL;
    if (! name)
	name = "-"; /* separator */

    key = toupper(key); /* make it uppercase */

    obj = new_object(MenuitemObject, 0, current_menu);
    if (obj) {
	obj->die = private_delmenu;
	obj->id = id++;
	obj->key = key;
	obj->action = fn;
	obj->value = 0;
	obj->text = new_string(name);
	obj->state |= GA_Enabled;

	if (name[0] == '-') {
	    flags = MF_SEPARATOR;
	    name = NULL;
	} else {
	    flags = MF_STRING;
	    setmenustring(obj, str, name, key);
	    name = str;
	}

	myAppendMenu(current_menu->handle, flags, obj->id, name);
    }
    return (menuitem) obj;
}

/*
 *  Find various parent objects of a menu (or any object).
 */
#if 0
PROTECTED
object parent_menubar(object obj)
{
    while (obj) {
	if (obj->kind == MenubarObject)
	    break;
	obj = obj->parent;
    }
    return obj;
}

PROTECTED
object parent_menu(object obj)
{
    while (obj) {
	if (obj->kind == MenuObject)
	    break;
	obj = obj->parent;
    }
    return obj;
}
#endif

/*
 *  The adjust_menu function is called just after the program
 *  receives a WM_INITMENU message.  This message is sent even if
 *  the user is attempting to use the system menu, which is nice.
 *  We use this function to keep menubars and menus up-to-date by
 *  calling their respective action functions.
 */
PROTECTED
void adjust_menu(WPARAM wParam)
{
    object obj;
    obj = find_by_handle((HANDLE)wParam);
    if (obj) {
	activatecontrol(obj);
	if (obj->kind == MenubarObject)
	    DrawMenuBar(obj->parent->handle);
    }
}

/*
 *  Handle the menu selection. wParam is what WM_[SYS]COMMAND sets
 *  it to i.e. the object id number. The menus will already have
 *  received WM_INITMENU messages so they will be up-to-date.
 */
PROTECTED
void handle_menu_id (WPARAM wParam)
{
    object obj;

    obj = find_by_id(wParam);
    if (obj)
	activatecontrol(obj);
}

/*
 *  Handle a menu accelerator key. The key will be a normal char,
 *  in the range of 0..9 or A..Z (not a..z because we use KEYDOWNs).
 *  Uses a recursive function to call the menu adjustor functions
 *  in order from menubar down to popup menu.
 */

static void adjust_menus_top_down(object obj)
{
    /* Recursively step up the list. */
    if (! obj)
	return;
    adjust_menus_top_down(obj->parent);

    /* Adjust menubar then child menus as we descend. */
    if (obj->kind == MenubarObject) {
	activatecontrol(obj);
	DrawMenuBar(obj->parent->handle);
    }
    else if (obj->kind == MenuObject)
	activatecontrol(obj);
}

/* Only search for the key within the menus of the focused window.
   If key is not found fall through to user's key handler. CJ */

PROTECTED
int handle_menu_key(WPARAM wParam)
{
    object win, obj;
    win = find_by_handle(GetFocus());
    if (win) {
	if (win->kind != WindowObject)
	    win = win->parent;
	obj = find_by_key(win, wParam);
	if (obj) {
	    adjust_menus_top_down(obj);
	    if (isenabled(obj)) /* Don't do menu actions which are greyed out. CJ */
		activatecontrol(obj);
	    return 1;
	}
    }
    return 0;
}
