From 7be7e47c3dd8d91c9a47c5a983ea3032e8f39ecb Mon Sep 17 00:00:00 2001
From: dg <dg@51575b47-30f0-44d4-a5cc-537603b46e54>
Date: Thu, 8 Sep 2011 23:02:29 +0000
Subject: [PATCH] Updated keyboard handling, should not double trigger anymore

git-svn-id: http://svn.net-core.org/repos/t-engine4@4358 51575b47-30f0-44d4-a5cc-537603b46e54
---
 .../engines/default/data/keybinds/actions.lua | 23 ++++--------
 .../default/data/keybinds/interface.lua       |  2 +-
 .../default/data/keybinds/inventory.lua       | 16 ++++----
 game/engines/default/data/keybinds/move.lua   |  2 +-
 game/engines/default/engine/Birther.lua       |  2 +
 game/engines/default/engine/DebugConsole.lua  |  1 +
 game/engines/default/engine/KeyBind.lua       | 36 +++++++++++++-----
 game/engines/default/engine/dialogs/Chat.lua  |  4 ++
 .../default/engine/dialogs/ShowEquipInven.lua |  4 ++
 .../default/engine/dialogs/ShowEquipment.lua  |  4 ++
 .../default/engine/dialogs/ShowInventory.lua  |  4 ++
 .../engine/dialogs/ShowPickupFloor.lua        |  4 ++
 .../default/engine/dialogs/ShowStore.lua      |  4 ++
 .../default/engine/dialogs/UseTalents.lua     |  4 ++
 .../engine/interface/ActorInventory.lua       | 11 ++++++
 .../engine/interface/PlayerHotkeys.lua        |  4 +-
 game/engines/default/engine/ui/Focusable.lua  |  1 +
 game/engines/default/engine/ui/Numberbox.lua  |  4 ++
 game/engines/default/engine/ui/Textbox.lua    |  4 ++
 game/engines/default/engine/utils.lua         |  6 +++
 game/modules/tome/dialogs/CharacterSheet.lua  |  4 ++
 game/modules/tome/dialogs/LevelupDialog.lua   |  2 +
 game/modules/tome/dialogs/PartyOrder.lua      |  4 ++
 game/modules/tome/dialogs/PartySelect.lua     |  4 ++
 game/modules/tome/dialogs/UseTalents.lua      |  4 ++
 .../tome/dialogs/debug/AlterFaction.lua       |  4 ++
 .../modules/tome/dialogs/debug/ChangeZone.lua |  4 ++
 .../modules/tome/dialogs/debug/CreateItem.lua |  4 ++
 game/modules/tome/dialogs/debug/DebugMain.lua |  4 ++
 .../modules/tome/dialogs/debug/GrantQuest.lua |  4 ++
 .../tome/dialogs/debug/SummonCreature.lua     |  4 ++
 game/modules/tome/dialogs/orders/Behavior.lua |  4 ++
 game/modules/tome/dialogs/orders/Talents.lua  |  4 ++
 src/core_lua.c                                |  8 ++++
 src/main.c                                    | 37 ++++++++++++-------
 src/map.c                                     |  7 ----
 src/map.h                                     |  2 -
 37 files changed, 184 insertions(+), 60 deletions(-)

diff --git a/game/engines/default/data/keybinds/actions.lua b/game/engines/default/data/keybinds/actions.lua
index d6e64838e6..4b6f879f13 100644
--- a/game/engines/default/data/keybinds/actions.lua
+++ b/game/engines/default/data/keybinds/actions.lua
@@ -18,34 +18,34 @@
 -- darkgod@te4.org
 
 defineAction{
-	default = { "uni:<", "uni:>" },
+	default = { "sym:=<:false:false:false:false", "sym:=>:false:false:false:false" },
 	type = "CHANGE_LEVEL",
 	group = "actions",
 	name = "Go to next/previous level",
 }
 
 defineAction{
-	default = { "uni:G" },
+	default = { "sym:=g:false:true:false:false" },
 	type = "LEVELUP",
 	group = "actions",
 	name = "Levelup window",
 }
 defineAction{
-	default = { "uni:m" },
+	default = { "sym:=m:false:false:false:false" },
 	type = "USE_TALENTS",
 	group = "actions",
 	name = "Use talents",
 }
 
 defineAction{
-	default = { "uni:j", "sym:_q:true:false:false:false" },
+	default = { "sym:=j:false:false:false:false", "sym:_q:true:false:false:false" },
 	type = "SHOW_QUESTS",
 	group = "actions",
 	name = "Show quests",
 }
 
 defineAction{
-	default = { "uni:r", "uni:R" },
+	default = { "sym:=r:false:false:false:false", "sym:=r:false:true:false:false" },
 	type = "REST",
 	group = "actions",
 	name = "Rest for a while",
@@ -73,7 +73,7 @@ defineAction{
 }
 
 defineAction{
-	default = { "uni:l" },
+	default = { "sym:=l:false:false:false:false" },
 	type = "LOOK_AROUND",
 	group = "actions",
 	name = "Look around",
@@ -87,14 +87,14 @@ defineAction{
 }
 
 defineAction{
-	default = { "sym:_t:true:false:false:false" },
+	default = { "sym:=t:true:false:false:false" },
 	type = "SHOW_TIME",
 	group = "actions",
 	name = "Show game calendar",
 }
 
 defineAction{
-	default = { "uni:c", "uni:C" },
+	default = { "sym:=c", "sym:=c:false:true:false:false" },
 	type = "SHOW_CHARACTER_SHEET",
 	group = "actions",
 	name = "Show character sheet",
@@ -107,13 +107,6 @@ defineAction{
 	name = "Switch graphical modes",
 }
 
-defineAction{
-	default = { "uni:?" },
-	type = "HELP",
-	group = "actions",
-	name = "Help",
-}
-
 defineAction{
 	default = { "sym:_RETURN:false:false:false:false", "sym:_KP_ENTER:false:false:false:false" },
 	type = "ACCEPT",
diff --git a/game/engines/default/data/keybinds/interface.lua b/game/engines/default/data/keybinds/interface.lua
index 655bdb0205..7bb381e8bd 100644
--- a/game/engines/default/data/keybinds/interface.lua
+++ b/game/engines/default/data/keybinds/interface.lua
@@ -25,7 +25,7 @@ defineAction{
 }
 
 defineAction{
-	default = { "sym:_m:true:false:false:false" },
+	default = { "sym:=m:true:false:false:false" },
 	type = "SHOW_MESSAGE_LOG",
 	group = "actions",
 	name = "Show message log",
diff --git a/game/engines/default/data/keybinds/inventory.lua b/game/engines/default/data/keybinds/inventory.lua
index 26b5ec066d..f8501c3a83 100644
--- a/game/engines/default/data/keybinds/inventory.lua
+++ b/game/engines/default/data/keybinds/inventory.lua
@@ -18,53 +18,53 @@
 -- darkgod@te4.org
 
 defineAction{
-	default = { "uni:i", },
+	default = { "sym:=i:false:false:false:false", },
 	type = "SHOW_INVENTORY",
 	group = "inventory",
 	name = "Show inventory",
 }
 defineAction{
-	default = { "uni:e", },
+	default = { "sym:=e:false:false:false:false", },
 	type = "SHOW_EQUIPMENT",
 	group = "inventory",
 	name = "Show equipment",
 }
 
 defineAction{
-	default = { "uni:g" },
+	default = { "sym:=g:false:false:false:false" },
 	type = "PICKUP_FLOOR",
 	group = "actions",
 	name = "Pickup items",
 }
 defineAction{
-	default = { "uni:d" },
+	default = { "sym:=d:false:false:false:false" },
 	type = "DROP_FLOOR",
 	group = "actions",
 	name = "Drop items",
 }
 
 defineAction{
-	default = { "uni:w", },
+	default = { "sym:=w:false:false:false:false", },
 	type = "WEAR_ITEM",
 	group = "inventory",
 	name = "Wield/wear items",
 }
 defineAction{
-	default = { "uni:t", },
+	default = { "sym:=t:false:false:false:false", },
 	type = "TAKEOFF_ITEM",
 	group = "inventory",
 	name = "Takeoff items",
 }
 
 defineAction{
-	default = { "uni:u", },
+	default = { "sym:=u:false:false:false:false", },
 	type = "USE_ITEM",
 	group = "inventory",
 	name = "Use items",
 }
 
 defineAction{
-	default = { "uni:x", },
+	default = { "sym:=x:false:false:false:false", },
 	type = "QUICK_SWITCH_WEAPON",
 	group = "inventory",
 	name = "Quick switch weapons set",
diff --git a/game/engines/default/data/keybinds/move.lua b/game/engines/default/data/keybinds/move.lua
index efb06861bc..184bd117d8 100644
--- a/game/engines/default/data/keybinds/move.lua
+++ b/game/engines/default/data/keybinds/move.lua
@@ -76,7 +76,7 @@ defineAction{
 
 -- Running
 defineAction{
-	default = { "uni:." },
+	default = { "sym:=.:false:false:false:false" },
 	type = "RUN",
 	group = "movement",
 	name = "Run",
diff --git a/game/engines/default/engine/Birther.lua b/game/engines/default/engine/Birther.lua
index c2d8ae0ba5..b0fd3b519e 100644
--- a/game/engines/default/engine/Birther.lua
+++ b/game/engines/default/engine/Birther.lua
@@ -139,6 +139,8 @@ function _M:on_register()
 	self:next()
 	self:select(self.list[self.c_list.sel])
 
+	self.key:unicodeInput(true)
+
 	if __module_extra_info.no_quickbirth then return end
 	if self.quickbirth then
 		if __module_extra_info.auto_quickbirth then
diff --git a/game/engines/default/engine/DebugConsole.lua b/game/engines/default/engine/DebugConsole.lua
index d4d6bf76a4..4cd67c84bc 100644
--- a/game/engines/default/engine/DebugConsole.lua
+++ b/game/engines/default/engine/DebugConsole.lua
@@ -31,6 +31,7 @@ commands = {}
 
 function _M:init()
 	engine.Dialog.init(self, "Lua Console", core.display.size())
+	game:onTickEnd(function() self.key:unicodeInput(true) end)
 	self:keyCommands{
 		_RETURN = function()
 			table.insert(self.commands, self.line)
diff --git a/game/engines/default/engine/KeyBind.lua b/game/engines/default/engine/KeyBind.lua
index d1f3741456..09b3acc6b5 100644
--- a/game/engines/default/engine/KeyBind.lua
+++ b/game/engines/default/engine/KeyBind.lua
@@ -117,6 +117,7 @@ end
 function _M:init()
 	engine.KeyCommand.init(self)
 	self.virtuals = {}
+	self.use_unicode = false
 
 	self:bindKeys()
 end
@@ -141,8 +142,8 @@ function _M:findBoundKeys(virtual)
 	return unpack(bs)
 end
 
-function _M:makeKeyString(sym, ctrl, shift, alt, meta, unicode)
-	return ("sym:%s:%s:%s:%s:%s"):format(tostring(self.sym_to_name[sym] or sym), tostring(ctrl), tostring(shift), tostring(alt), tostring(meta)), unicode and "uni:"..unicode
+function _M:makeKeyString(sym, ctrl, shift, alt, meta, unicode, key)
+	return ("sym:%s:%s:%s:%s:%s"):format(tostring(self.sym_to_name[sym] or sym), tostring(ctrl), tostring(shift), tostring(alt), tostring(meta)), key and ("sym:=%s:%s:%s:%s:%s"):format(key, tostring(ctrl), tostring(shift), tostring(alt), tostring(meta)), unicode and "uni:"..unicode
 end
 
 function _M:makeGestureString(gesture)
@@ -166,12 +167,14 @@ function _M:formatKeyString(ks)
 		shift = shift == "true" and true or false
 		alt = alt == "true" and true or false
 		meta = meta == "true" and true or false
-		if tonumber(sym) then
-			sym = tonumber(sym)
+		if sym:sub(1, 1) == "=" then
+			sym = sym:sub(2)
 		else
-			sym = _M[sym]
+			if tonumber(sym) then sym = tonumber(sym)
+			else sym = _M[sym]
+			end
+			sym = core.key.symName(sym)
 		end
-		sym = core.key.symName(sym)
 
 		if ctrl then sym = "[C]+"..sym end
 		if shift then sym = "[S]+"..sym end
@@ -203,24 +206,32 @@ function _M:formatKeyString(ks)
 end
 
 function _M:receiveKey(sym, ctrl, shift, alt, meta, unicode, isup, key, ismouse)
+	if unicode and not self.use_unicode then return end
+
 	self:handleStatus(sym, ctrl, shift, alt, meta, unicode, isup)
 
 	if self.any_key then self.any_key(sym, ctrl, shift, alt, meta, unicode, isup, key) end
 
 	local ks, us
-	if not ismouse then ks, us = self:makeKeyString(sym, ctrl, shift, alt, meta, unicode)
+	if not ismouse then ks, kks, us = self:makeKeyString(sym, ctrl, shift, alt, meta, unicode, key)
 	else ks = self:makeMouseString(sym, ctrl, shift, alt, meta) end
---	print("[BIND]", sym, ctrl, shift, alt, meta, unicode, " :=: ", ks, us, " ?=? ", self.binds[ks], us and self.binds[us])
+--	print("[BIND]", sym, ctrl, shift, alt, meta, unicode, " :=: ", ks, kks, us, " ?=? ", self.binds[ks], kks and self.binds[kks], us and self.binds[us])
 	if self.binds[ks] then
 		for virt, _ in pairs(self.binds[ks]) do if self.virtuals[virt] then
 			if isup and not _M.binds_def[virt].updown then return end
-			self.virtuals[virt](sym, ctrl, shift, alt, meta, unicode, isup)
+			self.virtuals[virt](sym, ctrl, shift, alt, meta, unicode, isup, key)
+			return true
+		end end
+	elseif kks and self.binds[kks] then
+		for virt, _ in pairs(self.binds[kks]) do if self.virtuals[virt] then
+			if isup and not _M.binds_def[virt].updown then return end
+			self.virtuals[virt](sym, ctrl, shift, alt, meta, unicode, isup, key)
 			return true
 		end end
 	elseif us and self.binds[us] then
 		for virt, _ in pairs(self.binds[us]) do if self.virtuals[virt] then
 --			if isup and not _M.binds_def[virt].updown then return end
-			self.virtuals[virt](sym, ctrl, shift, alt, meta, unicode, isup)
+			self.virtuals[virt](sym, ctrl, shift, alt, meta, unicode, isup, key)
 			return true
 		end end
 	end
@@ -228,6 +239,11 @@ function _M:receiveKey(sym, ctrl, shift, alt, meta, unicode, isup, key, ismouse)
 	return engine.KeyCommand.receiveKey(self, sym, ctrl, shift, alt, meta, unicode, isup, key)
 end
 
+--- Allow receiving unicode events
+function _M:unicodeInput(v)
+	self.use_unicode = v
+end
+
 --- Reset all binds
 function _M:reset()
 	self.virtuals = {}
diff --git a/game/engines/default/engine/dialogs/Chat.lua b/game/engines/default/engine/dialogs/Chat.lua
index 8ace9104d4..86e2ad1a9d 100644
--- a/game/engines/default/engine/dialogs/Chat.lua
+++ b/game/engines/default/engine/dialogs/Chat.lua
@@ -57,6 +57,10 @@ function _M:init(chat, id)
 	}
 end
 
+function _M:on_register()
+	game:onTickEnd(function() self.key:unicodeInput(true) end)
+end
+
 function _M:select(item)
 	local a = self.chat:get(self.cur_id).answers[item.answer]
 	if not a then return end
diff --git a/game/engines/default/engine/dialogs/ShowEquipInven.lua b/game/engines/default/engine/dialogs/ShowEquipInven.lua
index aad90445aa..74e08a2fc9 100644
--- a/game/engines/default/engine/dialogs/ShowEquipInven.lua
+++ b/game/engines/default/engine/dialogs/ShowEquipInven.lua
@@ -135,6 +135,10 @@ function _M:init(title, actor, filter, action, on_select)
 	}
 end
 
+function _M:on_register()
+	game:onTickEnd(function() self.key:unicodeInput(true) end)
+end
+
 function _M:defineHotkey(id)
 	if not self.actor or not self.actor.hotkey then return end
 
diff --git a/game/engines/default/engine/dialogs/ShowEquipment.lua b/game/engines/default/engine/dialogs/ShowEquipment.lua
index 1db6713e32..ac773a2e45 100644
--- a/game/engines/default/engine/dialogs/ShowEquipment.lua
+++ b/game/engines/default/engine/dialogs/ShowEquipment.lua
@@ -67,6 +67,10 @@ function _M:init(title, actor, filter, action)
 	}
 end
 
+function _M:on_register()
+	game:onTickEnd(function() self.key:unicodeInput(true) end)
+end
+
 function _M:select(item)
 	if item and self.uis[2] then
 		self.c_desc:switchItem(item, item.desc)
diff --git a/game/engines/default/engine/dialogs/ShowInventory.lua b/game/engines/default/engine/dialogs/ShowInventory.lua
index 06c677c92c..f7c3185ae4 100644
--- a/game/engines/default/engine/dialogs/ShowInventory.lua
+++ b/game/engines/default/engine/dialogs/ShowInventory.lua
@@ -65,6 +65,10 @@ function _M:init(title, inven, filter, action, actor)
 	}
 end
 
+function _M:on_register()
+	game:onTickEnd(function() self.key:unicodeInput(true) end)
+end
+
 function _M:select(item)
 	if item then
 		self.c_desc:switchItem(item, item.desc)
diff --git a/game/engines/default/engine/dialogs/ShowPickupFloor.lua b/game/engines/default/engine/dialogs/ShowPickupFloor.lua
index e86b22f669..5ec7a5e974 100644
--- a/game/engines/default/engine/dialogs/ShowPickupFloor.lua
+++ b/game/engines/default/engine/dialogs/ShowPickupFloor.lua
@@ -73,6 +73,10 @@ function _M:init(title, x, y, filter, action, takeall, actor)
 	}
 end
 
+function _M:on_register()
+	game:onTickEnd(function() self.key:unicodeInput(true) end)
+end
+
 function _M:used()
 	if self.taking_all then return end
 	self:generateList()
diff --git a/game/engines/default/engine/dialogs/ShowStore.lua b/game/engines/default/engine/dialogs/ShowStore.lua
index 62785e2599..721fb63925 100644
--- a/game/engines/default/engine/dialogs/ShowStore.lua
+++ b/game/engines/default/engine/dialogs/ShowStore.lua
@@ -80,6 +80,10 @@ function _M:init(title, store_inven, actor_inven, store_filter, actor_filter, ac
 	}
 end
 
+function _M:on_register()
+	game:onTickEnd(function() self.key:unicodeInput(true) end)
+end
+
 function _M:updateStore()
 	self:generateList()
 end
diff --git a/game/engines/default/engine/dialogs/UseTalents.lua b/game/engines/default/engine/dialogs/UseTalents.lua
index 3f606e3b0c..e8c72d0e69 100644
--- a/game/engines/default/engine/dialogs/UseTalents.lua
+++ b/game/engines/default/engine/dialogs/UseTalents.lua
@@ -114,6 +114,10 @@ Check out the keybinding screen in the game menu to bind hotkeys to a key (defau
 	}
 end
 
+function _M:on_register()
+	game:onTickEnd(function() self.key:unicodeInput(true) end)
+end
+
 function _M:defineHotkey(id)
 	if not self.actor.hotkey then return end
 	local item = self.list[self.c_list.sel]
diff --git a/game/engines/default/engine/interface/ActorInventory.lua b/game/engines/default/engine/interface/ActorInventory.lua
index 066bf099bf..8c60c39532 100644
--- a/game/engines/default/engine/interface/ActorInventory.lua
+++ b/game/engines/default/engine/interface/ActorInventory.lua
@@ -77,6 +77,17 @@ function _M:getInven(id)
 	end
 end
 
+--- Tells if an inventory still has room left
+function _M:canAddToInven(id)
+	if type(id) == "number" then
+		return #self.inven[id] < self.inven[id].max
+	elseif type(id) == "string" then
+		return #self.inven[self["INVEN_"..id]] < self.inven[self["INVEN_"..id]].max
+	else
+		return id
+	end
+end
+
 --- Adds an object to an inventory
 -- @return false if the object could not be added otherwise true and the inventory index where it is now
 function _M:addObject(inven_id, o)
diff --git a/game/engines/default/engine/interface/PlayerHotkeys.lua b/game/engines/default/engine/interface/PlayerHotkeys.lua
index 11003eb622..25422ca972 100644
--- a/game/engines/default/engine/interface/PlayerHotkeys.lua
+++ b/game/engines/default/engine/interface/PlayerHotkeys.lua
@@ -87,12 +87,12 @@ end
 
 --- Switch to previous hotkey page
 function _M:prevHotkeyPage()
-	self.hotkey_page = util.boundWrap(self.hotkey_page - 1, 1, 3)
+	self.hotkey_page = util.boundWrap(self.hotkey_page - 1, 1, 4)
 	self.changed = true
 end
 --- Switch to next hotkey page
 function _M:nextHotkeyPage()
-	self.hotkey_page = util.boundWrap(self.hotkey_page + 1, 1, 3)
+	self.hotkey_page = util.boundWrap(self.hotkey_page + 1, 1, 4)
 	self.changed = true
 end
 --- Switch to hotkey page
diff --git a/game/engines/default/engine/ui/Focusable.lua b/game/engines/default/engine/ui/Focusable.lua
index 704b13eac7..1b502c88c2 100644
--- a/game/engines/default/engine/ui/Focusable.lua
+++ b/game/engines/default/engine/ui/Focusable.lua
@@ -31,4 +31,5 @@ function _M:setFocus(v)
 	if not v then
 		self.focus_decay = self.focus_decay_max
 	end
+	if self.on_focus then self:on_focus(v) end
 end
diff --git a/game/engines/default/engine/ui/Numberbox.lua b/game/engines/default/engine/ui/Numberbox.lua
index 9a879f9f19..31c57bfd25 100644
--- a/game/engines/default/engine/ui/Numberbox.lua
+++ b/game/engines/default/engine/ui/Numberbox.lua
@@ -43,6 +43,10 @@ function _M:init(t)
 	Base.init(self, t)
 end
 
+function _M:on_focus(v)
+	game:onTickEnd(function() self.key:unicodeInput(v) end)
+end
+
 function _M:generate()
 	self.mouse:reset()
 	self.key:reset()
diff --git a/game/engines/default/engine/ui/Textbox.lua b/game/engines/default/engine/ui/Textbox.lua
index 828e6746dd..8bb644b939 100644
--- a/game/engines/default/engine/ui/Textbox.lua
+++ b/game/engines/default/engine/ui/Textbox.lua
@@ -44,6 +44,10 @@ function _M:init(t)
 	Base.init(self, t)
 end
 
+function _M:on_focus(v)
+	game:onTickEnd(function() self.key:unicodeInput(v) end)
+end
+
 function _M:generate()
 	self.mouse:reset()
 	self.key:reset()
diff --git a/game/engines/default/engine/utils.lua b/game/engines/default/engine/utils.lua
index 95560b979f..6b23ef0f8d 100644
--- a/game/engines/default/engine/utils.lua
+++ b/game/engines/default/engine/utils.lua
@@ -130,6 +130,12 @@ function table.listify(t)
 	return tt
 end
 
+function table.keys_to_values(t)
+	local tt = {}
+	for k, e in pairs(t) do tt[e] = k end
+	return tt
+end
+
 function table.keys(t)
 	local tt = {}
 	for k, e in pairs(t) do tt[#tt+1] = k end
diff --git a/game/modules/tome/dialogs/CharacterSheet.lua b/game/modules/tome/dialogs/CharacterSheet.lua
index 58b4e34850..b901f920b5 100644
--- a/game/modules/tome/dialogs/CharacterSheet.lua
+++ b/game/modules/tome/dialogs/CharacterSheet.lua
@@ -109,6 +109,10 @@ function _M:switchTo(kind)
 	self:updateKeys()
 end
 
+function _M:on_register()
+	game:onTickEnd(function() self.key:unicodeInput(true) end)
+end
+
 function _M:updateKeys()
 	self.key:addCommands{
 	_TAB = function() self:tabTabs() end,
diff --git a/game/modules/tome/dialogs/LevelupDialog.lua b/game/modules/tome/dialogs/LevelupDialog.lua
index 8aed9a45d1..8f7352e540 100644
--- a/game/modules/tome/dialogs/LevelupDialog.lua
+++ b/game/modules/tome/dialogs/LevelupDialog.lua
@@ -230,6 +230,8 @@ end
 
 function _M:updateKeys(kind)
 	self.key:reset()
+	self.key:unicodeInput(true)
+
 	if kind == "Stats" then
 		self.key:addCommands{
 			_TAB = function() self:tabTabs() end,
diff --git a/game/modules/tome/dialogs/PartyOrder.lua b/game/modules/tome/dialogs/PartyOrder.lua
index 391763ad30..299c0be8d1 100644
--- a/game/modules/tome/dialogs/PartyOrder.lua
+++ b/game/modules/tome/dialogs/PartyOrder.lua
@@ -50,6 +50,10 @@ function _M:init(actor, def)
 	self.key:addBinds{ EXIT = function() game:unregisterDialog(self) end, }
 end
 
+function _M:on_register()
+	game:onTickEnd(function() self.key:unicodeInput(true) end)
+end
+
 function _M:use(item)
 	if not item then return end
 	game:unregisterDialog(self)
diff --git a/game/modules/tome/dialogs/PartySelect.lua b/game/modules/tome/dialogs/PartySelect.lua
index b6476019b3..16930a84b6 100644
--- a/game/modules/tome/dialogs/PartySelect.lua
+++ b/game/modules/tome/dialogs/PartySelect.lua
@@ -39,6 +39,10 @@ function _M:init()
 	self.key:addBinds{ EXIT = function() game:unregisterDialog(self) end, }
 end
 
+function _M:on_register()
+	game:onTickEnd(function() self.key:unicodeInput(true) end)
+end
+
 function _M:use(item)
 	if not item then return end
 	game:unregisterDialog(self)
diff --git a/game/modules/tome/dialogs/UseTalents.lua b/game/modules/tome/dialogs/UseTalents.lua
index 8b0157b264..e0e54a3455 100644
--- a/game/modules/tome/dialogs/UseTalents.lua
+++ b/game/modules/tome/dialogs/UseTalents.lua
@@ -125,6 +125,10 @@ Right click or press '*' to configure.
 	}
 end
 
+function _M:on_register()
+	game:onTickEnd(function() self.key:unicodeInput(true) end)
+end
+
 function _M:defineHotkey(id)
 	if not self.actor.hotkey then return end
 	local item = self.cur_item
diff --git a/game/modules/tome/dialogs/debug/AlterFaction.lua b/game/modules/tome/dialogs/debug/AlterFaction.lua
index 87680dae84..884567155b 100644
--- a/game/modules/tome/dialogs/debug/AlterFaction.lua
+++ b/game/modules/tome/dialogs/debug/AlterFaction.lua
@@ -49,6 +49,10 @@ function _M:init()
 	self.key:addBinds{ EXIT = function() game:unregisterDialog(self) end, }
 end
 
+function _M:on_register()
+	game:onTickEnd(function() self.key:unicodeInput(true) end)
+end
+
 function _M:use(item)
 	if not item then return end
 	game:unregisterDialog(self)
diff --git a/game/modules/tome/dialogs/debug/ChangeZone.lua b/game/modules/tome/dialogs/debug/ChangeZone.lua
index 0ffe8200b0..6c083e01d6 100644
--- a/game/modules/tome/dialogs/debug/ChangeZone.lua
+++ b/game/modules/tome/dialogs/debug/ChangeZone.lua
@@ -48,6 +48,10 @@ function _M:init()
 	self.key:addBinds{ EXIT = function() game:unregisterDialog(self) end, }
 end
 
+function _M:on_register()
+	game:onTickEnd(function() self.key:unicodeInput(true) end)
+end
+
 function _M:use(item)
 	if not item then return end
 	game:unregisterDialog(self)
diff --git a/game/modules/tome/dialogs/debug/CreateItem.lua b/game/modules/tome/dialogs/debug/CreateItem.lua
index 0fa7ad036b..dc4de16fd7 100644
--- a/game/modules/tome/dialogs/debug/CreateItem.lua
+++ b/game/modules/tome/dialogs/debug/CreateItem.lua
@@ -48,6 +48,10 @@ function _M:init()
 	self.key:addBinds{ EXIT = function() game:unregisterDialog(self) end, }
 end
 
+function _M:on_register()
+	game:onTickEnd(function() self.key:unicodeInput(true) end)
+end
+
 function _M:use(item)
 	if not item then return end
 	game:unregisterDialog(self)
diff --git a/game/modules/tome/dialogs/debug/DebugMain.lua b/game/modules/tome/dialogs/debug/DebugMain.lua
index c9af7d7fc2..4c5c012bd7 100644
--- a/game/modules/tome/dialogs/debug/DebugMain.lua
+++ b/game/modules/tome/dialogs/debug/DebugMain.lua
@@ -39,6 +39,10 @@ function _M:init()
 	self.key:addBinds{ EXIT = function() game:unregisterDialog(self) end, }
 end
 
+function _M:on_register()
+	game:onTickEnd(function() self.key:unicodeInput(true) end)
+end
+
 function _M:use(item)
 	if not item then return end
 	game:unregisterDialog(self)
diff --git a/game/modules/tome/dialogs/debug/GrantQuest.lua b/game/modules/tome/dialogs/debug/GrantQuest.lua
index b54de23077..e88af1b087 100644
--- a/game/modules/tome/dialogs/debug/GrantQuest.lua
+++ b/game/modules/tome/dialogs/debug/GrantQuest.lua
@@ -48,6 +48,10 @@ function _M:init()
 	self.key:addBinds{ EXIT = function() game:unregisterDialog(self) end, }
 end
 
+function _M:on_register()
+	game:onTickEnd(function() self.key:unicodeInput(true) end)
+end
+
 function _M:use(item)
 	if not item then return end
 	game:unregisterDialog(self)
diff --git a/game/modules/tome/dialogs/debug/SummonCreature.lua b/game/modules/tome/dialogs/debug/SummonCreature.lua
index 06a5f163f3..72edd95b42 100644
--- a/game/modules/tome/dialogs/debug/SummonCreature.lua
+++ b/game/modules/tome/dialogs/debug/SummonCreature.lua
@@ -48,6 +48,10 @@ function _M:init()
 	self.key:addBinds{ EXIT = function() game:unregisterDialog(self) end, }
 end
 
+function _M:on_register()
+	game:onTickEnd(function() self.key:unicodeInput(true) end)
+end
+
 function _M:use(item)
 	if not item then return end
 	game:unregisterDialog(self)
diff --git a/game/modules/tome/dialogs/orders/Behavior.lua b/game/modules/tome/dialogs/orders/Behavior.lua
index 5f8532f098..8225e8f13e 100644
--- a/game/modules/tome/dialogs/orders/Behavior.lua
+++ b/game/modules/tome/dialogs/orders/Behavior.lua
@@ -40,6 +40,10 @@ function _M:init(actor, def)
 	self.key:addBinds{ EXIT = function() game:unregisterDialog(self) end, }
 end
 
+function _M:on_register()
+	game:onTickEnd(function() self.key:unicodeInput(true) end)
+end
+
 function _M:use(item)
 	if not item then return end
 	game:unregisterDialog(self)
diff --git a/game/modules/tome/dialogs/orders/Talents.lua b/game/modules/tome/dialogs/orders/Talents.lua
index 4334bbf45f..65177950e2 100644
--- a/game/modules/tome/dialogs/orders/Talents.lua
+++ b/game/modules/tome/dialogs/orders/Talents.lua
@@ -75,6 +75,10 @@ Word travels fast in Maj'Eyal, and if %s is a summon all future summons of the s
 	}
 end
 
+function _M:on_register()
+	game:onTickEnd(function() self.key:unicodeInput(true) end)
+end
+
 function _M:use(item)
 	if not item then return end
 
diff --git a/src/core_lua.c b/src/core_lua.c
index e146c53eee..038043de91 100644
--- a/src/core_lua.c
+++ b/src/core_lua.c
@@ -204,12 +204,20 @@ static int lua_flush_key_events(lua_State *L)
 	return 0;
 }
 
+static int lua_key_unicode(lua_State *L)
+{
+	if (lua_isboolean(L, 1)) SDL_StartTextInput();
+	else SDL_StopTextInput();
+	return 0;
+}
+
 static const struct luaL_reg keylib[] =
 {
 	{"set_current_handler", lua_set_current_keyhandler},
 	{"modState", lua_get_mod_state},
 	{"symName", lua_get_scancode_name},
 	{"flush", lua_flush_key_events},
+	{"unicodeInput", lua_key_unicode},
 	{NULL, NULL},
 };
 
diff --git a/src/main.c b/src/main.c
index 9e66f89c46..63a7106a51 100644
--- a/src/main.c
+++ b/src/main.c
@@ -237,12 +237,29 @@ extern SDL_Cursor *mouse_cursor;
 extern SDL_Cursor *mouse_cursor_down;
 void on_event(SDL_Event *event)
 {
-	static char *last_unicode = NULL;
-
 	switch (event->type) {
 	case SDL_TEXTINPUT:
-		if (last_unicode) free(last_unicode);
-		last_unicode = strdup(event->text.text);
+		if (current_keyhandler != LUA_NOREF)
+		{
+			lua_rawgeti(L, LUA_REGISTRYINDEX, current_keyhandler);
+			lua_pushstring(L, "receiveKey");
+			lua_gettable(L, -2);
+			lua_remove(L, -2);
+			lua_rawgeti(L, LUA_REGISTRYINDEX, current_keyhandler);
+			lua_pushnumber(L, 0);
+
+			SDL_Keymod _pKeyState = SDL_GetModState();
+			lua_pushboolean(L, (_pKeyState & KMOD_CTRL) ? TRUE : FALSE);
+			lua_pushboolean(L, (_pKeyState & KMOD_SHIFT) ? TRUE : FALSE);
+			lua_pushboolean(L, (_pKeyState & KMOD_ALT) ? TRUE : FALSE);
+			lua_pushboolean(L, (_pKeyState & KMOD_GUI) ? TRUE : FALSE);
+
+			lua_pushstring(L, event->text.text);
+			lua_pushboolean(L, FALSE);
+			lua_pushnil(L);
+
+			docall(L, 9, 0);
+		}
 		break;
 	case SDL_KEYDOWN:
 	case SDL_KEYUP:
@@ -261,14 +278,7 @@ void on_event(SDL_Event *event)
 			lua_pushboolean(L, (_pKeyState & KMOD_ALT) ? TRUE : FALSE);
 			lua_pushboolean(L, (_pKeyState & KMOD_GUI) ? TRUE : FALSE);
 
-			if (last_unicode)
-			{
-				lua_pushstring(L, last_unicode);
-				free(last_unicode);
-				last_unicode = NULL;
-			}
-			else
-				lua_pushnil(L);
+			lua_pushnil(L);
 			lua_pushboolean(L, (event->type == SDL_KEYUP) ? TRUE : FALSE);
 
 			/* Convert unicode UCS-2 to UTF8 string */
@@ -983,10 +993,9 @@ int main(int argc, char *argv[])
 	/* Sets up OpenGL double buffering */
 	resizeWindow(WIDTH, HEIGHT);
 
-	// Allow getting unicode events
-	SDL_StartTextInput();
 	// Allow screensaver to work
 	SDL_EnableScreenSaver();
+	SDL_StartTextInput();
 
 	// Get OpenGL capabilities
 	multitexture_active = GLEW_ARB_multitexture;
diff --git a/src/map.c b/src/map.c
index 95c03f2c3a..595531ffe6 100644
--- a/src/map.c
+++ b/src/map.c
@@ -55,8 +55,6 @@ static int map_object_new(lua_State *L)
 
 	obj->move_max = 0;
 
-	obj->closed = FALSE;
-
 	obj->cb_ref = LUA_NOREF;
 
 	obj->mm_r = -1;
@@ -88,8 +86,6 @@ static int map_object_free(lua_State *L)
 	map_object *obj = (map_object*)auxiliar_checkclass(L, "core{mapobj}", 1);
 	int i;
 
-	obj->closed = TRUE;
-
 	for (i = 0; i < obj->nb_textures; i++)
 		if (obj->textures_ref[i] != LUA_NOREF)
 			luaL_unref(L, LUA_REGISTRYINDEX, obj->textures_ref[i]);
@@ -1089,8 +1085,6 @@ void display_map_quad(GLuint *cur_tex, int *vert_idx, int *col_idx, map_type *ma
 	GLfloat *colors = map->colors;
 	GLfloat *texcoords = map->texcoords;
 
-	if (m->closed) exit(2);
-
 	/********************************************************
 	 ** Select the color to use
 	 ********************************************************/
@@ -1213,7 +1207,6 @@ void display_map_quad(GLuint *cur_tex, int *vert_idx, int *col_idx, map_type *ma
 	dm = m;
 	while (dm)
 	{
-		if (dm->closed) exit(3);
 		tglBindTexture(GL_TEXTURE_2D, dm->textures[0]);
 		DO_QUAD(dm, dx + (dm->dx + animdx) * map->tile_w, dy + (dm->dy + animdy) * map->tile_h, dm->dw, dm->dh, dm->scale, r, g, b, a, m->next);
 		dm->animdx = animdx;
diff --git a/src/map.h b/src/map.h
index 4aba6b2251..6b1c18ff15 100644
--- a/src/map.h
+++ b/src/map.h
@@ -52,8 +52,6 @@ struct s_map_object {
 
 	int cb_ref;
 
-	bool closed;
-
 	struct s_map_object *next;
 	int next_ref;
 };
-- 
GitLab