| 
						
					 | 
				
			
			 | 
			 | 
			
				@@ -3746,10 +3746,15 @@ void GUIFormSpecMenu::showTooltip(const std::wstring &text,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				void GUIFormSpecMenu::updateSelectedItem()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					// Don't update when dragging an item
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (m_selected_item && (m_selected_dragging || m_left_dragging))
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						return;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					verifySelectedItem();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					// If craftresult is nonempty and nothing else is selected, select it now.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (!m_selected_item) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					// If craftresult is not empty and nothing else is selected,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					// try to move it somewhere or select it now
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (!m_selected_item || m_shift_move_after_craft) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						for (const GUIInventoryList *e : m_inventorylists) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							if (e->getListname() != "craftpreview")
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								continue;
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@@ -3767,14 +3772,48 @@ void GUIFormSpecMenu::updateSelectedItem()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							if (item.empty())
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								continue;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							// Grab selected item from the crafting result list
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							m_selected_item = new GUIInventoryList::ItemSpec;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							m_selected_item->inventoryloc = e->getInventoryloc();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							m_selected_item->listname = "craftresult";
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							m_selected_item->i = 0;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							m_selected_item->slotsize = e->getSlotSize();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							m_selected_amount = item.count;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							m_selected_dragging = false;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							GUIInventoryList::ItemSpec s = GUIInventoryList::ItemSpec();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							s.inventoryloc = e->getInventoryloc();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							s.listname = "craftresult";
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							s.i = 0;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							s.slotsize = e->getSlotSize();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							if (m_shift_move_after_craft) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								// Try to shift-move the crafted item to the next list in the ring after the "craft" list.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								// We don't look for the "craftresult" list because it's a hidden list,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								// and shouldn't be part of the formspec, thus it won't be in the list ring.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								do {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									s16 r = getNextInventoryRing(s.inventoryloc, "craft");
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									if (r < 0) // Not found
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										break;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									const ListRingSpec &to_ring = m_inventory_rings[r];
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									Inventory *inv_to = m_invmgr->getInventory(to_ring.inventoryloc);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									if (!inv_to)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										break;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									InventoryList *list_to = inv_to->getList(to_ring.listname);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									if (!list_to)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										break;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									IMoveAction *a = new IMoveAction();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									a->count = item.count;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									a->from_inv = s.inventoryloc;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									a->from_list = s.listname;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									a->from_i = s.i;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									a->to_inv = to_ring.inventoryloc;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									a->to_list = to_ring.listname;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									a->move_somewhere = true;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									m_invmgr->inventoryAction(a);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								} while (0);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								m_shift_move_after_craft = false;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							} else {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								// Grab selected item from the crafting result list
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								m_selected_item = new GUIInventoryList::ItemSpec(s);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								m_selected_amount = item.count;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								m_selected_dragging = false;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							break;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@@ -3821,6 +3860,25 @@ ItemStack GUIFormSpecMenu::verifySelectedItem()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					return ItemStack();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				s16 GUIFormSpecMenu::getNextInventoryRing(
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						const InventoryLocation &inventoryloc, const std::string &listname)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					u16 rings = m_inventory_rings.size();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (rings < 2)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						return -1;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					// Look for the source ring
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					s16 index = -1;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					for (u16 i = 0; i < rings; i++) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						ListRingSpec &lr = m_inventory_rings[i];
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						if (lr.inventoryloc == inventoryloc && lr.listname == listname) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							// Set the index to the next ring
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							index = (i + 1) % rings;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							break;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					return index;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				void GUIFormSpecMenu::acceptInput(FormspecQuitMode quitmode)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if(m_text_dst)
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@@ -4052,19 +4110,6 @@ void GUIFormSpecMenu::tryClose()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				enum ButtonEventType : u8
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					BET_LEFT,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					BET_RIGHT,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					BET_MIDDLE,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					BET_WHEEL_UP,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					BET_WHEEL_DOWN,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					BET_UP,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					BET_DOWN,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					BET_MOVE,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					BET_OTHER
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				};
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				bool GUIFormSpecMenu::OnEvent(const SEvent& event)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (event.EventType==EET_KEY_INPUT_EVENT) {
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@@ -4117,13 +4162,14 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					/* Mouse event other than movement, or crossing the border of inventory
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					  field while holding right mouse button
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					  field while holding left, right, or middle mouse button
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					 */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (event.EventType == EET_MOUSE_INPUT_EVENT &&
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							(event.MouseInput.Event != EMIE_MOUSE_MOVED ||
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							 (event.MouseInput.Event == EMIE_MOUSE_MOVED &&
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							  event.MouseInput.isRightPressed() &&
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							  getItemAtPos(m_pointer).i != getItemAtPos(m_old_pointer).i))) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						(event.MouseInput.Event != EMIE_MOUSE_MOVED ||
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							((event.MouseInput.isLeftPressed() ||
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								event.MouseInput.isRightPressed() ||
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								event.MouseInput.isMiddlePressed()) &&
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							getItemAtPos(m_pointer).i != getItemAtPos(m_old_pointer).i))) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						// Get selected item and hovered/clicked item (s)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@@ -4132,13 +4178,15 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						GUIInventoryList::ItemSpec s = getItemAtPos(m_pointer);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						Inventory *inv_selected = NULL;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						InventoryList *list_selected = NULL;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						Inventory *inv_s = NULL;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						InventoryList *list_s = NULL;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						if (m_selected_item) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							inv_selected = m_invmgr->getInventory(m_selected_item->inventoryloc);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							sanity_check(inv_selected);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							sanity_check(inv_selected->getList(m_selected_item->listname) != NULL);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							list_selected = inv_selected->getList(m_selected_item->listname);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							sanity_check(list_selected);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						u32 s_count = 0;
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@@ -4174,12 +4222,21 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							s_count = list_s->getItem(s.i).count;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						} while(0);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						bool identical = m_selected_item && s.isValid() &&
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							(inv_selected == inv_s) &&
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							(m_selected_item->listname == s.listname) &&
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							(m_selected_item->i == s.i);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						// True if the hovered slot is the selected slot
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						bool identical = m_selected_item && s.isValid() && (*m_selected_item == s);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						ButtonEventType button = BET_LEFT;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						// True if the hovered slot is empty
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						bool empty = s.isValid() && list_s->getItem(s.i).empty();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						// True if the hovered item would stack with the selected item
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						bool matching = false;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						if (m_selected_item && s.isValid()) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							ItemStack a = list_selected->getItem(m_selected_item->i);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							ItemStack b = list_s->getItem(s.i);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							matching = a.stacksWith(b);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						ButtonEventType button = BET_OTHER;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						ButtonEventType updown = BET_OTHER;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						switch (event.MouseInput.Event) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						case EMIE_LMOUSE_PRESSED_DOWN:
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@@ -4220,6 +4277,10 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						// from s to the next inventory ring.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						u32 shift_move_amount = 0;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						// Set this number to a positive value to generate a move action
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						// from s to m_selected_item.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						u32 pickup_amount = 0;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						// Set this number to a positive value to generate a drop action
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						// from m_selected_item.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						u32 drop_amount = 0;
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@@ -4228,92 +4289,154 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						u32 craft_amount = 0;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						switch (updown) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						case BET_DOWN:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						case BET_DOWN: {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							// Some mouse button has been pressed
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							//infostream << "Mouse button " << button << " pressed at p=("
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							//	<< event.MouseInput.X << "," << event.MouseInput.Y << ")"
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							//	<< std::endl;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							if (m_held_mouse_button != BET_OTHER)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								break;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							if (button == BET_LEFT || button == BET_RIGHT || button == BET_MIDDLE)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								m_held_mouse_button = button;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							m_selected_dragging = false;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							if (s.isValid() && s.listname == "craftpreview") {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								// Craft preview has been clicked: craft
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								craft_amount = (button == BET_MIDDLE ? 10 : 1);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							} else if (!m_selected_item) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								if (s_count && button != BET_WHEEL_UP) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									// Non-empty stack has been clicked: select or shift-move it
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									m_selected_item = new GUIInventoryList::ItemSpec(s);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									u32 count;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									if (button == BET_RIGHT)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										count = (s_count + 1) / 2;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									else if (button == BET_MIDDLE)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										count = MYMIN(s_count, 10);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									else if (button == BET_WHEEL_DOWN)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										count = 1;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									else  // left
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										count = s_count;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									if (!event.MouseInput.Shift) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										// no shift: select item
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										m_selected_amount = count;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										m_selected_dragging = button != BET_WHEEL_DOWN;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										m_auto_place = false;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									} else {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										// shift pressed: move item, right click moves 1
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										shift_move_amount = button == BET_RIGHT ? 1 : count;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							} else { // m_selected_item != NULL
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								assert(m_selected_amount >= 1);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								if (s.isValid()) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									// Clicked a slot: move
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									if (button == BET_RIGHT || button == BET_WHEEL_UP)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										move_amount = 1;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									else if (button == BET_MIDDLE)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										move_amount = MYMIN(m_selected_amount, 10);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									else if (button == BET_LEFT)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										move_amount = m_selected_amount;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									// else wheeldown
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									if (identical) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										if (button == BET_WHEEL_DOWN) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
											if (m_selected_amount < s_count)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
												++m_selected_amount;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										} else {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
											if (move_amount >= m_selected_amount)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
												m_selected_amount = 0;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
											else
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
												m_selected_amount -= move_amount;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
											move_amount = 0;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								} else if (!getAbsoluteClippingRect().isPointInside(m_pointer)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										&& button != BET_WHEEL_DOWN) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							if (!s.isValid()) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								if (m_selected_item && !getAbsoluteClippingRect().isPointInside(m_pointer)) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									// Clicked outside of the window: drop
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									if (button == BET_RIGHT || button == BET_WHEEL_UP)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										drop_amount = 1;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									else if (button == BET_MIDDLE)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										drop_amount = MYMIN(m_selected_amount, 10);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									else  // left
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									else if (button == BET_LEFT)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										drop_amount = m_selected_amount;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								break;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						break;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						case BET_UP:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							if (s.listname == "craftpreview") {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								// Craft preview has been clicked: craft
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								if (button == BET_MIDDLE)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									craft_amount = 10;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								else if (event.MouseInput.Shift && button == BET_LEFT)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									// TODO: We should craft everything with shift-left-click,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									// but the slow crafting code limits us, so we only craft one
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									craft_amount = 1;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									//craft_amount = list_s->getItem(s.i).getStackMax(m_client->idef());
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								else
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									craft_amount = 1;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								// Holding shift moves the crafted item to the inventory
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								m_shift_move_after_craft = event.MouseInput.Shift;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							} else if (!m_selected_item && button != BET_WHEEL_UP && !empty) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								// Non-empty stack has been clicked: select or shift-move it
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								u32 count = 0;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								if (button == BET_RIGHT)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									count = (s_count + 1) / 2;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								else if (button == BET_MIDDLE)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									count = MYMIN(s_count, 10);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								else if (button == BET_WHEEL_DOWN)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									count = 1;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								else if (button == BET_LEFT)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									count = s_count;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								if (event.MouseInput.Shift) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									// Shift pressed: move item, right click moves 1
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									shift_move_amount = button == BET_RIGHT ? 1 : count;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								} else {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									// No shift: select item
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									m_selected_item = new GUIInventoryList::ItemSpec(s);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									m_selected_amount = count;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									m_selected_dragging = button != BET_WHEEL_DOWN;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							} else if (m_selected_item) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								// Clicked a slot: move
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								if (button == BET_RIGHT || button == BET_WHEEL_UP)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									move_amount = 1;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								else if (button == BET_WHEEL_DOWN)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									pickup_amount = MYMIN(s_count, 1);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								else if (button == BET_MIDDLE)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									move_amount = MYMIN(m_selected_amount, 10);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								else if (button == BET_LEFT)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									move_amount = m_selected_amount;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								if (event.MouseInput.Shift && !identical && matching) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									// Shift-move all items the same as the selected item to the next list
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									move_amount = 0;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									// Try to find somewhere to move the items to
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									s16 r = getNextInventoryRing(s.inventoryloc, s.listname);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									if (r < 0) // Not found
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										break;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									const ListRingSpec &to_ring = m_inventory_rings[r];
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									Inventory *inv_to = m_invmgr->getInventory(to_ring.inventoryloc);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									if (!inv_to)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										break;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									InventoryList *list_to = inv_to->getList(to_ring.listname);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									if (!list_to)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										break;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									ItemStack slct = list_selected->getItem(m_selected_item->i);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									for (s32 i = 0; i < list_s->getSize(); i++) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										// Skip the selected slot
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										if (i == m_selected_item->i)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
											continue;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										ItemStack item = list_s->getItem(i);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										if (slct.stacksWith(item)) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
											IMoveAction *a = new IMoveAction();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
											a->count = item.count;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
											a->from_inv = s.inventoryloc;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
											a->from_list = s.listname;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
											a->from_i = i;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
											a->to_inv = to_ring.inventoryloc;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
											a->to_list = to_ring.listname;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
											a->move_somewhere = true;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
											m_invmgr->inventoryAction(a);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								} else if (button == BET_LEFT && (empty || matching)) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									// We don't know if the user is left-dragging or just moving
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									// the item, so assume that they are left-dragging,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									// and wait for the next event before moving the item
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									m_left_dragging = true;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									m_client->inhibit_inventory_revert = true;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									m_left_drag_stack = list_selected->getItem(m_selected_item->i);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									m_left_drag_amount = m_selected_amount;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									m_left_drag_stacks.emplace_back(s, list_s->getItem(s.i));
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									move_amount = 0;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								} else if (identical) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									// Change the selected amount instead of moving
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									if (button == BET_WHEEL_DOWN) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										if (m_selected_amount < s_count)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
											++m_selected_amount;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									} else if (button == BET_WHEEL_UP) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										if (m_selected_amount > 0)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
											--m_selected_amount;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									} else {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										if (move_amount >= m_selected_amount)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
											m_selected_amount = 0;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										else
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
											m_selected_amount -= move_amount;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									move_amount = 0;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									pickup_amount = 0;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							break;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						case BET_UP: {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							// Some mouse button has been released
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							//infostream<<"Mouse button "<<button<<" released at p=("
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							//	<<p.X<<","<<p.Y<<")"<<std::endl;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							if (m_held_mouse_button != BET_OTHER && m_held_mouse_button != button)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								break;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							m_held_mouse_button = BET_OTHER;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							if (m_selected_dragging && m_selected_item) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								if (s.isValid()) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									if (!identical) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										// Dragged to different slot: move all selected
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										move_amount = m_selected_amount;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								if (s.isValid() && !identical && (empty || matching)) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									// Dragged to different slot: move all selected
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									move_amount = m_selected_amount;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								} else if (!getAbsoluteClippingRect().isPointInside(m_pointer)) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									// Dragged outside of window: drop all selected
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									drop_amount = m_selected_amount;
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@@ -4321,60 +4444,215 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							m_selected_dragging = false;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							// Keep track of whether the mouse button be released
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							// One click is drag without dropping. Click + release
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							// + click changes to drop item when moved mode
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							if (m_selected_item)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								m_auto_place = true;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						break;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						case BET_MOVE:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							// Mouse has been moved and rmb is down and mouse pointer just
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							// entered a new inventory field (checked in the entry-if, this
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							// is the only action here that is generated by mouse movement)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							if (m_selected_item && s.isValid() && s.listname != "craftpreview") {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								// Move 1 item
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								// TODO: middle mouse to move 10 items might be handy
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								if (m_auto_place) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									// Only move an item if the destination slot is empty
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									// or contains the same item type as what is going to be
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									// moved
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									InventoryList *list_from = inv_selected->getList(m_selected_item->listname);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									InventoryList *list_to = list_s;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									assert(list_from && list_to);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									ItemStack stack_from = list_from->getItem(m_selected_item->i);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									ItemStack stack_to = list_to->getItem(s.i);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									if (stack_to.empty() || stack_to.name == stack_from.name)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										move_amount = 1;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							if (m_left_dragging && button == BET_LEFT) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								m_left_dragging = false;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								m_client->inhibit_inventory_revert = false;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								if (m_left_drag_stacks.size() > 1) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									// Finalize the left-dragging
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									for (auto &ds : m_left_drag_stacks) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										// Check how many items we should move to this slot,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										// it may be less than the full split
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										Inventory *inv_to = m_invmgr->getInventory(ds.first.inventoryloc);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										InventoryList *list_to = inv_to->getList(ds.first.listname);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										ItemStack stack_to = list_to->getItem(ds.first.i);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										u16 amount = stack_to.count - ds.second.count;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										IMoveAction *a = new IMoveAction();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										a->count = amount;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										a->from_inv = m_selected_item->inventoryloc;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										a->from_list = m_selected_item->listname;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										a->from_i = m_selected_item->i;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										a->to_inv = ds.first.inventoryloc;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										a->to_list = ds.first.listname;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										a->to_i = ds.first.i;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										m_invmgr->inventoryAction(a);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								} else if (identical) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									// Put the selected item back where it came from
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									m_selected_amount = 0;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								} else if (s.isValid()) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									// Move the selected item
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									move_amount = m_selected_amount;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								m_left_drag_stacks.clear();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							break;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						case BET_MOVE: {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							// Mouse button is down and mouse pointer entered a new inventory field
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							if (!s.isValid() || s.listname == "craftpreview")
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								break;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							if (!m_selected_item && event.MouseInput.Shift) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								// Shift-move items while dragging
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								if (m_held_mouse_button == BET_RIGHT)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									shift_move_amount = 1;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								else if (m_held_mouse_button == BET_MIDDLE)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									shift_move_amount = MYMIN(s_count, 10);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								else if (m_held_mouse_button == BET_LEFT)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									shift_move_amount = s_count;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							} else if (m_selected_item) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								if (m_held_mouse_button != BET_LEFT) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									// Move items if the destination slot is empty
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									// or contains the same item type as what is going to be moved
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									if (!m_selected_dragging && (empty || matching)) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										if (m_held_mouse_button == BET_RIGHT)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
											move_amount = 1;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										else if (m_held_mouse_button == BET_MIDDLE)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
											move_amount = MYMIN(m_selected_amount, 10);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								} else if (m_left_dragging && (empty || matching) &&
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										m_left_drag_amount > m_left_drag_stacks.size()) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									// Add the slot to the left-drag list if it doesn't exist
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									bool found = false;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									for (auto &ds : m_left_drag_stacks) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										if (s == ds.first) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
											found = true;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
											break;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									if (!found) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										m_left_drag_stacks.emplace_back(s, list_s->getItem(s.i));
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								} else if (m_selected_dragging && matching && !identical) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									// Pickup items of the same type while dragging
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									pickup_amount = s_count;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							} else if (m_held_mouse_button == BET_LEFT) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								// Start picking up items
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								m_selected_item = new GUIInventoryList::ItemSpec(s);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								m_selected_amount = s_count;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								m_selected_dragging = true;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							break;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						case BET_OTHER: {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							// Some other mouse event has occured
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							// Currently only left-double-click should trigger this
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							if (!s.isValid() || event.MouseInput.Event != EMIE_LMOUSE_DOUBLE_CLICK)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								break;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							// Abort left-dragging
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							m_left_dragging = false;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							m_client->inhibit_inventory_revert = false;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							m_left_drag_stacks.clear();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							// Both the selected item and the hovered item need to be checked
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							// because we don't know exactly when the double-click happened
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							ItemStack slct;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							if (!m_selected_item && !empty)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								slct = list_s->getItem(s.i);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							else if (m_selected_item && (identical || empty))
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								slct = list_selected->getItem(m_selected_item->i);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							// Pickup all of the item from the list
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							if (slct.count > 0) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								for (s32 i = 0; i < list_s->getSize(); i++) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									// Skip the selected slot
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									if (i == s.i)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										continue;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									ItemStack item = list_s->getItem(i);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									if (slct.stacksWith(item)) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										// Found a match, check if we can pick it up
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										bool full = false;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										u16 amount = item.count;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										ItemStack leftover = slct.addItem(item, m_client->idef());
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										if (!leftover.empty()) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
											amount -= leftover.count;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
											full = true;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										if (amount > 0) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
											IMoveAction *a = new IMoveAction();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
											a->count = amount;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
											a->from_inv = s.inventoryloc;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
											a->from_list = s.listname;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
											a->from_i = i;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
											a->to_inv = s.inventoryloc;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
											a->to_list = s.listname;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
											a->to_i = s.i;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
											m_invmgr->inventoryAction(a);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
											if (m_selected_item)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
												m_selected_amount += amount;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										if (full) // Stack is full, stop
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
											break;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						break;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							break;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						default:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							break;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						// Update left-dragged slots
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						if (m_left_dragging && m_left_drag_stacks.size() > 1) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							// The split amount will always at least one, because the number
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							// of slots will never be greater than the selected amount
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							u16 split_amount = m_left_drag_amount / m_left_drag_stacks.size();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							ItemStack stack_from = m_left_drag_stack;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							m_selected_amount = m_left_drag_amount;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							for (auto &ds : m_left_drag_stacks) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								Inventory *inv_to = m_invmgr->getInventory(ds.first.inventoryloc);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								InventoryList *list_to = inv_to->getList(ds.first.listname);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								if (ds.first == *m_selected_item) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									// Adding to the source stack, just change the selected amount
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									m_selected_amount -= split_amount;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								} else {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									// Reset the stack to its original state
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									list_to->changeItem(ds.first.i, ds.second);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									// Add the new split to the stack
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									ItemStack add_stack = stack_from;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									add_stack.count = split_amount;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									ItemStack leftover = list_to->addItem(ds.first.i, add_stack);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									// Remove the split items from the source stack
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									u16 moved = split_amount - leftover.count;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									m_selected_amount -= moved;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									stack_from.count -= moved;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							// Save the adjusted source stack
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							list_selected->changeItem(m_selected_item->i, stack_from);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						// Possibly send inventory action to server
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						if (move_amount > 0) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							// Send IAction::Move
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							assert(m_selected_item && m_selected_item->isValid());
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							assert(s.isValid());
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							assert(list_selected && list_s);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							assert(inv_selected && inv_s);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							InventoryList *list_from = inv_selected->getList(m_selected_item->listname);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							InventoryList *list_to = list_s;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							assert(list_from && list_to);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							ItemStack stack_from = list_from->getItem(m_selected_item->i);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							ItemStack stack_to = list_to->getItem(s.i);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							ItemStack stack_from = list_selected->getItem(m_selected_item->i);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							ItemStack stack_to = list_s->getItem(s.i);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							// Check how many items can be moved
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							move_amount = stack_from.count = MYMIN(move_amount, stack_from.count);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							ItemStack leftover = stack_to.addItem(stack_from, m_client->idef());
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							bool move = true;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							// If source stack cannot be added to destination stack at all,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							// they are swapped
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							if (leftover.count == stack_from.count &&
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									leftover.name == stack_from.name) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							if (leftover.count == stack_from.count && leftover.name == stack_from.name) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								if (m_selected_swap.empty()) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									m_selected_amount = stack_to.count;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									m_selected_dragging = false;
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@@ -4383,7 +4661,7 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									// Skip next validation checks due async inventory calls
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									m_selected_swap = stack_to;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								} else {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									move = false;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									move_amount = 0;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							// Source stack goes fully into destination stack
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@@ -4396,7 +4674,7 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								m_selected_amount -= move_amount;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							if (move) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							if (move_amount > 0) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								infostream << "Handing IAction::Move to manager" << std::endl;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								IMoveAction *a = new IMoveAction();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								a->count = move_amount;
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@@ -4408,31 +4686,64 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								a->to_i = s.i;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								m_invmgr->inventoryAction(a);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						} else if (shift_move_amount > 0) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							u32 mis = m_inventory_rings.size();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							u32 i = 0;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							for (; i < mis; i++) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								const ListRingSpec &sp = m_inventory_rings[i];
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								if (sp.inventoryloc == s.inventoryloc
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
										&& sp.listname == s.listname)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									break;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						} else if (pickup_amount > 0) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							// Send IAction::Move
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							assert(m_selected_item && m_selected_item->isValid());
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							assert(s.isValid());
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							assert(list_selected && list_s);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							ItemStack stack_from = list_s->getItem(s.i);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							ItemStack stack_to = list_selected->getItem(m_selected_item->i);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							// Only move if the items are exactly the same,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							// we shouldn't attempt to pickup different items
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							if (matching) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								// Check how many items can be moved
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								pickup_amount = stack_from.count = MYMIN(pickup_amount, stack_from.count);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								ItemStack leftover = stack_to.addItem(stack_from, m_client->idef());
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								pickup_amount -= leftover.count;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							} else {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								pickup_amount = 0;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							if (pickup_amount > 0) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								m_selected_amount += pickup_amount;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								infostream << "Handing IAction::Move to manager" << std::endl;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								IMoveAction *a = new IMoveAction();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								a->count = pickup_amount;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								a->from_inv = s.inventoryloc;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								a->from_list = s.listname;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								a->from_i = s.i;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								a->to_inv = m_selected_item->inventoryloc;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								a->to_list = m_selected_item->listname;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								a->to_i = m_selected_item->i;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								m_invmgr->inventoryAction(a);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						} else if (shift_move_amount > 0) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							// Try to shift-move the item
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							do {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								if (i >= mis) // if not found
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								s16 r = getNextInventoryRing(s.inventoryloc, s.listname);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								if (r < 0) // Not found
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									break;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								u32 to_inv_ind = (i + 1) % mis;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								const ListRingSpec &to_inv_sp = m_inventory_rings[to_inv_ind];
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								const ListRingSpec &to_ring = m_inventory_rings[r];
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								InventoryList *list_from = list_s;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								if (!s.isValid())
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									break;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								Inventory *inv_to = m_invmgr->getInventory(to_inv_sp.inventoryloc);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								Inventory *inv_to = m_invmgr->getInventory(to_ring.inventoryloc);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								if (!inv_to)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									break;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								InventoryList *list_to = inv_to->getList(to_inv_sp.listname);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								InventoryList *list_to = inv_to->getList(to_ring.listname);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								if (!list_to)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									break;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								// Check how many items can be moved
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								ItemStack stack_from = list_from->getItem(s.i);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								assert(shift_move_amount <= stack_from.count);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								shift_move_amount = MYMIN(shift_move_amount, stack_from.count);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								if (shift_move_amount == 0)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									break;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								infostream << "Handing IAction::Move to manager" << std::endl;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								IMoveAction *a = new IMoveAction();
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@@ -4440,19 +4751,18 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								a->from_inv = s.inventoryloc;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								a->from_list = s.listname;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								a->from_i = s.i;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								a->to_inv = to_inv_sp.inventoryloc;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								a->to_list = to_inv_sp.listname;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								a->to_inv = to_ring.inventoryloc;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								a->to_list = to_ring.listname;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								a->move_somewhere = true;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								m_invmgr->inventoryAction(a);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							} while (0);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						} else if (drop_amount > 0) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							// Send IAction::Drop
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							assert(m_selected_item && m_selected_item->isValid());
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							assert(inv_selected);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							InventoryList *list_from = inv_selected->getList(m_selected_item->listname);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							assert(list_from);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							ItemStack stack_from = list_from->getItem(m_selected_item->i);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							assert(list_selected);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							ItemStack stack_from = list_selected->getItem(m_selected_item->i);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							// Check how many items can be dropped
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							drop_amount = stack_from.count = MYMIN(drop_amount, stack_from.count);
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@@ -4466,10 +4776,11 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							a->from_list = m_selected_item->listname;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							a->from_i = m_selected_item->i;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							m_invmgr->inventoryAction(a);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						} else if (craft_amount > 0) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							assert(s.isValid());
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							// if there are no items selected or the selected item
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							// If there are no items selected or the selected item
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							// belongs to craftresult list, proceed with crafting
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							if (!m_selected_item ||
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									!m_selected_item->isValid() || m_selected_item->listname == "craftresult") {
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@@ -4485,8 +4796,9 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						// If m_selected_amount has been decreased to zero, deselect
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						if (m_selected_amount == 0) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						// If m_selected_amount has been decreased to zero,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						// and we are not left-dragging, deselect
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						if (m_selected_amount == 0 && !m_left_dragging) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							m_selected_swap.clear();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							delete m_selected_item;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							m_selected_item = nullptr;
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				 
 |