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;
 | 
						|
}
 |