300 lines
6.7 KiB
C
300 lines
6.7 KiB
C
|
/* $Id: menu.c,v 1.1 2008-03-27 00:41:33 vsc Exp $
|
||
|
|
||
|
Part of SWI-Prolog
|
||
|
|
||
|
Author: Jan Wielemaker
|
||
|
E-mail: jan@swi.psy.uva.nl
|
||
|
WWW: http://www.swi-prolog.org
|
||
|
Copyright (C): 1985-2002, University of Amsterdam
|
||
|
|
||
|
This library is free software; you can redistribute it and/or
|
||
|
modify it under the terms of the GNU Lesser General Public
|
||
|
License as published by the Free Software Foundation; either
|
||
|
version 2.1 of the License, or (at your option) any later version.
|
||
|
|
||
|
This library 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
|
||
|
Lesser General Public License for more details.
|
||
|
|
||
|
You should have received a copy of the GNU Lesser General Public
|
||
|
License along with this library; if not, write to the Free Software
|
||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||
|
*/
|
||
|
|
||
|
#include <windows.h>
|
||
|
#include <tchar.h>
|
||
|
#define _MAKE_DLL
|
||
|
#include "console.h"
|
||
|
#include "console_i.h"
|
||
|
#include "menu.h"
|
||
|
|
||
|
#ifndef EOS
|
||
|
#define EOS 0
|
||
|
#endif
|
||
|
|
||
|
#define streq(s,q) (_tcscmp((s), (q)) == 0)
|
||
|
|
||
|
static TCHAR **menuids;
|
||
|
static int nmenus;
|
||
|
static int nmenualloc;
|
||
|
|
||
|
static struct rl_item
|
||
|
{ UINT id;
|
||
|
const TCHAR *name;
|
||
|
} rl_items[] =
|
||
|
{ { IDM_EXIT, _T("&Exit") },
|
||
|
{ IDM_CUT, _T("&Cut") },
|
||
|
{ IDM_COPY, _T("&Copy") },
|
||
|
{ IDM_PASTE, _T("&Paste") },
|
||
|
{ IDM_BREAK, _T("&Interrupt") },
|
||
|
{ IDM_FONT, _T("&Font ...") },
|
||
|
{ 0, NULL }
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
static UINT
|
||
|
lookupMenuLabel(const TCHAR *label)
|
||
|
{ int i;
|
||
|
size_t llen;
|
||
|
struct rl_item *builtin;
|
||
|
|
||
|
for(builtin = rl_items; builtin->id; builtin++)
|
||
|
{ if ( streq(builtin->name, label) )
|
||
|
return builtin->id;
|
||
|
}
|
||
|
|
||
|
for(i=0; i<nmenus; i++)
|
||
|
{ if ( streq(menuids[i], label) )
|
||
|
return i + IDM_USER;
|
||
|
}
|
||
|
|
||
|
if ( nmenus + 1 > nmenualloc )
|
||
|
{ if ( nmenualloc )
|
||
|
{ nmenualloc *= 2;
|
||
|
menuids = rlc_realloc(menuids, nmenualloc*sizeof(TCHAR *));
|
||
|
} else
|
||
|
{ nmenualloc = 32;
|
||
|
menuids = rlc_malloc(nmenualloc*sizeof(TCHAR *));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
llen = _tcslen(label);
|
||
|
menuids[nmenus] = rlc_malloc((llen+1)*sizeof(TCHAR));
|
||
|
_tcsncpy(menuids[nmenus], label, llen+1);
|
||
|
|
||
|
return nmenus++ + IDM_USER;
|
||
|
}
|
||
|
|
||
|
const TCHAR *
|
||
|
lookupMenuId(UINT id)
|
||
|
{ struct rl_item *builtin;
|
||
|
|
||
|
if ( id >= IDM_USER && (int)id - IDM_USER < nmenus )
|
||
|
return menuids[id-IDM_USER];
|
||
|
|
||
|
for(builtin = rl_items; builtin->id; builtin++)
|
||
|
{ if ( builtin->id == id )
|
||
|
return builtin->name;
|
||
|
}
|
||
|
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
insertMenu(HMENU in, const TCHAR *label, const TCHAR *before)
|
||
|
{ if ( !before )
|
||
|
{ if ( !label )
|
||
|
AppendMenu(in, MF_SEPARATOR, 0, NULL);
|
||
|
else
|
||
|
{ UINT id = lookupMenuLabel(label);
|
||
|
|
||
|
AppendMenu(in, MF_STRING, id, label);
|
||
|
}
|
||
|
} else
|
||
|
{ UINT bid = lookupMenuLabel(before);
|
||
|
MENUITEMINFO info;
|
||
|
|
||
|
memset(&info, 0, sizeof(info));
|
||
|
info.cbSize = sizeof(info);
|
||
|
info.fMask = MIIM_TYPE;
|
||
|
if ( label )
|
||
|
{ info.fType = MFT_STRING;
|
||
|
info.fMask |= MIIM_ID;
|
||
|
info.wID = lookupMenuLabel(label);
|
||
|
info.dwTypeData = (TCHAR *)label;
|
||
|
info.cch = (int)_tcslen(label);
|
||
|
} else
|
||
|
{ info.fType = MFT_SEPARATOR;
|
||
|
}
|
||
|
|
||
|
InsertMenuItem(in, bid, FALSE, &info);
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||
|
Find popup with given name.
|
||
|
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||
|
|
||
|
static HMENU
|
||
|
findPopup(RlcData b, const TCHAR *name, int *pos)
|
||
|
{ HMENU mb = GetMenu(rlc_hwnd(b));
|
||
|
|
||
|
if ( mb )
|
||
|
{ int i;
|
||
|
MENUITEMINFO info;
|
||
|
|
||
|
memset(&info, 0, sizeof(info));
|
||
|
info.cbSize = sizeof(info);
|
||
|
info.fMask = MIIM_TYPE;
|
||
|
|
||
|
for(i=0; ; i++)
|
||
|
{ MENUITEMINFO info;
|
||
|
TCHAR nbuf[MAXLABELLEN];
|
||
|
|
||
|
memset(&info, 0, sizeof(info));
|
||
|
info.cbSize = sizeof(info);
|
||
|
info.fMask = MIIM_TYPE|MIIM_SUBMENU;
|
||
|
info.dwTypeData = nbuf;
|
||
|
info.cch = sizeof(nbuf);
|
||
|
|
||
|
if ( !GetMenuItemInfo(mb, i, TRUE, &info) )
|
||
|
return NULL;
|
||
|
|
||
|
if ( info.fType == MF_STRING )
|
||
|
{ if ( streq(name, nbuf) )
|
||
|
{ if ( pos )
|
||
|
*pos = i;
|
||
|
|
||
|
return info.hSubMenu;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
static void
|
||
|
append_builtin(HMENU menu, UINT id)
|
||
|
{ AppendMenu(menu, MF_STRING, id, lookupMenuId(id));
|
||
|
}
|
||
|
|
||
|
|
||
|
void
|
||
|
rlc_add_menu_bar(HWND cwin)
|
||
|
{ HMENU menu = CreateMenu();
|
||
|
HMENU file = CreatePopupMenu();
|
||
|
HMENU edit = CreatePopupMenu();
|
||
|
HMENU settings = CreatePopupMenu();
|
||
|
HMENU run = CreatePopupMenu();
|
||
|
|
||
|
append_builtin(file, IDM_EXIT);
|
||
|
|
||
|
/*append_builtin(edit, IDM_CUT);*/
|
||
|
append_builtin(edit, IDM_COPY);
|
||
|
append_builtin(edit, IDM_PASTE);
|
||
|
|
||
|
append_builtin(settings, IDM_FONT);
|
||
|
|
||
|
append_builtin(run, IDM_BREAK);
|
||
|
|
||
|
AppendMenu(menu, MF_POPUP, (UINT)file, _T("&File"));
|
||
|
AppendMenu(menu, MF_POPUP, (UINT)edit, _T("&Edit"));
|
||
|
AppendMenu(menu, MF_POPUP, (UINT)settings, _T("&Settings"));
|
||
|
AppendMenu(menu, MF_POPUP, (UINT)run, _T("&Run"));
|
||
|
|
||
|
SetMenu(cwin, menu);
|
||
|
}
|
||
|
|
||
|
/*******************************
|
||
|
* EXTERNAL *
|
||
|
*******************************/
|
||
|
|
||
|
#define MEN_MAGIC 0x6c4a58e0
|
||
|
|
||
|
void
|
||
|
rlc_menu_action(rlc_console c, menu_data *data)
|
||
|
{ RlcData b = rlc_get_data(c);
|
||
|
|
||
|
if ( !data || !data->magic == MEN_MAGIC )
|
||
|
return;
|
||
|
|
||
|
if ( data->menu ) /* rlc_insert_menu_item() */
|
||
|
{ HMENU popup;
|
||
|
|
||
|
if ( (popup = findPopup(b, data->menu, NULL)) )
|
||
|
data->rc = insertMenu(popup, data->label, data->before);
|
||
|
else
|
||
|
data->rc = FALSE;
|
||
|
} else /* insert_menu() */
|
||
|
{ HMENU mb;
|
||
|
HWND hwnd = rlc_hwnd(c);
|
||
|
|
||
|
if ( !(mb = GetMenu(hwnd)) )
|
||
|
{ data->rc = FALSE;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( !findPopup(b, data->label, NULL) ) /* already there */
|
||
|
{ MENUITEMINFO info;
|
||
|
int bid = -1;
|
||
|
|
||
|
if ( data->before )
|
||
|
findPopup(b, data->before, &bid);
|
||
|
|
||
|
memset(&info, 0, sizeof(info));
|
||
|
info.cbSize = sizeof(info);
|
||
|
info.fMask = MIIM_TYPE|MIIM_SUBMENU;
|
||
|
info.fType = MFT_STRING;
|
||
|
info.hSubMenu = CreatePopupMenu();
|
||
|
info.dwTypeData = (TCHAR *)data->label;
|
||
|
info.cch = (int)_tcslen(data->label);
|
||
|
|
||
|
InsertMenuItem(mb, bid, TRUE, &info);
|
||
|
/* force redraw; not automatic! */
|
||
|
DrawMenuBar(hwnd);
|
||
|
}
|
||
|
|
||
|
data->rc = TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
int
|
||
|
rlc_insert_menu(rlc_console c, const TCHAR *label, const TCHAR *before)
|
||
|
{ HWND hwnd = rlc_hwnd(c);
|
||
|
menu_data data;
|
||
|
|
||
|
data.magic = MEN_MAGIC;
|
||
|
data.menu = NULL;
|
||
|
data.label = label;
|
||
|
data.before = before;
|
||
|
|
||
|
SendMessage(hwnd, WM_RLC_MENU, 0, (LPARAM)&data);
|
||
|
|
||
|
return data.rc;
|
||
|
}
|
||
|
|
||
|
|
||
|
int
|
||
|
rlc_insert_menu_item(rlc_console c,
|
||
|
const TCHAR *menu, const TCHAR *label, const TCHAR *before)
|
||
|
{ HWND hwnd = rlc_hwnd(c);
|
||
|
menu_data data;
|
||
|
|
||
|
data.magic = MEN_MAGIC;
|
||
|
data.menu = menu;
|
||
|
data.label = label;
|
||
|
data.before = before;
|
||
|
|
||
|
SendMessage(hwnd, WM_RLC_MENU, 0, (LPARAM)&data);
|
||
|
|
||
|
return data.rc;
|
||
|
}
|