summaryrefslogtreecommitdiff
blob: 8b9e1e8fb9d0cd8ef6bf0bd5889c74c38578fc41 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
From b1f6a30bcce020b3c377434137de9856a09b899a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Amadeusz=20=C5=BBo=C5=82nowski?= <aidecoe@aidecoe.name>
Date: Fri, 11 Nov 2011 11:27:43 +0100
Subject: [PATCH] Make scroll UTF-8 aware.  Fixes bug #3134941.

---
 src/scroll.c |   44 ++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 42 insertions(+), 2 deletions(-)

diff --git a/src/scroll.c b/src/scroll.c
index f78f807..738db0d 100644
--- a/src/scroll.c
+++ b/src/scroll.c
@@ -34,12 +34,33 @@
 
 struct scroll_data {
 	char *text;
+	unsigned int show_orig;
 	unsigned int show;
 	unsigned int step;
 	unsigned int start;
 	long resetcolor;
 };
 
+int utf8_charlen(char c) {
+	unsigned char uc = (unsigned char) c;
+	int len = 0;
+
+	if ((uc & 0x80) == 0)
+		return 1;
+
+	while ((uc & 0x80) != 0) {
+		++len;
+		uc <<= 1;
+	}
+
+	return (len > 0 && len <= 4) ? len : -1;
+}
+
+int is_utf8_char_tail(char c) {
+	unsigned char uc = (unsigned char) c;
+	return (uc & 0xc0) == 0x80;
+}
+
 void parse_scroll_arg(struct text_object *obj, const char *arg, void *free_at_crash)
 {
 	struct scroll_data *sd;
@@ -60,15 +81,18 @@ void parse_scroll_arg(struct text_object *obj, const char *arg, void *free_at_cr
 		sd->step = 1;
 	}
 	sd->text = malloc(strlen(arg + n1) + sd->show + 1);
+	// sd->show value may change when there are UTF-8 chars to be shown, so
+	// save its origin value
+	sd->show_orig = sd->show;
 
 	if (strlen(arg) > sd->show) {
 		for(n2 = 0; (unsigned int) n2 < sd->show; n2++) {
-		    sd->text[n2] = ' ';
+			sd->text[n2] = ' ';
 		}
 		sd->text[n2] = 0;
 	}
 	else
-	    sd->text[0] = 0;
+		sd->text[0] = 0;
 
 	strcat(sd->text, arg + n1);
 	sd->start = 0;
@@ -82,9 +106,13 @@ void print_scroll(struct text_object *obj, char *p, int p_max_size, struct infor
 {
 	struct scroll_data *sd = obj->data.opaque;
 	unsigned int j, colorchanges = 0, frontcolorchanges = 0, visibcolorchanges = 0, strend;
+	int charlen = 0;
+	unsigned int utf8lenfix = 0;
 	char *pwithcolors;
 	char buf[max_user_text];
 
+	sd->show = sd->show_orig;
+
 	if (!sd)
 		return;
 
@@ -109,6 +137,18 @@ void print_scroll(struct text_object *obj, char *p, int p_max_size, struct infor
 	while(*(buf + sd->start) == SPECIAL_CHAR) {
 		sd->start++;
 	}
+	//skip parts of UTF-8 character which messes up display
+	while(is_utf8_char_tail(*(buf + sd->start))) {
+		sd->start++;
+	}
+	//extend length to be shown for wide characters
+	j = 0;
+	while(j < sd->show + visibcolorchanges + utf8lenfix) {
+		charlen = utf8_charlen(*(buf + sd->start + j));
+		utf8lenfix += (charlen > 1 ? charlen - 1 : 0);
+		j += charlen;
+	}
+	sd->show = sd->show_orig + utf8lenfix;
 	//place all chars that should be visible in p, including colorchanges
 	for(j=0; j < sd->show + visibcolorchanges; j++) {
 		p[j] = *(buf + sd->start + j);
-- 
1.7.8.rc1