git-svn-id: https://yap.svn.sf.net/svnroot/yap/trunk@2170 b08c6af1-5177-4d33-ba66-4b1c6b8b522a
		
			
				
	
	
		
			309 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			309 lines
		
	
	
		
			6.9 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
 | |
| 
 | |
| 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;
 | |
| }
 |