public static StringBuffer shopkeeper(Room R, ShopKeeper E, HTTPRequest httpReq, java.util.Map<String,String> parms, int borderSize)
	{
		final int theme = (R!=null) ? R.getArea().getTheme() : CMProps.getIntVar(CMProps.Int.MUDTHEME);
		final StringBuffer str=new StringBuffer("");
		str.append(priceFactors(E,httpReq,parms,borderSize));
		if(parms.containsKey("SHOPINVENTORY"))
		{
			final ArrayList<Environmental> theclasses=new ArrayList<Environmental>();
			final ArrayList<String> theparms=new ArrayList<String>();
			final ArrayList<String> theprices=new ArrayList<String>();
			if(httpReq.isUrlParameter("SHP1"))
			{
				int num=1;
				String MATCHING=httpReq.getUrlParameter("SHP"+num);
				String theparm=httpReq.getUrlParameter("SDATA"+num);
				String theprice=httpReq.getUrlParameter("SPRIC"+num);
				final XVector<Environmental> inventory=new XVector<Environmental>(E.getShop().getStoreInventory());
				while((MATCHING!=null)&&(theparm!=null))
				{
					if(CMath.isNumber(MATCHING))
					{
						final Environmental O=inventory.elementAt(CMath.s_int(MATCHING)-1);
						if(O!=null)
							theclasses.add(O);
					}
					else
					if(MATCHING.startsWith("CATALOG-"))
					{
						Environmental O=RoomData.getMOBFromCatalog(MATCHING);
						if(O==null)
							O=RoomData.getItemFromAnywhere(null,MATCHING);
						if(O!=null)
							theclasses.add(O);
					}
					else
					if(MATCHING.indexOf('@')>0)
					{
						Environmental O=null;
						for (final MOB M2 : RoomData.getMOBCache())
						{
							if(MATCHING.equals(""+M2))
							{
								O = M2;
								break;
							}
						}
						if(O==null)
							O=RoomData.getItemFromAnywhere(null,MATCHING);
						if(O!=null)
							theclasses.add(O);
					}
					else
					{
						Environmental O=null;
						for(final Enumeration<MOB> m=CMClass.mobTypes();m.hasMoreElements();)
						{
							final MOB M2=m.nextElement();
							if(CMClass.classID(M2).equals(MATCHING)&&(!M2.isGeneric()))
							{
								O = (MOB) M2.copyOf();
								break;
							}
						}
						if(O==null)
						{
							for(final Enumeration<Ability> a=CMClass.abilities();a.hasMoreElements();)
							{
								final Ability A2=a.nextElement();
								if(CMClass.classID(A2).equals(MATCHING))
								{
									O = (Ability) A2.copyOf();
									break;
								}
							}
						}
						if(O==null)
							O=RoomData.getItemFromAnywhere(null,MATCHING);
						if(O!=null)
							theclasses.add(O);
					}
					theparms.add(theparm);
					theprices.add(theprice);
					num++;
					MATCHING=httpReq.getUrlParameter("SHP"+num);
					theparm=httpReq.getUrlParameter("SDATA"+num);
					theprice=httpReq.getUrlParameter("SPRIC"+num);
				}
			}
			else
			{
				final ArrayList<Item> itemClasses=new ArrayList<Item>();
				final ArrayList<MOB> mobClasses=new ArrayList<MOB>();
				for(final Iterator<Environmental> i=E.getShop().getStoreInventory();i.hasNext();)
				{
					final Environmental O=i.next();
					if(O instanceof Item)
						itemClasses.add((Item)O);
					if(O instanceof MOB)
						mobClasses.add((MOB)O);
					if(O instanceof Physical)
						CMLib.catalog().updateCatalogIntegrity((Physical)O);
					theclasses.add(O);
					theparms.add(""+E.getShop().numberInStock(O));
					theprices.add(""+E.getShop().stockPrice(O));
				}
				RoomData.contributeItems(itemClasses);
				RoomData.contributeMOBs(mobClasses);
			}
			str.append("<TABLE WIDTH=100% BORDER=\""+borderSize+"\" CELLSPACING=0 CELLPADDING=0>");
			for(int i=0;i<theclasses.size();i++)
			{
				final Environmental O=theclasses.get(i);
				final String theparm=theparms.get(i);
				String theprice=theprices.get(i);
				str.append("<TR><TD WIDTH=90%>");
				str.append("<SELECT ONCHANGE=\"EditAffect(this);\" NAME=SHP"+(i+1)+">");
				str.append("<OPTION VALUE=\"\">Delete!");
				final int shopIndex=getShopCardinality(E,O);
				if(shopIndex>=0)
					str.append("<OPTION SELECTED VALUE=\""+(shopIndex+1)+"\">"+O.Name()+" ("+O.ID()+")");
				else
				if(CMLib.flags().isCataloged(O))
					str.append("<OPTION SELECTED VALUE=\"CATALOG-"+O.Name()+"\">"+O.Name()+" (Cataloged)");
				else
				if(RoomData.getItemCache().contains(O))
					str.append("<OPTION SELECTED VALUE=\""+O+"\">"+O.Name()+RoomData.getObjIDSuffix(O));
				else
				if(RoomData.getMOBCache().contains(O))
					str.append("<OPTION SELECTED VALUE=\""+O+"\">"+O.Name()+RoomData.getObjIDSuffix(O));
				else
					str.append("<OPTION SELECTED VALUE=\""+O.ID()+"\">"+O.Name()+" ("+O.ID()+")");
				str.append("</SELECT>");
				str.append("<BR>");
				str.append("Stock: ");
				str.append("<INPUT TYPE=TEXT SIZE=5 NAME=SDATA"+(i+1)+" VALUE=\""+theparm+"\">");
				if((theprice==null)||(theprice.equals("null")))
					theprice="-1";
				str.append("&nbsp;&nbsp;&nbsp;");
				str.append("Price: <INPUT TYPE=TEXT SIZE=5 NAME=SPRIC"+(i+1)+" VALUE=\""+theprice+"\">");
				str.append("</TD><TD WIDTH=10%>");
				if(!CMLib.flags().isCataloged(O))
				{
					//if(O instanceof MOB)
						//str.append("<INPUT TYPE=BUTTON NAME=EDITSHOPMOB"+(i+1)+" VALUE=EDIT ONCLICK=\"EditShopMob('"+RoomData.getMOBCode(RoomData.getMOBCache(),(MOB)O)+"');\">");
					//else
					if(O instanceof Item)
						str.append("<INPUT TYPE=BUTTON NAME=EDITSHOPITEM"+(i+1)+" VALUE=EDIT ONCLICK=\"EditShopItem('"+RoomData.getItemCode(RoomData.getItemCache(),(Item)O)+"');\">");
				}
				str.append("</TD></TR>");
			}
			str.append("<TR><TD WIDTH=90%>");
			str.append("<SELECT ONCHANGE=\"AddAffect(this);\" NAME=SHP"+(theclasses.size()+1)+">");
			str.append("<OPTION SELECTED VALUE=\"\">Select an item");
			for (final Item I : RoomData.getItemCache())
			{
				str.append("<OPTION VALUE=\""+I+"\">"+I.Name()+RoomData.getObjIDSuffix(I));
			}
			for (final MOB M : RoomData.getMOBCache())
			{
				str.append("<OPTION VALUE=\""+M+"\">"+M.Name()+RoomData.getObjIDSuffix(M));
			}
			StringBuffer bufA=(StringBuffer)Resources.getResource("MUDGRINDER-STORESTUFF"+theme);
			if(bufA==null)
			{
				bufA=new StringBuffer("");
				final List<String> sortMeA=new ArrayList<String>();
				for(final Enumeration<Ability> a=CMClass.abilities();a.hasMoreElements();)
					sortMeA.add(CMClass.classID(a.nextElement()));
				for(final Enumeration<MOB> m=CMClass.mobTypes();m.hasMoreElements();)
					sortMeA.add(CMClass.classID(m.nextElement()));
				CMClass.addAllItemClassNames(sortMeA,true,true,false,theme);
				Collections.sort(sortMeA);
				for (final Object element : sortMeA)
				{
					final String cnam=(String)element;
					bufA.append("<OPTION VALUE=\""+cnam+"\">"+cnam);
				}
				Resources.submitResource("MUDGRINDER-STORESTUFF"+theme,bufA);
			}
			str.append(bufA);
			str.append("<OPTION VALUE=\"\">------ CATALOGED -------");
			String[] names;
			names=CMLib.catalog().getCatalogMobNames();
			for (final String name : names)
				str.append("<OPTION VALUE=\"CATALOG-"+name+"\">"+name);
			names=CMLib.catalog().getCatalogItemNames();
			for (final String name : names)
				str.append("<OPTION VALUE=\"CATALOG-"+name+"\">"+name);
			str.append("</SELECT><BR>");
			str.append("Stock: <INPUT TYPE=TEXT SIZE=5 NAME=SDATA"+(theclasses.size()+1)+" VALUE=\"1\">");
			str.append("&nbsp;&nbsp;&nbsp;");
			str.append("Price: <INPUT TYPE=TEXT SIZE=5 NAME=SPRIC"+(theclasses.size()+1)+" VALUE=\"-1\">");
			str.append("</TD><TD WIDTH=10%>");
			str.append("<INPUT TYPE=BUTTON NAME=ADDSHOPITEM VALUE=\"+Item\" ONCLICK=\"AddNewShopItem();\">");
			//str.append("<INPUT TYPE=BUTTON NAME=ADDSHOPMOB VALUE=\"+MOB\" ONCLICK=\"AddNewShopMOB();\">");
			str.append("</TD></TR>");
			str.append("</TABLE>");
		}
		return str;
	}