Partially fix unicode name truncation.
This fix ensures that name truncation always happens on codepoint boundaries and that a name has exactly 5 visible codepoints. This should cover all possible cases unless names can have grapheme clusters, afaik this is not the case.
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
-- Copyright 2023 <omicron.me@protonmail.com>
|
-- Copyright 2023 <omicron.me@protonmail.com>
|
||||||
--
|
--
|
||||||
-- This file is part of Omicron Frames
|
-- This file is part of Omicron Frames
|
||||||
--
|
--
|
||||||
-- Omicron Frames is free software: you can redistribute it and/or modify it
|
-- Omicron Frames is free software: you can redistribute it and/or modify it
|
||||||
-- under the terms of the GNU General Public License as published by the Free
|
-- under the terms of the GNU General Public License as published by the Free
|
||||||
-- Software Foundation, either version 3 of the License, or (at your option)
|
-- Software Foundation, either version 3 of the License, or (at your option)
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
-- more details.
|
-- more details.
|
||||||
--
|
--
|
||||||
-- You should have received a copy of the GNU General Public License along with
|
-- You should have received a copy of the GNU General Public License along with
|
||||||
-- Omicron Frames. If not, see <https://www.gnu.org/licenses/>.
|
-- Omicron Frames. If not, see <https://www.gnu.org/licenses/>.
|
||||||
local omif = select(2, ...)
|
local omif = select(2, ...)
|
||||||
local types = omif.GetModule("types")
|
local types = omif.GetModule("types")
|
||||||
|
|
||||||
@@ -35,24 +35,39 @@ types.UnitFrame = UnitFrame
|
|||||||
|
|
||||||
|
|
||||||
local colors = {
|
local colors = {
|
||||||
hostile = {0.5, 0.0, 0.0},
|
hostile = { 0.5, 0.0, 0.0 },
|
||||||
neutral = {0.7, 0.7, 0.0},
|
neutral = { 0.7, 0.7, 0.0 },
|
||||||
healthy = {0, 0.1, 0},
|
healthy = { 0, 0.1, 0 },
|
||||||
high = {0, 1.0, 0},
|
high = { 0, 1.0, 0 },
|
||||||
mid = {1.0, 1.0, 0},
|
mid = { 1.0, 1.0, 0 },
|
||||||
low = {1.0, 0.0, 0},
|
low = { 1.0, 0.0, 0 },
|
||||||
offline = {0.7, 0.7, 0.7},
|
offline = { 0.7, 0.7, 0.7 },
|
||||||
dead = {0.7, 0.7, 0.7},
|
dead = { 0.7, 0.7, 0.7 },
|
||||||
magic = {0.4, 0.4, 1.0},
|
magic = { 0.4, 0.4, 1.0 },
|
||||||
disease = {0.4, 0.2, 0.0},
|
disease = { 0.4, 0.2, 0.0 },
|
||||||
poison = {0.0, 0.7, 0.7},
|
poison = { 0.0, 0.7, 0.7 },
|
||||||
curse = {0.7, 0.0, 0.7},
|
curse = { 0.7, 0.0, 0.7 },
|
||||||
immune = {0.0, 0.2, 0.4},
|
immune = { 0.0, 0.2, 0.4 },
|
||||||
bomb = {1.0, 0.7, 0.7},
|
bomb = { 1.0, 0.7, 0.7 },
|
||||||
cyan = {0.0, 0.8, 0.8},
|
cyan = { 0.0, 0.8, 0.8 },
|
||||||
white = {1.0, 1.0, 1.0}
|
white = { 1.0, 1.0, 1.0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
-- This trucates _codepoints_ not graphemes. If combination codepoints are
|
||||||
|
-- contained in the string, it will not properly truncate and may return
|
||||||
|
-- incorrect graphemes
|
||||||
|
local function utf8_truncate(s, n)
|
||||||
|
local init = 0
|
||||||
|
for _ = 1, n do
|
||||||
|
local _, last = string.find(s, ".[\128-\191]*", init + 1)
|
||||||
|
if not last then
|
||||||
|
return s
|
||||||
|
end
|
||||||
|
init = last
|
||||||
|
end
|
||||||
|
return string.sub(s, 1, init)
|
||||||
|
end
|
||||||
|
|
||||||
---@param unit string
|
---@param unit string
|
||||||
---@param config table
|
---@param config table
|
||||||
function UnitFrame:Init(unit, config)
|
function UnitFrame:Init(unit, config)
|
||||||
@@ -127,7 +142,7 @@ function UnitFrame:StartRangeTicker()
|
|||||||
if self.rangeTicker then
|
if self.rangeTicker then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local delta = 0.45 + (fastrandom(0, 100)/1000)
|
local delta = 0.45 + (fastrandom(0, 100) / 1000)
|
||||||
self.rangeTicker = C_Timer.NewTicker(delta, function()
|
self.rangeTicker = C_Timer.NewTicker(delta, function()
|
||||||
self:UpdateRange()
|
self:UpdateRange()
|
||||||
end)
|
end)
|
||||||
@@ -157,7 +172,7 @@ end
|
|||||||
-- Returns
|
-- Returns
|
||||||
-- true if the unit is in range
|
-- true if the unit is in range
|
||||||
-- false if the unit is not in range
|
-- false if the unit is not in range
|
||||||
-- nil if it could not be determined
|
-- nil if it could not be determined
|
||||||
function UnitFrame:IsInRange()
|
function UnitFrame:IsInRange()
|
||||||
local unit = self.unit
|
local unit = self.unit
|
||||||
local friendlySpell = self.rangeFriendly
|
local friendlySpell = self.rangeFriendly
|
||||||
@@ -169,8 +184,8 @@ function UnitFrame:IsInRange()
|
|||||||
elseif enemySpell and UnitCanAttack("player", unit) then
|
elseif enemySpell and UnitCanAttack("player", unit) then
|
||||||
return IsSpellInRange(enemySpell, unit) == 1
|
return IsSpellInRange(enemySpell, unit) == 1
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Fall back to raid/party only range check
|
-- Fall back to raid/party only range check
|
||||||
local inRange, checkedRange = UnitInRange(unit)
|
local inRange, checkedRange = UnitInRange(unit)
|
||||||
if checkedRange then
|
if checkedRange then
|
||||||
return inRange
|
return inRange
|
||||||
@@ -181,7 +196,7 @@ end
|
|||||||
|
|
||||||
function UnitFrame:UpdateRange()
|
function UnitFrame:UpdateRange()
|
||||||
local unit = self.unit
|
local unit = self.unit
|
||||||
|
|
||||||
if UnitIsDeadOrGhost(unit) then
|
if UnitIsDeadOrGhost(unit) then
|
||||||
self.secureFrame:SetAlpha(1.0)
|
self.secureFrame:SetAlpha(1.0)
|
||||||
return
|
return
|
||||||
@@ -235,7 +250,7 @@ function UnitFrame:PrepareWheelBinds(bindings)
|
|||||||
-- scroll wheel to the current unit frame button when the mouse enters and
|
-- scroll wheel to the current unit frame button when the mouse enters and
|
||||||
-- to unbind it when the mouse leaves. When the keybind is triggered the
|
-- to unbind it when the mouse leaves. When the keybind is triggered the
|
||||||
-- button will receive a click with a custom button name
|
-- button will receive a click with a custom button name
|
||||||
|
|
||||||
-- Build a table with all lines of the scroll wheel + modifier combinations
|
-- Build a table with all lines of the scroll wheel + modifier combinations
|
||||||
-- we want to bind, then concat it with newlines into a full script
|
-- we want to bind, then concat it with newlines into a full script
|
||||||
local unit = self.unit
|
local unit = self.unit
|
||||||
@@ -247,13 +262,13 @@ function UnitFrame:PrepareWheelBinds(bindings)
|
|||||||
local prefix = ModifiersToPrefix(bind.mods)
|
local prefix = ModifiersToPrefix(bind.mods)
|
||||||
local button = bind.button == "wheel-up" and "MOUSEWHEELUP" or "MOUSEWHEELDOWN"
|
local button = bind.button == "wheel-up" and "MOUSEWHEELUP" or "MOUSEWHEELDOWN"
|
||||||
table.insert(bindScript,
|
table.insert(bindScript,
|
||||||
string.format([[self:SetBindingClick(false, "%s%s", "OmicronSecureFrame%s", "%s%s")]],
|
string.format([[self:SetBindingClick(false, "%s%s", "OmicronSecureFrame%s", "%s%s")]],
|
||||||
prefix, button, unit, prefix, bind.button
|
prefix, button, unit, prefix, bind.button
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local secure = self.secureFrame
|
local secure = self.secureFrame
|
||||||
local bindScript = table.concat(bindScript, "\n")
|
local bindScript = table.concat(bindScript, "\n")
|
||||||
|
|
||||||
@@ -272,7 +287,7 @@ function UnitFrame:SetMouseBinds(binds)
|
|||||||
|
|
||||||
secure:RegisterForClicks("AnyDown")
|
secure:RegisterForClicks("AnyDown")
|
||||||
self:PrepareWheelBinds(binds)
|
self:PrepareWheelBinds(binds)
|
||||||
|
|
||||||
for _, bind in ipairs(binds) do
|
for _, bind in ipairs(binds) do
|
||||||
local prefix = ModifiersToPrefix(bind.mods)
|
local prefix = ModifiersToPrefix(bind.mods)
|
||||||
local button
|
local button
|
||||||
@@ -295,7 +310,7 @@ function UnitFrame:SetMouseBinds(binds)
|
|||||||
if bind.kind == "macro" then
|
if bind.kind == "macro" then
|
||||||
self:SetMacroAction(button, bind.data)
|
self:SetMacroAction(button, bind.data)
|
||||||
elseif bind.kind == "spell" then
|
elseif bind.kind == "spell" then
|
||||||
self:SetSpellAction(button, bind.data)
|
self:SetSpellAction(button, bind.data)
|
||||||
else
|
else
|
||||||
secure:SetAttribute(button, bind.kind)
|
secure:SetAttribute(button, bind.kind)
|
||||||
end
|
end
|
||||||
@@ -455,7 +470,7 @@ end
|
|||||||
|
|
||||||
function UnitFrame:ROLE_CHANGED_INFORM(name, changer, old, new)
|
function UnitFrame:ROLE_CHANGED_INFORM(name, changer, old, new)
|
||||||
if UnitName(self.unit) == name then
|
if UnitName(self.unit) == name then
|
||||||
self:UpdateRole(new)
|
self:UpdateRole(new)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -563,7 +578,7 @@ function UnitFrame:UpdateHealthColor()
|
|||||||
elseif isFriend and pct >= 0.90 then
|
elseif isFriend and pct >= 0.90 then
|
||||||
self.hp:SetColor(unpack(colors.healthy))
|
self.hp:SetColor(unpack(colors.healthy))
|
||||||
elseif isFriend and pct >= 0.75 then
|
elseif isFriend and pct >= 0.75 then
|
||||||
local progress = (pct - 0.75) / (0.90-0.75)
|
local progress = (pct - 0.75) / (0.90 - 0.75)
|
||||||
self.hp:SetInterpolatedColor(colors.mid, colors.high, progress)
|
self.hp:SetInterpolatedColor(colors.mid, colors.high, progress)
|
||||||
else
|
else
|
||||||
local progress = pct / 0.75
|
local progress = pct / 0.75
|
||||||
@@ -580,25 +595,10 @@ function UnitFrame:UpdateName()
|
|||||||
-- TODO: UnitClass can return Unknown and the color can be nil. Having
|
-- TODO: UnitClass can return Unknown and the color can be nil. Having
|
||||||
-- the unit exist but not fully loaded is possibly a state we want to
|
-- the unit exist but not fully loaded is possibly a state we want to
|
||||||
-- handle more generally
|
-- handle more generally
|
||||||
local color = RAID_CLASS_COLORS[class] or {r=1, g=1, b=1}
|
local color = RAID_CLASS_COLORS[class] or { r = 1, g = 1, b = 1 }
|
||||||
self.name:SetTextColor(color.r, color.g, color.b)
|
self.name:SetTextColor(color.r, color.g, color.b)
|
||||||
else
|
else
|
||||||
self.name:SetTextColor(1, 1, 1)
|
self.name:SetTextColor(1, 1, 1)
|
||||||
end
|
end
|
||||||
self.name:SetText(UnitName(self.unit):sub(1, 5))
|
self.name:SetText(utf8_truncate((UnitName(self.unit)), 5))
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[
|
|
||||||
-- UNIT_AURA
|
|
||||||
-- UNIT_CLASSIFICATION_CHANGED
|
|
||||||
-- UNIT_COMBAT
|
|
||||||
-- UNIT_CONNECTION
|
|
||||||
-- UNIT_DISPLAYPOWER
|
|
||||||
-- UNIT_FACTION
|
|
||||||
-- UNIT_FLAGS
|
|
||||||
-- UNIT_LEVEL
|
|
||||||
-- UNIT_MANA
|
|
||||||
-- UNIT_HEALTH_PREDICTION
|
|
||||||
-- UNIT_PHASE
|
|
||||||
]]--
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user