1fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert#include "pseudolocalize.h"
2fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert
3fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringertusing namespace std;
4fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert
5a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin// String basis to generate expansion
6a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Kruminstatic const String16 k_expansion_string = String16("one two three "
7a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin    "four five six seven eight nine ten eleven twelve thirteen "
8a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin    "fourteen fiveteen sixteen seventeen nineteen twenty");
9a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin
10a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin// Special unicode characters to override directionality of the words
11a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Kruminstatic const String16 k_rlm = String16("\xe2\x80\x8f");
12a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Kruminstatic const String16 k_rlo = String16("\xE2\x80\xae");
13a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Kruminstatic const String16 k_pdf = String16("\xE2\x80\xac");
14a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin
15a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin// Placeholder marks
16a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Kruminstatic const String16 k_placeholder_open = String16("\xc2\xbb");
17a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Kruminstatic const String16 k_placeholder_close = String16("\xc2\xab");
18a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin
19fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringertstatic const char*
20a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Kruminpseudolocalize_char(const char16_t c)
21fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert{
22fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert    switch (c) {
23a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case 'a':   return "\xc3\xa5";
24a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case 'b':   return "\xc9\x93";
25a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case 'c':   return "\xc3\xa7";
26a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case 'd':   return "\xc3\xb0";
27a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case 'e':   return "\xc3\xa9";
28fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert        case 'f':   return "\xc6\x92";
29fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert        case 'g':   return "\xc4\x9d";
30a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case 'h':   return "\xc4\xa5";
31a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case 'i':   return "\xc3\xae";
32fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert        case 'j':   return "\xc4\xb5";
33a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case 'k':   return "\xc4\xb7";
34a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case 'l':   return "\xc4\xbc";
35fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert        case 'm':   return "\xe1\xb8\xbf";
36a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case 'n':   return "\xc3\xb1";
37a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case 'o':   return "\xc3\xb6";
38a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case 'p':   return "\xc3\xbe";
39fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert        case 'q':   return "\x51";
40a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case 'r':   return "\xc5\x95";
41fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert        case 's':   return "\xc5\xa1";
42a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case 't':   return "\xc5\xa3";
43a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case 'u':   return "\xc3\xbb";
44fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert        case 'v':   return "\x56";
45a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case 'w':   return "\xc5\xb5";
46fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert        case 'x':   return "\xd1\x85";
47a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case 'y':   return "\xc3\xbd";
48a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case 'z':   return "\xc5\xbe";
49fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert        case 'A':   return "\xc3\x85";
50fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert        case 'B':   return "\xce\xb2";
51a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case 'C':   return "\xc3\x87";
52a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case 'D':   return "\xc3\x90";
53a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case 'E':   return "\xc3\x89";
54a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case 'G':   return "\xc4\x9c";
55a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case 'H':   return "\xc4\xa4";
56a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case 'I':   return "\xc3\x8e";
57a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case 'J':   return "\xc4\xb4";
58fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert        case 'K':   return "\xc4\xb6";
59a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case 'L':   return "\xc4\xbb";
60fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert        case 'M':   return "\xe1\xb8\xbe";
61a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case 'N':   return "\xc3\x91";
62a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case 'O':   return "\xc3\x96";
63a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case 'P':   return "\xc3\x9e";
64fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert        case 'Q':   return "\x71";
65a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case 'R':   return "\xc5\x94";
66a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case 'S':   return "\xc5\xa0";
67a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case 'T':   return "\xc5\xa2";
68a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case 'U':   return "\xc3\x9b";
69fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert        case 'V':   return "\xce\xbd";
70a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case 'W':   return "\xc5\xb4";
71fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert        case 'X':   return "\xc3\x97";
72a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case 'Y':   return "\xc3\x9d";
73fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert        case 'Z':   return "\xc5\xbd";
74a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case '!':   return "\xc2\xa1";
75a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case '?':   return "\xc2\xbf";
76a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case '$':   return "\xe2\x82\xac";
77fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert        default:    return NULL;
78fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert    }
79fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert}
80fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert
810a1eed394fa287523b105aa569ed6348f4986483Elliott Hughesstatic bool
82a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Kruminis_possible_normal_placeholder_end(const char16_t c) {
83a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin    switch (c) {
84a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case 's': return true;
85a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case 'S': return true;
86a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case 'c': return true;
87a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case 'C': return true;
88a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case 'd': return true;
89a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case 'o': return true;
90a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case 'x': return true;
91a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case 'X': return true;
92a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case 'f': return true;
93a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case 'e': return true;
94a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case 'E': return true;
95a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case 'g': return true;
96a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case 'G': return true;
97a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case 'a': return true;
98a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case 'A': return true;
99a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case 'b': return true;
100a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case 'B': return true;
101a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case 'h': return true;
102a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case 'H': return true;
103a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case '%': return true;
104a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        case 'n': return true;
105a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        default:  return false;
106a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin    }
107a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin}
108a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin
109a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton KruminString16
110a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Kruminpseudo_generate_expansion(const unsigned int length) {
111a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin    String16 result = k_expansion_string;
112a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin    const char16_t* s = result.string();
113a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin    if (result.size() < length) {
114a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        result += String16(" ");
115a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        result += pseudo_generate_expansion(length - result.size());
116a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin    } else {
117a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        int ext = 0;
118a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        // Should contain only whole words, so looking for a space
119a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        for (unsigned int i = length + 1; i < result.size(); ++i) {
120a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin          ++ext;
121a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin          if (s[i] == ' ') {
122a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin            break;
123a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin          }
124a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        }
125a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        result.remove(length + ext, 0);
126a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin    }
127a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin    return result;
128a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin}
129a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin
130fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert/**
131fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert * Converts characters so they look like they've been localized.
132fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert *
133fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert * Note: This leaves escape sequences untouched so they can later be
134fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert * processed by ResTable::collectString in the normal way.
135fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert */
136a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton KruminString16
137a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Kruminpseudolocalize_string(const String16& source)
138fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert{
139a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin    const char16_t* s = source.string();
140a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin    String16 result;
141a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin    const size_t I = source.size();
142fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert    for (size_t i=0; i<I; i++) {
143a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        char16_t c = s[i];
144fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert        if (c == '\\') {
145a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin            // Escape syntax, no need to pseudolocalize
146fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert            if (i<I-1) {
147a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                result += String16("\\");
148fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert                i++;
149fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert                c = s[i];
150fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert                switch (c) {
151fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert                    case 'u':
152fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert                        // this one takes up 5 chars
153a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                        result += String16(s+i, 5);
154fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert                        i += 4;
155fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert                        break;
156fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert                    case 't':
157fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert                    case 'n':
158fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert                    case '#':
159fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert                    case '@':
160fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert                    case '?':
161fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert                    case '"':
162fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert                    case '\'':
163fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert                    case '\\':
164fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert                    default:
165a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                        result.append(&c, 1);
166fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert                        break;
167fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert                }
168fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert            } else {
169a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                result.append(&c, 1);
170a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin            }
171a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        } else if (c == '%') {
172a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin            // Placeholder syntax, no need to pseudolocalize
173a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin            result += k_placeholder_open;
174a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin            bool end = false;
175a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin            result.append(&c, 1);
176a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin            while (!end && i < I) {
177a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                ++i;
178a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                c = s[i];
179a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                result.append(&c, 1);
180a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                if (is_possible_normal_placeholder_end(c)) {
181a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                    end = true;
182a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                } else if (c == 't') {
183a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                    ++i;
184a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                    c = s[i];
185a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                    result.append(&c, 1);
186a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                    end = true;
187a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                }
188a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin            }
189a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin            result += k_placeholder_close;
190a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        } else if (c == '<' || c == '&') {
191a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin            // html syntax, no need to pseudolocalize
192a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin            bool tag_closed = false;
193a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin            while (!tag_closed && i < I) {
194a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                if (c == '&') {
195a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                    String16 escape_text;
196a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                    escape_text.append(&c, 1);
197a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                    bool end = false;
198a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                    size_t htmlCodePos = i;
199a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                    while (!end && htmlCodePos < I) {
200a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                        ++htmlCodePos;
201a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                        c = s[htmlCodePos];
202a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                        escape_text.append(&c, 1);
203a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                        // Valid html code
204a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                        if (c == ';') {
205a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                            end = true;
206a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                            i = htmlCodePos;
207a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                        }
208a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                        // Wrong html code
209a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                        else if (!((c == '#' ||
210a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                 (c >= 'a' && c <= 'z') ||
211a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                 (c >= 'A' && c <= 'Z') ||
212a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                                 (c >= '0' && c <= '9')))) {
213a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                            end = true;
214a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                        }
215a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                    }
216a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                    result += escape_text;
217a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                    if (escape_text != String16("&lt;")) {
218a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                        tag_closed = true;
219a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                    }
220a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                    continue;
221a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                }
222a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                if (c == '>') {
223a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                    tag_closed = true;
224a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                    result.append(&c, 1);
225a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                    continue;
226a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                }
227a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                result.append(&c, 1);
228a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                i++;
229a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                c = s[i];
230fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert            }
231fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert        } else {
232a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin            // This is a pure text that should be pseudolocalized
233fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert            const char* p = pseudolocalize_char(c);
234fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert            if (p != NULL) {
235a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                result += String16(p);
236fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert            } else {
237a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                result.append(&c, 1);
238fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert            }
239fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert        }
240fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert    }
241fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert    return result;
242fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert}
243fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert
244a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton KruminString16
245a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Kruminpseudobidi_string(const String16& source)
246a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin{
247a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin    const char16_t* s = source.string();
248a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin    String16 result;
249a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin    result += k_rlm;
250a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin    result += k_rlo;
251a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin    for (size_t i=0; i<source.size(); i++) {
252a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        char16_t c = s[i];
253a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        switch(c) {
254a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin            case ' ': result += k_pdf;
255a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                      result += k_rlm;
256a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                      result.append(&c, 1);
257a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                      result += k_rlm;
258a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                      result += k_rlo;
259a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                      break;
260a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin            default: result.append(&c, 1);
261a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin                     break;
262a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin        }
263a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin    }
264a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin    result += k_pdf;
265a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin    result += k_rlm;
266a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin    return result;
267a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin}
268fb903a45d7b924c1dfacadaa99ebdf93fd8a1de4Bjorn Bringert
269