1
2
3 #include "studiox_includes.h"
4 #include "xml_writer.h"
5 #include "xml_reader.h"
6 #include "csv_read_write.h"
7 #include "config_languages_dlg.h"
8
9 ///////////////////////////////////////////////////////////////////////////////
csv_read_write()10 csv_read_write::csv_read_write()
11 {
12 mpLine = NULL;
13 mpBuffer = NULL;
14 }
15
16 ///////////////////////////////////////////////////////////////////////////////
ExportLanguage(studiox_project * project)17 BOOL csv_read_write::ExportLanguage(studiox_project *project)
18 {
19 int index;
20 int src_language = project->mHeader.string_export_src;
21 int target_language = project->mHeader.string_export_target;
22 CString tag_data;
23 CString src_data;
24 CString pathname = project->mHeader.string_export_path;
25 pathname += "\\";
26 pathname += project->mHeader.string_export_filename;
27
28 GotoProjectDirectory();
29 CStdioFile file;
30
31 if (!file.Open(pathname, CFile::modeCreate | CFile::modeWrite))
32 {
33 return FALSE;
34 }
35
36 int display = GetProjectView()->GetActiveDisplay();
37 string_table *table = project->mDisplays[display].stable;
38
39 tag_data.Format(_T("name,%s,%s\n"),
40 config_languages_dlg::GetLanguageId(src_language),
41 config_languages_dlg::GetLanguageId(target_language));
42
43 //write BOM mark
44 unsigned char BOM_mark[] = { 0xef, 0xbb, 0xbf };
45 file.Write(BOM_mark, 3);
46
47 //write header line
48 WriteString(&file, tag_data);
49
50 src_language = config_languages_dlg::GetStringTableIndexFromLanguageIndex(project, src_language);
51 target_language = config_languages_dlg::GetStringTableIndexFromLanguageIndex(project, target_language);
52
53 if (src_language == -1)
54 {
55 return FALSE;
56 }
57
58 CString csv_line;
59
60 for (index = 0; index < table->CountStrings(); index++)
61 {
62 src_data = table->GetString(index, src_language);
63 if (!src_data.IsEmpty())
64 {
65 //string id
66 csv_line = table->GetStringId(index);
67 csv_line.Append(_T(","));
68
69 //source language string
70 src_data = MakeCsvFormatValue(src_data);
71 csv_line.Append(src_data);
72
73 //target language string
74 if (target_language >= 0)
75 {
76 csv_line.Append(_T(","));
77 tag_data = table->GetString(index, target_language);
78 tag_data = MakeCsvFormatValue(tag_data);
79 csv_line.Append(tag_data);
80 }
81 csv_line.Append(_T("\n"));
82
83 WriteString(&file, csv_line);
84 }
85 }
86
87 return TRUE;
88 }
89
90 ///////////////////////////////////////////////////////////////////////////////
ImportCsvFile(studiox_project * project,CString & pathname)91 BOOL csv_read_write::ImportCsvFile(studiox_project *project, CString &pathname)
92 {
93 CString src_language;
94 CString target_language;
95 CString string_id;
96 CString src_string;
97 CString target_string;
98 CString notes("");
99 BOOL status = TRUE;
100
101 int language_index;
102 int target_table_column;
103 int src_table_column;
104
105 int display = GetProjectView()->GetActiveDisplay();
106 string_table *table = project->mDisplays[display].stable;
107
108 ReadFile(pathname);
109
110 CString line;
111 CStringArray header_array;
112 GotoProjectDirectory();
113
114 ReadLine(line);
115 SplitString(line, ',', &header_array);
116
117 // Get the version information
118
119 if (header_array.GetCount() >= 3)
120 {
121 //there should be at lease 3 columns
122 int col, index;
123 CStringArray string_array;
124
125 src_language = header_array.GetAt(1);
126 language_index = config_languages_dlg::GetLanguageIdIndex(src_language);
127 src_table_column = config_languages_dlg::GetStringTableIndexFromLanguageIndex(project, language_index);
128
129 if (src_table_column == -1)
130 {
131 delete[]mpBuffer;
132 mpBuffer = NULL;
133 mpLine = NULL;
134 return FALSE;
135 }
136
137 while (ReadLine(line))
138 {
139 index = 0;
140 string_array.RemoveAll();
141 SplitCsvLine(line, string_array);
142
143 if (string_array.GetCount() < 2)
144 {
145 //string id and source language should be valid
146 status = FALSE;
147 break;
148 }
149
150 string_id = string_array.GetAt(0);
151 src_string = string_array.GetAt(1);
152
153 for (col = 2; col < header_array.GetCount(); col++)
154 {
155 target_language = header_array.GetAt(col);
156 language_index = config_languages_dlg::GetLanguageIdIndex(target_language);
157 target_table_column = config_languages_dlg::GetStringTableIndexFromLanguageIndex(project, language_index);
158
159 if (target_table_column == -1)
160 {
161 // the translation language doesn't exist in our project, so add it
162 //target_table_column = AddNewLanguage(language_index);
163 target_table_column = project->AddLanguage(language_index);
164 }
165
166 if (col < string_array.GetCount())
167 {
168 target_string = string_array.GetAt(col);
169 }
170 else
171 {
172 target_string = _T("");
173 }
174 table->ImportString(string_id, src_string, target_string, notes, src_table_column, target_table_column);
175 }
176 }
177 }
178 else
179 {
180 status = FALSE;
181 }
182
183 delete[]mpBuffer;
184 mpBuffer = NULL;
185 mpLine = NULL;
186
187 table->Sort();
188 table->UpdateGuixLanguageTable();
189 return status;
190 }
191
192 ///////////////////////////////////////////////////////////////////////////////
MakeCsvFormatValue(CString string)193 CString csv_read_write::MakeCsvFormatValue(CString string)
194 {
195 int index;
196 CString format_string;
197 BOOL embedded_special_character = FALSE;
198
199 for (index = 0; index < string.GetLength(); index++)
200 {
201 switch (string.GetAt(index))
202 {
203 case '\"':
204 case '\r':
205 case '\n':
206 case ',':
207 embedded_special_character = TRUE;
208 break;
209 }
210 }
211
212 //replace single double quotation with a pair of consecutive double quotes
213 string.Replace(_T("\""), _T("\"\""));
214
215 if (embedded_special_character)
216 {
217 //put double quotation around string
218 string.Insert(0, '\"');
219 string.Append(_T("\""));
220 }
221
222 return string;
223 }
224
225 ///////////////////////////////////////////////////////////////////////////////
WriteString(CStdioFile * file,CString string)226 void csv_read_write::WriteString(CStdioFile *file, CString string)
227 {
228 // The maximun UTF8 character is 6 bytes, calculate the maximun utf8 buffer size needed for the string.
229 int char_count = _tcslen(string) * 6 + 1;
230 char *utf8buf = new char[char_count];
231 strcpy_s(utf8buf, char_count, CT2A(string, CP_UTF8));
232 file->Write(utf8buf, strlen(utf8buf));
233
234 delete utf8buf;
235 }
236
237 ///////////////////////////////////////////////////////////////////////////////
FindDelimiterIndex(CString line,int start_index)238 int csv_read_write::FindDelimiterIndex(CString line, int start_index)
239 {
240 int quatation_mark_count = 0;
241
242 while (start_index < line.GetLength())
243 {
244 switch (line.GetAt(start_index))
245 {
246 case '\"':
247 quatation_mark_count++;
248 break;
249
250 case ',':
251 if (!(quatation_mark_count & 0x1))
252 {
253 //quotation mark should be paired
254 return start_index;
255 }
256 break;
257 }
258
259 start_index++;
260 }
261
262 if (!(quatation_mark_count & 0x1))
263 {
264 //quotation mark should be paired
265 return start_index;
266 }
267
268 return -1;
269 }
270
271 ///////////////////////////////////////////////////////////////////////////////
SplitCsvLine(CString & line,CStringArray & line_array)272 void csv_read_write::SplitCsvLine(CString &line, CStringArray &line_array)
273 {
274 int index = 0;
275 int length = line.GetLength();
276 int start, end;
277 CString string;
278
279 while (index < length)
280 {
281 start = index;
282 end = FindDelimiterIndex(line, start) - 1;
283
284 if (end < 0)
285 {
286 //should not happen
287 return;
288 }
289
290 index = end + 2;
291
292 if (line.GetAt(start) == '\"')
293 {
294 //remove double quotation mark around the string
295 start += 1;
296 end -= 1;
297 }
298
299 string = line.Mid(start, end - start + 1);
300
301 //replace 2 double colon to 1 double colon
302 string.Replace(_T("\"\""), _T("\""));
303
304 line_array.Add(string);
305 }
306 }
307
308 ///////////////////////////////////////////////////////////////////////////////
ReadLine(CString & line)309 BOOL csv_read_write::ReadLine(CString &line)
310 {
311 int double_quotation_count = 0;
312
313 if (!mpLine)
314 {
315 return FALSE;
316 }
317
318 while (mpLine[0] && ((mpLine[0] == '\r') || (mpLine[0] == '\n')))
319 {
320 mpLine++;
321 }
322
323 int line_end = 0;
324
325 while (mpLine[line_end])
326 {
327 if ((mpLine[line_end] == '\r') || (mpLine[line_end] == '\n'))
328 {
329 if (!(double_quotation_count & 0x01))
330 {
331 //double quotation mark should be paired
332 break;
333 }
334 }
335 else if (mpLine[line_end] == '\"')
336 {
337 double_quotation_count++;
338 }
339
340 line_end++;
341 }
342
343 if (line_end)
344 {
345 char *buf = new char[line_end + 1];
346 strncpy(buf, mpLine, line_end);
347 buf[line_end] = '\0';
348
349 line = CA2T(buf, CP_UTF8);
350 mpLine += line_end + 1;
351
352 delete[] buf;
353 return TRUE;
354 }
355
356 return FALSE;
357 }
358
359 ///////////////////////////////////////////////////////////////////////////////
ReadFile(CString pathname)360 void csv_read_write::ReadFile(CString pathname)
361 {
362 CStdioFile file(pathname, CStdioFile::modeRead | CFile::shareExclusive);
363 ULONG size = (ULONG)file.GetLength();
364 mpBuffer = new char[size + 1];
365 memset(mpBuffer, 0, size + 1);
366 file.Read(mpBuffer, size);
367
368 mpLine = mpBuffer;
369
370 if (size >= 3)
371 {
372 if ((unsigned char)mpLine[0] == 0xef &&
373 (unsigned char)mpLine[1] == 0xbb &&
374 (unsigned char)mpLine[2] == 0xbf)
375 {
376 //skip BOM mark
377 mpLine += 3;
378 }
379 }
380 }