about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--ranger/ext/utfwidth.py19
-rw-r--r--ranger/gui/bar.py16
2 files changed, 28 insertions, 7 deletions
diff --git a/ranger/ext/utfwidth.py b/ranger/ext/utfwidth.py
index a506c676..885e1381 100644
--- a/ranger/ext/utfwidth.py
+++ b/ranger/ext/utfwidth.py
@@ -18,6 +18,8 @@
 # ----
 # This file contains portions of code from cmus (uchar.c).
 
+import sys
+
 NARROW = 1
 WIDE = 2
 
@@ -32,6 +34,12 @@ def uwid(string):
 		i += bytelen
 	return width
 
+def uwid_of_first_char(string):
+	if not string:
+		return NARROW
+	bytelen = utf_byte_length(string[0])
+	return utf_char_width(string[:bytelen])
+
 def uchars(string):
 	"""Return a list with one string for each character"""
 	end = len(string)
@@ -43,6 +51,17 @@ def uchars(string):
 		i += bytelen
 	return result
 
+def uwidslice(string, start=0, end=sys.maxint):
+	chars = []
+	for c in uchars(string):
+		c_wid = utf_char_width(c)
+		if c_wid == NARROW:
+			chars.append(c)
+		elif c_wid == WIDE:
+			chars.append("")
+			chars.append(c)
+	return "".join(chars[start:end])
+
 def utf_byte_length(string):
 	"""Return the byte length of one utf character"""
 	firstord = ord(string[0])
diff --git a/ranger/gui/bar.py b/ranger/gui/bar.py
index 41cc8133..ab38562b 100644
--- a/ranger/gui/bar.py
+++ b/ranger/gui/bar.py
@@ -13,7 +13,8 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-from ranger.ext.utfwidth import uwid
+from ranger.ext.utfwidth import uwid, uwidslice, utf_char_width, \
+		uwid_of_first_char
 
 class Bar(object):
 	left = None
@@ -75,10 +76,11 @@ class Bar(object):
 		# Shrink items to a minimum size of 1 until there is enough room.
 		for item in self.left:
 			if not item.fixed:
-				itemlen = len(item)
-				if oversize > itemlen - 1:
-					item.cut_off_to(1)
-					oversize -= (itemlen - 1)
+				itemlen = uwid(item.string)
+				minimal_width = uwid_of_first_char(item.string)
+				if oversize > itemlen - minimal_width:
+					item.cut_off_to(minimal_width)
+					oversize -= (itemlen - minimal_width)
 				else:
 					item.cut_off(oversize)
 					break
@@ -132,10 +134,10 @@ class ColoredString(object):
 
 	def cut_off(self, n):
 		if n >= 1:
-			self.string = self.string[:-n]
+			self.string = uwidslice(self.string, 0, -n)
 
 	def cut_off_to(self, n):
-		self.string = self.string[:n]
+		self.string = uwidslice(self.string, 0, n)
 
 	def __len__(self):
 		return uwid(self.string)