This repository has been archived on 2023-08-20. You can view files and clone it, but cannot push or open issues or pull requests.
yap-6.3/swi/console/menu.c
2014-03-06 02:03:10 +00:00

310 lines
6.9 KiB
C
Executable File

/* $Id$
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <windows.h>
#include <tchar.h>
#define _MAKE_DLL 1
#undef _export
#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;
}
static 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_PTR)file, _T("&File"));
AppendMenu(menu, MF_POPUP, (UINT_PTR)edit, _T("&Edit"));
AppendMenu(menu, MF_POPUP, (UINT_PTR)settings, _T("&Settings"));
AppendMenu(menu, MF_POPUP, (UINT_PTR)run, _T("&Run"));
SetMenu(cwin, menu);
}
/*******************************
* EXTERNAL *
*******************************/
#define MEN_MAGIC 0x6c4a58e0
typedef struct menu_data
{ intptr_t magic; /* safety */
const TCHAR *menu; /* menu to operate on */
const TCHAR *label; /* new label */
const TCHAR *before; /* add before this one */
int rc; /* result */
} menu_data;
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;
}